aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/if_vlan.h15
1 files changed, 13 insertions, 2 deletions
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index c4a1cff9c768..7d30892da064 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -323,13 +323,24 @@ static inline int __vlan_insert_inner_tag(struct sk_buff *skb,
323 skb_push(skb, VLAN_HLEN); 323 skb_push(skb, VLAN_HLEN);
324 324
325 /* Move the mac header sans proto to the beginning of the new header. */ 325 /* Move the mac header sans proto to the beginning of the new header. */
326 memmove(skb->data, skb->data + VLAN_HLEN, mac_len - ETH_TLEN); 326 if (likely(mac_len > ETH_TLEN))
327 memmove(skb->data, skb->data + VLAN_HLEN, mac_len - ETH_TLEN);
327 skb->mac_header -= VLAN_HLEN; 328 skb->mac_header -= VLAN_HLEN;
328 329
329 veth = (struct vlan_ethhdr *)(skb->data + mac_len - ETH_HLEN); 330 veth = (struct vlan_ethhdr *)(skb->data + mac_len - ETH_HLEN);
330 331
331 /* first, the ethernet type */ 332 /* first, the ethernet type */
332 veth->h_vlan_proto = vlan_proto; 333 if (likely(mac_len >= ETH_TLEN)) {
334 /* h_vlan_encapsulated_proto should already be populated, and
335 * skb->data has space for h_vlan_proto
336 */
337 veth->h_vlan_proto = vlan_proto;
338 } else {
339 /* h_vlan_encapsulated_proto should not be populated, and
340 * skb->data has no space for h_vlan_proto
341 */
342 veth->h_vlan_encapsulated_proto = skb->protocol;
343 }
333 344
334 /* now, the TCI */ 345 /* now, the TCI */
335 veth->h_vlan_TCI = htons(vlan_tci); 346 veth->h_vlan_TCI = htons(vlan_tci);