From 5c35c86e2d9d4c522514cceec5e19e08e05ed4db Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 7 Aug 2013 15:22:41 +0200 Subject: conntrack: fix dump of IPv6 entries in the dying and unconfirmed list Use selected the family, instead of inconditionally request for IPv4. Signed-off-by: Pablo Neira Ayuso --- src/conntrack.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/conntrack.c b/src/conntrack.c index 7d2a365..bb4a026 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -1601,7 +1601,8 @@ static int nfct_mnl_socket_open(void) } static struct nlmsghdr * -nfct_mnl_nlmsghdr_put(char *buf, uint16_t subsys, uint16_t type) +nfct_mnl_nlmsghdr_put(char *buf, uint16_t subsys, uint16_t type, + uint8_t family) { struct nlmsghdr *nlh; struct nfgenmsg *nfh; @@ -1612,7 +1613,7 @@ nfct_mnl_nlmsghdr_put(char *buf, uint16_t subsys, uint16_t type) nlh->nlmsg_seq = time(NULL); nfh = mnl_nlmsg_put_extra_header(nlh, sizeof(struct nfgenmsg)); - nfh->nfgen_family = AF_INET; + nfh->nfgen_family = family; nfh->version = NFNETLINK_V0; nfh->res_id = 0; @@ -1625,13 +1626,13 @@ static void nfct_mnl_socket_close(void) } static int -nfct_mnl_dump(uint16_t subsys, uint16_t type, mnl_cb_t cb) +nfct_mnl_dump(uint16_t subsys, uint16_t type, mnl_cb_t cb, uint8_t family) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; int res; - nlh = nfct_mnl_nlmsghdr_put(buf, subsys, type); + nlh = nfct_mnl_nlmsghdr_put(buf, subsys, type, family); res = mnl_socket_sendto(sock.mnl, nlh, nlh->nlmsg_len); if (res < 0) @@ -1651,13 +1652,13 @@ nfct_mnl_dump(uint16_t subsys, uint16_t type, mnl_cb_t cb) } static int -nfct_mnl_get(uint16_t subsys, uint16_t type, mnl_cb_t cb) +nfct_mnl_get(uint16_t subsys, uint16_t type, mnl_cb_t cb, uint8_t family) { char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; int res; - nlh = nfct_mnl_nlmsghdr_put(buf, subsys, type); + nlh = nfct_mnl_nlmsghdr_put(buf, subsys, type, family); res = mnl_socket_sendto(sock.mnl, nlh, nlh->nlmsg_len); if (res < 0) @@ -2114,7 +2115,7 @@ int main(int argc, char *argv[]) res = nfct_mnl_dump(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_DYING, - mnl_nfct_dump_cb); + mnl_nfct_dump_cb, family); nfct_mnl_socket_close(); break; @@ -2124,7 +2125,7 @@ int main(int argc, char *argv[]) res = nfct_mnl_dump(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_UNCONFIRMED, - mnl_nfct_dump_cb); + mnl_nfct_dump_cb, family); nfct_mnl_socket_close(); break; @@ -2389,7 +2390,7 @@ int main(int argc, char *argv[]) res = nfct_mnl_get(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_STATS, - nfct_global_stats_cb); + nfct_global_stats_cb, AF_UNSPEC); nfct_mnl_socket_close(); @@ -2434,7 +2435,7 @@ try_proc_count: res = nfct_mnl_dump(NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET_STATS_CPU, - nfct_stats_cb); + nfct_stats_cb, AF_UNSPEC); nfct_mnl_socket_close(); @@ -2453,7 +2454,7 @@ try_proc_count: res = nfct_mnl_dump(NFNL_SUBSYS_CTNETLINK_EXP, IPCTNL_MSG_EXP_GET_STATS_CPU, - nfexp_stats_cb); + nfexp_stats_cb, AF_UNSPEC); nfct_mnl_socket_close(); -- cgit v1.2.3 From 43fbb438858cb704e23763091f1bc97a6c4bb098 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Tue, 3 Sep 2013 17:28:40 +0200 Subject: conntrack: minor cleanup Rename get_table to generic "optional argument handling" helper, so it can be re-used in upcoming patch. While at it, avoid copy&paste of "labelmap" handling. Signed-off-by: Florian Westphal --- src/conntrack.c | 41 +++++++++++++++++++---------------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/conntrack.c b/src/conntrack.c index bb4a026..8da94bf 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -890,20 +890,20 @@ add_command(unsigned int *cmd, const int newcmd) *cmd |= newcmd; } -static char *get_table(int argc, char *argv[]) +static char *get_optional_arg(int argc, char *argv[]) { - char *table = NULL; + char *arg = NULL; /* Nasty bug or feature in getopt_long ? * It seems that it behaves badly with optional arguments. * Fortunately, I just stole the fix from iptables ;) */ if (optarg) - return 0; + return arg; else if (optind < argc && argv[optind][0] != '-' && argv[optind][0] != '!') - table = argv[optind++]; + arg = argv[optind++]; - return table; + return arg; } enum { @@ -915,7 +915,7 @@ enum { static unsigned int check_type(int argc, char *argv[]) { - const char *table = get_table(argc, argv); + const char *table = get_optional_arg(argc, argv); /* default to conntrack subsystem if nothing has been specified. */ if (table == NULL) @@ -1819,6 +1819,15 @@ static int mnl_nfct_dump_cb(const struct nlmsghdr *nlh, void *data) static struct ctproto_handler *h; +static void labelmap_init(void) +{ + if (labelmap) + return; + labelmap = nfct_labelmap_new(NULL); + if (!labelmap) + perror("nfct_labelmap_new"); +} + int main(int argc, char *argv[]) { int c, cmd; @@ -1971,12 +1980,8 @@ 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"); - } + if (output_mask & _O_CL) + labelmap_init(); break; case 'z': options |= CT_OPT_ZERO; @@ -1988,12 +1993,7 @@ int main(int argc, char *argv[]) options |= opt2type[c]; - if (optarg) - continue; - else if (optind < argc && argv[optind][0] != '-' - && argv[optind][0] != '!') - tmp = argv[optind++]; - + tmp = get_optional_arg(argc, argv); if (tmp == NULL) continue; @@ -2024,10 +2024,7 @@ int main(int argc, char *argv[]) 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"); + labelmap_init(); unsigned int max = parse_label_get_max(optarg); struct nfct_bitmask * b = nfct_bitmask_new(max); -- cgit v1.2.3 From 06454c33f44c0f4d71a88a82b82da7bba5abde2d Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 5 Sep 2013 11:27:48 +0200 Subject: conntrack: support multiple -l options Using -l foo -l bar caused the "foo" label to be lost. Merge multiple -l options so "-l foo,bar" and "-l foo -l bar" have same effect. Signed-off-by: Florian Westphal --- conntrack.8 | 7 ++++--- src/conntrack.c | 29 ++++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/conntrack.8 b/conntrack.8 index f273434..6410e5b 100644 --- a/conntrack.8 +++ b/conntrack.8 @@ -144,10 +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. +.BI "-l, --label " "LABEL" +Specify a conntrack label. This option is only available in conjunction with "-L, --dump" or "-E, --event". -Match entries whose labels matches at least those specified as arguments. +Match entries whose labels match at least those specified. +Use multiple -l commands to specify multiple labels that need to be set. .TP .BI "-c, --secmark " "SECMARK" Specify the conntrack selinux security mark. diff --git a/src/conntrack.c b/src/conntrack.c index 8da94bf..fe68e42 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -1828,6 +1828,31 @@ static void labelmap_init(void) perror("nfct_labelmap_new"); } +static void merge_bitmasks(struct nfct_bitmask **current, + struct nfct_bitmask *src) +{ + unsigned int i; + + if (*current == NULL) { + *current = src; + return; + } + + /* "current" must be the larger bitmask object */ + if (nfct_bitmask_maxbit(src) > nfct_bitmask_maxbit(*current)) { + struct nfct_bitmask *tmp = *current; + *current = src; + src = tmp; + } + + for (i = 0; i <= nfct_bitmask_maxbit(src); i++) { + if (nfct_bitmask_test_bit(src, i)) + nfct_bitmask_set_bit(*current, i); + } + + nfct_bitmask_destroy(src); +} + int main(int argc, char *argv[]) { int c, cmd; @@ -2030,7 +2055,9 @@ int main(int argc, char *argv[]) struct nfct_bitmask * b = nfct_bitmask_new(max); parse_label(b, optarg2); - tmpl.label = b; + + /* join "-l foo -l bar" into single bitmask object */ + merge_bitmasks(&tmpl.label, b); free(optarg2); break; case 'a': -- cgit v1.2.3 From 991fc4ae561bfc7c9bc9da9598b0cc704295811f Mon Sep 17 00:00:00 2001 From: Clemence Faure Date: Thu, 5 Sep 2013 11:27:49 +0200 Subject: conntrack: support add/delete of conntrack labels new options "--label-add" and "--label-delete" to alter connlabels assigned to a connection. Signed-off-by: Clemence Faure Signed-off-by: Florian Westphal --- conntrack.8 | 10 +++- include/conntrack.h | 2 +- src/conntrack.c | 154 ++++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 140 insertions(+), 26 deletions(-) diff --git a/conntrack.8 b/conntrack.8 index 6410e5b..45e8582 100644 --- a/conntrack.8 +++ b/conntrack.8 @@ -146,9 +146,17 @@ In "--create" mode, the mask is ignored. .TP .BI "-l, --label " "LABEL" Specify a conntrack label. -This option is only available in conjunction with "-L, --dump" or "-E, --event". +This option is only available in conjunction with "-L, --dump", "-E, --event", or "-U --update". Match entries whose labels match at least those specified. Use multiple -l commands to specify multiple labels that need to be set. +Match entries whose labels matches at least those specified as arguments. +.BI "--label-add " "LABEL" +Specify the conntrack label to add to to the selected conntracks. +This option is only available in conjunction with "-I, --create" or "-U, --update". +.BI "--label-del " "[LABEL]" +Specify the conntrack label to delete from the selected conntracks. +If no label is given, all labels are deleted. +This option is only available in conjunction with "-U, --update". .TP .BI "-c, --secmark " "SECMARK" Specify the conntrack selinux security mark. diff --git a/include/conntrack.h b/include/conntrack.h index 6cd9962..c2a0c8f 100644 --- a/include/conntrack.h +++ b/include/conntrack.h @@ -10,7 +10,7 @@ #include #define NUMBER_OF_CMD 19 -#define NUMBER_OF_OPT 25 +#define NUMBER_OF_OPT 27 struct ctproto_handler { struct list_head head; diff --git a/src/conntrack.c b/src/conntrack.c index fe68e42..404ecc9 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -82,6 +82,9 @@ static struct { /* Allows filtering by ctlabels */ struct nfct_bitmask *label; + + /* Allows setting/removing specific ctlabels */ + struct nfct_bitmask *label_modify; } tmpl; static int alloc_tmpl_objects(void) @@ -109,6 +112,8 @@ static void free_tmpl_objects(void) nfexp_destroy(tmpl.exp); if (tmpl.label) nfct_bitmask_destroy(tmpl.label); + if (tmpl.label_modify) + nfct_bitmask_destroy(tmpl.label_modify); } enum ct_command { @@ -255,6 +260,12 @@ enum ct_options { CT_OPT_LABEL_BIT = 24, CT_OPT_LABEL = (1 << CT_OPT_LABEL_BIT), + + CT_OPT_ADD_LABEL_BIT = 25, + CT_OPT_ADD_LABEL = (1 << CT_OPT_ADD_LABEL_BIT), + + CT_OPT_DEL_LABEL_BIT = 26, + CT_OPT_DEL_LABEL = (1 << CT_OPT_DEL_LABEL_BIT), }; /* If you add a new option, you have to update NUMBER_OF_OPT in conntrack.h */ @@ -289,6 +300,8 @@ static const char *optflags[NUMBER_OF_OPT] = { [CT_OPT_ANY_NAT_BIT] = "any-nat", [CT_OPT_ZONE_BIT] = "zone", [CT_OPT_LABEL_BIT] = "label", + [CT_OPT_ADD_LABEL_BIT] = "label-add", + [CT_OPT_DEL_LABEL_BIT] = "label-del", }; static struct option original_opts[] = { @@ -330,12 +343,14 @@ static struct option original_opts[] = { {"any-nat", 2, 0, 'j'}, {"zone", 1, 0, 'w'}, {"label", 1, 0, 'l'}, + {"label-add", 1, 0, '<'}, + {"label-del", 2, 0, '>'}, {0, 0, 0, 0} }; 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:l:"; + "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 @@ -350,26 +365,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 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}, + /* 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,0,0}, +/*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,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,2,2,2}, +/*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,2,0,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,2,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,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,0,0}, +/*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,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,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,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,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,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,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,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,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,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,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,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,0,0}, }; static const int cmd2type[][2] = { @@ -402,6 +417,8 @@ static const int opt2type[] = { ['j'] = CT_OPT_ANY_NAT, ['w'] = CT_OPT_ZONE, ['l'] = CT_OPT_LABEL, + ['<'] = CT_OPT_ADD_LABEL, + ['>'] = CT_OPT_DEL_LABEL, }; static const int opt2family_attr[][2] = { @@ -425,6 +442,8 @@ static const int opt2attr[] = { ['i'] = ATTR_ID, ['w'] = ATTR_ZONE, ['l'] = ATTR_CONNLABELS, + ['<'] = ATTR_CONNLABELS, + ['>'] = ATTR_CONNLABELS, }; static char exit_msg[NUMBER_OF_CMD][64] = { @@ -472,6 +491,11 @@ static const char usage_expectation_parameters[] = " --mask-src ip\t\tSource mask address\n" " --mask-dst ip\t\tDestination mask address\n"; +static const char usage_update_parameters[] = + "Updating parameters and options:\n" + " --label-add label\tAdd label\n" + " --label-del label\tDelete label\n"; + static const char usage_parameters[] = "Common parameters and options:\n" " -s, --orig-src ip\t\tSource address from original direction\n" @@ -1045,6 +1069,7 @@ usage(char *prog) fprintf(stdout, "\n%s", usage_tables); fprintf(stdout, "\n%s", usage_conntrack_parameters); fprintf(stdout, "\n%s", usage_expectation_parameters); + fprintf(stdout, "\n%s", usage_update_parameters); fprintf(stdout, "\n%s\n", usage_parameters); } @@ -1349,7 +1374,7 @@ static int print_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); return NFCT_CB_CONTINUE; @@ -1376,6 +1401,58 @@ static void copy_status(struct nf_conntrack *tmp, const struct nf_conntrack *ct) } } +static struct nfct_bitmask *xnfct_bitmask_clone(const struct nfct_bitmask *a) +{ + struct nfct_bitmask *b = nfct_bitmask_clone(a); + if (!b) + exit_error(OTHER_PROBLEM, "out of memory"); + return b; +} + +static void copy_label(struct nf_conntrack *tmp, const struct nf_conntrack *ct) +{ + struct nfct_bitmask *ctb, *newmask; + unsigned int i; + + if ((options & (CT_OPT_ADD_LABEL|CT_OPT_DEL_LABEL)) == 0) + return; + + nfct_copy_attr(tmp, ct, ATTR_CONNLABELS); + ctb = (void *) nfct_get_attr(tmp, ATTR_CONNLABELS); + + if (options & CT_OPT_ADD_LABEL) { + if (ctb == NULL) { + newmask = xnfct_bitmask_clone(tmpl.label_modify); + nfct_set_attr(tmp, ATTR_CONNLABELS, newmask); + return; + } + + for (i = 0; i <= nfct_bitmask_maxbit(ctb); i++) { + if (nfct_bitmask_test_bit(tmpl.label_modify, i)) + nfct_bitmask_set_bit(ctb, i); + } + + newmask = xnfct_bitmask_clone(tmpl.label_modify); + nfct_set_attr(tmp, ATTR_CONNLABELS_MASK, newmask); + } else if (ctb != NULL) { + /* CT_OPT_DEL_LABEL */ + if (tmpl.label_modify == NULL) { + newmask = nfct_bitmask_new(0); + if (newmask) + nfct_set_attr(tmp, ATTR_CONNLABELS, newmask); + return; + } + + for (i = 0; i <= nfct_bitmask_maxbit(ctb); i++) { + if (nfct_bitmask_test_bit(tmpl.label_modify, i)) + nfct_bitmask_unset_bit(ctb, i); + } + + newmask = xnfct_bitmask_clone(tmpl.label_modify); + nfct_set_attr(tmp, ATTR_CONNLABELS_MASK, newmask); + } +} + static int update_cb(enum nf_conntrack_msg_type type, struct nf_conntrack *ct, void *data) @@ -1395,6 +1472,9 @@ static int update_cb(enum nf_conntrack_msg_type type, if (options & CT_OPT_TUPLE_REPL && !nfct_cmp(obj, ct, NFCT_CMP_REPL)) return NFCT_CB_CONTINUE; + if (filter_label(ct)) + return NFCT_CB_CONTINUE; + tmp = nfct_new(); if (tmp == NULL) exit_error(OTHER_PROBLEM, "out of memory"); @@ -1403,6 +1483,7 @@ static int update_cb(enum nf_conntrack_msg_type type, nfct_copy(tmp, obj, NFCT_CP_META); copy_mark(tmp, ct, &tmpl.mark); copy_status(tmp, ct); + copy_label(tmp, ct); /* do not send NFCT_Q_UPDATE if ct appears unchanged */ if (nfct_cmp(tmp, ct, NFCT_CMP_ALL | NFCT_CMP_MASK)) { @@ -2046,18 +2127,39 @@ int main(int argc, char *argv[]) tmpl.filter_mark_kernel.mask = tmpl.mark.mask; break; case 'l': + case '<': + case '>': options |= opt2type[c]; - char *optarg2 = strdup(optarg); labelmap_init(); + if ((options & (CT_OPT_DEL_LABEL|CT_OPT_ADD_LABEL)) == + (CT_OPT_DEL_LABEL|CT_OPT_ADD_LABEL)) + exit_error(OTHER_PROBLEM, "cannot use --label-add and " + "--label-del at the same time"); + + if (c == '>') { /* DELETE */ + char *tmp = get_optional_arg(argc, argv); + if (tmp == NULL) /* delete all labels */ + break; + optarg = tmp; + } + + char *optarg2 = strdup(optarg); unsigned int max = parse_label_get_max(optarg); struct nfct_bitmask * b = nfct_bitmask_new(max); + if (!b) + exit_error(OTHER_PROBLEM, "out of memory"); parse_label(b, optarg2); /* join "-l foo -l bar" into single bitmask object */ - merge_bitmasks(&tmpl.label, b); + if (c == 'l') { + merge_bitmasks(&tmpl.label, b); + } else { + merge_bitmasks(&tmpl.label_modify, b); + } + free(optarg2); break; case 'a': @@ -2216,6 +2318,10 @@ int main(int argc, char *argv[]) if (options & CT_OPT_MARK) nfct_set_attr_u32(tmpl.ct, ATTR_MARK, tmpl.mark.value); + if (options & CT_OPT_ADD_LABEL) + nfct_set_attr(tmpl.ct, ATTR_CONNLABELS, + xnfct_bitmask_clone(tmpl.label_modify)); + cth = nfct_open(CONNTRACK, 0); if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); -- cgit v1.2.3 From fee95ed0db0745b551dfb15c58800da5c1ca9e5f Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Thu, 5 Sep 2013 11:27:50 +0200 Subject: conntrack: do not exit when update returns an error If we fail to update an entry, just try to continue with the next one instead of exiting. Can happen f.e. when using "conntrack -U --add-label bla", but the conntrack entry in the kernel does not have the label extension set. Signed-off-by: Florian Westphal --- src/conntrack.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/conntrack.c b/src/conntrack.c index 404ecc9..1e45ca8 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -1492,12 +1492,10 @@ static int update_cb(enum nf_conntrack_msg_type type, } res = nfct_query(ith, NFCT_Q_UPDATE, tmp); - if (res < 0) { - nfct_destroy(tmp); - exit_error(OTHER_PROBLEM, - "Operation failed: %s", + if (res < 0) + fprintf(stderr, + "Operation failed: %s\n", err2str(errno, CT_UPDATE)); - } nfct_callback_register(ith, NFCT_T_ALL, print_cb, NULL); res = nfct_query(ith, NFCT_Q_GET, tmp); -- cgit v1.2.3 From 8c38d35c3d90d493fdead6d4ead0517ec09fee96 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 7 Aug 2013 19:41:30 +0200 Subject: conntrackd: cthelper: allow to attach expectations via nfqueue This requires the Linux kernel 3.12. Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/nfnetlink_queue.h | 13 +++++++++++++ include/myct.h | 1 + src/cthelper.c | 11 +++++++++++ 3 files changed, 25 insertions(+) diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h index e0d8fd8..0132bad 100644 --- a/include/linux/netfilter/nfnetlink_queue.h +++ b/include/linux/netfilter/nfnetlink_queue.h @@ -44,6 +44,9 @@ enum nfqnl_attr_type { NFQA_PAYLOAD, /* opaque data payload */ NFQA_CT, /* nf_conntrack_netlink.h */ NFQA_CT_INFO, /* enum ip_conntrack_info */ + NFQA_CAP_LEN, /* __u32 length of captured packet */ + NFQA_SKB_INFO, /* __u32 skb meta information */ + NFQA_EXP, /* nf_conntrack_netlink.h */ __NFQA_MAX }; @@ -95,5 +98,15 @@ enum nfqnl_attr_config { /* Flags for NFQA_CFG_FLAGS */ #define NFQA_CFG_F_FAIL_OPEN (1 << 0) #define NFQA_CFG_F_CONNTRACK (1 << 1) +#define NFQA_CFG_F_GSO (1 << 2) +#define NFQA_CFG_F_MAX (1 << 3) + +/* flags for NFQA_SKB_INFO */ +/* packet appears to have wrong checksums, but they are ok */ +#define NFQA_SKB_CSUMNOTREADY (1 << 0) +/* packet is GSO (i.e., exceeds device mtu) */ +#define NFQA_SKB_GSO (1 << 1) +/* csum not validated (incoming device doesn't support hw checksum, etc.) */ +#define NFQA_SKB_CSUM_NOTVERIFIED (1 << 2) #endif /* _NFNETLINK_QUEUE_H */ diff --git a/include/myct.h b/include/myct.h index 45d9f29..02d695c 100644 --- a/include/myct.h +++ b/include/myct.h @@ -37,6 +37,7 @@ struct myct_tuple { struct myct { struct nf_conntrack *ct; + struct nf_expect *exp; void *priv_data; }; diff --git a/src/cthelper.c b/src/cthelper.c index 5a8a92a..fec40fb 100644 --- a/src/cthelper.c +++ b/src/cthelper.c @@ -182,6 +182,15 @@ pkt_verdict_issue(struct ctd_helper_instance *cur, struct myct *myct, nfct_nlmsg_build(nlh, myct->ct); mnl_attr_nest_end(nlh, nest); + if (myct->exp) { + nest = mnl_attr_nest_start(nlh, NFQA_EXP); + if (nest == NULL) + return -1; + + nfexp_nlmsg_build(nlh, myct->exp); + mnl_attr_nest_end(nlh, nest); + } + if (mnl_socket_sendto(STATE_CTH(nl), nlh, nlh->nlmsg_len) < 0) { dlog(LOG_ERR, "failed to send verdict: %s", strerror(errno)); return -1; @@ -317,6 +326,8 @@ static int nfq_queue_cb(const struct nlmsghdr *nlh, void *data) if (ct != NULL) nfct_destroy(ct); + if (myct->exp != NULL) + nfexp_destroy(myct->exp); if (myct && myct->priv_data != NULL) free(myct->priv_data); if (myct != NULL) -- cgit v1.2.3 From 36118bfc4901b0978d2c8f17912fe91ec66f35e8 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 6 Aug 2013 14:21:04 +0200 Subject: conntrackd: helpers: add DHCPv6 helper This patch adds support for the DHCPv6 helper. 1) nfct helper add dhcpv6 inet6 udp 2) ip6tables -I OUTPUT -t raw -p udp --sport 546 -j CT --helper dhcpv6 3) run conntrackd You should see: % conntrack -L exp -f ipv6 279 proto=17 src=:: dst=ff02::1:2 sport=0 dport=546 mask-src=:: mask-dst=ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff sport=0 dport=65535 master-src=fe80::221:ccff:fe4a:7f9c master-dst=ff02::1:2 sport=546 dport=547 PERMANENT class=0 helper=dhcpv6 Signed-off-by: Pablo Neira Ayuso --- doc/helper/conntrackd.conf | 8 +++ src/helpers/Makefile.am | 7 ++- src/helpers/dhcpv6.c | 123 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 src/helpers/dhcpv6.c diff --git a/doc/helper/conntrackd.conf b/doc/helper/conntrackd.conf index 56f5162..358ad10 100644 --- a/doc/helper/conntrackd.conf +++ b/doc/helper/conntrackd.conf @@ -62,6 +62,14 @@ Helper { ExpectTimeout 300 } } + Type dhcpv6 inet6 udp { + QueueNum 4 + QueueLen 10240 + Policy dhcpv6 { + ExpectMax 1 + ExpectTimeout 300 + } + } } # diff --git a/src/helpers/Makefile.am b/src/helpers/Makefile.am index 589b4f3..59524f5 100644 --- a/src/helpers/Makefile.am +++ b/src/helpers/Makefile.am @@ -1,9 +1,14 @@ include $(top_srcdir)/Make_global.am -pkglib_LTLIBRARIES = ct_helper_ftp.la \ +pkglib_LTLIBRARIES = ct_helper_dhcpv6.la \ + ct_helper_ftp.la \ ct_helper_rpc.la \ ct_helper_tns.la +ct_helper_dhcpv6_la_SOURCES = dhcpv6.c +ct_helper_dhcpv6_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) +ct_helper_dhcpv6_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) + ct_helper_ftp_la_SOURCES = ftp.c ct_helper_ftp_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) ct_helper_ftp_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) diff --git a/src/helpers/dhcpv6.c b/src/helpers/dhcpv6.c new file mode 100644 index 0000000..73632ec --- /dev/null +++ b/src/helpers/dhcpv6.c @@ -0,0 +1,123 @@ +/* + * (C) 2013 by Pablo Neira Ayuso + * + * Adapted from: + * + * DHCPv6 multicast connection tracking helper. + * + * (c) 2012 Google Inc. + * + * Original author: Darren Willis + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include "conntrackd.h" +#include "helper.h" +#include "myct.h" +#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DHCPV6_CLIENT_PORT 546 + +static uint16_t dhcpv6_port; + +/* Timeouts for DHCPv6 replies, in seconds, indexed by message type. */ +static const int dhcpv6_timeouts[] = { + 0, /* No message has type 0. */ + 120, /* Solicit. */ + 0, /* Advertise. */ + 30, /* Request. */ + 4, /* Confirm. */ + 600, /* Renew. */ + 600, /* Rebind. */ + 0, /* Reply. */ + 1, /* Release. */ + 1, /* Decline. */ + 0, /* Reconfigure. */ + 120, /* Information Request. */ + 0, /* Relay-forward. */ + 0 /* Relay-reply. */ +}; + +static inline int ipv6_addr_is_multicast(const struct in6_addr *addr) +{ + return (addr->s6_addr32[0] & htonl(0xFF000000)) == htonl(0xFF000000); +} + +static int +dhcpv6_helper_cb(struct pkt_buff *pkt, uint32_t protoff, + struct myct *myct, uint32_t ctinfo) +{ + struct iphdr *iph = (struct iphdr *)pktb_network_header(pkt); + struct ip6_hdr *ip6h = (struct ip6_hdr *)pktb_network_header(pkt); + int dir = CTINFO2DIR(ctinfo); + union nfct_attr_grp_addr addr; + struct nf_expect *exp; + uint8_t *dhcpv6_msg_type; + + if (iph->version != 6 || !ipv6_addr_is_multicast(&ip6h->ip6_dst)) + return NF_ACCEPT; + + dhcpv6_msg_type = pktb_network_header(pkt) + protoff + sizeof(struct udphdr); + if (*dhcpv6_msg_type > ARRAY_SIZE(dhcpv6_timeouts)) { + printf("Dropping DHCPv6 message with bad type %u\n", + *dhcpv6_msg_type); + return NF_DROP; + } + + exp = nfexp_new(); + if (exp == NULL) + return NF_ACCEPT; + + cthelper_get_addr_src(myct->ct, dir, &addr); + + if (cthelper_expect_init(exp, myct->ct, 0, NULL, &addr, + IPPROTO_UDP, NULL, &dhcpv6_port, + NF_CT_EXPECT_PERMANENT)) { + nfexp_destroy(exp); + return NF_DROP; + } + + myct->exp = exp; + + if (dhcpv6_timeouts[*dhcpv6_msg_type] > 0) { + nfct_set_attr_u32(myct->ct, ATTR_TIMEOUT, + dhcpv6_timeouts[*dhcpv6_msg_type]); + } + + return NF_ACCEPT; +} + +static struct ctd_helper dhcpv6_helper = { + .name = "dhcpv6", + .l4proto = IPPROTO_UDP, + .cb = dhcpv6_helper_cb, + .policy = { + [0] = { + .name = "dhcpv6", + .expect_max = 1, + .expect_timeout = 300, + }, + }, +}; + +void __attribute__ ((constructor)) dhcpv6_init(void); + +void dhcpv6_init(void) +{ + dhcpv6_port = htons(DHCPV6_CLIENT_PORT); + helper_register(&dhcpv6_helper); +} -- cgit v1.2.3 From 0cf75aaf19ffd08e7c63fee737423d01343f4cb9 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 26 Sep 2013 18:25:45 +0200 Subject: nfct: modularize extensions Modularize timeout and helper extensions. Signed-off-by: Pablo Neira Ayuso --- include/nfct.h | 25 +++++++++++-------------- src/nfct-extensions/helper.c | 31 +++++++++++++++++++++++-------- src/nfct-extensions/timeout.c | 20 ++++++++++++++++++-- src/nfct.c | 35 +++++++++++++++++++++++++++++------ 4 files changed, 81 insertions(+), 30 deletions(-) diff --git a/include/nfct.h b/include/nfct.h index 5548b03..ddf9038 100644 --- a/include/nfct.h +++ b/include/nfct.h @@ -1,6 +1,8 @@ #ifndef _NFCT_H_ #define _NFCT_H_ +#include "linux_list.h" + enum { NFCT_SUBSYS_NONE = 0, NFCT_SUBSYS_TIMEOUT, @@ -19,21 +21,16 @@ enum { NFCT_CMD_DISABLE, }; +#define __init __attribute__((constructor)) + void nfct_perror(const char *msg); -int nfct_cmd_timeout_parse_params(int argc, char *argv[]); -int nfct_cmd_timeout_list(int argc, char *argv[]); -int nfct_cmd_timeout_add(int argc, char *argv[]); -int nfct_cmd_timeout_delete(int argc, char *argv[]); -int nfct_cmd_timeout_get(int argc, char *argv[]); -int nfct_cmd_timeout_flush(int argc, char *argv[]); - -int nfct_cmd_helper_parse_params(int argc, char *argv[]); -int nfct_cmd_helper_list(int argc, char *argv[]); -int nfct_cmd_helper_add(int argc, char *argv[]); -int nfct_cmd_helper_delete(int argc, char *argv[]); -int nfct_cmd_helper_get(int argc, char *argv[]); -int nfct_cmd_helper_flush(int argc, char *argv[]); -int nfct_cmd_helper_disable(int argc, char *argv[]); +struct nfct_extension { + struct list_head head; + int type; + int (*parse_params)(int argc, char *argv[]); +}; + +void nfct_extension_register(struct nfct_extension *ext); #endif diff --git a/src/nfct-extensions/helper.c b/src/nfct-extensions/helper.c index f91fc41..98ccde2 100644 --- a/src/nfct-extensions/helper.c +++ b/src/nfct-extensions/helper.c @@ -37,8 +37,14 @@ nfct_cmd_helper_usage(char *argv[]) "[parameters...]\n", VERSION, argv[0]); } -int -nfct_cmd_helper_parse_params(int argc, char *argv[]) +static int nfct_cmd_helper_list(int argc, char *argv[]); +static int nfct_cmd_helper_add(int argc, char *argv[]); +static int nfct_cmd_helper_delete(int argc, char *argv[]); +static int nfct_cmd_helper_get(int argc, char *argv[]); +static int nfct_cmd_helper_flush(int argc, char *argv[]); +static int nfct_cmd_helper_disable(int argc, char *argv[]); + +static int nfct_cmd_helper_parse_params(int argc, char *argv[]) { int cmd = NFCT_CMD_NONE, ret = 0; @@ -115,7 +121,7 @@ err: return MNL_CB_OK; } -int nfct_cmd_helper_list(int argc, char *argv[]) +static int nfct_cmd_helper_list(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; @@ -165,7 +171,7 @@ int nfct_cmd_helper_list(int argc, char *argv[]) return 0; } -int nfct_cmd_helper_add(int argc, char *argv[]) +static int nfct_cmd_helper_add(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; @@ -281,7 +287,7 @@ int nfct_cmd_helper_add(int argc, char *argv[]) return 0; } -int nfct_cmd_helper_delete(int argc, char *argv[]) +static int nfct_cmd_helper_delete(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; @@ -375,7 +381,7 @@ int nfct_cmd_helper_delete(int argc, char *argv[]) return 0; } -int nfct_cmd_helper_get(int argc, char *argv[]) +static int nfct_cmd_helper_get(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; @@ -468,7 +474,7 @@ int nfct_cmd_helper_get(int argc, char *argv[]) return 0; } -int nfct_cmd_helper_flush(int argc, char *argv[]) +static int nfct_cmd_helper_flush(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; @@ -519,7 +525,7 @@ int nfct_cmd_helper_flush(int argc, char *argv[]) return 0; } -int nfct_cmd_helper_disable(int argc, char *argv[]) +static int nfct_cmd_helper_disable(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; @@ -613,3 +619,12 @@ int nfct_cmd_helper_disable(int argc, char *argv[]) return 0; } +static struct nfct_extension helper = { + .type = NFCT_SUBSYS_HELPER, + .parse_params = nfct_cmd_helper_parse_params, +}; + +static void __init helper_init(void) +{ + nfct_extension_register(&helper); +} diff --git a/src/nfct-extensions/timeout.c b/src/nfct-extensions/timeout.c index 5b32023..dde489a 100644 --- a/src/nfct-extensions/timeout.c +++ b/src/nfct-extensions/timeout.c @@ -35,7 +35,13 @@ nfct_cmd_timeout_usage(char *argv[]) "[parameters...]\n", VERSION, argv[0]); } -int nfct_cmd_timeout_parse_params(int argc, char *argv[]) +static int nfct_cmd_timeout_list(int argc, char *argv[]); +static int nfct_cmd_timeout_add(int argc, char *argv[]); +static int nfct_cmd_timeout_delete(int argc, char *argv[]); +static int nfct_cmd_timeout_get(int argc, char *argv[]); +static int nfct_cmd_timeout_flush(int argc, char *argv[]); + +static int nfct_cmd_timeout_parse_params(int argc, char *argv[]) { int cmd = NFCT_CMD_NONE, ret; @@ -105,7 +111,7 @@ err: return MNL_CB_OK; } -int nfct_cmd_timeout_list(int argc, char *argv[]) +static int nfct_cmd_timeout_list(int argc, char *argv[]) { struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; @@ -484,3 +490,13 @@ int nfct_cmd_timeout_flush(int argc, char *argv[]) return 0; } + +static struct nfct_extension timeout = { + .type = NFCT_SUBSYS_TIMEOUT, + .parse_params = nfct_cmd_timeout_parse_params, +}; + +static void __init timeout_init(void) +{ + nfct_extension_register(&timeout); +} diff --git a/src/nfct.c b/src/nfct.c index b5c9654..4795570 100644 --- a/src/nfct.c +++ b/src/nfct.c @@ -25,6 +25,7 @@ #include #include +#include "linux_list.h" #include "nfct.h" static int nfct_cmd_version(int argc, char *argv[]); @@ -46,9 +47,28 @@ void nfct_perror(const char *msg) } } +static LIST_HEAD(nfct_extension_list); + +void nfct_extension_register(struct nfct_extension *ext) +{ + list_add(&ext->head, &nfct_extension_list); +} + +static struct nfct_extension *nfct_extension_lookup(int type) +{ + struct nfct_extension *ext; + + list_for_each_entry(ext, &nfct_extension_list, head) { + if (ext->type == type) + return ext; + } + return NULL; +} + int main(int argc, char *argv[]) { int subsys = NFCT_SUBSYS_NONE, ret = 0; + struct nfct_extension *ext; if (argc < 2) { usage(argv); @@ -70,18 +90,21 @@ int main(int argc, char *argv[]) } switch(subsys) { - case NFCT_SUBSYS_TIMEOUT: - ret = nfct_cmd_timeout_parse_params(argc, argv); - break; - case NFCT_SUBSYS_HELPER: - ret = nfct_cmd_helper_parse_params(argc, argv); - break; case NFCT_SUBSYS_VERSION: ret = nfct_cmd_version(argc, argv); break; case NFCT_SUBSYS_HELP: ret = nfct_cmd_help(argc, argv); break; + default: + ext = nfct_extension_lookup(subsys); + if (ext == NULL) { + fprintf(stderr, "nfct v%s: subsystem %s not supported\n", + VERSION, argv[1]); + return EXIT_FAILURE; + } + ret = ext->parse_params(argc, argv); + break; } return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } -- cgit v1.2.3 From ecfe6e93016559fdd18013ab5a2e1f200d330310 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 26 Sep 2013 17:53:06 +0200 Subject: build: add --disable-cthelper and --disable-cttimeout This patch allows you to disable userspace helper support and conntrack timeout tuning at build stage. By default, both features are enabled, to avoid breaking backward compatibility. Signed-off-by: Pablo Neira Ayuso --- configure.ac | 26 +++++++++++++++++++++++--- src/Makefile.am | 39 ++++++++++++++++++++++++++++++--------- src/read_config_yy.y | 6 ++++++ src/run.c | 9 ++++++--- 4 files changed, 65 insertions(+), 15 deletions(-) diff --git a/configure.ac b/configure.ac index 8bb4bec..f0800d6 100644 --- a/configure.ac +++ b/configure.ac @@ -54,12 +54,27 @@ else flex.]) fi +AC_ARG_ENABLE([cthelper], + AS_HELP_STRING([--disable-cthelper], [Do not build userspace helper support]), + [enable_cthelper="no"], [enable_cthelper="yes"]) +AC_ARG_ENABLE([cttimeout], + AS_HELP_STRING([--disable-cttimeout], [Do not build timeout support]), + [enable_cttimeout="no"], [enable_cttimeout="yes"]) + 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.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]) +AS_IF([test "x$enable_cttimeout" = "xyes"], [ + PKG_CHECK_MODULES([LIBNETFILTER_CTTIMEOUT], [libnetfilter_cttimeout >= 1.0.0]) +]) +AM_CONDITIONAL([HAVE_CTTIMEOUT], [test "x$enable_cttimeout" = "xyes"]) + +AS_IF([test "x$enable_cthelper" = "xyes"], [ + PKG_CHECK_MODULES([LIBNETFILTER_CTHELPER], [libnetfilter_cthelper >= 1.0.0]) + PKG_CHECK_MODULES([LIBNETFILTER_QUEUE], [libnetfilter_queue >= 1.0.2]) + AC_DEFINE([BUILD_CTHELPER], [1], [Building cthelper support]) +]) +AM_CONDITIONAL([HAVE_CTHELPER], [test "x$enable_cthelper" = "xyes"]) AC_CHECK_HEADERS([linux/capability.h],, [AC_MSG_ERROR([Cannot find linux/capabibility.h])]) @@ -126,3 +141,8 @@ fi AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/linux/Makefile include/linux/netfilter/Makefile extensions/Makefile src/helpers/Makefile]) AC_OUTPUT + +echo " +conntrack-tools configuration: + userspace conntrack helper support: ${enable_cthelper} + conntrack timeout support: ${enable_cttimeout}" diff --git a/src/Makefile.am b/src/Makefile.am index ec03e46..1bc3622 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,8 @@ include $(top_srcdir)/Make_global.am +if HAVE_CTHELPER SUBDIRS = helpers +endif AM_YFLAGS = -d @@ -11,17 +13,29 @@ sbin_PROGRAMS = conntrack conntrackd nfct conntrack_SOURCES = conntrack.c conntrack_LDADD = ../extensions/libct_proto_tcp.la ../extensions/libct_proto_udp.la ../extensions/libct_proto_udplite.la ../extensions/libct_proto_icmp.la ../extensions/libct_proto_icmpv6.la ../extensions/libct_proto_sctp.la ../extensions/libct_proto_dccp.la ../extensions/libct_proto_gre.la ../extensions/libct_proto_unknown.la ${LIBNETFILTER_CONNTRACK_LIBS} ${LIBMNL_LIBS} ${LIBNFNETLINK_LIBS} -nfct_SOURCES = nfct.c \ - helpers.c \ - nfct-extensions/timeout.c \ - nfct-extensions/helper.c +nfct_SOURCES = nfct.c + +if HAVE_CTHELPER +nfct_SOURCES += helpers.c \ + nfct-extensions/helper.c +endif + +if HAVE_CTTIMEOUT +nfct_SOURCES += nfct-extensions/timeout.c +endif nfct_LDADD = ${LIBMNL_LIBS} \ ${LIBNETFILTER_CONNTRACK_LIBS} \ - ${LIBNETFILTER_CTTIMEOUT_LIBS} \ - ${LIBNETFILTER_CTHELPER_LIBS} \ ${libdl_LIBS} +if HAVE_CTTIMEOUT +nfct_LDADD += ${LIBNETFILTER_CTTIMEOUT_LIBS} +endif + +if HAVE_CTHELPER +nfct_LDADD += ${LIBNETFILTER_CTHELPER_LIBS} +endif + nfct_LDFLAGS = -export-dynamic conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \ @@ -29,7 +43,7 @@ conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \ filter.c fds.c event.c process.c origin.c date.c \ cache.c cache-ct.c cache-exp.c \ cache_timer.c \ - ctnl.c cthelper.c \ + ctnl.c \ sync-mode.c sync-alarm.c sync-ftfw.c sync-notrack.c \ traffic_stats.c stats-mode.c \ network.c cidr.c \ @@ -39,15 +53,22 @@ conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c rbtree.c \ external_cache.c external_inject.c \ internal_cache.c internal_bypass.c \ read_config_yy.y read_config_lex.l \ - stack.c helpers.c utils.c expect.c + stack.c + +if HAVE_CTHELPER +conntrackd_SOURCES += cthelper.c helpers.c utils.c expect.c +endif # yacc and lex generate dirty code read_config_yy.o read_config_lex.o: AM_CFLAGS += -Wno-missing-prototypes -Wno-missing-declarations -Wno-implicit-function-declaration -Wno-nested-externs -Wno-undef -Wno-redundant-decls conntrackd_LDADD = ${LIBMNL_LIBS} ${LIBNETFILTER_CONNTRACK_LIBS} \ - ${LIBNETFILTER_QUEUE_LIBS} ${LIBNETFILTER_CTHELPER_LIBS} \ ${libdl_LIBS} ${LIBNFNETLINK_LIBS} +if HAVE_CTHELPER +conntrackd_LDADD += ${LIBNETFILTER_CTHELPER_LIBS} ${LIBNETFILTER_QUEUE_LIBS} +endif + conntrackd_LDFLAGS = -export-dynamic EXTRA_DIST = read_config_yy.h diff --git a/src/read_config_yy.y b/src/read_config_yy.y index b824150..fa517bb 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -1612,12 +1612,18 @@ helper_type: T_TYPE T_STRING T_STRING T_STRING '{' helper_type_list '}' exit(EXIT_FAILURE); } +#ifdef BUILD_CTHELPER /* XXX use configure.ac definitions. */ helper = helper_find("/usr/lib/conntrack-tools", $2, l4proto, RTLD_NOW); if (helper == NULL) { print_err(CTD_CFG_ERROR, "Unknown `%s' helper", $2); exit(EXIT_FAILURE); } +#else + print_err(CTD_CFG_ERROR, "Helper support is disabled, recompile " + "conntrackd"); + exit(EXIT_FAILURE); +#endif helper_inst = calloc(1, sizeof(struct ctd_helper_instance)); if (helper_inst == NULL) diff --git a/src/run.c b/src/run.c index 7fa6889..a9d4862 100644 --- a/src/run.c +++ b/src/run.c @@ -55,9 +55,10 @@ void killer(int signo) if (CONFIG(flags) & (CTD_SYNC_MODE | CTD_STATS_MODE)) ctnl_kill(); +#ifdef BUILD_CTHELPER if (CONFIG(flags) & CTD_HELPER) cthelper_kill(); - +#endif destroy_fds(STATE(fds)); unlink(CONFIG(lockfile)); dlog(LOG_NOTICE, "---- shutdown received ----"); @@ -205,9 +206,10 @@ static int local_handler(int fd, void *data) if (CONFIG(flags) & (CTD_SYNC_MODE | CTD_STATS_MODE)) return ctnl_local(fd, type, data); +#ifdef BUILD_CTHELPER if (CONFIG(flags) & CTD_HELPER) return cthelper_local(fd, type, data); - +#endif return ret; } @@ -259,11 +261,12 @@ init(void) if (ctnl_init() < 0) return -1; +#ifdef BUILD_CTHELPER if (CONFIG(flags) & CTD_HELPER) { if (cthelper_init() < 0) return -1; } - +#endif time(&STATE(stats).daemon_start_time); dlog(LOG_NOTICE, "initialization completed"); -- cgit v1.2.3 From b495e1d22faff636589a9646fbd4bb30902d3542 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 30 Sep 2013 16:06:58 +0200 Subject: nfct: timeout: use getprotoent The kernel bails out for unsupported protocols. Moreover, we don't need to upgrade to support new protocols. Signed-off-by: Pablo Neira Ayuso --- src/nfct-extensions/timeout.c | 40 ++++++++++++++++++---------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/src/nfct-extensions/timeout.c b/src/nfct-extensions/timeout.c index dde489a..7811bb2 100644 --- a/src/nfct-extensions/timeout.c +++ b/src/nfct-extensions/timeout.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -184,6 +185,7 @@ int nfct_cmd_timeout_add(int argc, char *argv[]) uint8_t l4proto; int ret, i; unsigned int j; + struct protoent *pent; if (argc < 6) { nfct_perror("missing parameters\n" @@ -211,28 +213,22 @@ int nfct_cmd_timeout_add(int argc, char *argv[]) } nfct_timeout_attr_set_u16(t, NFCT_TIMEOUT_ATTR_L3PROTO, l3proto); - if (strcmp(argv[5], "tcp") == 0) - l4proto = IPPROTO_TCP; - else if (strcmp(argv[5], "udp") == 0) - l4proto = IPPROTO_UDP; - else if (strcmp(argv[5], "udplite") == 0) - l4proto = IPPROTO_UDPLITE; - else if (strcmp(argv[5], "sctp") == 0) - l4proto = IPPROTO_SCTP; - else if (strcmp(argv[5], "dccp") == 0) - l4proto = IPPROTO_DCCP; - else if (strcmp(argv[5], "icmp") == 0) - l4proto = IPPROTO_ICMP; - else if (strcmp(argv[5], "icmpv6") == 0) - l4proto = IPPROTO_ICMPV6; - else if (strcmp(argv[5], "gre") == 0) - l4proto = IPPROTO_GRE; - else if (strcmp(argv[5], "generic") == 0) - l4proto = IPPROTO_RAW; - else { - nfct_perror("unknown layer 4 protocol"); - return -1; - } + pent = getprotobyname(argv[5]); + if (!pent) { + /* In Debian, /etc/protocols says ipv6-icmp. Support icmpv6 + * as well not to break backward compatibility. + */ + if (strcmp(argv[5], "icmpv6") == 0) + l4proto = IPPROTO_ICMPV6; + else if (strcmp(argv[5], "generic") == 0) + l4proto = IPPROTO_RAW; + else { + nfct_perror("unknown layer 4 protocol"); + return -1; + } + } else + l4proto = pent->p_proto; + nfct_timeout_attr_set_u8(t, NFCT_TIMEOUT_ATTR_L4PROTO, l4proto); for (i=6; i Date: Mon, 30 Sep 2013 16:31:03 +0200 Subject: nfct: timeout: split nfct_cmd_timeout_add in several functions This patch is a cleanup to split this function in smaller chunks. It is required to prepare default protocol timeout tuning via netlink. --- src/nfct-extensions/timeout.c | 123 +++++++++++++++++++++++++++--------------- 1 file changed, 80 insertions(+), 43 deletions(-) diff --git a/src/nfct-extensions/timeout.c b/src/nfct-extensions/timeout.c index 7811bb2..0cf92bb 100644 --- a/src/nfct-extensions/timeout.c +++ b/src/nfct-extensions/timeout.c @@ -1,5 +1,5 @@ /* - * (C) 2012 by Pablo Neira Ayuso + * (C) 2012-2013 by Pablo Neira Ayuso * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published @@ -174,53 +174,34 @@ static uint32_t nfct_timeout_attr_max[IPPROTO_MAX] = { [IPPROTO_RAW] = NFCT_TIMEOUT_ATTR_GENERIC_MAX, }; -int nfct_cmd_timeout_add(int argc, char *argv[]) +static int nfct_cmd_get_l3proto(char *argv[]) { - struct mnl_socket *nl; - char buf[MNL_SOCKET_BUFFER_SIZE]; - struct nlmsghdr *nlh; - uint32_t portid, seq; - struct nfct_timeout *t; - uint16_t l3proto; - uint8_t l4proto; - int ret, i; - unsigned int j; - struct protoent *pent; - - if (argc < 6) { - nfct_perror("missing parameters\n" - "syntax: nfct timeout add name " - "family protocol state1 " - "timeout1 state2 timeout2..."); - return -1; - } - - t = nfct_timeout_alloc(); - if (t == NULL) { - nfct_perror("OOM"); - return -1; - } - - nfct_timeout_attr_set(t, NFCT_TIMEOUT_ATTR_NAME, argv[3]); + int l3proto; - if (strcmp(argv[4], "inet") == 0) + if (strcmp(*argv, "inet") == 0) l3proto = AF_INET; - else if (strcmp(argv[4], "inet6") == 0) + else if (strcmp(*argv, "inet6") == 0) l3proto = AF_INET6; else { nfct_perror("unknown layer 3 protocol"); return -1; } - nfct_timeout_attr_set_u16(t, NFCT_TIMEOUT_ATTR_L3PROTO, l3proto); + return l3proto; +} + +static int nfct_cmd_get_l4proto(char *argv[]) +{ + int l4proto; + struct protoent *pent; - pent = getprotobyname(argv[5]); + pent = getprotobyname(*argv); if (!pent) { /* In Debian, /etc/protocols says ipv6-icmp. Support icmpv6 * as well not to break backward compatibility. */ - if (strcmp(argv[5], "icmpv6") == 0) + if (strcmp(*argv, "icmpv6") == 0) l4proto = IPPROTO_ICMPV6; - else if (strcmp(argv[5], "generic") == 0) + else if (strcmp(*argv, "generic") == 0) l4proto = IPPROTO_RAW; else { nfct_perror("unknown layer 4 protocol"); @@ -229,9 +210,35 @@ int nfct_cmd_timeout_add(int argc, char *argv[]) } else l4proto = pent->p_proto; + return l4proto; +} + +static int +nfct_cmd_timeout_parse(struct nfct_timeout *t, int argc, char *argv[]) +{ + int l3proto, l4proto; + unsigned int j; + const char *proto_name; + + l3proto = nfct_cmd_get_l3proto(argv); + if (l3proto < 0) + return -1; + + nfct_timeout_attr_set_u16(t, NFCT_TIMEOUT_ATTR_L3PROTO, l3proto); + + argc--; + argv++; + proto_name = *argv; + + l4proto = nfct_cmd_get_l4proto(argv); + if (l4proto < 0) + return -1; + nfct_timeout_attr_set_u8(t, NFCT_TIMEOUT_ATTR_L4PROTO, l4proto); + argc--; + argv++; - for (i=6; i1; argc-=2, argv+=2) { int matching = -1; for (j=0; j= argc) { - nfct_perror("missing value for this timeout"); - return -1; - } nfct_timeout_policy_attr_set_u32(t, matching, - atoi(argv[i+1])); - matching = -1; + atoi(*(argv+1))); } else { fprintf(stderr, "nfct v%s: Wrong state name: `%s' " "for protocol `%s'\n", - VERSION, argv[i], argv[5]); + VERSION, *argv, proto_name); return -1; } } + if (argc > 0) { + nfct_perror("missing value for this timeout"); + return -1; + } + + return 0; +} + +int nfct_cmd_timeout_add(int argc, char *argv[]) +{ + struct mnl_socket *nl; + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + uint32_t portid, seq; + struct nfct_timeout *t; + int ret; + + if (argc < 6) { + nfct_perror("missing parameters\n" + "syntax: nfct timeout add name " + "family protocol state1 " + "timeout1 state2 timeout2..."); + return -1; + } + + t = nfct_timeout_alloc(); + if (t == NULL) { + nfct_perror("OOM"); + return -1; + } + + nfct_timeout_attr_set(t, NFCT_TIMEOUT_ATTR_NAME, argv[3]); + + if (nfct_cmd_timeout_parse(t, argc-4, &argv[4]) < 0) + return -1; seq = time(NULL); nlh = nfct_timeout_nlmsg_build_hdr(buf, IPCTNL_MSG_TIMEOUT_NEW, -- cgit v1.2.3 From 386968d321d02571b593b3bbbf39891f44397469 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 30 Sep 2013 20:09:57 +0200 Subject: nfct: src: add nfct_mnl_talk and use it Add helper function nfct_mnl_talk and use it. Signed-off-by: Pablo Neira Ayuso --- include/nfct.h | 5 +++ src/nfct-extensions/helper.c | 99 ++++++------------------------------------- src/nfct-extensions/timeout.c | 82 +++++------------------------------ src/nfct.c | 25 +++++++++++ 4 files changed, 53 insertions(+), 158 deletions(-) diff --git a/include/nfct.h b/include/nfct.h index ddf9038..93717c5 100644 --- a/include/nfct.h +++ b/include/nfct.h @@ -33,4 +33,9 @@ struct nfct_extension { void nfct_extension_register(struct nfct_extension *ext); +int nfct_mnl_talk(struct mnl_socket *nl, struct nlmsghdr *nlh, + uint32_t seq, uint32_t portid, + int (*cb)(const struct nlmsghdr *nlh, void *data), + void *data); + #endif diff --git a/src/nfct-extensions/helper.c b/src/nfct-extensions/helper.c index 98ccde2..4171a47 100644 --- a/src/nfct-extensions/helper.c +++ b/src/nfct-extensions/helper.c @@ -127,7 +127,6 @@ static int nfct_cmd_helper_list(int argc, char *argv[]) char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; unsigned int seq, portid; - int ret; if (argc > 3) { nfct_perror("too many arguments"); @@ -150,22 +149,11 @@ static int nfct_cmd_helper_list(int argc, char *argv[]) } portid = mnl_socket_get_portid(nl); - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - nfct_perror("mnl_socket_send"); + if (nfct_mnl_talk(nl, nlh, seq, portid, nfct_helper_cb, NULL) < 0) { + nfct_perror("netlink error"); return -1; } - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, nfct_helper_cb, NULL); - if (ret <= 0) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) { - nfct_perror("error"); - return -1; - } mnl_socket_close(nl); return 0; @@ -181,7 +169,7 @@ static int nfct_cmd_helper_add(int argc, char *argv[]) uint16_t l3proto; uint8_t l4proto; struct ctd_helper *helper; - int ret, j; + int j; if (argc < 6) { nfct_perror("missing parameters\n" @@ -266,22 +254,11 @@ static int nfct_cmd_helper_add(int argc, char *argv[]) } portid = mnl_socket_get_portid(nl); - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - nfct_perror("mnl_socket_send"); + if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { + nfct_perror("netlink error"); return -1; } - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); - if (ret <= 0) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) { - nfct_perror("error"); - return -1; - } mnl_socket_close(nl); return 0; @@ -294,7 +271,6 @@ static int nfct_cmd_helper_delete(int argc, char *argv[]) struct nlmsghdr *nlh; uint32_t portid, seq; struct nfct_helper *t; - int ret; if (argc < 4) { nfct_perror("missing helper policy name"); @@ -359,20 +335,8 @@ static int nfct_cmd_helper_delete(int argc, char *argv[]) } portid = mnl_socket_get_portid(nl); - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - nfct_perror("mnl_socket_send"); - return -1; - } - - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); - if (ret <= 0) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) { - nfct_perror("error"); + if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { + nfct_perror("netlink error"); return -1; } @@ -388,7 +352,6 @@ static int nfct_cmd_helper_get(int argc, char *argv[]) struct nlmsghdr *nlh; uint32_t portid, seq; struct nfct_helper *t; - int ret; if (argc < 4) { nfct_perror("missing helper policy name"); @@ -453,22 +416,11 @@ static int nfct_cmd_helper_get(int argc, char *argv[]) } portid = mnl_socket_get_portid(nl); - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - nfct_perror("mnl_socket_send"); + if (nfct_mnl_talk(nl, nlh, seq, portid, nfct_helper_cb, NULL) < 0) { + nfct_perror("netlink error"); return -1; } - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, nfct_helper_cb, NULL); - if (ret <= 0) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) { - nfct_perror("error"); - return -1; - } mnl_socket_close(nl); return 0; @@ -480,7 +432,6 @@ static int nfct_cmd_helper_flush(int argc, char *argv[]) char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq; - int ret; if (argc > 3) { nfct_perror("too many arguments"); @@ -503,20 +454,8 @@ static int nfct_cmd_helper_flush(int argc, char *argv[]) } portid = mnl_socket_get_portid(nl); - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - nfct_perror("mnl_socket_send"); - return -1; - } - - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); - if (ret <= 0) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) { - nfct_perror("error"); + if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { + nfct_perror("netlink error"); return -1; } @@ -535,7 +474,6 @@ static int nfct_cmd_helper_disable(int argc, char *argv[]) uint16_t l3proto; uint8_t l4proto; struct ctd_helper *helper; - int ret; if (argc < 6) { nfct_perror("missing parameters\n" @@ -598,22 +536,11 @@ static int nfct_cmd_helper_disable(int argc, char *argv[]) } portid = mnl_socket_get_portid(nl); - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - nfct_perror("mnl_socket_send"); + if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { + nfct_perror("netlink error"); return -1; } - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); - if (ret <= 0) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) { - nfct_perror("error"); - return -1; - } mnl_socket_close(nl); return 0; diff --git a/src/nfct-extensions/timeout.c b/src/nfct-extensions/timeout.c index 0cf92bb..c361dab 100644 --- a/src/nfct-extensions/timeout.c +++ b/src/nfct-extensions/timeout.c @@ -118,7 +118,6 @@ static int nfct_cmd_timeout_list(int argc, char *argv[]) char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; unsigned int seq, portid; - int ret; if (argc > 3) { nfct_perror("too many arguments"); @@ -141,22 +140,11 @@ static int nfct_cmd_timeout_list(int argc, char *argv[]) } portid = mnl_socket_get_portid(nl); - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - nfct_perror("mnl_socket_send"); + if (nfct_mnl_talk(nl, nlh, seq, portid, nfct_timeout_cb, NULL) < 0) { + nfct_perror("netlink error"); return -1; } - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, nfct_timeout_cb, NULL); - if (ret <= 0) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) { - nfct_perror("error"); - return -1; - } mnl_socket_close(nl); return 0; @@ -281,7 +269,6 @@ int nfct_cmd_timeout_add(int argc, char *argv[]) struct nlmsghdr *nlh; uint32_t portid, seq; struct nfct_timeout *t; - int ret; if (argc < 6) { nfct_perror("missing parameters\n" @@ -321,22 +308,11 @@ int nfct_cmd_timeout_add(int argc, char *argv[]) } portid = mnl_socket_get_portid(nl); - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - nfct_perror("mnl_socket_send"); + if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { + nfct_perror("netlink error"); return -1; } - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); - if (ret <= 0) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) { - nfct_perror("error"); - return -1; - } mnl_socket_close(nl); return 0; @@ -349,7 +325,6 @@ int nfct_cmd_timeout_delete(int argc, char *argv[]) struct nlmsghdr *nlh; uint32_t portid, seq; struct nfct_timeout *t; - int ret; if (argc < 4) { nfct_perror("missing timeout policy name"); @@ -386,20 +361,8 @@ int nfct_cmd_timeout_delete(int argc, char *argv[]) } portid = mnl_socket_get_portid(nl); - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - nfct_perror("mnl_socket_send"); - return -1; - } - - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); - if (ret <= 0) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) { - nfct_perror("error"); + if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { + nfct_perror("netlink error"); return -1; } @@ -415,7 +378,6 @@ int nfct_cmd_timeout_get(int argc, char *argv[]) struct nlmsghdr *nlh; uint32_t portid, seq; struct nfct_timeout *t; - int ret; if (argc < 4) { nfct_perror("missing timeout policy name"); @@ -452,22 +414,11 @@ int nfct_cmd_timeout_get(int argc, char *argv[]) } portid = mnl_socket_get_portid(nl); - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - nfct_perror("mnl_socket_send"); + if (nfct_mnl_talk(nl, nlh, seq, portid, nfct_timeout_cb, NULL) < 0) { + nfct_perror("netlink error"); return -1; } - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, nfct_timeout_cb, NULL); - if (ret <= 0) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) { - nfct_perror("error"); - return -1; - } mnl_socket_close(nl); return 0; @@ -479,7 +430,6 @@ int nfct_cmd_timeout_flush(int argc, char *argv[]) char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq; - int ret; if (argc > 3) { nfct_perror("too many arguments"); @@ -502,20 +452,8 @@ int nfct_cmd_timeout_flush(int argc, char *argv[]) } portid = mnl_socket_get_portid(nl); - if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) { - nfct_perror("mnl_socket_send"); - return -1; - } - - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - while (ret > 0) { - ret = mnl_cb_run(buf, ret, seq, portid, NULL, NULL); - if (ret <= 0) - break; - ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); - } - if (ret == -1) { - nfct_perror("error"); + if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { + nfct_perror("netlink error"); return -1; } diff --git a/src/nfct.c b/src/nfct.c index 4795570..84bb1b7 100644 --- a/src/nfct.c +++ b/src/nfct.c @@ -143,3 +143,28 @@ static int nfct_cmd_help(int argc, char *argv[]) printf(help_msg, VERSION, argv[0]); return 0; } + +int nfct_mnl_talk(struct mnl_socket *nl, struct nlmsghdr *nlh, + uint32_t seq, uint32_t portid, + int (*cb)(const struct nlmsghdr *nlh, void *data), + void *data) +{ + int ret; + char buf[MNL_SOCKET_BUFFER_SIZE]; + + if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) + return -1; + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + while (ret > 0) { + ret = mnl_cb_run(buf, ret, seq, portid, cb, data); + if (ret <= 0) + break; + + ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); + } + if (ret == -1) + return -1; + + return 0; +} -- cgit v1.2.3 From 3c78a4543e12f5e82bdd771971d3534fa452117b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 1 Oct 2013 13:23:39 +0200 Subject: nfct: src: consolidate netlink socket creation Open the socket from the main function, then pass it as parameter to the corresponding interpreter. Signed-off-by: Pablo Neira Ayuso --- include/nfct.h | 3 +- src/nfct-extensions/helper.c | 125 +++++++++--------------------------------- src/nfct-extensions/timeout.c | 103 ++++++---------------------------- src/nfct.c | 25 ++++++++- 4 files changed, 68 insertions(+), 188 deletions(-) diff --git a/include/nfct.h b/include/nfct.h index 93717c5..682fe3a 100644 --- a/include/nfct.h +++ b/include/nfct.h @@ -28,11 +28,12 @@ void nfct_perror(const char *msg); struct nfct_extension { struct list_head head; int type; - int (*parse_params)(int argc, char *argv[]); + int (*parse_params)(struct mnl_socket *nl, int argc, char *argv[]); }; void nfct_extension_register(struct nfct_extension *ext); +struct mnl_socket *nfct_mnl_open(void); int nfct_mnl_talk(struct mnl_socket *nl, struct nlmsghdr *nlh, uint32_t seq, uint32_t portid, int (*cb)(const struct nlmsghdr *nlh, void *data), diff --git a/src/nfct-extensions/helper.c b/src/nfct-extensions/helper.c index 4171a47..7544ed7 100644 --- a/src/nfct-extensions/helper.c +++ b/src/nfct-extensions/helper.c @@ -37,14 +37,15 @@ nfct_cmd_helper_usage(char *argv[]) "[parameters...]\n", VERSION, argv[0]); } -static int nfct_cmd_helper_list(int argc, char *argv[]); -static int nfct_cmd_helper_add(int argc, char *argv[]); -static int nfct_cmd_helper_delete(int argc, char *argv[]); -static int nfct_cmd_helper_get(int argc, char *argv[]); -static int nfct_cmd_helper_flush(int argc, char *argv[]); -static int nfct_cmd_helper_disable(int argc, char *argv[]); - -static int nfct_cmd_helper_parse_params(int argc, char *argv[]) +static int nfct_cmd_helper_list(struct mnl_socket *nl, int argc, char *argv[]); +static int nfct_cmd_helper_add(struct mnl_socket *nl, int argc, char *argv[]); +static int nfct_cmd_helper_delete(struct mnl_socket *nl, int argc, char *argv[]); +static int nfct_cmd_helper_get(struct mnl_socket *nl, int argc, char *argv[]); +static int nfct_cmd_helper_flush(struct mnl_socket *nl, int argc, char *argv[]); +static int nfct_cmd_helper_disable(struct mnl_socket *nl, int argc, char *argv[]); + +static int +nfct_cmd_helper_parse_params(struct mnl_socket *nl, int argc, char *argv[]) { int cmd = NFCT_CMD_NONE, ret = 0; @@ -72,24 +73,25 @@ static int nfct_cmd_helper_parse_params(int argc, char *argv[]) nfct_cmd_helper_usage(argv); exit(EXIT_FAILURE); } + switch(cmd) { case NFCT_CMD_LIST: - ret = nfct_cmd_helper_list(argc, argv); + ret = nfct_cmd_helper_list(nl, argc, argv); break; case NFCT_CMD_ADD: - ret = nfct_cmd_helper_add(argc, argv); + ret = nfct_cmd_helper_add(nl, argc, argv); break; case NFCT_CMD_DELETE: - ret = nfct_cmd_helper_delete(argc, argv); + ret = nfct_cmd_helper_delete(nl, argc, argv); break; case NFCT_CMD_GET: - ret = nfct_cmd_helper_get(argc, argv); + ret = nfct_cmd_helper_get(nl, argc, argv); break; case NFCT_CMD_FLUSH: - ret = nfct_cmd_helper_flush(argc, argv); + ret = nfct_cmd_helper_flush(nl, argc, argv); break; case NFCT_CMD_DISABLE: - ret = nfct_cmd_helper_disable(argc, argv); + ret = nfct_cmd_helper_disable(nl, argc, argv); break; } @@ -121,9 +123,8 @@ err: return MNL_CB_OK; } -static int nfct_cmd_helper_list(int argc, char *argv[]) +static int nfct_cmd_helper_list(struct mnl_socket *nl, int argc, char *argv[]) { - struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; unsigned int seq, portid; @@ -137,18 +138,7 @@ static int nfct_cmd_helper_list(int argc, char *argv[]) nlh = nfct_helper_nlmsg_build_hdr(buf, NFNL_MSG_CTHELPER_GET, NLM_F_DUMP, seq); - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - nfct_perror("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - nfct_perror("mnl_socket_bind"); - return -1; - } portid = mnl_socket_get_portid(nl); - if (nfct_mnl_talk(nl, nlh, seq, portid, nfct_helper_cb, NULL) < 0) { nfct_perror("netlink error"); return -1; @@ -159,9 +149,8 @@ static int nfct_cmd_helper_list(int argc, char *argv[]) return 0; } -static int nfct_cmd_helper_add(int argc, char *argv[]) +static int nfct_cmd_helper_add(struct mnl_socket *nl, int argc, char *argv[]) { - struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq; @@ -242,31 +231,18 @@ static int nfct_cmd_helper_add(int argc, char *argv[]) nfct_helper_free(t); - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - nfct_perror("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - nfct_perror("mnl_socket_bind"); - return -1; - } portid = mnl_socket_get_portid(nl); - if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { nfct_perror("netlink error"); return -1; } - mnl_socket_close(nl); - return 0; } -static int nfct_cmd_helper_delete(int argc, char *argv[]) +static int +nfct_cmd_helper_delete(struct mnl_socket *nl, int argc, char *argv[]) { - struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq; @@ -323,31 +299,17 @@ static int nfct_cmd_helper_delete(int argc, char *argv[]) nfct_helper_free(t); - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - nfct_perror("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - nfct_perror("mnl_socket_bind"); - return -1; - } portid = mnl_socket_get_portid(nl); - if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { nfct_perror("netlink error"); return -1; } - mnl_socket_close(nl); - return 0; } -static int nfct_cmd_helper_get(int argc, char *argv[]) +static int nfct_cmd_helper_get(struct mnl_socket *nl, int argc, char *argv[]) { - struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq; @@ -404,31 +366,18 @@ static int nfct_cmd_helper_get(int argc, char *argv[]) nfct_helper_free(t); - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - nfct_perror("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - nfct_perror("mnl_socket_bind"); - return -1; - } portid = mnl_socket_get_portid(nl); - if (nfct_mnl_talk(nl, nlh, seq, portid, nfct_helper_cb, NULL) < 0) { nfct_perror("netlink error"); return -1; } - mnl_socket_close(nl); - return 0; } -static int nfct_cmd_helper_flush(int argc, char *argv[]) +static int +nfct_cmd_helper_flush(struct mnl_socket *nl, int argc, char *argv[]) { - struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq; @@ -442,18 +391,7 @@ static int nfct_cmd_helper_flush(int argc, char *argv[]) nlh = nfct_helper_nlmsg_build_hdr(buf, NFNL_MSG_CTHELPER_DEL, NLM_F_ACK, seq); - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - nfct_perror("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - nfct_perror("mnl_socket_bind"); - return -1; - } portid = mnl_socket_get_portid(nl); - if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { nfct_perror("netlink error"); return -1; @@ -464,9 +402,9 @@ static int nfct_cmd_helper_flush(int argc, char *argv[]) return 0; } -static int nfct_cmd_helper_disable(int argc, char *argv[]) +static int +nfct_cmd_helper_disable(struct mnl_socket *nl, int argc, char *argv[]) { - struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq; @@ -524,25 +462,12 @@ static int nfct_cmd_helper_disable(int argc, char *argv[]) nfct_helper_free(t); - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - nfct_perror("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - nfct_perror("mnl_socket_bind"); - return -1; - } portid = mnl_socket_get_portid(nl); - if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { nfct_perror("netlink error"); return -1; } - mnl_socket_close(nl); - return 0; } diff --git a/src/nfct-extensions/timeout.c b/src/nfct-extensions/timeout.c index c361dab..9f74eca 100644 --- a/src/nfct-extensions/timeout.c +++ b/src/nfct-extensions/timeout.c @@ -36,13 +36,14 @@ nfct_cmd_timeout_usage(char *argv[]) "[parameters...]\n", VERSION, argv[0]); } -static int nfct_cmd_timeout_list(int argc, char *argv[]); -static int nfct_cmd_timeout_add(int argc, char *argv[]); -static int nfct_cmd_timeout_delete(int argc, char *argv[]); -static int nfct_cmd_timeout_get(int argc, char *argv[]); -static int nfct_cmd_timeout_flush(int argc, char *argv[]); +static int nfct_cmd_timeout_list(struct mnl_socket *nl, int argc, char *argv[]); +static int nfct_cmd_timeout_add(struct mnl_socket *nl, int argc, char *argv[]); +static int nfct_cmd_timeout_delete(struct mnl_socket *nl, int argc, char *argv[]); +static int nfct_cmd_timeout_get(struct mnl_socket *nl, int argc, char *argv[]); +static int nfct_cmd_timeout_flush(struct mnl_socket *nl, int argc, char *argv[]); -static int nfct_cmd_timeout_parse_params(int argc, char *argv[]) +static int +nfct_cmd_timeout_parse_params(struct mnl_socket *nl, int argc, char *argv[]) { int cmd = NFCT_CMD_NONE, ret; @@ -68,19 +69,19 @@ static int nfct_cmd_timeout_parse_params(int argc, char *argv[]) } switch(cmd) { case NFCT_CMD_LIST: - ret = nfct_cmd_timeout_list(argc, argv); + ret = nfct_cmd_timeout_list(nl, argc, argv); break; case NFCT_CMD_ADD: - ret = nfct_cmd_timeout_add(argc, argv); + ret = nfct_cmd_timeout_add(nl, argc, argv); break; case NFCT_CMD_DELETE: - ret = nfct_cmd_timeout_delete(argc, argv); + ret = nfct_cmd_timeout_delete(nl, argc, argv); break; case NFCT_CMD_GET: - ret = nfct_cmd_timeout_get(argc, argv); + ret = nfct_cmd_timeout_get(nl, argc, argv); break; case NFCT_CMD_FLUSH: - ret = nfct_cmd_timeout_flush(argc, argv); + ret = nfct_cmd_timeout_flush(nl, argc, argv); break; } @@ -112,9 +113,8 @@ err: return MNL_CB_OK; } -static int nfct_cmd_timeout_list(int argc, char *argv[]) +static int nfct_cmd_timeout_list(struct mnl_socket *nl, int argc, char *argv[]) { - struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; unsigned int seq, portid; @@ -128,25 +128,12 @@ static int nfct_cmd_timeout_list(int argc, char *argv[]) nlh = nfct_timeout_nlmsg_build_hdr(buf, IPCTNL_MSG_TIMEOUT_GET, NLM_F_DUMP, seq); - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - nfct_perror("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - nfct_perror("mnl_socket_bind"); - return -1; - } portid = mnl_socket_get_portid(nl); - if (nfct_mnl_talk(nl, nlh, seq, portid, nfct_timeout_cb, NULL) < 0) { nfct_perror("netlink error"); return -1; } - mnl_socket_close(nl); - return 0; } @@ -262,9 +249,8 @@ nfct_cmd_timeout_parse(struct nfct_timeout *t, int argc, char *argv[]) return 0; } -int nfct_cmd_timeout_add(int argc, char *argv[]) +int nfct_cmd_timeout_add(struct mnl_socket *nl, int argc, char *argv[]) { - struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq; @@ -296,31 +282,17 @@ int nfct_cmd_timeout_add(int argc, char *argv[]) nfct_timeout_free(t); - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - nfct_perror("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - nfct_perror("mnl_socket_bind"); - return -1; - } portid = mnl_socket_get_portid(nl); - if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { nfct_perror("netlink error"); return -1; } - mnl_socket_close(nl); - return 0; } -int nfct_cmd_timeout_delete(int argc, char *argv[]) +int nfct_cmd_timeout_delete(struct mnl_socket *nl, int argc, char *argv[]) { - struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq; @@ -349,31 +321,17 @@ int nfct_cmd_timeout_delete(int argc, char *argv[]) nfct_timeout_free(t); - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - nfct_perror("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - nfct_perror("mnl_socket_bind"); - return -1; - } portid = mnl_socket_get_portid(nl); - if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { nfct_perror("netlink error"); return -1; } - mnl_socket_close(nl); - return 0; } -int nfct_cmd_timeout_get(int argc, char *argv[]) +int nfct_cmd_timeout_get(struct mnl_socket *nl, int argc, char *argv[]) { - struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq; @@ -402,31 +360,17 @@ int nfct_cmd_timeout_get(int argc, char *argv[]) nfct_timeout_free(t); - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - nfct_perror("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - nfct_perror("mnl_socket_bind"); - return -1; - } portid = mnl_socket_get_portid(nl); - if (nfct_mnl_talk(nl, nlh, seq, portid, nfct_timeout_cb, NULL) < 0) { nfct_perror("netlink error"); return -1; } - mnl_socket_close(nl); - return 0; } -int nfct_cmd_timeout_flush(int argc, char *argv[]) +int nfct_cmd_timeout_flush(struct mnl_socket *nl, int argc, char *argv[]) { - struct mnl_socket *nl; char buf[MNL_SOCKET_BUFFER_SIZE]; struct nlmsghdr *nlh; uint32_t portid, seq; @@ -440,25 +384,12 @@ int nfct_cmd_timeout_flush(int argc, char *argv[]) nlh = nfct_timeout_nlmsg_build_hdr(buf, IPCTNL_MSG_TIMEOUT_DELETE, NLM_F_ACK, seq); - nl = mnl_socket_open(NETLINK_NETFILTER); - if (nl == NULL) { - nfct_perror("mnl_socket_open"); - return -1; - } - - if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) { - nfct_perror("mnl_socket_bind"); - return -1; - } portid = mnl_socket_get_portid(nl); - if (nfct_mnl_talk(nl, nlh, seq, portid, NULL, NULL) < 0) { nfct_perror("netlink error"); return -1; } - mnl_socket_close(nl); - return 0; } diff --git a/src/nfct.c b/src/nfct.c index 84bb1b7..19e44be 100644 --- a/src/nfct.c +++ b/src/nfct.c @@ -69,6 +69,7 @@ int main(int argc, char *argv[]) { int subsys = NFCT_SUBSYS_NONE, ret = 0; struct nfct_extension *ext; + struct mnl_socket *nl; if (argc < 2) { usage(argv); @@ -103,7 +104,15 @@ int main(int argc, char *argv[]) VERSION, argv[1]); return EXIT_FAILURE; } - ret = ext->parse_params(argc, argv); + + nl = nfct_mnl_open(); + if (nl == NULL) { + nfct_perror("cannot open netlink"); + return -1; + } + + ret = ext->parse_params(nl, argc, argv); + mnl_socket_close(nl); break; } return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS; @@ -168,3 +177,17 @@ int nfct_mnl_talk(struct mnl_socket *nl, struct nlmsghdr *nlh, return 0; } + +struct mnl_socket *nfct_mnl_open(void) +{ + struct mnl_socket *nl; + + nl = mnl_socket_open(NETLINK_NETFILTER); + if (nl == NULL) + return NULL; + + if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) + return NULL; + + return nl; +} -- cgit v1.2.3 From 9b99aa2980574f4d3bf26145a1bf8bd69d34e764 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 3 Oct 2013 09:49:25 +0200 Subject: conntrackd: cthelper: add SANE helper This patch adds an userspace port of the SANE helper that is currently implemented in the kernel. This requires Linux kernel 3.12 to work. --- src/helpers/Makefile.am | 7 +- src/helpers/sane.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 src/helpers/sane.c diff --git a/src/helpers/Makefile.am b/src/helpers/Makefile.am index 59524f5..ad380e3 100644 --- a/src/helpers/Makefile.am +++ b/src/helpers/Makefile.am @@ -3,7 +3,8 @@ include $(top_srcdir)/Make_global.am pkglib_LTLIBRARIES = ct_helper_dhcpv6.la \ ct_helper_ftp.la \ ct_helper_rpc.la \ - ct_helper_tns.la + ct_helper_tns.la \ + ct_helper_sane.la ct_helper_dhcpv6_la_SOURCES = dhcpv6.c ct_helper_dhcpv6_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) @@ -20,3 +21,7 @@ ct_helper_rpc_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) ct_helper_tns_la_SOURCES = tns.c ct_helper_tns_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) ct_helper_tns_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) + +ct_helper_sane_la_SOURCES = sane.c +ct_helper_sane_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) +ct_helper_sane_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) diff --git a/src/helpers/sane.c b/src/helpers/sane.c new file mode 100644 index 0000000..79ca948 --- /dev/null +++ b/src/helpers/sane.c @@ -0,0 +1,172 @@ +/* + * (C) 2013 by Pablo Neira Ayuso + * + * Port this helper to userspace. + */ + +/* SANE connection tracking helper + * (SANE = Scanner Access Now Easy) + * For documentation about the SANE network protocol see + * http://www.sane-project.org/html/doc015.html + */ + +/* + * Copyright (C) 2007 Red Hat, Inc. + * Author: Michal Schmidt + * Based on the FTP conntrack helper (net/netfilter/nf_conntrack_ftp.c): + * (C) 1999-2001 Paul `Rusty' Russell + * (C) 2002-2004 Netfilter Core Team + * (C) 2003,2004 USAGI/WIDE Project + * (C) 2003 Yasuyuki Kozakai @USAGI + * + * 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. + */ + +#include "conntrackd.h" +#include "helper.h" +#include "myct.h" +#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum sane_state { + SANE_STATE_NORMAL, + SANE_STATE_START_REQUESTED, +}; + +struct sane_request { + uint32_t RPC_code; +#define SANE_NET_START 7 /* RPC code */ + + uint32_t handle; +}; + +struct sane_reply_net_start { + uint32_t status; +#define SANE_STATUS_SUCCESS 0 + + uint16_t zero; + uint16_t port; + /* other fields aren't interesting for conntrack */ +}; + +struct nf_ct_sane_master { + enum sane_state state; +}; + +static int +sane_helper_cb(struct pkt_buff *pkt, uint32_t protoff, + struct myct *myct, uint32_t ctinfo) +{ + unsigned int dataoff, datalen; + const struct tcphdr *th; + void *sb_ptr; + int ret = NF_ACCEPT; + int dir = CTINFO2DIR(ctinfo); + struct nf_ct_sane_master *ct_sane_info = myct->priv_data; + struct nf_expect *exp; + struct sane_request *req; + struct sane_reply_net_start *reply; + union nfct_attr_grp_addr saddr; + union nfct_attr_grp_addr daddr; + + /* Until there's been traffic both ways, don't look in packets. */ + if (ctinfo != IP_CT_ESTABLISHED && + ctinfo != IP_CT_ESTABLISHED_REPLY) + return NF_ACCEPT; + + th = (struct tcphdr *)(pktb_network_header(pkt) + protoff); + + /* No data? */ + dataoff = protoff + th->doff * 4; + if (dataoff >= pktb_len(pkt)) + return NF_ACCEPT; + + datalen = pktb_len(pkt) - dataoff; + + sb_ptr = pktb_network_header(pkt) + dataoff; + + if (dir == MYCT_DIR_ORIG) { + if (datalen != sizeof(struct sane_request)) + goto out; + + req = sb_ptr; + if (req->RPC_code != htonl(SANE_NET_START)) { + /* Not an interesting command */ + ct_sane_info->state = SANE_STATE_NORMAL; + goto out; + } + + /* We're interested in the next reply */ + ct_sane_info->state = SANE_STATE_START_REQUESTED; + goto out; + } + + /* Is it a reply to an uninteresting command? */ + if (ct_sane_info->state != SANE_STATE_START_REQUESTED) + goto out; + + /* It's a reply to SANE_NET_START. */ + ct_sane_info->state = SANE_STATE_NORMAL; + + if (datalen < sizeof(struct sane_reply_net_start)) { + pr_debug("nf_ct_sane: NET_START reply too short\n"); + goto out; + } + + reply = sb_ptr; + if (reply->status != htonl(SANE_STATUS_SUCCESS)) { + /* saned refused the command */ + pr_debug("nf_ct_sane: unsuccessful SANE_STATUS = %u\n", + ntohl(reply->status)); + goto out; + } + + /* Invalid saned reply? Ignore it. */ + if (reply->zero != 0) + goto out; + + exp = nfexp_new(); + if (exp == NULL) + return NF_DROP; + + cthelper_get_addr_src(myct->ct, MYCT_DIR_ORIG, &saddr); + cthelper_get_addr_dst(myct->ct, MYCT_DIR_ORIG, &daddr); + + if (cthelper_expect_init(exp, myct->ct, 0, &saddr, &daddr, + IPPROTO_TCP, NULL, &reply->port, 0)) { + nfexp_destroy(exp); + return NF_DROP; + } + myct->exp = exp; +out: + return ret; +} + +static struct ctd_helper sane_helper = { + .name = "sane", + .l4proto = IPPROTO_TCP, + .priv_data_len = sizeof(struct nf_ct_sane_master), + .cb = sane_helper_cb, + .policy = { + [0] = { + .name = "sane", + .expect_max = 1, + .expect_timeout = 5 * 60, + }, + }, +}; + +static void __attribute__ ((constructor)) sane_init(void) +{ + helper_register(&sane_helper); +} -- cgit v1.2.3 From ea753a152cbf3a2658b5ec5bacfb738c13a4c476 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 2 Oct 2013 19:21:01 +0200 Subject: conntrackd: cthelper: add TFTP helper This patch adds an userspace port of the TFTP helper that is currently implemented in the kernel. This includes NAT support. It requires a Linux kernel 3.12. Signed-off-by: Pablo Neira Ayuso --- include/helper.h | 3 ++ src/expect.c | 24 +++++++++ src/helpers/Makefile.am | 5 ++ src/helpers/tftp.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 170 insertions(+) create mode 100644 src/helpers/tftp.c diff --git a/include/helper.h b/include/helper.h index 9d96fb7..bd69af6 100644 --- a/include/helper.h +++ b/include/helper.h @@ -49,6 +49,9 @@ extern int cthelper_del_expect(struct nf_expect *exp); extern void cthelper_get_addr_src(struct nf_conntrack *ct, int dir, union nfct_attr_grp_addr *addr); extern void cthelper_get_addr_dst(struct nf_conntrack *ct, int dir, union nfct_attr_grp_addr *addr); +void cthelper_get_port_src(struct nf_conntrack *ct, int dir, uint16_t *port); +void cthelper_get_port_dst(struct nf_conntrack *ct, int dir, uint16_t *port); + extern int in4_pton(const char *src, int srclen, uint8_t *dst, int delim, const char **end); extern int in6_pton(const char *src, int srclen, uint8_t *dst, int delim, const char **end); diff --git a/src/expect.c b/src/expect.c index 470b9ae..bba0ed7 100644 --- a/src/expect.c +++ b/src/expect.c @@ -212,3 +212,27 @@ cthelper_get_addr_dst(struct nf_conntrack *ct, int dir, break; } } + +void cthelper_get_port_src(struct nf_conntrack *ct, int dir, uint16_t *port) +{ + switch (dir) { + case MYCT_DIR_ORIG: + *port = nfct_get_attr_u16(ct, ATTR_PORT_SRC); + break; + case MYCT_DIR_REPL: + *port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC); + break; + } +} + +void cthelper_get_port_dst(struct nf_conntrack *ct, int dir, uint16_t *port) +{ + switch (dir) { + case MYCT_DIR_ORIG: + *port = nfct_get_attr_u16(ct, ATTR_PORT_DST); + break; + case MYCT_DIR_REPL: + *port = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST); + break; + } +} diff --git a/src/helpers/Makefile.am b/src/helpers/Makefile.am index ad380e3..216a5a7 100644 --- a/src/helpers/Makefile.am +++ b/src/helpers/Makefile.am @@ -3,6 +3,7 @@ include $(top_srcdir)/Make_global.am pkglib_LTLIBRARIES = ct_helper_dhcpv6.la \ ct_helper_ftp.la \ ct_helper_rpc.la \ + ct_helper_tftp.la \ ct_helper_tns.la \ ct_helper_sane.la @@ -18,6 +19,10 @@ ct_helper_rpc_la_SOURCES = rpc.c ct_helper_rpc_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) ct_helper_rpc_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) +ct_helper_tftp_la_SOURCES = tftp.c +ct_helper_tftp_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) +ct_helper_tftp_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) + ct_helper_tns_la_SOURCES = tns.c ct_helper_tns_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) ct_helper_tns_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) diff --git a/src/helpers/tftp.c b/src/helpers/tftp.c new file mode 100644 index 0000000..45591c6 --- /dev/null +++ b/src/helpers/tftp.c @@ -0,0 +1,138 @@ +/* + * (C) 2013 by Pablo Neira Ayuso + * + * Adapted from: + * + * (C) 2001-2002 Magnus Boden + * (C) 2006-2012 Patrick McHardy + * 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. + */ + +#include "conntrackd.h" +#include "helper.h" +#include "myct.h" +#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct tftphdr { + uint16_t opcode; +}; + +#define TFTP_OPCODE_READ 1 +#define TFTP_OPCODE_WRITE 2 +#define TFTP_OPCODE_DATA 3 +#define TFTP_OPCODE_ACK 4 +#define TFTP_OPCODE_ERROR 5 + +static unsigned int nat_tftp(struct pkt_buff *pkt, uint32_t ctinfo, + struct nf_conntrack *ct, struct nf_expect *exp) +{ + struct nf_conntrack *nat_tuple; + static uint32_t zero[4] = { 0, 0, 0, 0 }; + + nat_tuple = nfct_new(); + if (nat_tuple == NULL) + return NF_ACCEPT; + + switch (nfct_get_attr_u8(ct, ATTR_L3PROTO)) { + case AF_INET: + nfct_set_attr_u8(nat_tuple, ATTR_L3PROTO, AF_INET); + nfct_set_attr_u32(nat_tuple, ATTR_IPV4_SRC, 0); + nfct_set_attr_u32(nat_tuple, ATTR_IPV4_DST, 0); + break; + case AF_INET6: + nfct_set_attr_u8(nat_tuple, ATTR_L3PROTO, AF_INET6); + nfct_set_attr(nat_tuple, ATTR_IPV6_SRC, &zero); + nfct_set_attr(nat_tuple, ATTR_IPV6_DST, &zero); + break; + } + nfct_set_attr_u8(nat_tuple, ATTR_L4PROTO, IPPROTO_UDP); + nfct_set_attr_u16(nat_tuple, ATTR_PORT_SRC, + nfct_get_attr_u16(ct, ATTR_PORT_SRC)); + nfct_set_attr_u16(nat_tuple, ATTR_PORT_DST, 0); + + nfexp_set_attr_u32(exp, ATTR_EXP_NAT_DIR, MYCT_DIR_REPL); + nfexp_set_attr(exp, ATTR_EXP_FN, "nat-follow-master"); + nfexp_set_attr(exp, ATTR_EXP_NAT_TUPLE, nat_tuple); + + return NF_ACCEPT; +} + +static int +tftp_helper_cb(struct pkt_buff *pkt, uint32_t protoff, + struct myct *myct, uint32_t ctinfo) +{ + const struct tftphdr *tfh; + struct nf_expect *exp; + unsigned int ret = NF_ACCEPT; + union nfct_attr_grp_addr saddr, daddr; + uint16_t dport; + + tfh = (struct tftphdr *)(pktb_network_header(pkt) + protoff + sizeof(struct udphdr)); + + switch (ntohs(tfh->opcode)) { + case TFTP_OPCODE_READ: + case TFTP_OPCODE_WRITE: + /* RRQ and WRQ works the same way */ + exp = nfexp_new(); + if (exp == NULL) { + pr_debug("cannot alloc expectation\n"); + return NF_DROP; + } + + cthelper_get_addr_src(myct->ct, MYCT_DIR_REPL, &saddr); + cthelper_get_addr_dst(myct->ct, MYCT_DIR_REPL, &daddr); + cthelper_get_port_dst(myct->ct, MYCT_DIR_REPL, &dport); + + if (cthelper_expect_init(exp, myct->ct, 0, &saddr, &daddr, + IPPROTO_UDP, NULL, &dport, 0)) { + nfexp_destroy(exp); + return NF_DROP; + } + + if (nfct_get_attr_u32(myct->ct, ATTR_STATUS) & IPS_NAT_MASK) + ret = nat_tftp(pkt, ctinfo, myct->ct, exp); + + myct->exp = exp; + break; + case TFTP_OPCODE_DATA: + case TFTP_OPCODE_ACK: + pr_debug("Data/ACK opcode\n"); + break; + case TFTP_OPCODE_ERROR: + pr_debug("Error opcode\n"); + break; + default: + pr_debug("Unknown opcode\n"); + } + return ret; +} + +static struct ctd_helper tftp_helper = { + .name = "tftp", + .l4proto = IPPROTO_UDP, + .cb = tftp_helper_cb, + .policy = { + [0] = { + .name = "tftp", + .expect_max = 1, + .expect_timeout = 5 * 60, + }, + }, +}; + +static void __attribute__ ((constructor)) tftp_init(void) +{ + helper_register(&tftp_helper); +} -- cgit v1.2.3 From 808a25129605c9e7de9f86fb8d5a5ed3310edd43 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 7 Oct 2013 14:41:20 +0200 Subject: conntrackd: cthelper: add amanda helper This patch adds a userspace port of the amanda helper that is currently implemented in the kernel. Signed-off-by: Pablo Neira Ayuso --- src/helpers/Makefile.am | 7 +- src/helpers/amanda.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 209 insertions(+), 1 deletion(-) create mode 100644 src/helpers/amanda.c diff --git a/src/helpers/Makefile.am b/src/helpers/Makefile.am index 216a5a7..fe28e83 100644 --- a/src/helpers/Makefile.am +++ b/src/helpers/Makefile.am @@ -1,12 +1,17 @@ include $(top_srcdir)/Make_global.am -pkglib_LTLIBRARIES = ct_helper_dhcpv6.la \ +pkglib_LTLIBRARIES = ct_helper_amanda.la \ + ct_helper_dhcpv6.la \ ct_helper_ftp.la \ ct_helper_rpc.la \ ct_helper_tftp.la \ ct_helper_tns.la \ ct_helper_sane.la +ct_helper_amanda_la_SOURCES = amanda.c +ct_helper_amanda_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) +ct_helper_amanda_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) + ct_helper_dhcpv6_la_SOURCES = dhcpv6.c ct_helper_dhcpv6_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) ct_helper_dhcpv6_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) diff --git a/src/helpers/amanda.c b/src/helpers/amanda.c new file mode 100644 index 0000000..c0cf701 --- /dev/null +++ b/src/helpers/amanda.c @@ -0,0 +1,203 @@ +/* + * (C) 2013 by Pablo Neira Ayuso + * + * Adapted from: + * + * Amanda extension for IP connection tracking + * + * (C) 2002 by Brian J. Murrell + * based on HW's ip_conntrack_irc.c as well as other modules + * (C) 2006 Patrick McHardy + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include "conntrackd.h" +#include "helper.h" +#include "myct.h" +#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int nat_amanda(struct pkt_buff *pkt, uint32_t ctinfo, + unsigned int matchoff, unsigned int matchlen, + struct nf_expect *exp) +{ + char buffer[sizeof("65535")]; + u_int16_t port, initial_port; + unsigned int ret; + const struct nf_conntrack *expected; + struct nf_conntrack *nat_tuple; + + nat_tuple = nfct_new(); + if (nat_tuple == NULL) + return NF_ACCEPT; + + expected = nfexp_get_attr(exp, ATTR_EXP_EXPECTED); + + /* Connection comes from client. */ + initial_port = nfct_get_attr_u16(expected, ATTR_PORT_DST); + nfexp_set_attr_u32(exp, ATTR_EXP_NAT_DIR, IP_CT_DIR_ORIGINAL); + + /* libnetfilter_conntrack needs this */ + nfct_set_attr_u8(nat_tuple, ATTR_L3PROTO, AF_INET); + nfct_set_attr_u32(nat_tuple, ATTR_IPV4_SRC, 0); + nfct_set_attr_u32(nat_tuple, ATTR_IPV4_DST, 0); + nfct_set_attr_u8(nat_tuple, ATTR_L4PROTO, IPPROTO_TCP); + nfct_set_attr_u16(nat_tuple, ATTR_PORT_DST, 0); + + /* When you see the packet, we need to NAT it the same as the + * this one (ie. same IP: it will be TCP and master is UDP). */ + nfexp_set_attr(exp, ATTR_EXP_FN, "nat-follow-master"); + + /* Try to get same port: if not, try to change it. */ + for (port = ntohs(initial_port); port != 0; port++) { + int res; + + nfct_set_attr_u16(nat_tuple, ATTR_PORT_SRC, htons(port)); + nfexp_set_attr(exp, ATTR_EXP_NAT_TUPLE, nat_tuple); + + res = cthelper_add_expect(exp); + if (res == 0) + break; + else if (res != -EBUSY) { + port = 0; + break; + } + } + + if (port == 0) { + pr_debug("all ports in use\n"); + return NF_DROP; + } + + sprintf(buffer, "%u", port); + ret = nfq_udp_mangle_ipv4(pkt, matchoff, matchlen, buffer, + strlen(buffer)); + if (ret != NF_ACCEPT) { + pr_debug("cannot mangle packet\n"); + cthelper_del_expect(exp); + } + return ret; +} + +static char amanda_buffer[65536]; +static unsigned int master_timeout = 300; + +enum amanda_strings { + SEARCH_CONNECT, + SEARCH_NEWLINE, + SEARCH_DATA, + SEARCH_MESG, + SEARCH_INDEX, +}; + +static const char *conns[] = { "DATA ", "MESG ", "INDEX " }; + +static int +amanda_helper_cb(struct pkt_buff *pkt, uint32_t protoff, + struct myct *myct, uint32_t ctinfo) +{ + struct nf_expect *exp; + char *data, *data_limit, *tmp; + unsigned int dataoff, i; + u_int16_t port, len; + int ret = NF_ACCEPT; + struct iphdr *iph; + union nfct_attr_grp_addr saddr, daddr; + + /* Only look at packets from the Amanda server */ + if (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) + return NF_ACCEPT; + + /* increase the UDP timeout of the master connection as replies from + * Amanda clients to the server can be quite delayed */ + nfct_set_attr_u32(myct->ct, ATTR_TIMEOUT, master_timeout); + + /* No data? */ + iph = (struct iphdr *)pktb_network_header(pkt); + dataoff = iph->ihl*4 + sizeof(struct udphdr); + if (dataoff >= pktb_len(pkt)) { + pr_debug("amanda_help: pktlen = %u\n", pktb_len(pkt)); + return NF_ACCEPT; + } + + memcpy(amanda_buffer, pktb_network_header(pkt) + dataoff, + pktb_len(pkt) - dataoff); + data = amanda_buffer; + data_limit = amanda_buffer + pktb_len(pkt) - dataoff; + *data_limit = '\0'; + + /* Search for the CONNECT string */ + data = strstr(data, "CONNECT "); + if (!data) + goto out; + data += strlen("CONNECT "); + + /* Only search first line. */ + if ((tmp = strchr(data, '\n'))) + *tmp = '\0'; + + for (i = 0; i < ARRAY_SIZE(conns); i++) { + char *match = strstr(data, conns[i]); + if (!match) + continue; + tmp = data = match + strlen(conns[i]); + port = strtoul(data, &data, 10); + len = data - tmp; + if (port == 0 || len > 5) + break; + + exp = nfexp_new(); + if (exp == NULL) + return NF_DROP; + + cthelper_get_addr_src(myct->ct, MYCT_DIR_ORIG, &saddr); + cthelper_get_addr_dst(myct->ct, MYCT_DIR_ORIG, &daddr); + cthelper_get_port_src(myct->ct, MYCT_DIR_ORIG, &port); + + if (cthelper_expect_init(exp, myct->ct, 0, &saddr, &daddr, + IPPROTO_TCP, NULL, &port, 0)) { + nfexp_destroy(exp); + return NF_DROP; + } + + if (nfct_get_attr_u32(myct->ct, ATTR_STATUS) & IPS_NAT_MASK) { + ret = nat_amanda(pkt, ctinfo, tmp - amanda_buffer, + len, exp); + } else + myct->exp = exp; + } +out: + return ret; +} + +static struct ctd_helper amanda_helper = { + .name = "amanda", + .l4proto = IPPROTO_UDP, + .cb = amanda_helper_cb, + .policy = { + [0] = { + .name = "amanda", + .expect_max = ARRAY_SIZE(conns), + .expect_timeout = 180, + }, + }, +}; + +void __attribute__ ((constructor)) amanda_init(void); + +void amanda_init(void) +{ + helper_register(&amanda_helper); +} -- cgit v1.2.3 From f3a760cad83a30524ef40d55d18fa1489252c8fb Mon Sep 17 00:00:00 2001 From: Hani Benhabiles Date: Fri, 11 Oct 2013 21:05:34 +0100 Subject: nfct: Fix use-after-free / double-free helper's list and flush commands handlers shouldn't call mnl_socket_close on the passed netlink socket as it is done in the main function after parse_params call. Bug introduced in (3c78a45 nfct: src: consolidate netlink socket creation). Signed-off-by: Hani Benhabiles Signed-off-by: Pablo Neira Ayuso --- src/nfct-extensions/helper.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/nfct-extensions/helper.c b/src/nfct-extensions/helper.c index 7544ed7..bfb153f 100644 --- a/src/nfct-extensions/helper.c +++ b/src/nfct-extensions/helper.c @@ -144,8 +144,6 @@ static int nfct_cmd_helper_list(struct mnl_socket *nl, int argc, char *argv[]) return -1; } - mnl_socket_close(nl); - return 0; } @@ -397,8 +395,6 @@ nfct_cmd_helper_flush(struct mnl_socket *nl, int argc, char *argv[]) return -1; } - mnl_socket_close(nl); - return 0; } -- cgit v1.2.3 From 7594d30611d7c4bec52ab90580b705fbf5d60925 Mon Sep 17 00:00:00 2001 From: Hani Benhabiles Date: Mon, 14 Oct 2013 23:14:24 +0100 Subject: conntrackd: Don't hardcode libs dir path Use CONNTRACKD_LIB_DIR instead of hardcoded path. Signed-off-by: Hani Benhabiles Signed-off-by: Pablo Neira Ayuso --- src/read_config_yy.y | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/read_config_yy.y b/src/read_config_yy.y index fa517bb..73fabbf 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -1613,8 +1613,7 @@ helper_type: T_TYPE T_STRING T_STRING T_STRING '{' helper_type_list '}' } #ifdef BUILD_CTHELPER - /* XXX use configure.ac definitions. */ - helper = helper_find("/usr/lib/conntrack-tools", $2, l4proto, RTLD_NOW); + helper = helper_find(CONNTRACKD_LIB_DIR, $2, l4proto, RTLD_NOW); if (helper == NULL) { print_err(CTD_CFG_ERROR, "Unknown `%s' helper", $2); exit(EXIT_FAILURE); -- cgit v1.2.3 From 91cf387fc61483bff05897fa356cfe183e165558 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 24 Dec 2013 13:22:46 +0100 Subject: build: don't include leftover .orig and .rej files in doc/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit And remove reference to .svn, we have been using git for quite some time already. Reported-by: Göran Uddeborg Signed-off-by: Pablo Neira Ayuso --- Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index bd366bf..975c538 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,4 +10,5 @@ DIST_SUBDIRS = include src extensions LIBS = @LIBNETFILTER_CONNTRACK_LIBS@ dist-hook: - rm -rf `find $(distdir)/doc -name .svn` + rm -rf `find $(distdir)/doc -name *.orig` + rm -rf `find $(distdir)/doc -name *.rej` -- cgit v1.2.3 From 92246dcc1fdcf222302a42926e0e95af2c30463e Mon Sep 17 00:00:00 2001 From: Ash Hughes Date: Sat, 8 Mar 2014 21:13:34 +0000 Subject: conntrackd: userspace SSDP helper Here is a patch which adds a userspace conntrack helper for the SSDP protocol. This is based on the code found at: http://marc.info/?t=132945775100001&r=1&w=2 I'm not sure how to get my laptop to play at IPv6, so I've not tested this part, but I've tested the IPv4 section and it works. Signed-off-by: Ash Hughes Signed-off-by: Pablo Neira Ayuso --- doc/helper/conntrackd.conf | 8 +++ doc/manual/conntrack-tools.tmpl | 1 + src/helpers/Makefile.am | 7 ++- src/helpers/ssdp.c | 134 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 1 deletion(-) create mode 100644 src/helpers/ssdp.c diff --git a/doc/helper/conntrackd.conf b/doc/helper/conntrackd.conf index 358ad10..d2d94a9 100644 --- a/doc/helper/conntrackd.conf +++ b/doc/helper/conntrackd.conf @@ -70,6 +70,14 @@ Helper { ExpectTimeout 300 } } + Type ssdp inet udp { + QueueNum 5 + QueueLen 10240 + Policy ssdp { + ExpectMax 1 + ExpectTimeout 300 + } + } } # diff --git a/doc/manual/conntrack-tools.tmpl b/doc/manual/conntrack-tools.tmpl index f21a4ff..d23dec5 100644 --- a/doc/manual/conntrack-tools.tmpl +++ b/doc/manual/conntrack-tools.tmpl @@ -890,6 +890,7 @@ maintainance. Oracle*TNS, to support its special Redirect message. NFSv3, mind that version 4 does not require this helper. FTP (this helper is also available in kernel-space). +SSDP. The following steps describe how to enable the RPC portmapper helper for NFSv3 (this is similar for other helpers): diff --git a/src/helpers/Makefile.am b/src/helpers/Makefile.am index fe28e83..78ef7aa 100644 --- a/src/helpers/Makefile.am +++ b/src/helpers/Makefile.am @@ -6,7 +6,8 @@ pkglib_LTLIBRARIES = ct_helper_amanda.la \ ct_helper_rpc.la \ ct_helper_tftp.la \ ct_helper_tns.la \ - ct_helper_sane.la + ct_helper_sane.la \ + ct_helper_ssdp.la ct_helper_amanda_la_SOURCES = amanda.c ct_helper_amanda_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) @@ -35,3 +36,7 @@ ct_helper_tns_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) ct_helper_sane_la_SOURCES = sane.c ct_helper_sane_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) ct_helper_sane_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) + +ct_helper_ssdp_la_SOURCES = ssdp.c +ct_helper_ssdp_la_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) +ct_helper_ssdp_la_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS) diff --git a/src/helpers/ssdp.c b/src/helpers/ssdp.c new file mode 100644 index 0000000..2713f23 --- /dev/null +++ b/src/helpers/ssdp.c @@ -0,0 +1,134 @@ +/* + * SSDP connection tracking helper + * (SSDP = Simple Service Discovery Protocol) + * For documentation about SSDP see + * http://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol + * + * Copyright (C) 2014 Ashley Hughes + * Based on the SSDP conntrack helper (nf_conntrack_ssdp.c), + * :http://marc.info/?t=132945775100001&r=1&w=2 + * (C) 2012 Ian Pilcher + * + * 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. + */ + +#include "conntrackd.h" +#include "helper.h" +#include "myct.h" +#include "log.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SSDP_MCAST_ADDR "239.255.255.250" +#define UPNP_MCAST_LL_ADDR "FF02::C" /* link-local */ +#define UPNP_MCAST_SL_ADDR "FF05::C" /* site-local */ + +#define SSDP_M_SEARCH "M-SEARCH" +#define SSDP_M_SEARCH_SIZE (sizeof SSDP_M_SEARCH - 1) + +static int ssdp_helper_cb(struct pkt_buff *pkt, uint32_t protoff, + struct myct *myct, uint32_t ctinfo) +{ + int ret = NF_ACCEPT; + union nfct_attr_grp_addr daddr, saddr, taddr; + struct iphdr *net_hdr = (struct iphdr *)pktb_network_header(pkt); + int good_packet = 0; + struct nf_expect *exp; + u_int16_t port; + unsigned int dataoff; + void *sb_ptr; + + cthelper_get_addr_dst(myct->ct, MYCT_DIR_ORIG, &daddr); + switch (nfct_get_attr_u8(myct->ct, ATTR_L3PROTO)) { + case AF_INET: + inet_pton(AF_INET, SSDP_MCAST_ADDR, &(taddr.ip)); + if (daddr.ip == taddr.ip) + good_packet = 1; + break; + case AF_INET6: + inet_pton(AF_INET6, UPNP_MCAST_LL_ADDR, &(taddr.ip6)); + if (daddr.ip6[0] == taddr.ip6[0] && + daddr.ip6[1] == taddr.ip6[1] && + daddr.ip6[2] == taddr.ip6[2] && + daddr.ip6[3] == taddr.ip6[3]) { + good_packet = 1; + break; + } + inet_pton(AF_INET6, UPNP_MCAST_SL_ADDR, &(taddr.ip6)); + if (daddr.ip6[0] == taddr.ip6[0] && + daddr.ip6[1] == taddr.ip6[1] && + daddr.ip6[2] == taddr.ip6[2] && + daddr.ip6[3] == taddr.ip6[3]) { + good_packet = 1; + break; + } + break; + default: + break; + } + + if (!good_packet) { + pr_debug("ssdp_help: destination address not multicast; ignoring\n"); + return NF_ACCEPT; + } + + /* No data? Ignore */ + dataoff = net_hdr->ihl*4 + sizeof(struct udphdr); + if (dataoff >= pktb_len(pkt)) { + pr_debug("ssdp_help: UDP payload too small for M-SEARCH; ignoring\n"); + return NF_ACCEPT; + } + + sb_ptr = pktb_network_header(pkt) + dataoff; + + if (memcmp(sb_ptr, SSDP_M_SEARCH, SSDP_M_SEARCH_SIZE) != 0) { + pr_debug("ssdp_help: UDP payload does not begin with 'M-SEARCH'; ignoring\n"); + return NF_ACCEPT; + } + + cthelper_get_addr_src(myct->ct, MYCT_DIR_ORIG, &saddr); + cthelper_get_port_src(myct->ct, MYCT_DIR_ORIG, &port); + + exp = nfexp_new(); + if (exp == NULL) + return NF_DROP; + + if (cthelper_expect_init(exp, myct->ct, 0, NULL, &saddr, + IPPROTO_UDP, NULL, &port, + NF_CT_EXPECT_PERMANENT)) { + nfexp_destroy(exp); + return NF_DROP; + } + myct->exp = exp; + + return ret; +} + +static struct ctd_helper ssdp_helper = { + .name = "ssdp", + .l4proto = IPPROTO_UDP, + .priv_data_len = 0, + .cb = ssdp_helper_cb, + .policy = { + [0] = { + .name = "ssdp", + .expect_max = 1, + .expect_timeout = 5 * 60, + }, + }, +}; + +static void __attribute__ ((constructor)) ssdp_init(void) +{ + helper_register(&ssdp_helper); +} -- cgit v1.2.3 From 34a8e200eee54b4bbecadf52bba8901cae129795 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 12 May 2014 17:21:21 +0200 Subject: nfct: remove unneeded included header This fixes a compilation breakage when libnetfilter_cttimeout.h is not installed. Reported-by: Hangbin Liu Signed-off-by: Pablo Neira Ayuso --- src/nfct.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/nfct.c b/src/nfct.c index 19e44be..533d75d 100644 --- a/src/nfct.c +++ b/src/nfct.c @@ -22,8 +22,6 @@ #include #include -#include -#include #include "linux_list.h" #include "nfct.h" -- cgit v1.2.3 From 1ecda7339e8678c0b4debe7003b4a42791ad478e Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 1 Oct 2013 13:28:11 +0200 Subject: nfct: timeout: add support for default protocol timeout tuning This new interface supersedes the /proc interface: /proc/sys/net/netfilter/nf_conntrack_PROTO_STATE_timeout to tune default conntrack timeout helpers. # nfct timeout default-get inet tcp .l3proto = 2, .l4proto = 6, .policy = { .SYN_SENT = 120, .SYN_RECV = 60, .ESTABLISHED = 432000, .FIN_WAIT = 120, .CLOSE_WAIT = 60, .LAST_ACK = 30, .TIME_WAIT = 120, .CLOSE = 10, .SYN_SENT2 = 120, .RETRANS = 300, .UNACKNOWLEDGED = 300, }, }; # nfct timeout default-set inet tcp ESTABLISHED 100 As replacement for the existing /proc interfaces for timeout tweaking. This feature requires a Linux kernel >= 3.13. Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/nfnetlink_cttimeout.h | 2 + include/nfct.h | 2 + src/nfct-extensions/timeout.c | 106 +++++++++++++++++++++++++- 3 files changed, 108 insertions(+), 2 deletions(-) diff --git a/include/linux/netfilter/nfnetlink_cttimeout.h b/include/linux/netfilter/nfnetlink_cttimeout.h index a2810a7..1ab0b97 100644 --- a/include/linux/netfilter/nfnetlink_cttimeout.h +++ b/include/linux/netfilter/nfnetlink_cttimeout.h @@ -6,6 +6,8 @@ enum ctnl_timeout_msg_types { IPCTNL_MSG_TIMEOUT_NEW, IPCTNL_MSG_TIMEOUT_GET, IPCTNL_MSG_TIMEOUT_DELETE, + IPCTNL_MSG_TIMEOUT_DEFAULT_SET, + IPCTNL_MSG_TIMEOUT_DEFAULT_GET, IPCTNL_MSG_TIMEOUT_MAX }; diff --git a/include/nfct.h b/include/nfct.h index 682fe3a..dc103c6 100644 --- a/include/nfct.h +++ b/include/nfct.h @@ -19,6 +19,8 @@ enum { NFCT_CMD_GET, NFCT_CMD_FLUSH, NFCT_CMD_DISABLE, + NFCT_CMD_DEFAULT_SET, + NFCT_CMD_DEFAULT_GET, }; #define __init __attribute__((constructor)) diff --git a/src/nfct-extensions/timeout.c b/src/nfct-extensions/timeout.c index 9f74eca..c9aa386 100644 --- a/src/nfct-extensions/timeout.c +++ b/src/nfct-extensions/timeout.c @@ -32,8 +32,8 @@ static void nfct_cmd_timeout_usage(char *argv[]) { fprintf(stderr, "nfct v%s: Missing command\n" - "%s timeout list|add|delete|get|flush " - "[parameters...]\n", VERSION, argv[0]); + "%s timeout " + "[, ...]\n", VERSION, argv[0]); } static int nfct_cmd_timeout_list(struct mnl_socket *nl, int argc, char *argv[]); @@ -41,6 +41,8 @@ static int nfct_cmd_timeout_add(struct mnl_socket *nl, int argc, char *argv[]); static int nfct_cmd_timeout_delete(struct mnl_socket *nl, int argc, char *argv[]); static int nfct_cmd_timeout_get(struct mnl_socket *nl, int argc, char *argv[]); static int nfct_cmd_timeout_flush(struct mnl_socket *nl, int argc, char *argv[]); +static int nfct_cmd_timeout_default_set(struct mnl_socket *nl, int argc, char *argv[]); +static int nfct_cmd_timeout_default_get(struct mnl_socket *nl, int argc, char *argv[]); static int nfct_cmd_timeout_parse_params(struct mnl_socket *nl, int argc, char *argv[]) @@ -61,6 +63,10 @@ nfct_cmd_timeout_parse_params(struct mnl_socket *nl, int argc, char *argv[]) cmd = NFCT_CMD_GET; else if (strncmp(argv[2], "flush", strlen(argv[2])) == 0) cmd = NFCT_CMD_FLUSH; + else if (strncmp(argv[2], "default-set", strlen(argv[2])) == 0) + cmd = NFCT_CMD_DEFAULT_SET; + else if (strncmp(argv[2], "default-get", strlen(argv[2])) == 0) + cmd = NFCT_CMD_DEFAULT_GET; else { fprintf(stderr, "nfct v%s: Unknown command: %s\n", VERSION, argv[2]); @@ -83,6 +89,12 @@ nfct_cmd_timeout_parse_params(struct mnl_socket *nl, int argc, char *argv[]) case NFCT_CMD_FLUSH: ret = nfct_cmd_timeout_flush(nl, argc, argv); break; + case NFCT_CMD_DEFAULT_SET: + ret = nfct_cmd_timeout_default_set(nl, argc, argv); + break; + case NFCT_CMD_DEFAULT_GET: + ret = nfct_cmd_timeout_default_get(nl, argc, argv); + break; } return ret; @@ -393,6 +405,96 @@ int nfct_cmd_timeout_flush(struct mnl_socket *nl, int argc, char *argv[]) return 0; } +static int +nfct_cmd_timeout_default_set(struct mnl_socket *nl, int argc, char *argv[]) +{ + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + uint32_t portid, seq; + struct nfct_timeout *t; + + if (argc < 6) { + nfct_perror("missing parameters\n" + "syntax: nfct timeout default-set " + "family protocol state1 " + "timeout1 state2 timeout2..."); + return -1; + } + + t = nfct_timeout_alloc(); + if (t == NULL) + return -1; + + if (nfct_cmd_timeout_parse(t, argc-3, &argv[3]) < 0) + return -1; + + seq = time(NULL); + nlh = nfct_timeout_nlmsg_build_hdr(buf, IPCTNL_MSG_TIMEOUT_DEFAULT_SET, + NLM_F_ACK, seq); + nfct_timeout_nlmsg_build_payload(nlh, t); + nfct_timeout_free(t); + + portid = mnl_socket_get_portid(nl); + if (nfct_mnl_talk(nl, nlh, seq, portid, nfct_timeout_cb, NULL) < 0) { + nfct_perror("netlink error"); + return -1; + } + + return 0; +} + +static int +nfct_cmd_timeout_default_get(struct mnl_socket *nl, int argc, char *argv[]) +{ + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + uint32_t portid, seq; + struct nfct_timeout *t; + int l3proto, l4proto; + + if (argc < 5) { + nfct_perror("missing parameters\n" + "syntax: nfct timeout default-get " + "family protocol"); + return -1; + } + + t = nfct_timeout_alloc(); + if (t == NULL) + return -1; + + argc-=3; + argv+=3; + + l3proto = nfct_cmd_get_l3proto(argv); + if (l3proto < 0) + return -1; + + nfct_timeout_attr_set_u16(t, NFCT_TIMEOUT_ATTR_L3PROTO, l3proto); + argc--; + argv++; + + l4proto = nfct_cmd_get_l4proto(argv); + if (l4proto < 0) + return -1; + + nfct_timeout_attr_set_u8(t, NFCT_TIMEOUT_ATTR_L4PROTO, l4proto); + + seq = time(NULL); + nlh = nfct_timeout_nlmsg_build_hdr(buf, IPCTNL_MSG_TIMEOUT_DEFAULT_GET, + NLM_F_ACK, seq); + nfct_timeout_nlmsg_build_payload(nlh, t); + nfct_timeout_free(t); + + portid = mnl_socket_get_portid(nl); + if (nfct_mnl_talk(nl, nlh, seq, portid, nfct_timeout_cb, NULL) < 0) { + nfct_perror("netlink error"); + return -1; + } + + return 0; +} + static struct nfct_extension timeout = { .type = NFCT_SUBSYS_TIMEOUT, .parse_params = nfct_cmd_timeout_parse_params, -- cgit v1.2.3 From 20ddbf33277108da86c69bb78890fac09e055627 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 29 May 2014 14:33:29 +0200 Subject: udp: bind UDP sender side to same interface of the receiver side Otherwise, the kernel may select a different interface for the client side. Original patch from Michael Griego. While at it, remove some trailing whitespaces. Signed-off-by: Pablo Neira Ayuso --- src/udp.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/udp.c b/src/udp.c index ecaa46e..d0a7f5b 100644 --- a/src/udp.c +++ b/src/udp.c @@ -136,14 +136,18 @@ struct udp_sock *udp_client_create(struct udp_conf *conf) m->addr.ipv4.sin_family = AF_INET; m->addr.ipv4.sin_port = htons(conf->port); m->addr.ipv4.sin_addr = conf->client.inet_addr; - m->sockaddr_len = sizeof(struct sockaddr_in); + m->sockaddr_len = sizeof(struct sockaddr_in); break; case AF_INET6: m->addr.ipv6.sin6_family = AF_INET6; m->addr.ipv6.sin6_port = htons(conf->port); memcpy(&m->addr.ipv6.sin6_addr, &conf->client.inet_addr6, sizeof(struct in6_addr)); - m->sockaddr_len = sizeof(struct sockaddr_in6); + m->sockaddr_len = sizeof(struct sockaddr_in6); + /* Bind the sender side to the same interface that we use to + * receive sync messages. + */ + m->addr.ipv6.sin6_scope_id = conf->server.ipv6.scope_id; break; default: ret = -1; -- cgit v1.2.3 From c392c159605956c7bd4a264ab4490e2b2704c0cd Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 13 Jun 2014 12:53:17 +0200 Subject: conntrackd: build: fix crash when optional kernel modules are not loaded Fix a possible crash if conntrackd sees DCCP, SCTP and ICMPv6 traffic and the corresponding kernel modules that track this traffic are not available. Fixes: http://bugzilla.netfilter.org/show_bug.cgi?id=910 Signed-off-by: Pablo Neira Ayuso --- src/build.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/build.c b/src/build.c index 5799b51..9ba8b57 100644 --- a/src/build.c +++ b/src/build.c @@ -105,14 +105,14 @@ static enum nf_conntrack_attr nat_type[] = ATTR_ORIG_NAT_SEQ_OFFSET_AFTER, ATTR_REPL_NAT_SEQ_CORRECTION_POS, ATTR_REPL_NAT_SEQ_OFFSET_BEFORE, ATTR_REPL_NAT_SEQ_OFFSET_AFTER }; +/* ICMP, UDP and TCP are always loaded with nf_conntrack_ipv4 */ static void build_l4proto_tcp(const struct nf_conntrack *ct, struct nethdr *n) { - ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT, - sizeof(struct nfct_attr_grp_port)); - if (!nfct_attr_is_set(ct, ATTR_TCP_STATE)) return; + ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT, + sizeof(struct nfct_attr_grp_port)); ct_build_u8(ct, ATTR_TCP_STATE, n, NTA_TCP_STATE); if (CONFIG(sync).tcp_window_tracking) { ct_build_u8(ct, ATTR_TCP_WSCALE_ORIG, n, NTA_TCP_WSCALE_ORIG); @@ -122,12 +122,12 @@ static void build_l4proto_tcp(const struct nf_conntrack *ct, struct nethdr *n) static void build_l4proto_sctp(const struct nf_conntrack *ct, struct nethdr *n) { - ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT, - sizeof(struct nfct_attr_grp_port)); - + /* SCTP is optional, make sure nf_conntrack_sctp is loaded */ if (!nfct_attr_is_set(ct, ATTR_SCTP_STATE)) return; + ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT, + sizeof(struct nfct_attr_grp_port)); ct_build_u8(ct, ATTR_SCTP_STATE, n, NTA_SCTP_STATE); ct_build_u32(ct, ATTR_SCTP_VTAG_ORIG, n, NTA_SCTP_VTAG_ORIG); ct_build_u32(ct, ATTR_SCTP_VTAG_REPL, n, NTA_SCTP_VTAG_REPL); @@ -135,18 +135,22 @@ static void build_l4proto_sctp(const struct nf_conntrack *ct, struct nethdr *n) static void build_l4proto_dccp(const struct nf_conntrack *ct, struct nethdr *n) { - ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT, - sizeof(struct nfct_attr_grp_port)); - + /* DCCP is optional, make sure nf_conntrack_dccp is loaded */ if (!nfct_attr_is_set(ct, ATTR_DCCP_STATE)) return; + ct_build_group(ct, ATTR_GRP_ORIG_PORT, n, NTA_PORT, + sizeof(struct nfct_attr_grp_port)); ct_build_u8(ct, ATTR_DCCP_STATE, n, NTA_DCCP_STATE); ct_build_u8(ct, ATTR_DCCP_ROLE, n, NTA_DCCP_ROLE); } static void build_l4proto_icmp(const struct nf_conntrack *ct, struct nethdr *n) { + /* This is also used by ICMPv6 and nf_conntrack_ipv6 is optional */ + if (!nfct_attr_is_set(ct, ATTR_ICMP_TYPE)) + return; + ct_build_u8(ct, ATTR_ICMP_TYPE, n, NTA_ICMP_TYPE); ct_build_u8(ct, ATTR_ICMP_CODE, n, NTA_ICMP_CODE); ct_build_u16(ct, ATTR_ICMP_ID, n, NTA_ICMP_ID); -- cgit v1.2.3 From e78ce22430f4b1e10daef21d480298d0fdb377d9 Mon Sep 17 00:00:00 2001 From: Arturo Borrero Date: Thu, 25 Sep 2014 11:45:11 +0200 Subject: man: fix hyphen used as minus sign Report from Debian's lintian: This manual page seems to contain a hyphen where a minus sign was intended. By default, "-" chars are interpreted as hyphens (U+2010) by groff, not as minus signs (U+002D). Since options to programs use minus signs (U+002D), this means for example in UTF-8 locales that you cannot cut and paste options, nor search for them easily. [...] Signed-off-by: Arturo Borrero Gonzalez Signed-off-by: Pablo Neira Ayuso --- conntrack.8 | 22 +++++++++++----------- conntrackd.8 | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/conntrack.8 b/conntrack.8 index 45e8582..abc26c5 100644 --- a/conntrack.8 +++ b/conntrack.8 @@ -1,4 +1,4 @@ -.TH CONNTRACK 8 "Jul 5, 2010" "" "" +.TH CONNTRACK 8 "Sep 25, 2014" "" "" .\" Man page written by Harald Welte (Dec 2007) @@ -32,7 +32,7 @@ Dump the external cache, i.e. show foreign states .TP .BI "-x " Display output in XML format. This option is only valid in combination -with "-i" and "-e" parameters. +with "\-i" and "\-e" parameters. .TP .BI "-f " "[|internal|external]" Flush the internal and/or external cache -- cgit v1.2.3 From 0ec644c3583b50e68ff23597d8d2c257bfcf7c71 Mon Sep 17 00:00:00 2001 From: Thomas Jarosch Date: Wed, 10 Dec 2014 22:56:35 +0100 Subject: channel: Fix file descriptor leak in channel_open() on error Detected by cppcheck Signed-off-by: Thomas Jarosch Signed-off-by: Pablo Neira Ayuso --- src/channel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/channel.c b/src/channel.c index 8b7c319..acbfa7d 100644 --- a/src/channel.c +++ b/src/channel.c @@ -109,6 +109,7 @@ channel_open(struct channel_conf *cfg) if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) { free(c); + close(fd); return NULL; } close(fd); -- cgit v1.2.3 From 1c68250df4ca260392f532bf968fa28c40a7f974 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sun, 21 Dec 2014 22:55:30 +0100 Subject: conntrack: fix doc/cli/test.sh create-expect when I run the test script of conntrack-tools sh doc/cli/test.sh create-expect the output is: conntrack v1.4.1 (conntrack-tools): You need to supply the `--reply-port-src' option for this command. Try `conntrack -h' or 'conntrack --help' for more information. This used to work without the --reply-port-src stuff using version 0.9.13 IIRC. Reported-by: Thomas Jarosch Signed-off-by: Pablo Neira Ayuso --- extensions/libct_proto_dccp.c | 2 +- extensions/libct_proto_sctp.c | 2 +- extensions/libct_proto_tcp.c | 2 +- extensions/libct_proto_udp.c | 2 +- extensions/libct_proto_udplite.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/libct_proto_dccp.c b/extensions/libct_proto_dccp.c index 586c4cc..f37ef68 100644 --- a/extensions/libct_proto_dccp.c +++ b/extensions/libct_proto_dccp.c @@ -78,7 +78,7 @@ static char dccp_commands_v_options[NUMBER_OF_CMD][DCCP_OPT_MAX] = /*CT_VERSION*/ {0,0,0,0,0,0,0,0,0,0}, /*CT_HELP*/ {0,0,0,0,0,0,0,0,0,0}, /*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0}, -/*EXP_CREATE*/ {1,1,1,1,1,1,0,1,1,1}, +/*EXP_CREATE*/ {1,1,0,0,1,1,0,1,1,1}, /*EXP_DELETE*/ {1,1,1,1,0,0,0,0,0,0}, /*EXP_GET*/ {1,1,1,1,0,0,0,0,0,0}, /*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0}, diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c index f4c94df..97042c3 100644 --- a/extensions/libct_proto_sctp.c +++ b/extensions/libct_proto_sctp.c @@ -81,7 +81,7 @@ static char sctp_commands_v_options[NUMBER_OF_CMD][SCTP_OPT_MAX] = /*CT_VERSION*/ {0,0,0,0,0,0,0,0,0,0,0}, /*CT_HELP*/ {0,0,0,0,0,0,0,0,0,0,0}, /*EXP_LIST*/ {0,0,0,0,0,0,0,0,0,0,0}, -/*EXP_CREATE*/ {1,1,1,1,1,1,0,1,1,1,1}, +/*EXP_CREATE*/ {1,1,0,0,1,1,0,1,1,1,1}, /*EXP_DELETE*/ {1,1,1,1,0,0,0,0,0,0,0}, /*EXP_GET*/ {1,1,1,1,0,0,0,0,0,0,0}, /*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0,0,0}, diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c index 0b43bf5..65acd5a 100644 --- a/extensions/libct_proto_tcp.c +++ b/extensions/libct_proto_tcp.c @@ -65,7 +65,7 @@ static char tcp_commands_v_options[NUMBER_OF_CMD][TCP_NUMBER_OF_OPT] = /*CT_VERSION*/ {0,0,0,0,0,0,0,0,0}, /*CT_HELP*/ {0,0,0,0,0,0,0,0,0}, /*EXP_LIST*/ {0,0,0,0,0,0,0,0,0}, -/*EXP_CREATE*/ {1,1,1,1,1,1,0,1,1}, +/*EXP_CREATE*/ {1,1,0,0,1,1,0,1,1}, /*EXP_DELETE*/ {1,1,1,1,0,0,0,0,0}, /*EXP_GET*/ {1,1,1,1,0,0,0,0,0}, /*EXP_FLUSH*/ {0,0,0,0,0,0,0,0,0}, diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c index d7c4da1..768304b 100644 --- a/extensions/libct_proto_udp.c +++ b/extensions/libct_proto_udp.c @@ -73,7 +73,7 @@ static char udp_commands_v_options[NUMBER_OF_CMD][UDP_NUMBER_OF_OPT] = /*CT_VERSION*/ {0,0,0,0,0,0,0,0}, /*CT_HELP*/ {0,0,0,0,0,0,0,0}, /*EXP_LIST*/ {0,0,0,0,0,0,0,0}, -/*EXP_CREATE*/ {1,1,1,1,1,1,1,1}, +/*EXP_CREATE*/ {1,1,0,0,1,1,1,1}, /*EXP_DELETE*/ {1,1,1,1,0,0,0,0}, /*EXP_GET*/ {1,1,1,1,0,0,0,0}, /*EXP_FLUSH*/ {0,0,0,0,0,0,0,0}, diff --git a/extensions/libct_proto_udplite.c b/extensions/libct_proto_udplite.c index bffd5fe..9b67bef 100644 --- a/extensions/libct_proto_udplite.c +++ b/extensions/libct_proto_udplite.c @@ -81,7 +81,7 @@ static char udplite_commands_v_options[NUMBER_OF_CMD][UDP_OPT_MAX] = /*CT_VERSION*/ {0,0,0,0,0,0,0,0}, /*CT_HELP*/ {0,0,0,0,0,0,0,0}, /*EXP_LIST*/ {0,0,0,0,0,0,0,0}, -/*EXP_CREATE*/ {1,1,1,1,1,1,1,1}, +/*EXP_CREATE*/ {1,1,0,0,1,1,1,1}, /*EXP_DELETE*/ {1,1,1,1,0,0,0,0}, /*EXP_GET*/ {1,1,1,1,0,0,0,0}, /*EXP_FLUSH*/ {0,0,0,0,0,0,0,0}, -- cgit v1.2.3 From a3cd4dfb85b3ee9194ea82eb5185f9df2cb4ecf8 Mon Sep 17 00:00:00 2001 From: Jarno Rajahalme Date: Mon, 2 Feb 2015 12:35:12 -0800 Subject: conntrack: fix setting labels in updates When updating labels we always have to send the same sized bitmask as we received, as the bits we do omit will otherwise cleared as "padding". Mask has to have the same size as the labels, otherwise it will not be encoded by libnetfilter_conntrack, as different sizes are not accepted by the kernel either. Finally, kernel only retains old bit values that we send as zeroes in BOTH the label and the mask, due to XOR used in bit manipulation. This patch fixes all these issues and allows updates to set new labels without accidentally clearing old ones. Signed-off-by: Jarno Rajahalme Signed-off-by: Florian Westphal --- src/conntrack.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/conntrack.c b/src/conntrack.c index 1e45ca8..f6d7d9a 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -1422,17 +1422,31 @@ static void copy_label(struct nf_conntrack *tmp, const struct nf_conntrack *ct) if (options & CT_OPT_ADD_LABEL) { if (ctb == NULL) { - newmask = xnfct_bitmask_clone(tmpl.label_modify); - nfct_set_attr(tmp, ATTR_CONNLABELS, newmask); + nfct_set_attr(tmp, ATTR_CONNLABELS, + xnfct_bitmask_clone(tmpl.label_modify)); return; } + /* If we send a bitmask shorter than the kernel sent to us, the bits we + * omit will be cleared (as "padding"). So we always have to send the + * same sized bitmask as we received. + * + * Mask has to have the same size as the labels, otherwise it will not + * be encoded by libnetfilter_conntrack, as different sizes are not + * accepted by the kernel. + */ + newmask = nfct_bitmask_new(nfct_bitmask_maxbit(ctb)); for (i = 0; i <= nfct_bitmask_maxbit(ctb); i++) { - if (nfct_bitmask_test_bit(tmpl.label_modify, i)) + if (nfct_bitmask_test_bit(tmpl.label_modify, i)) { nfct_bitmask_set_bit(ctb, i); + nfct_bitmask_set_bit(newmask, i); + } else if (nfct_bitmask_test_bit(ctb, i)) { + /* Kernel only retains old bit values that are sent as + * zeroes in BOTH labels and mask. + */ + nfct_bitmask_unset_bit(ctb, i); + } } - - newmask = xnfct_bitmask_clone(tmpl.label_modify); nfct_set_attr(tmp, ATTR_CONNLABELS_MASK, newmask); } else if (ctb != NULL) { /* CT_OPT_DEL_LABEL */ -- cgit v1.2.3 From 175f4af13fa8f2ed05907d1e780ee1f609908daa Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Thu, 19 Feb 2015 00:54:42 +0100 Subject: conntrackd: allow strings with underscore from flex scanner Some people use interface names with underscores, so allow them from the flex scanner. Original patch from http://patchwork.ozlabs.org/patch/440600/ Signed-off-by: Pablo Neira Ayuso --- src/read_config_lex.l | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/read_config_lex.l b/src/read_config_lex.l index b4d11d4..8350069 100644 --- a/src/read_config_lex.l +++ b/src/read_config_lex.l @@ -47,7 +47,7 @@ ip6_part {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\.\-]* +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] nack [N|n][A|a][C|c][K|k] alarm [A|a][L|l][A|a][R|r][M|m] -- cgit v1.2.3 From eed61ed57fd2a82b81af9bd2f6895b3aa5221f49 Mon Sep 17 00:00:00 2001 From: Felix Janda Date: Sat, 16 May 2015 11:19:02 +0200 Subject: configure: Add AM_PROG_AR to silence automake warning /usr/share/automake-1.13/am/ltlibrary.am: warning: 'ct_helper_tns.la': linking libtool libraries using a non-POSIX /usr/share/automake-1.13/am/ltlibrary.am: archiver requires 'AM_PROG_AR' in 'configure.ac' src/helpers/Makefile.am:3: while processing Libtool library 'ct_helper_tns.la' Signed-off-by: Felix Janda Signed-off-by: Pablo Neira Ayuso --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index f0800d6..523a192 100644 --- a/configure.ac +++ b/configure.ac @@ -14,6 +14,7 @@ AC_SUBST([libdl_LIBS]) AC_PROG_CC AC_DISABLE_STATIC +AM_PROG_AR AM_PROG_LIBTOOL AC_PROG_INSTALL AC_PROG_LN_S -- cgit v1.2.3 From 3c1b1e54a46ad31e6ee7e5d87eed84bd29d8f460 Mon Sep 17 00:00:00 2001 From: Felix Janda Date: Sat, 16 May 2015 11:26:57 +0200 Subject: include: Sync with kernel headers Signed-off-by: Felix Janda Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter/nfnetlink.h | 54 ++++++++----------------------- include/linux/netfilter/nfnetlink_queue.h | 5 ++- 2 files changed, 17 insertions(+), 42 deletions(-) diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index b64454c..c755646 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -18,6 +18,10 @@ enum nfnetlink_groups { #define NFNLGRP_CONNTRACK_EXP_UPDATE NFNLGRP_CONNTRACK_EXP_UPDATE NFNLGRP_CONNTRACK_EXP_DESTROY, #define NFNLGRP_CONNTRACK_EXP_DESTROY NFNLGRP_CONNTRACK_EXP_DESTROY + NFNLGRP_NFTABLES, +#define NFNLGRP_NFTABLES NFNLGRP_NFTABLES + NFNLGRP_ACCT_QUOTA, +#define NFNLGRP_ACCT_QUOTA NFNLGRP_ACCT_QUOTA __NFNLGRP_MAX, }; #define NFNLGRP_MAX (__NFNLGRP_MAX - 1) @@ -49,46 +53,14 @@ struct nfgenmsg { #define NFNL_SUBSYS_OSF 5 #define NFNL_SUBSYS_IPSET 6 #define NFNL_SUBSYS_ACCT 7 -#define NFNL_SUBSYS_COUNT 8 +#define NFNL_SUBSYS_CTNETLINK_TIMEOUT 8 +#define NFNL_SUBSYS_CTHELPER 9 +#define NFNL_SUBSYS_NFTABLES 10 +#define NFNL_SUBSYS_NFT_COMPAT 11 +#define NFNL_SUBSYS_COUNT 12 -#ifdef __KERNEL__ +/* Reserved control nfnetlink messages */ +#define NFNL_MSG_BATCH_BEGIN NLMSG_MIN_TYPE +#define NFNL_MSG_BATCH_END NLMSG_MIN_TYPE+1 -#include -#include -#include - -struct nfnl_callback { - int (*call)(struct sock *nl, struct sk_buff *skb, - const struct nlmsghdr *nlh, - const struct nlattr * const cda[]); - int (*call_rcu)(struct sock *nl, struct sk_buff *skb, - const struct nlmsghdr *nlh, - const struct nlattr * const cda[]); - const struct nla_policy *policy; /* netlink attribute policy */ - const u_int16_t attr_count; /* number of nlattr's */ -}; - -struct nfnetlink_subsystem { - const char *name; - __u8 subsys_id; /* nfnetlink subsystem ID */ - __u8 cb_count; /* number of callbacks */ - const struct nfnl_callback *cb; /* callback for individual types */ -}; - -extern int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n); -extern int nfnetlink_subsys_unregister(const struct nfnetlink_subsystem *n); - -extern int nfnetlink_has_listeners(struct net *net, unsigned int group); -extern int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, - int echo, gfp_t flags); -extern int nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error); -extern int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u_int32_t pid, int flags); - -extern void nfnl_lock(void); -extern void nfnl_unlock(void); - -#define MODULE_ALIAS_NFNL_SUBSYS(subsys) \ - MODULE_ALIAS("nfnetlink-subsys-" __stringify(subsys)) - -#endif /* __KERNEL__ */ -#endif /* _NFNETLINK_H */ +#endif /* _NFNETLINK_H */ diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h index 0132bad..8dd819e 100644 --- a/include/linux/netfilter/nfnetlink_queue.h +++ b/include/linux/netfilter/nfnetlink_queue.h @@ -47,6 +47,8 @@ enum nfqnl_attr_type { NFQA_CAP_LEN, /* __u32 length of captured packet */ NFQA_SKB_INFO, /* __u32 skb meta information */ NFQA_EXP, /* nf_conntrack_netlink.h */ + NFQA_UID, /* __u32 sk uid */ + NFQA_GID, /* __u32 sk gid */ __NFQA_MAX }; @@ -99,7 +101,8 @@ enum nfqnl_attr_config { #define NFQA_CFG_F_FAIL_OPEN (1 << 0) #define NFQA_CFG_F_CONNTRACK (1 << 1) #define NFQA_CFG_F_GSO (1 << 2) -#define NFQA_CFG_F_MAX (1 << 3) +#define NFQA_CFG_F_UID_GID (1 << 3) +#define NFQA_CFG_F_MAX (1 << 4) /* flags for NFQA_SKB_INFO */ /* packet appears to have wrong checksums, but they are ok */ -- cgit v1.2.3 From 1c637fe7ea8a70a77273366d24e221b0d3d64702 Mon Sep 17 00:00:00 2001 From: Felix Janda Date: Sat, 16 May 2015 11:38:53 +0200 Subject: src: Use stdint types Signed-off-by: Felix Janda Signed-off-by: Pablo Neira Ayuso --- extensions/libct_proto_dccp.c | 2 +- extensions/libct_proto_gre.c | 2 +- extensions/libct_proto_icmp.c | 4 ++-- extensions/libct_proto_icmpv6.c | 4 ++-- extensions/libct_proto_sctp.c | 4 ++-- extensions/libct_proto_tcp.c | 2 +- extensions/libct_proto_udp.c | 2 +- extensions/libct_proto_udplite.c | 2 +- include/bitops.h | 14 +++++++------- include/helper.h | 2 +- src/filter.c | 4 ++-- src/helpers/amanda.c | 4 ++-- src/helpers/ftp.c | 2 +- src/helpers/ssdp.c | 2 +- src/internal_bypass.c | 4 ++-- src/sync-notrack.c | 2 +- 16 files changed, 28 insertions(+), 28 deletions(-) diff --git a/extensions/libct_proto_dccp.c b/extensions/libct_proto_dccp.c index f37ef68..f6258ad 100644 --- a/extensions/libct_proto_dccp.c +++ b/extensions/libct_proto_dccp.c @@ -118,7 +118,7 @@ static int parse_options(char c, unsigned int *flags) { int i; - u_int16_t port; + uint16_t port; switch(c) { case 1: diff --git a/extensions/libct_proto_gre.c b/extensions/libct_proto_gre.c index 0274a37..2dc63d1 100644 --- a/extensions/libct_proto_gre.c +++ b/extensions/libct_proto_gre.c @@ -91,7 +91,7 @@ static int parse_options(char c, unsigned int *flags) { switch(c) { - u_int16_t port; + uint16_t port; case '1': port = htons(strtoul(optarg, NULL, 0)); nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, port); diff --git a/extensions/libct_proto_icmp.c b/extensions/libct_proto_icmp.c index d04397f..2ce1c65 100644 --- a/extensions/libct_proto_icmp.c +++ b/extensions/libct_proto_icmp.c @@ -72,8 +72,8 @@ static int parse(char c, unsigned int *flags) { switch(c) { - u_int8_t tmp; - u_int16_t id; + uint8_t tmp; + uint16_t id; case '1': tmp = atoi(optarg); nfct_set_attr_u8(ct, ATTR_ICMP_TYPE, tmp); diff --git a/extensions/libct_proto_icmpv6.c b/extensions/libct_proto_icmpv6.c index f8c2c68..18dd3e5 100644 --- a/extensions/libct_proto_icmpv6.c +++ b/extensions/libct_proto_icmpv6.c @@ -75,8 +75,8 @@ static int parse(char c, unsigned int *flags) { switch(c) { - u_int8_t tmp; - u_int16_t id; + uint8_t tmp; + uint16_t id; case '1': tmp = atoi(optarg); nfct_set_attr_u8(ct, ATTR_ICMP_TYPE, tmp); diff --git a/extensions/libct_proto_sctp.c b/extensions/libct_proto_sctp.c index 97042c3..04828bf 100644 --- a/extensions/libct_proto_sctp.c +++ b/extensions/libct_proto_sctp.c @@ -120,8 +120,8 @@ parse_options(char c, struct nf_conntrack *ct, unsigned int *flags) { int i; - u_int16_t port; - u_int32_t vtag; + uint16_t port; + uint32_t vtag; switch(c) { case 1: diff --git a/extensions/libct_proto_tcp.c b/extensions/libct_proto_tcp.c index 65acd5a..8a37a55 100644 --- a/extensions/libct_proto_tcp.c +++ b/extensions/libct_proto_tcp.c @@ -106,7 +106,7 @@ static int parse_options(char c, unsigned int *flags) { int i; - u_int16_t port; + uint16_t port; switch(c) { case '1': diff --git a/extensions/libct_proto_udp.c b/extensions/libct_proto_udp.c index 768304b..e30637c 100644 --- a/extensions/libct_proto_udp.c +++ b/extensions/libct_proto_udp.c @@ -87,7 +87,7 @@ static int parse_options(char c, unsigned int *flags) { switch(c) { - u_int16_t port; + uint16_t port; case '1': port = htons(atoi(optarg)); nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, port); diff --git a/extensions/libct_proto_udplite.c b/extensions/libct_proto_udplite.c index 9b67bef..f46cef0 100644 --- a/extensions/libct_proto_udplite.c +++ b/extensions/libct_proto_udplite.c @@ -95,7 +95,7 @@ static int parse_options(char c, unsigned int *flags) { switch(c) { - u_int16_t port; + uint16_t port; case '1': port = htons(atoi(optarg)); nfct_set_attr_u16(ct, ATTR_ORIG_PORT_SRC, port); diff --git a/include/bitops.h b/include/bitops.h index 51f4289..27fe58d 100644 --- a/include/bitops.h +++ b/include/bitops.h @@ -1,34 +1,34 @@ #ifndef _BITOPS_H_ #define _BITOPS_H_ -#include +#include -static inline void set_bit_u32(int nr, u_int32_t *addr) +static inline void set_bit_u32(int nr, uint32_t *addr) { addr[nr >> 5] |= (1UL << (nr & 31)); } -static inline void unset_bit_u32(int nr, u_int32_t *addr) +static inline void unset_bit_u32(int nr, uint32_t *addr) { addr[nr >> 5] &= ~(1UL << (nr & 31)); } -static inline int test_bit_u32(int nr, const u_int32_t *addr) +static inline int test_bit_u32(int nr, const uint32_t *addr) { return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0; } -static inline void set_bit_u16(int nr, u_int16_t *addr) +static inline void set_bit_u16(int nr, uint16_t *addr) { addr[nr >> 4] |= (1UL << (nr & 15)); } -static inline void unset_bit_u16(int nr, u_int16_t *addr) +static inline void unset_bit_u16(int nr, uint16_t *addr) { addr[nr >> 4] &= ~(1UL << (nr & 15)); } -static inline int test_bit_u16(int nr, const u_int16_t *addr) +static inline int test_bit_u16(int nr, const uint16_t *addr) { return ((1UL << (nr & 15)) & (addr[nr >> 4])) != 0; } diff --git a/include/helper.h b/include/helper.h index bd69af6..f412e55 100644 --- a/include/helper.h +++ b/include/helper.h @@ -25,7 +25,7 @@ struct ctd_helper { int (*cb)(struct pkt_buff *pkt, uint32_t protoff, struct myct *ct, - u_int32_t ctinfo); + uint32_t ctinfo); struct ctd_helper_policy policy[CTD_HELPER_POLICY_MAX]; diff --git a/src/filter.c b/src/filter.c index 8fac71b..1ae2cc5 100644 --- a/src/filter.c +++ b/src/filter.c @@ -33,8 +33,8 @@ struct ct_filter { int logic[CT_FILTER_MAX]; - u_int32_t l4protomap[IPPROTO_MAX/32]; - u_int16_t statemap[IPPROTO_MAX]; + uint32_t l4protomap[IPPROTO_MAX/32]; + uint16_t statemap[IPPROTO_MAX]; struct hashtable *h; struct hashtable *h6; struct vector *v; diff --git a/src/helpers/amanda.c b/src/helpers/amanda.c index c0cf701..9e6c4e7 100644 --- a/src/helpers/amanda.c +++ b/src/helpers/amanda.c @@ -34,7 +34,7 @@ static int nat_amanda(struct pkt_buff *pkt, uint32_t ctinfo, struct nf_expect *exp) { char buffer[sizeof("65535")]; - u_int16_t port, initial_port; + uint16_t port, initial_port; unsigned int ret; const struct nf_conntrack *expected; struct nf_conntrack *nat_tuple; @@ -111,7 +111,7 @@ amanda_helper_cb(struct pkt_buff *pkt, uint32_t protoff, struct nf_expect *exp; char *data, *data_limit, *tmp; unsigned int dataoff, i; - u_int16_t port, len; + uint16_t port, len; int ret = NF_ACCEPT; struct iphdr *iph; union nfct_attr_grp_addr saddr, daddr; diff --git a/src/helpers/ftp.c b/src/helpers/ftp.c index 2c8dcd6..e7fe7f7 100644 --- a/src/helpers/ftp.c +++ b/src/helpers/ftp.c @@ -58,7 +58,7 @@ enum nf_ct_ftp_type { }; static int -get_ipv6_addr(const char *src, size_t dlen, struct in6_addr *dst, u_int8_t term) +get_ipv6_addr(const char *src, size_t dlen, struct in6_addr *dst, uint8_t term) { const char *end; int ret = in6_pton(src, min_t(size_t, dlen, 0xffff), diff --git a/src/helpers/ssdp.c b/src/helpers/ssdp.c index 2713f23..bc41087 100644 --- a/src/helpers/ssdp.c +++ b/src/helpers/ssdp.c @@ -44,7 +44,7 @@ static int ssdp_helper_cb(struct pkt_buff *pkt, uint32_t protoff, struct iphdr *net_hdr = (struct iphdr *)pktb_network_header(pkt); int good_packet = 0; struct nf_expect *exp; - u_int16_t port; + uint16_t port; unsigned int dataoff; void *sb_ptr; diff --git a/src/internal_bypass.c b/src/internal_bypass.c index ce2ae46..61988c7 100644 --- a/src/internal_bypass.c +++ b/src/internal_bypass.c @@ -49,7 +49,7 @@ internal_bypass_ct_dump_cb(enum nf_conntrack_msg_type type, static void internal_bypass_ct_dump(int fd, int type) { struct nfct_handle *h; - u_int32_t family = AF_UNSPEC; + uint32_t family = AF_UNSPEC; int ret; h = nfct_open(CONFIG(netlink).subsys_id, 0); @@ -180,7 +180,7 @@ internal_bypass_exp_dump_cb(enum nf_conntrack_msg_type type, static void internal_bypass_exp_dump(int fd, int type) { struct nfct_handle *h; - u_int32_t family = AF_UNSPEC; + uint32_t family = AF_UNSPEC; int ret; h = nfct_open(CONFIG(netlink).subsys_id, 0); diff --git a/src/sync-notrack.c b/src/sync-notrack.c index a7df4e7..c810bbb 100644 --- a/src/sync-notrack.c +++ b/src/sync-notrack.c @@ -99,7 +99,7 @@ static int kernel_resync_cb(enum nf_conntrack_msg_type type, static void kernel_resync(void) { struct nfct_handle *h; - u_int32_t family = AF_UNSPEC; + uint32_t family = AF_UNSPEC; int ret; h = nfct_open(CONFIG(netlink).subsys_id, 0); -- cgit v1.2.3 From 12a5c50a831176b7f95a3535fe42ecbcf332afb1 Mon Sep 17 00:00:00 2001 From: Felix Janda Date: Sat, 16 May 2015 11:50:25 +0200 Subject: src: Include for fd_set Signed-off-by: Felix Janda Signed-off-by: Pablo Neira Ayuso --- include/mcast.h | 1 + include/tcp.h | 1 + include/udp.h | 1 + 3 files changed, 3 insertions(+) diff --git a/include/mcast.h b/include/mcast.h index 402a033..f0225aa 100644 --- a/include/mcast.h +++ b/include/mcast.h @@ -4,6 +4,7 @@ #include #include #include +#include struct mcast_conf { int ipproto; diff --git a/include/tcp.h b/include/tcp.h index 2f0fd0a..068d43a 100644 --- a/include/tcp.h +++ b/include/tcp.h @@ -3,6 +3,7 @@ #include #include +#include struct tcp_conf { int ipproto; diff --git a/include/udp.h b/include/udp.h index 9f9c17a..53d713d 100644 --- a/include/udp.h +++ b/include/udp.h @@ -3,6 +3,7 @@ #include #include +#include struct udp_conf { int ipproto; -- cgit v1.2.3 From fe1f2d58add1e56e651c43de8cd60db8123d49bb Mon Sep 17 00:00:00 2001 From: Felix Janda Date: Sat, 16 May 2015 12:05:33 +0200 Subject: src: Define _GNU_SOURCE to get members of tcphdr&ucphdr The source uses linux names for members of tcphdr. For example "source" instead of "th_sport", ... musl libc's headers need _GNU_SOURCE defined in order to expose these. Signed-off-by: Felix Janda Signed-off-by: Pablo Neira Ayuso --- src/cthelper.c | 1 + src/helpers/ftp.c | 1 + src/helpers/sane.c | 1 + src/helpers/tns.c | 1 + 4 files changed, 4 insertions(+) diff --git a/src/cthelper.c b/src/cthelper.c index fec40fb..bd8b8b7 100644 --- a/src/cthelper.c +++ b/src/cthelper.c @@ -31,6 +31,7 @@ #include #include #include +#define _GNU_SOURCE #include #include #include diff --git a/src/helpers/ftp.c b/src/helpers/ftp.c index e7fe7f7..24ee877 100644 --- a/src/helpers/ftp.c +++ b/src/helpers/ftp.c @@ -25,6 +25,7 @@ #include /* for isdigit */ #include +#define _GNU_SOURCE #include #include diff --git a/src/helpers/sane.c b/src/helpers/sane.c index 79ca948..c30f4ba 100644 --- a/src/helpers/sane.c +++ b/src/helpers/sane.c @@ -30,6 +30,7 @@ #include "log.h" #include #include +#define _GNU_SOURCE #include #include #include diff --git a/src/helpers/tns.c b/src/helpers/tns.c index 5833fea..2b4fed4 100644 --- a/src/helpers/tns.c +++ b/src/helpers/tns.c @@ -18,6 +18,7 @@ #include /* for isdigit */ #include +#define _GNU_SOURCE #include #include -- cgit v1.2.3 From 28171b61622390f241101cbc4573c443ef9935aa Mon Sep 17 00:00:00 2001 From: Felix Janda Date: Sat, 16 May 2015 12:20:25 +0200 Subject: netlink: Use instead of legacy synonym Signed-off-by: Felix Janda Signed-off-by: Pablo Neira Ayuso --- src/netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/netlink.c b/src/netlink.c index 5be102e..189f55a 100644 --- a/src/netlink.c +++ b/src/netlink.c @@ -26,7 +26,7 @@ #include #include #include -#include +#include #include struct nfct_handle *nl_init_event_handler(void) -- cgit v1.2.3 From 796f592eec3b83b61397f726a4e652a005cae3c2 Mon Sep 17 00:00:00 2001 From: Chas Williams III Date: Wed, 20 May 2015 07:50:50 -0600 Subject: cthelper: don't pass up a 0 length queue If the user didn't specify a queue length in the configuration file it will have a length of 0. Allow the kernel's default to take precedence instead. Signed-off-by: Charles (Chas) Williams Signed-off-by: Pablo Neira Ayuso --- src/cthelper.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cthelper.c b/src/cthelper.c index bd8b8b7..15d5126 100644 --- a/src/cthelper.c +++ b/src/cthelper.c @@ -470,7 +470,10 @@ static int cthelper_nfqueue_setup(struct ctd_helper_instance *cur) nfq_nlmsg_cfg_put_params(nlh, NFQNL_COPY_PACKET, 0xffff); mnl_attr_put_u32(nlh, NFQA_CFG_FLAGS, htonl(NFQA_CFG_F_CONNTRACK)); mnl_attr_put_u32(nlh, NFQA_CFG_MASK, htonl(0xffffffff)); - mnl_attr_put_u32(nlh, NFQA_CFG_QUEUE_MAXLEN, htonl(cur->queue_len)); + if (cur->queue_len > 0) { + mnl_attr_put_u32(nlh, NFQA_CFG_QUEUE_MAXLEN, + htonl(cur->queue_len)); + } if (mnl_socket_sendto(STATE_CTH(nl), nlh, nlh->nlmsg_len) < 0) { dlog(LOG_ERR, "failed to send configuration"); -- cgit v1.2.3 From 9d53701f4b1d5db5773513d5f370ca4a89371c9a Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 29 May 2015 14:51:22 +0200 Subject: expect: Fix wrong memset usage memset fills bytes, not ulongs - so the second parameter (the fill value) has to be a byte. Reported-by: Paul Aitken Signed-off-by: Pablo Neira Ayuso --- src/expect.c | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/expect.c b/src/expect.c index bba0ed7..5add7be 100644 --- a/src/expect.c +++ b/src/expect.c @@ -39,8 +39,7 @@ cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master, if (saddr) { switch(nfct_get_attr_u8(master, ATTR_L3PROTO)) { - int i; - uint32_t addr[4] = {}; + uint32_t addr[4]; case AF_INET: nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); @@ -52,10 +51,7 @@ cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master, 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[i], 0xffffffff, sizeof(uint32_t)); - + memset(addr, 0xff, sizeof(addr)); nfct_set_attr_u8(mask, ATTR_L3PROTO, AF_INET6); nfct_set_attr(mask, ATTR_IPV6_SRC, addr); break; @@ -64,8 +60,7 @@ cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master, } } else { switch(nfct_get_attr_u8(master, ATTR_L3PROTO)) { - int i; - uint32_t addr[4] = {}; + uint32_t addr[4]; case AF_INET: nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); @@ -75,9 +70,7 @@ cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master, nfct_set_attr_u32(mask, ATTR_IPV4_SRC, 0x00000000); break; case AF_INET6: - for (i=0; i<4; i++) - memset(&addr[i], 0x00000000, sizeof(uint32_t)); - + memset(addr, 0x00, sizeof(addr)); nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET6); nfct_set_attr(expected, ATTR_IPV6_SRC, addr); @@ -116,8 +109,7 @@ cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master, } switch(nfct_get_attr_u8(master, ATTR_L3PROTO)) { - uint32_t addr[4] = {}; - int i; + uint32_t addr[4]; case AF_INET: nfct_set_attr_u8(expected, ATTR_L3PROTO, AF_INET); @@ -127,10 +119,7 @@ cthelper_expect_init(struct nf_expect *exp, struct nf_conntrack *master, 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)); - + memset(addr, 0xff, sizeof(addr)); nfct_set_attr(mask, ATTR_IPV6_DST, addr); break; default: -- cgit v1.2.3 From 6dcfe88a27318e313c1cb9130177a839926fe042 Mon Sep 17 00:00:00 2001 From: Paul Aitken Date: Thu, 4 Jun 2015 10:15:00 +0100 Subject: conntrackd: remove unused 'numbytes' 'numbytes' isn't used and can be removed. Signed-off-by: Paul Aitken Signed-off-by: Pablo Neira Ayuso --- src/local.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/local.c b/src/local.c index feff608..453799a 100644 --- a/src/local.c +++ b/src/local.c @@ -117,11 +117,10 @@ void local_client_destroy(int fd) int do_local_client_step(int fd, void (*process)(char *buf)) { - int numbytes; char buf[1024]; memset(buf, 0, sizeof(buf)); - while ((numbytes = recv(fd, buf, sizeof(buf)-1, 0)) > 0) { + while (recv(fd, buf, sizeof(buf)-1, 0) > 0) { buf[sizeof(buf)-1] = '\0'; if (process) process(buf); -- cgit v1.2.3 From 0d48c76df2736fc3ab9b17dd97fa456cf98ee9e6 Mon Sep 17 00:00:00 2001 From: Paul Aitken Date: Thu, 4 Jun 2015 10:15:00 +0100 Subject: cthelper: Optimise nfq_queue_cb ct and myct have both already been checked for non-NULL, so there's no need to check either of them again later. Signed-off-by: Paul Aitken Signed-off-by: Pablo Neira Ayuso --- src/cthelper.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/cthelper.c b/src/cthelper.c index 15d5126..6537515 100644 --- a/src/cthelper.c +++ b/src/cthelper.c @@ -325,14 +325,12 @@ static int nfq_queue_cb(const struct nlmsghdr *nlh, void *data) if (pkt_verdict_issue(helper, myct, queue_num, id, verdict, pktb) < 0) goto err_pktb; - if (ct != NULL) - nfct_destroy(ct); + nfct_destroy(ct); if (myct->exp != NULL) nfexp_destroy(myct->exp); - if (myct && myct->priv_data != NULL) + if (myct->priv_data != NULL) free(myct->priv_data); - if (myct != NULL) - free(myct); + free(myct); return MNL_CB_OK; err_pktb: -- cgit v1.2.3 From aa9fd4a1a4cf2e78521c427554f3339f78f7a82b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 26 Jun 2015 10:03:25 +0200 Subject: tests: conntrack: don't overwrite read-only shell variable Signed-off-by: Pablo Neira Ayuso --- tests/conntrack/run-test.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/conntrack/run-test.sh b/tests/conntrack/run-test.sh index 2b7b6f2..1403e2c 100644 --- a/tests/conntrack/run-test.sh +++ b/tests/conntrack/run-test.sh @@ -1,6 +1,5 @@ #!/bin/bash -UID=`id -u` if [ $UID -ne 0 ] then echo "Run this test as root" -- cgit v1.2.3 From d5fdfac4873061620546c2328c55f9c5830fd0f8 Mon Sep 17 00:00:00 2001 From: Szilárd Pfeiffer Date: Thu, 25 Jun 2015 12:22:10 +0200 Subject: conntrack: refactor handling of address options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Szilárd Pfeiffer Signed-off-by: Pablo Neira Ayuso --- src/conntrack.c | 69 ++++++++++++++++++++++++++------------------------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/src/conntrack.c b/src/conntrack.c index f6d7d9a..1bf5b2b 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -437,6 +437,10 @@ static const int opt2attr[] = { ['d'] = ATTR_ORIG_L3PROTO, ['r'] = ATTR_REPL_L3PROTO, ['q'] = ATTR_REPL_L3PROTO, + ['{'] = ATTR_ORIG_L3PROTO, + ['}'] = ATTR_ORIG_L3PROTO, + ['['] = ATTR_ORIG_L3PROTO, + [']'] = ATTR_ORIG_L3PROTO, ['m'] = ATTR_MARK, ['c'] = ATTR_SECMARK, ['i'] = ATTR_ID, @@ -1946,6 +1950,31 @@ static void merge_bitmasks(struct nfct_bitmask **current, nfct_bitmask_destroy(src); } +static void +nfct_set_addr_from_opt(int opt, struct nf_conntrack *ct, union ct_address *ad, + int *family) +{ + int l3protonum; + + options |= opt2type[opt]; + l3protonum = parse_addr(optarg, ad); + if (l3protonum == AF_UNSPEC) { + exit_error(PARAMETER_PROBLEM, + "Invalid IP address `%s'", optarg); + } + set_family(family, l3protonum); + if (l3protonum == AF_INET) { + nfct_set_attr_u32(ct, + opt2family_attr[opt][0], + ad->v4); + } else if (l3protonum == AF_INET6) { + nfct_set_attr(ct, + opt2family_attr[opt][1], + &ad->v6); + } + nfct_set_attr_u8(ct, opt2attr[opt], l3protonum); +} + int main(int argc, char *argv[]) { int c, cmd; @@ -1953,7 +1982,7 @@ int main(int argc, char *argv[]) int res = 0, partial; size_t socketbuffersize = 0; int family = AF_UNSPEC; - int l3protonum, protonum = 0; + int protonum = 0; union ct_address ad; unsigned int command = 0; @@ -2024,47 +2053,13 @@ int main(int argc, char *argv[]) case 'd': case 'r': case 'q': - options |= opt2type[c]; - - l3protonum = parse_addr(optarg, &ad); - if (l3protonum == AF_UNSPEC) { - exit_error(PARAMETER_PROBLEM, - "Invalid IP address `%s'", optarg); - } - set_family(&family, l3protonum); - if (l3protonum == AF_INET) { - nfct_set_attr_u32(tmpl.ct, - opt2family_attr[c][0], - ad.v4); - } else if (l3protonum == AF_INET6) { - nfct_set_attr(tmpl.ct, - opt2family_attr[c][1], - &ad.v6); - } - nfct_set_attr_u8(tmpl.ct, opt2attr[c], l3protonum); + nfct_set_addr_from_opt(c, tmpl.ct, &ad, &family); break; case '{': case '}': case '[': case ']': - options |= opt2type[c]; - l3protonum = parse_addr(optarg, &ad); - if (l3protonum == AF_UNSPEC) { - exit_error(PARAMETER_PROBLEM, - "Invalid IP address `%s'", optarg); - } - set_family(&family, l3protonum); - if (l3protonum == AF_INET) { - nfct_set_attr_u32(tmpl.mask, - opt2family_attr[c][0], - ad.v4); - } else if (l3protonum == AF_INET6) { - nfct_set_attr(tmpl.mask, - opt2family_attr[c][1], - &ad.v6); - } - nfct_set_attr_u8(tmpl.mask, - ATTR_ORIG_L3PROTO, l3protonum); + nfct_set_addr_from_opt(c, tmpl.mask, &ad, &family); break; case 'p': options |= CT_OPT_PROTO; -- cgit v1.2.3 From 3309fdb4413cb32f9b95e05064dc9dbb56550939 Mon Sep 17 00:00:00 2001 From: Szilárd Pfeiffer Date: Thu, 25 Jun 2015 12:22:11 +0200 Subject: conntrack: fix expectation entry creation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Szilárd Pfeiffer Signed-off-by: Pablo Neira Ayuso --- src/conntrack.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/conntrack.c b/src/conntrack.c index 1bf5b2b..67fcda0 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -2057,6 +2057,8 @@ int main(int argc, char *argv[]) break; case '{': case '}': + nfct_set_addr_from_opt(c, tmpl.exptuple, &ad, &family); + break; case '[': case ']': nfct_set_addr_from_opt(c, tmpl.mask, &ad, &family); -- cgit v1.2.3 From 900d7e80b8d8339622912c88f6faea96af4115d7 Mon Sep 17 00:00:00 2001 From: Szilárd Pfeiffer Date: Fri, 3 Jul 2015 01:04:58 +0200 Subject: conntrack: made the protocol option value case insensitive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extensions register protocols by lowercase protocol name, but value of proto command line option may be uppercase. Extension related options cannot be used when protocol name comparision fails. Signed-off-by: Szilárd Pfeiffer Signed-off-by: Florian Westphal --- src/conntrack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/conntrack.c b/src/conntrack.c index 67fcda0..00b09b6 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -551,7 +551,7 @@ static struct ctproto_handler *findproto(char *name, int *pnum) /* is it in the list of supported protocol? */ list_for_each_entry(cur, &proto_list, head) { - if (strcmp(cur->name, name) == 0) { + if (strcasecmp(cur->name, name) == 0) { *pnum = cur->protonum; return cur; } -- cgit v1.2.3 From 38a46caa55ffe1ffee662503ac8abb57522baaa3 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 18 Aug 2015 18:51:50 +0200 Subject: conntrackd: fix sanitization of expection attribute in the wire format The maximum number of attribute is NTA_EXP_MAX for expectation sync messages. Signed-off-by: Pablo Neira Ayuso --- src/parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse.c b/src/parse.c index f3ec6ac..878e354 100644 --- a/src/parse.c +++ b/src/parse.c @@ -510,7 +510,7 @@ int msg2exp(struct nf_expect *exp, struct nethdr *net, size_t remain) ATTR_NETWORK2HOST(attr); if (attr->nta_len > len) goto err; - if (attr->nta_attr > NTA_MAX) + if (attr->nta_attr >= NTA_EXP_MAX) goto err; if (attr->nta_len < NTA_LENGTH(0)) goto err; -- cgit v1.2.3 From cf2c6ea6cf1dd2753c431374284e148aba55f947 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 18 Aug 2015 18:53:49 +0200 Subject: conntrackd: NTA_MAX is also an invalid attribute Otherwise this can result in an off-by-one array access. Signed-off-by: Pablo Neira Ayuso --- src/parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/parse.c b/src/parse.c index 878e354..3ac4092 100644 --- a/src/parse.c +++ b/src/parse.c @@ -297,7 +297,7 @@ int msg2ct(struct nf_conntrack *ct, struct nethdr *net, size_t remain) return -1; if (attr->nta_len < NTA_LENGTH(0)) return -1; - if (attr->nta_attr > NTA_MAX) + if (attr->nta_attr >= NTA_MAX) return -1; if (h[attr->nta_attr].size && attr->nta_len != h[attr->nta_attr].size) -- cgit v1.2.3 From be691dc236610ab349c3bffb9a891613f75c6ebe Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 18 Aug 2015 18:56:51 +0200 Subject: conntrackd: fix leak in fork_process_new() Release the child_process structure in case that fork() fails. Signed-off-by: Pablo Neira Ayuso --- src/process.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/process.c b/src/process.c index 7f0a395..3ddad5f 100644 --- a/src/process.c +++ b/src/process.c @@ -48,6 +48,8 @@ int fork_process_new(int type, int flags, void (*cb)(void *data), void *data) if (c->pid > 0) list_add(&c->head, &process_list); + else + free(c); return pid; } -- cgit v1.2.3 From 99dc0ba1e12c40a1c69c6f831a78a06248b3e2a4 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 18 Aug 2015 18:59:18 +0200 Subject: conntrackd: fix descriptor leak in do_local_request() Signed-off-by: Pablo Neira Ayuso --- src/local.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/local.c b/src/local.c index 453799a..85e5180 100644 --- a/src/local.c +++ b/src/local.c @@ -147,11 +147,14 @@ int do_local_request(int request, ret = send(fd, &request, sizeof(int), 0); if (ret == -1) - return -1; + goto err1; do_local_client_step(fd, step); local_client_destroy(fd); - + return 0; +err1: + local_client_destroy(fd); + return -1; } -- cgit v1.2.3 From 097bb594e6844fe3edc1b01768a8ced37433378b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 18 Aug 2015 19:05:23 +0200 Subject: conntrackd: fix error handling in nfq_queue_cb() Make sure we have a clean exit on error, everything needs to be properly released. Signed-off-by: Pablo Neira Ayuso --- src/cthelper.c | 29 +++++++++++++++-------------- src/local.c | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/cthelper.c b/src/cthelper.c index 6537515..54eb830 100644 --- a/src/cthelper.c +++ b/src/cthelper.c @@ -277,11 +277,11 @@ static int nfq_queue_cb(const struct nlmsghdr *nlh, void *data) if (!attr[NFQA_PAYLOAD]) { dlog(LOG_ERR, "packet with no payload"); - goto err; + goto err1; } if (!attr[NFQA_CT] || !attr[NFQA_CT_INFO]) { dlog(LOG_ERR, "no CT attached to this packet"); - goto err; + goto err1; } pkt = mnl_attr_get_payload(attr[NFQA_PAYLOAD]); @@ -292,22 +292,22 @@ static int nfq_queue_cb(const struct nlmsghdr *nlh, void *data) queue_num = ntohs(nfg->res_id); if (pkt_get(pkt, pktlen, ntohs(ph->hw_protocol), &protoff)) - goto err; + goto err1; ct = nfct_new(); if (ct == NULL) - goto err; + goto err1; if (nfct_payload_parse(mnl_attr_get_payload(attr[NFQA_CT]), mnl_attr_get_payload_len(attr[NFQA_CT]), l3num, ct) < 0) { dlog(LOG_ERR, "cannot convert message to CT"); - goto err; + goto err2; } myct = calloc(1, sizeof(struct myct)); if (myct == NULL) - goto err; + goto err2; myct->ct = ct; ctinfo = ntohl(mnl_attr_get_u32(attr[NFQA_CT_INFO])); @@ -315,15 +315,15 @@ static int nfq_queue_cb(const struct nlmsghdr *nlh, void *data) /* XXX: 256 bytes enough for possible NAT mangling in helpers? */ pktb = pktb_alloc(AF_INET, pkt, pktlen, 256); if (pktb == NULL) - goto err; + goto err3; /* Misconfiguration: if no helper found, accept the packet. */ helper = helper_run(pktb, protoff, myct, ctinfo, queue_num, &verdict); if (!helper) - goto err_pktb; + goto err4; if (pkt_verdict_issue(helper, myct, queue_num, id, verdict, pktb) < 0) - goto err_pktb; + goto err4; nfct_destroy(ct); if (myct->exp != NULL) @@ -333,18 +333,19 @@ static int nfq_queue_cb(const struct nlmsghdr *nlh, void *data) free(myct); return MNL_CB_OK; -err_pktb: +err4: pktb_free(pktb); -err: +err3: + free(myct); +err2: + nfct_destroy(ct); +err1: /* In case of error, we don't want to disrupt traffic. We accept all. * This is connection tracking after all. The policy is not to drop * packet unless we enter some inconsistent state. */ pkt_verdict_error(queue_num, id); - if (ct != NULL) - nfct_destroy(ct); - return MNL_CB_OK; } diff --git a/src/local.c b/src/local.c index 85e5180..3395b4c 100644 --- a/src/local.c +++ b/src/local.c @@ -77,7 +77,7 @@ int do_local_server_step(struct local_server *server, void *data, int rfd; struct sockaddr_un local; socklen_t sin_size = sizeof(struct sockaddr_un); - + rfd = accept(server->fd, (struct sockaddr *) &local, &sin_size); if (rfd == -1) return -1; -- cgit v1.2.3 From 743e4948eb3bdbdb3a7751c54f2c715ba829afd2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 18 Aug 2015 19:08:37 +0200 Subject: conntrackd: simplify branch in tcp_accept() The same code is executed regardless the reason why accept() has failed. Signed-off-by: Pablo Neira Ayuso --- src/tcp.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/tcp.c b/src/tcp.c index af27c46..c8f2544 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -247,13 +247,11 @@ int tcp_accept(struct tcp_sock *m) /* the other peer wants to connect ... */ ret = accept(m->fd, NULL, NULL); if (ret == -1) { - if (errno != EAGAIN) { - /* unexpected error. Give us another try. */ - m->state = TCP_SERVER_ACCEPTING; - } else { - /* waiting for new connections. */ - m->state = TCP_SERVER_ACCEPTING; - } + /* unexpected error: Give us another try. Or we have hit + * -EAGAIN, in that case we remain in the accepting connections + * state. + */ + m->state = TCP_SERVER_ACCEPTING; } else { /* the peer finally got connected. */ if (fcntl(ret, F_SETFL, O_NONBLOCK) == -1) { -- cgit v1.2.3 From 09d14955e436b144bc69b998c172b3ea47683195 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 18 Aug 2015 19:11:42 +0200 Subject: conntrackd: use strncpy to set up the cache name This is not exposed, but use the strncpy() variant to calm down static code validators. Signed-off-by: Pablo Neira Ayuso --- src/cache.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/cache.c b/src/cache.c index 7c41e54..79a024f 100644 --- a/src/cache.c +++ b/src/cache.c @@ -34,7 +34,7 @@ struct cache_feature *cache_feature[CACHE_MAX_FEATURE] = { }; struct cache *cache_create(const char *name, enum cache_type type, - unsigned int features, + unsigned int features, struct cache_extra *extra, struct cache_ops *ops) { @@ -53,7 +53,8 @@ struct cache *cache_create(const char *name, enum cache_type type, return NULL; memset(c, 0, sizeof(struct cache)); - strcpy(c->name, name); + strncpy(c->name, name, CACHE_MAX_NAMELEN); + c->name[CACHE_MAX_NAMELEN - 1] = '\0'; c->type = type; for (i = 0; i < CACHE_MAX_FEATURE; i++) { -- cgit v1.2.3 From 4134f1dafcc981757c40177bb3c5a3a7a144ff30 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 18 Aug 2015 19:16:26 +0200 Subject: conntrackd: missing break in expectation message parser function Fortunately, the TLVs come in order in the message, however, if the order is changed we'll incorrectly set up the expectation. Signed-off-by: Pablo Neira Ayuso --- src/parse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/parse.c b/src/parse.c index 3ac4092..919d36c 100644 --- a/src/parse.c +++ b/src/parse.c @@ -524,13 +524,15 @@ int msg2exp(struct nf_expect *exp, struct nethdr *net, size_t remain) attr = NTA_NEXT(attr, len); continue; } - switch(exp_h[attr->nta_attr].exp_attr) { + switch (exp_h[attr->nta_attr].exp_attr) { case ATTR_EXP_MASTER: exp_h[attr->nta_attr].parse(master, attr->nta_attr, NTA_DATA(attr)); + break; case ATTR_EXP_EXPECTED: exp_h[attr->nta_attr].parse(expected, attr->nta_attr, NTA_DATA(attr)); + break; case ATTR_EXP_MASK: exp_h[attr->nta_attr].parse(mask, attr->nta_attr, NTA_DATA(attr)); -- cgit v1.2.3 From 16363ecdc6d0ecfb13702bd1b2b176c96e78b1bb Mon Sep 17 00:00:00 2001 From: Arturo Borrero Gonzalez Date: Thu, 20 Aug 2015 12:45:20 +0200 Subject: list: fix prefetch dummy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [...] CC conntrack.o In file included from ../include/conntrack.h:4:0, from conntrack.c:41: conntrack.c: In function ‘findproto’: ../include/linux_list.h:385:59: warning: right-hand operand of comma expression has no effect [-Wunused-value] for (pos = list_entry((head)->next, typeof(*pos), member), \ ^ [...] The original patch is from Patrick McHardy . Signed-off-by: Arturo Borrero Gonzalez Signed-off-by: Pablo Neira Ayuso --- include/linux_list.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux_list.h b/include/linux_list.h index de182a4..efffb91 100644 --- a/include/linux_list.h +++ b/include/linux_list.h @@ -29,7 +29,7 @@ 1; \ }) -#define prefetch(x) 1 +#define prefetch(x) ((void)0) /* empty define to make this work in userspace -HW */ #ifndef smp_wmb -- cgit v1.2.3 From a8f74d021676096eaa40af72e6d91787408fe44d Mon Sep 17 00:00:00 2001 From: Arturo Borrero Gonzalez Date: Thu, 20 Aug 2015 13:56:42 +0200 Subject: doc/debian.conntrackd.init.d: drop file This file is likely dead code. It's outdated. Also I think distributors should manage themselves to integrate daemons in their operating systems. Following this idea, this file doesn't belong here. Signed-off-by: Arturo Borrero Gonzalez Signed-off-by: Pablo Neira Ayuso --- doc/debian.conntrackd.init.d | 48 -------------------------------------------- 1 file changed, 48 deletions(-) delete mode 100644 doc/debian.conntrackd.init.d diff --git a/doc/debian.conntrackd.init.d b/doc/debian.conntrackd.init.d deleted file mode 100644 index ba847dd..0000000 --- a/doc/debian.conntrackd.init.d +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/sh -# -# /etc/init.d/conntrackd -# -# Maximilian Wilhelm -# -- Mon, 06 Nov 2006 18:39:07 +0100 -# - -export PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin - -NAME="conntrackd" -DAEMON=`command -v conntrackd` -CONFIG="/etc/conntrack/conntrackd.conf" -PIDFILE="/var/run/${NAME}.pid" - - -# Gracefully exit if there is no daemon (debian way of life) -if [ ! -x "${DAEMON}" ]; then - exit 0 -fi - -# Check for config file -if [ ! -f /etc/conntrackd/conntrackd.conf ]; then - echo "Error: There is no config file for $NAME" >&2 - exit 1; -fi - -case "$1" in - start) - echo -n "Starting $NAME: " - start-stop-daemon --start --quiet --make-pidfile --pidfile "/var/run/${NAME}.pid" --background --exec "${DAEMON}" && echo "done." || echo "FAILED!" - ;; - stop) - echo -n "Stopping $NAME:" - start-stop-daemon --stop --quiet --oknodo --pidfile "/var/run/${NAME}.pid" && echo "done." || echo "FAILED!" - ;; - - restart) - $0 start - $0 stop - ;; - - *) - echo "Usage: /etc/init.d/conntrackd {start|stop|restart}" - exit 1 -esac - -exit 0 -- cgit v1.2.3 From 6ea080984022c6ece3e465d81b7b0b0f9709d356 Mon Sep 17 00:00:00 2001 From: Arturo Borrero Date: Thu, 20 Aug 2015 13:38:42 +0200 Subject: nfct: don't link against libnetfilter_conntrack The nfct program uses none of the symbols of libnetfilter_conntrack. Linking against it means that distributors have to maintain an useless depedency. This was spotted by the dpkg-shlibdeps tool. Signed-off-by: Arturo Borrero Gonzalez Signed-off-by: Pablo Neira Ayuso --- src/Makefile.am | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 1bc3622..a1d00f8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -25,7 +25,6 @@ nfct_SOURCES += nfct-extensions/timeout.c endif nfct_LDADD = ${LIBMNL_LIBS} \ - ${LIBNETFILTER_CONNTRACK_LIBS} \ ${libdl_LIBS} if HAVE_CTTIMEOUT -- cgit v1.2.3 From 1c36d487cda8d1bed799b4daa28c44aa7198bb31 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 21 Aug 2015 20:05:05 +0200 Subject: tests: fix run-test.sh This reports: run-test.sh: line 3: UID: read-only variable rename it to _UID. Signed-off-by: Pablo Neira Ayuso --- tests/nfct/run-test.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/nfct/run-test.sh b/tests/nfct/run-test.sh index 9bcad0d..851ee75 100644 --- a/tests/nfct/run-test.sh +++ b/tests/nfct/run-test.sh @@ -1,7 +1,7 @@ #!/bin/bash -UID=`id -u` -if [ $UID -ne 0 ] +_UID=`id -u` +if [ $_UID -ne 0 ] then echo "Run this test as root" exit 1 -- cgit v1.2.3 From dd73ceecdbe87b6ecf9e96643cd5326e520d7a1c Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 21 Aug 2015 19:18:38 +0200 Subject: nfct: Update syntax to specify command before subsystem This patch gets the nfct syntax in sync with nft so it looks like this: nfct object ... instead of: nfct object ... This patch retains backward compatibility so you can still use the old syntax. The manpage and tests have been also updated to promote the adoption of this syntax. We should have little existing clients of this tool as we can only use this to configure the cttimeout and cthelper infrastructures. Signed-off-by: Pablo Neira Ayuso --- include/nfct.h | 4 +- nfct.8 | 36 +++++++++------- src/nfct-extensions/helper.c | 46 ++++++++++---------- src/nfct-extensions/timeout.c | 53 ++++++++++------------- src/nfct.c | 97 +++++++++++++++++++++++++++++++++++-------- tests/nfct/test-live.sh | 14 +++---- tests/nfct/timeout/00tcp | 16 +++---- tests/nfct/timeout/01udp | 16 +++---- tests/nfct/timeout/02generic | 16 +++---- tests/nfct/timeout/03udplite | 16 +++---- tests/nfct/timeout/04icmp | 16 +++---- tests/nfct/timeout/05icmpv6 | 16 +++---- tests/nfct/timeout/06sctp | 16 +++---- tests/nfct/timeout/07dccp | 16 +++---- tests/nfct/timeout/08gre | 16 +++---- 15 files changed, 225 insertions(+), 169 deletions(-) diff --git a/include/nfct.h b/include/nfct.h index dc103c6..bfffdd6 100644 --- a/include/nfct.h +++ b/include/nfct.h @@ -9,6 +9,7 @@ enum { NFCT_SUBSYS_HELPER, NFCT_SUBSYS_VERSION, NFCT_SUBSYS_HELP, + NFCT_SUBSYS_MAX }; enum { @@ -21,6 +22,7 @@ enum { NFCT_CMD_DISABLE, NFCT_CMD_DEFAULT_SET, NFCT_CMD_DEFAULT_GET, + NFCT_CMD_MAX, }; #define __init __attribute__((constructor)) @@ -30,7 +32,7 @@ void nfct_perror(const char *msg); struct nfct_extension { struct list_head head; int type; - int (*parse_params)(struct mnl_socket *nl, int argc, char *argv[]); + int (*parse_params)(struct mnl_socket *nl, int argc, char *argv[], int cmd); }; void nfct_extension_register(struct nfct_extension *ext); diff --git a/nfct.8 b/nfct.8 index 6f5190a..863fe12 100644 --- a/nfct.8 +++ b/nfct.8 @@ -3,12 +3,26 @@ .\" Man page written by Pablo Neira Ayuso (Feb 2012) .SH NAME -nfct \- command line tool to interact with the connection tracking system +nfct \- command line tool to configure with the connection tracking system .SH SYNOPSIS -.BR "nfct subsystem command [parameters]" +.BR "nfct command subsystem [parameters]" .SH DESCRIPTION .B nfct -is the command line tool that allows you Netfilter's manipulate Connection Tracking System. +is the command line tool that allows to configure the Connection Tracking +System. +.SH COMMANDS +.TP +.BI "list " +List the existing objects. +.TP +.BI "add " +Add new object. +.TP +.BI "delete " +Delete an object. +.TP +.BI "get " +Get an existing object. .SH SUBSYS By the time this manpage has been written, the supported subsystem are .B timeout @@ -16,24 +30,14 @@ By the time this manpage has been written, the supported subsystem are .BI "timeout " The timeout subsystem allows you to define fine-grain timeout policies. .TP +.BI "helper " +The helper subsystem allows you to configure userspace helpers. +.TP .BI "version " Displays the version information. .TP .BI "help " Displays the help message. -.SH TIMEOUT SUBSYSTEM -.TP -.BI "list " -List the existing timeout policies. -.TP -.BI "add " -Add new timeout policy. -.TP -.BI "delete " -Delete timeout policy. -.TP -.BI "get " -Get existing timeout policy. .SH EXAMPLE .TP .B nfct timeout add test-tcp inet tcp established 100 close 10 close_wait 10 diff --git a/src/nfct-extensions/helper.c b/src/nfct-extensions/helper.c index bfb153f..dfc55e7 100644 --- a/src/nfct-extensions/helper.c +++ b/src/nfct-extensions/helper.c @@ -45,36 +45,31 @@ static int nfct_cmd_helper_flush(struct mnl_socket *nl, int argc, char *argv[]); static int nfct_cmd_helper_disable(struct mnl_socket *nl, int argc, char *argv[]); static int -nfct_cmd_helper_parse_params(struct mnl_socket *nl, int argc, char *argv[]) +nfct_helper_parse_params(struct mnl_socket *nl, int argc, char *argv[], int cmd) { - int cmd = NFCT_CMD_NONE, ret = 0; + int ret; if (argc < 3) { - fprintf(stderr, "nfct v%s: Missing command\n" - "%s helper list|add|delete|get|flush " - "[parameters...]\n", VERSION, argv[0]); - exit(EXIT_FAILURE); + nfct_cmd_helper_usage(argv); + return -1; } - if (strncmp(argv[2], "list", strlen(argv[2])) == 0) - cmd = NFCT_CMD_LIST; - else if (strncmp(argv[2], "add", strlen(argv[2])) == 0) - cmd = NFCT_CMD_ADD; - else if (strncmp(argv[2], "delete", strlen(argv[2])) == 0) - cmd = NFCT_CMD_DELETE; - else if (strncmp(argv[2], "get", strlen(argv[2])) == 0) - cmd = NFCT_CMD_GET; - else if (strncmp(argv[2], "flush", strlen(argv[2])) == 0) - cmd = NFCT_CMD_FLUSH; - else if (strncmp(argv[2], "disable", strlen(argv[2])) == 0) - cmd = NFCT_CMD_DISABLE; - else { + + switch (cmd) { + case NFCT_CMD_LIST: + case NFCT_CMD_ADD: + case NFCT_CMD_DELETE: + case NFCT_CMD_GET: + case NFCT_CMD_FLUSH: + case NFCT_CMD_DISABLE: + break; + default: fprintf(stderr, "nfct v%s: Unknown command: %s\n", VERSION, argv[2]); nfct_cmd_helper_usage(argv); exit(EXIT_FAILURE); } - switch(cmd) { + switch (cmd) { case NFCT_CMD_LIST: ret = nfct_cmd_helper_list(nl, argc, argv); break; @@ -93,6 +88,9 @@ nfct_cmd_helper_parse_params(struct mnl_socket *nl, int argc, char *argv[]) case NFCT_CMD_DISABLE: ret = nfct_cmd_helper_disable(nl, argc, argv); break; + default: + nfct_cmd_helper_usage(argv); + return -1; } return ret; @@ -160,8 +158,7 @@ static int nfct_cmd_helper_add(struct mnl_socket *nl, int argc, char *argv[]) if (argc < 6) { nfct_perror("missing parameters\n" - "syntax: nfct helper add name " - "family protocol"); + "syntax: nfct add helper name family protocol"); return -1; } @@ -411,8 +408,7 @@ nfct_cmd_helper_disable(struct mnl_socket *nl, int argc, char *argv[]) if (argc < 6) { nfct_perror("missing parameters\n" - "syntax: nfct helper add name " - "family protocol"); + "syntax: nfct add helper name family protocol"); return -1; } @@ -469,7 +465,7 @@ nfct_cmd_helper_disable(struct mnl_socket *nl, int argc, char *argv[]) static struct nfct_extension helper = { .type = NFCT_SUBSYS_HELPER, - .parse_params = nfct_cmd_helper_parse_params, + .parse_params = nfct_helper_parse_params, }; static void __init helper_init(void) diff --git a/src/nfct-extensions/timeout.c b/src/nfct-extensions/timeout.c index c9aa386..1cb04a1 100644 --- a/src/nfct-extensions/timeout.c +++ b/src/nfct-extensions/timeout.c @@ -32,7 +32,7 @@ static void nfct_cmd_timeout_usage(char *argv[]) { fprintf(stderr, "nfct v%s: Missing command\n" - "%s timeout " + "%s timeout " "[, ...]\n", VERSION, argv[0]); } @@ -45,35 +45,30 @@ static int nfct_cmd_timeout_default_set(struct mnl_socket *nl, int argc, char *a static int nfct_cmd_timeout_default_get(struct mnl_socket *nl, int argc, char *argv[]); static int -nfct_cmd_timeout_parse_params(struct mnl_socket *nl, int argc, char *argv[]) +nfct_timeout_parse_params(struct mnl_socket *nl, int argc, char *argv[], int cmd) { - int cmd = NFCT_CMD_NONE, ret; + int ret; if (argc < 3) { nfct_cmd_timeout_usage(argv); return -1; } - if (strncmp(argv[2], "list", strlen(argv[2])) == 0) - cmd = NFCT_CMD_LIST; - else if (strncmp(argv[2], "add", strlen(argv[2])) == 0) - cmd = NFCT_CMD_ADD; - else if (strncmp(argv[2], "delete", strlen(argv[2])) == 0) - cmd = NFCT_CMD_DELETE; - else if (strncmp(argv[2], "get", strlen(argv[2])) == 0) - cmd = NFCT_CMD_GET; - else if (strncmp(argv[2], "flush", strlen(argv[2])) == 0) - cmd = NFCT_CMD_FLUSH; - else if (strncmp(argv[2], "default-set", strlen(argv[2])) == 0) - cmd = NFCT_CMD_DEFAULT_SET; - else if (strncmp(argv[2], "default-get", strlen(argv[2])) == 0) - cmd = NFCT_CMD_DEFAULT_GET; - else { - fprintf(stderr, "nfct v%s: Unknown command: %s\n", - VERSION, argv[2]); + + switch (cmd) { + case NFCT_CMD_LIST: + case NFCT_CMD_ADD: + case NFCT_CMD_DELETE: + case NFCT_CMD_GET: + case NFCT_CMD_FLUSH: + case NFCT_CMD_DEFAULT_SET: + case NFCT_CMD_DEFAULT_GET: + break; + default: nfct_cmd_timeout_usage(argv); return -1; } - switch(cmd) { + + switch (cmd) { case NFCT_CMD_LIST: ret = nfct_cmd_timeout_list(nl, argc, argv); break; @@ -95,6 +90,9 @@ nfct_cmd_timeout_parse_params(struct mnl_socket *nl, int argc, char *argv[]) case NFCT_CMD_DEFAULT_GET: ret = nfct_cmd_timeout_default_get(nl, argc, argv); break; + default: + nfct_cmd_timeout_usage(argv); + return -1; } return ret; @@ -270,9 +268,7 @@ int nfct_cmd_timeout_add(struct mnl_socket *nl, int argc, char *argv[]) if (argc < 6) { nfct_perror("missing parameters\n" - "syntax: nfct timeout add name " - "family protocol state1 " - "timeout1 state2 timeout2..."); + "syntax: nfct add timeout name family protocol state1 timeout1 ..."); return -1; } @@ -415,9 +411,7 @@ nfct_cmd_timeout_default_set(struct mnl_socket *nl, int argc, char *argv[]) if (argc < 6) { nfct_perror("missing parameters\n" - "syntax: nfct timeout default-set " - "family protocol state1 " - "timeout1 state2 timeout2..."); + "syntax: nfct default-set timeout family protocol state1 timeout1..."); return -1; } @@ -454,8 +448,7 @@ nfct_cmd_timeout_default_get(struct mnl_socket *nl, int argc, char *argv[]) if (argc < 5) { nfct_perror("missing parameters\n" - "syntax: nfct timeout default-get " - "family protocol"); + "syntax: nfct default-get timeout family protocol"); return -1; } @@ -497,7 +490,7 @@ nfct_cmd_timeout_default_get(struct mnl_socket *nl, int argc, char *argv[]) static struct nfct_extension timeout = { .type = NFCT_SUBSYS_TIMEOUT, - .parse_params = nfct_cmd_timeout_parse_params, + .parse_params = nfct_timeout_parse_params, }; static void __init timeout_init(void) diff --git a/src/nfct.c b/src/nfct.c index 533d75d..3331e5b 100644 --- a/src/nfct.c +++ b/src/nfct.c @@ -31,7 +31,7 @@ static int nfct_cmd_help(int argc, char *argv[]); static void usage(char *argv[]) { - fprintf(stderr, "Usage: %s subsystem command [parameters]...\n", + fprintf(stderr, "Usage: %s command subsystem [parameters]...\n", argv[0]); } @@ -63,32 +63,93 @@ static struct nfct_extension *nfct_extension_lookup(int type) return NULL; } +static const char *nfct_cmd_array[NFCT_CMD_MAX] = { + [NFCT_CMD_LIST] = "list", + [NFCT_CMD_ADD] = "add", + [NFCT_CMD_DELETE] = "delete", + [NFCT_CMD_GET] = "get", + [NFCT_CMD_FLUSH] = "flush", + [NFCT_CMD_DISABLE] = "disable", + [NFCT_CMD_DEFAULT_SET] = "default-set", + [NFCT_CMD_DEFAULT_GET] = "default-get", +}; + +static int nfct_cmd_parse(const char *cmdstr) +{ + int i; + + for (i = 1; i < NFCT_CMD_MAX; i++) { + if (strncmp(nfct_cmd_array[i], cmdstr, strlen(cmdstr)) == 0) + return i; + } + return -1; +} + +static int nfct_cmd_error(char *argv[]) +{ + fprintf(stderr, "nfct v%s: Unknown command: %s\n", VERSION, argv[1]); + usage(argv); + + return EXIT_FAILURE; +} + +static const char *nfct_subsys_array[NFCT_SUBSYS_MAX] = { + [NFCT_SUBSYS_TIMEOUT] = "timeout", + [NFCT_SUBSYS_HELPER] = "helper", + [NFCT_SUBSYS_VERSION] = "version", + [NFCT_SUBSYS_HELP] = "help", +}; + +static int nfct_subsys_parse(const char *cmdstr) +{ + int i; + + for (i = 1; i < NFCT_SUBSYS_MAX; i++) { + if (strncmp(nfct_subsys_array[i], cmdstr, strlen(cmdstr)) == 0) + return i; + } + return -1; +} + +static int nfct_subsys_error(char *argv[]) +{ + fprintf(stderr, "nfct v%s: Unknown subsystem: %s\n", VERSION, argv[1]); + usage(argv); + + return EXIT_FAILURE; +} + int main(int argc, char *argv[]) { - int subsys = NFCT_SUBSYS_NONE, ret = 0; + int subsys, cmd, ret = 0; struct nfct_extension *ext; struct mnl_socket *nl; - if (argc < 2) { + if (argc < 3) { usage(argv); exit(EXIT_FAILURE); } - if (strncmp(argv[1], "timeout", strlen(argv[1])) == 0) { - subsys = NFCT_SUBSYS_TIMEOUT; - } else if (strncmp(argv[1], "helper", strlen(argv[1])) == 0) { - subsys = NFCT_SUBSYS_HELPER; - } else if (strncmp(argv[1], "version", strlen(argv[1])) == 0) - subsys = NFCT_SUBSYS_VERSION; - else if (strncmp(argv[1], "help", strlen(argv[1])) == 0) - subsys = NFCT_SUBSYS_HELP; - else { - fprintf(stderr, "nfct v%s: Unknown subsystem: %s\n", - VERSION, argv[1]); - usage(argv); - exit(EXIT_FAILURE); + + cmd = nfct_cmd_parse(argv[1]); + if (cmd < 0) { + /* Workaround not to break backward compatibility and to get + * the syntax in sync with nft. Old nfct versions allow to + * specify the subsystem before the command. + */ + subsys = nfct_subsys_parse(argv[1]); + if (subsys < 0) + return nfct_subsys_error(argv); + + cmd = nfct_cmd_parse(argv[2]); + if (cmd < 0) + return nfct_cmd_error(argv); + } else { + subsys = nfct_subsys_parse(argv[2]); + if (subsys < 0) + return nfct_subsys_error(argv); } - switch(subsys) { + switch (subsys) { case NFCT_SUBSYS_VERSION: ret = nfct_cmd_version(argc, argv); break; @@ -109,7 +170,7 @@ int main(int argc, char *argv[]) return -1; } - ret = ext->parse_params(nl, argc, argv); + ret = ext->parse_params(nl, argc, argv, cmd); mnl_socket_close(nl); break; } diff --git a/tests/nfct/test-live.sh b/tests/nfct/test-live.sh index c338e63..2257087 100644 --- a/tests/nfct/test-live.sh +++ b/tests/nfct/test-live.sh @@ -6,7 +6,7 @@ WAIT_BETWEEN_TESTS=10 # flush cttimeout table -nfct timeout flush +nfct flush timeout # flush the conntrack table conntrack -F @@ -19,7 +19,7 @@ echo "---- test no. 1 ----" conntrack -E -p 13 & -nfct timeout add test-generic inet generic timeout 100 +nfct add timeout test-generic inet generic timeout 100 iptables -I OUTPUT -t raw -p all -j CT --timeout test-generic hping3 -c 1 -V -I eth0 -0 8.8.8.8 -H 13 @@ -30,7 +30,7 @@ echo "---- end test no. 1 ----" sleep $WAIT_BETWEEN_TESTS iptables -D OUTPUT -t raw -p all -j CT --timeout test-generic -nfct timeout del test-generic +nfct del timeout test-generic # # No.2: test TCP timeout policy @@ -40,14 +40,14 @@ echo "---- test no. 2 ----" conntrack -E -p tcp & -nfct timeout add test-tcp inet tcp syn_sent 100 +nfct add timeout test-tcp inet tcp syn_sent 100 iptables -I OUTPUT -t raw -p tcp -j CT --timeout test-tcp hping3 -V -S -p 80 -s 5050 8.8.8.8 -c 1 sleep $WAIT_BETWEEN_TESTS iptables -D OUTPUT -t raw -p tcp -j CT --timeout test-tcp -nfct timeout del test-tcp +nfct del timeout test-tcp killall -15 conntrack @@ -61,12 +61,12 @@ echo "---- test no. 3 ----" conntrack -E -p icmp & -nfct timeout add test-icmp inet icmp timeout 50 +nfct add timeout test-icmp inet icmp timeout 50 iptables -I OUTPUT -t raw -p icmp -j CT --timeout test-icmp hping3 -1 8.8.8.8 -c 2 iptables -D OUTPUT -t raw -p icmp -j CT --timeout test-icmp -nfct timeout del test-icmp +nfct del timeout test-icmp killall -15 conntrack diff --git a/tests/nfct/timeout/00tcp b/tests/nfct/timeout/00tcp index c9d7d24..ab2e6fc 100644 --- a/tests/nfct/timeout/00tcp +++ b/tests/nfct/timeout/00tcp @@ -1,16 +1,16 @@ # add policy object `test' -nfct timeout add test inet tcp established 100 ; OK +nfct add timeout test inet tcp established 100 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK # get unexistent policy object `dummy' -nfct timeout get test ; BAD +nfct get timeout test ; BAD # delete policy object `test', however, it does not exists anymore -nfct timeout delete test ; BAD +nfct delete timeout test ; BAD # add policy object `test' -nfct timeout add test inet tcp syn_sent 1 syn_recv 2 established 3 fin_wait 4 close_wait 5 last_ack 6 time_wait 7 close 8 syn_sent2 9 retrans 10 unacknowledged 11 ; OK +nfct add timeout test inet tcp syn_sent 1 syn_recv 2 established 3 fin_wait 4 close_wait 5 last_ack 6 time_wait 7 close 8 syn_sent2 9 retrans 10 unacknowledged 11 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK diff --git a/tests/nfct/timeout/01udp b/tests/nfct/timeout/01udp index 952526c..f8097d6 100644 --- a/tests/nfct/timeout/01udp +++ b/tests/nfct/timeout/01udp @@ -1,16 +1,16 @@ # add policy object `test' -nfct timeout add test inet udp unreplied 10 ; OK +nfct add timeout test inet udp unreplied 10 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK # get unexistent policy object `dummy' -nfct timeout get test ; BAD +nfct get timeout test ; BAD # delete policy object `test', however, it does not exists anymore -nfct timeout delete test ; BAD +nfct delete timeout test ; BAD # add policy object `test' -nfct timeout add test inet udp unreplied 1 replied 2 ; OK +nfct add timeout test inet udp unreplied 1 replied 2 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK diff --git a/tests/nfct/timeout/02generic b/tests/nfct/timeout/02generic index b6ca699..ffba138 100644 --- a/tests/nfct/timeout/02generic +++ b/tests/nfct/timeout/02generic @@ -1,16 +1,16 @@ # add policy object `test' -nfct timeout add test inet generic timeout 10 ; OK +nfct add timeout test inet generic timeout 10 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK # get unexistent policy object `dummy' -nfct timeout get test ; BAD +nfct get timeout test ; BAD # delete policy object `test', however, it does not exists anymore -nfct timeout delete test ; BAD +nfct delete timeout test ; BAD # add policy object `test' -nfct timeout add test inet generic timeout 1 ; OK +nfct add timeout test inet generic timeout 1 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK diff --git a/tests/nfct/timeout/03udplite b/tests/nfct/timeout/03udplite index 69dda15..8ed3459 100644 --- a/tests/nfct/timeout/03udplite +++ b/tests/nfct/timeout/03udplite @@ -1,16 +1,16 @@ # add policy object `test' -nfct timeout add test inet udplite unreplied 10 ; OK +nfct add timeout test inet udplite unreplied 10 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK # get unexistent policy object `dummy' -nfct timeout get test ; BAD +nfct get timeout test ; BAD # delete policy object `test', however, it does not exists anymore -nfct timeout delete test ; BAD +nfct delete timeout test ; BAD # add policy object `test' -nfct timeout add test inet udplite unreplied 1 replied 2 ; OK +nfct add timeout test inet udplite unreplied 1 replied 2 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK diff --git a/tests/nfct/timeout/04icmp b/tests/nfct/timeout/04icmp index 606e8b9..edb1c99 100644 --- a/tests/nfct/timeout/04icmp +++ b/tests/nfct/timeout/04icmp @@ -1,16 +1,16 @@ # add policy object `test' -nfct timeout add test inet icmp timeout 10 ; OK +nfct add timeout test inet icmp timeout 10 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK # get unexistent policy object `dummy' -nfct timeout get test ; BAD +nfct get timeout test ; BAD # delete policy object `test', however, it does not exists anymore -nfct timeout delete test ; BAD +nfct delete timeout test ; BAD # add policy object `test' -nfct timeout add test inet icmp timeout 1 ; OK +nfct add timeout test inet icmp timeout 1 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK diff --git a/tests/nfct/timeout/05icmpv6 b/tests/nfct/timeout/05icmpv6 index 16541f5..40ccc49 100644 --- a/tests/nfct/timeout/05icmpv6 +++ b/tests/nfct/timeout/05icmpv6 @@ -1,16 +1,16 @@ # add policy object `test' -nfct timeout add test inet6 icmpv6 timeout 10 ; OK +nfct add timeout test inet6 icmpv6 timeout 10 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK # get unexistent policy object `dummy' -nfct timeout get test ; BAD +nfct get timeout test ; BAD # delete policy object `test', however, it does not exists anymore -nfct timeout delete test ; BAD +nfct delete timeout test ; BAD # add policy object `test' -nfct timeout add test inet6 icmpv6 timeout 1 ; OK +nfct add timeout test inet6 icmpv6 timeout 1 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK diff --git a/tests/nfct/timeout/06sctp b/tests/nfct/timeout/06sctp index f475215..62b44c6 100644 --- a/tests/nfct/timeout/06sctp +++ b/tests/nfct/timeout/06sctp @@ -1,16 +1,16 @@ # add policy object `test' -nfct timeout add test inet sctp established 100 ; OK +nfct add timeout test inet sctp established 100 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK # get unexistent policy object `dummy' -nfct timeout get test ; BAD +nfct get timeout test ; BAD # delete policy object `test', however, it does not exists anymore -nfct timeout delete test ; BAD +nfct delete timeout test ; BAD # add policy object `test' -nfct timeout add test inet sctp closed 1 cookie_wait 2 cookie_echoed 3 established 4 shutdown_sent 5 shutdown_recd 6 shutdown_ack_sent 7 ; OK +nfct add timeout test inet sctp closed 1 cookie_wait 2 cookie_echoed 3 established 4 shutdown_sent 5 shutdown_recd 6 shutdown_ack_sent 7 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK diff --git a/tests/nfct/timeout/07dccp b/tests/nfct/timeout/07dccp index 1bd4fa5..1d88585 100644 --- a/tests/nfct/timeout/07dccp +++ b/tests/nfct/timeout/07dccp @@ -1,16 +1,16 @@ # add policy object `test' -nfct timeout add test inet dccp request 100 ; OK +nfct add timeout test inet dccp request 100 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK # get unexistent policy object `dummy' -nfct timeout get test ; BAD +nfct get timeout test ; BAD # delete policy object `test', however, it does not exists anymore -nfct timeout delete test ; BAD +nfct delete timeout test ; BAD # add policy object `test' -nfct timeout add test inet dccp request 1 respond 2 partopen 3 open 4 closereq 5 closing 6 timewait 7 ; OK +nfct add timeout test inet dccp request 1 respond 2 partopen 3 open 4 closereq 5 closing 6 timewait 7 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK diff --git a/tests/nfct/timeout/08gre b/tests/nfct/timeout/08gre index 7ef4bdb..709b943 100644 --- a/tests/nfct/timeout/08gre +++ b/tests/nfct/timeout/08gre @@ -1,16 +1,16 @@ # add policy object `test' -nfct timeout add test inet gre unreplied 10 ; OK +nfct add timeout test inet gre unreplied 10 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK # get unexistent policy object `dummy' -nfct timeout get test ; BAD +nfct get timeout test ; BAD # delete policy object `test', however, it does not exists anymore -nfct timeout delete test ; BAD +nfct delete timeout test ; BAD # add policy object `test' -nfct timeout add test inet gre unreplied 1 replied 2 ; OK +nfct add timeout test inet gre unreplied 1 replied 2 ; OK # get policy object `test' -nfct timeout get test ; OK +nfct get timeout test ; OK # delete policy object `test' -nfct timeout delete test ; OK +nfct delete timeout test ; OK -- cgit v1.2.3 From 882bb111285a3a4465995b4af03040a291145d7b Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Fri, 21 Aug 2015 19:18:38 +0200 Subject: nfct: update syntax in documentation Since dd73ceecdbe8 ("nfct: Update syntax to specify command before subsystem") the command comes before the object type. Update documentation accordingly. Signed-off-by: Pablo Neira Ayuso --- README.nfct | 6 +++--- doc/helper/conntrackd.conf | 2 +- doc/manual/conntrack-tools.tmpl | 4 ++-- nfct.8 | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.nfct b/README.nfct index 4d8e6cc..89dd328 100644 --- a/README.nfct +++ b/README.nfct @@ -9,11 +9,11 @@ more similar to `ip' and `nftables' tools (in the long run!). The `nfct' command line tool allows you to define custom timeout policies: -# nfct timeout add custom-tcp-policy1 inet tcp established 100 +# nfct add timeout custom-tcp-policy1 inet tcp established 100 You can also retrieve the existing timeout policies with: -# nfct timeout list +# nfct list timeout .tcp-policy = { .l3proto = 2, .l4proto = 6, @@ -39,7 +39,7 @@ Then, you can use the timeout policy with iptables: You can define policies for other protocols as well, eg: -# nfct timeout add custom-udp-policy1 inet udp unreplied 10 replied 20 +# nfct add timeout custom-udp-policy1 inet udp unreplied 10 replied 20 And attach them via iptables: diff --git a/doc/helper/conntrackd.conf b/doc/helper/conntrackd.conf index d2d94a9..5c07509 100644 --- a/doc/helper/conntrackd.conf +++ b/doc/helper/conntrackd.conf @@ -6,7 +6,7 @@ Helper { # Before this, you have to make sure you have registered the `ftp' # user-space helper stub via: # - # nfct helper add ftp inet tcp + # nfct add helper ftp inet tcp # Type ftp inet tcp { # diff --git a/doc/manual/conntrack-tools.tmpl b/doc/manual/conntrack-tools.tmpl index d23dec5..87a792e 100644 --- a/doc/manual/conntrack-tools.tmpl +++ b/doc/manual/conntrack-tools.tmpl @@ -899,8 +899,8 @@ maintainance. Register user-space helper: -nfct helper add rpc inet udp -nfct helper add rpc inet tcp +nfct add helper rpc inet udp +nfct add helper rpc inet tcp This registers the portmapper helper for both UDP and TCP (NFSv3 traffic goes both over TCP and UDP). diff --git a/nfct.8 b/nfct.8 index 863fe12..336d9cd 100644 --- a/nfct.8 +++ b/nfct.8 @@ -40,7 +40,7 @@ Displays the version information. Displays the help message. .SH EXAMPLE .TP -.B nfct timeout add test-tcp inet tcp established 100 close 10 close_wait 10 +.B nfct add timeout test-tcp inet tcp established 100 close 10 close_wait 10 .TP This creates a timeout policy for tcp using 100 seconds for the ESTABLISHED state, 10 seconds for CLOSE state and 10 seconds for the CLOSE_WAIT state. .TP -- cgit v1.2.3 From 5df0941f73bffabd775d1c14e62295cfe46956eb Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 8 Sep 2015 19:39:46 +0200 Subject: conntrack-tools 1.4.3 release Signed-off-by: Pablo Neira Ayuso --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 523a192..70d3729 100644 --- a/configure.ac +++ b/configure.ac @@ -1,4 +1,4 @@ -AC_INIT(conntrack-tools, 1.4.2, pablo@netfilter.org) +AC_INIT(conntrack-tools, 1.4.3, pablo@netfilter.org) AC_CONFIG_AUX_DIR([build-aux]) AC_CANONICAL_HOST -- cgit v1.2.3