linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / net / ipv4 / netfilter / ipt_REJECT.c
index 266d649..3eb47aa 100644 (file)
@@ -92,10 +92,7 @@ static inline struct rtable *route_reverse(struct sk_buff *skb,
        fl.fl_ip_sport = tcph->dest;
        fl.fl_ip_dport = tcph->source;
 
-       if (xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0)) {
-               dst_release(&rt->u.dst);
-               rt = NULL;
-       }
+       xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0);
 
        return rt;
 }
@@ -104,10 +101,12 @@ static inline struct rtable *route_reverse(struct sk_buff *skb,
 static void send_reset(struct sk_buff *oldskb, int hook)
 {
        struct sk_buff *nskb;
+       struct iphdr *iph = oldskb->nh.iph;
        struct tcphdr _otcph, *oth, *tcph;
        struct rtable *rt;
        u_int16_t tmp_port;
        u_int32_t tmp_addr;
+       unsigned int tcplen;
        int needs_ack;
        int hh_len;
 
@@ -124,7 +123,16 @@ static void send_reset(struct sk_buff *oldskb, int hook)
        if (oth->rst)
                return;
 
-       /* FIXME: Check checksum --RR */
+       /* Check checksum */
+       tcplen = oldskb->len - iph->ihl * 4;
+       if (((hook != NF_IP_LOCAL_IN && oldskb->ip_summed != CHECKSUM_HW) ||
+            (hook == NF_IP_LOCAL_IN &&
+             oldskb->ip_summed != CHECKSUM_UNNECESSARY)) &&
+           csum_tcpudp_magic(iph->saddr, iph->daddr, tcplen, IPPROTO_TCP,
+                             oldskb->ip_summed == CHECKSUM_HW ? oldskb->csum :
+                             skb_checksum(oldskb, iph->ihl * 4, tcplen, 0)))
+               return;
+
        if ((rt = route_reverse(oldskb, oth, hook)) == NULL)
                return;
 
@@ -145,7 +153,6 @@ static void send_reset(struct sk_buff *oldskb, int hook)
 
        /* This packet will not be the same as the other: clear nf fields */
        nf_reset(nskb);
-       nskb->nfcache = 0;
        nskb->nfmark = 0;
 #ifdef CONFIG_BRIDGE_NETFILTER
        nf_bridge_put(nskb->nf_bridge);
@@ -196,7 +203,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
                                                sizeof(struct tcphdr), 0));
 
        /* Adjust IP TTL, DF */
-       nskb->nh.iph->ttl = MAXTTL;
+       nskb->nh.iph->ttl = dst_metric(nskb->dst, RTAX_HOPLIMIT);
        /* Set DF, id = 0 */
        nskb->nh.iph->frag_off = htons(IP_DF);
        nskb->nh.iph->id = 0;
@@ -275,12 +282,13 @@ static unsigned int reject(struct sk_buff **pskb,
 }
 
 static int check(const char *tablename,
-                const struct ipt_entry *e,
+                const void *e_void,
                 void *targinfo,
                 unsigned int targinfosize,
                 unsigned int hook_mask)
 {
        const struct ipt_reject_info *rejinfo = targinfo;
+       const struct ipt_entry *e = e_void;
 
        if (targinfosize != IPT_ALIGN(sizeof(struct ipt_reject_info))) {
                DEBUGP("REJECT: targinfosize %u != 0\n", targinfosize);