]> git.neil.brown.name Git - history.git/commitdiff
[NETFILTER]: ipt_REJECT bugfix for TCP RST packets + asymm. routing.
authorHarald Welte <laforge@netfilter.org>
Sun, 30 Mar 2003 23:01:47 +0000 (15:01 -0800)
committerDavid S. Miller <davem@nuts.ninka.net>
Sun, 30 Mar 2003 23:01:47 +0000 (15:01 -0800)
net/ipv4/netfilter/ipt_REJECT.c

index a2a9ec092a60ab51b379391950d95bfe5b951e2e..6025e66cb4fce644a6c01bdd7edb20e8a709a969 100644 (file)
@@ -44,6 +44,7 @@ static void send_reset(struct sk_buff *oldskb, int local)
        u_int16_t tmp_port;
        u_int32_t tmp_addr;
        int needs_ack;
+       int hh_len;
 
        /* IP header checks: fragment, too short. */
        if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)
@@ -63,13 +64,36 @@ static void send_reset(struct sk_buff *oldskb, int local)
                         csum_partial((char *)otcph, otcplen, 0)) != 0)
                return;
 
+
+       {
+               struct flowi fl = { .nl_u = { .ip4_u =
+                                             { .daddr = oldskb->nh.iph->saddr,
+                                               .saddr = (local ?
+                                                         oldskb->nh.iph->daddr :
+                                                         0),
+                                               .tos = (RT_TOS(oldskb->nh.iph->tos) |
+                                                       RTO_CONN) } } };
+
+               /* Routing: if not headed for us, route won't like source */
+               if (ip_route_output_key(&rt, &fl))
+                       return;
+       
+               hh_len = (rt->u.dst.dev->hard_header_len + 15)&~15;
+       }
+
+
        /* Copy skb (even if skb is about to be dropped, we can't just
            clone it because there may be other things, such as tcpdump,
-           interested in it) */
-       nskb = skb_copy(oldskb, GFP_ATOMIC);
+           interested in it). We also need to expand headroom in case
+          hh_len of incoming interface < hh_len of outgoing interface */
+       nskb = skb_copy_expand(oldskb, hh_len, skb_tailroom(oldskb),
+                              GFP_ATOMIC);
        if (!nskb)
                return;
 
+       dst_release(nskb->dst);
+       nskb->dst = &rt->u.dst;
+
        /* This packet will not be the same as the other: clear nf fields */
        nf_conntrack_put(nskb->nfct);
        nskb->nfct = NULL;
@@ -132,23 +156,6 @@ static void send_reset(struct sk_buff *oldskb, int local)
        nskb->nh.iph->check = ip_fast_csum((unsigned char *)nskb->nh.iph, 
                                           nskb->nh.iph->ihl);
 
-       {
-               struct flowi fl = { .nl_u = { .ip4_u =
-                                             { .daddr = nskb->nh.iph->daddr,
-                                               .saddr = (local ?
-                                                         nskb->nh.iph->saddr :
-                                                         0),
-                                               .tos = (RT_TOS(nskb->nh.iph->tos) |
-                                                       RTO_CONN) } } };
-
-               /* Routing: if not headed for us, route won't like source */
-               if (ip_route_output_key(&rt, &fl))
-                       goto free_nskb;
-       }
-
-       dst_release(nskb->dst);
-       nskb->dst = &rt->u.dst;
-
        /* "Never happens" */
        if (nskb->len > dst_pmtu(nskb->dst))
                goto free_nskb;