Skip to contentSkip to conversation

ctnetlink port to nf_conntrack take #3

RFC PATCH Applied Pablo Neira Ayuso 4 participants 13 messages Dec 5, 2005 – Jan 6, 2006 2 messages not in the archive

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 ctnetlink port to nf_conntrack take #3

Hi!

Attached the 3rd incarnation of the ctnetlink port to nf_conntrack, it includes all recent Patrick's bugfixes and Yasuyuki's comments.

nf_conntrack_netlink.c is available at:
http://people.netfilter.org/pablo/nf_conntrack_netlink.c

Signature · 1 line
Pablo
include/net/netfilter/nf_conntrack.h +31 -0
index cc48256..64b82b7 100644
@@ -94,6 +94,9 @@ struct nf_conn
 	/* Current number of expected connections */
 	unsigned int expecting;
 
+	/* Unique ID that identifies this conntrack*/
+	unsigned int id;
+
 	/* Helper. if any */
 	struct nf_conntrack_helper *helper;
 
@@ -140,6 +143,9 @@ struct nf_conntrack_expect
 	/* Usage count. */
 	atomic_t use;
 
+	/* Unique ID */
+	unsigned int id;
+
 	/* Flags */
 	unsigned int flags;
 
@@ -190,6 +196,31 @@ static inline void nf_ct_put(struct nf_c
 	nf_conntrack_put(&ct->ct_general);
 }
 
+extern struct nf_conntrack_tuple_hash *
+__nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
+		    const struct nf_conn *ignored_conntrack);
+
+extern void nf_conntrack_hash_insert(struct nf_conn *ct);
+
+extern struct nf_conntrack_expect *
+__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+
+extern struct nf_conntrack_expect *
+nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+
+extern void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
+
+extern void nf_ct_remove_expectations(struct nf_conn *ct);
+
+extern void nf_conntrack_flush(void);
+
+extern struct nf_conntrack_helper *
+nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple);
+extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
+
+extern struct nf_conntrack_helper *
+__nf_conntrack_helper_find_byname(const char *name);
+
 /* call to create an explicit dependency on nf_conntrack. */
 extern void need_nf_conntrack(void);
 
include/net/netfilter/nf_conntrack_helper.h +2 -0
index 5a66b2a..86ec817 100644
@@ -33,6 +33,8 @@ struct nf_conntrack_helper
 		    unsigned int protoff,
 		    struct nf_conn *ct,
 		    enum ip_conntrack_info conntrackinfo);
+
+	int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct);
 };
 
 extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
include/net/netfilter/nf_conntrack_l3proto.h +14 -1
index 01663e5..67856eb 100644
@@ -14,6 +14,8 @@
 #include <linux/seq_file.h>
 #include <net/netfilter/nf_conntrack.h>
 
+struct nfattr;
+
 struct nf_conntrack_l3proto
 {
 	/* Next pointer. */
@@ -70,6 +72,12 @@ struct nf_conntrack_l3proto
 
 	u_int32_t (*get_features)(const struct nf_conntrack_tuple *tuple);
 
+	int (*tuple_to_nfattr)(struct sk_buff *skb,
+			       const struct nf_conntrack_tuple *t);
+
+	int (*nfattr_to_tuple)(struct nfattr *tb[],
+			       struct nf_conntrack_tuple *t);
+
 	/* Module (if any) which this is connected to. */
 	struct module *me;
 };
@@ -81,11 +89,16 @@ extern int nf_conntrack_l3proto_register
 extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
 
 static inline struct nf_conntrack_l3proto *
-nf_ct_find_l3proto(u_int16_t l3proto)
+__nf_ct_l3proto_find(u_int16_t l3proto)
 {
 	return nf_ct_l3protos[l3proto];
 }
 
+extern struct nf_conntrack_l3proto *
+nf_ct_l3proto_find_get(u_int16_t l3proto);
+
+extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
+
 /* Existing built-in protocols */
 extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
 extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
include/net/netfilter/nf_conntrack_protocol.h +25 -1
index b3afda3..1f33737 100644
@@ -12,6 +12,7 @@
 #include <net/netfilter/nf_conntrack.h>
 
 struct seq_file;
+struct nfattr;
 
 struct nf_conntrack_protocol
 {
@@ -66,6 +67,18 @@ struct nf_conntrack_protocol
 		     enum ip_conntrack_info *ctinfo,
 		     int pf, unsigned int hooknum);
 
+	/* convert protoinfo to nfnetink attributes */
+	int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
+			 const struct nf_conn *ct);
+
+	/* convert nfnetlink attributes to protoinfo */
+	int (*from_nfattr)(struct nfattr *tb[], struct nf_conn *ct);
+
+	int (*tuple_to_nfattr)(struct sk_buff *skb,
+			       const struct nf_conntrack_tuple *t);
+	int (*nfattr_to_tuple)(struct nfattr *tb[],
+			       struct nf_conntrack_tuple *t);
+
 	/* Module (if any) which this is connected to. */
 	struct module *me;
 };
@@ -80,12 +93,23 @@ extern struct nf_conntrack_protocol nf_c
 extern struct nf_conntrack_protocol **nf_ct_protos[PF_MAX];
 
 extern struct nf_conntrack_protocol *
-nf_ct_find_proto(u_int16_t l3proto, u_int8_t protocol);
+__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol);
+
+extern struct nf_conntrack_protocol *
+nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol);
+
+extern void nf_ct_proto_put(struct nf_conntrack_protocol *p);
 
 /* Protocol registration. */
 extern int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto);
 extern void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto);
 
+/* Generic netlink helpers */
+extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
+				      const struct nf_conntrack_tuple *tuple);
+extern int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[],
+				      struct nf_conntrack_tuple *t);
+
 /* Log invalid packets */
 extern unsigned int nf_ct_log_invalid;
 
include/net/netfilter/nf_conntrack_tuple.h +0 -0
net/ipv4/netfilter/ip_conntrack_netlink.c +0 -0
net/ipv4/netfilter/ip_conntrack_proto_icmp.c +0 -0
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +47 -0

59 lines not on this page · raw message

net/ipv4/netfilter/nf_conntrack_proto_icmp.c +67 -8

103 lines not on this page · raw message

net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +47 -0

59 lines not on this page · raw message

net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +1 -1
index c0f1da5..00574f7 100644
@@ -185,7 +185,7 @@ icmpv6_error_message(struct sk_buff *skb
 		return -NF_ACCEPT;
 	}
 
-	inproto = nf_ct_find_proto(PF_INET6, inprotonum);
+	inproto = __nf_ct_proto_find(PF_INET6, inprotonum);
 
 	/* Are they talking about one of our connections? */
 	if (!nf_ct_get_tuple(skb, inip6off, inprotoff, PF_INET6, inprotonum,
net/netfilter/Kconfig +7 -0
index a84f922..d6a0b96 100644
@@ -95,4 +95,11 @@ config NF_CONNTRACK_FTP
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NF_CT_NETLINK
+	tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
+	depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK
+	depends on NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
+	help
+	  This option enables support for a netlink-based userspace interface
+
 endmenu
net/netfilter/Makefile +3 -0
index 55f019a..cb21831 100644
@@ -13,3 +13,6 @@ obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_con
 
 # SCTP protocol connection tracking
 obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
+
+# netlink interface for nf_conntrack
+obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
net/netfilter/nf_conntrack_core.c +208 -24

390 lines not on this page · raw message

net/netfilter/nf_conntrack_proto_tcp.c +71 -0

89 lines not on this page · raw message

net/netfilter/nf_conntrack_proto_udp.c +10 -0
index 3cae7ce..1a592a5 100644
@@ -196,6 +196,11 @@ struct nf_conntrack_protocol nf_conntrac
 	.packet			= udp_packet,
 	.new			= udp_new,
 	.error			= udp_error4,
+#if defined(CONFIG_NF_CT_NETLINK) || \
+    defined(CONFIG_NF_CT_NETLINK_MODULE)
+	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
+	.nfattr_to_tuple	= nf_ct_port_nfattr_to_tuple,
+#endif
 };
 
 struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
@@ -210,6 +215,11 @@ struct nf_conntrack_protocol nf_conntrac
 	.packet			= udp_packet,
 	.new			= udp_new,
 	.error			= udp_error6,
+#if defined(CONFIG_NF_CT_NETLINK) || \
+    defined(CONFIG_NF_CT_NETLINK_MODULE)
+	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
+	.nfattr_to_tuple	= nf_ct_port_nfattr_to_tuple,
+#endif
 };
 
 EXPORT_SYMBOL(nf_conntrack_protocol_udp4);
net/netfilter/nf_conntrack_standalone.c +29 -10
index 5af381f..4c82f37 100644
@@ -161,14 +161,14 @@ static int ct_seq_show(struct seq_file *
 	if (NF_CT_DIRECTION(hash))
 		return 0;
 
-	l3proto = nf_ct_find_l3proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
-				     .tuple.src.l3num);
+	l3proto = __nf_ct_l3proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
+				       .tuple.src.l3num);
 
 	NF_CT_ASSERT(l3proto);
-	proto = nf_ct_find_proto(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
-				 .tuple.src.l3num,
-				 conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
-				 .tuple.dst.protonum);
+	proto = __nf_ct_proto_find(conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
+				   .tuple.src.l3num,
+				   conntrack->tuplehash[IP_CT_DIR_ORIGINAL]
+				   .tuple.dst.protonum);
 	NF_CT_ASSERT(proto);
 
 	if (seq_printf(s, "%-8s %u %-8s %u %ld ",
@@ -307,9 +307,9 @@ static int exp_seq_show(struct seq_file 
 		   expect->tuple.src.l3num,
 		   expect->tuple.dst.protonum);
 	print_tuple(s, &expect->tuple,
-		    nf_ct_find_l3proto(expect->tuple.src.l3num),
-		    nf_ct_find_proto(expect->tuple.src.l3num,
-				     expect->tuple.dst.protonum));
+		    __nf_ct_l3proto_find(expect->tuple.src.l3num),
+		    __nf_ct_proto_find(expect->tuple.src.l3num,
+				       expect->tuple.dst.protonum));
 	return seq_putc(s, '\n');
 }
 
@@ -847,7 +847,11 @@ EXPORT_SYMBOL(nf_conntrack_helper_unregi
 EXPORT_SYMBOL(nf_ct_iterate_cleanup);
 EXPORT_SYMBOL(__nf_ct_refresh_acct);
 EXPORT_SYMBOL(nf_ct_protos);
-EXPORT_SYMBOL(nf_ct_find_proto);
+EXPORT_SYMBOL(__nf_ct_proto_find);
+EXPORT_SYMBOL(nf_ct_proto_find_get);
+EXPORT_SYMBOL(nf_ct_proto_put);
+EXPORT_SYMBOL(nf_ct_l3proto_find_get);
+EXPORT_SYMBOL(nf_ct_l3proto_put);
 EXPORT_SYMBOL(nf_ct_l3protos);
 EXPORT_SYMBOL(nf_conntrack_expect_alloc);
 EXPORT_SYMBOL(nf_conntrack_expect_put);
@@ -867,3 +871,18 @@ EXPORT_SYMBOL(nf_ct_get_tuple);
 EXPORT_SYMBOL(nf_ct_invert_tuple);
 EXPORT_SYMBOL(nf_conntrack_in);
 EXPORT_SYMBOL(__nf_conntrack_attach);
+EXPORT_SYMBOL(nf_conntrack_alloc);
+EXPORT_SYMBOL(nf_conntrack_free);
+EXPORT_SYMBOL(nf_conntrack_flush);
+EXPORT_SYMBOL(nf_ct_remove_expectations);
+EXPORT_SYMBOL(nf_ct_helper_find_get);
+EXPORT_SYMBOL(nf_ct_helper_put);
+EXPORT_SYMBOL(__nf_conntrack_helper_find_byname);
+EXPORT_SYMBOL(__nf_conntrack_find);
+EXPORT_SYMBOL(nf_ct_unlink_expect);
+EXPORT_SYMBOL(nf_conntrack_hash_insert);
+EXPORT_SYMBOL(__nf_conntrack_expect_find);
+EXPORT_SYMBOL(nf_conntrack_expect_find);
+EXPORT_SYMBOL(nf_conntrack_expect_list);
+EXPORT_SYMBOL(nf_ct_port_tuple_to_nfattr);
+EXPORT_SYMBOL(nf_ct_port_nfattr_to_tuple);
#1 lore raw

Hi, Pablo,

From: Pablo Neira Ayuso <[email protected]>
Date: Mon, 05 Dec 2005 11:42:47 +0100

Quoted 5 lines

Attached the 3rd incarnation of the ctnetlink port to nf_conntrack, it includes all recent Patrick's bugfixes and Yasuyuki's comments.

nf_conntrack_netlink.c is available at:
http://people.netfilter.org/pablo/nf_conntrack_netlink.c

Great work.

I have 2 more comments as follows. I'll send patches for them and adding support for ICMPv6 in other mails.

Quoted 14 lines
net/ipv4/netfilter/nf_conntrack_proto_icmp.c +14 -0
+static int icmp_nfattr_to_tuple(struct nfattr *tb[],
+				struct nf_conntrack_tuple *tuple)
+{
+	if (!tb[CTA_PROTO_ICMP_TYPE-1]
+	    || !tb[CTA_PROTO_ICMP_CODE-1]
+	    || !tb[CTA_PROTO_ICMP_ID-1])
+		return -EINVAL;
+
+	if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto))
+		return -EINVAL;
+
+	tuple->dst.u.icmp.type = 
+			*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_TYPE-1]);
+	tuple->dst.u.icmp.code =

net/ipv4/netfilter/nf_conntrack_proto_icmp.c checksum_skipped: · line 335

Quoted 10 lines
net/ipv4/netfilter/nf_conntrack_proto_icmp.c +10 -0
+			*(u_int8_t *)NFA_DATA(tb[CTA_PROTO_ICMP_CODE-1]);
+	tuple->src.u.icmp.id =
+			*(u_int16_t *)NFA_DATA(tb[CTA_PROTO_ICMP_ID-1]);
+
+	if (tuple->dst.u.icmp.type >= sizeof(valid_new)
+	    || !valid_new[tuple->dst.u.icmp.type])
+		return -EINVAL;
+
+	return 0;
+}

This rejects tuples for replying like Echo reply. How about invmap instead of valid_new ?

This can be said about the resent patch for "ip_conntrack"_netlink from you. I'll also send patch for it.

net/netfilter/nf_conntrack_standalone.c EXPORT_SYMBOL(nf_ct_get_tuple); · line 888

Quoted 6 lines
net/netfilter/nf_conntrack_standalone.c +6 -0
+EXPORT_SYMBOL(nf_conntrack_hash_insert);
+EXPORT_SYMBOL(__nf_conntrack_expect_find);
+EXPORT_SYMBOL(nf_conntrack_expect_find);
+EXPORT_SYMBOL(nf_conntrack_expect_list);
+EXPORT_SYMBOL(nf_ct_port_tuple_to_nfattr);
+EXPORT_SYMBOL(nf_ct_port_nfattr_to_tuple);

nf_ct_port_{tuple_to_nfattr,nfattr_to_tuple} should be surrouned with CONFIG_NF_CT_NETLINK.

Regards,

-- Yasuyuki Kozakai

A message that is not in the archive (sent off-list or not yet received): [email protected]

#3 lore raw
Quoted 10 lines · Yasuyuki KOZAKAI
Quoted 5 lines

Attached the 3rd incarnation of the ctnetlink port to nf_conntrack, it includes all recent Patrick's bugfixes and Yasuyuki's comments.

nf_conntrack_netlink.c is available at:
http://people.netfilter.org/pablo/nf_conntrack_netlink.c

Great work.

I have 2 more comments as follows. I'll send patches for them and adding support for ICMPv6 in other mails.

Apart from these minor issues, I'm fine with the patch too. I'll apply it tommorrow if noone objects.

#4 lore raw

From: Patrick McHardy <[email protected]>
Date: Thu, 15 Dec 2005 02:30:49 +0100

Quoted 7 lines
Quoted 6 lines · Yasuyuki KOZAKAI
Quoted 5 lines

Attached the 3rd incarnation of the ctnetlink port to nf_conntrack, it includes all recent Patrick's bugfixes and Yasuyuki's comments.

nf_conntrack_netlink.c is available at:
http://people.netfilter.org/pablo/nf_conntrack_netlink.c

Quoted 7 lines
Quoted 4 lines

Great work.

I have 2 more comments as follows. I'll send patches for them and adding support for ICMPv6 in other mails.

Apart from these minor issues, I'm fine with the patch too. I'll apply it tommorrow if noone objects.

Well, I've found a issue. Current dumping code returns the informations about IPv6 connections regardless of the address family in nfctnetlink header (nfgenmsg). As a result, conntrack program prints "0.0.0.0 ....."

A something like filtering with address family might be necessary while dumping. Yes, that would be inefficient. One long term solution would be conntrack hash per layer 3 protocol.

The handling for other requests seem not to have this issue. Because they make tuple which includes l3num and it is set to the address family in nfctnetlink header. This means that just only requested layer 3 protocol for connection can be handled.

-- Yasuyuki Kozakai

A message that is not in the archive (sent off-list or not yet received): [email protected]

#6 lore raw
Quoted 7 lines · Yasuyuki KOZAKAI

Well, I've found a issue. Current dumping code returns the informations about IPv6 connections regardless of the address family in nfctnetlink header (nfgenmsg). As a result, conntrack program prints "0.0.0.0 ....."

A something like filtering with address family might be necessary while dumping. Yes, that would be inefficient. One long term solution would be conntrack hash per layer 3 protocol.

The filtering sounds fine for now. Dumping already has a large overhead because the repeated iterations over the entire hash to find out where to continue after an skb was full, this is not going to make it much worse. I'm going to fix it up when adding the patch.

#7 lore raw

Hi Patrick,

Quoted 7 lines · Patrick McHardy
Quoted 5 lines · Yasuyuki KOZAKAI

Well, I've found a issue. Current dumping code returns the informations about
IPv6 connections regardless of the address family in nfctnetlink header (nfgenmsg). As a result, conntrack program prints "0.0.0.0 ....."

Quoted 8 lines
Quoted 3 lines

A something like filtering with address family might be necessary while dumping. Yes, that would be inefficient. One long term solution would be conntrack hash per layer 3 protocol.

The filtering sounds fine for now. Dumping already has a large overhead because the repeated iterations over the entire hash to find out where to continue after an skb was full, this is not going to make it much worse. I'm going to fix it up when adding the patch.

Attached the take #4 of the ctnetlink port to nf_conntrack, it includes lastest Yasuyuki's fixes. But it doesn't fix the issue exposed above. Hope that it will make you save some time.

Signature · 1 line
Pablo
include/linux/netfilter/nfnetlink_conntrack.h +3 -0
index 116fcac..b8e9a5b 100644
@@ -64,6 +64,9 @@ enum ctattr_l4proto {
 	CTA_PROTO_ICMP_ID,
 	CTA_PROTO_ICMP_TYPE,
 	CTA_PROTO_ICMP_CODE,
+	CTA_PROTO_ICMPV6_ID,
+	CTA_PROTO_ICMPV6_TYPE,
+	CTA_PROTO_ICMPV6_CODE,
 	__CTA_PROTO_MAX
 };
 #define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1)
include/net/netfilter/nf_conntrack.h +31 -0
index cc48256..64b82b7 100644
@@ -94,6 +94,9 @@ struct nf_conn
 	/* Current number of expected connections */
 	unsigned int expecting;
 
+	/* Unique ID that identifies this conntrack*/
+	unsigned int id;
+
 	/* Helper. if any */
 	struct nf_conntrack_helper *helper;
 
@@ -140,6 +143,9 @@ struct nf_conntrack_expect
 	/* Usage count. */
 	atomic_t use;
 
+	/* Unique ID */
+	unsigned int id;
+
 	/* Flags */
 	unsigned int flags;
 
@@ -190,6 +196,31 @@ static inline void nf_ct_put(struct nf_c
 	nf_conntrack_put(&ct->ct_general);
 }
 
+extern struct nf_conntrack_tuple_hash *
+__nf_conntrack_find(const struct nf_conntrack_tuple *tuple,
+		    const struct nf_conn *ignored_conntrack);
+
+extern void nf_conntrack_hash_insert(struct nf_conn *ct);
+
+extern struct nf_conntrack_expect *
+__nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+
+extern struct nf_conntrack_expect *
+nf_conntrack_expect_find(const struct nf_conntrack_tuple *tuple);
+
+extern void nf_ct_unlink_expect(struct nf_conntrack_expect *exp);
+
+extern void nf_ct_remove_expectations(struct nf_conn *ct);
+
+extern void nf_conntrack_flush(void);
+
+extern struct nf_conntrack_helper *
+nf_ct_helper_find_get( const struct nf_conntrack_tuple *tuple);
+extern void nf_ct_helper_put(struct nf_conntrack_helper *helper);
+
+extern struct nf_conntrack_helper *
+__nf_conntrack_helper_find_byname(const char *name);
+
 /* call to create an explicit dependency on nf_conntrack. */
 extern void need_nf_conntrack(void);
 
include/net/netfilter/nf_conntrack_helper.h +2 -0
index 5a66b2a..86ec817 100644
@@ -33,6 +33,8 @@ struct nf_conntrack_helper
 		    unsigned int protoff,
 		    struct nf_conn *ct,
 		    enum ip_conntrack_info conntrackinfo);
+
+	int (*to_nfattr)(struct sk_buff *skb, const struct nf_conn *ct);
 };
 
 extern int nf_conntrack_helper_register(struct nf_conntrack_helper *);
include/net/netfilter/nf_conntrack_l3proto.h +14 -1
index 01663e5..67856eb 100644
@@ -14,6 +14,8 @@
 #include <linux/seq_file.h>
 #include <net/netfilter/nf_conntrack.h>
 
+struct nfattr;
+
 struct nf_conntrack_l3proto
 {
 	/* Next pointer. */
@@ -70,6 +72,12 @@ struct nf_conntrack_l3proto
 
 	u_int32_t (*get_features)(const struct nf_conntrack_tuple *tuple);
 
+	int (*tuple_to_nfattr)(struct sk_buff *skb,
+			       const struct nf_conntrack_tuple *t);
+
+	int (*nfattr_to_tuple)(struct nfattr *tb[],
+			       struct nf_conntrack_tuple *t);
+
 	/* Module (if any) which this is connected to. */
 	struct module *me;
 };
@@ -81,11 +89,16 @@ extern int nf_conntrack_l3proto_register
 extern void nf_conntrack_l3proto_unregister(struct nf_conntrack_l3proto *proto);
 
 static inline struct nf_conntrack_l3proto *
-nf_ct_find_l3proto(u_int16_t l3proto)
+__nf_ct_l3proto_find(u_int16_t l3proto)
 {
 	return nf_ct_l3protos[l3proto];
 }
 
+extern struct nf_conntrack_l3proto *
+nf_ct_l3proto_find_get(u_int16_t l3proto);
+
+extern void nf_ct_l3proto_put(struct nf_conntrack_l3proto *p);
+
 /* Existing built-in protocols */
 extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4;
 extern struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv6;
include/net/netfilter/nf_conntrack_protocol.h +25 -1
index b3afda3..1f33737 100644
@@ -12,6 +12,7 @@
 #include <net/netfilter/nf_conntrack.h>
 
 struct seq_file;
+struct nfattr;
 
 struct nf_conntrack_protocol
 {
@@ -66,6 +67,18 @@ struct nf_conntrack_protocol
 		     enum ip_conntrack_info *ctinfo,
 		     int pf, unsigned int hooknum);
 
+	/* convert protoinfo to nfnetink attributes */
+	int (*to_nfattr)(struct sk_buff *skb, struct nfattr *nfa,
+			 const struct nf_conn *ct);
+
+	/* convert nfnetlink attributes to protoinfo */
+	int (*from_nfattr)(struct nfattr *tb[], struct nf_conn *ct);
+
+	int (*tuple_to_nfattr)(struct sk_buff *skb,
+			       const struct nf_conntrack_tuple *t);
+	int (*nfattr_to_tuple)(struct nfattr *tb[],
+			       struct nf_conntrack_tuple *t);
+
 	/* Module (if any) which this is connected to. */
 	struct module *me;
 };
@@ -80,12 +93,23 @@ extern struct nf_conntrack_protocol nf_c
 extern struct nf_conntrack_protocol **nf_ct_protos[PF_MAX];
 
 extern struct nf_conntrack_protocol *
-nf_ct_find_proto(u_int16_t l3proto, u_int8_t protocol);
+__nf_ct_proto_find(u_int16_t l3proto, u_int8_t protocol);
+
+extern struct nf_conntrack_protocol *
+nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol);
+
+extern void nf_ct_proto_put(struct nf_conntrack_protocol *p);
 
 /* Protocol registration. */
 extern int nf_conntrack_protocol_register(struct nf_conntrack_protocol *proto);
 extern void nf_conntrack_protocol_unregister(struct nf_conntrack_protocol *proto);
 
+/* Generic netlink helpers */
+extern int nf_ct_port_tuple_to_nfattr(struct sk_buff *skb,
+				      const struct nf_conntrack_tuple *tuple);
+extern int nf_ct_port_nfattr_to_tuple(struct nfattr *tb[],
+				      struct nf_conntrack_tuple *t);
+
 /* Log invalid packets */
 extern unsigned int nf_ct_log_invalid;
 
include/net/netfilter/nf_conntrack_tuple.h +0 -0
net/ipv4/netfilter/ip_conntrack_netlink.c +0 -0
net/ipv4/netfilter/ip_conntrack_proto_icmp.c +0 -0
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +47 -0

59 lines not on this page · raw message

net/ipv4/netfilter/nf_conntrack_proto_icmp.c +79 -18

130 lines not on this page · raw message

net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +47 -0

59 lines not on this page · raw message

net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c +68 -9

104 lines not on this page · raw message

net/netfilter/Kconfig +7 -0
index a84f922..d6a0b96 100644
@@ -95,4 +95,11 @@ config NF_CONNTRACK_FTP
 
 	  To compile it as a module, choose M here.  If unsure, say N.
 
+config NF_CT_NETLINK
+	tristate 'Connection tracking netlink interface (EXPERIMENTAL)'
+	depends on EXPERIMENTAL && NF_CONNTRACK && NETFILTER_NETLINK
+	depends on NF_CONNTRACK!=y || NETFILTER_NETLINK!=m
+	help
+	  This option enables support for a netlink-based userspace interface
+
 endmenu
net/netfilter/Makefile +3 -0
index 55f019a..cb21831 100644
@@ -13,3 +13,6 @@ obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_con
 
 # SCTP protocol connection tracking
 obj-$(CONFIG_NF_CT_PROTO_SCTP) += nf_conntrack_proto_sctp.o
+
+# netlink interface for nf_conntrack
+obj-$(CONFIG_NF_CT_NETLINK) += nf_conntrack_netlink.o
net/netfilter/nf_conntrack_core.c +208 -24

390 lines not on this page · raw message

net/netfilter/nf_conntrack_proto_tcp.c +71 -0

89 lines not on this page · raw message

net/netfilter/nf_conntrack_proto_udp.c +10 -0
index 3cae7ce..1a592a5 100644
@@ -196,6 +196,11 @@ struct nf_conntrack_protocol nf_conntrac
 	.packet			= udp_packet,
 	.new			= udp_new,
 	.error			= udp_error4,
+#if defined(CONFIG_NF_CT_NETLINK) || \
+    defined(CONFIG_NF_CT_NETLINK_MODULE)
+	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
+	.nfattr_to_tuple	= nf_ct_port_nfattr_to_tuple,
+#endif
 };
 
 struct nf_conntrack_protocol nf_conntrack_protocol_udp6 =
@@ -210,6 +215,11 @@ struct nf_conntrack_protocol nf_conntrac
 	.packet			= udp_packet,
 	.new			= udp_new,
 	.error			= udp_error6,
+#if defined(CONFIG_NF_CT_NETLINK) || \
+    defined(CONFIG_NF_CT_NETLINK_MODULE)
+	.tuple_to_nfattr	= nf_ct_port_tuple_to_nfattr,
+	.nfattr_to_tuple	= nf_ct_port_nfattr_to_tuple,
+#endif
 };
 
 EXPORT_SYMBOL(nf_conntrack_protocol_udp4);
net/netfilter/nf_conntrack_standalone.c +32 -10

65 lines not on this page · raw message

net/netfilter/nf_conntrack_netlink.c new file +1642 -0

1,642 lines not on this page · raw message

#8 lore raw
Quoted 3 lines · Pablo Neira Ayuso

Attached the take #4 of the ctnetlink port to nf_conntrack, it includes lastest Yasuyuki's fixes. But it doesn't fix the issue exposed above. Hope that it will make you save some time.

Thanks, almost applied :) But I need a Signed-off-by: line for this patch.

#9 lore raw
Quoted 9 lines · Patrick McHardy
Quoted 3 lines · Pablo Neira Ayuso

Attached the take #4 of the ctnetlink port to nf_conntrack, it includes lastest Yasuyuki's fixes. But it doesn't fix the issue exposed above. Hope that it will make you save some time.

Thanks, almost applied :) But I need a Signed-off-by: line for this patch.

Sorry, I forgot to add it. The patch with the approapiate header and the Signed-off-by is available at:

http://people.netfilter.org/pablo/ctnetlink-port.patch

cheers,

Signature · 1 line
Pablo
#11 lore raw
In reply to Patrick McHardy
Quoted 12 lines · Patrick McHardy
Quoted 8 lines · Yasuyuki KOZAKAI

Well, I've found a issue. Current dumping code returns the informations about
IPv6 connections regardless of the address family in nfctnetlink header (nfgenmsg). As a result, conntrack program prints "0.0.0.0 ....."

A something like filtering with address family might be necessary while dumping. Yes, that would be inefficient. One long term solution would be conntrack hash per layer 3 protocol.

Quoted 4 lines

The filtering sounds fine for now. Dumping already has a large overhead because the repeated iterations over the entire hash to find out where to continue after an skb was full, this is not going to make it much worse. I'm going to fix it up when adding the patch.

What about the patch attached? It applies on top of my previous global ctnetlink port to nf_conntrack take#4 patch.

Signature · 1 line
Pablo

[NETFILTER] Dump entries based on the layer 3 protocol number

Dump entries of a given Layer 3 protocol number.

net/netfilter/nf_conntrack_netlink.c +17 -6
Index: netfilter-2.6.14.git/net/netfilter/nf_conntrack_netlink.c
===================================================================
@@ -400,6 +400,8 @@ static int ctnetlink_done(struct netlink
 	return 0;
 }
 
+#define L3PROTO(ct) ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num
+
 static int
 ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
 {
@@ -407,6 +409,8 @@ ctnetlink_dump_table(struct sk_buff *skb
 	struct nf_conntrack_tuple_hash *h;
 	struct list_head *i;
 	u_int32_t *id = (u_int32_t *) &cb->args[1];
+	struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
+	u_int8_t l3proto = nfmsg->nfgen_family;
 
 	DEBUGP("entered %s, last bucket=%lu id=%u\n", __FUNCTION__, 
 			cb->args[0], *id);
@@ -418,6 +422,11 @@ ctnetlink_dump_table(struct sk_buff *skb
 			if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
 				continue;
 			ct = nf_ct_tuplehash_to_ctrack(h);
+			/* Dump entries of a given L3 protocol number.
+			 * If it is not specified, ie. l3proto == 0,
+			 * then dump everything. */
+			if (l3proto && L3PROTO(ct) != l3proto)
+				continue;
 			if (ct->id <= *id)
 				continue;
 			if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
@@ -444,6 +453,8 @@ ctnetlink_dump_table_w(struct sk_buff *s
 	struct nf_conntrack_tuple_hash *h;
 	struct list_head *i;
 	u_int32_t *id = (u_int32_t *) &cb->args[1];
+	struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
+	u_int8_t l3proto = nfmsg->nfgen_family;	
 
 	DEBUGP("entered %s, last bucket=%u id=%u\n", __FUNCTION__, 
 			cb->args[0], *id);
@@ -455,6 +466,8 @@ ctnetlink_dump_table_w(struct sk_buff *s
 			if (DIRECTION(h) != IP_CT_DIR_ORIGINAL)
 				continue;
 			ct = nf_ct_tuplehash_to_ctrack(h);
+			if (l3proto && L3PROTO(ct) != l3proto)
+				continue;
 			if (ct->id <= *id)
 				continue;
 			if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid,
@@ -750,9 +763,6 @@ ctnetlink_get_conntrack(struct sock *ctn
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		u32 rlen;
 
-		if (nfmsg->nfgen_family != AF_INET)
-			return -EAFNOSUPPORT;
-
 		if (NFNL_MSG_TYPE(nlh->nlmsg_type) ==
 					IPCTNL_MSG_CT_GET_CTRZERO) {
 #ifdef CONFIG_NF_CT_ACCT
@@ -1251,12 +1261,16 @@ ctnetlink_exp_dump_table(struct sk_buff 
 	struct nf_conntrack_expect *exp = NULL;
 	struct list_head *i;
 	u_int32_t *id = (u_int32_t *) &cb->args[0];
+	struct nfgenmsg *nfmsg = NLMSG_DATA(cb->nlh);
+	u_int8_t l3proto = nfmsg->nfgen_family;
 
 	DEBUGP("entered %s, last id=%llu\n", __FUNCTION__, *id);
 
 	read_lock_bh(&nf_conntrack_lock);
 	list_for_each_prev(i, &nf_conntrack_expect_list) {
 		exp = (struct nf_conntrack_expect *) i;
+		if (l3proto && exp->tuple.src.l3num != l3proto)
+			continue;
 		if (exp->id <= *id)
 			continue;
 		if (ctnetlink_exp_fill_info(skb, NETLINK_CB(cb->skb).pid,
@@ -1298,9 +1312,6 @@ ctnetlink_get_expect(struct sock *ctnl, 
 	if (nlh->nlmsg_flags & NLM_F_DUMP) {
 		u32 rlen;
 
-		if (nfmsg->nfgen_family != AF_INET)
-			return -EAFNOSUPPORT;
-
 		if ((*errp = netlink_dump_start(ctnl, skb, nlh,
 		    				ctnetlink_exp_dump_table,
 						ctnetlink_done)) != 0)
#12 lore raw
Quoted 4 lines · Pablo Neira Ayuso

What about the patch attached? It applies on top of my previous global ctnetlink port to nf_conntrack take#4 patch.

[NETFILTER] Dump entries based on the layer 3 protocol number

Also applied, thanks.

#13 lore raw
In reply to Pablo Neira Ayuso

From: Pablo Neira Ayuso <[email protected]>
Date: Thu, 15 Dec 2005 20:16:55 +0100

Quoted 13 lines
Quoted 12 lines · Patrick McHardy
Quoted 8 lines · Yasuyuki KOZAKAI

Well, I've found a issue. Current dumping code returns the informations about
IPv6 connections regardless of the address family in nfctnetlink header (nfgenmsg). As a result, conntrack program prints "0.0.0.0 ....."

A something like filtering with address family might be necessary while dumping. Yes, that would be inefficient. One long term solution would be conntrack hash per layer 3 protocol.

Quoted 7 lines
Quoted 4 lines

The filtering sounds fine for now. Dumping already has a large overhead because the repeated iterations over the entire hash to find out where to continue after an skb was full, this is not going to make it much worse. I'm going to fix it up when adding the patch.

What about the patch attached? It applies on top of my previous global ctnetlink port to nf_conntrack take#4 patch.

looks fine to me. And that's good idea to dump informations of all connections if AF_UNSPEC is set in nfgenmsg. But I don't know that such way to handle AF_UNSPEC can be generic policy of nfnetlink.

-- Yasuyuki Kozakai

#14 lore raw

Sorry everyone, slowly catching up with my mail backlog

Quoted 6 lines · Yasuyuki KOZAKAI
Quoted 2 lines

What about the patch attached? It applies on top of my previous global ctnetlink port to nf_conntrack take#4 patch.

looks fine to me. And that's good idea to dump informations of all connections if AF_UNSPEC is set in nfgenmsg. But I don't know that such way to handle AF_UNSPEC can be generic policy of nfnetlink.

It is a nice use, but it would clash with our current definition of NF_ARP - in case we ever implement something via nfnetlink for the ARP protocol.

NF_ARP is defined to 0 in netfilter_arp.h, as a kludge around the problem of ARP not having an AF_ARP constant.

Signature · 5 lines
- Harald Welte <[email protected]>                 http://netfilter.org/
============================================================================
  "Fragmentation is like classful addressing -- an interesting early
   architectural error that shows how much experimentation was going
   on while IP was being designed."                    -- Paul Vixie