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/rose | |
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/rose')
-rw-r--r-- | net/rose/af_rose.c | 107 | ||||
-rw-r--r-- | net/rose/rose_link.c | 16 | ||||
-rw-r--r-- | net/rose/rose_route.c | 75 | ||||
-rw-r--r-- | net/rose/rose_subr.c | 7 |
4 files changed, 119 insertions, 86 deletions
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index a92bf86f5..07acd3946 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -39,6 +39,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> @@ -404,6 +405,8 @@ static int rose_setsockopt(struct socket *sock, int level, int optname, char *optval, int optlen) { struct sock *sk = sock->sk; + struct net_device *dev; + char devname[IFNAMSIZ]; int opt; if (level != SOL_ROSE) @@ -454,6 +457,22 @@ static int rose_setsockopt(struct socket *sock, int level, int optname, sk->protinfo.rose->qbitincl = opt ? 1 : 0; 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.rose->device = dev; + return 0; + default: return -ENOPROTOOPT; } @@ -463,14 +482,23 @@ static int rose_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_ROSE) 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 ROSE_DEFER: @@ -501,16 +529,32 @@ static int rose_getsockopt(struct socket *sock, int level, int optname, val = sk->protinfo.rose->qbitincl; break; + case SO_BINDTODEVICE: + dev = sk->protinfo.rose->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 rose_listen(struct socket *sock, int backlog) @@ -666,7 +710,8 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct sock *sk = sock->sk; struct sockaddr_rose *addr = (struct sockaddr_rose *)uaddr; struct net_device *dev; - ax25_address *user, *source; + ax25_address *user = NULL; + rose_address *source = NULL; int n; if (sk->zapped == 0) @@ -683,21 +728,36 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (addr->srose_ndigis > ROSE_MAX_DIGIS) return -EINVAL; + /* + * User did not set interface with SO_BINDTODEVICE + * thus we'll use the compatibility code + */ + + dev = sk->protinfo.rose->device; + if (dev == NULL) { + if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) { + SOCK_DEBUG(sk, "ROSE: bind failed: invalid address\n"); + return -EADDRNOTAVAIL; + } - if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) { - SOCK_DEBUG(sk, "ROSE: bind failed: invalid address\n"); - return -EADDRNOTAVAIL; + source = &addr->srose_addr; + sk->protinfo.rose->device = dev; + } else { + source = (rose_address *) dev->dev_addr; } - source = &addr->srose_call; - - if ((user = ax25_findbyuid(current->euid)) == NULL) { - if (ax25_uid_policy && !capable(CAP_NET_BIND_SERVICE)) + /* root can do whatever (s)he likes, but anyone else... */ + if (!capable(CAP_NET_BIND_SERVICE)) + { + /* FIXME: strictly speaking this has nothing to do with AX.25 */ + user = ax25_find_match_for_uid(current->euid, &addr->srose_call, dev->name); + if (user == NULL && ax25_uid_policy) return -EACCES; - user = source; } - sk->protinfo.rose->source_addr = addr->srose_addr; + if (user == NULL) user = &addr->srose_call; + + sk->protinfo.rose->source_addr = *source; sk->protinfo.rose->source_call = *user; sk->protinfo.rose->device = dev; sk->protinfo.rose->source_ndigis = addr->srose_ndigis; @@ -766,21 +826,8 @@ static int rose_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le if ((sk->protinfo.rose->lci = rose_new_lci(sk->protinfo.rose->neighbour)) == 0) return -ENETUNREACH; - if (sk->zapped) { /* Must bind first - autobinding in this may or may not work */ - sk->zapped = 0; - - if ((dev = rose_dev_first()) == NULL) - return -ENETUNREACH; - - if ((user = ax25_findbyuid(current->euid)) == NULL) - return -EINVAL; - - memcpy(&sk->protinfo.rose->source_addr, dev->dev_addr, ROSE_ADDR_LEN); - sk->protinfo.rose->source_call = *user; - sk->protinfo.rose->device = dev; - - rose_insert_socket(sk); /* Finish the bind */ - } + if (sk->zapped) + return -EINVAL; sk->protinfo.rose->dest_addr = addr->srose_addr; sk->protinfo.rose->dest_call = addr->srose_call; diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index 2c793e4e6..a4e5f71bd 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c @@ -104,14 +104,12 @@ static void rose_t0timer_expiry(unsigned long param) */ static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh) { - ax25_address *rose_call; - if (ax25cmp(&rose_callsign, &null_ax25_address) == 0) - rose_call = (ax25_address *)neigh->dev->dev_addr; + neigh->addr.src = *((ax25_address *) neigh->dev->dev_addr); else - rose_call = &rose_callsign; + neigh->addr.src = rose_callsign; - neigh->ax25 = ax25_send_frame(skb, 260, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev); + neigh->ax25 = ax25_send_frame(skb, 260, &neigh->addr, neigh->dev); return (neigh->ax25 != NULL); } @@ -123,14 +121,12 @@ static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh) */ static int rose_link_up(struct rose_neigh *neigh) { - ax25_address *rose_call; - if (ax25cmp(&rose_callsign, &null_ax25_address) == 0) - rose_call = (ax25_address *)neigh->dev->dev_addr; + neigh->addr.src = *((ax25_address *) neigh->dev->dev_addr); else - rose_call = &rose_callsign; + neigh->addr.src = rose_callsign; - neigh->ax25 = ax25_find_cb(rose_call, &neigh->callsign, neigh->digipeat, neigh->dev); + neigh->ax25 = ax25_find_cb(&neigh->addr, neigh->dev); return (neigh->ax25 != NULL); } diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 1bedfdf0d..4de549586 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -77,23 +77,23 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct net_device return -EINVAL; for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) - if (ax25cmp(&rose_route->neighbour, &rose_neigh->callsign) == 0 && rose_neigh->dev == dev) + if (ax25cmp(&rose_route->neighbour, &rose_neigh->addr.dest) == 0 && rose_neigh->dev == dev) break; if (rose_neigh == NULL) { if ((rose_neigh = kmalloc(sizeof(*rose_neigh), GFP_ATOMIC)) == NULL) return -ENOMEM; - rose_neigh->callsign = rose_route->neighbour; - rose_neigh->digipeat = NULL; - rose_neigh->ax25 = NULL; - rose_neigh->dev = dev; - rose_neigh->count = 0; - rose_neigh->use = 0; - rose_neigh->dce_mode = 0; - rose_neigh->loopback = 0; - rose_neigh->number = rose_neigh_no++; - rose_neigh->restarted = 0; + rose_neigh->addr.dest = rose_route->neighbour; + rose_neigh->addr.dcount = 0; + rose_neigh->ax25 = NULL; + rose_neigh->dev = dev; + rose_neigh->count = 0; + rose_neigh->use = 0; + rose_neigh->dce_mode = 0; + rose_neigh->loopback = 0; + rose_neigh->number = rose_neigh_no++; + rose_neigh->restarted = 0; skb_queue_head_init(&rose_neigh->queue); @@ -101,18 +101,11 @@ static int rose_add_node(struct rose_route_struct *rose_route, struct net_device init_timer(&rose_neigh->t0timer); if (rose_route->ndigis != 0) { - if ((rose_neigh->digipeat = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL) { - kfree(rose_neigh); - return -ENOMEM; - } - - rose_neigh->digipeat->ndigi = rose_route->ndigis; - rose_neigh->digipeat->lastrepeat = -1; + rose_neigh->addr.dcount = rose_route->ndigis; + rose_neigh->addr.lastrepeat = -1; - for (i = 0; i < rose_route->ndigis; i++) { - rose_neigh->digipeat->calls[i] = rose_route->digipeaters[i]; - rose_neigh->digipeat->repeated[i] = 0; - } + for (i = 0; i < rose_route->ndigis; i++) + rose_neigh->addr.digipeater[i] = rose_route->digipeaters[i]; } save_flags(flags); cli(); @@ -234,8 +227,6 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) if ((s = rose_neigh_list) == rose_neigh) { rose_neigh_list = rose_neigh->next; restore_flags(flags); - if (rose_neigh->digipeat != NULL) - kfree(rose_neigh->digipeat); kfree(rose_neigh); return; } @@ -244,8 +235,6 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) if (s->next == rose_neigh) { s->next = rose_neigh->next; restore_flags(flags); - if (rose_neigh->digipeat != NULL) - kfree(rose_neigh->digipeat); kfree(rose_neigh); return; } @@ -309,7 +298,7 @@ static int rose_del_node(struct rose_route_struct *rose_route, struct net_device if (rose_node->loopback) return -EINVAL; for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) - if (ax25cmp(&rose_route->neighbour, &rose_neigh->callsign) == 0 && rose_neigh->dev == dev) + if (ax25cmp(&rose_route->neighbour, &rose_neigh->addr.dest) == 0 && rose_neigh->dev == dev) break; if (rose_neigh == NULL) return -EINVAL; @@ -353,16 +342,16 @@ int rose_add_loopback_neigh(void) if ((rose_loopback_neigh = kmalloc(sizeof(struct rose_neigh), GFP_ATOMIC)) == NULL) return -ENOMEM; - rose_loopback_neigh->callsign = null_ax25_address; - rose_loopback_neigh->digipeat = NULL; - rose_loopback_neigh->ax25 = NULL; - rose_loopback_neigh->dev = NULL; - rose_loopback_neigh->count = 0; - rose_loopback_neigh->use = 0; - rose_loopback_neigh->dce_mode = 1; - rose_loopback_neigh->loopback = 1; - rose_loopback_neigh->number = rose_neigh_no++; - rose_loopback_neigh->restarted = 1; + rose_loopback_neigh->addr.dest = null_ax25_address; + rose_loopback_neigh->addr.dcount = 0; + rose_loopback_neigh->ax25 = NULL; + rose_loopback_neigh->dev = NULL; + rose_loopback_neigh->count = 0; + rose_loopback_neigh->use = 0; + rose_loopback_neigh->dce_mode = 1; + rose_loopback_neigh->loopback = 1; + rose_loopback_neigh->number = rose_neigh_no++; + rose_loopback_neigh->restarted = 1; skb_queue_head_init(&rose_loopback_neigh->queue); @@ -787,11 +776,11 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25) dest_addr = (rose_address *)(skb->data + 4); for (rose_neigh = rose_neigh_list; rose_neigh != NULL; rose_neigh = rose_neigh->next) - if (ax25cmp(&ax25->dest_addr, &rose_neigh->callsign) == 0 && ax25->ax25_dev->dev == rose_neigh->dev) + if (ax25cmp(&ax25->addr.dest, &rose_neigh->addr.dest) == 0 && ax25->device == rose_neigh->dev) break; if (rose_neigh == NULL) { - printk("rose_route : unknown neighbour or device %s\n", ax2asc(&ax25->dest_addr)); + printk("rose_route : unknown neighbour or device %s\n", ax2asc(&ax25->addr.dest)); return 0; } @@ -1034,7 +1023,7 @@ int rose_neigh_get_info(char *buffer, char **start, off_t offset, int length) /* if (!rose_neigh->loopback) { */ len += sprintf(buffer + len, "%05d %-9s %-4s %3d %3d %3s %3s %3lu %3lu", rose_neigh->number, - (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(&rose_neigh->callsign), + (rose_neigh->loopback) ? "RSLOOP-0" : ax2asc(&rose_neigh->addr.dest), rose_neigh->dev ? rose_neigh->dev->name : "???", rose_neigh->count, rose_neigh->use, @@ -1043,9 +1032,9 @@ int rose_neigh_get_info(char *buffer, char **start, off_t offset, int length) ax25_display_timer(&rose_neigh->t0timer) / HZ, ax25_display_timer(&rose_neigh->ftimer) / HZ); - if (rose_neigh->digipeat != NULL) { - for (i = 0; i < rose_neigh->digipeat->ndigi; i++) - len += sprintf(buffer + len, " %s", ax2asc(&rose_neigh->digipeat->calls[i])); + if (rose_neigh->addr.dcount != 0) { + for (i = 0; i < rose_neigh->addr.dcount; i++) + len += sprintf(buffer + len, " %s", ax2asc(&rose_neigh->addr.digipeater[i])); } len += sprintf(buffer + len, "\n"); diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 384347a0e..f881e5da5 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c @@ -119,8 +119,9 @@ void rose_write_internal(struct sock *sk, int frametype) unsigned char lci1, lci2; char buffer[100]; int len, faclen = 0; + int ax25_header_len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + 1; - len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 1; + len = ax25_header_len + ROSE_MIN_LEN; switch (frametype) { case ROSE_CALL_REQUEST: @@ -141,9 +142,9 @@ void rose_write_internal(struct sock *sk, int frametype) /* * Space for AX.25 header and PID. */ - skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + 1); + skb_reserve(skb, ax25_header_len); - dptr = skb_put(skb, skb_tailroom(skb)); + dptr = skb_put(skb, len - ax25_header_len); lci1 = (sk->protinfo.rose->lci >> 8) & 0x0F; lci2 = (sk->protinfo.rose->lci >> 0) & 0xFF; |