aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c35
1 files changed, 25 insertions, 10 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 1ba2cfe3f8e8..5367bfba0947 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2289,8 +2289,8 @@ EXPORT_SYMBOL(skb_checksum_help);
2289 2289
2290__be16 skb_network_protocol(struct sk_buff *skb, int *depth) 2290__be16 skb_network_protocol(struct sk_buff *skb, int *depth)
2291{ 2291{
2292 unsigned int vlan_depth = skb->mac_len;
2292 __be16 type = skb->protocol; 2293 __be16 type = skb->protocol;
2293 int vlan_depth = skb->mac_len;
2294 2294
2295 /* Tunnel gso handlers can set protocol to ethernet. */ 2295 /* Tunnel gso handlers can set protocol to ethernet. */
2296 if (type == htons(ETH_P_TEB)) { 2296 if (type == htons(ETH_P_TEB)) {
@@ -2303,15 +2303,30 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth)
2303 type = eth->h_proto; 2303 type = eth->h_proto;
2304 } 2304 }
2305 2305
2306 while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { 2306 /* if skb->protocol is 802.1Q/AD then the header should already be
2307 struct vlan_hdr *vh; 2307 * present at mac_len - VLAN_HLEN (if mac_len > 0), or at
2308 2308 * ETH_HLEN otherwise
2309 if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN))) 2309 */
2310 return 0; 2310 if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
2311 2311 if (vlan_depth) {
2312 vh = (struct vlan_hdr *)(skb->data + vlan_depth); 2312 if (unlikely(WARN_ON(vlan_depth < VLAN_HLEN)))
2313 type = vh->h_vlan_encapsulated_proto; 2313 return 0;
2314 vlan_depth += VLAN_HLEN; 2314 vlan_depth -= VLAN_HLEN;
2315 } else {
2316 vlan_depth = ETH_HLEN;
2317 }
2318 do {
2319 struct vlan_hdr *vh;
2320
2321 if (unlikely(!pskb_may_pull(skb,
2322 vlan_depth + VLAN_HLEN)))
2323 return 0;
2324
2325 vh = (struct vlan_hdr *)(skb->data + vlan_depth);
2326 type = vh->h_vlan_encapsulated_proto;
2327 vlan_depth += VLAN_HLEN;
2328 } while (type == htons(ETH_P_8021Q) ||
2329 type == htons(ETH_P_8021AD));
2315 } 2330 }
2316 2331
2317 *depth = vlan_depth; 2332 *depth = vlan_depth;