diff options
author | Alex Harpin <development@landsofshadow.co.uk> | 2015-11-21 14:44:29 +0000 |
---|---|---|
committer | Alex Harpin <development@landsofshadow.co.uk> | 2015-11-21 14:44:29 +0000 |
commit | 2a53b5dfee3c80b4c4940ad4c73c82248b4571bb (patch) | |
tree | 73a4fe81edc619a6180ee8d1a02ef5b1942ba910 /src | |
parent | 1e0476f8157fc09c6f9ff086e7b55452b39ea48d (diff) | |
parent | e61ac9a2e58cdcf6dc9a12d32b1f221e078e5d05 (diff) | |
download | conntrack-tools-2a53b5dfee3c80b4c4940ad4c73c82248b4571bb.tar.gz conntrack-tools-2a53b5dfee3c80b4c4940ad4c73c82248b4571bb.zip |
Merge tag 'conntrack-tools-1.4.0' into lithium
conntrack-tools 1.4.0 release
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/build.c | 3 | ||||
-rw-r--r-- | src/conntrack.c | 161 | ||||
-rw-r--r-- | src/cthelper.c | 9 | ||||
-rw-r--r-- | src/ctnl.c | 4 | ||||
-rw-r--r-- | src/expect.c | 2 | ||||
-rw-r--r-- | src/filter.c | 12 | ||||
-rw-r--r-- | src/helpers/ftp.c | 7 | ||||
-rw-r--r-- | src/nfct-extensions/helper.c | 8 | ||||
-rw-r--r-- | src/parse.c | 1 | ||||
-rw-r--r-- | src/read_config_lex.l | 1 | ||||
-rw-r--r-- | src/read_config_yy.y | 42 |
12 files changed, 131 insertions, 124 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index e00d35b..ec03e46 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -9,8 +9,7 @@ CLEANFILES = read_config_yy.c read_config_lex.c 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} +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 \ @@ -47,7 +46,7 @@ read_config_yy.o read_config_lex.o: AM_CFLAGS += -Wno-missing-prototypes -Wno-mi conntrackd_LDADD = ${LIBMNL_LIBS} ${LIBNETFILTER_CONNTRACK_LIBS} \ ${LIBNETFILTER_QUEUE_LIBS} ${LIBNETFILTER_CTHELPER_LIBS} \ - ${libdl_LIBS} + ${libdl_LIBS} ${LIBNFNETLINK_LIBS} conntrackd_LDFLAGS = -export-dynamic diff --git a/src/build.c b/src/build.c index f01e7c8..330f057 100644 --- a/src/build.c +++ b/src/build.c @@ -360,7 +360,8 @@ void exp2msg(const struct nf_expect *exp, struct nethdr *n) exp_build_u32(exp, ATTR_EXP_NAT_DIR, n, NTA_EXP_NAT_DIR); } - exp_build_str(exp, ATTR_EXP_HELPER_NAME, n, NTA_EXP_HELPER_NAME); + if (nfexp_attr_is_set(exp, ATTR_EXP_HELPER_NAME)) + exp_build_str(exp, ATTR_EXP_HELPER_NAME, n, NTA_EXP_HELPER_NAME); if (nfexp_attr_is_set(exp, ATTR_EXP_FN)) exp_build_str(exp, ATTR_EXP_FN, n, NTA_EXP_FN); } diff --git a/src/conntrack.c b/src/conntrack.c index ee85022..7451a80 100644 --- a/src/conntrack.c +++ b/src/conntrack.c @@ -587,6 +587,8 @@ exit_error(enum exittype status, const char *msg, ...) va_end(args); if (status == PARAMETER_PROBLEM) exit_tryhelp(status); + /* release template objects that were allocated in the setup stage. */ + free_tmpl_objects(); exit(status); } @@ -820,45 +822,27 @@ add_command(unsigned int *cmd, const int newcmd) *cmd |= newcmd; } -static char *get_table(int argc, char *argv[]) +static unsigned int +check_type(int argc, char *argv[]) { char *table = NULL; - /* Nasty bug or feature in getopt_long ? + /* 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; - else if (optind < argc && argv[optind][0] != '-' && - argv[optind][0] != '!') + else if (optind < argc && argv[optind][0] != '-' + && argv[optind][0] != '!') table = argv[optind++]; - - return table; -} - -enum { - CT_TABLE_CONNTRACK, - CT_TABLE_EXPECT, - CT_TABLE_DYING, - CT_TABLE_UNCONFIRMED, -}; - -static unsigned int check_type(int argc, char *argv[]) -{ - const char *table = get_table(argc, argv); - - /* default to conntrack subsystem if nothing has been specified. */ - if (table == NULL) - return CT_TABLE_CONNTRACK; - + + if (!table) + return 0; + if (strncmp("expect", table, strlen(table)) == 0) - return CT_TABLE_EXPECT; + return 1; else if (strncmp("conntrack", table, strlen(table)) == 0) - return CT_TABLE_CONNTRACK; - else if (strncmp("dying", table, strlen(table)) == 0) - return CT_TABLE_DYING; - else if (strncmp("unconfirmed", table, strlen(table)) == 0) - return CT_TABLE_UNCONFIRMED; + return 0; else exit_error(PARAMETER_PROBLEM, "unknown type `%s'", table); @@ -1072,7 +1056,7 @@ filter_nat(const struct nf_conntrack *obj, const struct nf_conntrack *ct) else if (options & CT_OPT_DST_NAT) return !has_dstnat; - return (options & (CT_OPT_SRC_NAT | CT_OPT_DST_NAT)) ? 1 : 0; + return 0; } static int counter; @@ -1557,6 +1541,26 @@ nfct_mnl_dump(uint16_t subsys, uint16_t type, mnl_cb_t cb) return res; } +static int +nfct_mnl_get(uint16_t subsys, uint16_t type, mnl_cb_t cb) +{ + char buf[MNL_SOCKET_BUFFER_SIZE]; + struct nlmsghdr *nlh; + int res; + + nlh = nfct_mnl_nlmsghdr_put(buf, subsys, type); + + res = mnl_socket_sendto(sock.mnl, nlh, nlh->nlmsg_len); + if (res < 0) + return res; + + res = mnl_socket_recvfrom(sock.mnl, buf, sizeof(buf)); + if (res < 0) + return res; + + return mnl_cb_run(buf, res, nlh->nlmsg_seq, sock.portid, cb, NULL); +} + static int nfct_stats_attr_cb(const struct nlattr *attr, void *data) { const struct nlattr **tb = data; @@ -1651,24 +1655,34 @@ static int nfexp_stats_cb(const struct nlmsghdr *nlh, void *data) return MNL_CB_OK; } -static int mnl_nfct_dump_cb(const struct nlmsghdr *nlh, void *data) +static int nfct_stats_global_attr_cb(const struct nlattr *attr, void *data) { - struct nf_conntrack *ct; - char buf[4096]; + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); - ct = nfct_new(); - if (ct == NULL) + if (mnl_attr_type_valid(attr, CTA_STATS_GLOBAL_MAX) < 0) return MNL_CB_OK; - nfct_nlmsg_parse(nlh, ct); + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) { + perror("mnl_attr_validate"); + return MNL_CB_ERROR; + } - nfct_snprintf(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, 0); - printf("%s\n", buf); + tb[type] = attr; + return MNL_CB_OK; +} - nfct_destroy(ct); +static int nfct_global_stats_cb(const struct nlmsghdr *nlh, void *data) +{ + struct nlattr *tb[CTA_STATS_GLOBAL_MAX+1] = {}; + struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); - counter++; + mnl_attr_parse(nlh, sizeof(*nfg), nfct_stats_global_attr_cb, tb); + if (tb[CTA_STATS_GLOBAL_ENTRIES]) { + printf("%d\n", + ntohl(mnl_attr_get_u32(tb[CTA_STATS_GLOBAL_ENTRIES]))); + } return MNL_CB_OK; } @@ -1706,16 +1720,6 @@ int main(int argc, char *argv[]) switch(c) { /* commands */ case 'L': - type = check_type(argc, argv); - /* Special case: dumping dying and unconfirmed list - * are handled like normal conntrack dumps. - */ - if (type == CT_TABLE_DYING || - type == CT_TABLE_UNCONFIRMED) - add_command(&command, cmd2type[c][0]); - else - add_command(&command, cmd2type[c][type]); - break; case 'I': case 'D': case 'G': @@ -1726,25 +1730,14 @@ int main(int argc, char *argv[]) case 'C': case 'S': type = check_type(argc, argv); - if (type == CT_TABLE_DYING || - type == CT_TABLE_UNCONFIRMED) { - exit_error(PARAMETER_PROBLEM, - "Can't do that command with " - "tables `dying' and `unconfirmed'"); - } add_command(&command, cmd2type[c][type]); break; case 'U': type = check_type(argc, argv); - if (type == CT_TABLE_DYING || - type == CT_TABLE_UNCONFIRMED) { - exit_error(PARAMETER_PROBLEM, - "Can't do that command with " - "tables `dying' and `unconfirmed'"); - } else if (type == CT_TABLE_CONNTRACK) + if (type == 0) add_command(&command, CT_UPDATE); else - exit_error(PARAMETER_PROBLEM, + exit_error(PARAMETER_PROBLEM, "Can't update expectations"); break; /* options */ @@ -1944,28 +1937,6 @@ int main(int argc, char *argv[]) struct nfct_filter_dump *filter_dump; case CT_LIST: - if (type == CT_TABLE_DYING) { - if (nfct_mnl_socket_open() < 0) - exit_error(OTHER_PROBLEM, "Can't open handler"); - - res = nfct_mnl_dump(NFNL_SUBSYS_CTNETLINK, - IPCTNL_MSG_CT_GET_DYING, - mnl_nfct_dump_cb); - - nfct_mnl_socket_close(); - break; - } else if (type == CT_TABLE_UNCONFIRMED) { - if (nfct_mnl_socket_open() < 0) - exit_error(OTHER_PROBLEM, "Can't open handler"); - - res = nfct_mnl_dump(NFNL_SUBSYS_CTNETLINK, - IPCTNL_MSG_CT_GET_UNCONFIRMED, - mnl_nfct_dump_cb); - - nfct_mnl_socket_close(); - break; - } - cth = nfct_open(CONNTRACK, 0); if (!cth) exit_error(OTHER_PROBLEM, "Can't open handler"); @@ -2216,7 +2187,25 @@ int main(int argc, char *argv[]) res = nfexp_catch(cth); nfct_close(cth); break; - case CT_COUNT: { + case CT_COUNT: + /* If we fail with netlink, fall back to /proc to ensure + * backward compatibility. + */ + if (nfct_mnl_socket_open() < 0) + goto try_proc_count; + + res = nfct_mnl_get(NFNL_SUBSYS_CTNETLINK, + IPCTNL_MSG_CT_GET_STATS, + nfct_global_stats_cb); + + nfct_mnl_socket_close(); + + /* don't look at /proc, we got the information via ctnetlink */ + if (res >= 0) + break; + +try_proc_count: + { #define NF_CONNTRACK_COUNT_PROC "/proc/sys/net/netfilter/nf_conntrack_count" FILE *fd; int count; diff --git a/src/cthelper.c b/src/cthelper.c index e303558..307be96 100644 --- a/src/cthelper.c +++ b/src/cthelper.c @@ -353,8 +353,9 @@ static int cthelper_setup(struct ctd_helper_instance *cur) nfct_helper_attr_set_u32(t, NFCTH_ATTR_STATUS, NFCT_HELPER_STATUS_ENABLED); - dlog(LOG_NOTICE, "configuring helper `%s' with queuenum=%d", - cur->helper->name, cur->queue_num); + dlog(LOG_NOTICE, "configuring helper `%s' with queuenum=%d and " + "queuelen=%d", cur->helper->name, cur->queue_num, + cur->queue_len); for (j=0; j<CTD_HELPER_POLICY_MAX; j++) { struct nfct_helper_policy *p; @@ -431,7 +432,9 @@ static int cthelper_nfqueue_setup(struct ctd_helper_instance *cur) nlh = nfq_hdr_put(buf, NFQNL_MSG_CONFIG, cur->queue_num); nfq_nlmsg_cfg_put_params(nlh, NFQNL_COPY_PACKET, 0xffff); - mnl_attr_put_u32(nlh, NFQA_CFG_FLAGS, htonl(NFQNL_F_CONNTRACK)); + 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 (mnl_socket_sendto(STATE_CTH(nl), nlh, nlh->nlmsg_len) < 0) { dlog(LOG_ERR, "failed to send configuration"); @@ -164,7 +164,9 @@ static void do_polling_alarm(struct alarm_block *a, void *data) STATE(mode)->internal->exp.purge(); nl_send_resync(STATE(resync)); - nl_send_expect_resync(STATE(resync)); + if (CONFIG(flags) & CTD_EXPECT) + nl_send_expect_resync(STATE(resync)); + add_alarm(&STATE(polling_alarm), CONFIG(poll_kernel_secs), 0); } diff --git a/src/expect.c b/src/expect.c index 94c26bc..6069770 100644 --- a/src/expect.c +++ b/src/expect.c @@ -177,7 +177,7 @@ static int cthelper_expect_cmd(struct nf_expect *exp, int cmd) int cthelper_add_expect(struct nf_expect *exp) { - return cthelper_expect_cmd(exp, NFCT_Q_CREATE); + return cthelper_expect_cmd(exp, NFCT_Q_CREATE_UPDATE); } int cthelper_del_expect(struct nf_expect *exp) diff --git a/src/filter.c b/src/filter.c index 39dd4ca..02a8078 100644 --- a/src/filter.c +++ b/src/filter.c @@ -473,7 +473,17 @@ int exp_filter_find(struct exp_filter *f, const struct nf_expect *exp) return 1; list_for_each_entry(item, &f->list, head) { - const char *name = nfexp_get_attr(exp, ATTR_EXP_HELPER_NAME); + const char *name; + + if (nfexp_attr_is_set(exp, ATTR_EXP_HELPER_NAME)) + name = nfexp_get_attr(exp, ATTR_EXP_HELPER_NAME); + else { + /* No helper name, this is likely to be a kernel older + * which does not include the helper name, just skip + * this so we don't crash. + */ + return 0; + } /* we allow partial matching to support things like sip-PORT. */ if (strncasecmp(item->helper_name, name, diff --git a/src/helpers/ftp.c b/src/helpers/ftp.c index 962020b..2c8dcd6 100644 --- a/src/helpers/ftp.c +++ b/src/helpers/ftp.c @@ -346,7 +346,12 @@ static int nf_nat_ftp_fmt_cmd(enum nf_ct_ftp_type type, port >> 8, port & 0xFF); case NF_CT_FTP_EPRT: - return snprintf(buffer, buflen, "|1|%pI4|%u|", &addr, port); + return snprintf(buffer, buflen, "|1|%u.%u.%u.%u|%u|", + ((unsigned char *)&addr)[0], + ((unsigned char *)&addr)[1], + ((unsigned char *)&addr)[2], + ((unsigned char *)&addr)[3], + port); case NF_CT_FTP_EPSV: return snprintf(buffer, buflen, "|||%u|", port); } diff --git a/src/nfct-extensions/helper.c b/src/nfct-extensions/helper.c index e8f85bb..f91fc41 100644 --- a/src/nfct-extensions/helper.c +++ b/src/nfct-extensions/helper.c @@ -202,9 +202,7 @@ int nfct_cmd_helper_add(int argc, char *argv[]) return -1; } - /* XXX use prefix defined in configure.ac. */ - helper = helper_find("/usr/lib/conntrack-tools", - argv[3], l4proto, RTLD_LAZY); + helper = helper_find(CONNTRACKD_LIB_DIR, argv[3], l4proto, RTLD_LAZY); if (helper == NULL) { nfct_perror("that helper is not supported"); return -1; @@ -558,9 +556,7 @@ int nfct_cmd_helper_disable(int argc, char *argv[]) return -1; } - /* XXX use prefix defined in configure.ac. */ - helper = helper_find("/usr/lib/conntrack-tools", - argv[3], l4proto, RTLD_LAZY); + helper = helper_find(CONNTRACKD_LIB_DIR, argv[3], l4proto, RTLD_LAZY); if (helper == NULL) { nfct_perror("that helper is not supported"); return -1; diff --git a/src/parse.c b/src/parse.c index c3b7f7f..8ce4495 100644 --- a/src/parse.c +++ b/src/parse.c @@ -19,6 +19,7 @@ #include "network.h" +#include <stdlib.h> #include <libnetfilter_conntrack/libnetfilter_conntrack.h> #ifndef ssizeof diff --git a/src/read_config_lex.l b/src/read_config_lex.l index 31fa32e..bec2d81 100644 --- a/src/read_config_lex.l +++ b/src/read_config_lex.l @@ -144,6 +144,7 @@ notrack [N|n][O|o][T|t][R|r][A|a][C|c][K|k] "ErrorQueueLength" { return T_ERROR_QUEUE_LENGTH; } "Helper" { return T_HELPER; } "QueueNum" { return T_HELPER_QUEUE_NUM; } +"QueueLen" { return T_HELPER_QUEUE_LEN; } "Policy" { return T_HELPER_POLICY; } "ExpectMax" { return T_HELPER_EXPECT_MAX; } "ExpectTimeout" { return T_HELPER_EXPECT_TIMEOUT; } diff --git a/src/read_config_yy.y b/src/read_config_yy.y index 623b79d..72a9654 100644 --- a/src/read_config_yy.y +++ b/src/read_config_yy.y @@ -56,6 +56,7 @@ struct stack symbol_stack; enum { SYMBOL_HELPER_QUEUE_NUM, + SYMBOL_HELPER_QUEUE_LEN, SYMBOL_HELPER_POLICY_EXPECT_ROOT, SYMBOL_HELPER_EXPECT_POLICY_LEAF, }; @@ -86,8 +87,8 @@ enum { %token T_SCHEDULER T_TYPE T_PRIO T_NETLINK_EVENTS_RELIABLE %token T_DISABLE_INTERNAL_CACHE T_DISABLE_EXTERNAL_CACHE T_ERROR_QUEUE_LENGTH %token T_OPTIONS T_TCP_WINDOW_TRACKING T_EXPECT_SYNC -%token T_HELPER T_HELPER_QUEUE_NUM T_HELPER_POLICY T_HELPER_EXPECT_MAX -%token T_HELPER_EXPECT_TIMEOUT +%token T_HELPER T_HELPER_QUEUE_NUM T_HELPER_QUEUE_LEN T_HELPER_POLICY +%token T_HELPER_EXPECT_TIMEOUT T_HELPER_EXPECT_MAX %token <string> T_IP T_PATH_VAL %token <val> T_NUMBER @@ -1313,25 +1314,6 @@ filter_protocol_item : T_UDP pent->p_proto); }; -filter_protocol_item : T_UDP -{ - struct protoent *pent; - - pent = getprotobyname("udp"); - if (pent == NULL) { - print_err(CTD_CFG_WARN, "getprotobyname() cannot find " - "protocol `udp' in /etc/protocols"); - break; - } - ct_filter_add_proto(STATE(us_filter), pent->p_proto); - - __kernel_filter_start(); - - nfct_filter_add_attr_u32(STATE(filter), - NFCT_FILTER_L4PROTO, - pent->p_proto); -}; - filter_item : T_ADDRESS T_ACCEPT '{' filter_address_list '}' { ct_filter_set_logic(STATE(us_filter), @@ -1658,6 +1640,13 @@ helper_type: T_TYPE T_STRING T_STRING T_STRING '{' helper_type_list '}' stack_item_free(e); break; } + case SYMBOL_HELPER_QUEUE_LEN: { + int *qlen = (int *) &e->data; + + helper_inst->queue_len = *qlen; + stack_item_free(e); + break; + } case SYMBOL_HELPER_POLICY_EXPECT_ROOT: { struct ctd_helper_policy *pol = (struct ctd_helper_policy *) &e->data; @@ -1715,6 +1704,17 @@ helper_type: T_HELPER_QUEUE_NUM T_NUMBER stack_item_push(&symbol_stack, e); }; +helper_type: T_HELPER_QUEUE_LEN T_NUMBER +{ + int *qlen; + struct stack_item *e; + + e = stack_item_alloc(SYMBOL_HELPER_QUEUE_LEN, sizeof(int)); + qlen = (int *) e->data; + *qlen = $2; + stack_item_push(&symbol_stack, e); +}; + helper_type: T_HELPER_POLICY T_STRING '{' helper_policy_list '}' { struct stack_item *e; |