|
@@ -1459,6 +1459,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock,
|
|
|
struct net_device *dev;
|
|
|
__be16 proto = 0;
|
|
|
int err;
|
|
|
+ int extra_len = 0;
|
|
|
|
|
|
/*
|
|
|
* Get and verify the address.
|
|
@@ -1493,8 +1494,16 @@ retry:
|
|
|
* raw protocol and you must do your own fragmentation at this level.
|
|
|
*/
|
|
|
|
|
|
+ if (unlikely(sock_flag(sk, SOCK_NOFCS))) {
|
|
|
+ if (!netif_supports_nofcs(dev)) {
|
|
|
+ err = -EPROTONOSUPPORT;
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
+ extra_len = 4; /* We're doing our own CRC */
|
|
|
+ }
|
|
|
+
|
|
|
err = -EMSGSIZE;
|
|
|
- if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN)
|
|
|
+ if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN + extra_len)
|
|
|
goto out_unlock;
|
|
|
|
|
|
if (!skb) {
|
|
@@ -1526,7 +1535,7 @@ retry:
|
|
|
goto retry;
|
|
|
}
|
|
|
|
|
|
- if (len > (dev->mtu + dev->hard_header_len)) {
|
|
|
+ if (len > (dev->mtu + dev->hard_header_len + extra_len)) {
|
|
|
/* Earlier code assumed this would be a VLAN pkt,
|
|
|
* double-check this now that we have the actual
|
|
|
* packet in hand.
|
|
@@ -1548,6 +1557,9 @@ retry:
|
|
|
if (err < 0)
|
|
|
goto out_unlock;
|
|
|
|
|
|
+ if (unlikely(extra_len == 4))
|
|
|
+ skb->no_fcs = 1;
|
|
|
+
|
|
|
dev_queue_xmit(skb);
|
|
|
rcu_read_unlock();
|
|
|
return len;
|
|
@@ -2209,6 +2221,7 @@ static int packet_snd(struct socket *sock,
|
|
|
struct packet_sock *po = pkt_sk(sk);
|
|
|
unsigned short gso_type = 0;
|
|
|
int hlen, tlen;
|
|
|
+ int extra_len = 0;
|
|
|
|
|
|
/*
|
|
|
* Get and verify the address.
|
|
@@ -2288,8 +2301,16 @@ static int packet_snd(struct socket *sock,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (unlikely(sock_flag(sk, SOCK_NOFCS))) {
|
|
|
+ if (!netif_supports_nofcs(dev)) {
|
|
|
+ err = -EPROTONOSUPPORT;
|
|
|
+ goto out_unlock;
|
|
|
+ }
|
|
|
+ extra_len = 4; /* We're doing our own CRC */
|
|
|
+ }
|
|
|
+
|
|
|
err = -EMSGSIZE;
|
|
|
- if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN))
|
|
|
+ if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN + extra_len))
|
|
|
goto out_unlock;
|
|
|
|
|
|
err = -ENOBUFS;
|
|
@@ -2315,7 +2336,7 @@ static int packet_snd(struct socket *sock,
|
|
|
if (err < 0)
|
|
|
goto out_free;
|
|
|
|
|
|
- if (!gso_type && (len > dev->mtu + reserve)) {
|
|
|
+ if (!gso_type && (len > dev->mtu + reserve + extra_len)) {
|
|
|
/* Earlier code assumed this would be a VLAN pkt,
|
|
|
* double-check this now that we have the actual
|
|
|
* packet in hand.
|
|
@@ -2353,6 +2374,9 @@ static int packet_snd(struct socket *sock,
|
|
|
len += vnet_hdr_len;
|
|
|
}
|
|
|
|
|
|
+ if (unlikely(extra_len == 4))
|
|
|
+ skb->no_fcs = 1;
|
|
|
+
|
|
|
/*
|
|
|
* Now send it
|
|
|
*/
|