From 7533cca286edee99db29eb1238653a2040738d3e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 14 Apr 2009 10:35:27 +0200 Subject: src: add initial DCCP support This patch adds initial DCCP support for libnetfilter_conntrack. Signed-off-by: Pablo Neira Ayuso --- include/internal/object.h | 10 +++++- include/libnetfilter_conntrack/Makefile.am | 2 +- .../libnetfilter_conntrack.h | 1 + .../libnetfilter_conntrack_dccp.h | 33 +++++++++++++++++++ src/conntrack/build.c | 38 +++++++++++++++++----- src/conntrack/compare.c | 10 ++++++ src/conntrack/getter.c | 6 ++++ src/conntrack/parse.c | 17 ++++++++++ src/conntrack/setter.c | 6 ++++ src/conntrack/snprintf_default.c | 25 ++++++++++++++ src/conntrack/snprintf_xml.c | 1 + 11 files changed, 138 insertions(+), 11 deletions(-) create mode 100644 include/libnetfilter_conntrack/libnetfilter_conntrack_dccp.h diff --git a/include/internal/object.h b/include/internal/object.h index f76bf98..1db6b36 100644 --- a/include/internal/object.h +++ b/include/internal/object.h @@ -53,6 +53,9 @@ union __nfct_l4_src { struct { u_int16_t port; } sctp; + struct { + u_int16_t port; + } dccp; }; union __nfct_l4_dst { @@ -70,6 +73,9 @@ union __nfct_l4_dst { struct { u_int16_t port; } sctp; + struct { + u_int16_t port; + } dccp; }; union __nfct_address { @@ -110,7 +116,9 @@ union __nfct_protoinfo { u_int8_t state; u_int32_t vtag[__DIR_MAX]; } sctp; - + struct { + u_int8_t state; + } dccp; }; struct __nfct_counters { diff --git a/include/libnetfilter_conntrack/Makefile.am b/include/libnetfilter_conntrack/Makefile.am index c5f762f..fd36bfb 100644 --- a/include/libnetfilter_conntrack/Makefile.am +++ b/include/libnetfilter_conntrack/Makefile.am @@ -1,2 +1,2 @@ -pkginclude_HEADERS = libnetfilter_conntrack.h linux_nfnetlink_conntrack.h libnetfilter_conntrack_tcp.h libnetfilter_conntrack_udp.h libnetfilter_conntrack_icmp.h libnetfilter_conntrack_sctp.h libnetfilter_conntrack_ipv4.h libnetfilter_conntrack_ipv6.h +pkginclude_HEADERS = libnetfilter_conntrack.h linux_nfnetlink_conntrack.h libnetfilter_conntrack_tcp.h libnetfilter_conntrack_udp.h libnetfilter_conntrack_icmp.h libnetfilter_conntrack_sctp.h libnetfilter_conntrack_dccp.h libnetfilter_conntrack_ipv4.h libnetfilter_conntrack_ipv6.h diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h index f2b6dbb..3d25c6b 100644 --- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h +++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h @@ -121,6 +121,7 @@ enum nf_conntrack_attr { ATTR_SCTP_VTAG_ORIG, /* u32 bits */ ATTR_SCTP_VTAG_REPL, /* u32 bits */ ATTR_HELPER_NAME, /* string (30 bytes max) */ + ATTR_DCCP_STATE = 56, /* u8 bits */ ATTR_MAX }; diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack_dccp.h b/include/libnetfilter_conntrack/libnetfilter_conntrack_dccp.h new file mode 100644 index 0000000..46138de --- /dev/null +++ b/include/libnetfilter_conntrack/libnetfilter_conntrack_dccp.h @@ -0,0 +1,33 @@ +/* + * (C) 2009 by Pablo Neira Ayuso + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + */ + +#ifndef _LIBNETFILTER_CONNTRACK_DCCP_H_ +#define _LIBNETFILTER_CONNTRACK_DCCP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +enum dccp_state { + DCCP_CONNTRACK_NONE, + DCCP_CONNTRACK_REQUEST, + DCCP_CONNTRACK_RESPOND, + DCCP_CONNTRACK_PARTOPEN, + DCCP_CONNTRACK_OPEN, + DCCP_CONNTRACK_CLOSEREQ, + DCCP_CONNTRACK_CLOSING, + DCCP_CONNTRACK_TIMEWAIT, + DCCP_CONNTRACK_IGNORE, + DCCP_CONNTRACK_INVALID, + DCCP_CONNTRACK_MAX +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/conntrack/build.c b/src/conntrack/build.c index 4b2e292..1738402 100644 --- a/src/conntrack/build.c +++ b/src/conntrack/build.c @@ -50,6 +50,7 @@ void __build_tuple_proto(struct nfnlhdr *req, case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_SCTP: + case IPPROTO_DCCP: case IPPROTO_GRE: case IPPROTO_UDPLITE: nfnl_addattr_l(&req->nlh, size, CTA_PROTO_SRC_PORT, @@ -98,14 +99,20 @@ void __build_tuple(struct nfnlhdr *req, nfnl_nest_end(&req->nlh, nest); } -void __build_protoinfo(struct nfnlhdr *req, - size_t size, - const struct nf_conntrack *ct) +static void __build_protoinfo(struct nfnlhdr *req, size_t size, + const struct nf_conntrack *ct) { struct nfattr *nest, *nest_proto; switch(ct->tuple[__DIR_ORIG].protonum) { case IPPROTO_TCP: + if (!(test_bit(ATTR_TCP_STATE, ct->set) || + (test_bit(ATTR_TCP_FLAGS_ORIG, ct->set) && + test_bit(ATTR_TCP_MASK_ORIG, ct->set)) || + (test_bit(ATTR_TCP_FLAGS_REPL, ct->set) && + test_bit(ATTR_TCP_MASK_REPL, ct->set)))) { + break; + } nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO); nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_TCP); if (test_bit(ATTR_TCP_STATE, ct->set)) @@ -129,6 +136,11 @@ void __build_protoinfo(struct nfnlhdr *req, nfnl_nest_end(&req->nlh, nest); break; case IPPROTO_SCTP: + if (!(test_bit(ATTR_SCTP_STATE, ct->set) && + (test_bit(ATTR_SCTP_VTAG_ORIG, ct->set) && + test_bit(ATTR_SCTP_VTAG_REPL, ct->set)))) { + break; + } nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO); nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_SCTP); if (test_bit(ATTR_SCTP_STATE, ct->set)) @@ -147,6 +159,19 @@ void __build_protoinfo(struct nfnlhdr *req, nfnl_nest_end(&req->nlh, nest_proto); nfnl_nest_end(&req->nlh, nest); break; + case IPPROTO_DCCP: + if (!(test_bit(ATTR_DCCP_STATE, ct->set))) + break; + + nest = nfnl_nest(&req->nlh, size, CTA_PROTOINFO); + nest_proto = nfnl_nest(&req->nlh, size, CTA_PROTOINFO_DCCP); + if (test_bit(ATTR_DCCP_STATE, ct->set)) + nfnl_addattr_l(&req->nlh, size, + CTA_PROTOINFO_DCCP_STATE, + &ct->protoinfo.dccp.state, + sizeof(u_int8_t)); + nfnl_nest_end(&req->nlh, nest_proto); + nfnl_nest_end(&req->nlh, nest); default: break; } @@ -404,12 +429,7 @@ int __build_conntrack(struct nfnl_subsys_handle *ssh, if (test_bit(ATTR_SECMARK, ct->set)) __build_secmark(req, size, ct); - if (test_bit(ATTR_TCP_STATE, ct->set) || - (test_bit(ATTR_TCP_FLAGS_ORIG, ct->set) && - test_bit(ATTR_TCP_MASK_ORIG, ct->set)) || - (test_bit(ATTR_TCP_FLAGS_REPL, ct->set) && - test_bit(ATTR_TCP_MASK_REPL, ct->set))) - __build_protoinfo(req, size, ct); + __build_protoinfo(req, size, ct); if (test_bit(ATTR_SNAT_IPV4, ct->set) && test_bit(ATTR_SNAT_PORT, ct->set)) diff --git a/src/conntrack/compare.c b/src/conntrack/compare.c index 1be1c71..ba3fdf8 100644 --- a/src/conntrack/compare.c +++ b/src/conntrack/compare.c @@ -352,6 +352,14 @@ cmp_sctp_state(const struct nf_conntrack *ct1, return (ct1->protoinfo.sctp.state == ct2->protoinfo.sctp.state); } +static int +cmp_dccp_state(const struct nf_conntrack *ct1, + const struct nf_conntrack *ct2, + unsigned int flags) +{ + return (ct1->protoinfo.dccp.state == ct2->protoinfo.dccp.state); +} + static int cmp_meta(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2, unsigned int flags) @@ -368,6 +376,8 @@ static int cmp_meta(const struct nf_conntrack *ct1, return 0; if (!__cmp(ATTR_SCTP_STATE, ct1, ct2, flags, cmp_sctp_state)) return 0; + if (!__cmp(ATTR_DCCP_STATE, ct1, ct2, flags, cmp_dccp_state)) + return 0; return 1; } diff --git a/src/conntrack/getter.c b/src/conntrack/getter.c index 65661d4..2338db2 100644 --- a/src/conntrack/getter.c +++ b/src/conntrack/getter.c @@ -287,6 +287,11 @@ static const void *get_attr_helper_name(const struct nf_conntrack *ct) return ct->helper_name; } +static const void *get_attr_dccp_state(const struct nf_conntrack *ct) +{ + return &ct->protoinfo.dccp.state; +} + get_attr get_attr_array[ATTR_MAX] = { [ATTR_ORIG_IPV4_SRC] = get_attr_orig_ipv4_src, [ATTR_ORIG_IPV4_DST] = get_attr_orig_ipv4_dst, @@ -344,4 +349,5 @@ get_attr get_attr_array[ATTR_MAX] = { [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, + [ATTR_DCCP_STATE] = get_attr_dccp_state, }; diff --git a/src/conntrack/parse.c b/src/conntrack/parse.c index d453bc6..9a42ed7 100644 --- a/src/conntrack/parse.c +++ b/src/conntrack/parse.c @@ -244,6 +244,20 @@ static void __parse_protoinfo_sctp(const struct nfattr *attr, } +static void __parse_protoinfo_dccp(const struct nfattr *attr, + struct nf_conntrack *ct) +{ + struct nfattr *tb[CTA_PROTOINFO_DCCP_MAX]; + + nfnl_parse_nested(tb, CTA_PROTOINFO_DCCP_MAX, attr); + + if (tb[CTA_PROTOINFO_DCCP_STATE-1]) { + ct->protoinfo.dccp.state = + *(u_int8_t *)NFA_DATA(tb[CTA_PROTOINFO_DCCP_STATE-1]); + set_bit(ATTR_DCCP_STATE, ct->set); + } +} + static void __parse_protoinfo(const struct nfattr *attr, struct nf_conntrack *ct) { @@ -256,6 +270,9 @@ static void __parse_protoinfo(const struct nfattr *attr, if (tb[CTA_PROTOINFO_SCTP-1]) __parse_protoinfo_sctp(tb[CTA_PROTOINFO_SCTP-1], ct); + + if (tb[CTA_PROTOINFO_DCCP-1]) + __parse_protoinfo_dccp(tb[CTA_PROTOINFO_DCCP-1], ct); } static void __parse_counters(const struct nfattr *attr, diff --git a/src/conntrack/setter.c b/src/conntrack/setter.c index 6e275ab..481fad1 100644 --- a/src/conntrack/setter.c +++ b/src/conntrack/setter.c @@ -314,6 +314,11 @@ static void set_attr_helper_name(struct nf_conntrack *ct, const void *value) ct->helper_name[__NFCT_HELPER_NAMELEN-1] = '\0'; } +static void set_attr_dccp_state(struct nf_conntrack *ct, const void *value) +{ + ct->protoinfo.dccp.state = *((u_int8_t *) value); +} + static void set_attr_do_nothing(struct nf_conntrack *ct, const void *value) {} set_attr set_attr_array[ATTR_MAX] = { @@ -373,4 +378,5 @@ set_attr set_attr_array[ATTR_MAX] = { [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, + [ATTR_DCCP_STATE] = set_attr_dccp_state, }; diff --git a/src/conntrack/snprintf_default.c b/src/conntrack/snprintf_default.c index dbc5fb1..4802c47 100644 --- a/src/conntrack/snprintf_default.c +++ b/src/conntrack/snprintf_default.c @@ -16,6 +16,7 @@ static char *proto2str[IPPROTO_MAX] = { [IPPROTO_SCTP] = "sctp", [IPPROTO_GRE] = "gre", [IPPROTO_UDPLITE] = "udplite", + [IPPROTO_DCCP] = "dccp", }; static char *l3proto2str[AF_MAX] = { @@ -47,6 +48,19 @@ static const char *sctp_states[] = { "SHUTDOWN_ACK_SENT", }; +static const char *dccp_states[] = { + "NONE", + "REQUEST", + "RESPOND", + "PARTOPEN", + "OPEN", + "CLOSEREQ", + "CLOSING", + "TIMEWAIT", + "IGNORE", + "INVALID", +}; + static int __snprintf_l3protocol(char *buf, unsigned int len, const struct nf_conntrack *ct) @@ -86,6 +100,12 @@ int __snprintf_protoinfo_sctp(char *buf, { return snprintf(buf, len, "%s ", sctp_states[ct->protoinfo.sctp.state]); } +int __snprintf_protoinfo_dccp(char *buf, + unsigned int len, + const struct nf_conntrack *ct) +{ + return snprintf(buf, len, "%s ", dccp_states[ct->protoinfo.dccp.state]); +} int __snprintf_address_ipv4(char *buf, unsigned int len, @@ -288,6 +308,11 @@ int __snprintf_conntrack_default(char *buf, BUFFER_SIZE(ret, size, len, offset); } + if (test_bit(ATTR_DCCP_STATE, ct->set)) { + ret = __snprintf_protoinfo_dccp(buf+offset, len, ct); + BUFFER_SIZE(ret, size, len, offset); + } + ret = __snprintf_address(buf+offset, len, &ct->tuple[__DIR_ORIG]); BUFFER_SIZE(ret, size, len, offset); diff --git a/src/conntrack/snprintf_xml.c b/src/conntrack/snprintf_xml.c index 5dbba9f..ff34e86 100644 --- a/src/conntrack/snprintf_xml.c +++ b/src/conntrack/snprintf_xml.c @@ -62,6 +62,7 @@ static char *proto2str[IPPROTO_MAX] = { [IPPROTO_SCTP] = "sctp", [IPPROTO_GRE] = "gre", [IPPROTO_UDPLITE] = "udplite", + [IPPROTO_DCCP] = "dccp", }; static char *l3proto2str[AF_MAX] = { [AF_INET] = "ipv4", -- cgit v1.2.3