ax25: zero length frame filtering in AX25
[safe/jmp/linux-2.6] / net / ax25 / af_ax25.c
index 14db01a..7da5ebb 100644 (file)
@@ -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,6 +44,7 @@
 #include <linux/sysctl.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <net/net_namespace.h>
 #include <net/tcp_states.h>
 #include <net/ip.h>
 #include <net/arp.h>
@@ -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;
@@ -302,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;
                        }
@@ -315,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;
@@ -496,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);
 
@@ -556,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;
 
@@ -628,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;
@@ -780,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)
@@ -830,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();
@@ -855,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) {
@@ -878,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);
@@ -1018,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);
@@ -1101,21 +1114,19 @@ static int __must_check ax25_connect(struct socket *sock,
         * 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;
@@ -1127,22 +1138,22 @@ static int __must_check ax25_connect(struct socket *sock,
                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;
@@ -1159,12 +1170,12 @@ static int __must_check ax25_connect(struct socket *sock,
                /* 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;
@@ -1194,7 +1205,7 @@ static int __must_check ax25_connect(struct socket *sock,
                        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);
@@ -1203,7 +1214,7 @@ static int __must_check ax25_connect(struct socket *sock,
                if (ax25->ax25_dev == NULL) {
                        kfree(digi);
                        err = -EHOSTUNREACH;
-                       goto out;
+                       goto out_release;
                }
        }
 
@@ -1213,7 +1224,7 @@ static int __must_check ax25_connect(struct socket *sock,
                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;
@@ -1223,7 +1234,7 @@ static int __must_check ax25_connect(struct socket *sock,
        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.. */
@@ -1255,55 +1266,53 @@ static int __must_check ax25_connect(struct socket *sock,
        /* 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;
 
@@ -1328,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:
@@ -1425,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;
 
@@ -1463,21 +1473,20 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
                        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;
                                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;
@@ -1525,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;
@@ -1551,10 +1558,8 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock,
        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");
 
@@ -1573,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);
 
@@ -1581,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);
@@ -1634,6 +1639,13 @@ static int ax25_recvmsg(struct kiocb *iocb, struct socket *sock,
        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;
                msg->msg_flags |= MSG_TRUNC;
@@ -1853,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;
@@ -1876,6 +1889,7 @@ static void *ax25_info_next(struct seq_file *seq, void *v, loff_t *pos)
 }
 
 static void ax25_info_stop(struct seq_file *seq, void *v)
+       __releases(ax25_list_lock)
 {
        spin_unlock_bh(&ax25_list_lock);
 }
@@ -1919,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,
@@ -1983,9 +1995,8 @@ static const struct proto_ops ax25_proto_ops = {
 /*
  *     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,
 };
 
@@ -2005,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;
 }
@@ -2021,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();