]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/packet/af_packet.c
Merge tag 'fbdev-4.10' of git://git.kernel.org/pub/scm/linux/kernel/git/tomba/linux
[karo-tx-linux.git] / net / packet / af_packet.c
index d2238b204691b8e4f2e3acb9bc167b553ba32d50..89f2e8c1f4dc959ce2d9a822183495ec43d7619a 100644 (file)
@@ -1967,17 +1967,6 @@ static unsigned int run_filter(struct sk_buff *skb,
        return res;
 }
 
-static int __packet_rcv_vnet(const struct sk_buff *skb,
-                            struct virtio_net_hdr *vnet_hdr)
-{
-       *vnet_hdr = (const struct virtio_net_hdr) { 0 };
-
-       if (virtio_net_hdr_from_skb(skb, vnet_hdr, vio_le()))
-               BUG();
-
-       return 0;
-}
-
 static int packet_rcv_vnet(struct msghdr *msg, const struct sk_buff *skb,
                           size_t *len)
 {
@@ -1987,7 +1976,7 @@ static int packet_rcv_vnet(struct msghdr *msg, const struct sk_buff *skb,
                return -EINVAL;
        *len -= sizeof(vnet_hdr);
 
-       if (__packet_rcv_vnet(skb, &vnet_hdr))
+       if (virtio_net_hdr_from_skb(skb, &vnet_hdr, vio_le()))
                return -EINVAL;
 
        return memcpy_to_msg(msg, (void *)&vnet_hdr, sizeof(vnet_hdr));
@@ -2246,8 +2235,9 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev,
        spin_unlock(&sk->sk_receive_queue.lock);
 
        if (po->has_vnet_hdr) {
-               if (__packet_rcv_vnet(skb, h.raw + macoff -
-                                          sizeof(struct virtio_net_hdr))) {
+               if (virtio_net_hdr_from_skb(skb, h.raw + macoff -
+                                           sizeof(struct virtio_net_hdr),
+                                           vio_le())) {
                        spin_lock(&sk->sk_receive_queue.lock);
                        goto drop_n_account;
                }
@@ -2390,8 +2380,6 @@ static void tpacket_set_protocol(const struct net_device *dev,
 
 static int __packet_snd_vnet_parse(struct virtio_net_hdr *vnet_hdr, size_t len)
 {
-       unsigned short gso_type = 0;
-
        if ((vnet_hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) &&
            (__virtio16_to_cpu(vio_le(), vnet_hdr->csum_start) +
             __virtio16_to_cpu(vio_le(), vnet_hdr->csum_offset) + 2 >
@@ -2403,29 +2391,6 @@ static int __packet_snd_vnet_parse(struct virtio_net_hdr *vnet_hdr, size_t len)
        if (__virtio16_to_cpu(vio_le(), vnet_hdr->hdr_len) > len)
                return -EINVAL;
 
-       if (vnet_hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
-               switch (vnet_hdr->gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
-               case VIRTIO_NET_HDR_GSO_TCPV4:
-                       gso_type = SKB_GSO_TCPV4;
-                       break;
-               case VIRTIO_NET_HDR_GSO_TCPV6:
-                       gso_type = SKB_GSO_TCPV6;
-                       break;
-               case VIRTIO_NET_HDR_GSO_UDP:
-                       gso_type = SKB_GSO_UDP;
-                       break;
-               default:
-                       return -EINVAL;
-               }
-
-               if (vnet_hdr->gso_type & VIRTIO_NET_HDR_GSO_ECN)
-                       gso_type |= SKB_GSO_TCP_ECN;
-
-               if (vnet_hdr->gso_size == 0)
-                       return -EINVAL;
-       }
-
-       vnet_hdr->gso_type = gso_type;  /* changes type, temporary storage */
        return 0;
 }
 
@@ -2445,27 +2410,6 @@ static int packet_snd_vnet_parse(struct msghdr *msg, size_t *len,
        return __packet_snd_vnet_parse(vnet_hdr, *len);
 }
 
-static int packet_snd_vnet_gso(struct sk_buff *skb,
-                              struct virtio_net_hdr *vnet_hdr)
-{
-       if (vnet_hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) {
-               u16 s = __virtio16_to_cpu(vio_le(), vnet_hdr->csum_start);
-               u16 o = __virtio16_to_cpu(vio_le(), vnet_hdr->csum_offset);
-
-               if (!skb_partial_csum_set(skb, s, o))
-                       return -EINVAL;
-       }
-
-       skb_shinfo(skb)->gso_size =
-               __virtio16_to_cpu(vio_le(), vnet_hdr->gso_size);
-       skb_shinfo(skb)->gso_type = vnet_hdr->gso_type;
-
-       /* Header must be checked, and gso_segs computed. */
-       skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
-       skb_shinfo(skb)->gso_segs = 0;
-       return 0;
-}
-
 static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb,
                void *frame, struct net_device *dev, void *data, int tp_len,
                __be16 proto, unsigned char *addr, int hlen, int copylen,
@@ -2725,7 +2669,8 @@ tpacket_error:
                        }
                }
 
-               if (po->has_vnet_hdr && packet_snd_vnet_gso(skb, vnet_hdr)) {
+               if (po->has_vnet_hdr && virtio_net_hdr_to_skb(skb, vnet_hdr,
+                                                             vio_le())) {
                        tp_len = -EINVAL;
                        goto tpacket_error;
                }
@@ -2916,7 +2861,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
        packet_pick_tx_queue(dev, skb);
 
        if (po->has_vnet_hdr) {
-               err = packet_snd_vnet_gso(skb, &vnet_hdr);
+               err = virtio_net_hdr_to_skb(skb, &vnet_hdr, vio_le());
                if (err)
                        goto out_free;
                len += sizeof(vnet_hdr);
@@ -3648,19 +3593,25 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
 
                if (optlen != sizeof(val))
                        return -EINVAL;
-               if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)
-                       return -EBUSY;
                if (copy_from_user(&val, optval, sizeof(val)))
                        return -EFAULT;
                switch (val) {
                case TPACKET_V1:
                case TPACKET_V2:
                case TPACKET_V3:
-                       po->tp_version = val;
-                       return 0;
+                       break;
                default:
                        return -EINVAL;
                }
+               lock_sock(sk);
+               if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) {
+                       ret = -EBUSY;
+               } else {
+                       po->tp_version = val;
+                       ret = 0;
+               }
+               release_sock(sk);
+               return ret;
        }
        case PACKET_RESERVE:
        {
@@ -4164,6 +4115,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
        /* Added to avoid minimal code churn */
        struct tpacket_req *req = &req_u->req;
 
+       lock_sock(sk);
        /* Opening a Tx-ring is NOT supported in TPACKET_V3 */
        if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) {
                net_warn_ratelimited("Tx-ring is not supported.\n");
@@ -4245,7 +4197,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                        goto out;
        }
 
-       lock_sock(sk);
 
        /* Detach socket from network */
        spin_lock(&po->bind_lock);
@@ -4294,11 +4245,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                if (!tx_ring)
                        prb_shutdown_retire_blk_timer(po, rb_queue);
        }
-       release_sock(sk);
 
        if (pg_vec)
                free_pg_vec(pg_vec, order, req->tp_block_nr);
 out:
+       release_sock(sk);
        return err;
 }