netdev
[Top] [All Lists]

[PATCH] netfilter fixes v2.3.99-pre4-2

To: torvalds@xxxxxxxxxxxxx
Subject: [PATCH] netfilter fixes v2.3.99-pre4-2
From: Rusty Russell <rusty@xxxxxxxxxxxxxxxx>
Date: Tue, 04 Apr 2000 00:51:06 +0930
Cc: netdev@xxxxxxxxxxx
Sender: owner-netdev@xxxxxxxxxxx
Linus, please apply.

Note to all: I am out this week (knee reconstruction).  If I post
before Thursday, I'm probably on pain medication, so check my patches
carefully 8).

This fixes:
1) Module unload races.
2) NAT on fragment issues (GameSpy crash).
3) Partially-initialized NAT entries if protocol doesn't like packet.
4) `check' failure one-too-many-down() bug.

Some paranoia issues:
1) Now doing an external lookup will never create a new connection.
2) Extra checks for locally-injected truncated IP packets (raw
   sockets).

Enjoy!
Rusty.

diff -urN --minimal --exclude *.lds --exclude *.sgml --exclude classlist.h 
--exclude devlist.h --exclude autoconf.h --exclude compile.h --exclude 
version.h --exclude .* --exclude *.[oa] --exclude *.orig --exclude config 
--exclude asm --exclude modules --exclude *.[Ss] --exclude System.map --exclude 
consolemap_deftbl.c --exclude *~ --exclude TAGS --exclude tags --exclude 
modversions.h --exclude install-kernel 
linux-2.3.99-pre4-2/include/linux/netfilter_ipv4/ip_conntrack_protocol.h 
working/include/linux/netfilter_ipv4/ip_conntrack_protocol.h
--- linux-2.3.99-pre4-2/include/linux/netfilter_ipv4/ip_conntrack_protocol.h    
Sat Apr  8 18:10:12 2000
+++ working/include/linux/netfilter_ipv4/ip_conntrack_protocol.h        Mon Apr 
 3 14:47:59 2000
@@ -37,10 +37,10 @@
                      struct iphdr *iph, size_t len,
                      enum ip_conntrack_info ctinfo);
 
-       /* Called when a new connection for this protocol found; returns
-        * TRUE if it's OK.  If so, packet() called next. */
-       int (*new)(struct ip_conntrack *conntrack,
-                  struct iphdr *iph, size_t len);
+       /* Called when a new connection for this protocol found;
+        * returns timeout.  If so, packet() called next. */
+       unsigned long (*new)(struct ip_conntrack *conntrack,
+                            struct iphdr *iph, size_t len);
 
        /* Module (if any) which this is connected to. */
        struct module *me;
diff -urN --minimal --exclude *.lds --exclude *.sgml --exclude classlist.h 
--exclude devlist.h --exclude autoconf.h --exclude compile.h --exclude 
version.h --exclude .* --exclude *.[oa] --exclude *.orig --exclude config 
--exclude asm --exclude modules --exclude *.[Ss] --exclude System.map --exclude 
consolemap_deftbl.c --exclude *~ --exclude TAGS --exclude tags --exclude 
modversions.h --exclude install-kernel 
linux-2.3.99-pre4-2/include/linux/netfilter_ipv4/ipt_state.h 
working/include/linux/netfilter_ipv4/ipt_state.h
--- linux-2.3.99-pre4-2/include/linux/netfilter_ipv4/ipt_state.h        Sat Mar 
18 05:26:20 2000
+++ working/include/linux/netfilter_ipv4/ipt_state.h    Mon Apr  3 14:18:20 2000
@@ -1,8 +1,7 @@
 #ifndef _IPT_STATE_H
 #define _IPT_STATE_H
 
-#define _IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)+1))
-#define IPT_STATE_BIT(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? 
_IPT_STATE_BIT((ctinfo)-IP_CT_IS_REPLY) : _IPT_STATE_BIT(ctinfo))
+#define IPT_STATE_BIT(ctinfo) (1 << ((ctinfo)%IP_CT_IS_REPLY+1))
 #define IPT_STATE_INVALID (1 << 0)
 
 struct ipt_state_info
diff -urN --minimal --exclude *.lds --exclude *.sgml --exclude classlist.h 
--exclude devlist.h --exclude autoconf.h --exclude compile.h --exclude 
version.h --exclude .* --exclude *.[oa] --exclude *.orig --exclude config 
--exclude asm --exclude modules --exclude *.[Ss] --exclude System.map --exclude 
consolemap_deftbl.c --exclude *~ --exclude TAGS --exclude tags --exclude 
modversions.h --exclude install-kernel 
linux-2.3.99-pre4-2/net/ipv4/ip_fragment.c working/net/ipv4/ip_fragment.c
--- linux-2.3.99-pre4-2/net/ipv4/ip_fragment.c  Thu Feb 10 14:38:09 2000
+++ working/net/ipv4/ip_fragment.c      Mon Apr  3 14:18:20 2000
@@ -387,8 +387,13 @@
        */
        skb->security = qp->fragments->skb->security;
 
+#ifdef CONFIG_NETFILTER
+       /* Connection association is same as fragment (if any). */
+       skb->nfct = qp->fragments->skb->nfct;
+       nf_conntrack_get(skb->nfct);
 #ifdef CONFIG_NETFILTER_DEBUG
        skb->nf_debug = qp->fragments->skb->nf_debug;
+#endif
 #endif
 
        /* Done with all fragments. Fixup the new IP header. */
diff -urN --minimal --exclude *.lds --exclude *.sgml --exclude classlist.h 
--exclude devlist.h --exclude autoconf.h --exclude compile.h --exclude 
version.h --exclude .* --exclude *.[oa] --exclude *.orig --exclude config 
--exclude asm --exclude modules --exclude *.[Ss] --exclude System.map --exclude 
consolemap_deftbl.c --exclude *~ --exclude TAGS --exclude tags --exclude 
modversions.h --exclude install-kernel 
linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_conntrack_core.c 
working/net/ipv4/netfilter/ip_conntrack_core.c
--- linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_conntrack_core.c  Sat Apr  1 
19:03:03 2000
+++ working/net/ipv4/netfilter/ip_conntrack_core.c      Mon Apr  3 14:18:20 2000
@@ -343,6 +343,7 @@
        size_t hash, repl_hash;
        struct ip_conntrack_expect *expected;
        enum ip_conntrack_info ctinfo;
+       unsigned long extra_jiffies;
        int i;
 
        if (!invert_tuple(&repl_tuple, tuple, protocol)) {
@@ -366,19 +367,24 @@
        repl_hash = hash_conntrack(&repl_tuple);
 
        memset(conntrack, 0, sizeof(struct ip_conntrack));
-       atomic_set(&conntrack->ct_general.use, 1);
+       atomic_set(&conntrack->ct_general.use, 2);
        conntrack->ct_general.destroy = destroy_conntrack;
        conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple = *tuple;
        conntrack->tuplehash[IP_CT_DIR_ORIGINAL].ctrack = conntrack;
        conntrack->tuplehash[IP_CT_DIR_REPLY].tuple = repl_tuple;
        conntrack->tuplehash[IP_CT_DIR_REPLY].ctrack = conntrack;
-       for(i=0; i < IP_CT_NUMBER; i++)
+       for (i=0; i < IP_CT_NUMBER; i++)
                conntrack->infos[i].master = &conntrack->ct_general;
 
-       if (!protocol->new(conntrack, skb->nh.iph, skb->len)) {
+       extra_jiffies = protocol->new(conntrack, skb->nh.iph, skb->len);
+       if (!extra_jiffies) {
                kmem_cache_free(ip_conntrack_cachep, conntrack);
                return 1;
        }
+       conntrack->timeout.data = (unsigned long)conntrack;
+       conntrack->timeout.function = death_by_timeout;
+       conntrack->timeout.expires = jiffies + extra_jiffies;
+       add_timer(&conntrack->timeout);
 
        /* Sew in at head of hash list. */
        WRITE_LOCK(&ip_conntrack_lock);
@@ -421,7 +427,7 @@
 }
 
 static void
-resolve_normal_ct(struct sk_buff *skb)
+resolve_normal_ct(struct sk_buff *skb, int create)
 {
        struct ip_conntrack_tuple tuple;
        struct ip_conntrack_tuple_hash *h;
@@ -436,7 +442,7 @@
        do {
                /* look for tuple match */
                h = ip_conntrack_find_get(&tuple, NULL);
-               if (!h && init_conntrack(&tuple, proto, skb))
+               if (!h && (!create || init_conntrack(&tuple, proto, skb)))
                        return;
        } while (!h);
 
@@ -464,13 +470,15 @@
 }
 
 /* Return conntrack and conntrack_info a given skb */
-struct ip_conntrack *
-ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+static struct ip_conntrack *
+__ip_conntrack_get(struct sk_buff *skb,
+                  enum ip_conntrack_info *ctinfo,
+                  int create)
 {
        if (!skb->nfct) {
                /* It may be an icmp error... */
                if (!icmp_error_track(skb))
-                       resolve_normal_ct(skb);
+                       resolve_normal_ct(skb, create);
        }
 
        if (skb->nfct) {
@@ -485,6 +493,12 @@
        return NULL;
 }
 
+struct ip_conntrack *
+ip_conntrack_get(struct sk_buff *skb, enum ip_conntrack_info *ctinfo)
+{
+       return __ip_conntrack_get(skb, ctinfo, 0);
+}
+
 /* Netfilter hook itself. */
 unsigned int ip_conntrack_in(unsigned int hooknum,
                             struct sk_buff **pskb,
@@ -512,13 +526,13 @@
                        return NF_STOLEN;
        }
 
-       ct = ip_conntrack_get(*pskb, &ctinfo);
-       if (!ct)
+       ct = __ip_conntrack_get(*pskb, &ctinfo, 1);
+       if (!ct) {
                /* Not valid part of a connection */
                return NF_ACCEPT;
+       }
 
        proto = find_proto((*pskb)->nh.iph->protocol);
-       /* If this is new, this is first time timer will be set */
        ret = proto->packet(ct, (*pskb)->nh.iph, (*pskb)->len, ctinfo);
 
        if (ret == -1) {
@@ -645,24 +659,16 @@
        MOD_DEC_USE_COUNT;
 }
 
-/* Refresh conntrack for this many jiffies: if noone calls this,
-   conntrack will vanish with current skb. */
+/* Refresh conntrack for this many jiffies. */
 void ip_ct_refresh(struct ip_conntrack *ct, unsigned long extra_jiffies)
 {
+       IP_NF_ASSERT(ct->timeout.data == (unsigned long)ct);
+
        WRITE_LOCK(&ip_conntrack_lock);
-       /* If this hasn't had a timer before, it's still being set up */
-       if (ct->timeout.data == 0) {
-               ct->timeout.data = (unsigned long)ct;
-               ct->timeout.function = death_by_timeout;
+       /* Need del_timer for race avoidance (may already be dying). */
+       if (del_timer(&ct->timeout)) {
                ct->timeout.expires = jiffies + extra_jiffies;
-               atomic_inc(&ct->ct_general.use);
                add_timer(&ct->timeout);
-       } else {
-               /* Need del_timer for race avoidance (may already be dying). */
-               if (del_timer(&ct->timeout)) {
-                       ct->timeout.expires = jiffies + extra_jiffies;
-                       add_timer(&ct->timeout);
-               }
        }
        WRITE_UNLOCK(&ip_conntrack_lock);
 }
diff -urN --minimal --exclude *.lds --exclude *.sgml --exclude classlist.h 
--exclude devlist.h --exclude autoconf.h --exclude compile.h --exclude 
version.h --exclude .* --exclude *.[oa] --exclude *.orig --exclude config 
--exclude asm --exclude modules --exclude *.[Ss] --exclude System.map --exclude 
consolemap_deftbl.c --exclude *~ --exclude TAGS --exclude tags --exclude 
modversions.h --exclude install-kernel 
linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_conntrack_proto_generic.c 
working/net/ipv4/netfilter/ip_conntrack_proto_generic.c
--- linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_conntrack_proto_generic.c Sat Mar 
18 05:26:20 2000
+++ working/net/ipv4/netfilter/ip_conntrack_proto_generic.c     Mon Apr  3 
14:18:20 2000
@@ -48,9 +48,10 @@
 }
 
 /* Called when a new connection for this protocol found. */
-static int new(struct ip_conntrack *conntrack, struct iphdr *iph, size_t len)
+static unsigned long
+new(struct ip_conntrack *conntrack, struct iphdr *iph, size_t len)
 {
-       return 1;
+       return GENERIC_TIMEOUT;
 }
 
 struct ip_conntrack_protocol ip_conntrack_generic_protocol
diff -urN --minimal --exclude *.lds --exclude *.sgml --exclude classlist.h 
--exclude devlist.h --exclude autoconf.h --exclude compile.h --exclude 
version.h --exclude .* --exclude *.[oa] --exclude *.orig --exclude config 
--exclude asm --exclude modules --exclude *.[Ss] --exclude System.map --exclude 
consolemap_deftbl.c --exclude *~ --exclude TAGS --exclude tags --exclude 
modversions.h --exclude install-kernel 
linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_conntrack_proto_icmp.c 
working/net/ipv4/netfilter/ip_conntrack_proto_icmp.c
--- linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_conntrack_proto_icmp.c    Sat Apr 
 1 19:03:03 2000
+++ working/net/ipv4/netfilter/ip_conntrack_proto_icmp.c        Mon Apr  3 
14:18:20 2000
@@ -86,8 +86,8 @@
 }
 
 /* Called when a new connection for this protocol found. */
-static int icmp_new(struct ip_conntrack *conntrack,
-                    struct iphdr *iph, size_t len)
+static unsigned long icmp_new(struct ip_conntrack *conntrack,
+                             struct iphdr *iph, size_t len)
 {
        static u_int8_t valid_new[]
                = { [ICMP_ECHO] = 1,
@@ -103,7 +103,7 @@
                DUMP_TUPLE(&conntrack->tuplehash[0].tuple);
                return 0;
        }
-       return 1;
+       return ICMP_TIMEOUT;
 }
 
 struct ip_conntrack_protocol ip_conntrack_protocol_icmp
diff -urN --minimal --exclude *.lds --exclude *.sgml --exclude classlist.h 
--exclude devlist.h --exclude autoconf.h --exclude compile.h --exclude 
version.h --exclude .* --exclude *.[oa] --exclude *.orig --exclude config 
--exclude asm --exclude modules --exclude *.[Ss] --exclude System.map --exclude 
consolemap_deftbl.c --exclude *~ --exclude TAGS --exclude tags --exclude 
modversions.h --exclude install-kernel 
linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_conntrack_proto_tcp.c 
working/net/ipv4/netfilter/ip_conntrack_proto_tcp.c
--- linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_conntrack_proto_tcp.c     Sat Apr 
 1 19:03:03 2000
+++ working/net/ipv4/netfilter/ip_conntrack_proto_tcp.c Mon Apr  3 14:18:20 2000
@@ -189,14 +189,13 @@
        conntrack->proto.tcp_state = newconntrack;
        WRITE_UNLOCK(&tcp_lock);
 
-       /* Refresh: need write lock to write to conntrack. */
        ip_ct_refresh(conntrack, tcp_timeouts[conntrack->proto.tcp_state]);
        return NF_ACCEPT;
 }
 
 /* Called when a new connection for this protocol found. */
-static int tcp_new(struct ip_conntrack *conntrack,
-                  struct iphdr *iph, size_t len)
+static unsigned long tcp_new(struct ip_conntrack *conntrack,
+                            struct iphdr *iph, size_t len)
 {
        enum tcp_conntrack newconntrack;
        struct tcphdr *tcph = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
@@ -210,11 +209,10 @@
        if (newconntrack == TCP_CONNTRACK_MAX) {
                DEBUGP("ip_conntrack_tcp: invalid new deleting.\n");
                return 0;
-       } else {
-               conntrack->proto.tcp_state = newconntrack;
-               ip_ct_refresh(conntrack, 
tcp_timeouts[conntrack->proto.tcp_state]);
        }
-       return 1;
+
+       conntrack->proto.tcp_state = newconntrack;
+       return tcp_timeouts[conntrack->proto.tcp_state];
 }
 
 struct ip_conntrack_protocol ip_conntrack_protocol_tcp
diff -urN --minimal --exclude *.lds --exclude *.sgml --exclude classlist.h 
--exclude devlist.h --exclude autoconf.h --exclude compile.h --exclude 
version.h --exclude .* --exclude *.[oa] --exclude *.orig --exclude config 
--exclude asm --exclude modules --exclude *.[Ss] --exclude System.map --exclude 
consolemap_deftbl.c --exclude *~ --exclude TAGS --exclude tags --exclude 
modversions.h --exclude install-kernel 
linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_conntrack_proto_udp.c 
working/net/ipv4/netfilter/ip_conntrack_proto_udp.c
--- linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_conntrack_proto_udp.c     Sat Apr 
 1 19:03:03 2000
+++ working/net/ipv4/netfilter/ip_conntrack_proto_udp.c Mon Apr  3 14:18:20 2000
@@ -54,10 +54,10 @@
 }
 
 /* Called when a new connection for this protocol found. */
-static int udp_new(struct ip_conntrack *conntrack,
-                   struct iphdr *iph, size_t len)
+static unsigned long udp_new(struct ip_conntrack *conntrack,
+                            struct iphdr *iph, size_t len)
 {
-       return 1;
+       return UDP_TIMEOUT;
 }
 
 struct ip_conntrack_protocol ip_conntrack_protocol_udp
diff -urN --minimal --exclude *.lds --exclude *.sgml --exclude classlist.h 
--exclude devlist.h --exclude autoconf.h --exclude compile.h --exclude 
version.h --exclude .* --exclude *.[oa] --exclude *.orig --exclude config 
--exclude asm --exclude modules --exclude *.[Ss] --exclude System.map --exclude 
consolemap_deftbl.c --exclude *~ --exclude TAGS --exclude tags --exclude 
modversions.h --exclude install-kernel 
linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_conntrack_standalone.c 
working/net/ipv4/netfilter/ip_conntrack_standalone.c
--- linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_conntrack_standalone.c    Sat Apr 
 1 19:03:03 2000
+++ working/net/ipv4/netfilter/ip_conntrack_standalone.c        Mon Apr  3 
14:18:20 2000
@@ -169,8 +169,6 @@
           interface.  We degfragment them at LOCAL_OUT, however,
           so we have to refragment them here. */
        if ((*pskb)->len > rt->u.dst.pmtu) {
-               DEBUGP("ip_conntrack: refragm %p (size %u) to %u (okfn %p)\n",
-                      *pskb, (*pskb)->len, rt->u.dst.pmtu, okfn);
                /* No hook can be after us, so this should be OK. */
                ip_fragment(*pskb, okfn);
                return NF_STOLEN;
@@ -178,13 +176,29 @@
        return NF_ACCEPT;
 }
 
+static unsigned int ip_conntrack_local(unsigned int hooknum,
+                                      struct sk_buff **pskb,
+                                      const struct net_device *in,
+                                      const struct net_device *out,
+                                      int (*okfn)(struct sk_buff *))
+{
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr)
+           || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr)) {
+               if (net_ratelimit())
+                       printk("ipt_hook: happy cracking.\n");
+               return NF_ACCEPT;
+       }
+       return ip_conntrack_in(hooknum, pskb, in, out, okfn);
+}
+
 /* Connection tracking may drop packets, but never alters them, so
    make it the first hook. */
 static struct nf_hook_ops ip_conntrack_in_ops
 = { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_PRE_ROUTING,
        NF_IP_PRI_CONNTRACK };
 static struct nf_hook_ops ip_conntrack_local_out_ops
-= { { NULL, NULL }, ip_conntrack_in, PF_INET, NF_IP_LOCAL_OUT,
+= { { NULL, NULL }, ip_conntrack_local, PF_INET, NF_IP_LOCAL_OUT,
        NF_IP_PRI_CONNTRACK };
 /* Refragmenter; last chance. */
 static struct nf_hook_ops ip_conntrack_out_ops
diff -urN --minimal --exclude *.lds --exclude *.sgml --exclude classlist.h 
--exclude devlist.h --exclude autoconf.h --exclude compile.h --exclude 
version.h --exclude .* --exclude *.[oa] --exclude *.orig --exclude config 
--exclude asm --exclude modules --exclude *.[Ss] --exclude System.map --exclude 
consolemap_deftbl.c --exclude *~ --exclude TAGS --exclude tags --exclude 
modversions.h --exclude install-kernel 
linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_nat_standalone.c 
working/net/ipv4/netfilter/ip_nat_standalone.c
--- linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_nat_standalone.c  Sat Apr  1 
19:03:03 2000
+++ working/net/ipv4/netfilter/ip_nat_standalone.c      Mon Apr  3 14:18:20 2000
@@ -130,6 +130,11 @@
           const struct net_device *out,
           int (*okfn)(struct sk_buff *))
 {
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr)
+           || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+               return NF_ACCEPT;
+
        /* We can hit fragment here; forwarded packets get
           defragmented by connection tracking coming in, then
           fragmented (grr) by the forward code.
@@ -150,6 +155,21 @@
        return ip_nat_fn(hooknum, pskb, in, out, okfn);
 }
 
+static unsigned int
+ip_nat_local_fn(unsigned int hooknum,
+               struct sk_buff **pskb,
+               const struct net_device *in,
+               const struct net_device *out,
+               int (*okfn)(struct sk_buff *))
+{
+       /* root is playing with raw sockets. */
+       if ((*pskb)->len < sizeof(struct iphdr)
+           || (*pskb)->nh.iph->ihl * 4 < sizeof(struct iphdr))
+               return NF_ACCEPT;
+
+       return ip_nat_fn(hooknum, pskb, in, out, okfn);
+}
+
 /* We must be after connection tracking and before packet filtering. */
 
 /* Before packet filtering, change destination */
@@ -160,7 +180,7 @@
 = { { NULL, NULL }, ip_nat_out, PF_INET, NF_IP_POST_ROUTING, 
NF_IP_PRI_NAT_SRC};
 /* Before packet filtering, change destination */
 static struct nf_hook_ops ip_nat_local_out_ops
-= { { NULL, NULL }, ip_nat_fn, PF_INET, NF_IP_LOCAL_OUT, NF_IP_PRI_NAT_DST };
+= { { NULL, NULL }, ip_nat_local_fn, PF_INET, NF_IP_LOCAL_OUT, 
NF_IP_PRI_NAT_DST };
 
 /* Protocol registration. */
 int ip_nat_protocol_register(struct ip_nat_protocol *proto)
diff -urN --minimal --exclude *.lds --exclude *.sgml --exclude classlist.h 
--exclude devlist.h --exclude autoconf.h --exclude compile.h --exclude 
version.h --exclude .* --exclude *.[oa] --exclude *.orig --exclude config 
--exclude asm --exclude modules --exclude *.[Ss] --exclude System.map --exclude 
consolemap_deftbl.c --exclude *~ --exclude TAGS --exclude tags --exclude 
modversions.h --exclude install-kernel 
linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_tables.c 
working/net/ipv4/netfilter/ip_tables.c
--- linux-2.3.99-pre4-2/net/ipv4/netfilter/ip_tables.c  Sat Apr  1 19:03:03 2000
+++ working/net/ipv4/netfilter/ip_tables.c      Mon Apr  3 14:52:21 2000
@@ -39,7 +39,7 @@
 #define IP_NF_ASSERT(x)                                                \
 do {                                                           \
        if (!(x))                                               \
-               printk("IPT_ASSERT: %s:%s:%u\n",                \
+               printk("IP_NF_ASSERT: %s:%s:%u\n",              \
                       __FUNCTION__, __FILE__, __LINE__);       \
 } while(0)
 #else
@@ -683,7 +683,6 @@
        target = find_target_lock(t->u.name, &ret, &ipt_mutex);
        if (!target) {
                duprintf("check_entry: `%s' not found\n", t->u.name);
-               up(&ipt_mutex);
                return ret;
        }
        if (target->me)
@@ -1283,17 +1282,16 @@
 {
        int ret;
 
+       MOD_INC_USE_COUNT;
        ret = down_interruptible(&ipt_mutex);
        if (ret != 0)
                return ret;
 
-       if (list_named_insert(&ipt_target, target)) {
-               MOD_INC_USE_COUNT;
-               ret = 0;
-       } else {
+       if (!list_named_insert(&ipt_target, target)) {
                duprintf("ipt_register_target: `%s' already in list!\n",
                         target->name);
                ret = -EINVAL;
+               MOD_DEC_USE_COUNT;
        }
        up(&ipt_mutex);
        return ret;
@@ -1313,16 +1311,18 @@
 {
        int ret;
 
+       MOD_INC_USE_COUNT;
        ret = down_interruptible(&ipt_mutex);
-       if (ret != 0)
+       if (ret != 0) {
+               MOD_DEC_USE_COUNT;
                return ret;
-
+       }
        if (list_named_insert(&ipt_match, match)) {
-               MOD_INC_USE_COUNT;
                ret = 0;
        } else {
                duprintf("ipt_register_match: `%s' already in list!\n",
                         match->name);
+               MOD_DEC_USE_COUNT;
                ret = -EINVAL;
        }
        up(&ipt_mutex);
@@ -1346,10 +1346,12 @@
        static struct ipt_table_info bootstrap
                = { 0, 0, { 0 }, { 0 }, { }, { } };
 
+       MOD_INC_USE_COUNT;
        newinfo = vmalloc(sizeof(struct ipt_table_info)
                          + SMP_ALIGN(table->table->size) * smp_num_cpus);
        if (!newinfo) {
                ret = -ENOMEM;
+               MOD_DEC_USE_COUNT;
                return ret;
        }
        memcpy(newinfo->entries, table->table->entries, table->table->size);
@@ -1361,12 +1363,14 @@
                              table->table->underflow);
        if (ret != 0) {
                vfree(newinfo);
+               MOD_DEC_USE_COUNT;
                return ret;
        }
 
        ret = down_interruptible(&ipt_mutex);
        if (ret != 0) {
                vfree(newinfo);
+               MOD_DEC_USE_COUNT;
                return ret;
        }
 
@@ -1386,7 +1390,6 @@
 
        table->lock = RW_LOCK_UNLOCKED;
        list_prepend(&ipt_tables, table);
-       MOD_INC_USE_COUNT;
 
  unlock:
        up(&ipt_mutex);
@@ -1394,6 +1397,7 @@
 
  free_unlock:
        vfree(newinfo);
+       MOD_DEC_USE_COUNT;
        goto unlock;
 }

--
Hacking time.

<Prev in Thread] Current Thread [Next in Thread>