diff options
author | Alex Harpin <development@landsofshadow.co.uk> | 2015-11-25 18:50:37 +0000 |
---|---|---|
committer | Alex Harpin <development@landsofshadow.co.uk> | 2015-11-25 18:50:37 +0000 |
commit | 04a362036d1d1b97e2c6560d431e73f14b269007 (patch) | |
tree | c540572d2078af88bc304b6f5ebd3e0f5848a2d7 | |
parent | 0049da2e13635a50d6d3324da19dcded340c3074 (diff) | |
parent | fbe3181be4f2e33509b1c20b95fd55eb3e7075d7 (diff) | |
download | conntrack-tools-04a362036d1d1b97e2c6560d431e73f14b269007.tar.gz conntrack-tools-04a362036d1d1b97e2c6560d431e73f14b269007.zip |
Merge tag 'conntrack-tools-1.4.2' into lithium
conntrack-tools 1.4.2 release
42 files changed, 439 insertions, 1151 deletions
diff --git a/Make_global.am b/Make_global.am index 23c7dd0..8084249 100644 --- a/Make_global.am +++ b/Make_global.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include AM_CFLAGS = -std=gnu99 -W -Wall \ - -Wmissing-prototypes -Wwrite-strings -Wcast-qual -Wfloat-equal -Wshadow -Wpointer-arith -Wbad-function-cast -Wsign-compare -Waggregate-return -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wstrict-prototypes -Wundef \ + -Wmissing-prototypes -Wwrite-strings -Wfloat-equal -Wshadow -Wpointer-arith -Wbad-function-cast -Wsign-compare -Waggregate-return -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wstrict-prototypes -Wundef \ -Wno-unused-parameter ${LIBNFNETLINK_CFLAGS} ${LIBMNL_CFLAGS} \ ${LIBNETFILTER_CONNTRACK_CFLAGS} \ ${LIBNETFILTER_CTTIMEOUT_CFLAGS} \ diff --git a/configure.ac b/configure.ac index 44c49e2..8bb4bec 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(conntrack-tools, 1.4.1, pablo@netfilter.org) +AC_INIT(conntrack-tools, 1.4.2, pablo@netfilter.org) AC_CONFIG_AUX_DIR([build-aux]) AC_CANONICAL_HOST @@ -56,7 +56,7 @@ fi PKG_CHECK_MODULES([LIBNFNETLINK], [libnfnetlink >= 1.0.1]) PKG_CHECK_MODULES([LIBMNL], [libmnl >= 1.0.3]) -PKG_CHECK_MODULES([LIBNETFILTER_CONNTRACK], [libnetfilter_conntrack >= 1.0.2]) +PKG_CHECK_MODULES([LIBNETFILTER_CONNTRACK], [libnetfilter_conntrack >= 1.0.4]) PKG_CHECK_MODULES([LIBNETFILTER_CTTIMEOUT], [libnetfilter_cttimeout >= 1.0.0]) PKG_CHECK_MODULES([LIBNETFILTER_CTHELPER], [libnetfilter_cthelper >= 1.0.0]) PKG_CHECK_MODULES([LIBNETFILTER_QUEUE], [libnetfilter_queue >= 1.0.2]) diff --git a/conntrack.8 b/conntrack.8 index a411fd4..f273434 100644 --- a/conntrack.8 +++ b/conntrack.8 @@ -88,11 +88,13 @@ Show the in-kernel connection tracking system statistics. Atomically zero counters after reading them. This option is only valid in combination with the "-L, --dump" command options. .TP -.BI "-o, --output [extended,xml,timestamp,id,ktimestamp] " +.BI "-o, --output [extended,xml,timestamp,id,ktimestamp,labels] " Display output in a certain format. With the extended output option, this tool displays the layer 3 information. With ktimestamp, it displays the in-kernel timestamp available since 2.6.38 (you can enable it via echo 1 > /proc/sys/net/netfilter/nf_conntrack_timestamp). +The labels output option tells conntrack to show the names of connection +tracking labels that might be present. .TP .BI "-e, --event-mask " "[ALL|NEW|UPDATES|DESTROY][,...]" Set the bitmask of events that are to be generated by the in-kernel ctnetlink @@ -142,6 +144,11 @@ the MARK value into the ctmark. Otherwise, the mask is logically ANDed with the existing mark before the comparision. In "--create" mode, the mask is ignored. .TP +.BI "-l, --label " "LABEL,..." +Specify the conntrack labels. +This option is only available in conjunction with "-L, --dump" or "-E, --event". +Match entries whose labels matches at least those specified as arguments. +.TP .BI "-c, --secmark " "SECMARK" Specify the conntrack selinux security mark. .TP diff --git a/include/conntrack.h b/include/conntrack.h index fd6126b..6cd9962 100644 --- a/include/conntrack.h +++ b/include/conntrack.h @@ -10,7 +10,7 @@ #include <netinet/in.h> #define NUMBER_OF_CMD 19 -#define NUMBER_OF_OPT 24 +#define NUMBER_OF_OPT 25 struct ctproto_handler { struct list_head head; diff --git a/include/conntrackd.h b/include/conntrackd.h index 19e613c..d338fc4 100644 --- a/include/conntrackd.h +++ b/include/conntrackd.h @@ -104,7 +104,6 @@ struct ct_conf { unsigned int netlink_buffer_size_max_grown; int nl_overrun_resync; unsigned int flags; - int family; /* protocol family */ unsigned int resend_queue_size; /* FTFW protocol */ unsigned int window_size; int poll_kernel_secs; diff --git a/include/filter.h b/include/filter.h index 3c7c8cc..d0acd96 100644 --- a/include/filter.h +++ b/include/filter.h @@ -51,6 +51,7 @@ void ct_filter_set_logic(struct ct_filter *f, enum ct_filter_type type, enum ct_filter_logic logic); int ct_filter_conntrack(const struct nf_conntrack *ct, int userspace); +int ct_filter_master(const struct nf_conntrack *master); struct exp_filter; struct nf_expect; diff --git a/include/internal.h b/include/internal.h index 2ba9714..1a796a7 100644 --- a/include/internal.h +++ b/include/internal.h @@ -40,6 +40,7 @@ struct internal_handler { void (*new)(struct nf_expect *exp, int origin_type); void (*upd)(struct nf_expect *exp, int origin_type); int (*del)(struct nf_expect *exp, int origin_type); + int (*find)(const struct nf_conntrack *master); void (*dump)(int fd, int type); void (*populate)(struct nf_expect *exp); diff --git a/include/network.h b/include/network.h index 41c35af..cc312cb 100644 --- a/include/network.h +++ b/include/network.h @@ -173,18 +173,6 @@ static inline int between(uint32_t seq1, uint32_t seq2, uint32_t seq3) return seq3 - seq2 >= seq1 - seq2; } -#define PLD_NETWORK2HOST(x) \ -({ \ - x->len = ntohs(x->len); \ - x->query = ntohs(x->query); \ -}) - -#define PLD_HOST2NETWORK(x) \ -({ \ - x->len = htons(x->len); \ - x->query = htons(x->query); \ -}) - struct netattr { uint16_t nta_len; uint16_t nta_attr; @@ -240,9 +228,13 @@ enum nta_attr { NTA_TCP_WSCALE_ORIG, /* uint8_t */ NTA_TCP_WSCALE_REPL, /* uint8_t */ NTA_HELPER_NAME, /* string (variable length) */ + NTA_LABELS, /* array of uint32_t (variable length) */ NTA_MAX }; +/* allow to serialize/replicate up to 4k labels per flow */ +#define NTA_LABELS_MAX_SIZE (4096/sizeof(uint32_t)) + struct nta_attr_natseqadj { uint32_t orig_seq_correction_pos; uint32_t orig_seq_offset_before; diff --git a/src/build.c b/src/build.c index 330f057..9ba8b57 100644 --- a/src/build.c +++ b/src/build.c @@ -162,6 +162,42 @@ static void build_l4proto_udp(const struct nf_conntrack *ct, struct nethdr *n) sizeof(struct nfct_attr_grp_port)); } +static void ct_build_clabel(const struct nf_conntrack *ct, struct nethdr *n) +{ + const struct nfct_bitmask *b; + uint32_t *words; + unsigned int wordcount, i, maxbit; + + if (!nfct_attr_is_set(ct, ATTR_CONNLABELS)) + return; + + b = nfct_get_attr(ct, ATTR_CONNLABELS); + + maxbit = nfct_bitmask_maxbit(b); + for (i=0; i <= maxbit; i++) { + if (nfct_bitmask_test_bit(b, i)) + break; + } + + if (i > maxbit) + return; + + wordcount = (nfct_bitmask_maxbit(b) / 32) + 1; + words = put_header(n, NTA_LABELS, wordcount * sizeof(*words)); + + for (i=0; i < wordcount; i++) { + int bit = 31; + uint32_t tmp = 0; + + do { + if (nfct_bitmask_test_bit(b, (32 * i) + bit)) + tmp |= (1 << bit); + } while (--bit >= 0); + + words[i] = htonl(tmp); + } +} + #ifndef IPPROTO_DCCP #define IPPROTO_DCCP 33 #endif @@ -237,6 +273,9 @@ void ct2msg(const struct nf_conntrack *ct, struct nethdr *n) if (nfct_attr_is_set(ct, ATTR_HELPER_NAME)) ct_build_str(ct, ATTR_HELPER_NAME, n, NTA_HELPER_NAME); + + if (nfct_attr_is_set(ct, ATTR_CONNLABELS)) + ct_build_clabel(ct, n); } static void diff --git a/src/cache-ct.c b/src/cache-ct.c index 0ad8d2a..f86d143 100644 --- a/src/cache-ct.c +++ b/src/cache-ct.c @@ -59,7 +59,7 @@ cache_hash6_ct(const struct nf_conntrack *ct, const struct hashtable *table) uint32_t a[10]; memcpy(&a[0], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4); - memcpy(&a[4], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4); + memcpy(&a[4], nfct_get_attr(ct, ATTR_IPV6_DST), sizeof(uint32_t)*4); a[8] = nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16 | nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); a[9] = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16 | @@ -88,14 +88,21 @@ cache_ct_hash(const void *data, const struct hashtable *table) return ret; } +/* master conntrack of expectations have no ID */ +static inline int +cache_ct_cmp_id(const struct nf_conntrack *ct1, const struct nf_conntrack *ct2) +{ + return nfct_attr_is_set(ct2, ATTR_ID) ? + nfct_get_attr_u32(ct1, ATTR_ID) == nfct_get_attr_u32(ct2, ATTR_ID) : 1; +} + static int cache_ct_cmp(const void *data1, const void *data2) { const struct cache_object *obj = data1; const struct nf_conntrack *ct = data2; return nfct_cmp(obj->ptr, ct, NFCT_CMP_ORIG) && - nfct_get_attr_u32(obj->ptr, ATTR_ID) == - nfct_get_attr_u32(ct, ATTR_ID); + cache_ct_cmp_id(obj->ptr, ct); } static void *cache_ct_alloc(void) diff --git a/src/cache-exp.c b/src/cache-exp.c index e88877a..9183b2c 100644 --- a/src/cache-exp.c +++ b/src/cache-exp.c @@ -59,7 +59,7 @@ cache_hash6_exp(const struct nf_conntrack *ct, const struct hashtable *table) uint32_t a[10]; memcpy(&a[0], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4); - memcpy(&a[4], nfct_get_attr(ct, ATTR_IPV6_SRC), sizeof(uint32_t)*4); + memcpy(&a[4], nfct_get_attr(ct, ATTR_IPV6_DST), sizeof(uint32_t)*4); a[8] = nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO) << 16 | nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); a[9] = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) << 16 | diff --git a/src/conntrack.c b/src/conntrack.c index 227c355..7d2a365 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -79,6 +79,9 @@ static struct { /* Allow to filter by mark from kernel-space. */ struct nfct_filter_dump_mark filter_mark_kernel; + + /* Allows filtering by ctlabels */ + struct nfct_bitmask *label; } tmpl; static int alloc_tmpl_objects(void) @@ -104,6 +107,8 @@ static void free_tmpl_objects(void) nfct_destroy(tmpl.mask); if (tmpl.exp) nfexp_destroy(tmpl.exp); + if (tmpl.label) + nfct_bitmask_destroy(tmpl.label); } enum ct_command { @@ -247,13 +252,16 @@ enum ct_options { CT_OPT_ZONE_BIT = 23, CT_OPT_ZONE = (1 << CT_OPT_ZONE_BIT), + + CT_OPT_LABEL_BIT = 24, + CT_OPT_LABEL = (1 << CT_OPT_LABEL_BIT), }; /* If you add a new option, you have to update NUMBER_OF_OPT in conntrack.h */ /* Update this mask to allow to filter based on new options. */ #define CT_COMPARISON (CT_OPT_PROTO | CT_OPT_ORIG | CT_OPT_REPL | \ CT_OPT_MARK | CT_OPT_SECMARK | CT_OPT_STATUS | \ - CT_OPT_ID | CT_OPT_ZONE) + CT_OPT_ID | CT_OPT_ZONE | CT_OPT_LABEL) static const char *optflags[NUMBER_OF_OPT] = { [CT_OPT_ORIG_SRC_BIT] = "src", @@ -280,6 +288,7 @@ static const char *optflags[NUMBER_OF_OPT] = { [CT_OPT_BUFFERSIZE_BIT] = "buffer-size", [CT_OPT_ANY_NAT_BIT] = "any-nat", [CT_OPT_ZONE_BIT] = "zone", + [CT_OPT_LABEL_BIT] = "label", }; static struct option original_opts[] = { @@ -320,12 +329,13 @@ static struct option original_opts[] = { {"buffer-size", 1, 0, 'b'}, {"any-nat", 2, 0, 'j'}, {"zone", 1, 0, 'w'}, + {"label", 1, 0, 'l'}, {0, 0, 0, 0} }; -static const char *getopt_str = "L::I::U::D::G::E::F::hVs:d:r:q:" +static const char *getopt_str = ":L::I::U::D::G::E::F::hVs:d:r:q:" "p:t:u:e:a:z[:]:{:}:m:i:f:o:n::" - "g::c:b:C::Sj::w:"; + "g::c:b:C::Sj::w:l:"; /* Table of legal combinations of commands and options. If any of the * given commands make an option legal, that option is legal (applies to @@ -340,26 +350,26 @@ static const char *getopt_str = "L::I::U::D::G::E::F::hVs:d:r:q:" static char commands_v_options[NUMBER_OF_CMD][NUMBER_OF_OPT] = /* Well, it's better than "Re: Linux vs FreeBSD" */ { - /* s d r q p t u z e [ ] { } a m i f n g o c b j w*/ -/*CT_LIST*/ {2,2,2,2,2,0,2,2,0,0,0,0,0,0,2,0,2,2,2,2,2,0,2,2}, -/*CT_CREATE*/ {3,3,3,3,1,1,2,0,0,0,0,0,0,2,2,0,0,2,2,0,0,0,0,2}, -/*CT_UPDATE*/ {2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0}, -/*CT_DELETE*/ {2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,2}, -/*CT_GET*/ {3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0}, -/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0,2,2,2,2,2,2,2}, -/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*HELP*/ {0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0}, -/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_GET*/ {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0}, -/*CT_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*CT_STATS*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_STATS*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + /* s d r q p t u z e [ ] { } a m i f n g o c b j w l*/ +/*CT_LIST*/ {2,2,2,2,2,0,2,2,0,0,0,0,0,0,2,0,2,2,2,2,2,0,2,2,2}, +/*CT_CREATE*/ {3,3,3,3,1,1,2,0,0,0,0,0,0,2,2,0,0,2,2,0,0,0,0,2,0}, +/*CT_UPDATE*/ {2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,0,0}, +/*CT_DELETE*/ {2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,2,2,2,2,0,0,0,2,0}, +/*CT_GET*/ {3,3,3,3,1,0,0,0,0,0,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0}, +/*CT_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*CT_EVENT*/ {2,2,2,2,2,0,0,0,2,0,0,0,0,0,2,0,0,2,2,2,2,2,2,2,2}, +/*VERSION*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*HELP*/ {0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,2,0,0,0,0,0}, +/*EXP_CREATE*/{1,1,2,2,1,1,2,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_DELETE*/{1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_GET*/ {1,1,2,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_EVENT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0}, +/*CT_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_COUNT*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*CT_STATS*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, +/*EXP_STATS*/ {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, }; static const int cmd2type[][2] = { @@ -391,6 +401,7 @@ static const int opt2type[] = { ['i'] = CT_OPT_ID, ['j'] = CT_OPT_ANY_NAT, ['w'] = CT_OPT_ZONE, + ['l'] = CT_OPT_LABEL, }; static const int opt2family_attr[][2] = { @@ -413,6 +424,7 @@ static const int opt2attr[] = { ['c'] = ATTR_SECMARK, ['i'] = ATTR_ID, ['w'] = ATTR_ZONE, + ['l'] = ATTR_CONNLABELS, }; static char exit_msg[NUMBER_OF_CMD][64] = { @@ -450,7 +462,8 @@ static const char usage_conntrack_parameters[] = " -c, --secmark secmark\t\t\tSet selinux secmark\n" " -e, --event-mask eventmask\t\tEvent mask, eg. NEW,DESTROY\n" " -z, --zero \t\t\t\tZero counters while listing\n" - " -o, --output type[,...]\t\tOutput format, eg. xml\n"; + " -o, --output type[,...]\t\tOutput format, eg. xml\n" + " -l, --label label[,...]\t\tconntrack labels\n"; static const char usage_expectation_parameters[] = "Expectation parameters and options:\n" @@ -488,6 +501,7 @@ static unsigned int addr_valid_flags[ADDR_VALID_FLAGS_MAX] = { static LIST_HEAD(proto_list); static unsigned int options; +static struct nfct_labelmap *labelmap; void register_proto(struct ctproto_handler *h) { @@ -731,6 +745,7 @@ enum { _O_TMS = (1 << 2), _O_ID = (1 << 3), _O_KTMS = (1 << 4), + _O_CL = (1 << 5), }; enum { @@ -749,8 +764,8 @@ static struct parse_parameter { { IPS_ASSURED, IPS_SEEN_REPLY, 0, IPS_FIXED_TIMEOUT, IPS_EXPECTED} }, { {"ALL", "NEW", "UPDATES", "DESTROY"}, 4, { CT_EVENT_F_ALL, CT_EVENT_F_NEW, CT_EVENT_F_UPD, CT_EVENT_F_DEL } }, - { {"xml", "extended", "timestamp", "id", "ktimestamp"}, 5, - { _O_XML, _O_EXT, _O_TMS, _O_ID, _O_KTMS }, + { {"xml", "extended", "timestamp", "id", "ktimestamp", "labels", }, 6, + { _O_XML, _O_EXT, _O_TMS, _O_ID, _O_KTMS, _O_CL }, }, }; @@ -814,6 +829,59 @@ parse_u32_mask(const char *arg, struct u32_mask *m) m->mask = ~0; } +static int +get_label(char *name) +{ + int bit = nfct_labelmap_get_bit(labelmap, name); + if (bit < 0) + exit_error(PARAMETER_PROBLEM, "unknown label '%s'", name); + return bit; +} + +static void +set_label(struct nfct_bitmask *b, char *name) +{ + int bit = get_label(name); + nfct_bitmask_set_bit(b, bit); +} + +static unsigned int +set_max_label(char *name, unsigned int current_max) +{ + int bit = get_label(name); + if ((unsigned int) bit > current_max) + return (unsigned int) bit; + return current_max; +} + +static unsigned int +parse_label_get_max(char *arg) +{ + unsigned int max = 0; + char *parse; + + while ((parse = strchr(arg, ',')) != NULL) { + parse[0] = '\0'; + max = set_max_label(arg, max); + arg = &parse[1]; + } + + max = set_max_label(arg, max); + return max; +} + +static void +parse_label(struct nfct_bitmask *b, char *arg) +{ + char * parse; + while ((parse = strchr(arg, ',')) != NULL) { + parse[0] = '\0'; + set_label(b, arg); + arg = &parse[1]; + } + set_label(b, arg); +} + static void add_command(unsigned int *cmd, const int newcmd) { @@ -982,6 +1050,24 @@ usage(char *prog) static unsigned int output_mask; +static int +filter_label(const struct nf_conntrack *ct) +{ + if (tmpl.label == NULL) + return 0; + + const struct nfct_bitmask *ctb = nfct_get_attr(ct, ATTR_CONNLABELS); + if (ctb == NULL) + return 1; + + for (unsigned int i = 0; i <= nfct_bitmask_maxbit(tmpl.label); i++) { + if (nfct_bitmask_test_bit(tmpl.label, i) && + !nfct_bitmask_test_bit(ctb, i)) + return 1; + } + + return 0; +} static int filter_mark(const struct nf_conntrack *ct) @@ -992,7 +1078,6 @@ filter_mark(const struct nf_conntrack *ct) return 0; } - static int filter_nat(const struct nf_conntrack *obj, const struct nf_conntrack *ct) { @@ -1123,6 +1208,9 @@ static int event_cb(enum nf_conntrack_msg_type type, if (filter_mark(ct)) return NFCT_CB_CONTINUE; + if (filter_label(ct)) + return NFCT_CB_CONTINUE; + if (options & CT_COMPARISON && !nfct_cmp(obj, ct, NFCT_CMP_ALL | NFCT_CMP_MASK)) return NFCT_CB_CONTINUE; @@ -1141,7 +1229,7 @@ static int event_cb(enum nf_conntrack_msg_type type, if (!(output_mask & _O_XML)) { struct timeval tv; gettimeofday(&tv, NULL); - printf("[%-8ld.%-6ld]\t", tv.tv_sec, tv.tv_usec); + printf("[%-.8ld.%-.6ld]\t", tv.tv_sec, tv.tv_usec); } else op_flags |= NFCT_OF_TIME; } @@ -1150,7 +1238,7 @@ static int event_cb(enum nf_conntrack_msg_type type, if (output_mask & _O_ID) op_flags |= NFCT_OF_ID; - nfct_snprintf(buf, sizeof(buf), ct, type, op_type, op_flags); + nfct_snprintf_labels(buf, sizeof(buf), ct, type, op_type, op_flags, labelmap); printf("%s\n", buf); fflush(stdout); @@ -1175,6 +1263,9 @@ static int dump_cb(enum nf_conntrack_msg_type type, if (filter_mark(ct)) return NFCT_CB_CONTINUE; + if (filter_label(ct)) + return NFCT_CB_CONTINUE; + if (options & CT_COMPARISON && !nfct_cmp(obj, ct, NFCT_CMP_ALL | NFCT_CMP_MASK)) return NFCT_CB_CONTINUE; @@ -1194,7 +1285,7 @@ static int dump_cb(enum nf_conntrack_msg_type type, if (output_mask & _O_ID) op_flags |= NFCT_OF_ID; - nfct_snprintf(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, op_type, op_flags); + nfct_snprintf_labels(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, op_type, op_flags, labelmap); printf("%s\n", buf); counter++; @@ -1879,6 +1970,12 @@ int main(int argc, char *argv[]) case 'o': options |= CT_OPT_OUTPUT; parse_parameter(optarg, &output_mask, PARSE_OUTPUT); + if (output_mask & _O_CL) { + if (!labelmap) + labelmap = nfct_labelmap_new(NULL); + if (!labelmap) + perror("nfct_labelmap_new"); + } break; case 'z': options |= CT_OPT_ZERO; @@ -1922,6 +2019,22 @@ int main(int argc, char *argv[]) tmpl.filter_mark_kernel.val = tmpl.mark.value; tmpl.filter_mark_kernel.mask = tmpl.mark.mask; break; + case 'l': + options |= opt2type[c]; + char *optarg2 = strdup(optarg); + + if (!labelmap) + labelmap = nfct_labelmap_new(NULL); + if (!labelmap) + exit_error(OTHER_PROBLEM, "unable to open labelmap file"); + + unsigned int max = parse_label_get_max(optarg); + struct nfct_bitmask * b = nfct_bitmask_new(max); + + parse_label(b, optarg2); + tmpl.label = b; + free(optarg2); + break; case 'a': fprintf(stderr, "WARNING: ignoring -%c, " "deprecated option.\n", c); @@ -1941,15 +2054,13 @@ int main(int argc, char *argv[]) socketbuffersize = atol(optarg); options |= CT_OPT_BUFFERSIZE; break; + case ':': + exit_error(PARAMETER_PROBLEM, + "option `%s' requires an " + "argument", argv[optind-1]); case '?': - if (optopt) - exit_error(PARAMETER_PROBLEM, - "option `%s' requires an " - "argument", argv[optind-1]); - else - exit_error(PARAMETER_PROBLEM, - "unknown option `%s'", - argv[optind-1]); + exit_error(PARAMETER_PROBLEM, + "unknown option `%s'", argv[optind-1]); break; default: if (h && h->parse_opts @@ -2372,6 +2483,8 @@ try_proc: free_tmpl_objects(); free_options(); + if (labelmap) + nfct_labelmap_destroy(labelmap); if (command && exit_msg[cmd][0]) { fprintf(stderr, "%s v%s (conntrack-tools): ",PROGNAME,VERSION); diff --git a/src/cthelper.c b/src/cthelper.c index 307be96..5a8a92a 100644 --- a/src/cthelper.c +++ b/src/cthelper.c @@ -30,6 +30,7 @@ #include <netinet/in.h> #include <netinet/ip.h> +#include <netinet/ip6.h> #include <netinet/tcp.h> #include <netinet/udp.h> #include <net/ethernet.h> @@ -77,6 +78,8 @@ nfq_hdr_put(char *buf, int type, uint32_t queue_num) static int pkt_get(void *pkt, uint32_t pktlen, uint16_t proto, uint32_t *protoff) { + uint8_t protocol; + switch(proto) { case ETHERTYPE_IP: { struct iphdr *ip = (struct iphdr *) pkt; @@ -94,41 +97,60 @@ pkt_get(void *pkt, uint32_t pktlen, uint16_t proto, uint32_t *protoff) } *protoff = 4 * ip->ihl; + protocol = ip->protocol; + break; + } + case ETHERTYPE_IPV6: { + struct iphdr *ip = (struct iphdr *) pkt; + struct ip6_hdr *ip6 = (struct ip6_hdr *) pkt; - switch (ip->protocol) { - case IPPROTO_TCP: { - struct tcphdr *tcph = - (struct tcphdr *) ((char *)pkt + *protoff); - - /* No room for IPv4 header plus TCP header. */ - if (pktlen < *protoff + sizeof(struct tcphdr) - || pktlen < *protoff + tcph->doff * 4) { - dlog(LOG_ERR, "no room for IPv4 + TCP header, skip"); - return -1; - } - return 0; + /* No room for IPv6 header. */ + if (pktlen < sizeof(struct ip6_hdr)) { + dlog(LOG_ERR, "no room for IPv6 header"); + return -1; } - case IPPROTO_UDP: - /* No room for IPv4 header plus UDP header. */ - if (pktlen < *protoff + sizeof(struct udphdr)) { - dlog(LOG_ERR, "no room for IPv4 + UDP header, skip"); - return -1; - } - return 0; - default: - dlog(LOG_ERR, "not TCP/UDP, skipping"); + + /* this is not IPv6, skip. */ + if (ip->version != 6) { + dlog(LOG_ERR, "not IPv6, skipping"); return -1; } + + *protoff = sizeof(struct ip6_hdr); + protocol = ip6->ip6_nxt; break; } - case ETHERTYPE_IPV6: - dlog(LOG_ERR, "no IPv6 support sorry"); - return 0; default: /* Unknown layer 3 protocol. */ dlog(LOG_ERR, "unknown layer 3 protocol (%d), skipping", proto); return -1; } + + switch (protocol) { + case IPPROTO_TCP: { + struct tcphdr *tcph = + (struct tcphdr *) ((char *)pkt + *protoff); + + /* No room for IPv4 header plus TCP header. */ + if (pktlen < *protoff + sizeof(struct tcphdr) || + pktlen < *protoff + tcph->doff * 4) { + dlog(LOG_ERR, "no room for IPv4 + TCP header, skip"); + return -1; + } + return 0; + } + case IPPROTO_UDP: + /* No room for IPv4 header plus UDP header. */ + if (pktlen < *protoff + sizeof(struct udphdr)) { + dlog(LOG_ERR, "no room for IPv4 + UDP header, skip"); + return -1; + } + return 0; + default: + dlog(LOG_ERR, "not TCP/UDP, skipping"); + return -1; + } + return 0; } @@ -143,9 +165,11 @@ pkt_verdict_issue(struct ctd_helper_instance *cur, struct myct *myct, nlh = nfq_hdr_put(buf, NFQNL_MSG_VERDICT, queue_num); - /* save private data and send it back to kernel-space. */ - nfct_set_attr_l(myct->ct, ATTR_HELPER_INFO, myct->priv_data, - cur->helper->priv_data_len); + /* save private data and send it back to kernel-space, if any. */ + if (myct->priv_data) { + nfct_set_attr_l(myct->ct, ATTR_HELPER_INFO, myct->priv_data, + cur->helper->priv_data_len); + } nfq_nlmsg_verdict_put(nlh, id, verdict); if (pktb_mangled(pktb)) @@ -226,7 +226,7 @@ static int exp_event_handler(const struct nlmsghdr *nlh, STATE(stats).nl_events_filtered++; goto out; } - if (ct_filter_conntrack(master, 1)) + if (ct_filter_master(master)) return NFCT_CB_CONTINUE; origin_type = origin_find(nlh); @@ -281,7 +281,7 @@ static int exp_dump_handler(enum nf_conntrack_msg_type type, if (!exp_filter_find(STATE(exp_filter), exp)) return NFCT_CB_CONTINUE; - if (ct_filter_conntrack(master, 1)) + if (ct_filter_master(master)) return NFCT_CB_CONTINUE; switch(type) { @@ -315,7 +315,7 @@ static int exp_get_handler(enum nf_conntrack_msg_type type, if (!exp_filter_find(STATE(exp_filter), exp)) return NFCT_CB_CONTINUE; - if (ct_filter_conntrack(master, 1)) + if (ct_filter_master(master)) return NFCT_CB_CONTINUE; STATE(get_retval) = 1; diff --git a/src/expect.c b/src/expect.c index 6069770..470b9ae 100644 --- a/src/expect.c +++ b/src/expect.c @@ -54,7 +54,7 @@ cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master, nfct_set_attr(expected, ATTR_IPV6_SRC, saddr->ip6); for (i=0; i<4; i++) - memset(addr, 0xffffffff, sizeof(uint32_t)); + memset(&addr[i], 0xffffffff, sizeof(uint32_t)); nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET6); nfct_set_attr(mask, ATTR_IPV6_SRC, addr); @@ -76,7 +76,7 @@ cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master, break; case AF_INET6: for (i=0; i<4; i++) - memset(addr, 0x00000000, sizeof(uint32_t)); + memset(&addr[i], 0x00000000, sizeof(uint32_t)); nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET6); nfct_set_attr(expected, ATTR_IPV6_SRC, addr); diff --git a/src/filter.c b/src/filter.c index 02a8078..8fac71b 100644 --- a/src/filter.c +++ b/src/filter.c @@ -373,8 +373,8 @@ static inline int ct_filter_sanity_check(const struct nf_conntrack *ct) switch(nfct_get_attr_u8(ct, ATTR_L3PROTO)) { case AF_INET: - if (!nfct_attr_is_set(ct, ATTR_IPV4_SRC) || - !nfct_attr_is_set(ct, ATTR_IPV4_DST)) { + if (!nfct_attr_is_set(ct, ATTR_ORIG_IPV4_SRC) || + !nfct_attr_is_set(ct, ATTR_REPL_IPV4_SRC)) { dlog(LOG_ERR, "missing IPv4 address. " "You forgot to load " "nf_conntrack_ipv4?"); @@ -382,8 +382,8 @@ static inline int ct_filter_sanity_check(const struct nf_conntrack *ct) } break; case AF_INET6: - if (!nfct_attr_is_set(ct, ATTR_IPV6_SRC) || - !nfct_attr_is_set(ct, ATTR_IPV6_DST)) { + if (!nfct_attr_is_set(ct, ATTR_ORIG_IPV6_SRC) || + !nfct_attr_is_set(ct, ATTR_REPL_IPV6_SRC)) { dlog(LOG_ERR, "missing IPv6 address. " "You forgot to load " "nf_conntrack_ipv6?"); @@ -407,6 +407,51 @@ int ct_filter_conntrack(const struct nf_conntrack *ct, int userspace) return 0; } +static inline int +ct_filter_master_sanity_check(const struct nf_conntrack *master) +{ + if (master == NULL) { + dlog(LOG_ERR, "no master tuple in expectation"); + return 0; + } + + if (!nfct_attr_is_set(master, ATTR_L3PROTO)) { + dlog(LOG_ERR, "missing layer 3 protocol"); + return 0; + } + + switch (nfct_get_attr_u8(master, ATTR_L3PROTO)) { + case AF_INET: + if (!nfct_attr_is_set(master, ATTR_IPV4_SRC) || + !nfct_attr_is_set(master, ATTR_IPV4_DST)) { + dlog(LOG_ERR, "missing IPv4 address. " + "You forgot to load nf_conntrack_ipv4?"); + return 0; + } + break; + case AF_INET6: + if (!nfct_attr_is_set(master, ATTR_IPV6_SRC) || + !nfct_attr_is_set(master, ATTR_IPV6_DST)) { + dlog(LOG_ERR, "missing IPv6 address. " + "You forgot to load nf_conntrack_ipv6?"); + return 0; + } + break; + } + return 1; +} + +int ct_filter_master(const struct nf_conntrack *master) +{ + if (!ct_filter_master_sanity_check(master)) + return 1; + + /* Check if we've got a master conntrack for this expectation in our + * caches. If there is not, we don't want this expectation either. + */ + return STATE(mode)->internal->exp.find(master) ? 0 : 1; +} + struct exp_filter { struct list_head list; }; diff --git a/src/internal_bypass.c b/src/internal_bypass.c index 1194339..ce2ae46 100644 --- a/src/internal_bypass.c +++ b/src/internal_bypass.c @@ -283,6 +283,11 @@ static int internal_bypass_exp_event_del(struct nf_expect *exp, int origin) return 1; } +static int internal_bypass_exp_master_find(const struct nf_conntrack *master) +{ + return nl_get_conntrack(STATE(get), master) == 0; +} + struct internal_handler internal_bypass = { .init = internal_bypass_init, .close = internal_bypass_close, @@ -309,5 +314,6 @@ struct internal_handler internal_bypass = { .new = internal_bypass_exp_event_new, .upd = internal_bypass_exp_event_upd, .del = internal_bypass_exp_event_del, + .find = internal_bypass_exp_master_find, }, }; diff --git a/src/internal_cache.c b/src/internal_cache.c index ba2d74b..bad31f3 100644 --- a/src/internal_cache.c +++ b/src/internal_cache.c @@ -364,6 +364,16 @@ static int internal_cache_exp_event_del(struct nf_expect *exp, int origin) return 1; } +static int internal_cache_exp_master_find(const struct nf_conntrack *master) +{ + struct cache_object *obj; + int id; + + obj = cache_find(STATE(mode)->internal->ct.data, + (struct nf_conntrack *)master, &id); + return obj ? 1 : 0; +} + struct internal_handler internal_cache = { .flags = INTERNAL_F_POPULATE | INTERNAL_F_RESYNC, .init = internal_cache_init, @@ -391,5 +401,6 @@ struct internal_handler internal_cache = { .new = internal_cache_exp_event_new, .upd = internal_cache_exp_event_upd, .del = internal_cache_exp_event_del, + .find = internal_cache_exp_master_find, }, }; @@ -23,6 +23,7 @@ #include <sys/types.h> #include <sys/stat.h> +#include <errno.h> #include <fcntl.h> #include <sys/utsname.h> #include <string.h> @@ -112,6 +113,23 @@ set_action_by_table(int i, int argc, char *argv[], return i; } +static void +set_nice_value(int nv) +{ + errno = 0; + if (nice(nv) == -1 && errno) /* warn only */ + fprintf(stderr, "Cannot set nice level %d: %s\n", + nv, strerror(errno)); +} + +static void +do_chdir(const char *d) +{ + if (chdir(d)) + fprintf(stderr, "Cannot change current directory to %s: %s\n", + d, strerror(errno)); +} + int main(int argc, char *argv[]) { int ret, i, action = -1; @@ -356,7 +374,7 @@ int main(int argc, char *argv[]) /* * Setting process priority and scheduler */ - nice(CONFIG(nice)); + set_nice_value(CONFIG(nice)); if (CONFIG(sched).type != SCHED_OTHER) { struct sched_param schedparam = { @@ -382,7 +400,7 @@ int main(int argc, char *argv[]) exit(EXIT_FAILURE); } - chdir("/"); + do_chdir("/"); close(STDIN_FILENO); /* Daemonize conntrackd */ diff --git a/src/netlink.c b/src/netlink.c index bd38d99..5be102e 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -146,9 +146,11 @@ void nl_resize_socket_buffer(struct nfct_handle *h) "to %u bytes", CONFIG(netlink_buffer_size)); } +static const int family = AF_UNSPEC; + int nl_dump_conntrack_table(struct nfct_handle *h) { - return nfct_query(h, NFCT_Q_DUMP, &CONFIG(family)); + return nfct_query(h, NFCT_Q_DUMP, &family); } static int @@ -182,7 +184,7 @@ int nl_flush_conntrack_table_selective(void) } nfct_callback_register(h, NFCT_T_ALL, nl_flush_selective_cb, NULL); - ret = nfct_query(h, NFCT_Q_DUMP, &CONFIG(family)); + ret = nfct_query(h, NFCT_Q_DUMP, &family); nfct_close(h); @@ -191,7 +193,6 @@ int nl_flush_conntrack_table_selective(void) int nl_send_resync(struct nfct_handle *h) { - int family = CONFIG(family); return nfct_send(h, NFCT_Q_DUMP, &family); } @@ -380,16 +381,15 @@ int nl_get_expect(struct nfct_handle *h, const struct nf_expect *exp) int nl_dump_expect_table(struct nfct_handle *h) { - return nfexp_query(h, NFCT_Q_DUMP, &CONFIG(family)); + return nfexp_query(h, NFCT_Q_DUMP, &family); } int nl_flush_expect_table(struct nfct_handle *h) { - return nfexp_query(h, NFCT_Q_FLUSH, &CONFIG(family)); + return nfexp_query(h, NFCT_Q_FLUSH, &family); } int nl_send_expect_resync(struct nfct_handle *h) { - int family = CONFIG(family); return nfexp_send(h, NFCT_Q_DUMP, &family); } diff --git a/src/parse.c b/src/parse.c index 8ce4495..f3ec6ac 100644 --- a/src/parse.c +++ b/src/parse.c @@ -29,15 +29,19 @@ static void ct_parse_u8(struct nf_conntrack *ct, int attr, void *data); static void ct_parse_u16(struct nf_conntrack *ct, int attr, void *data); static void ct_parse_u32(struct nf_conntrack *ct, int attr, void *data); -static void ct_parse_str(struct nf_conntrack *ct, int attr, void *data); +static void ct_parse_str(struct nf_conntrack *ct, + const struct netattr *, void *data); static void ct_parse_group(struct nf_conntrack *ct, int attr, void *data); static void ct_parse_nat_seq_adj(struct nf_conntrack *ct, int attr, void *data); +static void ct_parse_clabel(struct nf_conntrack *ct, + const struct netattr *, void *data); struct ct_parser { void (*parse)(struct nf_conntrack *ct, int attr, void *data); - int attr; - int size; - int max_size; + void (*parse2)(struct nf_conntrack *ct, const struct netattr *, void *); + uint16_t attr; + uint16_t size; + uint16_t max_size; }; static struct ct_parser h[NTA_MAX] = { @@ -176,10 +180,15 @@ static struct ct_parser h[NTA_MAX] = { .size = NTA_SIZE(sizeof(uint8_t)), }, [NTA_HELPER_NAME] = { - .parse = ct_parse_str, + .parse2 = ct_parse_str, .attr = ATTR_HELPER_NAME, .max_size = NFCT_HELPER_NAME_MAX, }, + [NTA_LABELS] = { + .parse2 = ct_parse_clabel, + .attr = ATTR_CONNLABELS, + .max_size = NTA_SIZE(NTA_LABELS_MAX_SIZE), + }, }; static void @@ -204,9 +213,9 @@ ct_parse_u32(struct nf_conntrack *ct, int attr, void *data) } static void -ct_parse_str(struct nf_conntrack *ct, int attr, void *data) +ct_parse_str(struct nf_conntrack *ct, const struct netattr *attr, void *data) { - nfct_set_attr(ct, h[attr].attr, data); + nfct_set_attr(ct, h[attr->nta_attr].attr, data); } static void @@ -216,6 +225,44 @@ ct_parse_group(struct nf_conntrack *ct, int attr, void *data) } static void +ct_parse_clabel(struct nf_conntrack *ct, const struct netattr *attr, void *data) +{ + struct nfct_bitmask *bitm; + unsigned int i, wordcount; + const uint32_t *words; + unsigned int len; + + len = attr->nta_len - NTA_LENGTH(0); + wordcount = len / sizeof(*words); + if (!wordcount) + return; + + if (len & (sizeof(*words) - 1)) + return; + + bitm = nfct_bitmask_new((len * 8) - 1); + if (!bitm) + return; + + words = data; + for (i=0; i < wordcount; i++) { + uint32_t word; + int bit; + + if (words[i] == 0) + continue; + + word = htonl(words[i]); + bit = 31; + do { + if (word & (1 << bit)) + nfct_bitmask_set_bit(bitm, (32 * i) + bit); + } while (--bit >= 0); + } + nfct_set_attr(ct, ATTR_CONNLABELS, bitm); +} + +static void ct_parse_nat_seq_adj(struct nf_conntrack *ct, int attr, void *data) { struct nta_attr_natseqadj *this = data; @@ -248,14 +295,22 @@ int msg2ct(struct nf_conntrack *ct, struct nethdr *net, size_t remain) ATTR_NETWORK2HOST(attr); if (attr->nta_len > len) return -1; + if (attr->nta_len < NTA_LENGTH(0)) + return -1; if (attr->nta_attr > NTA_MAX) return -1; if (h[attr->nta_attr].size && attr->nta_len != h[attr->nta_attr].size) return -1; - if (h[attr->nta_attr].max_size && - attr->nta_len > h[attr->nta_attr].max_size) - return -1; + + if (h[attr->nta_attr].max_size) { + if (attr->nta_len > h[attr->nta_attr].max_size) + return -1; + h[attr->nta_attr].parse2(ct, attr, NTA_DATA(attr)); + attr = NTA_NEXT(attr, len); + continue; + } + if (h[attr->nta_attr].parse == NULL) { attr = NTA_NEXT(attr, len); continue; @@ -457,6 +512,8 @@ int msg2exp(struct nf_expect *exp, struct nethdr *net, size_t remain) goto err; if (attr->nta_attr > NTA_MAX) goto err; + if (attr->nta_len < NTA_LENGTH(0)) + goto err; if (exp_h[attr->nta_attr].size && attr->nta_len != exp_h[attr->nta_attr].size) goto err; diff --git a/src/read_config_lex.l b/src/read_config_lex.l index bec2d81..b4d11d4 100644 --- a/src/read_config_lex.l +++ b/src/read_config_lex.l @@ -44,8 +44,8 @@ ip4 {ip4_part}\.{ip4_part}\.{ip4_part}\.{ip4_part}{ip4_cidr}? hex_255 [0-9a-fA-F]{1,4} ip6_cidr \/[0-1]*[0-9]*[0-9]+ ip6_part {hex_255}":"? -ip6_form1 {ip6_part}{0,16}"::"{ip6_part}{0,16} -ip6_form2 ({hex_255}":"){16}{hex_255} +ip6_form1 {ip6_part}{0,7}"::"{ip6_part}{0,7} +ip6_form2 ({hex_255}":"){0,7}{hex_255} ip6 {ip6_form1}{ip6_cidr}?|{ip6_form2}{ip6_cidr}? string [a-zA-Z][a-zA-Z0-9\.\-]* persistent [P|p][E|e][R|r][S|s][I|i][S|s][T|t][E|e][N|n][T|T] diff --git a/src/read_config_yy.y b/src/read_config_yy.y index 72a9654..b824150 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -1193,10 +1193,7 @@ scheduler_line : T_PRIO T_NUMBER family : T_FAMILY T_STRING { - if (strncmp($2, "IPv6", strlen("IPv6")) == 0) - conf.family = AF_INET6; - else - conf.family = AF_INET; + print_err(CTD_CFG_WARN, "`Family' is deprecated, ignoring"); }; event_iterations_limit : T_EVENT_ITER_LIMIT T_NUMBER @@ -1863,10 +1860,6 @@ init_config(char *filename) yyparse(); fclose(fp); - /* default to IPv4 */ - if (CONFIG(family) == 0) - CONFIG(family) = AF_INET; - /* set to default is not specified */ if (strcmp(CONFIG(lockfile), "") == 0) strncpy(CONFIG(lockfile), DEFAULT_LOCKFILE, FILENAME_MAXLEN); @@ -40,14 +40,14 @@ #include <time.h> #include <fcntl.h> -void killer(int signal) +void killer(int signo) { /* Signals are re-entrant, disable signal handling to avoid problems * in case we receive SIGINT and SIGTERM in a row. This function is * also called via -k from the unix socket context, we already disabled * signals in that path, so don't do it. */ - if (signal) + if (signo) sigprocmask(SIG_BLOCK, &STATE(block), NULL); local_server_destroy(&STATE(local)); diff --git a/tests/conntrackd/cthelper/.gitignore b/tests/conntrackd/cthelper/.gitignore deleted file mode 100644 index 928e44b..0000000 --- a/tests/conntrackd/cthelper/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -.deps/ -.libs/ -Makefile -Makefile.in -*.o -*.la -*.lo - -/aclocal.m4 -/autom4te.cache/ -/build-aux/ -/config.* -/configure -/libtool diff --git a/tests/conntrackd/cthelper/Make_global.am b/tests/conntrackd/cthelper/Make_global.am deleted file mode 100644 index 06785a1..0000000 --- a/tests/conntrackd/cthelper/Make_global.am +++ /dev/null @@ -1,7 +0,0 @@ -AM_CPPFLAGS = -I$(top_srcdir)/include -I../../../include - -AM_CFLAGS = -std=gnu99 -W -Wall \ - -Wmissing-prototypes -Wwrite-strings -Wcast-qual -Wfloat-equal -Wshadow -Wpointer-arith -Wbad-function-cast -Wsign-compare -Waggregate-return -Wmissing-declarations -Wredundant-decls -Wnested-externs -Winline -Wstrict-prototypes -Wundef \ - -Wno-unused-parameter \ - ${LIBNETFILTER_CONNTRACK_CFLAGS} \ - ${LIBNETFILTER_CTTIMEOUT_CFLAGS} diff --git a/tests/conntrackd/cthelper/Makefile.am b/tests/conntrackd/cthelper/Makefile.am deleted file mode 100644 index b8f0d42..0000000 --- a/tests/conntrackd/cthelper/Makefile.am +++ /dev/null @@ -1,20 +0,0 @@ -include $(top_srcdir)/Make_global.am - -check_PROGRAMS = cthelper-test - -cthelper_test_SOURCES = proto.c \ - ct.c \ - l3_ipv4.c \ - l4_tcp.c \ - l4_udp.c \ - expect.c \ - ../../../src/helpers.c \ - main.c - -cthelper_test_LDFLAGS = -dynamic \ - -lpcap \ - -ldl \ - -lmnl \ - -lnetfilter_queue \ - -lnetfilter_conntrack \ - -export-dynamic diff --git a/tests/conntrackd/cthelper/README b/tests/conntrackd/cthelper/README deleted file mode 100644 index 6e8b385..0000000 --- a/tests/conntrackd/cthelper/README +++ /dev/null @@ -1,2 +0,0 @@ -This directory contains PCAP files with traffic traces that we can use to test -the user-space helpers. diff --git a/tests/conntrackd/cthelper/configure.ac b/tests/conntrackd/cthelper/configure.ac deleted file mode 100644 index 8b3da5c..0000000 --- a/tests/conntrackd/cthelper/configure.ac +++ /dev/null @@ -1,64 +0,0 @@ -AC_INIT(cthelper-test, 0.0.1, pablo@netfilter.org) -AC_CONFIG_AUX_DIR([build-aux]) - -AC_CANONICAL_HOST -AC_CONFIG_MACRO_DIR([m4]) -AM_INIT_AUTOMAKE([-Wall foreign subdir-objects - tar-pax no-dist-gzip dist-bzip2 1.6]) - -dnl kernel style compile messages -m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) - -AC_SEARCH_LIBS([dlopen], [dl], [libdl_LIBS="$LIBS"; LIBS=""]) -AC_SUBST([libdl_LIBS]) - -AC_PROG_CC -AC_DISABLE_STATIC -AM_PROG_LIBTOOL -AC_PROG_INSTALL -AC_PROG_LN_S -AM_PROG_LEX -AC_PROG_YACC - -case "$host" in -*-*-linux*) ;; -*) AC_MSG_ERROR([Linux only, dude!]);; -esac - -PKG_CHECK_MODULES([LIBNETFILTER_CONNTRACK], [libnetfilter_conntrack >= 1.0.0]) -PKG_CHECK_MODULES([LIBNETFILTER_QUEUE], [libnetfilter_queue >= 1.0.0]) - -AC_CHECK_HEADERS(arpa/inet.h) -dnl check for inet_pton -AC_CHECK_FUNCS(inet_pton) -dnl Some systems have it, but not IPv6 -if test "$ac_cv_func_inet_pton" = "yes" ; then -AC_MSG_CHECKING(if inet_pton supports IPv6) -AC_RUN_IFELSE([AC_LANG_SOURCE([[ -#ifdef HAVE_SYS_TYPES_H -#include <sys/types.h> -#endif -#ifdef HAVE_SYS_SOCKET_H -#include <sys/socket.h> -#endif -#ifdef HAVE_NETINET_IN_H -#include <netinet/in.h> -#endif -#ifdef HAVE_ARPA_INET_H -#include <arpa/inet.h> -#endif -int main() - { - struct in6_addr addr6; - if (inet_pton(AF_INET6, "::1", &addr6) < 1) - exit(1); - else - exit(0); - } - ]])],[ AC_MSG_RESULT(yes) - AC_DEFINE_UNQUOTED(HAVE_INET_PTON_IPV6, 1, [Define to 1 if inet_pton supports IPv6.]) - ],[AC_MSG_RESULT(no)],[AC_MSG_RESULT(no)]) -fi - -AC_CONFIG_FILES([Makefile]) -AC_OUTPUT diff --git a/tests/conntrackd/cthelper/ct.c b/tests/conntrackd/cthelper/ct.c deleted file mode 100755 index 1c17336..0000000 --- a/tests/conntrackd/cthelper/ct.c +++ /dev/null @@ -1,91 +0,0 @@ -#include <stdlib.h> -#include <netinet/ip.h> -#include <netinet/tcp.h> - -#include <linux/if_ether.h> - -#include <libnetfilter_conntrack/libnetfilter_conntrack.h> - -#include "proto.h" -#include "helper.h" -#include "myct.h" -#include "ct.h" - -static LIST_HEAD(ct_list); - -struct nf_ct_entry * -ct_alloc(const uint8_t *pkt, unsigned int l3hdr_len, - struct cthelper_proto_l2l3_helper *l3h, - struct cthelper_proto_l4_helper *l4h) -{ - struct nf_ct_entry *ct; - - ct = calloc(1, sizeof(struct nf_ct_entry)); - if (ct == NULL) - return NULL; - - ct->myct = calloc(1, sizeof(struct myct)); - if (ct->myct == NULL) { - free(ct); - return NULL; - } - ct->myct->ct = nfct_new(); - if (ct->myct->ct == NULL) { - free(ct->myct); - free(ct); - return NULL; - } - /* FIXME: use good private helper size */ - ct->myct->priv_data = calloc(1, 128); - if (ct->myct->priv_data == NULL) { - nfct_destroy(ct->myct->ct); - free(ct->myct); - free(ct); - return NULL; - } - - l3h->l3ct_build(pkt, ct->myct->ct); - l4h->l4ct_build(pkt + l3hdr_len, ct->myct->ct); - - return ct; -} - -struct nf_ct_entry * -ct_find(const uint8_t *pkt, unsigned int l3hdr_len, - struct cthelper_proto_l2l3_helper *l3h, - struct cthelper_proto_l4_helper *l4h, unsigned int *ctinfo) -{ - struct nf_ct_entry *cur; - - list_for_each_entry(cur, &ct_list, head) { - if (l3h->l3ct_cmp_orig(pkt, cur->myct->ct) && - l4h->l4ct_cmp_orig(pkt + l3hdr_len, cur->myct->ct)) { - *ctinfo = 0; - return cur; - } - if (l3h->l3ct_cmp_repl(pkt, cur->myct->ct) && - l4h->l4ct_cmp_repl(pkt + l3hdr_len, cur->myct->ct)) { - *ctinfo = IP_CT_IS_REPLY; - return cur; - } - } - return NULL; -} - -void ct_add(struct nf_ct_entry *ct) -{ - list_add(&ct->head, &ct_list); -} - -void ct_flush(void) -{ - struct nf_ct_entry *cur, *tmp; - - list_for_each_entry_safe(cur, tmp, &ct_list, head) { - list_del(&cur->head); - free(cur->myct->priv_data); - free(cur->myct->ct); - free(cur->myct); - free(cur); - } -} diff --git a/tests/conntrackd/cthelper/ct.h b/tests/conntrackd/cthelper/ct.h deleted file mode 100755 index f01d49d..0000000 --- a/tests/conntrackd/cthelper/ct.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef _CT_H_ -#define _CT_H_ - -#include "../../../include/linux_list.h" -#include "../../../include/myct.h" - -struct nf_ct_entry { - struct list_head head; - struct myct *myct; -}; - -struct cthelper_proto_l2l3_helper; -struct cthelper_proto_l4_helper; - -struct nf_ct_entry *ct_alloc(const uint8_t *pkt, unsigned int l3hdr_len, struct cthelper_proto_l2l3_helper *l3h, struct cthelper_proto_l4_helper *l4h); - -struct nf_ct_entry *ct_find(const uint8_t *pkt, unsigned int l3hdr_len, struct cthelper_proto_l2l3_helper *l3h, struct cthelper_proto_l4_helper *l4h, unsigned int *ctinfo); - -void ct_add(struct nf_ct_entry *ct); -void ct_flush(void); - -#endif diff --git a/tests/conntrackd/cthelper/expect.c b/tests/conntrackd/cthelper/expect.c deleted file mode 100644 index d1d1d28..0000000 --- a/tests/conntrackd/cthelper/expect.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation (or any later at your option). - * - * This code has been sponsored by Vyatta Inc. <http://www.vyatta.com> - */ - -#include "../../../include/helper.h" -#include "test.h" - -#include <stdio.h> -#include <string.h> -#include <limits.h> -#include <errno.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <dlfcn.h> - -int -cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master, - uint32_t class, - union nfct_attr_grp_addr *saddr, - union nfct_attr_grp_addr *daddr, - uint8_t l4proto, uint16_t *sport, uint16_t *dport, - uint32_t flags) -{ - struct nf_conntrack *expected, *mask; - - expected = nfct_new(); - if (!expected) - return -1; - - mask = nfct_new(); - if (!mask) - return -1; - - if (saddr) { - switch(nfct_get_attr_u8(master, ATTR_L3PROTO)) { - int i; - uint32_t addr[4] = {}; - - case AF_INET: - nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); - nfct_set_attr_u32(expected, ATTR_IPV4_SRC, saddr->ip); - - nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET); - nfct_set_attr_u32(mask, ATTR_IPV4_SRC, 0xffffffff); - break; - case AF_INET6: - nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET6); - nfct_set_attr(expected, ATTR_IPV6_SRC, saddr->ip6); - - for (i=0; i<4; i++) - memset(addr, 0xffffffff, sizeof(uint32_t)); - - nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET6); - nfct_set_attr(mask, ATTR_IPV6_SRC, addr); - break; - default: - break; - } - } else { - switch(nfct_get_attr_u8(master, ATTR_L3PROTO)) { - int i; - uint32_t addr[4] = {}; - - case AF_INET: - nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); - nfct_set_attr_u32(expected, ATTR_IPV4_SRC, 0x00000000); - - nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET); - nfct_set_attr_u32(mask, ATTR_IPV4_SRC, 0x00000000); - break; - case AF_INET6: - for (i=0; i<4; i++) - memset(addr, 0x00000000, sizeof(uint32_t)); - - nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET6); - nfct_set_attr(expected, ATTR_IPV6_SRC, addr); - - nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET6); - nfct_set_attr(mask, ATTR_IPV6_SRC, addr); - break; - default: - break; - } - } - - if (sport) { - switch(l4proto) { - case IPPROTO_TCP: - case IPPROTO_UDP: - nfct_set_attr_u8(expected, ATTR_L4PROTO, l4proto); - nfct_set_attr_u16(expected, ATTR_PORT_SRC, *sport); - nfct_set_attr_u8(mask, ATTR_L4PROTO, l4proto); - nfct_set_attr_u16(mask, ATTR_PORT_SRC, 0xffff); - break; - default: - break; - } - } else { - switch(l4proto) { - case IPPROTO_TCP: - case IPPROTO_UDP: - nfct_set_attr_u8(expected, ATTR_L4PROTO, l4proto); - nfct_set_attr_u16(expected, ATTR_PORT_SRC, 0x0000); - nfct_set_attr_u8(mask, ATTR_L4PROTO, l4proto); - nfct_set_attr_u16(mask, ATTR_PORT_SRC, 0x0000); - break; - default: - break; - } - } - - switch(nfct_get_attr_u8(master, ATTR_L3PROTO)) { - uint32_t addr[4] = {}; - int i; - - case AF_INET: - nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); - nfct_set_attr_u32(expected, ATTR_IPV4_DST, daddr->ip); - nfct_set_attr_u32(mask, ATTR_IPV4_DST, 0xffffffff); - break; - case AF_INET6: - nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET6); - nfct_set_attr(expected, ATTR_IPV6_DST, daddr->ip6); - - for (i=0; i<4; i++) - memset(addr, 0xffffffff, sizeof(uint32_t)); - - nfct_set_attr(mask, ATTR_IPV6_DST, addr); - break; - default: - break; - } - - switch(l4proto) { - case IPPROTO_TCP: - case IPPROTO_UDP: - nfct_set_attr_u8(expected, ATTR_L4PROTO, l4proto); - nfct_set_attr_u16(expected, ATTR_PORT_DST, *dport); - nfct_set_attr_u8(mask, ATTR_L4PROTO, l4proto); - nfct_set_attr_u16(mask, ATTR_PORT_DST, 0xffff); - break; - default: - break; - } - - nfexp_set_attr(exp, ATTR_EXP_MASTER, master); - nfexp_set_attr(exp, ATTR_EXP_EXPECTED, expected); - nfexp_set_attr(exp, ATTR_EXP_MASK, mask); - - nfct_destroy(expected); - nfct_destroy(mask); - - return 0; -} - -int cthelper_add_expect(struct nf_expect *exp) -{ - cthelper_test_stats.ct_expect_created++; - return 0; -} - -int cthelper_del_expect(struct nf_expect *exp) -{ - return 0; -} - -void -cthelper_get_addr_src(struct nf_conntrack *ct, int dir, - union nfct_attr_grp_addr *addr) -{ - switch (dir) { - case MYCT_DIR_ORIG: - nfct_get_attr_grp(ct, ATTR_GRP_ORIG_ADDR_SRC, addr); - break; - case MYCT_DIR_REPL: - nfct_get_attr_grp(ct, ATTR_GRP_REPL_ADDR_SRC, addr); - break; - } -} - -void -cthelper_get_addr_dst(struct nf_conntrack *ct, int dir, - union nfct_attr_grp_addr *addr) -{ - switch (dir) { - case MYCT_DIR_ORIG: - nfct_get_attr_grp(ct, ATTR_GRP_ORIG_ADDR_DST, addr); - break; - case MYCT_DIR_REPL: - nfct_get_attr_grp(ct, ATTR_GRP_REPL_ADDR_DST, addr); - break; - } -} diff --git a/tests/conntrackd/cthelper/l3_ipv4.c b/tests/conntrackd/cthelper/l3_ipv4.c deleted file mode 100755 index 8edfd2e..0000000 --- a/tests/conntrackd/cthelper/l3_ipv4.c +++ /dev/null @@ -1,86 +0,0 @@ -#include <stdlib.h> -#include <netinet/ip.h> -#include <linux/if_ether.h> - -#include "proto.h" - -#include <libnetfilter_conntrack/libnetfilter_conntrack.h> - -#define PRINT_CMP(...) - -static void -l3_ipv4_ct_build_tuple(const uint8_t *pkt, struct nf_conntrack *ct) -{ - const struct iphdr *iph = (const struct iphdr *)pkt; - - nfct_set_attr_u16(ct, ATTR_ORIG_L3PROTO, AF_INET); - nfct_set_attr_u16(ct, ATTR_REPL_L3PROTO, AF_INET); - nfct_set_attr_u32(ct, ATTR_ORIG_IPV4_SRC, iph->saddr); - nfct_set_attr_u32(ct, ATTR_ORIG_IPV4_DST, iph->daddr); - nfct_set_attr_u32(ct, ATTR_REPL_IPV4_SRC, iph->daddr); - nfct_set_attr_u32(ct, ATTR_REPL_IPV4_DST, iph->saddr); -} - -static int -l3_ipv4_ct_cmp_tuple_orig(const uint8_t *pkt, struct nf_conntrack *ct) -{ - const struct iphdr *iph = (const struct iphdr *)pkt; - - PRINT_CMP("cmp_orig iph->saddr: %x == %x\n", - iph->saddr, nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC)); - PRINT_CMP("cmp_orig iph->daddr: %x == %x\n", - iph->daddr, nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST)); - - if (iph->saddr == nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_SRC) && - iph->daddr == nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST)) - return 1; - - return 0; -} - -static int -l3_ipv4_ct_cmp_tuple_repl(const uint8_t *pkt, struct nf_conntrack *ct) -{ - const struct iphdr *iph = (const struct iphdr *)pkt; - - PRINT_CMP("cmp_repl iph->saddr: %x == %x\n", - iph->saddr, nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC)); - PRINT_CMP("cmp_repl iph->daddr: %x == %x\n", - iph->daddr, nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST)); - - if (iph->saddr == nfct_get_attr_u32(ct, ATTR_REPL_IPV4_SRC) && - iph->daddr == nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST)) - return 1; - - return 0; -} - -static int l3_ipv4_pkt_l4proto_num(const uint8_t *pkt) -{ - const struct iphdr *iph = (const struct iphdr *)pkt; - - return iph->protocol; -} - -static int l3_ipv4_pkt_l3hdr_len(const uint8_t *pkt) -{ - const struct iphdr *iph = (const struct iphdr *)pkt; - - return iph->ihl << 2; -} - -static struct cthelper_proto_l2l3_helper ipv4 = { - .l2protonum = ETH_P_IP, - .l3protonum = AF_INET, - .l2hdr_len = ETH_HLEN, - .l3ct_build = l3_ipv4_ct_build_tuple, - .l3ct_cmp_orig = l3_ipv4_ct_cmp_tuple_orig, - .l3ct_cmp_repl = l3_ipv4_ct_cmp_tuple_repl, - .l3pkt_hdr_len = l3_ipv4_pkt_l3hdr_len, - .l4pkt_proto = l3_ipv4_pkt_l4proto_num, -}; - -void l2l3_ipv4_init(void) -{ - cthelper_proto_l2l3_helper_register(&ipv4); -} diff --git a/tests/conntrackd/cthelper/l4_tcp.c b/tests/conntrackd/cthelper/l4_tcp.c deleted file mode 100755 index f27c85d..0000000 --- a/tests/conntrackd/cthelper/l4_tcp.c +++ /dev/null @@ -1,88 +0,0 @@ -#include <netinet/ip.h> -#include <netinet/tcp.h> - -#include "proto.h" - -#include <libnetfilter_conntrack/libnetfilter_conntrack.h> - -#define PRINT_CMP(...) - -static void l4_tcp_ct_build_tuple(const uint8_t *pkt, struct nf_conntrack *ct) -{ - const struct tcphdr *tcph = (const struct tcphdr *)pkt; - - nfct_set_attr_u8(ct, ATTR_ORIG_L4PROTO, IPPROTO_TCP); - nfct_set_attr_u8(ct, ATTR_REPL_L4PROTO, IPPROTO_TCP); - nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, tcph->source); - nfct_set_attr_u16(ct, ATTR_ORIG_PORT_DST, tcph->dest); - nfct_set_attr_u16(ct, ATTR_REPL_PORT_SRC, tcph->dest); - nfct_set_attr_u16(ct, ATTR_REPL_PORT_DST, tcph->source); -} - -static int l4_tcp_ct_cmp_tuple_orig(const uint8_t *pkt, struct nf_conntrack *ct) -{ - const struct tcphdr *tcph = (const struct tcphdr *)pkt; - - PRINT_CMP("cmp_orig tcph->source: %u == %u\n", - tcph->source, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)); - PRINT_CMP("cmp_orig tcph->dest: %u == %u\n", - tcph->dest, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)); - - if (tcph->source == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) && - tcph->dest == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)) - return 1; - - return 0; -} - -static int -l4_tcp_ct_cmp_tuple_repl(const uint8_t *pkt, struct nf_conntrack *ct) -{ - const struct tcphdr *tcph = (const struct tcphdr *)pkt; - - PRINT_CMP("cmp_repl tcph->source: %u == %u\n", - tcph->source, nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC)); - PRINT_CMP("cmp_repl tcph->dest: %u == %u\n", - tcph->dest, nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST)); - - if (tcph->source == nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC) && - tcph->dest == nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST)) - return 1; - - return 0; -} - -static int -l4_tcp_ct_cmp_port(struct nf_conntrack *ct, uint16_t port) -{ - PRINT_CMP("cmp_port src: %u == %u\n", - port, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)); - PRINT_CMP("cmp_port dst: %u == %u\n", - port, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)); - - if (port == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) || - port == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)) - return 1; - - return 0; -} - -static int l4_tcp_pkt_no_data(const uint8_t *pkt) -{ - const struct tcphdr *tcph = (const struct tcphdr *)pkt; - return tcph->syn || tcph->fin || tcph->rst || !tcph->psh; -} - -static struct cthelper_proto_l4_helper tcp = { - .l4protonum = IPPROTO_TCP, - .l4ct_build = l4_tcp_ct_build_tuple, - .l4ct_cmp_orig = l4_tcp_ct_cmp_tuple_orig, - .l4ct_cmp_repl = l4_tcp_ct_cmp_tuple_repl, - .l4ct_cmp_port = l4_tcp_ct_cmp_port, - .l4pkt_no_data = l4_tcp_pkt_no_data, -}; - -void l4_tcp_init(void) -{ - cthelper_proto_l4_helper_register(&tcp); -} diff --git a/tests/conntrackd/cthelper/l4_udp.c b/tests/conntrackd/cthelper/l4_udp.c deleted file mode 100755 index 4d52d0a..0000000 --- a/tests/conntrackd/cthelper/l4_udp.c +++ /dev/null @@ -1,88 +0,0 @@ -#include <netinet/ip.h> -#include <netinet/udp.h> - -#include "proto.h" - -#include <libnetfilter_conntrack/libnetfilter_conntrack.h> - -#define PRINT_CMP(...) - -static void l4_udp_ct_build_tuple(const uint8_t *pkt, struct nf_conntrack *ct) -{ - const struct udphdr *udph = (const struct udphdr *)pkt; - - nfct_set_attr_u8(ct, ATTR_ORIG_L4PROTO, IPPROTO_UDP); - nfct_set_attr_u8(ct, ATTR_REPL_L4PROTO, IPPROTO_UDP); - nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, udph->source); - nfct_set_attr_u16(ct, ATTR_ORIG_PORT_DST, udph->dest); - nfct_set_attr_u16(ct, ATTR_REPL_PORT_SRC, udph->dest); - nfct_set_attr_u16(ct, ATTR_REPL_PORT_DST, udph->source); -} - -static int l4_udp_ct_cmp_tuple_orig(const uint8_t *pkt, struct nf_conntrack *ct) -{ - const struct udphdr *udph = (const struct udphdr *)pkt; - - PRINT_CMP("cmp_orig udph->source: %u == %u\n", - udph->source, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)); - PRINT_CMP("cmp_orig udph->dest: %u == %u\n", - udph->dest, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)); - - if (udph->source == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) && - udph->dest == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)) - return 1; - - return 0; -} - -static int -l4_udp_ct_cmp_tuple_repl(const uint8_t *pkt, struct nf_conntrack *ct) -{ - const struct udphdr *udph = (const struct udphdr *)pkt; - - PRINT_CMP("cmp_repl udph->source: %u == %u\n", - udph->source, nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC)); - PRINT_CMP("cmp_repl udph->dest: %u == %u\n", - udph->dest, nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST)); - - if (udph->source == nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC) && - udph->dest == nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST)) - return 1; - - return 0; -} - -static int -l4_udp_ct_cmp_port(struct nf_conntrack *ct, uint16_t port) -{ - PRINT_CMP("cmp_port src: %u == %u\n", - port, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC)); - PRINT_CMP("cmp_port dst: %u == %u\n", - port, nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)); - - if (port == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC) || - port == nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST)) - return 1; - - return 0; -} - -static int l4_udp_pkt_no_data(const uint8_t *pkt) -{ - /* UDP has no control packets. */ - return 1; -} - -static struct cthelper_proto_l4_helper tcp = { - .l4protonum = IPPROTO_UDP, - .l4ct_build = l4_udp_ct_build_tuple, - .l4ct_cmp_orig = l4_udp_ct_cmp_tuple_orig, - .l4ct_cmp_repl = l4_udp_ct_cmp_tuple_repl, - .l4ct_cmp_port = l4_udp_ct_cmp_port, - .l4pkt_no_data = l4_udp_pkt_no_data, -}; - -void l4_udp_init(void) -{ - cthelper_proto_l4_helper_register(&tcp); -} diff --git a/tests/conntrackd/cthelper/main.c b/tests/conntrackd/cthelper/main.c deleted file mode 100755 index 7021f00..0000000 --- a/tests/conntrackd/cthelper/main.c +++ /dev/null @@ -1,220 +0,0 @@ -#include <stdio.h> -#include <pcap.h> -#include <stdlib.h> -#include <stdint.h> -#include <stdbool.h> -#include <netinet/ip.h> -#include <arpa/inet.h> -#include <string.h> -#include <dlfcn.h> - -#include "ct.h" -#include "proto.h" -#include "../../../include/helper.h" -#include "test.h" - -#include <libnetfilter_queue/pktbuff.h> - -struct cthelper_test_stats cthelper_test_stats; - -enum { - TEST_NORMAL = 0, - TEST_DNAT, -}; - -static int -cthelper_process_packet(const uint8_t *pkt, uint32_t pktlen, - struct ctd_helper *h, int proto, uint16_t port, - int type) -{ - struct pkt_buff *pktb; - struct cthelper_proto_l2l3_helper *l3h; - struct cthelper_proto_l4_helper *l4h; - unsigned int l3hdr_len, l4protonum; - struct nf_ct_entry *ct; - int ret, this_proto; - uint32_t dataoff, ctinfo = 0; - - l3h = cthelper_proto_l2l3_helper_find(pkt, &l4protonum, &l3hdr_len); - if (l3h == NULL) { - fprintf(stderr, "Unsupported layer 3 protocol, skipping.\n"); - return -1; - } - - l4h = cthelper_proto_l4_helper_find(pkt, l4protonum); - if (l4h == NULL) { - fprintf(stderr, "Unsupported layer 4 protocol, skipping.\n"); - return -1; - } - /* get layer 3 header. */ - pkt += l3h->l2hdr_len; - pktlen -= l3h->l2hdr_len; - - /* skip packet with mismatching protocol */ - this_proto = l3h->l4pkt_proto(pkt); - if (this_proto != proto) { - cthelper_test_stats.pkt_mismatch_proto++; - return 0; - } - - /* Look for the fake conntrack. */ - ct = ct_find(pkt, l3hdr_len, l3h, l4h, &ctinfo); - if (ct == NULL) { - /* It doesn't exist any, create one. */ - ct = ct_alloc(pkt, l3hdr_len, l3h, l4h); - if (ct == NULL) { - fprintf(stderr, "Not enough memory\n"); - return -1; - } - ct_add(ct); - ctinfo += IP_CT_NEW; - } else - ctinfo += IP_CT_ESTABLISHED; - - /* skip packets with mismatching ports */ - if (!l4h->l4ct_cmp_port(ct->myct->ct, ntohs(port))) { - cthelper_test_stats.pkt_mismatch_port++; - return -1; - } - - /* - * FIXME: reminder, implement this below in the kernel for cthelper. - */ - - /* This packet contains no data, skip it. */ -/* if (l4h->l4pkt_no_data && l4h->l4pkt_no_data(pkt + l3hdr_len)) { - NFG_DEBUG("skipping packet with no data\n"); - continue; - } */ - - /* Create the fake network buffer. */ - pktb = pktb_alloc(AF_INET, pkt, pktlen, 128); - if (pktb == NULL) { - fprintf(stderr, "Not enough memory\n"); - return -1; - } - - dataoff = l3h->l3pkt_hdr_len(pkt); - if (dataoff > pktb_len(pktb)) { - fprintf(stderr, "wrong layer 3 offset: %d > %d\n", - dataoff, pktb_len(pktb)); - return -1; - } - - /* tweak to run DNAT mangling code using the same PCAP file. */ - if (type == TEST_DNAT) { - struct nf_conntrack *tmp = ct->myct->ct; - /* as long as this is tested, who cares the destination IP? */ - in_addr_t addr = inet_addr("1.1.1.1"); - - /* clone the real conntrack, to add DNAT information */ - ct->myct->ct = nfct_clone(ct->myct->ct); - /* set fake DNAT information */ - nfct_set_attr_u32(ct->myct->ct, ATTR_STATUS, IPS_DST_NAT); - nfct_set_attr_u32(ct->myct->ct, ATTR_ORIG_IPV4_DST, addr); - /* pass it to helper */ - ret = h->cb(pktb, dataoff, ct->myct, ctinfo); - /* restore real conntrack */ - nfct_destroy(ct->myct->ct); - ct->myct->ct = tmp; - - if (pktb_mangled(pktb)) { - uint32_t i; - uint8_t *data = pktb_network_header(pktb); - - printf("\e[1;31mmangled content: "); - - for (i=0; i < pktb_len(pktb); i++) - printf("%c", data[i]); - - printf("\e[0m\n"); - } - } else - ret = h->cb(pktb, dataoff, ct->myct, ctinfo); - - pktb_free(pktb); - - return ret; -} - -static int -cthelper_test(const char *pcapfile, const char *helper_name, - int l4proto, uint16_t port, int type) -{ - struct pcap_pkthdr pcaph; - char errbuf[PCAP_ERRBUF_SIZE]; - const u_char *pkt; - pcap_t *handle; - struct ctd_helper *h; - - h = helper_find("/usr/lib/conntrack-tools", - helper_name, l4proto, RTLD_NOW); - if (h == NULL) { - fprintf(stderr, "couldn't find helper: %s\n", helper_name); - return -1; - } - - handle = pcap_open_offline(pcapfile, errbuf); - if (handle == NULL) { - fprintf(stderr, "couldn't open pcap file %s: %s\n", - pcapfile, errbuf); - return -1; - } - while ((pkt = pcap_next(handle, &pcaph)) != NULL) { - cthelper_test_stats.pkts++; - cthelper_process_packet(pkt, pcaph.caplen, h, l4proto, port, - type); - } - - ct_flush(); - pcap_close(handle); - return 0; -} - -int main(int argc, char *argv[]) -{ - int ret, l4proto, type = TEST_NORMAL; - - if (argc < 5 || argc > 6) { - fprintf(stderr, "Wrong usage:\n"); - fprintf(stderr, "%s <pcap_file> <helper-name> <proto> " - "<port> [dnat]\n", - argv[0]); - fprintf(stderr, "example: %s file.pcap ftp tcp 21\n", argv[0]); - exit(EXIT_FAILURE); - } - if (strncmp("tcp", argv[3], strlen("tcp")) == 0) - l4proto = IPPROTO_TCP; - else if (strncmp("udp", argv[3], strlen("udp")) == 0) - l4proto = IPPROTO_UDP; - else { - fprintf(stderr, "%s not supported, send a patch to Pablo\n", - argv[3]); - exit(EXIT_FAILURE); - } - if (argc == 6) { - if (strncmp("dnat", argv[5], strlen("dnat")) == 0) { - type = TEST_DNAT; - printf("test dnat\n"); - } - } - - /* Initialization of supported layer 3 and 4 protocols here. */ - l2l3_ipv4_init(); - l4_tcp_init(); - l4_udp_init(); - - if (cthelper_test(argv[1], argv[2], l4proto, atoi(argv[4]), type) < 0) - ret = EXIT_FAILURE; - else - ret = EXIT_SUCCESS; - - printf("\e[1;34mTest results: expect_created=%d packets=%d " - "packets_skipped=%d\e[0m\n", - cthelper_test_stats.ct_expect_created, - cthelper_test_stats.pkts, - cthelper_test_stats.pkt_mismatch_proto + - cthelper_test_stats.pkt_mismatch_port); - - return ret; -} diff --git a/tests/conntrackd/cthelper/pcaps/nfsv3.pcap b/tests/conntrackd/cthelper/pcaps/nfsv3.pcap Binary files differdeleted file mode 100644 index 04606bd..0000000 --- a/tests/conntrackd/cthelper/pcaps/nfsv3.pcap +++ /dev/null diff --git a/tests/conntrackd/cthelper/pcaps/oracle-tns-redirect.pcap b/tests/conntrackd/cthelper/pcaps/oracle-tns-redirect.pcap Binary files differdeleted file mode 100644 index 32f8952..0000000 --- a/tests/conntrackd/cthelper/pcaps/oracle-tns-redirect.pcap +++ /dev/null diff --git a/tests/conntrackd/cthelper/proto.c b/tests/conntrackd/cthelper/proto.c deleted file mode 100755 index 6a1f345..0000000 --- a/tests/conntrackd/cthelper/proto.c +++ /dev/null @@ -1,49 +0,0 @@ -#include <stdlib.h> -#include <netinet/in.h> -#include <linux/if_ether.h> - -#include "linux_list.h" -#include "proto.h" - -static LIST_HEAD(l2l3_helper_list); -static LIST_HEAD(l4_helper_list); - -struct cthelper_proto_l2l3_helper * -cthelper_proto_l2l3_helper_find(const uint8_t *pkt, - unsigned int *l4protonum, - unsigned int *l3hdr_len) -{ - const struct ethhdr *eh = (const struct ethhdr *)pkt; - struct cthelper_proto_l2l3_helper *cur; - - list_for_each_entry(cur, &l2l3_helper_list, head) { - if (ntohs(cur->l2protonum) == eh->h_proto) { - *l4protonum = cur->l4pkt_proto(pkt + ETH_HLEN); - *l3hdr_len = cur->l3pkt_hdr_len(pkt + ETH_HLEN); - return cur; - } - } - return NULL; -} - -void cthelper_proto_l2l3_helper_register(struct cthelper_proto_l2l3_helper *h) -{ - list_add(&h->head, &l2l3_helper_list); -} - -struct cthelper_proto_l4_helper * -cthelper_proto_l4_helper_find(const uint8_t *pkt, unsigned int l4protocol) -{ - struct cthelper_proto_l4_helper *cur; - - list_for_each_entry(cur, &l4_helper_list, head) { - if (cur->l4protonum == l4protocol) - return cur; - } - return NULL; -} - -void cthelper_proto_l4_helper_register(struct cthelper_proto_l4_helper *h) -{ - list_add(&h->head, &l4_helper_list); -} diff --git a/tests/conntrackd/cthelper/proto.h b/tests/conntrackd/cthelper/proto.h deleted file mode 100755 index 9e99eea..0000000 --- a/tests/conntrackd/cthelper/proto.h +++ /dev/null @@ -1,50 +0,0 @@ -#ifndef _HELPER_H_ -#define _HELPER_H_ - -#include <stdint.h> - -#include "../../../include/linux_list.h" - -struct nf_conntrack; - -struct cthelper_proto_l4_helper { - struct list_head head; - - unsigned int l4protonum; - - void (*l4ct_build)(const uint8_t *pkt, struct nf_conntrack *ct); - int (*l4ct_cmp_orig)(const uint8_t *pkt, struct nf_conntrack *ct); - int (*l4ct_cmp_repl)(const uint8_t *pkt, struct nf_conntrack *ct); - int (*l4ct_cmp_port)(struct nf_conntrack *ct, uint16_t port); - - int (*l4pkt_no_data)(const uint8_t *pkt); -}; - -struct cthelper_proto_l2l3_helper { - struct list_head head; - - unsigned int l2protonum; - unsigned int l2hdr_len; - - unsigned int l3protonum; - - void (*l3ct_build)(const uint8_t *pkt, struct nf_conntrack *ct); - int (*l3ct_cmp_orig)(const uint8_t *pkt, struct nf_conntrack *ct); - int (*l3ct_cmp_repl)(const uint8_t *pkt, struct nf_conntrack *ct); - - int (*l3pkt_hdr_len)(const uint8_t *pkt); - int (*l4pkt_proto)(const uint8_t *pkt); -}; - -struct cthelper_proto_l2l3_helper *cthelper_proto_l2l3_helper_find(const uint8_t *pkt, unsigned int *l4protonum, unsigned int *l3hdr_len); -void cthelper_proto_l2l3_helper_register(struct cthelper_proto_l2l3_helper *h); - -struct cthelper_proto_l4_helper *cthelper_proto_l4_helper_find(const uint8_t *pkt, unsigned int l4protonum); -void cthelper_proto_l4_helper_register(struct cthelper_proto_l4_helper *h); - -/* Initialization of supported protocols here. */ -void l2l3_ipv4_init(void); -void l4_tcp_init(void); -void l4_udp_init(void); - -#endif diff --git a/tests/conntrackd/cthelper/run-test.sh b/tests/conntrackd/cthelper/run-test.sh deleted file mode 100644 index fe31602..0000000 --- a/tests/conntrackd/cthelper/run-test.sh +++ /dev/null @@ -1,11 +0,0 @@ -echo "Running test for oracle TNS port 1521" -./cthelper-test pcaps/oracle-tns-redirect.pcap tns tcp 1521 - -echo "Running test for oracle TNS port 1521" -./cthelper-test pcaps/oracle-tns-redirect.pcap tns tcp 1521 dnat - -echo "Running test for NFSv3 UDP port 111" -./cthelper-test pcaps/nfsv3.pcap rpc udp 111 - -echo "Running test for NFSv3 TCP port 111" -./cthelper-test pcaps/nfsv3.pcap rpc tcp 111 diff --git a/tests/conntrackd/cthelper/test.h b/tests/conntrackd/cthelper/test.h deleted file mode 100644 index 4f5a6b6..0000000 --- a/tests/conntrackd/cthelper/test.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef _CTHELPER_TEST_H_ -#define _CTHELPER_TEST_H_ - -struct cthelper_test_stats { - int pkts; - int pkt_mismatch_proto; - int pkt_mismatch_port; - int ct_expect_created; -}; - -extern struct cthelper_test_stats cthelper_test_stats; - -#endif |