Upgrade to 4.4.50-rt62
[kvmfornfv.git] / kernel / net / l2tp / l2tp_ip.c
index ec22078..445b7cd 100644 (file)
@@ -11,6 +11,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <asm/ioctls.h>
 #include <linux/icmp.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
@@ -123,12 +124,11 @@ static int l2tp_ip_recv(struct sk_buff *skb)
        struct l2tp_tunnel *tunnel = NULL;
        int length;
 
-       /* Point to L2TP header */
-       optr = ptr = skb->data;
-
        if (!pskb_may_pull(skb, 4))
                goto discard;
 
+       /* Point to L2TP header */
+       optr = ptr = skb->data;
        session_id = ntohl(*((__be32 *) ptr));
        ptr += 4;
 
@@ -156,6 +156,9 @@ static int l2tp_ip_recv(struct sk_buff *skb)
                if (!pskb_may_pull(skb, length))
                        goto discard;
 
+               /* Point to L2TP header */
+               optr = ptr = skb->data;
+               ptr += 4;
                pr_debug("%s: ip recv\n", tunnel->name);
                print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
        }
@@ -249,8 +252,6 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        int ret;
        int chk_addr_ret;
 
-       if (!sock_flag(sk, SOCK_ZAPPED))
-               return -EINVAL;
        if (addr_len < sizeof(struct sockaddr_l2tpip))
                return -EINVAL;
        if (addr->l2tp_family != AF_INET)
@@ -265,6 +266,9 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        read_unlock_bh(&l2tp_ip_lock);
 
        lock_sock(sk);
+       if (!sock_flag(sk, SOCK_ZAPPED))
+               goto out;
+
        if (sk->sk_state != TCP_CLOSE || addr_len < sizeof(struct sockaddr_l2tpip))
                goto out;
 
@@ -552,6 +556,30 @@ out:
        return err ? err : copied;
 }
 
+int l2tp_ioctl(struct sock *sk, int cmd, unsigned long arg)
+{
+       struct sk_buff *skb;
+       int amount;
+
+       switch (cmd) {
+       case SIOCOUTQ:
+               amount = sk_wmem_alloc_get(sk);
+               break;
+       case SIOCINQ:
+               spin_lock_bh(&sk->sk_receive_queue.lock);
+               skb = skb_peek(&sk->sk_receive_queue);
+               amount = skb ? skb->len : 0;
+               spin_unlock_bh(&sk->sk_receive_queue.lock);
+               break;
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       return put_user(amount, (int __user *)arg);
+}
+EXPORT_SYMBOL(l2tp_ioctl);
+
 static struct proto l2tp_ip_prot = {
        .name              = "L2TP/IP",
        .owner             = THIS_MODULE,
@@ -560,7 +588,7 @@ static struct proto l2tp_ip_prot = {
        .bind              = l2tp_ip_bind,
        .connect           = l2tp_ip_connect,
        .disconnect        = l2tp_ip_disconnect,
-       .ioctl             = udp_ioctl,
+       .ioctl             = l2tp_ioctl,
        .destroy           = l2tp_ip_destroy_sock,
        .setsockopt        = ip_setsockopt,
        .getsockopt        = ip_getsockopt,