diff options
Diffstat (limited to 'net')
| -rw-r--r-- | net/ethernet/eth.c | 13 | ||||
| -rw-r--r-- | net/packet/af_packet.c | 26 |
2 files changed, 25 insertions, 14 deletions
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 4c520110b04f..f7a3d7a171c7 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
| @@ -265,6 +265,18 @@ void eth_header_cache_update(struct hh_cache *hh, | |||
| 265 | EXPORT_SYMBOL(eth_header_cache_update); | 265 | EXPORT_SYMBOL(eth_header_cache_update); |
| 266 | 266 | ||
| 267 | /** | 267 | /** |
| 268 | * eth_header_parser_protocol - extract protocol from L2 header | ||
| 269 | * @skb: packet to extract protocol from | ||
| 270 | */ | ||
| 271 | __be16 eth_header_parse_protocol(const struct sk_buff *skb) | ||
| 272 | { | ||
| 273 | const struct ethhdr *eth = eth_hdr(skb); | ||
| 274 | |||
| 275 | return eth->h_proto; | ||
| 276 | } | ||
| 277 | EXPORT_SYMBOL(eth_header_parse_protocol); | ||
| 278 | |||
| 279 | /** | ||
| 268 | * eth_prepare_mac_addr_change - prepare for mac change | 280 | * eth_prepare_mac_addr_change - prepare for mac change |
| 269 | * @dev: network device | 281 | * @dev: network device |
| 270 | * @p: socket address | 282 | * @p: socket address |
| @@ -346,6 +358,7 @@ const struct header_ops eth_header_ops ____cacheline_aligned = { | |||
| 346 | .parse = eth_header_parse, | 358 | .parse = eth_header_parse, |
| 347 | .cache = eth_header_cache, | 359 | .cache = eth_header_cache, |
| 348 | .cache_update = eth_header_cache_update, | 360 | .cache_update = eth_header_cache_update, |
| 361 | .parse_protocol = eth_header_parse_protocol, | ||
| 349 | }; | 362 | }; |
| 350 | 363 | ||
| 351 | /** | 364 | /** |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 1cd1d83a4be0..8376bc1c1508 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -1850,6 +1850,15 @@ oom: | |||
| 1850 | return 0; | 1850 | return 0; |
| 1851 | } | 1851 | } |
| 1852 | 1852 | ||
| 1853 | static void packet_parse_headers(struct sk_buff *skb, struct socket *sock) | ||
| 1854 | { | ||
| 1855 | if (!skb->protocol && sock->type == SOCK_RAW) { | ||
| 1856 | skb_reset_mac_header(skb); | ||
| 1857 | skb->protocol = dev_parse_header_protocol(skb); | ||
| 1858 | } | ||
| 1859 | |||
| 1860 | skb_probe_transport_header(skb); | ||
| 1861 | } | ||
| 1853 | 1862 | ||
| 1854 | /* | 1863 | /* |
| 1855 | * Output a raw packet to a device layer. This bypasses all the other | 1864 | * Output a raw packet to a device layer. This bypasses all the other |
| @@ -1970,7 +1979,7 @@ retry: | |||
| 1970 | if (unlikely(extra_len == 4)) | 1979 | if (unlikely(extra_len == 4)) |
| 1971 | skb->no_fcs = 1; | 1980 | skb->no_fcs = 1; |
| 1972 | 1981 | ||
| 1973 | skb_probe_transport_header(skb, 0); | 1982 | packet_parse_headers(skb, sock); |
| 1974 | 1983 | ||
| 1975 | dev_queue_xmit(skb); | 1984 | dev_queue_xmit(skb); |
| 1976 | rcu_read_unlock(); | 1985 | rcu_read_unlock(); |
| @@ -2404,15 +2413,6 @@ static void tpacket_destruct_skb(struct sk_buff *skb) | |||
| 2404 | sock_wfree(skb); | 2413 | sock_wfree(skb); |
| 2405 | } | 2414 | } |
| 2406 | 2415 | ||
| 2407 | static void tpacket_set_protocol(const struct net_device *dev, | ||
| 2408 | struct sk_buff *skb) | ||
| 2409 | { | ||
| 2410 | if (dev->type == ARPHRD_ETHER) { | ||
| 2411 | skb_reset_mac_header(skb); | ||
| 2412 | skb->protocol = eth_hdr(skb)->h_proto; | ||
| 2413 | } | ||
| 2414 | } | ||
| 2415 | |||
| 2416 | static int __packet_snd_vnet_parse(struct virtio_net_hdr *vnet_hdr, size_t len) | 2416 | static int __packet_snd_vnet_parse(struct virtio_net_hdr *vnet_hdr, size_t len) |
| 2417 | { | 2417 | { |
| 2418 | if ((vnet_hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && | 2418 | if ((vnet_hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) && |
| @@ -2483,8 +2483,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
| 2483 | return err; | 2483 | return err; |
| 2484 | if (!dev_validate_header(dev, skb->data, hdrlen)) | 2484 | if (!dev_validate_header(dev, skb->data, hdrlen)) |
| 2485 | return -EINVAL; | 2485 | return -EINVAL; |
| 2486 | if (!skb->protocol) | ||
| 2487 | tpacket_set_protocol(dev, skb); | ||
| 2488 | 2486 | ||
| 2489 | data += hdrlen; | 2487 | data += hdrlen; |
| 2490 | to_write -= hdrlen; | 2488 | to_write -= hdrlen; |
| @@ -2519,7 +2517,7 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
| 2519 | len = ((to_write > len_max) ? len_max : to_write); | 2517 | len = ((to_write > len_max) ? len_max : to_write); |
| 2520 | } | 2518 | } |
| 2521 | 2519 | ||
| 2522 | skb_probe_transport_header(skb, 0); | 2520 | packet_parse_headers(skb, sock); |
| 2523 | 2521 | ||
| 2524 | return tp_len; | 2522 | return tp_len; |
| 2525 | } | 2523 | } |
| @@ -2925,7 +2923,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) | |||
| 2925 | virtio_net_hdr_set_proto(skb, &vnet_hdr); | 2923 | virtio_net_hdr_set_proto(skb, &vnet_hdr); |
| 2926 | } | 2924 | } |
| 2927 | 2925 | ||
| 2928 | skb_probe_transport_header(skb, reserve); | 2926 | packet_parse_headers(skb, sock); |
| 2929 | 2927 | ||
| 2930 | if (unlikely(extra_len == 4)) | 2928 | if (unlikely(extra_len == 4)) |
| 2931 | skb->no_fcs = 1; | 2929 | skb->no_fcs = 1; |
