patch-2.3.99-pre1 linux/net/ax25/af_ax25.c
Next file: linux/net/econet/af_econet.c
Previous file: linux/net/atm/Makefile
Back to the patch index
Back to the overall index
- Lines: 253
- Date:
Sun Mar 12 19:21:26 2000
- Orig file:
v2.3.51/linux/net/ax25/af_ax25.c
- Orig date:
Wed Feb 16 17:03:52 2000
diff -u --recursive --new-file v2.3.51/linux/net/ax25/af_ax25.c linux/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 @@
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 @@
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,14 +732,23 @@
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:
@@ -763,17 +794,30 @@
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 @@
/*
* 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 @@
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 @@
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 @@
/*
* 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 @@
kfree(sk->protinfo.ax25->digipeat);
sk->protinfo.ax25->digipeat = NULL;
}
-
+
/*
* Handle digi-peaters to be used.
*/
@@ -1138,6 +1194,9 @@
* 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 @@
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;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)