diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2015-06-24 04:23:46 +0200 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2015-06-24 10:03:18 +0200 |
commit | e5067d7cd967cb17067de24a162306b79f432b20 (patch) | |
tree | 541f101762df32a5742bec354009986a96d8e564 /net/netrom | |
parent | 86a981e836404006efc35881ebf3d5ae36925e82 (diff) |
Import newax25-2.4.3.patch.1.bz2HEADnewax25-2.4.3-1
And cleanup the *.orig and *.rej files and whitespace errors that are part
of the original patch.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'net/netrom')
-rw-r--r-- | net/netrom/af_netrom.c | 130 | ||||
-rw-r--r-- | net/netrom/nr_loopback.c | 6 | ||||
-rw-r--r-- | net/netrom/nr_route.c | 98 |
3 files changed, 124 insertions, 110 deletions
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index a4b89d294..3ba0b8c81 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -47,6 +47,7 @@ #include <linux/net.h> #include <linux/stat.h> #include <net/ax25.h> +#include <net/ax25_uid.h> #include <linux/inet.h> #include <linux/netdevice.h> #include <linux/if_arp.h> @@ -347,6 +348,8 @@ static int nr_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) { struct sock *sk = sock->sk; + char devname[IFNAMSIZ]; + struct net_device *dev; int opt; if (level != SOL_NETROM) @@ -389,6 +392,21 @@ static int nr_setsockopt(struct socket *sock, int level, int optname, sk->protinfo.nr->idle = opt * 60 * HZ; return 0; + case SO_BINDTODEVICE: + if (optlen > IFNAMSIZ) optlen = IFNAMSIZ; + if (copy_from_user(devname, optval, optlen)) + return -EFAULT; + + dev = dev_get_by_name(devname); + if (dev == NULL) return -ENODEV; + + if (sk->type == SOCK_SEQPACKET && + (sock->state != SS_UNCONNECTED || sk->state == TCP_LISTEN)) + return -EADDRNOTAVAIL; + + sk->protinfo.nr->device=dev; + return 0; + default: return -ENOPROTOOPT; } @@ -398,15 +416,24 @@ static int nr_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) { struct sock *sk = sock->sk; + struct net_device *dev; + char devname[IFNAMSIZ]; + void *valptr; int val = 0; - int len; + int maxlen, length; if (level != SOL_NETROM) return -ENOPROTOOPT; - if (get_user(len, optlen)) + if (get_user(maxlen, optlen)) return -EFAULT; + if (maxlen < 1) + return -EFAULT; + + valptr = (void *) &val; + length = min(maxlen, sizeof(int)); + switch (optname) { case NETROM_T1: val = sk->protinfo.nr->t1 / HZ; @@ -428,16 +455,33 @@ static int nr_getsockopt(struct socket *sock, int level, int optname, val = sk->protinfo.nr->idle / (60 * HZ); break; + case SO_BINDTODEVICE: + dev = sk->protinfo.nr->device; + + if (dev != NULL) { + strncpy(devname, dev->name, IFNAMSIZ); + length = min(strlen(dev->name)+1, maxlen); + devname[length-1] = '\0'; + } else { + *devname = '\0'; + length = 1; + } + + valptr = (void *) devname; + break; + + default: return -ENOPROTOOPT; } - len = min(len, sizeof(int)); + if (put_user(length, optlen)) + return -EFAULT; - if (put_user(len, optlen)) + if (copy_to_user(optval, valptr, length)) return -EFAULT; - return copy_to_user(optval, &val, len) ? -EFAULT : 0; + return 0; } static int nr_listen(struct socket *sock, int backlog) @@ -589,13 +633,12 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct sock *sk = sock->sk; struct full_sockaddr_ax25 *addr = (struct full_sockaddr_ax25 *)uaddr; struct net_device *dev; - ax25_address *user, *source; + ax25_address *user = NULL, *source = NULL; if (sk->zapped == 0) return -EINVAL; - if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(struct -full_sockaddr_ax25)) + if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(struct full_sockaddr_ax25)) return -EINVAL; if (addr_len < (addr->fsa_ax25.sax25_ndigis * sizeof(ax25_address) + sizeof(struct sockaddr_ax25))) @@ -604,32 +647,42 @@ full_sockaddr_ax25)) if (addr->fsa_ax25.sax25_family != AF_NETROM) return -EINVAL; - if ((dev = nr_dev_get(&addr->fsa_ax25.sax25_call)) == NULL) { - SOCK_DEBUG(sk, "NET/ROM: bind failed: invalid node callsign\n"); - return -EADDRNOTAVAIL; - } - /* - * Only the super user can set an arbitrary user callsign. + * User did not set the interfave with SO_BINDTODEVICE, + * use compatibility code. */ - if (addr->fsa_ax25.sax25_ndigis == 1) { - if (!capable(CAP_NET_BIND_SERVICE)) - return -EACCES; - sk->protinfo.nr->user_addr = addr->fsa_digipeater[0]; - sk->protinfo.nr->source_addr = addr->fsa_ax25.sax25_call; - } else { - source = &addr->fsa_ax25.sax25_call; - if ((user = ax25_findbyuid(current->euid)) == NULL) { - if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) - return -EPERM; - user = source; + dev = sk->protinfo.nr->device; + if (dev == NULL) { + if (addr_len > sizeof(struct sockaddr_ax25) && addr->fsax25_ndigis == 1) { + /* device callsign provided */ + if(ax25cmp(&addr->fsa_digipeater[0], &null_ax25_address) && + (dev = nr_dev_get(&addr->fsa_digipeater[0])) == NULL) + return -EADDRNOTAVAIL; + source = &addr->fsa_digipeater[0]; + } else { + if ((dev = nr_dev_get(&addr->fsax25_call)) == NULL) + return -EADDRNOTAVAIL; + source = &addr->fsa_ax25.sax25_call; } - sk->protinfo.nr->user_addr = *user; - sk->protinfo.nr->source_addr = *source; + sk->protinfo.nr->device = dev; + } else { + source = (ax25_address *) dev->dev_addr; } + if (!capable(CAP_NET_BIND_SERVICE)) + { + /* FIXME: should not be coupled with AX.25 */ + user = ax25_find_match_for_uid(current->euid, &addr->fsax25_call, dev->name); + if (user == NULL && ax25_uid_policy) + return -EACCES; + } + + if (user == NULL) user = &addr->fsax25_call; + sk->protinfo.nr->user_addr = *user; + sk->protinfo.nr->source_addr = *source; + sk->protinfo.nr->device = dev; nr_insert_socket(sk); @@ -643,7 +696,6 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, { struct sock *sk = sock->sk; struct sockaddr_ax25 *addr = (struct sockaddr_ax25 *)uaddr; - ax25_address *user, *source = NULL; struct net_device *dev; if (sk->state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) { @@ -668,26 +720,8 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr, if (addr->sax25_family != AF_NETROM) return -EINVAL; - if (sk->zapped) { /* Must bind first - autobinding in this may or may not work */ - sk->zapped = 0; - - if ((dev = nr_dev_first()) == NULL) - return -ENETUNREACH; - - source = (ax25_address *)dev->dev_addr; - - if ((user = ax25_findbyuid(current->euid)) == NULL) { - if (ax25_uid_policy && !capable(CAP_NET_ADMIN)) - return -EPERM; - user = source; - } - - sk->protinfo.nr->user_addr = *user; - sk->protinfo.nr->source_addr = *source; - sk->protinfo.nr->device = dev; - - nr_insert_socket(sk); /* Finish the bind */ - } + if (sk->zapped) + return -EADDRNOTAVAIL; sk->protinfo.nr->dest_addr = addr->sax25_call; diff --git a/net/netrom/nr_loopback.c b/net/netrom/nr_loopback.c index 5290ae024..519ca55da 100644 --- a/net/netrom/nr_loopback.c +++ b/net/netrom/nr_loopback.c @@ -44,10 +44,10 @@ int nr_loopback_queue(struct sk_buff *skb) { struct sk_buff *skbn; - if ((skbn = alloc_skb(skb->len, GFP_ATOMIC)) != NULL) { - memcpy(skb_put(skbn, skb->len), skb->data, skb->len); - skbn->h.raw = skbn->data; + skbn = skb_clone(skb, GFP_ATOMIC); + kfree(skb); + if (skbn != NULL) { skb_queue_tail(&loopback_queue, skbn); if (!nr_loopback_running()) 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"); |