summaryrefslogtreecommitdiffstats
path: root/net/ax25
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2000-03-19 01:28:40 +0000
committerRalf Baechle <ralf@linux-mips.org>2000-03-19 01:28:40 +0000
commit8abb719409c9060a7c0676f76e9182c1e0b8ca46 (patch)
treeb88cc5a6cd513a04a512b7e6215c873c90a1c5dd /net/ax25
parentf01bd7aeafd95a08aafc9e3636bb26974df69d82 (diff)
Merge with 2.3.99-pre1.
Diffstat (limited to 'net/ax25')
-rw-r--r--net/ax25/af_ax25.c145
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;