Merge tag 'v2.6.35-rc6' into drm-radeon-next
[sfrench/cifs-2.6.git] / net / sched / act_nat.c
index d885ba311564d9a766fce6eac37edbaf0ed82b71..724553e8ed7bc9d8ecd668c71ab9373936a3d2d3 100644 (file)
@@ -159,6 +159,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
                        iph->daddr = new_addr;
 
                csum_replace4(&iph->check, addr, new_addr);
+       } else if ((iph->frag_off & htons(IP_OFFSET)) ||
+                  iph->protocol != IPPROTO_ICMP) {
+               goto out;
        }
 
        ihl = iph->ihl * 4;
@@ -202,7 +205,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
        {
                struct icmphdr *icmph;
 
-               if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph)))
+               if (!pskb_may_pull(skb, ihl + sizeof(*icmph)))
                        goto drop;
 
                icmph = (void *)(skb_network_header(skb) + ihl);
@@ -212,6 +215,9 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
                    (icmph->type != ICMP_PARAMETERPROB))
                        break;
 
+               if (!pskb_may_pull(skb, ihl + sizeof(*icmph) + sizeof(*iph)))
+                       goto drop;
+
                iph = (void *)(icmph + 1);
                if (egress)
                        addr = iph->daddr;
@@ -247,6 +253,7 @@ static int tcf_nat(struct sk_buff *skb, struct tc_action *a,
                break;
        }
 
+out:
        return action;
 
 drop: