diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-03-19 01:28:40 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-03-19 01:28:40 +0000 |
commit | 8abb719409c9060a7c0676f76e9182c1e0b8ca46 (patch) | |
tree | b88cc5a6cd513a04a512b7e6215c873c90a1c5dd /net/ax25 | |
parent | f01bd7aeafd95a08aafc9e3636bb26974df69d82 (diff) |
Merge with 2.3.99-pre1.
Diffstat (limited to 'net/ax25')
-rw-r--r-- | net/ax25/af_ax25.c | 145 |
1 files changed, 107 insertions, 38 deletions
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index a676660dc..949c2b3e9 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -96,6 +96,10 @@ * AX.25 038 Matthias(DG2FEF) Small fixes to the syscall interface to make kernel * independent of AX25_MAX_DIGIS used by applications. * Tomi(OH2BNS) Fixed ax25_getname(). + * Joerg(DL1BKE) Starting to phase out the support for full_sockaddr_ax25 + * with only 6 digipeaters and sockaddr_ax25 in ax25_bind(), + * ax25_connect() and ax25_sendmsg() + * Joerg(DL1BKE) Added support for SO_BINDTODEVICE */ #include <linux/config.h> @@ -624,6 +628,8 @@ ax25_cb *ax25_create_cb(void) static int ax25_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_AX25) @@ -702,6 +708,22 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, char *op sk->protinfo.ax25->paclen = opt; 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.ax25->ax25_dev = ax25_dev_ax25dev(dev); + ax25_fillin_cb(sk->protinfo.ax25, sk->protinfo.ax25->ax25_dev); + return 0; + default: return -ENOPROTOOPT; } @@ -710,15 +732,24 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname, char *op static int ax25_getsockopt(struct socket *sock, int level, int optname, char *optval, int *optlen) { struct sock *sk = sock->sk; + struct ax25_dev *ax25_dev; + char devname[IFNAMSIZ]; + void *valptr; int val = 0; - int len; + int maxlen, length; if (level != SOL_AX25) 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 AX25_WINDOW: val = sk->protinfo.ax25->window; @@ -763,17 +794,30 @@ static int ax25_getsockopt(struct socket *sock, int level, int optname, char *op case AX25_PACLEN: val = sk->protinfo.ax25->paclen; break; + + case SO_BINDTODEVICE: + ax25_dev = sk->protinfo.ax25->ax25_dev; + + if (ax25_dev != NULL && ax25_dev->dev != NULL) { + strncpy(devname, ax25_dev->dev->name, IFNAMSIZ); + length = min(strlen(ax25_dev->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(len, optlen)) + if (put_user(length, optlen)) return -EFAULT; - if (copy_to_user(optval, &val, len)) + if (copy_to_user(optval, valptr, length)) return -EFAULT; return 0; @@ -997,9 +1041,9 @@ static int ax25_release(struct socket *sock) /* * We support a funny extension here so you can (as root) give any callsign - * digipeated via a local address as source. This is a hack until we add - * BSD 4.4 ADDIFADDR type support. It is however small and trivially backward - * compatible 8) + * digipeated via a local address as source. This hack is obsolete now + * that we've implemented support for SO_BINDTODEVICE. It is however small + * and trivially backward compatible. */ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) { @@ -1011,11 +1055,16 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) if (sk->zapped == 0) return -EINVAL; - if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(struct full_sockaddr_ax25)) - return -EINVAL; + if (addr_len != sizeof(struct sockaddr_ax25) && + addr_len != sizeof(struct full_sockaddr_ax25)) { + /* support for old structure may go away some time */ + if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) || + (addr_len > sizeof(struct full_sockaddr_ax25))) + return -EINVAL; - if (addr_len < (addr->fsa_ax25.sax25_ndigis * sizeof(ax25_address) + sizeof(struct sockaddr_ax25))) - return -EINVAL; + printk(KERN_WARNING "ax25_bind(): %s uses old (6 digipeater) socket structure.\n", + current->comm); + } if (addr->fsa_ax25.sax25_family != AF_AX25) return -EINVAL; @@ -1029,34 +1078,28 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) else sk->protinfo.ax25->source_addr = *call; - SOCK_DEBUG(sk, "AX25: source address set to %s\n", ax2asc(&sk->protinfo.ax25->source_addr)); + /* + * User already set interface with SO_BINDTODEVICE + */ + + if (sk->protinfo.ax25->ax25_dev != NULL) + goto done; if (addr_len > sizeof(struct sockaddr_ax25) && addr->fsa_ax25.sax25_ndigis == 1) { - if (ax25cmp(&addr->fsa_digipeater[0], &null_ax25_address) == 0) { - ax25_dev = NULL; - SOCK_DEBUG(sk, "AX25: bound to any device\n"); - } else { - if ((ax25_dev = ax25_addr_ax25dev(&addr->fsa_digipeater[0])) == NULL) { - SOCK_DEBUG(sk, "AX25: bind failed - no device\n"); - return -EADDRNOTAVAIL; - } - SOCK_DEBUG(sk, "AX25: bound to device %s\n", ax25_dev->dev->name); - } - } else { - if ((ax25_dev = ax25_addr_ax25dev(&addr->fsa_ax25.sax25_call)) == NULL) { - SOCK_DEBUG(sk, "AX25: bind failed - no device\n"); + if (ax25cmp(&addr->fsa_digipeater[0], &null_ax25_address) != 0 && + (ax25_dev = ax25_addr_ax25dev(&addr->fsa_digipeater[0])) == NULL) + return -EADDRNOTAVAIL; + } else { + if ((ax25_dev = ax25_addr_ax25dev(&addr->fsa_ax25.sax25_call)) == NULL) return -EADDRNOTAVAIL; - } - SOCK_DEBUG(sk, "AX25: bound to device %s\n", ax25_dev->dev->name); } if (ax25_dev != NULL) ax25_fillin_cb(sk->protinfo.ax25, ax25_dev); +done: ax25_insert_socket(sk->protinfo.ax25); - sk->zapped = 0; - SOCK_DEBUG(sk, "AX25: socket is bound\n"); return 0; } @@ -1095,8 +1138,21 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le /* * some sanity checks. code further down depends on this */ - if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(struct full_sockaddr_ax25)) - return -EINVAL; + + if (addr_len == sizeof(struct sockaddr_ax25)) { + /* support for this will go away in early 2.5.x */ + printk(KERN_WARNING "ax25_connect(): %s uses obsolete socket structure\n", + current->comm); + } + else if (addr_len != sizeof(struct full_sockaddr_ax25)) { + /* support for old structure may go away some time */ + if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) || + (addr_len > sizeof(struct full_sockaddr_ax25))) + return -EINVAL; + + printk(KERN_WARNING "ax25_connect(): %s uses old (6 digipeater) socket structure.\n", + current->comm); + } if (fsa->fsa_ax25.sax25_family != AF_AX25) return -EINVAL; @@ -1105,7 +1161,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le kfree(sk->protinfo.ax25->digipeat); sk->protinfo.ax25->digipeat = NULL; } - + /* * Handle digi-peaters to be used. */ @@ -1138,6 +1194,9 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr, int addr_le * been filled in, error if it hasn't. */ if (sk->zapped) { + /* check if we can remove this feature. It is broken. */ + printk(KERN_WARNING "ax25_connect(): %s uses autobind, please contact jreuter@poboxes.com\n", + current->comm); if ((err = ax25_rt_autobind(sk->protinfo.ax25, &fsa->fsa_ax25.sax25_call)) < 0) return err; ax25_fillin_cb(sk->protinfo.ax25, sk->protinfo.ax25->ax25_dev); @@ -1330,10 +1389,20 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, int len, struct if (usax != NULL) { if (usax->sax25_family != AF_AX25) return -EINVAL; - if (addr_len < sizeof(struct sockaddr_ax25) || addr_len > sizeof(struct full_sockaddr_ax25)) - return -EINVAL; - if (addr_len < (usax->sax25_ndigis * AX25_ADDR_LEN + sizeof(struct sockaddr_ax25))) - return -EINVAL; + + if (addr_len == sizeof(struct sockaddr_ax25)) { + printk(KERN_WARNING "ax25_sendmsg(): %s uses obsolete socket structure\n", + current->comm); + } + else if (addr_len != sizeof(struct full_sockaddr_ax25)) { + /* support for old structure may go away some time */ + if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) || + (addr_len > sizeof(struct full_sockaddr_ax25))) + return -EINVAL; + + printk(KERN_WARNING "ax25_sendmsg(): %s uses old (6 digipeater) socket structure.\n", + current->comm); + } if (addr_len > sizeof(struct sockaddr_ax25) && usax->sax25_ndigis != 0) { int ct = 0; |