[NET]: Make /proc/net per network namespace
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / netrom / af_netrom.c
index bf9837dd95c4505642b99f93e9b96403d055685e..15c8a92bd7193bc6d19d386fadeb6a23815f2c51 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/netdevice.h>
 #include <linux/if_arp.h>
 #include <linux/skbuff.h>
+#include <net/net_namespace.h>
 #include <net/sock.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
@@ -625,42 +626,42 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
        ax25_address *source = NULL;
        ax25_uid_assoc *user;
        struct net_device *dev;
+       int err = 0;
 
        lock_sock(sk);
        if (sk->sk_state == TCP_ESTABLISHED && sock->state == SS_CONNECTING) {
                sock->state = SS_CONNECTED;
-               release_sock(sk);
-               return 0;       /* Connect completed during a ERESTARTSYS event */
+               goto out_release;       /* Connect completed during a ERESTARTSYS event */
        }
 
        if (sk->sk_state == TCP_CLOSE && sock->state == SS_CONNECTING) {
                sock->state = SS_UNCONNECTED;
-               release_sock(sk);
-               return -ECONNREFUSED;
+               err = -ECONNREFUSED;
+               goto out_release;
        }
 
        if (sk->sk_state == TCP_ESTABLISHED) {
-               release_sock(sk);
-               return -EISCONN;        /* No reconnect on a seqpacket socket */
+               err = -EISCONN; /* No reconnect on a seqpacket socket */
+               goto out_release;
        }
 
        sk->sk_state   = TCP_CLOSE;
        sock->state = SS_UNCONNECTED;
 
        if (addr_len != sizeof(struct sockaddr_ax25) && addr_len != sizeof(struct full_sockaddr_ax25)) {
-               release_sock(sk);
-               return -EINVAL;
+               err = -EINVAL;
+               goto out_release;
        }
        if (addr->sax25_family != AF_NETROM) {
-               release_sock(sk);
-               return -EINVAL;
+               err = -EINVAL;
+               goto out_release;
        }
        if (sock_flag(sk, SOCK_ZAPPED)) {       /* Must bind first - autobinding in this may or may not work */
                sock_reset_flag(sk, SOCK_ZAPPED);
 
                if ((dev = nr_dev_first()) == NULL) {
-                       release_sock(sk);
-                       return -ENETUNREACH;
+                       err = -ENETUNREACH;
+                       goto out_release;
                }
                source = (ax25_address *)dev->dev_addr;
 
@@ -671,8 +672,8 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
                } else {
                        if (ax25_uid_policy && !capable(CAP_NET_ADMIN)) {
                                dev_put(dev);
-                               release_sock(sk);
-                               return -EPERM;
+                               err = -EPERM;
+                               goto out_release;
                        }
                        nr->user_addr   = *source;
                }
@@ -707,8 +708,8 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
 
        /* Now the loop */
        if (sk->sk_state != TCP_ESTABLISHED && (flags & O_NONBLOCK)) {
-               release_sock(sk);
-               return -EINPROGRESS;
+               err = -EINPROGRESS;
+               goto out_release;
        }
 
        /*
@@ -716,46 +717,46 @@ static int nr_connect(struct socket *sock, struct sockaddr *uaddr,
         * closed.
         */
        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 (;;) {
-                       set_current_state(TASK_INTERRUPTIBLE);
+                       prepare_to_wait(sk->sk_sleep, &wait,
+                                       TASK_INTERRUPTIBLE);
                        if (sk->sk_state != TCP_SYN_SENT)
                                break;
-                       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) {
                sock->state = SS_UNCONNECTED;
-               release_sock(sk);
-               return sock_error(sk);  /* Always set at this point */
+               err = sock_error(sk);   /* Always set at this point */
+               goto out_release;
        }
 
        sock->state = SS_CONNECTED;
+
+out_release:
        release_sock(sk);
 
-       return 0;
+       return err;
 }
 
 static int nr_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;
 
@@ -765,42 +766,40 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags)
        lock_sock(sk);
        if (sk->sk_type != SOCK_SEQPACKET) {
                err = -EOPNOTSUPP;
-               goto out;
+               goto out_release;
        }
 
        if (sk->sk_state != TCP_LISTEN) {
                err = -EINVAL;
-               goto out;
+               goto out_release;
        }
 
        /*
         *      The write 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;
 
-               current->state = TASK_INTERRUPTIBLE;
-               release_sock(sk);
                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_release;
 
        newsk = skb->sk;
        newsk->sk_socket = newsock;
@@ -811,8 +810,9 @@ static int nr_accept(struct socket *sock, struct socket *newsock, int flags)
        sk_acceptq_removed(sk);
        newsock->sk = newsk;
 
-out:
+out_release:
        release_sock(sk);
+
        return err;
 }
 
@@ -878,7 +878,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
        if (frametype == NR_PROTOEXT &&
            circuit_index == NR_PROTO_IP && circuit_id == NR_PROTO_IP) {
                skb_pull(skb, NR_NETWORK_LEN + NR_TRANSPORT_LEN);
-               skb->h.raw = skb->data;
+               skb_reset_transport_header(skb);
 
                return nr_rx_ip(skb, dev);
        }
@@ -904,7 +904,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev)
        }
 
        if (sk != NULL) {
-               skb->h.raw = skb->data;
+               skb_reset_transport_header(skb);
 
                if (frametype == NR_CONNACK && skb->len == 22)
                        nr_sk(sk)->bpqext = 1;
@@ -1074,6 +1074,7 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock,
                goto out;
 
        skb_reserve(skb, size - len);
+       skb_reset_transport_header(skb);
 
        /*
         *      Push down the NET/ROM header
@@ -1094,14 +1095,12 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock,
        /*
         *      Put the data on the end
         */
+       skb_put(skb, len);
 
-       skb->h.raw = skb_put(skb, len);
-
-       asmptr = skb->h.raw;
        SOCK_DEBUG(sk, "NET/ROM: Appending user data\n");
 
        /* User data follows immediately after the NET/ROM transport header */
-       if (memcpy_fromiovec(asmptr, msg->msg_iov, len)) {
+       if (memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len)) {
                kfree_skb(skb);
                err = -EFAULT;
                goto out;
@@ -1149,7 +1148,7 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
                return er;
        }
 
-       skb->h.raw = skb->data;
+       skb_reset_transport_header(skb);
        copied     = skb->len;
 
        if (copied > size) {
@@ -1161,7 +1160,8 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
 
        if (sax != NULL) {
                sax->sax25_family = AF_NETROM;
-               memcpy(sax->sax25_call.ax25_call, skb->data + 7, AX25_ADDR_LEN);
+               skb_copy_from_linear_data_offset(skb, 7, sax->sax25_call.ax25_call,
+                             AX25_ADDR_LEN);
        }
 
        msg->msg_namelen = sizeof(*sax);
@@ -1209,6 +1209,12 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
                release_sock(sk);
                return ret;
 
+       case SIOCGSTAMPNS:
+               lock_sock(sk);
+               ret = sock_get_timestampns(sk, argp);
+               release_sock(sk);
+               return ret;
+
        case SIOCGIFADDR:
        case SIOCSIFADDR:
        case SIOCGIFDSTADDR:
@@ -1323,7 +1329,7 @@ static int nr_info_show(struct seq_file *seq, void *v)
        return 0;
 }
 
-static struct seq_operations nr_info_seqops = {
+static const struct seq_operations nr_info_seqops = {
        .start = nr_info_start,
        .next = nr_info_next,
        .stop = nr_info_stop,
@@ -1442,9 +1448,9 @@ static int __init nr_proto_init(void)
 
        nr_loopback_init();
 
-       proc_net_fops_create("nr", S_IRUGO, &nr_info_fops);
-       proc_net_fops_create("nr_neigh", S_IRUGO, &nr_neigh_fops);
-       proc_net_fops_create("nr_nodes", S_IRUGO, &nr_nodes_fops);
+       proc_net_fops_create(&init_net, "nr", S_IRUGO, &nr_info_fops);
+       proc_net_fops_create(&init_net, "nr_neigh", S_IRUGO, &nr_neigh_fops);
+       proc_net_fops_create(&init_net, "nr_nodes", S_IRUGO, &nr_nodes_fops);
 out:
        return rc;
 fail:
@@ -1472,9 +1478,9 @@ static void __exit nr_exit(void)
 {
        int i;
 
-       proc_net_remove("nr");
-       proc_net_remove("nr_neigh");
-       proc_net_remove("nr_nodes");
+       proc_net_remove(&init_net, "nr");
+       proc_net_remove(&init_net, "nr_neigh");
+       proc_net_remove(&init_net, "nr_nodes");
        nr_loopback_clear();
 
        nr_rt_free();