patch-2.4.22 linux-2.4.22/net/ipv4/netfilter/ip_conntrack_core.c
Next file: linux-2.4.22/net/ipv4/netfilter/ip_conntrack_ftp.c
Previous file: linux-2.4.22/net/ipv4/netfilter/arpt_mangle.c
Back to the patch index
Back to the overall index
- Lines: 178
- Date:
2003-08-25 04:44:44.000000000 -0700
- Orig file:
linux-2.4.21/net/ipv4/netfilter/ip_conntrack_core.c
- Orig date:
2003-06-13 07:51:39.000000000 -0700
diff -urN linux-2.4.21/net/ipv4/netfilter/ip_conntrack_core.c linux-2.4.22/net/ipv4/netfilter/ip_conntrack_core.c
@@ -174,8 +174,8 @@
static void
destroy_expect(struct ip_conntrack_expect *exp)
{
- DEBUGP("destroy_expect(%p) use=%d\n", exp, atomic_read(exp->use));
- IP_NF_ASSERT(atomic_read(exp->use));
+ DEBUGP("destroy_expect(%p) use=%d\n", exp, atomic_read(&exp->use));
+ IP_NF_ASSERT(atomic_read(&exp->use));
IP_NF_ASSERT(!timer_pending(&exp->timeout));
kfree(exp);
@@ -257,16 +257,14 @@
}
/* delete all unconfirmed expectations for this conntrack */
-static void remove_expectations(struct ip_conntrack *ct)
+static void remove_expectations(struct ip_conntrack *ct, int drop_refcount)
{
struct list_head *exp_entry, *next;
struct ip_conntrack_expect *exp;
DEBUGP("remove_expectations(%p)\n", ct);
- for (exp_entry = ct->sibling_list.next;
- exp_entry != &ct->sibling_list; exp_entry = next) {
- next = exp_entry->next;
+ list_for_each_safe(exp_entry, next, &ct->sibling_list) {
exp = list_entry(exp_entry, struct ip_conntrack_expect,
expected_list);
@@ -274,8 +272,11 @@
* the un-established ones only */
if (exp->sibling) {
DEBUGP("remove_expectations: skipping established %p of %p\n", exp->sibling, ct);
- /* Indicate that this expectations parent is dead */
- exp->expectant = NULL;
+ if (drop_refcount) {
+ /* Indicate that this expectations parent is dead */
+ ip_conntrack_put(exp->expectant);
+ exp->expectant = NULL;
+ }
continue;
}
@@ -300,7 +301,7 @@
&ct->tuplehash[IP_CT_DIR_REPLY]);
/* Destroy all un-established, pending expectations */
- remove_expectations(ct);
+ remove_expectations(ct, 1);
}
static void
@@ -313,9 +314,6 @@
IP_NF_ASSERT(atomic_read(&nfct->use) == 0);
IP_NF_ASSERT(!timer_pending(&ct->timeout));
- if (ct->master && master_ct(ct))
- ip_conntrack_put(master_ct(ct));
-
/* To make sure we don't get any weird locking issues here:
* destroy_conntrack() MUST NOT be called with a write lock
* to ip_conntrack_lock!!! -HW */
@@ -332,9 +330,12 @@
/* Delete our master expectation */
if (ct->master) {
- /* can't call __unexpect_related here,
- * since it would screw up expect_list */
- list_del(&ct->master->expected_list);
+ if (ct->master->expectant) {
+ /* can't call __unexpect_related here,
+ * since it would screw up expect_list */
+ list_del(&ct->master->expected_list);
+ ip_conntrack_put(ct->master->expectant);
+ }
kfree(ct->master);
}
WRITE_UNLOCK(&ip_conntrack_lock);
@@ -596,7 +597,7 @@
int dropped = 0;
READ_LOCK(&ip_conntrack_lock);
- h = LIST_FIND(chain, unreplied, struct ip_conntrack_tuple_hash *);
+ h = LIST_FIND_B(chain, unreplied, struct ip_conntrack_tuple_hash *);
if (h)
atomic_inc(&h->ctrack->ct_general.use);
READ_UNLOCK(&ip_conntrack_lock);
@@ -695,9 +696,6 @@
INIT_LIST_HEAD(&conntrack->sibling_list);
- /* Mark clearly that it's not in the hash table. */
- conntrack->tuplehash[IP_CT_DIR_ORIGINAL].list.next = NULL;
-
WRITE_LOCK(&ip_conntrack_lock);
/* Need finding and deleting of expected ONLY if we win race */
READ_LOCK(&ip_conntrack_expect_tuple_lock);
@@ -705,6 +703,14 @@
struct ip_conntrack_expect *, tuple);
READ_UNLOCK(&ip_conntrack_expect_tuple_lock);
+ /* If master is not in hash table yet (ie. packet hasn't left
+ this machine yet), how can other end know about expected?
+ Hence these are not the droids you are looking for (if
+ master ct never got confirmed, we'd hold a reference to it
+ and weird things would happen to future packets). */
+ if (expected && !is_confirmed(expected->expectant))
+ expected = NULL;
+
/* Look up the conntrack helper for master connections only */
if (!expected)
conntrack->helper = ip_ct_find_helper(&repl_tuple);
@@ -715,12 +721,7 @@
&& ! del_timer(&expected->timeout))
expected = NULL;
- /* If master is not in hash table yet (ie. packet hasn't left
- this machine yet), how can other end know about expected?
- Hence these are not the droids you are looking for (if
- master ct never got confirmed, we'd hold a reference to it
- and weird things would happen to future packets). */
- if (expected && is_confirmed(expected->expectant)) {
+ if (expected) {
DEBUGP("conntrack: expectation arrives ct=%p exp=%p\n",
conntrack, expected);
/* Welcome, Mr. Bond. We've been expecting you... */
@@ -1033,18 +1034,11 @@
return -ENOMEM;
}
- /* Zero out the new structure, then fill out it with the data */
DEBUGP("new expectation %p of conntrack %p\n", new, related_to);
- memset(new, 0, sizeof(*expect));
- INIT_LIST_HEAD(&new->list);
- INIT_LIST_HEAD(&new->expected_list);
memcpy(new, expect, sizeof(*expect));
new->expectant = related_to;
new->sibling = NULL;
- /* increase usage count. This sucks. The memset above overwrites
- * old usage count [if still present] and we increase to one. Only
- * works because everything is done under ip_conntrack_lock() */
- atomic_inc(&new->use);
+ atomic_set(&new->use, 1);
/* add to expected list for this connection */
list_add(&new->expected_list, &related_to->sibling_list);
@@ -1149,7 +1143,7 @@
{
if (i->ctrack->helper == me) {
/* Get rid of any expected. */
- remove_expectations(i->ctrack);
+ remove_expectations(i->ctrack, 0);
/* And *then* set helper to NULL */
i->ctrack->helper = NULL;
}
@@ -1309,8 +1303,8 @@
getorigdst(struct sock *sk, int optval, void *user, int *len)
{
struct ip_conntrack_tuple_hash *h;
- struct ip_conntrack_tuple tuple = { { sk->rcv_saddr, { sk->sport } },
- { sk->daddr, { sk->dport },
+ struct ip_conntrack_tuple tuple = { { sk->rcv_saddr, { .tcp = { sk->sport } } },
+ { sk->daddr, { .tcp = { sk->dport } },
IPPROTO_TCP } };
/* We only do TCP at the moment: is there a better way? */
@@ -1483,8 +1477,10 @@
ip_ct_attach = ip_conntrack_attach;
return ret;
+#ifdef CONFIG_SYSCTL
err_free_ct_cachep:
kmem_cache_destroy(ip_conntrack_cachep);
+#endif /*CONFIG_SYSCTL*/
err_free_hash:
vfree(ip_conntrack_hash);
err_unreg_sockopt:
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)