linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / net / ipv4 / netfilter / ipt_REJECT.c
index 269bc20..3eb47aa 100644 (file)
@@ -12,6 +12,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/skbuff.h>
 #include <linux/ip.h>
@@ -105,6 +106,7 @@ static void send_reset(struct sk_buff *oldskb, int hook)
        struct rtable *rt;
        u_int16_t tmp_port;
        u_int32_t tmp_addr;
+       unsigned int tcplen;
        int needs_ack;
        int hh_len;
 
@@ -122,7 +124,13 @@ static void send_reset(struct sk_buff *oldskb, int hook)
                return;
 
        /* Check checksum */
-       if (nf_ip_checksum(oldskb, hook, iph->ihl * 4, IPPROTO_TCP))
+       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)
@@ -146,7 +154,10 @@ 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->nfmark = 0;
-       skb_init_secmark(nskb);
+#ifdef CONFIG_BRIDGE_NETFILTER
+       nf_bridge_put(nskb->nf_bridge);
+       nskb->nf_bridge = NULL;
+#endif
 
        tcph = (struct tcphdr *)((u_int32_t*)nskb->nh.iph + nskb->nh.iph->ihl);
 
@@ -225,7 +236,6 @@ static unsigned int reject(struct sk_buff **pskb,
                           const struct net_device *in,
                           const struct net_device *out,
                           unsigned int hooknum,
-                          const struct xt_target *target,
                           const void *targinfo,
                           void *userinfo)
 {
@@ -273,7 +283,6 @@ static unsigned int reject(struct sk_buff **pskb,
 
 static int check(const char *tablename,
                 const void *e_void,
-                const struct xt_target *target,
                 void *targinfo,
                 unsigned int targinfosize,
                 unsigned int hook_mask)
@@ -281,6 +290,23 @@ static int check(const char *tablename,
        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);
+               return 0;
+       }
+
+       /* Only allow these for packet filtering. */
+       if (strcmp(tablename, "filter") != 0) {
+               DEBUGP("REJECT: bad table `%s'.\n", tablename);
+               return 0;
+       }
+       if ((hook_mask & ~((1 << NF_IP_LOCAL_IN)
+                          | (1 << NF_IP_FORWARD)
+                          | (1 << NF_IP_LOCAL_OUT))) != 0) {
+               DEBUGP("REJECT: bad hook mask %X\n", hook_mask);
+               return 0;
+       }
+
        if (rejinfo->with == IPT_ICMP_ECHOREPLY) {
                printk("REJECT: ECHOREPLY no longer supported.\n");
                return 0;
@@ -292,29 +318,26 @@ static int check(const char *tablename,
                        return 0;
                }
        }
+
        return 1;
 }
 
 static struct ipt_target ipt_reject_reg = {
        .name           = "REJECT",
        .target         = reject,
-       .targetsize     = sizeof(struct ipt_reject_info),
-       .table          = "filter",
-       .hooks          = (1 << NF_IP_LOCAL_IN) | (1 << NF_IP_FORWARD) |
-                         (1 << NF_IP_LOCAL_OUT),
        .checkentry     = check,
        .me             = THIS_MODULE,
 };
 
-static int __init ipt_reject_init(void)
+static int __init init(void)
 {
        return ipt_register_target(&ipt_reject_reg);
 }
 
-static void __exit ipt_reject_fini(void)
+static void __exit fini(void)
 {
        ipt_unregister_target(&ipt_reject_reg);
 }
 
-module_init(ipt_reject_init);
-module_exit(ipt_reject_fini);
+module_init(init);
+module_exit(fini);