Skip to contentSkip to conversation

add support for explicit helper assignment

PATCH In review Pablo Neira Ayuso 4 participants 7 messages Oct 9, 2008 – Oct 11, 2008 netfilter

lore
Share & tools
lore

Pablo Neira Ayuso

author maintainer
#0 lore raw

PATCH 1/1 add support for explicit helper assignment

This patch adds support for the explicit helper assignment to libnetfilter_conntrack. You can use it to test the load-on-demand helper
modules via ctnetlink.

Signature · 1 line
"Los honestos son inadaptados sociales" -- Les Luthiers

[PATCH][libnetfilter_conntrack] add support for explicit helper assignment

This patch adds support for explicit helper assignment.

include/internal/extern.h +2 -0
index a43cde7..0caa30c 100644
@@ -9,4 +9,6 @@ extern filter_attr 	filter_attr_array[];
 extern set_exp_attr	set_exp_attr_array[];
 extern get_exp_attr	get_exp_attr_array[];
 
+extern const char 	*helper_id_to_name[];
+
 #endif
include/internal/object.h +1 -0
index e39a576..509f54b 100644
@@ -137,6 +137,7 @@ struct nf_conntrack {
 	u_int32_t 	status;
 	u_int32_t	use;
 	u_int32_t	id;
+	u_int32_t	helper_id;
 
 	union __nfct_protoinfo 	protoinfo;
 	struct __nfct_counters 	counters[__DIR_MAX];
include/libnetfilter_conntrack/libnetfilter_conntrack.h +17 -0
index 46eed0a..ee22fa9 100644
@@ -120,9 +120,26 @@ enum nf_conntrack_attr {
 	ATTR_SCTP_STATE = 52,			/* u8 bits */
 	ATTR_SCTP_VTAG_ORIG,			/* u32 bits */
 	ATTR_SCTP_VTAG_REPL,			/* u32 bits */
+	ATTR_HELPER_ID,				/* u32 bits */
 	ATTR_MAX
 };
 
+/* helper id's */
+
+enum nf_conntrack_helper_id {
+	NFCT_HELPER_UNSPEC = 0,
+	NFCT_HELPER_AMANDA,
+	NFCT_HELPER_FTP,
+	NFCT_HELPER_H323,
+	NFCT_HELPER_IRC = 4,
+	NFCT_HELPER_NETBIOS_NS,
+	NFCT_HELPER_PPTP,
+	NFCT_HELPER_SANE,
+	NFCT_HELPER_SIP = 8,
+	NFCT_HELPER_TFTP,
+	NFCT_HELPER_MAX
+};
+
 /* message type */
 enum nf_conntrack_msg_type {
 	NFCT_T_UNKNOWN = 0,
src/conntrack/build.c +35 -0
index 1bc87f9..8c7cb7f 100644
@@ -308,6 +308,38 @@ void __build_secmark(struct nfnlhdr *req,
 	nfnl_addattr32(&req->nlh, size, CTA_SECMARK, htonl(ct->secmark));
 }
 
+const char *helper_id_to_name[] = {
+	[NFCT_HELPER_UNSPEC]		= "unknown-helper",
+	[NFCT_HELPER_AMANDA] 		= "amanda",
+	[NFCT_HELPER_FTP] 		= "ftp",
+	[NFCT_HELPER_H323]		= "h323",
+	[NFCT_HELPER_IRC]		= "irc",
+	[NFCT_HELPER_NETBIOS_NS]	= "netbios_ns",
+	[NFCT_HELPER_PPTP]		= "pptp",
+	[NFCT_HELPER_SANE]		= "sane",
+	[NFCT_HELPER_SIP]		= "sip",
+	[NFCT_HELPER_TFTP]		= "tftp",
+};
+
+void __build_helper_name(struct nfnlhdr *req,
+			 size_t size,
+			 const struct nf_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	/* helper set, but probably unsupported */
+	if (ct->helper_id == 0)
+		return;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_HELP);
+	nfnl_addattr_l(&req->nlh,
+			size, 
+			CTA_HELP_NAME,
+			helper_id_to_name[ct->helper_id],
+			strlen(helper_id_to_name[ct->helper_id]));
+	nfnl_nest_end(&req->nlh, nest);
+}
+
 int __build_conntrack(struct nfnl_subsys_handle *ssh,
 		      struct nfnlhdr *req,
 		      size_t size,
@@ -417,5 +449,8 @@ int __build_conntrack(struct nfnl_subsys_handle *ssh,
 	    test_bit(ATTR_REPL_NAT_SEQ_OFFSET_AFTER, ct->set))
 	    	__build_nat_seq_adj(req, size, ct, __DIR_REPL);
 
+	if (test_bit(ATTR_HELPER_ID, ct->set))
+		__build_helper_name(req, size, ct);
+
 	return 0;
 }
src/conntrack/getter.c +6 -0
index 20a2a35..65035f0 100644
@@ -282,6 +282,11 @@ static const void *get_attr_repl_off_aft(const struct nf_conntrack *ct)
 	return &ct->tuple[__DIR_REPL].natseq.offset_after;
 }
 
+static const void *get_attr_helper_id(const struct nf_conntrack *ct)
+{
+	return &ct->helper_id;
+}
+
 get_attr get_attr_array[] = {
 	[ATTR_ORIG_IPV4_SRC]		= get_attr_orig_ipv4_src,
 	[ATTR_ORIG_IPV4_DST] 		= get_attr_orig_ipv4_dst,
@@ -338,4 +343,5 @@ get_attr get_attr_array[] = {
 	[ATTR_SCTP_STATE]		= get_attr_sctp_state,
 	[ATTR_SCTP_VTAG_ORIG]		= get_attr_sctp_vtag_orig,
 	[ATTR_SCTP_VTAG_REPL]		= get_attr_sctp_vtag_repl,
+	[ATTR_HELPER_ID]		= get_attr_helper_id,
 };
src/conntrack/parse.c +28 -0
index 11cf5ff..41c0c26 100644
@@ -356,6 +356,31 @@ __parse_nat_seq(const struct nfattr *attr, struct nf_conntrack *ct, int dir)
 	}
 }
 
+static void 
+__parse_helper(const struct nfattr *attr, struct nf_conntrack *ct)
+{
+	int i, found = 0;
+	struct nfattr *tb[CTA_NAT_SEQ_MAX];
+
+	nfnl_parse_nested(tb, CTA_NAT_SEQ_MAX, attr);
+	if (!tb[CTA_HELP_NAME-1])
+		return;
+
+	for (i=0; i<NFCT_HELPER_MAX; i++) {
+		if (strcmp(NFA_DATA(tb[CTA_HELP_NAME-1]), 
+			   helper_id_to_name[i]) == 0) {
+			found = 1;
+			break;
+		}
+	}
+
+	if (!found)
+		return;
+
+	ct->helper_id = i;
+	set_bit(ATTR_HELPER_ID, ct->set);
+}
+
 int __parse_message_type(const struct nlmsghdr *nlh)
 {
 	u_int16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
@@ -447,4 +472,7 @@ void __parse_conntrack(const struct nlmsghdr *nlh,
 		ct->id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_ID-1]));
 		set_bit(ATTR_ID, ct->set);
 	}
+
+	if (cda[CTA_HELP-1])
+		__parse_helper(cda[CTA_HELP-1], ct);
 }
src/conntrack/setter.c +11 -0
index 6759652..b9e93ca 100644
@@ -308,6 +308,16 @@ static void set_attr_repl_off_aft(struct nf_conntrack *ct, const void *value)
 	ct->tuple[__DIR_REPL].natseq.offset_after = *((u_int32_t *) value);
 }
 
+static void set_attr_helper_id(struct nf_conntrack *ct, const void *value)
+{
+	u_int32_t val = *((u_int32_t *)value);
+
+	if (val >= NFCT_HELPER_MAX)
+		val = 0;
+
+	ct->helper_id = val;
+}
+
 static void set_attr_do_nothing(struct nf_conntrack *ct, const void *value) {}
 
 set_attr set_attr_array[] = {
@@ -366,4 +376,5 @@ set_attr set_attr_array[] = {
 	[ATTR_SCTP_STATE]	= set_attr_sctp_state,
 	[ATTR_SCTP_VTAG_ORIG]	= set_attr_sctp_vtag_orig,
 	[ATTR_SCTP_VTAG_REPL]	= set_attr_sctp_vtag_repl,
+	[ATTR_HELPER_ID]	= set_attr_helper_id,
 };
utils/conntrack_create.c +1 -0
index bc591b5..04b9807 100644
@@ -29,6 +29,7 @@ int main()
 
 	nfct_set_attr_u8(ct, ATTR_TCP_STATE, TCP_CONNTRACK_LISTEN);
 	nfct_set_attr_u32(ct, ATTR_TIMEOUT, 100);
+	nfct_set_attr_u32(ct, ATTR_HELPER_ID, NFCT_HELPER_FTP);
 
 	h = nfct_open(CONNTRACK, 0);
 	if (!h) {
#1 lore raw
Quoted 3 lines · Pablo Neira Ayuso

This patch adds support for the explicit helper assignment to libnetfilter_conntrack. You can use it to test the load-on-demand helper modules via ctnetlink.

<CUT>

Quoted 28 lines
include/libnetfilter_conntrack/libnetfilter_conntrack.h +14 -0
+enum nf_conntrack_helper_id {
+	NFCT_HELPER_UNSPEC = 0,
+	NFCT_HELPER_AMANDA,
+	NFCT_HELPER_FTP,
+	NFCT_HELPER_H323,
+	NFCT_HELPER_IRC = 4,
+	NFCT_HELPER_NETBIOS_NS,
+	NFCT_HELPER_PPTP,
+	NFCT_HELPER_SANE,
+	NFCT_HELPER_SIP = 8,
+	NFCT_HELPER_TFTP,
+	NFCT_HELPER_MAX
+};
+
 /* message type */
 enum nf_conntrack_msg_type {
 	NFCT_T_UNKNOWN = 0,
src/conntrack/build.c +3 -0
index 1bc87f9..8c7cb7f 100644
@@ -308,6 +308,38 @@ void __build_secmark(struct nfnlhdr *req,
 	nfnl_addattr32(&req->nlh, size, CTA_SECMARK, htonl(ct->secmark));
 }
 
+const char *helper_id_to_name[] = {
+	[NFCT_HELPER_UNSPEC]		= "unknown-helper",
+	[NFCT_HELPER_AMANDA] 		= "amanda",

src/conntrack/build.c void __build_secmark(struct nfnlhdr *req, · line 323

Quoted 10 lines
src/conntrack/build.c +10 -0
+	[NFCT_HELPER_FTP] 		= "ftp",
+	[NFCT_HELPER_H323]		= "h323",
+	[NFCT_HELPER_IRC]		= "irc",
+	[NFCT_HELPER_NETBIOS_NS]	= "netbios_ns",
+	[NFCT_HELPER_PPTP]		= "pptp",
+	[NFCT_HELPER_SANE]		= "sane",
+	[NFCT_HELPER_SIP]		= "sip",
+	[NFCT_HELPER_TFTP]		= "tftp",
+};
+

Any chances to make it more frendly to new helpers and compatible with out-of-tree helpers by registering a name directly from a helper and using it? We may for example introduce something like /proc/net/nf_helpers.

Best regards,

Krzysztof Olędzki

author maintainer
#2 lore raw
Quoted 17 lines · Krzysztof Oledzki
Quoted 17 lines
src/conntrack/build.c +9 -0
index 1bc87f9..8c7cb7f 100644
@@ -308,6 +308,38 @@ void __build_secmark(struct nfnlhdr *req,
     nfnl_addattr32(&req->nlh, size, CTA_SECMARK, htonl(ct->secmark));
 }
 
+const char *helper_id_to_name[] = {
+    [NFCT_HELPER_UNSPEC]        = "unknown-helper",
+    [NFCT_HELPER_AMANDA]         = "amanda",
+    [NFCT_HELPER_FTP]         = "ftp",
+    [NFCT_HELPER_H323]        = "h323",
+    [NFCT_HELPER_IRC]        = "irc",
+    [NFCT_HELPER_NETBIOS_NS]    = "netbios_ns",
+    [NFCT_HELPER_PPTP]        = "pptp",
+    [NFCT_HELPER_SANE]        = "sane",
Quoted 8 lines

src/conntrack/build.c void __build_secmark(struct nfnlhdr *req, · line 323

Quoted 4 lines
src/conntrack/build.c +4 -0
+    [NFCT_HELPER_SIP]        = "sip",
+    [NFCT_HELPER_TFTP]        = "tftp",
+};
+

Any chances to make it more frendly to new helpers and compatible with out-of-tree helpers by registering a name directly from a helper and using it? We may for example introduce something like /proc/net/nf_helpers.

We may directly set the name of the helper using the string that identifies it instead of this id. However, this means more memory consumption but more flexibility. I have another patch here that uses strings to do so. The problem is that helpers doesn't have a limitation in the name length and I don't like the idea of having a field "helper_name" with variable length inside the nf_conntrack object. We could make some reasonable assumptions, like considering that the helper name would not be larger than 32 bytes.

Using this patch, the new helpers would need a new version of the library as you have said. However, the argument of supporting out-of-tree helpers doesn't convince me, what out-of-tree helpers are you refering to?

BTW, the patch is not yet applied anyway.

Signature · 1 line
"Los honestos son inadaptados sociales" -- Les Luthiers
#3 lore raw
Quoted 27 lines · Pablo Neira Ayuso
Quoted 17 lines · Krzysztof Oledzki
Quoted 17 lines
src/conntrack/build.c +9 -0
index 1bc87f9..8c7cb7f 100644
@@ -308,6 +308,38 @@ void __build_secmark(struct nfnlhdr *req,
     nfnl_addattr32(&req->nlh, size, CTA_SECMARK, htonl(ct->secmark));
 }
 
+const char *helper_id_to_name[] = {
+    [NFCT_HELPER_UNSPEC]        = "unknown-helper",
+    [NFCT_HELPER_AMANDA]         = "amanda",
+    [NFCT_HELPER_FTP]         = "ftp",
+    [NFCT_HELPER_H323]        = "h323",
+    [NFCT_HELPER_IRC]        = "irc",
+    [NFCT_HELPER_NETBIOS_NS]    = "netbios_ns",
+    [NFCT_HELPER_PPTP]        = "pptp",
+    [NFCT_HELPER_SANE]        = "sane",
Quoted 8 lines

src/conntrack/build.c void __build_secmark(struct nfnlhdr *req, · line 323

Quoted 4 lines
src/conntrack/build.c +4 -0
+    [NFCT_HELPER_SIP]        = "sip",
+    [NFCT_HELPER_TFTP]        = "tftp",
+};
+

Any chances to make it more frendly to new helpers and compatible with out-of-tree helpers by registering a name directly from a helper and using it? We may for example introduce something like /proc/net/nf_helpers.

Quoted 8 lines

We may directly set the name of the helper using the string that identifies it instead of this id. However, this means more memory consumption but more flexibility. I have another patch here that uses strings to do so. The problem is that helpers doesn't have a limitation in the name length and I don't like the idea of having a field "helper_name" with variable length inside the nf_conntrack object. We could make some reasonable assumptions, like considering that the helper name would not be larger than 32 bytes.

Yep, 32 bytes seems to be a good compromise.

Quoted 4 lines

Using this patch, the new helpers would need a new version of the library as you have said. However, the argument of supporting out-of-tree helpers doesn't convince me, what out-of-tree helpers are you refering to?

nf_conntrack_rtsp for example

Best regards,

Krzysztof Olędzki

#4 lore raw
Quoted 8 lines · Krzysztof Oledzki
Quoted 5 lines

Using this patch, the new helpers would need a new version of the library as you have said. However, the argument of supporting out-of-tree helpers doesn't convince me, what out-of-tree helpers are you refering to?

nf_conntrack_rtsp for example

And whatever is lingering in crapomatic, eh? ;-)

#5 lore raw
In reply to Pablo Neira Ayuso
Quoted 5 lines · Pablo Neira Ayuso
Quoted 3 lines · Krzysztof Oledzki

Any chances to make it more frendly to new helpers and compatible with out-of-tree helpers by registering a name directly from a helper and using it? We may for example introduce something like /proc/net/nf_helpers.

Quoted 8 lines

We may directly set the name of the helper using the string that identifies it instead of this id. However, this means more memory consumption but more flexibility. I have another patch here that uses strings to do so. The problem is that helpers doesn't have a limitation in the name length and I don't like the idea of having a field "helper_name" with variable length inside the nf_conntrack object. We could make some reasonable assumptions, like considering that the helper name would not be larger than 32 bytes.

Limiting the name makes sense. The helper match can only match on I think 16 bytes, and that seems big enough.

author maintainer
#6 lore raw
Quoted 16 lines · Patrick McHardy
Quoted 6 lines · Pablo Neira Ayuso
Quoted 4 lines · Krzysztof Oledzki

Any chances to make it more frendly to new helpers and compatible with out-of-tree helpers by registering a name directly from a helper and using it? We may for example introduce something like /proc/net/nf_helpers.

Quoted 8 lines

We may directly set the name of the helper using the string that identifies it instead of this id. However, this means more memory consumption but more flexibility. I have another patch here that uses strings to do so. The problem is that helpers doesn't have a limitation in the name length and I don't like the idea of having a field "helper_name" with variable length inside the nf_conntrack object. We could make some reasonable assumptions, like considering that the helper name would not be larger than 32 bytes.

Quoted 2 lines

Limiting the name makes sense. The helper match can only match on I think 16 bytes, and that seems big enough.

Fine, I have set it to the same size used in xt_helper (30 bytes, that seems a lot to me, I actually prefer 16 bytes as you said).

BTW, the helper name support for libnetfilter_conntrack looks like the patch attached.

Signature · 1 line
"Los honestos son inadaptados sociales" -- Les Luthiers
include/internal/object.h +3 -0
index e39a576..f68d340 100644
@@ -138,6 +138,9 @@ struct nf_conntrack {
 	u_int32_t	use;
 	u_int32_t	id;
 
+#define __NFCT_HELPER_NAMELEN		30	/* same length in xt_helper */
+	char 		helper_name[__NFCT_HELPER_NAMELEN];
+
 	union __nfct_protoinfo 	protoinfo;
 	struct __nfct_counters 	counters[__DIR_MAX];
 	struct __nfct_nat 	snat;
include/libnetfilter_conntrack/libnetfilter_conntrack.h +1 -0
index 46eed0a..e66f0f8 100644
@@ -120,6 +120,7 @@ enum nf_conntrack_attr {
 	ATTR_SCTP_STATE = 52,			/* u8 bits */
 	ATTR_SCTP_VTAG_ORIG,			/* u32 bits */
 	ATTR_SCTP_VTAG_REPL,			/* u32 bits */
+	ATTR_HELPER_NAME,			/* string (30 bytes max) */
 	ATTR_MAX
 };
 
src/conntrack/build.c +18 -0
index 1bc87f9..f9d6f8e 100644
@@ -308,6 +308,21 @@ void __build_secmark(struct nfnlhdr *req,
 	nfnl_addattr32(&req->nlh, size, CTA_SECMARK, htonl(ct->secmark));
 }
 
+void __build_helper_name(struct nfnlhdr *req,
+			 size_t size,
+			 const struct nf_conntrack *ct)
+{
+	struct nfattr *nest;
+
+	nest = nfnl_nest(&req->nlh, size, CTA_HELP);
+	nfnl_addattr_l(&req->nlh,
+		       size, 
+		       CTA_HELP_NAME,
+		       ct->helper_name,
+		       strlen(ct->helper_name));
+	nfnl_nest_end(&req->nlh, nest);
+}
+
 int __build_conntrack(struct nfnl_subsys_handle *ssh,
 		      struct nfnlhdr *req,
 		      size_t size,
@@ -417,5 +432,8 @@ int __build_conntrack(struct nfnl_subsys_handle *ssh,
 	    test_bit(ATTR_REPL_NAT_SEQ_OFFSET_AFTER, ct->set))
 	    	__build_nat_seq_adj(req, size, ct, __DIR_REPL);
 
+	if (test_bit(ATTR_HELPER_NAME, ct->set))
+		__build_helper_name(req, size, ct);
+
 	return 0;
 }
src/conntrack/getter.c +6 -0
index 20a2a35..658d010 100644
@@ -282,6 +282,11 @@ static const void *get_attr_repl_off_aft(const struct nf_conntrack *ct)
 	return &ct->tuple[__DIR_REPL].natseq.offset_after;
 }
 
+static const void *get_attr_helper_name(const struct nf_conntrack *ct)
+{
+	return ct->helper_name;
+}
+
 get_attr get_attr_array[] = {
 	[ATTR_ORIG_IPV4_SRC]		= get_attr_orig_ipv4_src,
 	[ATTR_ORIG_IPV4_DST] 		= get_attr_orig_ipv4_dst,
@@ -338,4 +343,5 @@ get_attr get_attr_array[] = {
 	[ATTR_SCTP_STATE]		= get_attr_sctp_state,
 	[ATTR_SCTP_VTAG_ORIG]		= get_attr_sctp_vtag_orig,
 	[ATTR_SCTP_VTAG_REPL]		= get_attr_sctp_vtag_repl,
+	[ATTR_HELPER_NAME]		= get_attr_helper_name,
 };
src/conntrack/parse.c +19 -0
index 11cf5ff..d453bc6 100644
@@ -356,6 +356,22 @@ __parse_nat_seq(const struct nfattr *attr, struct nf_conntrack *ct, int dir)
 	}
 }
 
+static void 
+__parse_helper(const struct nfattr *attr, struct nf_conntrack *ct)
+{
+	struct nfattr *tb[CTA_HELP_MAX];
+
+	nfnl_parse_nested(tb, CTA_HELP_MAX, attr);
+	if (!tb[CTA_HELP_NAME-1])
+		return;
+
+	strncpy(ct->helper_name, 
+		NFA_DATA(tb[CTA_HELP_NAME-1]),
+		__NFCT_HELPER_NAMELEN);
+	ct->helper_name[__NFCT_HELPER_NAMELEN-1] = '\0';
+	set_bit(ATTR_HELPER_NAME, ct->set);
+}
+
 int __parse_message_type(const struct nlmsghdr *nlh)
 {
 	u_int16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
@@ -447,4 +463,7 @@ void __parse_conntrack(const struct nlmsghdr *nlh,
 		ct->id = ntohl(*(u_int32_t *)NFA_DATA(cda[CTA_ID-1]));
 		set_bit(ATTR_ID, ct->set);
 	}
+
+	if (cda[CTA_HELP-1])
+		__parse_helper(cda[CTA_HELP-1], ct);
 }
src/conntrack/setter.c +7 -0
index 6759652..3291bd1 100644
@@ -308,6 +308,12 @@ static void set_attr_repl_off_aft(struct nf_conntrack *ct, const void *value)
 	ct->tuple[__DIR_REPL].natseq.offset_after = *((u_int32_t *) value);
 }
 
+static void set_attr_helper_name(struct nf_conntrack *ct, const void *value)
+{
+	strncpy(ct->helper_name, value, __NFCT_HELPER_NAMELEN);
+	ct->helper_name[__NFCT_HELPER_NAMELEN-1] = '\0';
+}
+
 static void set_attr_do_nothing(struct nf_conntrack *ct, const void *value) {}
 
 set_attr set_attr_array[] = {
@@ -366,4 +372,5 @@ set_attr set_attr_array[] = {
 	[ATTR_SCTP_STATE]	= set_attr_sctp_state,
 	[ATTR_SCTP_VTAG_ORIG]	= set_attr_sctp_vtag_orig,
 	[ATTR_SCTP_VTAG_REPL]	= set_attr_sctp_vtag_repl,
+	[ATTR_HELPER_NAME]	= set_attr_helper_name,
 };
utils/conntrack_create.c +1 -0
index bc591b5..34efa57 100644
@@ -29,6 +29,7 @@ int main()
 
 	nfct_set_attr_u8(ct, ATTR_TCP_STATE, TCP_CONNTRACK_LISTEN);
 	nfct_set_attr_u32(ct, ATTR_TIMEOUT, 100);
+	nfct_set_attr(ct, ATTR_HELPER_NAME, "ftp");
 
 	h = nfct_open(CONNTRACK, 0);
 	if (!h) {