diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-10-06 06:28:31 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-10-18 23:22:07 -0400 |
commit | bc416d9768aa9a2e46eb11354a9c58399dafeb01 (patch) | |
tree | a3ecf948353d11d199dfb64b0c4302c5b4aaccb6 /net/ipv4/ip_fragment.c | |
parent | f7ba35da583cf6aefba887a8dcf86acec4f3a350 (diff) |
macvlan: handle fragmented multicast frames
Fragmented multicast frames are delivered to a single macvlan port,
because ip defrag logic considers other samples are redundant.
Implement a defrag step before trying to send the multicast frame.
Reported-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ip_fragment.c')
-rw-r--r-- | net/ipv4/ip_fragment.c | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 0e0ab98abc6f..763589ad673d 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -682,6 +682,42 @@ int ip_defrag(struct sk_buff *skb, u32 user) | |||
682 | } | 682 | } |
683 | EXPORT_SYMBOL(ip_defrag); | 683 | EXPORT_SYMBOL(ip_defrag); |
684 | 684 | ||
685 | struct sk_buff *ip_check_defrag(struct sk_buff *skb, u32 user) | ||
686 | { | ||
687 | const struct iphdr *iph; | ||
688 | u32 len; | ||
689 | |||
690 | if (skb->protocol != htons(ETH_P_IP)) | ||
691 | return skb; | ||
692 | |||
693 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | ||
694 | return skb; | ||
695 | |||
696 | iph = ip_hdr(skb); | ||
697 | if (iph->ihl < 5 || iph->version != 4) | ||
698 | return skb; | ||
699 | if (!pskb_may_pull(skb, iph->ihl*4)) | ||
700 | return skb; | ||
701 | iph = ip_hdr(skb); | ||
702 | len = ntohs(iph->tot_len); | ||
703 | if (skb->len < len || len < (iph->ihl * 4)) | ||
704 | return skb; | ||
705 | |||
706 | if (ip_is_fragment(ip_hdr(skb))) { | ||
707 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
708 | if (skb) { | ||
709 | if (pskb_trim_rcsum(skb, len)) | ||
710 | return skb; | ||
711 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); | ||
712 | if (ip_defrag(skb, user)) | ||
713 | return NULL; | ||
714 | skb->rxhash = 0; | ||
715 | } | ||
716 | } | ||
717 | return skb; | ||
718 | } | ||
719 | EXPORT_SYMBOL(ip_check_defrag); | ||
720 | |||
685 | #ifdef CONFIG_SYSCTL | 721 | #ifdef CONFIG_SYSCTL |
686 | static int zero; | 722 | static int zero; |
687 | 723 | ||