diff options
| author | Rusty Russell <rusty@rustcorp.com.au> | 2003-09-11 04:34:40 -0700 |
|---|---|---|
| committer | Hideaki Yoshifuji <yoshfuji@linux-ipv6.org> | 2003-09-11 04:34:40 -0700 |
| commit | ee2dea7df2b05dfbd73780ab624dd2b61ebebdb8 (patch) | |
| tree | 859250eb64726cbccc3415e495a18789479d67a6 | |
| parent | 8b699049130fdd66bac86d73199ec4610e72cfff (diff) | |
[NETFILTER]: REJECT nonlinear fixes after sync with 2.4
Harald synced up ipt_REJECT.c from 2.4 route fixes, but it had
changed a fair bit because of the nonlinear fixes. This repairs it.
1) Copying of tcp header onto stack.
2) ...which also checks length requirement.
3) Skip checksum check: requires linear packet.
| -rw-r--r-- | net/ipv4/netfilter/ipt_REJECT.c | 38 |
1 files changed, 14 insertions, 24 deletions
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index 272dab8ded25..671a7d3057a5 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c @@ -84,45 +84,34 @@ static inline struct rtable *route_reverse(struct sk_buff *skb, int local) static void send_reset(struct sk_buff *oldskb, int local) { struct sk_buff *nskb; - struct tcphdr *otcph, *tcph; + struct tcphdr otcph, *tcph; struct rtable *rt; - unsigned int otcplen; 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) - || oldskb->len < (oldskb->nh.iph->ihl<<2) + sizeof(struct tcphdr)) + /* IP header checks: fragment. */ + if (oldskb->nh.iph->frag_off & htons(IP_OFFSET)) return; - otcph = (struct tcphdr *)((u_int32_t*)oldskb->nh.iph + oldskb->nh.iph->ihl); - otcplen = oldskb->len - oldskb->nh.iph->ihl*4; - if (skb_copy_bits(oldskb, oldskb->nh.iph->ihl*4, - otcph, sizeof(*otcph)) < 0) - return; + &otcph, sizeof(otcph)) < 0) + return; /* No RST for RST. */ - if (otcph->rst) - return; - - /* Check checksum. */ - if (tcp_v4_check(otcph, otcplen, oldskb->nh.iph->saddr, - oldskb->nh.iph->daddr, - csum_partial((char *)otcph, otcplen, 0)) != 0) + if (otcph.rst) return; + /* FIXME: Check checksum --RR */ if ((rt = route_reverse(oldskb, local)) == NULL) 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). We also need to expand headroom in case - hh_len of incoming interface < hh_len of outgoing interface */ + /* We need a linear, writeable skb. 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) { @@ -163,12 +152,13 @@ static void send_reset(struct sk_buff *oldskb, int local) if (tcph->ack) { needs_ack = 0; - tcph->seq = otcph->ack_seq; + tcph->seq = otcph.ack_seq; tcph->ack_seq = 0; } else { needs_ack = 1; - tcph->ack_seq = htonl(ntohl(otcph->seq) + otcph->syn + otcph->fin - + otcplen - (otcph->doff<<2)); + tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin + + oldskb->len - oldskb->nh.iph->ihl*4 + - (otcph.doff<<2)); tcph->seq = 0; } |
