diff options
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 32 |
1 files changed, 28 insertions, 4 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 2dbb32b988c4..ae2d484416dd 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -1459,6 +1459,7 @@ static int packet_sendmsg_spkt(struct kiocb *iocb, struct socket *sock, | |||
1459 | struct net_device *dev; | 1459 | struct net_device *dev; |
1460 | __be16 proto = 0; | 1460 | __be16 proto = 0; |
1461 | int err; | 1461 | int err; |
1462 | int extra_len = 0; | ||
1462 | 1463 | ||
1463 | /* | 1464 | /* |
1464 | * Get and verify the address. | 1465 | * Get and verify the address. |
@@ -1493,8 +1494,16 @@ retry: | |||
1493 | * raw protocol and you must do your own fragmentation at this level. | 1494 | * raw protocol and you must do your own fragmentation at this level. |
1494 | */ | 1495 | */ |
1495 | 1496 | ||
1497 | if (unlikely(sock_flag(sk, SOCK_NOFCS))) { | ||
1498 | if (!netif_supports_nofcs(dev)) { | ||
1499 | err = -EPROTONOSUPPORT; | ||
1500 | goto out_unlock; | ||
1501 | } | ||
1502 | extra_len = 4; /* We're doing our own CRC */ | ||
1503 | } | ||
1504 | |||
1496 | err = -EMSGSIZE; | 1505 | err = -EMSGSIZE; |
1497 | if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN) | 1506 | if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN + extra_len) |
1498 | goto out_unlock; | 1507 | goto out_unlock; |
1499 | 1508 | ||
1500 | if (!skb) { | 1509 | if (!skb) { |
@@ -1526,7 +1535,7 @@ retry: | |||
1526 | goto retry; | 1535 | goto retry; |
1527 | } | 1536 | } |
1528 | 1537 | ||
1529 | if (len > (dev->mtu + dev->hard_header_len)) { | 1538 | if (len > (dev->mtu + dev->hard_header_len + extra_len)) { |
1530 | /* Earlier code assumed this would be a VLAN pkt, | 1539 | /* Earlier code assumed this would be a VLAN pkt, |
1531 | * double-check this now that we have the actual | 1540 | * double-check this now that we have the actual |
1532 | * packet in hand. | 1541 | * packet in hand. |
@@ -1548,6 +1557,9 @@ retry: | |||
1548 | if (err < 0) | 1557 | if (err < 0) |
1549 | goto out_unlock; | 1558 | goto out_unlock; |
1550 | 1559 | ||
1560 | if (unlikely(extra_len == 4)) | ||
1561 | skb->no_fcs = 1; | ||
1562 | |||
1551 | dev_queue_xmit(skb); | 1563 | dev_queue_xmit(skb); |
1552 | rcu_read_unlock(); | 1564 | rcu_read_unlock(); |
1553 | return len; | 1565 | return len; |
@@ -2209,6 +2221,7 @@ static int packet_snd(struct socket *sock, | |||
2209 | struct packet_sock *po = pkt_sk(sk); | 2221 | struct packet_sock *po = pkt_sk(sk); |
2210 | unsigned short gso_type = 0; | 2222 | unsigned short gso_type = 0; |
2211 | int hlen, tlen; | 2223 | int hlen, tlen; |
2224 | int extra_len = 0; | ||
2212 | 2225 | ||
2213 | /* | 2226 | /* |
2214 | * Get and verify the address. | 2227 | * Get and verify the address. |
@@ -2288,8 +2301,16 @@ static int packet_snd(struct socket *sock, | |||
2288 | } | 2301 | } |
2289 | } | 2302 | } |
2290 | 2303 | ||
2304 | if (unlikely(sock_flag(sk, SOCK_NOFCS))) { | ||
2305 | if (!netif_supports_nofcs(dev)) { | ||
2306 | err = -EPROTONOSUPPORT; | ||
2307 | goto out_unlock; | ||
2308 | } | ||
2309 | extra_len = 4; /* We're doing our own CRC */ | ||
2310 | } | ||
2311 | |||
2291 | err = -EMSGSIZE; | 2312 | err = -EMSGSIZE; |
2292 | if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN)) | 2313 | if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN + extra_len)) |
2293 | goto out_unlock; | 2314 | goto out_unlock; |
2294 | 2315 | ||
2295 | err = -ENOBUFS; | 2316 | err = -ENOBUFS; |
@@ -2315,7 +2336,7 @@ static int packet_snd(struct socket *sock, | |||
2315 | if (err < 0) | 2336 | if (err < 0) |
2316 | goto out_free; | 2337 | goto out_free; |
2317 | 2338 | ||
2318 | if (!gso_type && (len > dev->mtu + reserve)) { | 2339 | if (!gso_type && (len > dev->mtu + reserve + extra_len)) { |
2319 | /* Earlier code assumed this would be a VLAN pkt, | 2340 | /* Earlier code assumed this would be a VLAN pkt, |
2320 | * double-check this now that we have the actual | 2341 | * double-check this now that we have the actual |
2321 | * packet in hand. | 2342 | * packet in hand. |
@@ -2353,6 +2374,9 @@ static int packet_snd(struct socket *sock, | |||
2353 | len += vnet_hdr_len; | 2374 | len += vnet_hdr_len; |
2354 | } | 2375 | } |
2355 | 2376 | ||
2377 | if (unlikely(extra_len == 4)) | ||
2378 | skb->no_fcs = 1; | ||
2379 | |||
2356 | /* | 2380 | /* |
2357 | * Now send it | 2381 | * Now send it |
2358 | */ | 2382 | */ |