summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2003-09-11 04:34:40 -0700
committerHideaki Yoshifuji <yoshfuji@linux-ipv6.org>2003-09-11 04:34:40 -0700
commitee2dea7df2b05dfbd73780ab624dd2b61ebebdb8 (patch)
tree859250eb64726cbccc3415e495a18789479d67a6
parent8b699049130fdd66bac86d73199ec4610e72cfff (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.c38
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;
}