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 9abc503b19b7..fb8b0546485b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2283,8 +2283,8 @@ EXPORT_SYMBOL(skb_checksum_help);
2283 2283
2284__be16 skb_network_protocol(struct sk_buff *skb, int *depth) 2284__be16 skb_network_protocol(struct sk_buff *skb, int *depth)
2285{ 2285{
2286 unsigned int vlan_depth = skb->mac_len;
2286 __be16 type = skb->protocol; 2287 __be16 type = skb->protocol;
2287 int vlan_depth = skb->mac_len;
2288 2288
2289 /* Tunnel gso handlers can set protocol to ethernet. */ 2289 /* Tunnel gso handlers can set protocol to ethernet. */
2290 if (type == htons(ETH_P_TEB)) { 2290 if (type == htons(ETH_P_TEB)) {
@@ -2297,15 +2297,30 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth)
2297 type = eth->h_proto; 2297 type = eth->h_proto;
2298 } 2298 }
2299 2299
2300 while (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { 2300 /* if skb->protocol is 802.1Q/AD then the header should already be
2301 struct vlan_hdr *vh; 2301 * present at mac_len - VLAN_HLEN (if mac_len > 0), or at
2302 2302 * ETH_HLEN otherwise
2303 if (unlikely(!pskb_may_pull(skb, vlan_depth + VLAN_HLEN))) 2303 */
2304 return 0; 2304 if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) {
2305 2305 if (vlan_depth) {
2306 vh = (struct vlan_hdr *)(skb->data + vlan_depth); 2306 if (unlikely(WARN_ON(vlan_depth < VLAN_HLEN)))
2307 type = vh->h_vlan_encapsulated_proto; 2307 return 0;
2308 vlan_depth += VLAN_HLEN; 2308 vlan_depth -= VLAN_HLEN;
2309 } else {
2310 vlan_depth = ETH_HLEN;
2311 }
2312 do {
2313 struct vlan_hdr *vh;
2314
2315 if (unlikely(!pskb_may_pull(skb,
2316 vlan_depth + VLAN_HLEN)))
2317 return 0;
2318
2319 vh = (struct vlan_hdr *)(skb->data + vlan_depth);
2320 type = vh->h_vlan_encapsulated_proto;
2321 vlan_depth += VLAN_HLEN;
2322 } while (type == htons(ETH_P_8021Q) ||
2323 type == htons(ETH_P_8021AD));
2309 } 2324 }
2310 2325
2311 *depth = vlan_depth; 2326 *depth = vlan_depth;