ax25: zero length frame filtering in AX25
[safe/jmp/linux-2.6] / net / ax25 / af_ax25.c
index a5c94f1..7da5ebb 100644 (file)
@@ -13,7 +13,7 @@
  * Copyright (C) Hans Alblas PE1AYX (hans@esrac.ele.tue.nl)
  * Copyright (C) Frederic Rible F1OAT (frible@teaser.fr)
  */
-#include <linux/config.h>
+#include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/errno.h>
 #include <linux/types.h>
@@ -23,7 +23,6 @@
 #include <linux/sched.h>
 #include <linux/timer.h>
 #include <linux/string.h>
-#include <linux/smp_lock.h>
 #include <linux/sockios.h>
 #include <linux/net.h>
 #include <net/ax25.h>
@@ -45,7 +44,8 @@
 #include <linux/sysctl.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <net/tcp.h>
+#include <net/net_namespace.h>
+#include <net/tcp_states.h>
 #include <net/ip.h>
 #include <net/arp.h>
 
@@ -54,7 +54,7 @@
 HLIST_HEAD(ax25_list);
 DEFINE_SPINLOCK(ax25_list_lock);
 
-static struct proto_ops ax25_proto_ops;
+static const struct proto_ops ax25_proto_ops;
 
 static void ax25_free_sock(struct sock *sk)
 {
@@ -87,10 +87,22 @@ static void ax25_kill_by_device(struct net_device *dev)
                return;
 
        spin_lock_bh(&ax25_list_lock);
+again:
        ax25_for_each(s, node, &ax25_list) {
                if (s->ax25_dev == ax25_dev) {
                        s->ax25_dev = NULL;
+                       spin_unlock_bh(&ax25_list_lock);
                        ax25_disconnect(s, ENETUNREACH);
+                       spin_lock_bh(&ax25_list_lock);
+
+                       /* The entry could have been deleted from the
+                        * list meanwhile and thus the next pointer is
+                        * no longer valid.  Play it safe and restart
+                        * the scan.  Forward progress is ensured
+                        * because we set s->ax25_dev to NULL and we
+                        * are never passed a NULL 'dev' argument.
+                        */
+                       goto again;
                }
        }
        spin_unlock_bh(&ax25_list_lock);
@@ -104,6 +116,9 @@ static int ax25_device_event(struct notifier_block *this, unsigned long event,
 {
        struct net_device *dev = (struct net_device *)ptr;
 
+       if (!net_eq(dev_net(dev), &init_net))
+               return NOTIFY_DONE;
+
        /* Reject non AX.25 devices */
        if (dev->type != ARPHRD_AX25)
                return NOTIFY_DONE;
@@ -145,7 +160,7 @@ struct sock *ax25_find_listener(ax25_address *addr, int digi,
        ax25_cb *s;
        struct hlist_node *node;
 
-       spin_lock_bh(&ax25_list_lock);
+       spin_lock(&ax25_list_lock);
        ax25_for_each(s, node, &ax25_list) {
                if ((s->iamdigi && !digi) || (!s->iamdigi && digi))
                        continue;
@@ -154,12 +169,12 @@ struct sock *ax25_find_listener(ax25_address *addr, int digi,
                        /* If device is null we match any device */
                        if (s->ax25_dev == NULL || s->ax25_dev->dev == dev) {
                                sock_hold(s->sk);
-                               spin_unlock_bh(&ax25_list_lock);
+                               spin_unlock(&ax25_list_lock);
                                return s->sk;
                        }
                }
        }
-       spin_unlock_bh(&ax25_list_lock);
+       spin_unlock(&ax25_list_lock);
 
        return NULL;
 }
@@ -174,7 +189,7 @@ struct sock *ax25_get_socket(ax25_address *my_addr, ax25_address *dest_addr,
        ax25_cb *s;
        struct hlist_node *node;
 
-       spin_lock_bh(&ax25_list_lock);
+       spin_lock(&ax25_list_lock);
        ax25_for_each(s, node, &ax25_list) {
                if (s->sk && !ax25cmp(&s->source_addr, my_addr) &&
                    !ax25cmp(&s->dest_addr, dest_addr) &&
@@ -185,7 +200,7 @@ struct sock *ax25_get_socket(ax25_address *my_addr, ax25_address *dest_addr,
                }
        }
 
-       spin_unlock_bh(&ax25_list_lock);
+       spin_unlock(&ax25_list_lock);
 
        return sk;
 }
@@ -227,13 +242,15 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr,
        return NULL;
 }
 
+EXPORT_SYMBOL(ax25_find_cb);
+
 void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto)
 {
        ax25_cb *s;
        struct sk_buff *copy;
        struct hlist_node *node;
 
-       spin_lock_bh(&ax25_list_lock);
+       spin_lock(&ax25_list_lock);
        ax25_for_each(s, node, &ax25_list) {
                if (s->sk != NULL && ax25cmp(&s->source_addr, addr) == 0 &&
                    s->sk->sk_type == SOCK_RAW &&
@@ -246,7 +263,7 @@ void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto)
                                kfree_skb(copy);
                }
        }
-       spin_unlock_bh(&ax25_list_lock);
+       spin_unlock(&ax25_list_lock);
 }
 
 /*
@@ -261,9 +278,9 @@ static void ax25_destroy_timer(unsigned long data)
 {
        ax25_cb *ax25=(ax25_cb *)data;
        struct sock *sk;
-       
+
        sk=ax25->sk;
-       
+
        bh_lock_sock(sk);
        sock_hold(sk);
        ax25_destroy_socket(ax25);
@@ -300,6 +317,9 @@ void ax25_destroy_socket(ax25_cb *ax25)
                                /* Queue the unaccepted socket for death */
                                sock_orphan(skb->sk);
 
+                               /* 9A4GL: hack to release unaccepted sockets */
+                               skb->sk->sk_state = TCP_LISTEN;
+
                                ax25_start_heartbeat(sax25);
                                sax25->state = AX25_STATE_0;
                        }
@@ -313,10 +333,9 @@ void ax25_destroy_socket(ax25_cb *ax25)
                if (atomic_read(&ax25->sk->sk_wmem_alloc) ||
                    atomic_read(&ax25->sk->sk_rmem_alloc)) {
                        /* Defer: outstanding buffers */
-                       init_timer(&ax25->dtimer);
+                       setup_timer(&ax25->dtimer, ax25_destroy_timer,
+                                       (unsigned long)ax25);
                        ax25->dtimer.expires  = jiffies + 2 * HZ;
-                       ax25->dtimer.function = ax25_destroy_timer;
-                       ax25->dtimer.data     = (unsigned long)ax25;
                        add_timer(&ax25->dtimer);
                } else {
                        struct sock *sk=ax25->sk;
@@ -367,62 +386,82 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg)
                ax25_disconnect(ax25, ENETRESET);
                break;
 
-       case AX25_WINDOW:
-               if (ax25->modulus == AX25_MODULUS) {
-                       if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7)
-                               return -EINVAL;
-               } else {
-                       if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63)
-                               return -EINVAL;
-               }
-               ax25->window = ax25_ctl.arg;
-               break;
-
-       case AX25_T1:
+       case AX25_WINDOW:
+               if (ax25->modulus == AX25_MODULUS) {
+                       if (ax25_ctl.arg < 1 || ax25_ctl.arg > 7)
+                               return -EINVAL;
+               } else {
+                       if (ax25_ctl.arg < 1 || ax25_ctl.arg > 63)
+                               return -EINVAL;
+               }
+               ax25->window = ax25_ctl.arg;
+               break;
+
+       case AX25_T1:
                if (ax25_ctl.arg < 1)
-                       return -EINVAL;
-               ax25->rtt = (ax25_ctl.arg * HZ) / 2;
-               ax25->t1  = ax25_ctl.arg * HZ;
-               break;
-
-       case AX25_T2:
-               if (ax25_ctl.arg < 1)
-                       return -EINVAL;
-               ax25->t2 = ax25_ctl.arg * HZ;
-               break;
-
-       case AX25_N2:
-               if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31)
                        return -EINVAL;
-               ax25->n2count = 0;
-               ax25->n2 = ax25_ctl.arg;
-               break;
-
-       case AX25_T3:
-               if (ax25_ctl.arg < 0)
-                       return -EINVAL;
-               ax25->t3 = ax25_ctl.arg * HZ;
-               break;
-
-       case AX25_IDLE:
-               if (ax25_ctl.arg < 0)
-                       return -EINVAL;
-               ax25->idle = ax25_ctl.arg * 60 * HZ;
-               break;
-
-       case AX25_PACLEN:
-               if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535)
-                       return -EINVAL;
-               ax25->paclen = ax25_ctl.arg;
-               break;
-
-       default:
-               return -EINVAL;
+               ax25->rtt = (ax25_ctl.arg * HZ) / 2;
+               ax25->t1  = ax25_ctl.arg * HZ;
+               break;
+
+       case AX25_T2:
+               if (ax25_ctl.arg < 1)
+                       return -EINVAL;
+               ax25->t2 = ax25_ctl.arg * HZ;
+               break;
+
+       case AX25_N2:
+               if (ax25_ctl.arg < 1 || ax25_ctl.arg > 31)
+                       return -EINVAL;
+               ax25->n2count = 0;
+               ax25->n2 = ax25_ctl.arg;
+               break;
+
+       case AX25_T3:
+               if (ax25_ctl.arg < 0)
+                       return -EINVAL;
+               ax25->t3 = ax25_ctl.arg * HZ;
+               break;
+
+       case AX25_IDLE:
+               if (ax25_ctl.arg < 0)
+                       return -EINVAL;
+               ax25->idle = ax25_ctl.arg * 60 * HZ;
+               break;
+
+       case AX25_PACLEN:
+               if (ax25_ctl.arg < 16 || ax25_ctl.arg > 65535)
+                       return -EINVAL;
+               ax25->paclen = ax25_ctl.arg;
+               break;
+
+       default:
+               return -EINVAL;
          }
 
        return 0;
 }
 
+static void ax25_fillin_cb_from_dev(ax25_cb *ax25, ax25_dev *ax25_dev)
+{
+       ax25->rtt     = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]) / 2;
+       ax25->t1      = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]);
+       ax25->t2      = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T2]);
+       ax25->t3      = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T3]);
+       ax25->n2      = ax25_dev->values[AX25_VALUES_N2];
+       ax25->paclen  = ax25_dev->values[AX25_VALUES_PACLEN];
+       ax25->idle    = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_IDLE]);
+       ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF];
+
+       if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) {
+               ax25->modulus = AX25_EMODULUS;
+               ax25->window  = ax25_dev->values[AX25_VALUES_EWINDOW];
+       } else {
+               ax25->modulus = AX25_MODULUS;
+               ax25->window  = ax25_dev->values[AX25_VALUES_WINDOW];
+       }
+}
+
 /*
  *     Fill in a created AX.25 created control block with the default
  *     values for a particular device.
@@ -432,39 +471,28 @@ void ax25_fillin_cb(ax25_cb *ax25, ax25_dev *ax25_dev)
        ax25->ax25_dev = ax25_dev;
 
        if (ax25->ax25_dev != NULL) {
-               ax25->rtt     = ax25_dev->values[AX25_VALUES_T1] / 2;
-               ax25->t1      = ax25_dev->values[AX25_VALUES_T1];
-               ax25->t2      = ax25_dev->values[AX25_VALUES_T2];
-               ax25->t3      = ax25_dev->values[AX25_VALUES_T3];
-               ax25->n2      = ax25_dev->values[AX25_VALUES_N2];
-               ax25->paclen  = ax25_dev->values[AX25_VALUES_PACLEN];
-               ax25->idle    = ax25_dev->values[AX25_VALUES_IDLE];
-               ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF];
-
-               if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) {
-                       ax25->modulus = AX25_EMODULUS;
-                       ax25->window  = ax25_dev->values[AX25_VALUES_EWINDOW];
-               } else {
-                       ax25->modulus = AX25_MODULUS;
-                       ax25->window  = ax25_dev->values[AX25_VALUES_WINDOW];
-               }
+               ax25_fillin_cb_from_dev(ax25, ax25_dev);
+               return;
+       }
+
+       /*
+        * No device, use kernel / AX.25 spec default values
+        */
+       ax25->rtt     = msecs_to_jiffies(AX25_DEF_T1) / 2;
+       ax25->t1      = msecs_to_jiffies(AX25_DEF_T1);
+       ax25->t2      = msecs_to_jiffies(AX25_DEF_T2);
+       ax25->t3      = msecs_to_jiffies(AX25_DEF_T3);
+       ax25->n2      = AX25_DEF_N2;
+       ax25->paclen  = AX25_DEF_PACLEN;
+       ax25->idle    = msecs_to_jiffies(AX25_DEF_IDLE);
+       ax25->backoff = AX25_DEF_BACKOFF;
+
+       if (AX25_DEF_AXDEFMODE) {
+               ax25->modulus = AX25_EMODULUS;
+               ax25->window  = AX25_DEF_EWINDOW;
        } else {
-               ax25->rtt     = AX25_DEF_T1 / 2;
-               ax25->t1      = AX25_DEF_T1;
-               ax25->t2      = AX25_DEF_T2;
-               ax25->t3      = AX25_DEF_T3;
-               ax25->n2      = AX25_DEF_N2;
-               ax25->paclen  = AX25_DEF_PACLEN;
-               ax25->idle    = AX25_DEF_IDLE;
-               ax25->backoff = AX25_DEF_BACKOFF;
-
-               if (AX25_DEF_AXDEFMODE) {
-                       ax25->modulus = AX25_EMODULUS;
-                       ax25->window  = AX25_DEF_EWINDOW;
-               } else {
-                       ax25->modulus = AX25_MODULUS;
-                       ax25->window  = AX25_DEF_WINDOW;
-               }
+               ax25->modulus = AX25_MODULUS;
+               ax25->window  = AX25_DEF_WINDOW;
        }
 }
 
@@ -475,10 +503,9 @@ ax25_cb *ax25_create_cb(void)
 {
        ax25_cb *ax25;
 
-       if ((ax25 = kmalloc(sizeof(*ax25), GFP_ATOMIC)) == NULL)
+       if ((ax25 = kzalloc(sizeof(*ax25), GFP_ATOMIC)) == NULL)
                return NULL;
 
-       memset(ax25, 0x00, sizeof(*ax25));
        atomic_set(&ax25->refcount, 1);
 
        skb_queue_head_init(&ax25->write_queue);
@@ -486,11 +513,7 @@ ax25_cb *ax25_create_cb(void)
        skb_queue_head_init(&ax25->ack_queue);
        skb_queue_head_init(&ax25->reseq_queue);
 
-       init_timer(&ax25->timer);
-       init_timer(&ax25->t1timer);
-       init_timer(&ax25->t2timer);
-       init_timer(&ax25->t3timer);
-       init_timer(&ax25->idletimer);
+       ax25_setup_timers(ax25);
 
        ax25_fillin_cb(ax25, NULL);
 
@@ -546,7 +569,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
                        res = -EINVAL;
                        break;
                }
-               ax25->rtt = (opt * HZ) / 2;
+               ax25->rtt = (opt * HZ) >> 1;
                ax25->t1  = opt * HZ;
                break;
 
@@ -618,7 +641,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
                        break;
                }
 
-               dev = dev_get_by_name(devname);
+               dev = dev_get_by_name(&init_net, devname);
                if (dev == NULL) {
                        res = -ENODEV;
                        break;
@@ -770,11 +793,14 @@ static struct proto ax25_proto = {
        .obj_size = sizeof(struct sock),
 };
 
-static int ax25_create(struct socket *sock, int protocol)
+static int ax25_create(struct net *net, struct socket *sock, int protocol)
 {
        struct sock *sk;
        ax25_cb *ax25;
 
+       if (net != &init_net)
+               return -EAFNOSUPPORT;
+
        switch (sock->type) {
        case SOCK_DGRAM:
                if (protocol == 0 || protocol == PF_AX25)
@@ -820,7 +846,8 @@ static int ax25_create(struct socket *sock, int protocol)
                return -ESOCKTNOSUPPORT;
        }
 
-       if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, &ax25_proto, 1)) == NULL)
+       sk = sk_alloc(net, PF_AX25, GFP_ATOMIC, &ax25_proto);
+       if (sk == NULL)
                return -ENOMEM;
 
        ax25 = sk->sk_protinfo = ax25_create_cb();
@@ -845,7 +872,8 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
        struct sock *sk;
        ax25_cb *ax25, *oax25;
 
-       if ((sk = sk_alloc(PF_AX25, GFP_ATOMIC, osk->sk_prot, 1)) == NULL)
+       sk = sk_alloc(sock_net(osk), PF_AX25, GFP_ATOMIC,       osk->sk_prot);
+       if (sk == NULL)
                return NULL;
 
        if ((ax25 = ax25_create_cb()) == NULL) {
@@ -868,13 +896,11 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
 
        sk->sk_destruct = ax25_free_sock;
        sk->sk_type     = osk->sk_type;
-       sk->sk_socket   = osk->sk_socket;
        sk->sk_priority = osk->sk_priority;
        sk->sk_protocol = osk->sk_protocol;
        sk->sk_rcvbuf   = osk->sk_rcvbuf;
        sk->sk_sndbuf   = osk->sk_sndbuf;
        sk->sk_state    = TCP_ESTABLISHED;
-       sk->sk_sleep    = osk->sk_sleep;
        sock_copy_flags(sk, osk);
 
        oax25 = ax25_sk(osk);
@@ -896,13 +922,13 @@ struct sock *ax25_make_new(struct sock *osk, struct ax25_dev *ax25_dev)
        ax25->source_addr = oax25->source_addr;
 
        if (oax25->digipeat != NULL) {
-               if ((ax25->digipeat = kmalloc(sizeof(ax25_digi), GFP_ATOMIC)) == NULL) {
+               ax25->digipeat = kmemdup(oax25->digipeat, sizeof(ax25_digi),
+                                        GFP_ATOMIC);
+               if (ax25->digipeat == NULL) {
                        sk_free(sk);
                        ax25_cb_put(ax25);
                        return NULL;
                }
-
-               memcpy(ax25->digipeat, oax25->digipeat, sizeof(ax25_digi));
        }
 
        sk->sk_protinfo = ax25;
@@ -1008,21 +1034,18 @@ static int ax25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        int err = 0;
 
        if (addr_len != sizeof(struct sockaddr_ax25) &&
-           addr_len != sizeof(struct full_sockaddr_ax25)) {
-               /* support for old structure may go away some time */
+           addr_len != sizeof(struct full_sockaddr_ax25))
+               /* support for old structure may go away some time
+                * ax25_bind(): uses old (6 digipeater) socket structure.
+                */
                if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||
-                   (addr_len > sizeof(struct full_sockaddr_ax25))) {
+                   (addr_len > sizeof(struct full_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;
 
-       user = ax25_findbyuid(current->euid);
+       user = ax25_findbyuid(current_euid());
        if (user) {
                call = user->call;
                ax25_uid_put(user);
@@ -1078,8 +1101,8 @@ out:
 /*
  *     FIXME: nonblock behaviour looks like it may have a bug.
  */
-static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
-       int addr_len, int flags)
+static int __must_check ax25_connect(struct socket *sock,
+       struct sockaddr *uaddr, int addr_len, int flags)
 {
        struct sock *sk = sock->sk;
        ax25_cb *ax25 = ax25_sk(sk), *ax25t;
@@ -1091,21 +1114,19 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
         * some sanity checks. code further down depends on this
         */
 
-       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))
+               /* support for this will go away in early 2.5.x
+                * ax25_connect(): uses obsolete socket structure
+                */
+               ;
+       else if (addr_len != sizeof(struct full_sockaddr_ax25))
+               /* support for old structure may go away some time
+                * ax25_connect(): uses old (6 digipeater) socket structure.
+                */
                if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||
-                   (addr_len > sizeof(struct full_sockaddr_ax25))) {
+                   (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;
@@ -1117,31 +1138,29 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
                switch (sk->sk_state) {
                case TCP_SYN_SENT: /* still trying */
                        err = -EINPROGRESS;
-                       goto out;
+                       goto out_release;
 
                case TCP_ESTABLISHED: /* connection established */
                        sock->state = SS_CONNECTED;
-                       goto out;
+                       goto out_release;
 
                case TCP_CLOSE: /* connection refused */
                        sock->state = SS_UNCONNECTED;
                        err = -ECONNREFUSED;
-                       goto out;
+                       goto out_release;
                }
        }
 
        if (sk->sk_state == TCP_ESTABLISHED && sk->sk_type == SOCK_SEQPACKET) {
                err = -EISCONN; /* No reconnect on a seqpacket socket */
-               goto out;
+               goto out_release;
        }
 
        sk->sk_state   = TCP_CLOSE;
        sock->state = SS_UNCONNECTED;
 
-       if (ax25->digipeat != NULL) {
-               kfree(ax25->digipeat);
-               ax25->digipeat = NULL;
-       }
+       kfree(ax25->digipeat);
+       ax25->digipeat = NULL;
 
        /*
         *      Handle digi-peaters to be used.
@@ -1151,12 +1170,12 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
                /* Valid number of digipeaters ? */
                if (fsa->fsa_ax25.sax25_ndigis < 1 || fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS) {
                        err = -EINVAL;
-                       goto out;
+                       goto out_release;
                }
 
                if ((digi = kmalloc(sizeof(ax25_digi), GFP_KERNEL)) == NULL) {
                        err = -ENOBUFS;
-                       goto out;
+                       goto out_release;
                }
 
                digi->ndigi      = fsa->fsa_ax25.sax25_ndigis;
@@ -1186,7 +1205,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
                        current->comm);
                if ((err = ax25_rt_autobind(ax25, &fsa->fsa_ax25.sax25_call)) < 0) {
                        kfree(digi);
-                       goto out;
+                       goto out_release;
                }
 
                ax25_fillin_cb(ax25, ax25->ax25_dev);
@@ -1195,17 +1214,17 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
                if (ax25->ax25_dev == NULL) {
                        kfree(digi);
                        err = -EHOSTUNREACH;
-                       goto out;
+                       goto out_release;
                }
        }
 
        if (sk->sk_type == SOCK_SEQPACKET &&
            (ax25t=ax25_find_cb(&ax25->source_addr, &fsa->fsa_ax25.sax25_call, digi,
-                        ax25->ax25_dev->dev))) {
+                        ax25->ax25_dev->dev))) {
                kfree(digi);
                err = -EADDRINUSE;              /* Already such a connection */
                ax25_cb_put(ax25t);
-               goto out;
+               goto out_release;
        }
 
        ax25->dest_addr = fsa->fsa_ax25.sax25_call;
@@ -1215,7 +1234,7 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
        if (sk->sk_type != SOCK_SEQPACKET) {
                sock->state = SS_CONNECTED;
                sk->sk_state   = TCP_ESTABLISHED;
-               goto out;
+               goto out_release;
        }
 
        /* Move to connecting socket, ax.25 lapb WAIT_UA.. */
@@ -1247,55 +1266,53 @@ static int ax25_connect(struct socket *sock, struct sockaddr *uaddr,
        /* Now the loop */
        if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {
                err = -EINPROGRESS;
-               goto out;
+               goto out_release;
        }
 
        if (sk->sk_state == TCP_SYN_SENT) {
-               struct task_struct *tsk = current;
-               DECLARE_WAITQUEUE(wait, tsk);
+               DEFINE_WAIT(wait);
 
-               add_wait_queue(sk->sk_sleep, &wait);
                for (;;) {
+                       prepare_to_wait(sk->sk_sleep, &wait,
+                                       TASK_INTERRUPTIBLE);
                        if (sk->sk_state != TCP_SYN_SENT)
                                break;
-                       set_current_state(TASK_INTERRUPTIBLE);
-                       release_sock(sk);
-                       if (!signal_pending(tsk)) {
+                       if (!signal_pending(current)) {
+                               release_sock(sk);
                                schedule();
                                lock_sock(sk);
                                continue;
                        }
-                       current->state = TASK_RUNNING;
-                       remove_wait_queue(sk->sk_sleep, &wait);
-                       return -ERESTARTSYS;
+                       err = -ERESTARTSYS;
+                       break;
                }
-               current->state = TASK_RUNNING;
-               remove_wait_queue(sk->sk_sleep, &wait);
+               finish_wait(sk->sk_sleep, &wait);
+
+               if (err)
+                       goto out_release;
        }
 
        if (sk->sk_state != TCP_ESTABLISHED) {
                /* Not in ABM, not in WAIT_UA -> failed */
                sock->state = SS_UNCONNECTED;
                err = sock_error(sk);   /* Always set at this point */
-               goto out;
+               goto out_release;
        }
 
        sock->state = SS_CONNECTED;
 
-       err=0;
-out:
+       err = 0;
+out_release:
        release_sock(sk);
 
        return err;
 }
 
-
 static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
 {
-       struct task_struct *tsk = current;
-       DECLARE_WAITQUEUE(wait, tsk);
        struct sk_buff *skb;
        struct sock *newsk;
+       DEFINE_WAIT(wait);
        struct sock *sk;
        int err = 0;
 
@@ -1320,39 +1337,36 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags)
         *      The read queue this time is holding sockets ready to use
         *      hooked into the SABM we saved
         */
-       add_wait_queue(sk->sk_sleep, &wait);
        for (;;) {
+               prepare_to_wait(sk->sk_sleep, &wait, TASK_INTERRUPTIBLE);
                skb = skb_dequeue(&sk->sk_receive_queue);
                if (skb)
                        break;
 
-               release_sock(sk);
-               current->state = TASK_INTERRUPTIBLE;
                if (flags & O_NONBLOCK) {
-                       current->state = TASK_RUNNING;
-                       remove_wait_queue(sk->sk_sleep, &wait);
-                       return -EWOULDBLOCK;
+                       err = -EWOULDBLOCK;
+                       break;
                }
-               if (!signal_pending(tsk)) {
+               if (!signal_pending(current)) {
+                       release_sock(sk);
                        schedule();
                        lock_sock(sk);
                        continue;
                }
-               current->state = TASK_RUNNING;
-               remove_wait_queue(sk->sk_sleep, &wait);
-               return -ERESTARTSYS;
+               err = -ERESTARTSYS;
+               break;
        }
-       current->state = TASK_RUNNING;
-       remove_wait_queue(sk->sk_sleep, &wait);
+       finish_wait(sk->sk_sleep, &wait);
+
+       if (err)
+               goto out;
 
        newsk            = skb->sk;
-       newsk->sk_socket = newsock;
-       newsk->sk_sleep  = &newsock->wait;
+       sock_graft(newsk, newsock);
 
        /* Now attach up the new socket */
        kfree_skb(skb);
        sk->sk_ack_backlog--;
-       newsock->sk    = newsk;
        newsock->state = SS_CONNECTED;
 
 out:
@@ -1417,11 +1431,15 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
        struct sockaddr_ax25 sax;
        struct sk_buff *skb;
        ax25_digi dtmp, *dp;
-       unsigned char *asmptr;
        ax25_cb *ax25;
        size_t size;
        int lv, err, addr_len = msg->msg_namelen;
 
+       /* AX.25 empty data frame has no meaning : don't send */
+       if (len == 0) {
+               return (0);
+       }
+
        if (msg->msg_flags & ~(MSG_DONTWAIT|MSG_EOR|MSG_CMSG_COMPAT))
                return -EINVAL;
 
@@ -1448,28 +1466,27 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
                err = -EMSGSIZE;
                goto out;
        }
-               
+
        if (usax != NULL) {
                if (usax->sax25_family != AF_AX25) {
                        err = -EINVAL;
                        goto out;
                }
 
-               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))
+                       /* ax25_sendmsg(): uses obsolete socket structure */
+                       ;
+               else if (addr_len != sizeof(struct full_sockaddr_ax25))
+                       /* support for old structure may go away some time
+                        * ax25_sendmsg(): uses old (6 digipeater)
+                        * socket structure.
+                        */
                        if ((addr_len < sizeof(struct sockaddr_ax25) + sizeof(ax25_address) * 6) ||
-                           (addr_len > sizeof(struct full_sockaddr_ax25))) {
-                               err = -EINVAL;
+                           (addr_len > sizeof(struct full_sockaddr_ax25))) {
+                               err = -EINVAL;
                                goto out;
                        }
 
-                       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;
@@ -1517,10 +1534,8 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
                dp = ax25->digipeat;
        }
 
-       SOCK_DEBUG(sk, "AX.25: sendto: Addresses built.\n");
-
        /* Build a packet */
-       SOCK_DEBUG(sk, "AX.25: sendto: building packet.\n");
+       SOCK_DEBUG(sk, "AX.25: sendto: Addresses built. Building packet.\n");
 
        /* Assume the worst case */
        size = len + ax25->ax25_dev->dev->hard_header_len;
@@ -1540,13 +1555,11 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
                goto out;
        }
 
-       skb->nh.raw = skb->data;
+       skb_reset_network_header(skb);
 
        /* Add the PID if one is not supplied by the user in the skb */
-       if (!ax25->pidincl) {
-               asmptr  = skb_push(skb, 1);
-               *asmptr = sk->sk_protocol;
-       }
+       if (!ax25->pidincl)
+               *skb_push(skb, 1) = sk->sk_protocol;
 
        SOCK_DEBUG(sk, "AX.25: Transmitting buffer\n");
 
@@ -1565,7 +1578,7 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
                goto out;
        }
 
-       asmptr = skb_push(skb, 1 + ax25_addr_size(dp));
+       skb_push(skb, 1 + ax25_addr_size(dp));
 
        SOCK_DEBUG(sk, "Building AX.25 Header (dp=%p).\n", dp);
 
@@ -1573,17 +1586,17 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
                SOCK_DEBUG(sk, "Num digipeaters=%d\n", dp->ndigi);
 
        /* Build an AX.25 header */
-       asmptr += (lv = ax25_addr_build(asmptr, &ax25->source_addr,
-                                       &sax.sax25_call, dp,
-                                       AX25_COMMAND, AX25_MODULUS));
+       lv = ax25_addr_build(skb->data, &ax25->source_addr, &sax.sax25_call,
+                            dp, AX25_COMMAND, AX25_MODULUS);
 
        SOCK_DEBUG(sk, "Built header (%d bytes)\n",lv);
 
-       skb->h.raw = asmptr;
+       skb_set_transport_header(skb, lv);
 
-       SOCK_DEBUG(sk, "base=%p pos=%p\n", skb->data, asmptr);
+       SOCK_DEBUG(sk, "base=%p pos=%p\n",
+                  skb->data, skb_transport_header(skb));
 
-       *asmptr = AX25_UI;
+       *skb_transport_header(skb) = AX25_UI;
 
        /* Datagram frames go straight out of the door as UI */
        ax25_queue_xmit(skb, ax25->ax25_dev->dev);
@@ -1616,15 +1629,22 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        /* Now we can treat all alike */
        skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT,
-                               flags & MSG_DONTWAIT, &err);
+                               flags & MSG_DONTWAIT, &err);
        if (skb == NULL)
                goto out;
 
        if (!ax25_sk(sk)->pidincl)
                skb_pull(skb, 1);               /* Remove PID */
 
-       skb->h.raw = skb->data;
-       copied     = skb->len;
+       skb_reset_transport_header(skb);
+       copied = skb->len;
+
+       /* AX.25 empty data frame has no meaning : ignore it */
+       if (copied == 0) {
+               err = copied;
+               skb_free_datagram(sk, skb);
+               goto out;
+       }
 
        if (copied > size) {
                copied = size;
@@ -1637,9 +1657,10 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
                struct sockaddr_ax25 *sax = (struct sockaddr_ax25 *)msg->msg_name;
                ax25_digi digi;
                ax25_address src;
+               const unsigned char *mac = skb_mac_header(skb);
 
-               ax25_addr_parse(skb->mac.raw+1, skb->data-skb->mac.raw-1, &src, NULL, &digi, NULL, NULL);
-
+               ax25_addr_parse(mac + 1, skb->data - mac - 1, &src, NULL,
+                               &digi, NULL, NULL);
                sax->sax25_family = AF_AX25;
                /* We set this correctly, even though we may not let the
                   application know the digi calls further down (because it
@@ -1695,16 +1716,16 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                /* These two are safe on a single CPU system as only user tasks fiddle here */
                if ((skb = skb_peek(&sk->sk_receive_queue)) != NULL)
                        amount = skb->len;
-               res = put_user(amount, (int __user *)argp);
+               res = put_user(amount, (int __user *) argp);
                break;
        }
 
        case SIOCGSTAMP:
-               if (sk != NULL) {
-                       res = sock_get_timestamp(sk, argp);
-                       break;
-               }
-               res = -EINVAL;
+               res = sock_get_timestamp(sk, argp);
+               break;
+
+       case SIOCGSTAMPNS:
+               res = sock_get_timestampns(sk, argp);
                break;
 
        case SIOCAX25ADDUID:    /* Add a uid to the uid/call map table */
@@ -1833,7 +1854,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                break;
 
        default:
-               res = dev_ioctl(cmd, argp);
+               res = -ENOIOCTLCMD;
                break;
        }
        release_sock(sk);
@@ -1844,6 +1865,7 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
 #ifdef CONFIG_PROC_FS
 
 static void *ax25_info_start(struct seq_file *seq, loff_t *pos)
+       __acquires(ax25_list_lock)
 {
        struct ax25_cb *ax25;
        struct hlist_node *node;
@@ -1865,8 +1887,9 @@ static void *ax25_info_next(struct seq_file *seq, void *v, loff_t *pos)
        return hlist_entry( ((struct ax25_cb *)v)->ax25_node.next,
                            struct ax25_cb, ax25_node);
 }
-       
+
 static void ax25_info_stop(struct seq_file *seq, void *v)
+       __releases(ax25_list_lock)
 {
        spin_unlock_bh(&ax25_list_lock);
 }
@@ -1874,6 +1897,7 @@ static void ax25_info_stop(struct seq_file *seq, void *v)
 static int ax25_info_show(struct seq_file *seq, void *v)
 {
        ax25_cb *ax25 = v;
+       char buf[11];
        int k;
 
 
@@ -1885,13 +1909,13 @@ static int ax25_info_show(struct seq_file *seq, void *v)
        seq_printf(seq, "%8.8lx %s %s%s ",
                   (long) ax25,
                   ax25->ax25_dev == NULL? "???" : ax25->ax25_dev->dev->name,
-                  ax2asc(&ax25->source_addr),
+                  ax2asc(buf, &ax25->source_addr),
                   ax25->iamdigi? "*":"");
-       seq_printf(seq, "%s", ax2asc(&ax25->dest_addr));
+       seq_printf(seq, "%s", ax2asc(buf, &ax25->dest_addr));
 
        for (k=0; (ax25->digipeat != NULL) && (k < ax25->digipeat->ndigi); k++) {
                seq_printf(seq, ",%s%s",
-                          ax2asc(&ax25->digipeat->calls[k]),
+                          ax2asc(buf, &ax25->digipeat->calls[k]),
                           ax25->digipeat->repeated[k]? "*":"");
        }
 
@@ -1909,19 +1933,17 @@ static int ax25_info_show(struct seq_file *seq, void *v)
                   ax25->paclen);
 
        if (ax25->sk != NULL) {
-               bh_lock_sock(ax25->sk);
-               seq_printf(seq," %d %d %ld\n",
+               seq_printf(seq, " %d %d %lu\n",
                           atomic_read(&ax25->sk->sk_wmem_alloc),
                           atomic_read(&ax25->sk->sk_rmem_alloc),
-                          ax25->sk->sk_socket != NULL ? SOCK_INODE(ax25->sk->sk_socket)->i_ino : 0L);
-               bh_unlock_sock(ax25->sk);
+                          sock_i_ino(ax25->sk));
        } else {
                seq_puts(seq, " * * *\n");
        }
        return 0;
 }
 
-static struct seq_operations ax25_info_seqops = {
+static const struct seq_operations ax25_info_seqops = {
        .start = ax25_info_start,
        .next = ax25_info_next,
        .stop = ax25_info_stop,
@@ -1933,7 +1955,7 @@ static int ax25_info_open(struct inode *inode, struct file *file)
        return seq_open(file, &ax25_info_seqops);
 }
 
-static struct file_operations ax25_info_fops = {
+static const struct file_operations ax25_info_fops = {
        .owner = THIS_MODULE,
        .open = ax25_info_open,
        .read = seq_read,
@@ -1949,33 +1971,32 @@ static struct net_proto_family ax25_family_ops = {
        .owner  =       THIS_MODULE,
 };
 
-static struct proto_ops ax25_proto_ops = {
-       .family =       PF_AX25,
-       .owner =        THIS_MODULE,
-       .release =      ax25_release,
-       .bind =         ax25_bind,
-       .connect =      ax25_connect,
-       .socketpair =   sock_no_socketpair,
-       .accept =       ax25_accept,
-       .getname =      ax25_getname,
-       .poll =         datagram_poll,
-       .ioctl =        ax25_ioctl,
-       .listen =       ax25_listen,
-       .shutdown =     ax25_shutdown,
-       .setsockopt =   ax25_setsockopt,
-       .getsockopt =   ax25_getsockopt,
-       .sendmsg =      ax25_sendmsg,
-       .recvmsg =      ax25_recvmsg,
-       .mmap =         sock_no_mmap,
-       .sendpage =     sock_no_sendpage,
+static const struct proto_ops ax25_proto_ops = {
+       .family         = PF_AX25,
+       .owner          = THIS_MODULE,
+       .release        = ax25_release,
+       .bind           = ax25_bind,
+       .connect        = ax25_connect,
+       .socketpair     = sock_no_socketpair,
+       .accept         = ax25_accept,
+       .getname        = ax25_getname,
+       .poll           = datagram_poll,
+       .ioctl          = ax25_ioctl,
+       .listen         = ax25_listen,
+       .shutdown       = ax25_shutdown,
+       .setsockopt     = ax25_setsockopt,
+       .getsockopt     = ax25_getsockopt,
+       .sendmsg        = ax25_sendmsg,
+       .recvmsg        = ax25_recvmsg,
+       .mmap           = sock_no_mmap,
+       .sendpage       = sock_no_sendpage,
 };
 
 /*
  *     Called by socket.c on kernel start up
  */
-static struct packet_type ax25_packet_type = {
-       .type   =       __constant_htons(ETH_P_AX25),
-       .dev    =       NULL,                           /* All devices */
+static struct packet_type ax25_packet_type __read_mostly = {
+       .type   =       cpu_to_be16(ETH_P_AX25),
        .func   =       ax25_kiss_rcv,
 };
 
@@ -1983,24 +2004,6 @@ static struct notifier_block ax25_dev_notifier = {
        .notifier_call =ax25_device_event,
 };
 
-EXPORT_SYMBOL(ax25_encapsulate);
-EXPORT_SYMBOL(ax25_rebuild_header);
-EXPORT_SYMBOL(ax25_findbyuid);
-EXPORT_SYMBOL(ax25_find_cb);
-EXPORT_SYMBOL(ax25_linkfail_register);
-EXPORT_SYMBOL(ax25_linkfail_release);
-EXPORT_SYMBOL(ax25_listen_register);
-EXPORT_SYMBOL(ax25_listen_release);
-EXPORT_SYMBOL(ax25_protocol_register);
-EXPORT_SYMBOL(ax25_protocol_release);
-EXPORT_SYMBOL(ax25_send_frame);
-EXPORT_SYMBOL(ax25_uid_policy);
-EXPORT_SYMBOL(ax25cmp);
-EXPORT_SYMBOL(ax2asc);
-EXPORT_SYMBOL(asc2ax);
-EXPORT_SYMBOL(null_ax25_address);
-EXPORT_SYMBOL(ax25_display_timer);
-
 static int __init ax25_init(void)
 {
        int rc = proto_register(&ax25_proto, 0);
@@ -2013,9 +2016,9 @@ static int __init ax25_init(void)
        register_netdevice_notifier(&ax25_dev_notifier);
        ax25_register_sysctl();
 
-       proc_net_fops_create("ax25_route", S_IRUGO, &ax25_route_fops);
-       proc_net_fops_create("ax25", S_IRUGO, &ax25_info_fops);
-       proc_net_fops_create("ax25_calls", S_IRUGO, &ax25_uid_fops);
+       proc_net_fops_create(&init_net, "ax25_route", S_IRUGO, &ax25_route_fops);
+       proc_net_fops_create(&init_net, "ax25", S_IRUGO, &ax25_info_fops);
+       proc_net_fops_create(&init_net, "ax25_calls", S_IRUGO, &ax25_uid_fops);
 out:
        return rc;
 }
@@ -2029,9 +2032,9 @@ MODULE_ALIAS_NETPROTO(PF_AX25);
 
 static void __exit ax25_exit(void)
 {
-       proc_net_remove("ax25_route");
-       proc_net_remove("ax25");
-       proc_net_remove("ax25_calls");
+       proc_net_remove(&init_net, "ax25_route");
+       proc_net_remove(&init_net, "ax25");
+       proc_net_remove(&init_net, "ax25_calls");
        ax25_rt_free();
        ax25_uid_free();
        ax25_dev_free();