diff options
Diffstat (limited to 'net/ax25/ax25_route.c')
-rw-r--r-- | net/ax25/ax25_route.c | 282 |
1 files changed, 81 insertions, 201 deletions
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index b4606111e..04a7c8542 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -1,10 +1,10 @@ /* - * AX.25 release 033 + * AX.25 release 036 * * This is ALPHA test software. This code may break your machine, randomly fail to work with new * releases, misbehave and/or generally screw up. It might even work. * - * This code REQUIRES 1.2.1 or higher/ NET3.029 + * This code REQUIRES 2.1.15 or higher/ NET3.038 * * This module: * This module is free software; you can redistribute it and/or @@ -39,8 +39,10 @@ * on routes. * AX.25 033 Jonathan(G4KLX) Remove auto-router. * Joerg(DL1BKE) Moved BPQ Ethernet driver to seperate device. + * AX.25 035 Frederic(F1OAT) Support for pseudo-digipeating. + * Jonathan(G4KLX) Support for packet forwarding. */ - + #include <linux/config.h> #if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) #include <linux/errno.h> @@ -65,22 +67,9 @@ #include <linux/mm.h> #include <linux/interrupt.h> -static struct ax25_route { - struct ax25_route *next; - ax25_address callsign; - struct device *dev; - ax25_digi *digipeat; - char ip_mode; -} *ax25_route = NULL; - -struct ax25_dev ax25_device[AX25_MAX_DEVICES] = { - {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}, - {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}, - {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}, - {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL} -}; +static ax25_route *ax25_route_list = NULL; -static struct ax25_route *ax25_find_route(ax25_address *, struct device *); +static ax25_route *ax25_find_route(ax25_address *, struct device *); /* * small macro to drop non-digipeated digipeaters and reverse path @@ -100,28 +89,28 @@ static inline void ax25_route_invert(ax25_digi *in, ax25_digi *out) void ax25_rt_device_down(struct device *dev) { - struct ax25_route *s, *t, *ax25_rt = ax25_route; + ax25_route *s, *t, *ax25_rt = ax25_route_list; while (ax25_rt != NULL) { s = ax25_rt; ax25_rt = ax25_rt->next; if (s->dev == dev) { - if (ax25_route == s) { - ax25_route = s->next; + if (ax25_route_list == s) { + ax25_route_list = s->next; if (s->digipeat != NULL) - kfree_s((void *)s->digipeat, sizeof(ax25_digi)); - kfree_s((void *)s, (sizeof *s)); + kfree_s(s->digipeat, sizeof(ax25_digi)); + kfree_s(s, sizeof(ax25_route)); } else { - for (t = ax25_route; t != NULL; t = t->next) { + for (t = ax25_route_list; t != NULL; t = t->next) { if (t->next == s) { t->next = s->next; if (s->digipeat != NULL) - kfree_s((void *)s->digipeat, sizeof(ax25_digi)); - kfree_s((void *)s, sizeof(*s)); + kfree_s(s->digipeat, sizeof(ax25_digi)); + kfree_s(s, sizeof(ax25_route)); break; } - } + } } } } @@ -130,10 +119,10 @@ void ax25_rt_device_down(struct device *dev) int ax25_rt_ioctl(unsigned int cmd, void *arg) { unsigned long flags; - struct ax25_route *s, *t, *ax25_rt; + ax25_route *s, *t, *ax25_rt; struct ax25_routes_struct route; struct ax25_route_opt_struct rt_option; - struct device *dev; + ax25_dev *ax25_dev; int i, err; switch (cmd) { @@ -141,12 +130,12 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) if ((err = verify_area(VERIFY_READ, arg, sizeof(route))) != 0) return err; copy_from_user(&route, arg, sizeof(route)); - if ((dev = ax25rtr_get_dev(&route.port_addr)) == NULL) + if ((ax25_dev = ax25_addr_ax25dev(&route.port_addr)) == NULL) return -EINVAL; if (route.digi_count > AX25_MAX_DIGIS) return -EINVAL; - for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) { - if (ax25cmp(&ax25_rt->callsign, &route.dest_addr) == 0 && ax25_rt->dev == dev) { + for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) { + if (ax25cmp(&ax25_rt->callsign, &route.dest_addr) == 0 && ax25_rt->dev == ax25_dev->dev) { if (ax25_rt->digipeat != NULL) { kfree_s(ax25_rt->digipeat, sizeof(ax25_digi)); ax25_rt->digipeat = NULL; @@ -154,7 +143,7 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) if (route.digi_count != 0) { if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) return -ENOMEM; - ax25_rt->digipeat->lastrepeat = 0; + ax25_rt->digipeat->lastrepeat = -1; ax25_rt->digipeat->ndigi = route.digi_count; for (i = 0; i < route.digi_count; i++) { ax25_rt->digipeat->repeated[i] = 0; @@ -164,28 +153,27 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) return 0; } } - if ((ax25_rt = (struct ax25_route *)kmalloc(sizeof(struct ax25_route), GFP_ATOMIC)) == NULL) + if ((ax25_rt = kmalloc(sizeof(ax25_route), GFP_ATOMIC)) == NULL) return -ENOMEM; ax25_rt->callsign = route.dest_addr; - ax25_rt->dev = dev; + ax25_rt->dev = ax25_dev->dev; ax25_rt->digipeat = NULL; ax25_rt->ip_mode = ' '; if (route.digi_count != 0) { if ((ax25_rt->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) { - kfree_s(ax25_rt, sizeof(struct ax25_route)); + kfree_s(ax25_rt, sizeof(ax25_route)); return -ENOMEM; } - ax25_rt->digipeat->lastrepeat = 0; + ax25_rt->digipeat->lastrepeat = -1; ax25_rt->digipeat->ndigi = route.digi_count; for (i = 0; i < route.digi_count; i++) { ax25_rt->digipeat->repeated[i] = 0; ax25_rt->digipeat->calls[i] = route.digi_addr[i]; } } - save_flags(flags); - cli(); - ax25_rt->next = ax25_route; - ax25_route = ax25_rt; + save_flags(flags); cli(); + ax25_rt->next = ax25_route_list; + ax25_route_list = ax25_rt; restore_flags(flags); break; @@ -193,25 +181,25 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) if ((err = verify_area(VERIFY_READ, arg, sizeof(route))) != 0) return err; copy_from_user(&route, arg, sizeof(route)); - if ((dev = ax25rtr_get_dev(&route.port_addr)) == NULL) + if ((ax25_dev = ax25_addr_ax25dev(&route.port_addr)) == NULL) return -EINVAL; - ax25_rt = ax25_route; + ax25_rt = ax25_route_list; while (ax25_rt != NULL) { s = ax25_rt; ax25_rt = ax25_rt->next; - if (s->dev == dev && ax25cmp(&route.dest_addr, &s->callsign) == 0) { - if (ax25_route == s) { - ax25_route = s->next; + if (s->dev == ax25_dev->dev && ax25cmp(&route.dest_addr, &s->callsign) == 0) { + if (ax25_route_list == s) { + ax25_route_list = s->next; if (s->digipeat != NULL) - kfree_s((void *)s->digipeat, sizeof(ax25_digi)); - kfree_s((void *)s, (sizeof *s)); + kfree_s(s->digipeat, sizeof(ax25_digi)); + kfree_s(s, sizeof(ax25_route)); } else { - for (t = ax25_route; t != NULL; t = t->next) { + for (t = ax25_route_list; t != NULL; t = t->next) { if (t->next == s) { t->next = s->next; if (s->digipeat != NULL) - kfree_s((void *)s->digipeat, sizeof(ax25_digi)); - kfree_s((void *)s, sizeof(*s)); + kfree_s(s->digipeat, sizeof(ax25_digi)); + kfree_s(s, sizeof(ax25_route)); break; } } @@ -224,10 +212,10 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) if ((err = verify_area(VERIFY_READ, arg, sizeof(rt_option))) != 0) return err; copy_from_user(&rt_option, arg, sizeof(rt_option)); - if ((dev = ax25rtr_get_dev(&rt_option.port_addr)) == NULL) + if ((ax25_dev = ax25_addr_ax25dev(&rt_option.port_addr)) == NULL) return -EINVAL; - for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) { - if (ax25_rt->dev == dev && ax25cmp(&rt_option.dest_addr, &ax25_rt->callsign) == 0) { + for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) { + if (ax25_rt->dev == ax25_dev->dev && ax25cmp(&rt_option.dest_addr, &ax25_rt->callsign) == 0) { switch (rt_option.cmd) { case AX25_SET_RT_IPMODE: switch (rt_option.arg) { @@ -256,7 +244,7 @@ int ax25_rt_ioctl(unsigned int cmd, void *arg) int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int dummy) { - struct ax25_route *ax25_rt; + ax25_route *ax25_rt; int len = 0; off_t pos = 0; off_t begin = 0; @@ -267,7 +255,7 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int d len += sprintf(buffer, "callsign dev mode digipeaters\n"); - for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) { + for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) { if (ax25cmp(&ax25_rt->callsign, &null_ax25_address) == 0) callsign = "default"; else @@ -287,20 +275,20 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int d len += sprintf(buffer + len, " *"); break; } - + if (ax25_rt->digipeat != NULL) for (i = 0; i < ax25_rt->digipeat->ndigi; i++) len += sprintf(buffer + len, " %s", ax2asc(&ax25_rt->digipeat->calls[i])); - + len += sprintf(buffer + len, "\n"); - + pos = begin + len; if (pos < offset) { len = 0; begin = pos; } - + if (pos > offset + length) break; } @@ -315,55 +303,20 @@ int ax25_rt_get_info(char *buffer, char **start, off_t offset, int length, int d return len; } -int ax25_cs_get_info(char *buffer, char **start, off_t offset, int length, int dummy) -{ - ax25_uid_assoc *pt; - int len = 0; - off_t pos = 0; - off_t begin = 0; - - cli(); - - len += sprintf(buffer, "Policy: %d\n", ax25_uid_policy); - - for (pt = ax25_uid_list; pt != NULL; pt = pt->next) { - len += sprintf(buffer + len, "%6d %s\n", pt->uid, ax2asc(&pt->call)); - - pos = begin + len; - - if (pos < offset) { - len = 0; - begin = pos; - } - - if (pos > offset + length) - break; - } - - sti(); - - *start = buffer + (offset - begin); - len -= offset - begin; - - if (len > length) len = length; - - return len; -} - /* * Find AX.25 route */ -static struct ax25_route *ax25_find_route(ax25_address *addr, struct device *dev) +static ax25_route *ax25_find_route(ax25_address *addr, struct device *dev) { - struct ax25_route *ax25_spe_rt = NULL; - struct ax25_route *ax25_def_rt = NULL; - struct ax25_route *ax25_rt; - + ax25_route *ax25_spe_rt = NULL; + ax25_route *ax25_def_rt = NULL; + ax25_route *ax25_rt; + /* * Bind to the physical interface we heard them on, or the default * route if none is found; */ - for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) { + for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) { if (dev == NULL) { if (ax25cmp(&ax25_rt->callsign, addr) == 0 && ax25_rt->dev != NULL) ax25_spe_rt = ax25_rt; @@ -379,7 +332,7 @@ static struct ax25_route *ax25_find_route(ax25_address *addr, struct device *dev if (ax25_spe_rt != NULL) return ax25_spe_rt; - + return ax25_def_rt; } @@ -391,12 +344,12 @@ static struct ax25_route *ax25_find_route(ax25_address *addr, struct device *dev static inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat) { int k; - + for (k = 0; k < digipeat->ndigi; k++) { if (ax25cmp(addr, &digipeat->calls[k]) == 0) break; } - + digipeat->ndigi = k; } @@ -406,18 +359,19 @@ static inline void ax25_adjust_path(ax25_address *addr, ax25_digi *digipeat) */ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) { - struct ax25_route *ax25_rt; + ax25_route *ax25_rt; ax25_address *call; if ((ax25_rt = ax25_find_route(addr, NULL)) == NULL) return -EHOSTUNREACH; - - ax25->device = ax25_rt->dev; + + if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) + return -EHOSTUNREACH; if ((call = ax25_findbyuid(current->euid)) == NULL) { if (ax25_uid_policy && !suser()) return -EPERM; - call = (ax25_address *)ax25->device->dev_addr; + call = (ax25_address *)ax25->ax25_dev->dev->dev_addr; } ax25->source_addr = *call; @@ -441,25 +395,27 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr) */ void ax25_rt_build_path(ax25_cb *ax25, ax25_address *addr, struct device *dev) { - struct ax25_route *ax25_rt; - + ax25_route *ax25_rt; + if ((ax25_rt = ax25_find_route(addr, dev)) == NULL) return; - + if (ax25_rt->digipeat == NULL) return; if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) return; - ax25->device = ax25_rt->dev; + if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) + return; + *ax25->digipeat = *ax25_rt->digipeat; ax25_adjust_path(addr, ax25->digipeat); } void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device *dev) { - struct ax25_route *ax25_rt; + ax25_route *ax25_rt; ax25_digi digipeat; ax25_address src, dest; unsigned char *bp; @@ -472,24 +428,24 @@ void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device * if (ax25_rt->digipeat == NULL) return; - + digipeat = *ax25_rt->digipeat; - + ax25_adjust_path(addr, &digipeat); len = ax25_rt->digipeat->ndigi * AX25_ADDR_LEN; - + if (skb_headroom(skb) < len) { printk(KERN_CRIT "ax25_dg_build_path: not enough headroom for digis in skb\n"); return; } - - memcpy(&dest, skb->data , AX25_ADDR_LEN); + + memcpy(&dest, skb->data + 0, AX25_ADDR_LEN); memcpy(&src, skb->data + 7, AX25_ADDR_LEN); bp = skb_push(skb, len); - build_ax25_addr(bp, &src, &dest, ax25_rt->digipeat, C_COMMAND, MODULUS); + ax25_addr_build(bp, &src, &dest, ax25_rt->digipeat, AX25_COMMAND, AX25_MODULUS); } /* @@ -497,99 +453,24 @@ void ax25_dg_build_path(struct sk_buff *skb, ax25_address *addr, struct device * */ char ax25_ip_mode_get(ax25_address *callsign, struct device *dev) { - struct ax25_route *ax25_rt; + ax25_route *ax25_rt; - for (ax25_rt = ax25_route; ax25_rt != NULL; ax25_rt = ax25_rt->next) + for (ax25_rt = ax25_route_list; ax25_rt != NULL; ax25_rt = ax25_rt->next) if (ax25cmp(&ax25_rt->callsign, callsign) == 0 && ax25_rt->dev == dev) return ax25_rt->ip_mode; return ' '; } -/* - * Wow, a bit of data hiding. Is this C++ or what ? - */ -int ax25_dev_get_value(struct device *dev, int valueno) -{ - int i; - - for (i = 0; i < AX25_MAX_DEVICES; i++) - if (ax25_device[i].dev != NULL && ax25_device[i].dev == dev) - return ax25_device[i].values[valueno]; - - printk(KERN_WARNING "ax25_dev_get_value called with invalid device\n"); - - return 0; -} - -/* - * This is called when an interface is brought up. These are - * reasonable defaults. - */ -void ax25_dev_device_up(struct device *dev) -{ - struct ax25_dev *ax25_dev = NULL; - int i; - - for (i = 0; i < AX25_MAX_DEVICES; i++) { - if (ax25_device[i].dev == NULL) { - ax25_dev = ax25_device + i; - break; - } - } - - if (ax25_dev == NULL) { - printk(KERN_ERR "ax25_dev_device_up cannot find free AX.25 device\n"); - return; - } - - ax25_unregister_sysctl(); - - sprintf(ax25_dev->name, "%s.parms", dev->name); - - ax25_dev->dev = dev; - - ax25_dev->values[AX25_VALUES_IPDEFMODE] = AX25_DEF_IPDEFMODE; - ax25_dev->values[AX25_VALUES_AXDEFMODE] = AX25_DEF_AXDEFMODE; - ax25_dev->values[AX25_VALUES_TEXT] = AX25_DEF_TEXT; - ax25_dev->values[AX25_VALUES_BACKOFF] = AX25_DEF_BACKOFF; - ax25_dev->values[AX25_VALUES_CONMODE] = AX25_DEF_CONMODE; - ax25_dev->values[AX25_VALUES_WINDOW] = AX25_DEF_WINDOW; - ax25_dev->values[AX25_VALUES_EWINDOW] = AX25_DEF_EWINDOW; - ax25_dev->values[AX25_VALUES_T1] = AX25_DEF_T1; - ax25_dev->values[AX25_VALUES_T2] = AX25_DEF_T2; - ax25_dev->values[AX25_VALUES_T3] = AX25_DEF_T3; - ax25_dev->values[AX25_VALUES_IDLE] = AX25_DEF_IDLE; - ax25_dev->values[AX25_VALUES_N2] = AX25_DEF_N2; - ax25_dev->values[AX25_VALUES_DIGI] = AX25_DEF_DIGI; - ax25_dev->values[AX25_VALUES_PACLEN] = AX25_DEF_PACLEN; - ax25_dev->values[AX25_VALUES_MAXQUEUE] = AX25_DEF_MAXQUEUE; - - ax25_register_sysctl(); -} - -void ax25_dev_device_down(struct device *dev) -{ - int i; - - ax25_unregister_sysctl(); - - for (i = 0; i < AX25_MAX_DEVICES; i++) - if (ax25_device[i].dev != NULL && ax25_device[i].dev == dev) - ax25_device[i].dev = NULL; - - ax25_register_sysctl(); -} - #ifdef MODULE /* - * Free all memory associated with routing and device structures. + * Free all memory associated with routing structures. */ void ax25_rt_free(void) { - struct ax25_route *s, *ax25_rt = ax25_route; - + ax25_route *s, *ax25_rt = ax25_route_list; + while (ax25_rt != NULL) { s = ax25_rt; ax25_rt = ax25_rt->next; @@ -597,11 +478,10 @@ void ax25_rt_free(void) if (s->digipeat != NULL) kfree_s(s->digipeat, sizeof(ax25_digi)); - kfree_s(s, sizeof(struct ax25_route)); + kfree_s(s, sizeof(ax25_route)); } } #endif #endif - |