summaryrefslogtreecommitdiffstats
path: root/net/netrom/nr_route.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netrom/nr_route.c')
-rw-r--r--net/netrom/nr_route.c98
1 files changed, 39 insertions, 59 deletions
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index ec0578b51..e6793fb0b 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -60,8 +60,8 @@ static void nr_remove_neigh(struct nr_neigh *);
* Add a new route to a node, and in the process add the node and the
* neighbour if it is new.
*/
-static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax25,
- ax25_digi *ax25_digi, struct net_device *dev, int quality, int obs_count)
+static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_addr_t *ax25_addr,
+ struct net_device *dev, int quality, int obs_count)
{
struct nr_node *nr_node;
struct nr_neigh *nr_neigh;
@@ -77,7 +77,7 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
break;
for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next)
- if (ax25cmp(ax25, &nr_neigh->callsign) == 0 && nr_neigh->dev == dev)
+ if (ax25cmp(&ax25_addr->dest, &nr_neigh->addr.dest) == 0 && nr_neigh->dev == dev)
break;
/*
@@ -106,8 +106,8 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL)
return -ENOMEM;
- nr_neigh->callsign = *ax25;
- nr_neigh->digipeat = NULL;
+ nr_neigh->addr = *ax25_addr;
+ nr_neigh->addr.src = *((ax25_address *) dev->dev_addr);
nr_neigh->ax25 = NULL;
nr_neigh->dev = dev;
nr_neigh->quality = sysctl_netrom_default_path_quality;
@@ -116,13 +116,7 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
nr_neigh->number = nr_neigh_no++;
nr_neigh->failed = 0;
- if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
- if ((nr_neigh->digipeat = kmalloc(sizeof(*ax25_digi), GFP_KERNEL)) == NULL) {
- kfree(nr_neigh);
- return -ENOMEM;
- }
- memcpy(nr_neigh->digipeat, ax25_digi, sizeof(ax25_digi));
- }
+ /* FIXME: not SMP safe! */
save_flags(flags);
cli();
@@ -133,7 +127,7 @@ static int nr_add_node(ax25_address *nr, const char *mnemonic, ax25_address *ax2
restore_flags(flags);
}
- if (quality != 0 && ax25cmp(nr, ax25) == 0 && !nr_neigh->locked)
+ if (quality != 0 && ax25cmp(nr, &ax25_addr->dest) == 0 && !nr_neigh->locked)
nr_neigh->quality = quality;
if (nr_node == NULL) {
@@ -294,8 +288,6 @@ static void nr_remove_neigh(struct nr_neigh *nr_neigh)
if ((s = nr_neigh_list) == nr_neigh) {
nr_neigh_list = nr_neigh->next;
restore_flags(flags);
- if (nr_neigh->digipeat != NULL)
- kfree(nr_neigh->digipeat);
kfree(nr_neigh);
return;
}
@@ -304,8 +296,6 @@ static void nr_remove_neigh(struct nr_neigh *nr_neigh)
if (s->next == nr_neigh) {
s->next = nr_neigh->next;
restore_flags(flags);
- if (nr_neigh->digipeat != NULL)
- kfree(nr_neigh->digipeat);
kfree(nr_neigh);
return;
}
@@ -333,7 +323,7 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n
if (nr_node == NULL) return -EINVAL;
for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next)
- if (ax25cmp(neighbour, &nr_neigh->callsign) == 0 && nr_neigh->dev == dev)
+ if (ax25cmp(neighbour, &nr_neigh->addr.dest) == 0 && nr_neigh->dev == dev)
break;
if (nr_neigh == NULL) return -EINVAL;
@@ -370,13 +360,13 @@ static int nr_del_node(ax25_address *callsign, ax25_address *neighbour, struct n
/*
* Lock a neighbour with a quality.
*/
-static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct net_device *dev, unsigned int quality)
+static int nr_add_neigh(ax25_addr_t *ax25_addr, struct net_device *dev, unsigned int quality)
{
struct nr_neigh *nr_neigh;
unsigned long flags;
for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next) {
- if (ax25cmp(callsign, &nr_neigh->callsign) == 0 && nr_neigh->dev == dev) {
+ if (ax25cmp(&ax25_addr->dest, &nr_neigh->addr.dest) == 0 && nr_neigh->dev == dev) {
nr_neigh->quality = quality;
nr_neigh->locked = 1;
return 0;
@@ -386,8 +376,8 @@ static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct net
if ((nr_neigh = kmalloc(sizeof(*nr_neigh), GFP_ATOMIC)) == NULL)
return -ENOMEM;
- nr_neigh->callsign = *callsign;
- nr_neigh->digipeat = NULL;
+ nr_neigh->addr = *ax25_addr;
+ nr_neigh->addr.src = *((ax25_address *) dev->dev_addr);
nr_neigh->ax25 = NULL;
nr_neigh->dev = dev;
nr_neigh->quality = quality;
@@ -396,14 +386,6 @@ static int nr_add_neigh(ax25_address *callsign, ax25_digi *ax25_digi, struct net
nr_neigh->number = nr_neigh_no++;
nr_neigh->failed = 0;
- if (ax25_digi != NULL && ax25_digi->ndigi > 0) {
- if ((nr_neigh->digipeat = kmalloc(sizeof(*ax25_digi), GFP_KERNEL)) == NULL) {
- kfree(nr_neigh);
- return -ENOMEM;
- }
- memcpy(nr_neigh->digipeat, ax25_digi, sizeof(ax25_digi));
- }
-
save_flags(flags);
cli();
@@ -424,7 +406,7 @@ static int nr_del_neigh(ax25_address *callsign, struct net_device *dev, unsigned
struct nr_neigh *nr_neigh;
for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next)
- if (ax25cmp(callsign, &nr_neigh->callsign) == 0 && nr_neigh->dev == dev)
+ if (ax25cmp(callsign, &nr_neigh->addr.dest) == 0 && nr_neigh->dev == dev)
break;
if (nr_neigh == NULL) return -EINVAL;
@@ -586,31 +568,26 @@ struct net_device *nr_dev_get(ax25_address *addr)
for (dev = dev_base; dev != NULL; dev = dev->next) {
if ((dev->flags & IFF_UP) && dev->type == ARPHRD_NETROM && ax25cmp(addr, (ax25_address *)dev->dev_addr) == 0) {
dev_hold(dev);
- goto out;
+ break;
}
}
-out:
+
read_unlock(&dev_base_lock);
return dev;
}
-static ax25_digi *nr_call_to_digi(int ndigis, ax25_address *digipeaters)
+static ax25_addr_t *nr_neigh_to_addr(ax25_address *callsign, int ndigis, ax25_address *digipeater)
{
- static ax25_digi ax25_digi;
+ static ax25_addr_t ax25_addr;
int i;
- if (ndigis == 0)
- return NULL;
+ ax25_addr.dest = *callsign;
+ ax25_addr.dcount = ndigis;
- for (i = 0; i < ndigis; i++) {
- ax25_digi.calls[i] = digipeaters[i];
- ax25_digi.repeated[i] = 0;
- }
+ for (i = 0; i < ndigis; i++)
+ ax25_addr.digipeater[i] = digipeater[i];
- ax25_digi.ndigi = ndigis;
- ax25_digi.lastrepeat = -1;
-
- return &ax25_digi;
+ return &ax25_addr;
}
/*
@@ -632,16 +609,13 @@ int nr_rt_ioctl(unsigned int cmd, void *arg)
return -EINVAL;
switch (nr_route.type) {
case NETROM_NODE:
- return nr_add_node(&nr_route.callsign,
- nr_route.mnemonic,
- &nr_route.neighbour,
- nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters),
+ return nr_add_node(&nr_route.callsign, nr_route.mnemonic,
+ nr_neigh_to_addr(&nr_route.neighbour, nr_route.ndigis, nr_route.digipeaters),
dev, nr_route.quality,
nr_route.obs_count);
case NETROM_NEIGH:
- return nr_add_neigh(&nr_route.callsign,
- nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters),
- dev, nr_route.quality);
+ return nr_add_neigh(nr_neigh_to_addr(&nr_route.callsign, nr_route.ndigis, nr_route.digipeaters),
+ dev, nr_route.quality);
default:
return -EINVAL;
}
@@ -713,8 +687,8 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
nr_dest = (ax25_address *)(skb->data + 7);
if (ax25 != NULL)
- nr_add_node(nr_src, "", &ax25->dest_addr, ax25->digipeat,
- ax25->ax25_dev->dev, 0, sysctl_netrom_obsolescence_count_initialiser);
+ nr_add_node(nr_src, "", &ax25->addr, ax25->device, 0,
+ sysctl_netrom_obsolescence_count_initialiser);
if ((dev = nr_dev_get(nr_dest)) != NULL) { /* Its for me */
if (ax25 == NULL) /* Its from me */
@@ -745,7 +719,13 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
dptr = skb_push(skb, 1);
*dptr = AX25_P_NETROM;
- nr_neigh->ax25 = ax25_send_frame(skb, 256, (ax25_address *)dev->dev_addr, &nr_neigh->callsign, nr_neigh->digipeat, nr_neigh->dev);
+ /* The next line is dirty hotfix. There is a bug in nr_add_neigh() -
+ * src callsign is taken from dev->dev_addr of device on which the
+ * broadcast was received. But this is AX25 device (and callsign),
+ * not the netrom device, so the callsign is bad.
+ */
+ nr_neigh->addr.src = *((ax25_address*)dev->dev_addr);
+ nr_neigh->ax25 = ax25_send_frame(skb, 256, &nr_neigh->addr, nr_neigh->dev);
return (nr_neigh->ax25 != NULL);
}
@@ -814,16 +794,16 @@ int nr_neigh_get_info(char *buffer, char **start, off_t offset, int length)
for (nr_neigh = nr_neigh_list; nr_neigh != NULL; nr_neigh = nr_neigh->next) {
len += sprintf(buffer + len, "%05d %-9s %-4s %3d %d %3d %3d",
nr_neigh->number,
- ax2asc(&nr_neigh->callsign),
+ ax2asc(&nr_neigh->addr.dest),
nr_neigh->dev ? nr_neigh->dev->name : "???",
nr_neigh->quality,
nr_neigh->locked,
nr_neigh->count,
nr_neigh->failed);
- if (nr_neigh->digipeat != NULL) {
- for (i = 0; i < nr_neigh->digipeat->ndigi; i++)
- len += sprintf(buffer + len, " %s", ax2asc(&nr_neigh->digipeat->calls[i]));
+ if (nr_neigh->addr.dcount) {
+ for (i = 0; i < nr_neigh->addr.dcount; i++)
+ len += sprintf(buffer + len, " %s", ax2asc(&nr_neigh->addr.digipeater[i]));
}
len += sprintf(buffer + len, "\n");