All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/2] Port nfnetlink and nfnetlink_conntrack to 2.6
@ 2005-03-27 23:56 Pablo Neira
  2005-03-30 15:57 ` Wang Jian
  0 siblings, 1 reply; 2+ messages in thread
From: Pablo Neira @ 2005-03-27 23:56 UTC (permalink / raw)
  To: Netfilter Development Mailinglist

[-- Attachment #1: Type: text/plain, Size: 920 bytes --]

Comments about changes:

o Minor change: my compiler (gcc-2.95) complained about ct_debug so I 
inserted the classical DEBUGP macro.

o No important modifications in nfnetlink.c

o Added support to identify conntracks by id.

o Removed ordered list, now we just insert a unsigned int in struct 
ip_conntrack to hold the id. Now the table dumping is done iterating the 
hash table.

o Adaptation to ct-event API

o improved way to delete a conntrack (marcus sundberg)

o kill [dump|change]_natinfo, now that must be handle in 
[dump|change]_status.

o IMPORTANT: I haven't tested expectation handling.

Things I consider to do:

o split CTNL_MSG_GETCONNTRACK to two messages types: 
CTNL_MSG_GETCONNTRACK and CTNL_MSG_DMPCONNTRACK (dump)

o split CTNL_MSG_NEWCONNTRACK to two messages types: 
CTNL_MSG_NEWCONNTRACK and CTNL_MSG_UPDCONNTRACK (update)

o Move nfnetlink.h and nfnetlink_conntrack.h to netfilter/ directory.

[-- Attachment #2: nfct.patch --]
[-- Type: text/x-patch, Size: 27636 bytes --]

--- linux-2.5/net/ipv4/netfilter/nfnetlink.c.orig	2005-03-07 20:16:24.000000000 +0100
+++ linux-2.5/net/ipv4/netfilter/nfnetlink.c	2005-03-26 04:22:53.000000000 +0100
@@ -42,14 +42,9 @@
 static char __initdata nfversion[] = "0.12";
 
 #if 1
-static int nf_debug_level = 1;
-#define nf_debug(level, format, arg...)					\
-do {									\
-	if (nf_debug_level > level)					\
-		printk(KERN_DEBUG "%s: " format, __FUNCTION__, ## arg);	\
-} while(0)
+#define DEBUGP printk
 #else
-#define nf_debug(level, format, arg...)
+#define DEBUGP(format, args...)
 #endif
 
 static struct sock *nfnl = NULL;
@@ -87,9 +82,7 @@
 
 int nfnetlink_subsys_register(struct nfnetlink_subsystem *n)
 {
-	MOD_INC_USE_COUNT;
-
-	nf_debug(0, "registering subsystem ID %u\n", n->subsys_id);
+	DEBUGP("registering subsystem ID %u\n", n->subsys_id);
 
 	nfnl_lock();
 	list_add(&n->list, &subsys_list);
@@ -101,15 +94,13 @@
 
 int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n)
 {
-	nf_debug(0, "unregistering subsystem ID %u\n", n->subsys_id);
+	DEBUGP("unregistering subsystem ID %u\n", n->subsys_id);
 
 	nfnl_lock();
 	subsys_table[n->subsys_id] = NULL;
 	list_del(&n->list);
 	nfnl_unlock();
 
-	MOD_DEC_USE_COUNT;
-
 	return 0;
 }
 
@@ -126,8 +117,7 @@
 	ss = subsys_table[subsys_id];
 
 	if (type >= ss->cb_count) {
-		nf_debug(0, "msgtype %u >= %u, returning\n", type, 
-			 ss->cb_count);
+		DEBUGP("msgtype %u >= %u, returning\n", type, ss->cb_count);
 		return NULL;
 	}
 
@@ -222,38 +212,38 @@
 	struct nfnl_callback *nc;
 	int type, err = 0;
 
-	nf_debug(0, "entered; subsys=%u, msgtype=%u\n",
+	DEBUGP("entered; subsys=%u, msgtype=%u\n",
 		 NFNL_SUBSYS_ID(nlh->nlmsg_type),
 		 NFNL_MSG_TYPE(nlh->nlmsg_type));
 
 	/* Only requests are handled by kernel now. */
 	if (!(nlh->nlmsg_flags & NLM_F_REQUEST)) {
-		nf_debug(0, "received non-request message\n");
+		DEBUGP("received non-request message\n");
 		return 0;
 	}
 
 	/* Unknown message: reply with EINVAL */
 	type = nlh->nlmsg_type;
 	if (NFNL_SUBSYS_ID(type) > NFNL_SUBSYS_COUNT) {
-		nf_debug(0, "subsys_id > subsys_count\n");
+		DEBUGP("subsys_id > subsys_count\n");
 		goto err_inval;
 	}
 
 	/* All the messages must have at least 1 byte length */
 	if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) {
-		nf_debug(0, "received message was too short\n");
+		DEBUGP("received message was too short\n");
 		return 0;
 	}
 
 	nc = nfnetlink_find_client(type);
 	if (!nc) {
-		nf_debug(0, "unable to find client for type %d\n", type);
+		DEBUGP("unable to find client for type %d\n", type);
 		goto err_inval;
 	}
 
 	if (nc->cap_required && 
 	    !cap_raised(NETLINK_CB(skb).eff_cap, nc->cap_required)) {
-		nf_debug(0, "permission denied for type %d\n", type);
+		DEBUGP("permission denied for type %d\n", type);
 		*errp = -EPERM;
 		return -1;
 	}
@@ -304,10 +294,11 @@
 		if (nfnl_shlock_nowait())
 			return;
 
-		while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) {
+		while ((skb = skb_dequeue(&sk->sk_receive_queue)) != NULL) {
 			if (nfnetlink_rcv_skb(skb)) {
 				if (skb->len)
-					skb_queue_head(&sk->receive_queue, skb);
+					skb_queue_head(&sk->sk_receive_queue,
+						       skb);
 				else
 					kfree_skb(skb);
 				break;
@@ -316,13 +307,13 @@
 		}
 
 		up(&nfnl_sem);
-	} while(nfnl && nfnl->receive_queue.qlen);
+	} while(nfnl && nfnl->sk_receive_queue.qlen);
 }
 
 void __exit nfnetlink_exit(void)
 {
 	printk("Netfilter removing netlink socket.\n");
-	sock_release(nfnl->socket);
+	sock_release(nfnl->sk_socket);
 	return;
 }
 
--- linux-2.5/include/linux/nfnetlink.h.orig	2005-03-07 20:41:04.000000000 +0100
+++ linux-2.5/include/linux/nfnetlink.h	2005-03-28 00:12:37.000000000 +0200
@@ -72,8 +72,9 @@
 #define NFM_PAYLOAD(n)  NLMSG_PAYLOAD(n, sizeof(struct nfgenmsg))
 
 
+/* Now it's uses NETLINK_FIREWALL */
 #ifndef NETLINK_NETFILTER
-#define NETLINK_NETFILTER	6
+#define NETLINK_NETFILTER	3
 #endif
 
 /* netfilter netlink message types are split in two pieces:
--- linux-2.5/net/ipv4/netfilter/nfnetlink_conntrack.c.orig	2005-03-07 20:16:55.000000000 +0100
+++ linux-2.5/net/ipv4/netfilter/nfnetlink_conntrack.c	2005-03-28 01:36:29.000000000 +0200
@@ -57,16 +57,8 @@
 static char __initdata ctversion[] = "0.12";
 
 #if 1
-static int ct_debug_level = 1;
-#define ct_debug(level, format, arg...)					\
-do {									\
-	if(ct_debug_level > level)					\
-		printk(KERN_DEBUG "%s: " format, __FUNCTION__, ## arg);	\
-} while(0)
-/* FIXME: this define is just needed for DUMP_TUPLE */
-#define DEBUGP(format, args...)	ct_debug(0, format, ## args)
+#define DEBUGP printk
 #else
-#define ct_debug(level, format, arg...)
 #define DEBUGP(format, args...)
 #endif
 
@@ -142,32 +134,19 @@
 }
 
 static inline int
-ctnetlink_dump_natinfo(struct sk_buff *skb, const struct ip_conntrack *ct)
+ctnetlink_dump_mark(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
-#ifdef CONFIG_IP_NF_NAT_NEEDED
-	const struct ip_nat_info *info = &ct->nat.info;
-	struct cta_nat cn;
-
-	if (!info->initialized || !info->num_manips)
-		return 0;
-
-	cn.num_manips = info->num_manips;
-	memcpy(&cn.manips, &info->manips,
-	       info->num_manips * sizeof(struct ip_nat_info_manip));
-	NFA_PUT(skb, CTA_NATINFO, sizeof(struct cta_nat), &cn);
-	return 0;
-
-nfattr_failure:
-	return -1;
-#else
 	return 0;
-#endif
 }
 
 static inline int
-ctnetlink_dump_mark(struct sk_buff *skb, const struct ip_conntrack *ct)
+ctnetlink_dump_id(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
+	NFA_PUT(skb, CTA_ID, sizeof(unsigned int), &ct->id);
 	return 0;
+
+nfattr_failure:
+	return -1;
 }
 
 static int
@@ -193,8 +172,8 @@
 	    ctnetlink_dump_timeout(skb, ct) < 0 ||
 	    ctnetlink_dump_protoinfo(skb, ct) < 0 ||
 	    ctnetlink_dump_helpinfo(skb, ct) < 0 ||
-	    ctnetlink_dump_natinfo(skb, ct) < 0 ||
-	    ctnetlink_dump_mark(skb, ct) < 0)
+	    ctnetlink_dump_mark(skb, ct) < 0 ||
+	    ctnetlink_dump_id(skb, ct) < 0)
 		goto nfattr_failure;
 
 	nlh->nlmsg_len = skb->tail - b;
@@ -230,7 +209,7 @@
 	return groups;
 }
 
-#define EVENT(m,e) ((m) & (1 << (e)))
+#define EVENT(m,e) (m & e)
 
 static int ctnetlink_conntrack_event(struct notifier_block *this,
                                      unsigned long events, void *ptr)
@@ -243,8 +222,8 @@
 	unsigned char *b;
 	int flags = 0;
 
-	/* FIXME: much too big, costs lots of socket buffer space */
-	skb = alloc_skb(400 /* NLMSG_GOODSIZE */, GFP_ATOMIC);
+	/* netlink_trim now reduces the impact of using NLMSG_GOODSIZE */
+	skb = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
 	if (!skb)
 		return NOTIFY_DONE;
 
@@ -271,7 +250,7 @@
 	if (ctnetlink_dump_tuples(skb, ct) < 0)
 		goto nfattr_failure;
 
-	if (EVENT(events, IPCT_STATUS)
+	if ((EVENT(events, IPCT_STATUS) || EVENT(events, IPCT_NATINFO))
 	    && ctnetlink_dump_status(skb, ct) < 0)
 		goto nfattr_failure;
 	if (EVENT(events, IPCT_REFRESH)
@@ -283,9 +262,6 @@
 	if (EVENT(events, IPCT_HELPINFO)
 	    && ctnetlink_dump_helpinfo(skb, ct) < 0)
 		goto nfattr_failure;
-	if (EVENT(events, IPCT_NATINFO)
-	    && ctnetlink_dump_natinfo(skb, ct) < 0)
-		goto nfattr_failure;
 
 	nlh->nlmsg_len = skb->tail - b;
 	nfnetlink_send(skb, 0, ctnetlink_get_mcgroups(ct), 0);
@@ -303,18 +279,17 @@
 	[CTA_STATUS-1]		= sizeof(unsigned long),
 	[CTA_PROTOINFO-1]	= sizeof(struct cta_proto),
 	[CTA_HELPINFO-1]	= sizeof(struct cta_help),
-	[CTA_NATINFO-1]		= sizeof(struct cta_nat),
 	[CTA_TIMEOUT-1]		= sizeof(unsigned long),
+	[CTA_ID-1]		= sizeof(unsigned int),
 
 	[CTA_EXP_TUPLE-1]	= sizeof(struct ip_conntrack_tuple),
 	[CTA_EXP_MASK-1]	= sizeof(struct ip_conntrack_tuple),
 	[CTA_EXP_SEQNO-1]	= sizeof(u_int32_t),
 	[CTA_EXP_PROTO-1]	= sizeof(struct cta_exp_proto),
-	[CTA_EXP_HELP-1]	= sizeof(struct cta_exp_help),
 	[CTA_EXP_TIMEOUT-1]	= sizeof(unsigned long)
 };
 
-static inline int ctnetlink_kill(const struct ip_conntrack *i, void *data)
+static inline int ctnetlink_kill(struct ip_conntrack *i, void *data)
 {
 	struct ip_conntrack *t = (struct ip_conntrack *)data;
 
@@ -332,12 +307,18 @@
 	struct ip_conntrack_tuple_hash *h;
 	struct ip_conntrack_tuple *tuple;
 	struct nfattr *cda[CTA_MAX];
+	struct ip_conntrack *ct;
+	unsigned int *id = NULL;
 
-	ct_debug(0, "entered\n");
+	DEBUGP("entered %s\n", __FUNCTION__);
 
 	if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
 		return -EINVAL;
 
+	if (cda[CTA_ID-1] &&
+	    NFA_PAYLOAD(cda[CTA_ID-1]) < cta_min[CTA_ID-1])
+		return -EINVAL;
+
 	if (cda[CTA_ORIG-1] &&
 	    NFA_PAYLOAD(cda[CTA_ORIG-1]) < cta_min[CTA_ORIG-1])
 		return -EINVAL;
@@ -345,6 +326,9 @@
 	if (cda[CTA_RPLY-1] &&
 	    NFA_PAYLOAD(cda[CTA_RPLY-1]) < cta_min[CTA_RPLY-1])
 		return -EINVAL;
+
+	if (cda[CTA_ID-1])
+		id = NFA_DATA(cda[CTA_ID-1]);
 	
 	if (cda[CTA_ORIG-1])
 		tuple = NFA_DATA(cda[CTA_ORIG-1]);
@@ -352,52 +336,69 @@
 		if (cda[CTA_RPLY-1])
 			tuple = NFA_DATA(cda[CTA_RPLY-1]);
 		else {
-			ct_debug(0, "no tuple found in request\n");
+			DEBUGP("no tuple found in request\n");
 			return -EINVAL;
 		}
 	}
 
 	h = ip_conntrack_find_get(tuple, NULL);
 	if (!h) {
-		ct_debug(0, "tuple not found in conntrack hash:");
+		DEBUGP("tuple not found in conntrack hash:");
 		DUMP_TUPLE(tuple);
 		return -ENOENT;
 	}
 
-	ct_debug(0, "calling selective_cleanup\n");
-	ip_ct_selective_cleanup(ctnetlink_kill, h->ctrack);
-	ip_conntrack_put(h->ctrack);
+	ct = tuplehash_to_ctrack(h);
+	if (*id != ct->id) {
+		DEBUGP("matching tuple with different id: %u!=%u", *id, ct->id);
+		return -ENOENT;
+	}
+	if (del_timer(&ct->timeout)) {
+		ip_conntrack_put(ct);
+		ct->timeout.function((unsigned long)ct);
+	}
+	DEBUGP("leaving\n");
 
 	return 0;
 }
 
 static int ctnetlink_done(struct netlink_callback *cb)
 {
-	ct_debug(0, "entering\n");
+	DEBUGP("entered %s\n", __FUNCTION__);
 	return 0;
 }
 
 static int
 ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	struct ip_conntrack *ct;
+	struct ip_conntrack *ct = NULL;
+	struct ip_conntrack_tuple_hash *h;
+	struct list_head *i;
 
-	ct_debug(0, "entered, last=%lu\n", cb->args[0]);
+	DEBUGP("entered %s, last bucket=%lu id=%lu\n", __FUNCTION__, 
+			cb->args[0], cb->args[1]);
 
-	/* Traverse ordered list; send originals then reply. */
 	READ_LOCK(&ip_conntrack_lock);
-	list_for_each_entry(ct, &ip_conntrack_ordered_list, olist) {
-		if (ct->id <= cb->args[0])
-			continue;
-		if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
-		                        cb->nlh->nlmsg_seq,
-					CTNL_MSG_NEWCONNTRACK, 1, ct) < 0)
-			break;
-		cb->args[0] = ct->id;
+	for (; cb->args[0] < ip_conntrack_htable_size; 
+					cb->args[0]++, cb->args[1]=0) {
+		list_for_each(i, &ip_conntrack_hash[cb->args[0]]) {
+			h = (struct ip_conntrack_tuple_hash *) i;
+			if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
+				continue;
+			ct = tuplehash_to_ctrack(h);
+			if (ct->id <= cb->args[1])
+				continue;
+			if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
+		                        	cb->nlh->nlmsg_seq,
+						CTNL_MSG_NEWCONNTRACK,
+						1, ct) < 0)
+				break;
+			cb->args[1] = ct->id;
+		}
 	}
 	READ_UNLOCK(&ip_conntrack_lock);
-	
-	ct_debug(0, "leaving, last=%lu\n", cb->args[0]);
+
+	DEBUGP("leaving, last bucket=%lu id=%lu\n", cb->args[0], cb->args[1]);
 
 	return skb->len;
 }
@@ -412,8 +413,9 @@
 	struct ip_conntrack *ct;
 	struct sk_buff *skb2 = NULL;
 	int err;
+	unsigned int *id = NULL;
 
-	ct_debug(0, "entered\n");
+	DEBUGP("entered %s\n", __FUNCTION__);
 
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		struct nfgenmsg *msg = NLMSG_DATA(nlh);
@@ -437,6 +439,10 @@
 	if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
 		return -EINVAL;
 
+	if (cda[CTA_ID-1] &&
+	    NFA_PAYLOAD(cda[CTA_ID-1]) < cta_min[CTA_ID-1])
+		return -EINVAL;
+
 	if (cda[CTA_ORIG-1] &&
 	    NFA_PAYLOAD(cda[CTA_ORIG-1]) < cta_min[CTA_ORIG-1])
 		return -EINVAL;
@@ -444,6 +450,9 @@
 	if (cda[CTA_RPLY-1] &&
 	    NFA_PAYLOAD(cda[CTA_RPLY-1]) < cta_min[CTA_RPLY-1])
 		return -EINVAL;
+
+	if (cda[CTA_ID-1])
+		id = NFA_DATA(cda[CTA_ID-1]);
 	
 	if (cda[CTA_ORIG-1])
 		tuple = NFA_DATA(cda[CTA_ORIG-1]);
@@ -456,11 +465,17 @@
 
 	h = ip_conntrack_find_get(tuple, NULL);
 	if (!h) {
-		ct_debug(0, "tuple not found in conntrack hash:");
+		DEBUGP("tuple not found in conntrack hash:");
 		DUMP_TUPLE(tuple);
 		return -ENOENT;
 	}
-	ct = h->ctrack;
+	DEBUGP("tuple found\n");
+	ct = tuplehash_to_ctrack(h);
+
+	if (*id != ct->id) {
+		DEBUGP("matching tuple with different id: %u!=%u", *id, ct->id);
+		return -ENOENT;
+	}
 
 	skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_ATOMIC);
 	if (!skb2) {
@@ -472,12 +487,20 @@
 	err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, 
 				  CTNL_MSG_NEWCONNTRACK, 1, ct);
 	ip_conntrack_put(ct);
-	if (err <= 0)
+	if (err <= 0) {
+		DEBUGP("error filling info\n");
 		goto nlmsg_failure;
+	}
+	/* This simpifies user space handling --pablo */
+        NLMSG_PUT(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, NLMSG_DONE, 0);
 
 	err = netlink_unicast(ctnl, skb2, NETLINK_CB(skb).pid, MSG_DONTWAIT);
-	if (err < 0)
+	if (err < 0) {
+		DEBUGP("error sending skb\n");
 		return err;
+	}
+
+	DEBUGP("leaving\n");
 	return 0;
 
 nlmsg_failure:
@@ -486,6 +509,7 @@
 	return -1;
 }
 
+/* TODO: Now we have to handle NAT modifications here */
 static inline int
 ctnetlink_change_status(struct ip_conntrack *ct, unsigned long *status)
 {
@@ -516,13 +540,13 @@
 	if (cp->num_proto != proto)
 		return -EINVAL;
 
-	icp = __ip_ct_find_proto(cp->num_proto);
-	if (icp->ctnl_check_private
-	    && icp->ctnl_check_private(&cp->proto) < 0)
+	icp = ip_ct_find_proto(cp->num_proto);
+	if (icp->change_check_proto
+	    && icp->change_check_proto(&cp->proto) < 0)
 		return -EINVAL;
 
-	if (icp->ctnl_change)
-		icp->ctnl_change(ct, &cp->proto);
+	if (icp->change_proto)
+		icp->change_proto(ct, &cp->proto);
 
 	return 0;
 }
@@ -543,7 +567,7 @@
 		if (helper == NULL)
 			return -ENOENT;
 	} else if (*h->name == '\0') {
-		ip_conntrack_remove_expectations(ct, 1);
+		ip_ct_remove_expectations(ct);
 		ct->helper = NULL;
 		return 0;
 	}
@@ -553,43 +577,13 @@
 		return -EINVAL;
 
 	ct->helper = helper;
-	if (helper->ctnl_change)
-		helper->ctnl_change(ct, &h->help);
+	if (helper->change_help)
+		helper->change_help(ct, &h->help);
 
 	return 0;
 }
 
 static inline int
-ctnetlink_change_natinfo(struct ip_conntrack *ct, struct cta_nat *n)
-{
-#ifdef CONFIG_IP_NF_NAT_NEEDED
-	struct ip_nat_info *info = &ct->nat.info;
-	int i;
-
-	if (n->num_manips > IP_NAT_MAX_MANIPS)
-		return -EINVAL;
-
-	if (info->initialized && n->num_manips < info->num_manips)
-		return -EINVAL;
-
-	for (i = 0; i < n->num_manips; i++) {
-		if (n->manips[i].direction > IP_CT_DIR_MAX)
-			return -EINVAL;
-		if (n->manips[i].hooknum > NF_IP_NUMHOOKS)
-			return -EINVAL;
-		if (n->manips[i].hooknum == NF_IP_FORWARD)
-			return -EINVAL;
-		if (n->manips[i].maniptype > IP_NAT_MANIP_DST)
-			return -EINVAL;
-	}
-
-	return 0;
-#else
-	return -EOPNOTSUPP;
-#endif
-}
-
-static inline int
 ctnetlink_change_timeout(struct ip_conntrack *ct, unsigned long *timeout)
 {
 	if (!del_timer(&ct->timeout))
@@ -605,8 +599,8 @@
 {
 	void *data;
 	int err;
-	
-	ct_debug(0, "entered\n");
+
+	DEBUGP("entered %s\n", __FUNCTION__);
 
 	if (cda[CTA_STATUS-1]) {
 		data = NFA_DATA(cda[CTA_STATUS-1]);
@@ -623,18 +617,13 @@
 		if ((err = ctnetlink_change_helpinfo(ct, data)) < 0)
 			return err;
 	}
-	if (cda[CTA_NATINFO-1]) {
-		data = NFA_DATA(cda[CTA_NATINFO-1]);
-		if ((err = ctnetlink_change_natinfo(ct, data)) < 0)
-			return err;
-	}
 	if (cda[CTA_TIMEOUT-1]) {
 		data = NFA_DATA(cda[CTA_TIMEOUT-1]);
 		if ((err = ctnetlink_change_timeout(ct, data)) < 0)
 			return err;
 	}
 
-	ct_debug(0, "all done\n");
+	DEBUGP("all done\n");
 	return 0;
 }
 
@@ -642,18 +631,19 @@
 ctnetlink_create_conntrack(struct nfattr *cda[])
 {
 	struct ip_conntrack *ct;
-	struct ip_conntrack_tuple *otuple, *rtuple, t;
+	struct ip_conntrack_tuple *otuple, *rtuple;
 	struct ip_conntrack_protocol *icp;
 	struct cta_proto *proto;
 	unsigned long *status;
 	unsigned long *timeout;
 	int err;
+	unsigned int hash, hash_repl;
 
-	ct_debug(0, "entered\n");
+	DEBUGP("entered %s\n", __FUNCTION__);
 
 	if (!(cda[CTA_ORIG-1] && cda[CTA_RPLY-1] && cda[CTA_STATUS-1] &&
 	      cda[CTA_PROTOINFO-1] && cda[CTA_TIMEOUT-1])) {
-		ct_debug(0, "required attribute(s) missing\n");
+		DEBUGP("required attribute(s) missing\n");
 		return -EINVAL;
 	}
 
@@ -661,22 +651,20 @@
 	rtuple  = NFA_DATA(cda[CTA_RPLY-1]);
 	timeout = NFA_DATA(cda[CTA_TIMEOUT-1]);
 
-	status  = NFA_DATA(cda[CTA_STATUS-1]);
+	status = NFA_DATA(cda[CTA_STATUS-1]);
+	/* cannot create unconfirmed connections */
 	if (!(*status & IPS_CONFIRMED))
-		return -EINVAL;	/* cannot create unconfirmed connections */
+		return -EINVAL;	
 
 	proto = NFA_DATA(cda[CTA_PROTOINFO-1]);
-	icp   = __ip_ct_find_proto(proto->num_proto);
-
-	if (!invert_tuple(&t, otuple, icp) || !ip_ct_tuple_equal(&t, rtuple))
-		; // FIXME: nat changes reply tuples // return -EINVAL;
+	icp   = ip_ct_find_proto(proto->num_proto);
 
-	if (icp->ctnl_check_tuples
-	    && icp->ctnl_check_tuples(otuple, rtuple) < 0)
+	if (icp->change_check_tuples
+	    && icp->change_check_tuples(otuple, rtuple) < 0)
 		return -EINVAL;
 	
-	if (icp->ctnl_check_private
-	    && icp->ctnl_check_private(&proto->proto) < 0)
+	if (icp->change_check_proto
+	    && icp->change_check_proto(&proto->proto) < 0)
 		return -EINVAL;
 
 	ct = ip_conntrack_alloc(otuple, rtuple);
@@ -686,9 +674,10 @@
 	ct->status = *status;
 	ct->timeout.expires = jiffies + *timeout * HZ;
 
-	if (icp->ctnl_change)
-		icp->ctnl_change(ct, &proto->proto);
+	if (icp->change_proto)
+		icp->change_proto(ct, &proto->proto);
 
+	/* FIXME: Split function to NEW and CHANGE */
 	cda[CTA_ORIG-1] = cda[CTA_RPLY-1] = cda[CTA_PROTOINFO-1] = 
 		cda[CTA_STATUS-1] = cda[CTA_TIMEOUT-1] = NULL;
 
@@ -698,10 +687,12 @@
 		return err;
 	}
 
-	ip_conntrack_place_in_lists(ct);
+	hash = hash_conntrack(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
+	hash_repl = hash_conntrack(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
+	ip_conntrack_insert(ct, hash, hash_repl);
 	add_timer(&ct->timeout);
 
-	ct_debug(0, "all done\n");
+	DEBUGP("all done\n");
 	return 0;
 }
 
@@ -714,16 +705,19 @@
 	struct ip_conntrack_tuple_hash *h = NULL;
 	int i, err = 0;
 
-	ct_debug(0, "entered\n");
+	DEBUGP("entered %s\n", __FUNCTION__);
 
 	if (nfnetlink_check_attributes(ctnl_subsys, nlh, cda) < 0)
 		return -EINVAL;
 
 	for (i = 0; i < CTA_MAX; i++)
-		if (cda[i] && NFA_PAYLOAD(cda[i]) < cta_min[i])
+		if (cda[i] && NFA_PAYLOAD(cda[i]) < cta_min[i]) {
+			DEBUGP("attribute %u has incorrect size %u<%u\n", 
+				i, NFA_PAYLOAD(cda[i]), cta_min[i]);
 			return -EINVAL;
+		}
 
-	ct_debug(0, "all attribute sizes ok\n");
+	DEBUGP("all attribute sizes ok\n");
 
 	if (cda[CTA_ORIG-1])
 		otuple = NFA_DATA(cda[CTA_ORIG-1]);
@@ -732,33 +726,36 @@
 		rtuple = NFA_DATA(cda[CTA_RPLY-1]);
 
 	if (otuple == NULL && rtuple == NULL) {
-		ct_debug(0, "no tuple found in request\n");
+		DEBUGP("no tuple found in request\n");
 		return -EINVAL;
 	}
 
-	WRITE_LOCK(&ip_conntrack_lock);
+	/* If we create a conntrack, it isn't in the hashed yet so
+	 * no need to lock. Split this function in two. */
 	if (otuple)
-		h = __ip_conntrack_find_get(otuple, NULL);
+		h = ip_conntrack_find_get(otuple, NULL);
 	if (h == NULL && rtuple)
-		h = __ip_conntrack_find_get(rtuple, NULL);
+		h = ip_conntrack_find_get(rtuple, NULL);
 
+	WRITE_LOCK(&ip_conntrack_lock);
 	if (h == NULL) {
-		ct_debug(0, "no such conntrack, create new\n");
+		DEBUGP("no such conntrack, create new\n");
 		err = -ENOENT;
 		if (!(nlh->nlmsg_flags & NLM_F_CREATE))
 			goto out_unlock;
 		err = ctnetlink_create_conntrack(cda);
+
 		goto out_unlock;
 	} else {
-		ct_debug(0, "conntrack found, change\n");
+		DEBUGP("conntrack found, change\n");
 		err = -EEXIST;
 		if (nlh->nlmsg_flags & NLM_F_EXCL)
 			goto out_put;
-		err = ctnetlink_change_conntrack(h->ctrack, cda);
+		err = ctnetlink_change_conntrack(tuplehash_to_ctrack(h), cda);
 	}
 
 out_put:
-	ip_conntrack_put(h->ctrack);
+	ip_conntrack_put(tuplehash_to_ctrack(h));
 out_unlock:
 	WRITE_UNLOCK(&ip_conntrack_lock);
 	return err;
@@ -781,10 +778,10 @@
 }
 
 static inline int
-ctnetlink_exp_dump_seqno(struct sk_buff *skb,
-                         const struct ip_conntrack_expect *exp)
+ctnetlink_exp_dump_timeout(struct sk_buff *skb, 
+			   const struct ip_conntrack_expect *exp)
 {
-	NFA_PUT(skb, CTA_EXP_SEQNO, sizeof(u_int32_t), &exp->seq);
+	NFA_PUT(skb, CTA_EXP_TIMEOUT, sizeof(unsigned long), &exp->timeout);
 	return 0;
 	
 nfattr_failure:
@@ -798,21 +795,6 @@
 	return 0;
 }
 
-static inline int
-ctnetlink_exp_dump_help(struct sk_buff *skb,
-                        const struct ip_conntrack_expect *exp)
-{
-	struct cta_exp_help ch;
-
-	memcpy(&ch.help, &exp->help, sizeof(ch.help));
-	NFA_PUT(skb, CTA_EXP_HELP, sizeof(union ip_conntrack_expect_help),
-	        &exp->help);
-	return 0;
-	
-nfattr_failure:
-	return -1;
-}
-
 static int
 ctnetlink_exp_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
 		    int event, 
@@ -833,9 +815,7 @@
 	nfmsg->nfgen_family = AF_INET;
 
 	if (ctnetlink_exp_dump_tuples(skb, exp) < 0 ||
-	    ctnetlink_exp_dump_seqno(skb, exp) < 0 ||
-	    ctnetlink_exp_dump_proto(skb, exp) < 0 ||
-	    ctnetlink_exp_dump_help(skb, exp) < 0)
+	    ctnetlink_exp_dump_timeout(skb, exp) < 0)
 		goto nfattr_failure;
 
 	nlh->nlmsg_len = skb->tail - b;
@@ -867,7 +847,7 @@
 		kfree_skb(skb);
 	return NULL;
 }
-
+/*
 static void
 ctnetlink_exp_create(struct ip_conntrack_expect *exp)
 {
@@ -893,7 +873,7 @@
 	}
 	kfree_skb(skb);
 	return;
-}
+}*/
 
 static int
 ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, 
@@ -931,7 +911,7 @@
 	/* after list removal, usage count == 1 */
 	ip_conntrack_unexpect_related(exp);
 	/* we have put what we 'get' above. after this line usage count == 0 */
-	ip_conntrack_expect_put(exp);
+	ip_conntrack_expect_free(exp);
 
 	return 0;
 }
@@ -958,7 +938,7 @@
 static int
 ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 {
-	ct_debug(0, "entered\n");
+	DEBUGP("entered %s\n", __FUNCTION__);
 	if (cb->args[0] == 0) {
 		READ_LOCK(&ip_conntrack_lock);
 		LIST_FIND(&ip_conntrack_expect_list, 
@@ -968,7 +948,7 @@
 		READ_UNLOCK(&ip_conntrack_lock);
 		cb->args[0] = 1;
 	}
-	ct_debug(0, "returning\n");
+	DEBUGP("returning\n");
 
 	return skb->len;
 }
@@ -984,8 +964,7 @@
 	struct sk_buff *skb2 = NULL;
 	int err, proto;
 
-	ct_debug(0, "entered\n");
-
+	DEBUGP("entered %s\n", __FUNCTION__);
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		struct nfgenmsg *msg = NLMSG_DATA(nlh);
 		u32 rlen;
@@ -993,7 +972,7 @@
 		if (msg->nfgen_family != AF_INET)
 			return -EAFNOSUPPORT;
 
-		ct_debug(0, "starting dump\n");
+		DEBUGP("starting dump\n");
 			if ((*errp = netlink_dump_start(ctnl, skb, nlh,
 		    				ctnetlink_exp_dump_table,
 						ctnetlink_done)) != 0)
@@ -1065,15 +1044,15 @@
 	struct ip_conntrack_tuple *tuple, *mask;
 	struct ip_conntrack_tuple *orig, *reply;
 	struct ip_conntrack_tuple_hash *h = NULL;
-	struct ip_conntrack_expect exp, *new;
+	struct ip_conntrack_expect *exp;
 	struct ip_conntrack_helper *helper;
 	unsigned long timeout;
 	int err;
 
-	ct_debug(0, "entered\n");
+	DEBUGP("entered %s\n", __FUNCTION__);
 
 	if (!(cda[CTA_ORIG-1] || cda[CTA_RPLY-1])) {
-		ct_debug(0, "required attributes missing\n");
+		DEBUGP("required attributes missing\n");
 		return -EINVAL;
 	}
 
@@ -1082,21 +1061,13 @@
 	orig  = NFA_DATA(cda[CTA_ORIG-1]);
 	reply = NFA_DATA(cda[CTA_RPLY-1]);
 
-	memcpy(&exp.tuple, tuple, sizeof(struct ip_conntrack_tuple));
-	memcpy(&exp.mask, mask, sizeof(struct ip_conntrack_tuple));
-
-	exp.expectfn = NULL;
-
-	if (cda[CTA_EXP_SEQNO-1])
-		exp.seq = *(u_int32_t *)NFA_DATA(cda[CTA_EXP_SEQNO-1]);
-
-	h = __ip_conntrack_find_get(orig, NULL);
+	h = ip_conntrack_find_get(orig, NULL);
 	if (h == NULL)
-		h = __ip_conntrack_find_get(reply, NULL);
+		h = ip_conntrack_find_get(reply, NULL);
 	if (h == NULL)
 		return -ENOENT;
 
-	helper = h->ctrack->helper;
+	helper = tuplehash_to_ctrack(h)->helper;
 
 	if (cda[CTA_EXP_TIMEOUT-1])
 		timeout = *(unsigned long *)NFA_DATA(cda[CTA_EXP_TIMEOUT-1]);
@@ -1105,24 +1076,21 @@
 	else
 		return -EINVAL;
 
-	if (helper && helper->ctnl_new_expect) {
-		struct cta_exp_proto *cp = NULL;
-		struct cta_exp_help *ch = NULL;
-
-		if (cda[CTA_EXP_PROTO-1])
-			cp = NFA_DATA(cda[CTA_EXP_PROTO-1]);
-		if (cda[CTA_EXP_HELP-1])
-			ch = NFA_DATA(cda[CTA_EXP_HELP-1]);
-		
-		helper->ctnl_new_expect(&exp, &cp->proto, &ch->help);
-	}
+	exp = ip_conntrack_expect_alloc();
+	if (!exp)
+		return -ENOMEM;
+	
+	exp->expectfn = NULL;
+	exp->master = tuplehash_to_ctrack(h);
+	memcpy(&exp->tuple, tuple, sizeof(struct ip_conntrack_tuple));
+	memcpy(&exp->mask, mask, sizeof(struct ip_conntrack_tuple));
 
-	err = __ip_conntrack_expect_related(h->ctrack, &exp, &new);
+	err = ip_conntrack_expect_related(exp);
 	if (err < 0)
 		return err;
 	
-	new->timeout.expires = jiffies + timeout * HZ;
-	add_timer(&new->timeout);
+	exp->timeout.expires = jiffies + timeout * HZ;
+	add_timer(&exp->timeout);
 	return 0;
 }
 
@@ -1149,7 +1117,8 @@
 	mask  = NFA_DATA(cda[CTA_EXP_MASK-1]);
 
 	WRITE_LOCK(&ip_conntrack_lock);
-	exp = __ip_ct_expect_find_tm(tuple, mask);
+	
+	exp = ip_conntrack_expect_find_get(tuple);
 
 	if (exp == NULL) {
 		err = -ENOENT;
@@ -1180,7 +1149,7 @@
 {
 	printk("ctnetlink: unregistering with nfnetlink.\n");
 //	ip_conntrack_notify_unregister(&ctnl_exp_notify);
-	ip_conntrack_notify_unregister(&ctnl_notifier);
+	ip_conntrack_unregister_notifier(&ctnl_notifier);
 	nfnetlink_subsys_unregister(ctnl_subsys);
 	kfree(ctnl_subsys);
 	return;
@@ -1219,7 +1188,7 @@
 		goto err_free_subsys;
 	}
 
-	if ((ret = ip_conntrack_notify_register(&ctnl_notifier)) < 0) {
+	if ((ret = ip_conntrack_register_notifier(&ctnl_notifier)) < 0) {
 		printk("ctnetlink_init: cannot register notifier.\n");
 		goto err_unreg_subsys;
 	}
--- linux-2.5/include/linux/nfnetlink_conntrack.h.orig	2005-03-07 20:40:54.000000000 +0100
+++ linux-2.5/include/linux/nfnetlink_conntrack.h	2005-03-28 00:11:39.000000000 +0200
@@ -5,6 +5,12 @@
 
 /* CTNETLINK for ip_conntrack */
 
+/* TODO: Add more message types:
+ *
+ * 	o CTNL_MSG_UPDCONNTRACK, update conntracks
+ * 	o CTNL_MSG_DMPCONNTRACK, dump conntrack table
+ * 	o CTNL_MSG_FSHCONNTRACK, flush conntrack table
+ */
 enum cntl_msg_types {
 	CTNL_MSG_NEWCONNTRACK,
 	CTNL_MSG_GETCONNTRACK,
@@ -28,15 +34,14 @@
 	CTA_STATUS,     /* [unsigned long] Status of connection. */
 	CTA_PROTOINFO,  /* [cta_proto] Protocol specific ct information. */
 	CTA_HELPINFO,   /* [cta_help] Helper specific information. */
-	CTA_NATINFO,    /* [cta_nat] Any NAT transformations. */
 	CTA_TIMEOUT,    /* [unsigned long] timer */
 	CTA_MARK,       /* [unsigned long] mark .*/
+	CTA_ID,		/* [unsigned int] id */
 	
 	CTA_EXP_TUPLE,	/* [ip_conntrack_tuple] Expected tuple */
 	CTA_EXP_MASK,	/* [ip_conntrack_tuple] Mask for EXP_TUPLE */
 	CTA_EXP_SEQNO,	/* [u_int32_t] sequence number */
 	CTA_EXP_PROTO,	/* [cta_exp_proto] */
-	CTA_EXP_HELP,	/* [cta_exp_help] */
 	CTA_EXP_TIMEOUT,/* [unsigned long] timer */
 
 	CTA_MAX = CTA_EXP_TIMEOUT
@@ -45,12 +50,6 @@
 /* Attribute specific data structures.
  */
 
-#include <linux/netfilter_ipv4/ip_nat.h>
-struct cta_nat {
-	unsigned int num_manips;
-	struct ip_nat_info_manip manips[IP_NAT_MAX_MANIPS];
-};
-
 struct cta_proto {
 	unsigned char num_proto;	/* Protocol number IPPROTO_X */
 	union ip_conntrack_proto proto;
@@ -67,10 +66,6 @@
 	union ip_conntrack_expect_proto proto;
 };
 
-struct cta_exp_help {
-	union ip_conntrack_expect_help help;
-};
-
 /* ctnetlink multicast groups: reports any change of ctinfo,
  * ctstatus, or protocol state change.
  */

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH 2/2] Port nfnetlink and nfnetlink_conntrack to 2.6
  2005-03-27 23:56 [PATCH 2/2] Port nfnetlink and nfnetlink_conntrack to 2.6 Pablo Neira
@ 2005-03-30 15:57 ` Wang Jian
  0 siblings, 0 replies; 2+ messages in thread
From: Wang Jian @ 2005-03-30 15:57 UTC (permalink / raw)
  To: Netfilter Development Mailinglist

Hi Pablo Neira,

I want to use nfnetlink-ctnetlink to keep track of successful session in
a project. Can you make it avaible in pom-ng?

Thanks.

On Mon, 28 Mar 2005 01:56:15 +0200, Pablo Neira <pablo@eurodev.net> wrote:

> Comments about changes:
> 
> o Minor change: my compiler (gcc-2.95) complained about ct_debug so I 
> inserted the classical DEBUGP macro.
> 
> o No important modifications in nfnetlink.c
> 
> o Added support to identify conntracks by id.
> 
> o Removed ordered list, now we just insert a unsigned int in struct 
> ip_conntrack to hold the id. Now the table dumping is done iterating the 
> hash table.
> 
> o Adaptation to ct-event API
> 
> o improved way to delete a conntrack (marcus sundberg)
> 
> o kill [dump|change]_natinfo, now that must be handle in 
> [dump|change]_status.
> 
> o IMPORTANT: I haven't tested expectation handling.
> 
> Things I consider to do:
> 
> o split CTNL_MSG_GETCONNTRACK to two messages types: 
> CTNL_MSG_GETCONNTRACK and CTNL_MSG_DMPCONNTRACK (dump)
> 
> o split CTNL_MSG_NEWCONNTRACK to two messages types: 
> CTNL_MSG_NEWCONNTRACK and CTNL_MSG_UPDCONNTRACK (update)
> 
> o Move nfnetlink.h and nfnetlink_conntrack.h to netfilter/ directory.



-- 
  lark

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2005-03-30 15:57 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-27 23:56 [PATCH 2/2] Port nfnetlink and nfnetlink_conntrack to 2.6 Pablo Neira
2005-03-30 15:57 ` Wang Jian

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.