summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac5
-rw-r--r--conntrack.82
-rw-r--r--extensions/libct_proto_unknown.c11
-rw-r--r--include/Makefile.am2
-rw-r--r--include/helper.h1
-rw-r--r--include/helpers/Makefile.am1
-rw-r--r--include/helpers/ftp.h14
-rw-r--r--include/helpers/rpc.h15
-rw-r--r--include/helpers/sane.h13
-rw-r--r--include/helpers/tns.h9
-rw-r--r--src/Makefile.am2
-rw-r--r--src/build.c15
-rw-r--r--src/cache.c4
-rw-r--r--src/conntrack.c364
-rw-r--r--src/filter.c2
-rw-r--r--src/hash.c1
-rw-r--r--src/helpers.c3
-rw-r--r--src/helpers/Makefile.am2
-rw-r--r--src/helpers/ftp.c32
-rw-r--r--src/helpers/rpc.c13
-rw-r--r--src/helpers/sane.c10
-rw-r--r--src/helpers/ssdp.c1
-rw-r--r--src/helpers/tns.c7
-rw-r--r--src/main.c2
-rw-r--r--src/nfct-extensions/helper.c184
-rw-r--r--src/process.c2
-rw-r--r--src/queue.c4
-rw-r--r--src/read_config_yy.y12
-rw-r--r--src/run.c2
-rw-r--r--tests/conntrack/testsuite/00create37
-rw-r--r--tests/conntrack/testsuite/09dumpopt26
31 files changed, 529 insertions, 269 deletions
diff --git a/configure.ac b/configure.ac
index b12b722..d9d351b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -77,15 +77,12 @@ AC_CHECK_HEADERS([linux/capability.h],, [AC_MSG_ERROR([Cannot find linux/capabib
AC_CHECK_HEADERS(arpa/inet.h)
AC_CHECK_FUNCS(inet_pton)
-# Let nfct use dlopen() on helper libraries without resolving all symbols.
-AX_CHECK_LINK_FLAG([-Wl,-z,lazy], [AC_SUBST([LAZY_LDFLAGS], [-Wl,-z,lazy])])
-
if test ! -z "$libdir"; then
MODULE_DIR="\\\"$libdir/conntrack-tools/\\\""
CFLAGS="$CFLAGS -DCONNTRACKD_LIB_DIR=$MODULE_DIR"
fi
-AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/linux/Makefile include/linux/netfilter/Makefile extensions/Makefile src/helpers/Makefile])
+AC_CONFIG_FILES([Makefile src/Makefile include/Makefile include/helpers/Makefile include/linux/Makefile include/linux/netfilter/Makefile extensions/Makefile src/helpers/Makefile])
AC_OUTPUT
echo "
diff --git a/conntrack.8 b/conntrack.8
index c3214ee..0db427b 100644
--- a/conntrack.8
+++ b/conntrack.8
@@ -114,7 +114,7 @@ Load entries from a given file. To read from stdin, "\-" should be specified.
Atomically zero counters after reading them. This option is only valid in
combination with the "\-L, \-\-dump" command options.
.TP
-.BI "-o, --output [extended,xml,save,timestamp,id,ktimestamp,labels,userspace] "
+.BI "-o, --output [extended,xml,save,timestamp,id,ktimestamp,labels] "
Display output in a certain format. With the extended output option, this tool
displays the layer 3 information. With ktimestamp, it displays the in-kernel
timestamp available since 2.6.38 (you can enable it via the \fBsysctl(8)\fP
diff --git a/extensions/libct_proto_unknown.c b/extensions/libct_proto_unknown.c
index 2a47704..b877c56 100644
--- a/extensions/libct_proto_unknown.c
+++ b/extensions/libct_proto_unknown.c
@@ -21,10 +21,21 @@ static void help(void)
fprintf(stdout, " no options (unsupported)\n");
}
+static void final_check(unsigned int flags,
+ unsigned int cmd,
+ struct nf_conntrack *ct)
+{
+ if (nfct_attr_is_set(ct, ATTR_REPL_L3PROTO) &&
+ nfct_attr_is_set(ct, ATTR_L4PROTO) &&
+ !nfct_attr_is_set(ct, ATTR_REPL_L4PROTO))
+ nfct_set_attr_u8(ct, ATTR_REPL_L4PROTO, nfct_get_attr_u8(ct, ATTR_L4PROTO));
+}
+
struct ctproto_handler ct_proto_unknown = {
.name = "unknown",
.help = help,
.opts = opts,
+ .final_check = final_check,
.version = VERSION,
};
diff --git a/include/Makefile.am b/include/Makefile.am
index 352054e..4741b50 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = linux
+SUBDIRS = linux helpers
noinst_HEADERS = alarm.h jhash.h cache.h linux_list.h linux_rbtree.h \
sync.h conntrackd.h local.h udp.h tcp.h \
diff --git a/include/helper.h b/include/helper.h
index d540667..08d4cf4 100644
--- a/include/helper.h
+++ b/include/helper.h
@@ -56,6 +56,7 @@ extern int in4_pton(const char *src, int srclen, uint8_t *dst, int delim, const
extern int in6_pton(const char *src, int srclen, uint8_t *dst, int delim, const char **end);
extern void helper_register(struct ctd_helper *helper);
+struct ctd_helper *__helper_find(const char *helper_name, uint8_t l4proto);
struct ctd_helper *helper_find(const char *libdir_path, const char *name, uint8_t l4proto, int flags);
#define min_t(type, x, y) ({ \
diff --git a/include/helpers/Makefile.am b/include/helpers/Makefile.am
new file mode 100644
index 0000000..99a4257
--- /dev/null
+++ b/include/helpers/Makefile.am
@@ -0,0 +1 @@
+noinst_HEADERS = ftp.h rpc.h sane.h tns.h
diff --git a/include/helpers/ftp.h b/include/helpers/ftp.h
new file mode 100644
index 0000000..50e2d0c
--- /dev/null
+++ b/include/helpers/ftp.h
@@ -0,0 +1,14 @@
+#ifndef _CTD_FTP_H
+#define _CTD_FTP_H
+
+#define NUM_SEQ_TO_REMEMBER 2
+
+/* This structure exists only once per master */
+struct ftp_info {
+ /* Valid seq positions for cmd matching after newline */
+ uint32_t seq_aft_nl[MYCT_DIR_MAX][NUM_SEQ_TO_REMEMBER];
+ /* 0 means seq_match_aft_nl not set */
+ int seq_aft_nl_num[MYCT_DIR_MAX];
+};
+
+#endif
diff --git a/include/helpers/rpc.h b/include/helpers/rpc.h
new file mode 100644
index 0000000..b0b8d17
--- /dev/null
+++ b/include/helpers/rpc.h
@@ -0,0 +1,15 @@
+#ifndef _CTD_RPC_H
+#define _CTD_RPC_H
+
+struct rpc_info {
+ /* XID */
+ uint32_t xid;
+ /* program */
+ uint32_t pm_prog;
+ /* program version */
+ uint32_t pm_vers;
+ /* transport protocol: TCP|UDP */
+ uint32_t pm_prot;
+};
+
+#endif
diff --git a/include/helpers/sane.h b/include/helpers/sane.h
new file mode 100644
index 0000000..1e70ff6
--- /dev/null
+++ b/include/helpers/sane.h
@@ -0,0 +1,13 @@
+#ifndef _CTD_SANE_H
+#define _CTD_SANE_H
+
+enum sane_state {
+ SANE_STATE_NORMAL,
+ SANE_STATE_START_REQUESTED,
+};
+
+struct nf_ct_sane_master {
+ enum sane_state state;
+};
+
+#endif
diff --git a/include/helpers/tns.h b/include/helpers/tns.h
new file mode 100644
index 0000000..60dcf25
--- /dev/null
+++ b/include/helpers/tns.h
@@ -0,0 +1,9 @@
+#ifndef _CTD_TNS_H
+#define _CTD_TNS_H
+
+struct tns_info {
+ /* Scan next DATA|REDIRECT packet */
+ bool parse;
+};
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 1d56394..a1a91a0 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,8 +35,6 @@ if HAVE_CTHELPER
nfct_LDADD += ${LIBNETFILTER_CTHELPER_LIBS}
endif
-nfct_LDFLAGS = -export-dynamic ${LAZY_LDFLAGS}
-
conntrackd_SOURCES = alarm.c main.c run.c hash.c queue.c queue_tx.c rbtree.c \
local.c log.c mcast.c udp.c netlink.c vector.c \
filter.c fds.c event.c process.c origin.c date.c \
diff --git a/src/build.c b/src/build.c
index 63e47c7..c07974f 100644
--- a/src/build.c
+++ b/src/build.c
@@ -133,11 +133,12 @@ static enum nf_conntrack_attr nat_type[] =
/* 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);
@@ -147,12 +148,13 @@ 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);
@@ -160,12 +162,13 @@ 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);
}
diff --git a/src/cache.c b/src/cache.c
index 79a024f..9bc8d0f 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -69,12 +69,12 @@ struct cache *cache_create(const char *name, enum cache_type type,
memcpy(c->feature_type, feature_type, sizeof(feature_type));
- c->features = malloc(sizeof(struct cache_feature) * j);
+ c->features = malloc(sizeof(struct cache_feature *) * j);
if (!c->features) {
free(c);
return NULL;
}
- memcpy(c->features, feature_array, sizeof(struct cache_feature) * j);
+ memcpy(c->features, feature_array, sizeof(struct cache_feature *) * j);
c->num_features = j;
c->extra_offset = size;
diff --git a/src/conntrack.c b/src/conntrack.c
index fe5574d..d49ac1a 100644
--- a/src/conntrack.c
+++ b/src/conntrack.c
@@ -68,10 +68,14 @@
#include <linux/netfilter/nf_conntrack_common.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
-static struct nfct_mnl_socket {
+struct nfct_mnl_socket {
struct mnl_socket *mnl;
uint32_t portid;
-} _sock;
+};
+
+static struct nfct_mnl_socket _sock;
+static struct nfct_mnl_socket _modifier_sock;
+static struct nfct_mnl_socket _event_sock;
struct u32_mask {
uint32_t value;
@@ -605,7 +609,7 @@ static const char usage_parameters[] =
#define OPTION_OFFSET 256
-static struct nfct_handle *cth, *ith;
+static struct nfct_handle *cth;
static struct option *opts = original_opts;
static unsigned int global_option_offset = 0;
@@ -796,6 +800,7 @@ static int ct_save_snprintf(char *buf, size_t len,
struct ctproto_handler *cur;
uint8_t l3proto, l4proto;
int tuple_attrs[4] = {};
+ bool l4proto_set;
unsigned i;
int ret;
@@ -856,6 +861,7 @@ static int ct_save_snprintf(char *buf, size_t len,
l4proto = nfct_get_attr_u8(ct, ATTR_L4PROTO);
+ l4proto_set = false;
/* is it in the list of supported protocol? */
list_for_each_entry(cur, &proto_list, head) {
if (cur->protonum != l4proto)
@@ -866,9 +872,16 @@ static int ct_save_snprintf(char *buf, size_t len,
ret = ct_snprintf_opts(buf + offset, len, ct, cur->print_opts);
BUFFER_SIZE(ret, size, len, offset);
+
+ l4proto_set = true;
break;
}
+ if (!l4proto_set) {
+ ret = snprintf(buf + offset, len, "-p %d ", l4proto);
+ BUFFER_SIZE(ret, size, len, offset);
+ }
+
/* skip trailing space, if any */
for (; size && buf[size-1] == ' '; --size)
buf[size-1] = '\0';
@@ -878,6 +891,21 @@ static int ct_save_snprintf(char *buf, size_t len,
extern struct ctproto_handler ct_proto_unknown;
+static int parse_proto_num(const char *str)
+{
+ char *endptr;
+ long val;
+
+ val = strtol(str, &endptr, 0);
+ if (val >= IPPROTO_MAX ||
+ val < 0 ||
+ endptr == str ||
+ *endptr != '\0')
+ return -1;
+
+ return val;
+}
+
static struct ctproto_handler *findproto(char *name, int *pnum)
{
struct ctproto_handler *cur;
@@ -897,8 +925,8 @@ static struct ctproto_handler *findproto(char *name, int *pnum)
return &ct_proto_unknown;
}
/* using a protocol number? */
- protonum = atoi(name);
- if (protonum >= 0 && protonum <= IPPROTO_MAX) {
+ protonum = parse_proto_num(name);
+ if (protonum >= 0) {
/* try lookup by number, perhaps this protocol is supported */
list_for_each_entry(cur, &proto_list, head) {
if (cur->protonum == protonum) {
@@ -1124,8 +1152,7 @@ enum {
_O_ID = (1 << 3),
_O_KTMS = (1 << 4),
_O_CL = (1 << 5),
- _O_US = (1 << 6),
- _O_SAVE = (1 << 7),
+ _O_SAVE = (1 << 6),
};
enum {
@@ -1145,7 +1172,7 @@ static struct parse_parameter {
{ {"ALL", "NEW", "UPDATES", "DESTROY"}, 4,
{ CT_EVENT_F_ALL, CT_EVENT_F_NEW, CT_EVENT_F_UPD, CT_EVENT_F_DEL } },
{ {"xml", "extended", "timestamp", "id", "ktimestamp", "labels", "userspace", "save"}, 8,
- { _O_XML, _O_EXT, _O_TMS, _O_ID, _O_KTMS, _O_CL, _O_US, _O_SAVE },
+ { _O_XML, _O_EXT, _O_TMS, _O_ID, _O_KTMS, _O_CL, 0, _O_SAVE },
},
};
@@ -1974,7 +2001,7 @@ static int event_cb(const struct nlmsghdr *nlh, void *data)
nfct_snprintf_labels(buf, sizeof(buf), ct, type, op_type, op_flags, labelmap);
done:
- if ((output_mask & _O_US) && nlh->nlmsg_pid) {
+ if (nlh->nlmsg_pid) {
char *prog = get_progname(nlh->nlmsg_pid);
if (prog)
@@ -1992,61 +2019,33 @@ out:
return MNL_CB_OK;
}
-static int dump_cb(enum nf_conntrack_msg_type type,
- struct nf_conntrack *ct,
- void *data)
-{
- unsigned int op_type = NFCT_O_DEFAULT;
- unsigned int op_flags = 0;
- struct ct_cmd *cmd = data;
- char buf[1024];
-
- if (nfct_filter(cmd, ct, cur_tmpl))
- return NFCT_CB_CONTINUE;
-
- if (output_mask & _O_SAVE) {
- ct_save_snprintf(buf, sizeof(buf), ct, labelmap, NFCT_T_NEW);
- goto done;
- }
-
- if (output_mask & _O_XML) {
- op_type = NFCT_O_XML;
- if (dump_xml_header_done) {
- dump_xml_header_done = 0;
- printf("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
- "<conntrack>\n");
- }
- }
- if (output_mask & _O_EXT)
- op_flags = NFCT_OF_SHOW_LAYER3;
- if (output_mask & _O_KTMS)
- op_flags |= NFCT_OF_TIMESTAMP;
- if (output_mask & _O_ID)
- op_flags |= NFCT_OF_ID;
-
- nfct_snprintf_labels(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, op_type, op_flags, labelmap);
-done:
- printf("%s\n", buf);
-
- counter++;
+static int nfct_mnl_request(struct nfct_mnl_socket *sock, uint16_t subsys,
+ int family, uint16_t type, uint16_t flags,
+ mnl_cb_t cb, const struct nf_conntrack *ct,
+ const struct ct_cmd *cmd);
- return NFCT_CB_CONTINUE;
-}
-
-static int delete_cb(enum nf_conntrack_msg_type type,
- struct nf_conntrack *ct,
- void *data)
+static int mnl_nfct_delete_cb(const struct nlmsghdr *nlh, void *data)
{
+ struct nfct_mnl_socket *modifier_sock = &_modifier_sock;
unsigned int op_type = NFCT_O_DEFAULT;
unsigned int op_flags = 0;
struct ct_cmd *cmd = data;
+ struct nf_conntrack *ct;
char buf[1024];
int res;
+ ct = nfct_new();
+ if (ct == NULL)
+ return MNL_CB_OK;
+
+ nfct_nlmsg_parse(nlh, ct);
+
if (nfct_filter(cmd, ct, cur_tmpl))
- return NFCT_CB_CONTINUE;
+ goto destroy_ok;
- res = nfct_query(ith, NFCT_Q_DESTROY, ct);
+ res = nfct_mnl_request(modifier_sock, NFNL_SUBSYS_CTNETLINK,
+ nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO),
+ IPCTNL_MSG_CT_DELETE, NLM_F_ACK, NULL, ct, NULL);
if (res < 0)
exit_error(OTHER_PROBLEM,
"Operation failed: %s",
@@ -2070,16 +2069,23 @@ done:
counter++;
- return NFCT_CB_CONTINUE;
+destroy_ok:
+ nfct_destroy(ct);
+ return MNL_CB_OK;
}
-static int print_cb(enum nf_conntrack_msg_type type,
- struct nf_conntrack *ct,
- void *data)
+static int mnl_nfct_print_cb(const struct nlmsghdr *nlh, void *data)
{
- char buf[1024];
unsigned int op_type = NFCT_O_DEFAULT;
unsigned int op_flags = 0;
+ struct nf_conntrack *ct;
+ char buf[1024];
+
+ ct = nfct_new();
+ if (ct == NULL)
+ return MNL_CB_OK;
+
+ nfct_nlmsg_parse(nlh, ct);
if (output_mask & _O_SAVE) {
ct_save_snprintf(buf, sizeof(buf), ct, labelmap, NFCT_T_NEW);
@@ -2097,7 +2103,9 @@ static int print_cb(enum nf_conntrack_msg_type type,
done:
printf("%s\n", buf);
- return NFCT_CB_CONTINUE;
+ nfct_destroy(ct);
+
+ return MNL_CB_OK;
}
static void copy_mark(const struct ct_cmd *cmd, struct nf_conntrack *tmp,
@@ -2190,29 +2198,34 @@ static void copy_label(const struct ct_cmd *cmd, struct nf_conntrack *tmp,
}
}
-static int update_cb(enum nf_conntrack_msg_type type,
- struct nf_conntrack *ct,
- void *data)
+static int mnl_nfct_update_cb(const struct nlmsghdr *nlh, void *data)
{
struct ct_cmd *cmd = data;
- struct nf_conntrack *obj = cmd->tmpl.ct, *tmp;
+ struct nfct_mnl_socket *modifier_sock = &_modifier_sock;
+ struct nf_conntrack *ct, *obj = cmd->tmpl.ct, *tmp = NULL;
int res;
+ ct = nfct_new();
+ if (ct == NULL)
+ return MNL_CB_OK;
+
+ nfct_nlmsg_parse(nlh, ct);
+
if (filter_nat(cmd, ct) ||
filter_label(ct, cur_tmpl) ||
filter_network(cmd, ct))
- return NFCT_CB_CONTINUE;
+ goto destroy_ok;
if (nfct_attr_is_set(obj, ATTR_ID) && nfct_attr_is_set(ct, ATTR_ID) &&
nfct_get_attr_u32(obj, ATTR_ID) != nfct_get_attr_u32(ct, ATTR_ID))
- return NFCT_CB_CONTINUE;
+ goto destroy_ok;
if (cmd->options & CT_OPT_TUPLE_ORIG &&
!nfct_cmp(obj, ct, NFCT_CMP_ORIG))
- return NFCT_CB_CONTINUE;
+ goto destroy_ok;
if (cmd->options & CT_OPT_TUPLE_REPL &&
!nfct_cmp(obj, ct, NFCT_CMP_REPL))
- return NFCT_CB_CONTINUE;
+ goto destroy_ok;
tmp = nfct_new();
if (tmp == NULL)
@@ -2225,36 +2238,36 @@ static int update_cb(enum nf_conntrack_msg_type type,
copy_label(cmd, tmp, ct, cur_tmpl);
/* do not send NFCT_Q_UPDATE if ct appears unchanged */
- if (nfct_cmp(tmp, ct, NFCT_CMP_ALL | NFCT_CMP_MASK)) {
- nfct_destroy(tmp);
- return NFCT_CB_CONTINUE;
- }
+ if (nfct_cmp(tmp, ct, NFCT_CMP_ALL | NFCT_CMP_MASK))
+ goto destroy_ok;
- res = nfct_query(ith, NFCT_Q_UPDATE, tmp);
- 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_mnl_request(modifier_sock, NFNL_SUBSYS_CTNETLINK, cmd->family,
+ IPCTNL_MSG_CT_NEW, NLM_F_ACK, NULL, tmp, NULL);
+ if (res < 0) {
+ fprintf(stderr, "Operation failed: %s\n",
+ err2str(errno, CT_UPDATE));
+ }
- res = nfct_query(ith, NFCT_Q_GET, tmp);
+ res = nfct_mnl_request(modifier_sock, NFNL_SUBSYS_CTNETLINK, cmd->family,
+ IPCTNL_MSG_CT_GET, NLM_F_ACK,
+ mnl_nfct_print_cb, tmp, NULL);
if (res < 0) {
- nfct_destroy(tmp);
/* the entry has vanish in middle of the update */
- if (errno == ENOENT) {
- nfct_callback_unregister(ith);
- return NFCT_CB_CONTINUE;
- }
+ if (errno == ENOENT)
+ goto destroy_ok;
exit_error(OTHER_PROBLEM,
"Operation failed: %s",
err2str(errno, CT_UPDATE));
}
- nfct_destroy(tmp);
- nfct_callback_unregister(ith);
counter++;
- return NFCT_CB_CONTINUE;
+destroy_ok:
+ if (tmp)
+ nfct_destroy(tmp);
+ nfct_destroy(ct);
+
+ return MNL_CB_OK;
}
static int dump_exp_cb(enum nf_conntrack_msg_type type,
@@ -2400,7 +2413,7 @@ out_err:
}
static int nfct_mnl_socket_open(struct nfct_mnl_socket *socket,
- unsigned int events)
+ unsigned int events)
{
socket->mnl = mnl_socket_open(NETLINK_NETFILTER);
if (socket->mnl == NULL) {
@@ -2441,8 +2454,25 @@ static void nfct_mnl_socket_close(const struct nfct_mnl_socket *sock)
mnl_socket_close(sock->mnl);
}
-static int nfct_mnl_recv(struct nfct_mnl_socket *sock,
- const struct nlmsghdr *nlh, mnl_cb_t cb, void *data)
+static int nfct_mnl_socket_check_open(struct nfct_mnl_socket *socket,
+ unsigned int events)
+{
+ if (socket->mnl != NULL)
+ return 0;
+
+ return nfct_mnl_socket_open(socket, events);
+}
+
+static void nfct_mnl_socket_check_close(struct nfct_mnl_socket *sock)
+{
+ if (sock->mnl) {
+ nfct_mnl_socket_close(sock);
+ memset(sock, 0, sizeof(*sock));
+ }
+}
+
+static int __nfct_mnl_dump(struct nfct_mnl_socket *sock,
+ const struct nlmsghdr *nlh, mnl_cb_t cb, void *data)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
int res;
@@ -2478,11 +2508,12 @@ nfct_mnl_dump(struct nfct_mnl_socket *sock, uint16_t subsys, uint16_t type,
if (filter_dump)
nfct_nlmsg_build_filter(nlh, filter_dump);
- return nfct_mnl_recv(sock, nlh, cb, cmd);
+ return __nfct_mnl_dump(sock, nlh, cb, cmd);
}
static int nfct_mnl_talk(struct nfct_mnl_socket *sock,
- const struct nlmsghdr *nlh, mnl_cb_t cb)
+ const struct nlmsghdr *nlh, mnl_cb_t cb,
+ const struct ct_cmd *cmd)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
int ret;
@@ -2495,38 +2526,27 @@ static int nfct_mnl_talk(struct nfct_mnl_socket *sock,
if (ret < 0)
return ret;
- return mnl_cb_run(buf, ret, nlh->nlmsg_seq, sock->portid, cb, NULL);
-}
-
-static int
-nfct_mnl_get(struct nfct_mnl_socket *sock, uint16_t subsys, uint16_t type,
- mnl_cb_t cb, uint8_t family)
-{
- char buf[MNL_SOCKET_BUFFER_SIZE];
- struct nlmsghdr *nlh;
-
- nlh = nfct_mnl_nlmsghdr_put(buf, subsys, type, 0, family);
-
- return nfct_mnl_talk(sock, nlh, cb);
+ return mnl_cb_run(buf, ret, nlh->nlmsg_seq, sock->portid, cb, (void *)cmd);
}
-static int
-nfct_mnl_create(struct nfct_mnl_socket *sock, uint16_t subsys, uint16_t type,
- const struct nf_conntrack *ct)
+static int nfct_mnl_request(struct nfct_mnl_socket *sock, uint16_t subsys,
+ int family, uint16_t type, uint16_t flags,
+ mnl_cb_t cb, const struct nf_conntrack *ct,
+ const struct ct_cmd *cmd)
{
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
int err;
- nlh = nfct_mnl_nlmsghdr_put(buf, subsys, type,
- NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL,
- nfct_get_attr_u8(ct, ATTR_ORIG_L3PROTO));
+ nlh = nfct_mnl_nlmsghdr_put(buf, subsys, type, flags, family);
- err = nfct_nlmsg_build(nlh, ct);
- if (err < 0)
- return err;
+ if (ct) {
+ err = nfct_nlmsg_build(nlh, ct);
+ if (err < 0)
+ return err;
+ }
- return nfct_mnl_talk(sock, nlh, NULL);
+ return nfct_mnl_talk(sock, nlh, cb, cmd);
}
#define UNKNOWN_STATS_NUM 4
@@ -3096,6 +3116,8 @@ static void do_parse(struct ct_cmd *ct_cmd, int argc, char *argv[])
nfct_set_nat_details(c, tmpl->ct, &ad,
port_str, family);
}
+ free(port_str);
+ free(nat_address);
}
break;
case 'w':
@@ -3250,28 +3272,25 @@ static void do_parse(struct ct_cmd *ct_cmd, int argc, char *argv[])
ct_cmd->socketbuffersize = socketbuffersize;
}
-static int do_command_ct(const char *progname, struct ct_cmd *cmd)
+static int do_command_ct(const char *progname, struct ct_cmd *cmd,
+ struct nfct_mnl_socket *sock)
{
- struct nfct_mnl_socket *sock = &_sock;
+ struct nfct_mnl_socket *modifier_sock = &_modifier_sock;
+ struct nfct_mnl_socket *event_sock = &_event_sock;
struct nfct_filter_dump *filter_dump;
int res = 0;
switch(cmd->command) {
case CT_LIST:
- if (nfct_mnl_socket_open(sock, 0) < 0)
- exit_error(OTHER_PROBLEM, "Can't open handler");
-
if (cmd->type == CT_TABLE_DYING) {
res = nfct_mnl_dump(sock, NFNL_SUBSYS_CTNETLINK,
IPCTNL_MSG_CT_GET_DYING,
mnl_nfct_dump_cb, cmd, NULL);
- nfct_mnl_socket_close(sock);
break;
} else if (cmd->type == CT_TABLE_UNCONFIRMED) {
res = nfct_mnl_dump(sock, NFNL_SUBSYS_CTNETLINK,
IPCTNL_MSG_CT_GET_UNCONFIRMED,
mnl_nfct_dump_cb, cmd, NULL);
- nfct_mnl_socket_close(sock);
break;
}
@@ -3315,10 +3334,7 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
printf("</conntrack>\n");
fflush(stdout);
}
-
- nfct_mnl_socket_close(sock);
break;
-
case EXP_LIST:
cth = nfct_open(EXPECT, 0);
if (!cth)
@@ -3347,16 +3363,13 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
nfct_set_attr(cmd->tmpl.ct, ATTR_CONNLABELS,
xnfct_bitmask_clone(cmd->tmpl.label_modify));
- res = nfct_mnl_socket_open(sock, 0);
- if (res < 0)
- exit_error(OTHER_PROBLEM, "Can't open netlink socket");
-
- res = nfct_mnl_create(sock, NFNL_SUBSYS_CTNETLINK,
- IPCTNL_MSG_CT_NEW, cmd->tmpl.ct);
+ res = nfct_mnl_request(sock, NFNL_SUBSYS_CTNETLINK, cmd->family,
+ IPCTNL_MSG_CT_NEW,
+ NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL,
+ NULL, cmd->tmpl.ct, NULL);
if (res >= 0)
counter++;
- nfct_mnl_socket_close(sock);
break;
case EXP_CREATE:
@@ -3373,31 +3386,21 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
break;
case CT_UPDATE:
- cth = nfct_open(CONNTRACK, 0);
- /* internal handler for delete_cb, otherwise we hit EILSEQ */
- ith = nfct_open(CONNTRACK, 0);
- if (!cth || !ith)
+ if (nfct_mnl_socket_check_open(modifier_sock, 0) < 0)
exit_error(OTHER_PROBLEM, "Can't open handler");
nfct_filter_init(cmd);
-
- nfct_callback_register(cth, NFCT_T_ALL, update_cb, cmd);
-
- res = nfct_query(cth, NFCT_Q_DUMP, &cmd->family);
- nfct_close(ith);
- nfct_close(cth);
+ res = nfct_mnl_dump(sock, NFNL_SUBSYS_CTNETLINK,
+ IPCTNL_MSG_CT_GET, mnl_nfct_update_cb,
+ cmd, NULL);
break;
case CT_DELETE:
- cth = nfct_open(CONNTRACK, 0);
- ith = nfct_open(CONNTRACK, 0);
- if (!cth || !ith)
+ if (nfct_mnl_socket_check_open(modifier_sock, 0) < 0)
exit_error(OTHER_PROBLEM, "Can't open handler");
nfct_filter_init(cmd);
- nfct_callback_register(cth, NFCT_T_ALL, delete_cb, cmd);
-
filter_dump = nfct_filter_dump_create();
if (filter_dump == NULL)
exit_error(OTHER_PROBLEM, "OOM");
@@ -3411,12 +3414,11 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
NFCT_FILTER_DUMP_L3NUM,
cmd->family);
- res = nfct_query(cth, NFCT_Q_DUMP_FILTER, filter_dump);
+ res = nfct_mnl_dump(sock, NFNL_SUBSYS_CTNETLINK,
+ IPCTNL_MSG_CT_GET, mnl_nfct_delete_cb,
+ cmd, filter_dump);
nfct_filter_dump_destroy(filter_dump);
-
- nfct_close(ith);
- nfct_close(cth);
break;
case EXP_DELETE:
@@ -3431,13 +3433,9 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
break;
case CT_GET:
- cth = nfct_open(CONNTRACK, 0);
- if (!cth)
- exit_error(OTHER_PROBLEM, "Can't open handler");
-
- nfct_callback_register(cth, NFCT_T_ALL, dump_cb, cmd);
- res = nfct_query(cth, NFCT_Q_GET, cmd->tmpl.ct);
- nfct_close(cth);
+ res = nfct_mnl_request(sock, NFNL_SUBSYS_CTNETLINK, cmd->family,
+ IPCTNL_MSG_CT_GET, NLM_F_ACK,
+ mnl_nfct_dump_cb, cmd->tmpl.ct, cmd);
break;
case EXP_GET:
@@ -3453,11 +3451,9 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
break;
case CT_FLUSH:
- cth = nfct_open(CONNTRACK, 0);
- if (!cth)
- exit_error(OTHER_PROBLEM, "Can't open handler");
- res = nfct_query(cth, NFCT_Q_FLUSH_FILTER, &cmd->family);
- nfct_close(cth);
+ res = nfct_mnl_request(sock, NFNL_SUBSYS_CTNETLINK, cmd->family,
+ IPCTNL_MSG_CT_DELETE, NLM_F_ACK, NULL, NULL, NULL);
+
fprintf(stderr, "%s v%s (conntrack-tools): ",PROGNAME,VERSION);
fprintf(stderr,"connection tracking table has been emptied.\n");
break;
@@ -3483,9 +3479,9 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
if (cmd->event_mask & CT_EVENT_F_DEL)
nl_events |= NF_NETLINK_CONNTRACK_DESTROY;
- res = nfct_mnl_socket_open(sock, nl_events);
+ res = nfct_mnl_socket_open(event_sock, nl_events);
} else {
- res = nfct_mnl_socket_open(sock,
+ res = nfct_mnl_socket_open(event_sock,
NF_NETLINK_CONNTRACK_NEW |
NF_NETLINK_CONNTRACK_UPDATE |
NF_NETLINK_CONNTRACK_DESTROY);
@@ -3524,7 +3520,7 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
while (1) {
char buf[MNL_SOCKET_BUFFER_SIZE];
- res = mnl_socket_recvfrom(sock->mnl, buf, sizeof(buf));
+ res = mnl_socket_recvfrom(event_sock->mnl, buf, sizeof(buf));
if (res < 0) {
if (errno == ENOBUFS) {
fprintf(stderr,
@@ -3543,7 +3539,7 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
}
res = mnl_cb_run(buf, res, 0, 0, event_cb, cmd);
}
- mnl_socket_close(sock->mnl);
+ mnl_socket_close(event_sock->mnl);
break;
case EXP_EVENT:
@@ -3577,21 +3573,14 @@ static int do_command_ct(const char *progname, struct ct_cmd *cmd)
/* If we fail with netlink, fall back to /proc to ensure
* backward compatibility.
*/
- if (nfct_mnl_socket_open(sock, 0) < 0)
- goto try_proc_count;
-
- res = nfct_mnl_get(sock,
- NFNL_SUBSYS_CTNETLINK,
- IPCTNL_MSG_CT_GET_STATS,
- nfct_global_stats_cb, AF_UNSPEC);
-
- nfct_mnl_socket_close(sock);
+ res = nfct_mnl_request(sock, NFNL_SUBSYS_CTNETLINK, AF_UNSPEC,
+ IPCTNL_MSG_CT_GET_STATS, 0,
+ nfct_global_stats_cb, NULL, NULL);
/* 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;
@@ -3623,15 +3612,10 @@ try_proc_count:
/* If we fail with netlink, fall back to /proc to ensure
* backward compatibility.
*/
- if (nfct_mnl_socket_open(sock, 0) < 0)
- goto try_proc;
-
res = nfct_mnl_dump(sock, NFNL_SUBSYS_CTNETLINK,
IPCTNL_MSG_CT_GET_STATS_CPU,
nfct_stats_cb, NULL, NULL);
- nfct_mnl_socket_close(sock);
-
/* don't look at /proc, we got the information via ctnetlink */
if (res >= 0)
break;
@@ -3642,15 +3626,10 @@ try_proc_count:
/* If we fail with netlink, fall back to /proc to ensure
* backward compatibility.
*/
- if (nfct_mnl_socket_open(sock, 0) < 0)
- goto try_proc;
-
res = nfct_mnl_dump(sock, NFNL_SUBSYS_CTNETLINK_EXP,
IPCTNL_MSG_EXP_GET_STATS_CPU,
nfexp_stats_cb, NULL, NULL);
- nfct_mnl_socket_close(sock);
-
/* don't look at /proc, we got the information via ctnetlink */
if (res >= 0)
break;
@@ -3872,6 +3851,8 @@ static const char *ct_unsupp_cmd_file(const struct ct_cmd *cmd)
int main(int argc, char *argv[])
{
+ struct nfct_mnl_socket *modifier_sock = &_modifier_sock;
+ struct nfct_mnl_socket *sock = &_sock;
struct ct_cmd *cmd, *next;
LIST_HEAD(cmd_list);
int res = 0;
@@ -3886,6 +3867,9 @@ int main(int argc, char *argv[])
register_gre();
register_unknown();
+ if (nfct_mnl_socket_open(sock, 0) < 0)
+ exit_error(OTHER_PROBLEM, "Can't open handler");
+
if (argc > 2 &&
(!strcmp(argv[1], "-R") || !strcmp(argv[1], "--load-file"))) {
ct_parse_file(&cmd_list, argv[0], argv[2]);
@@ -3897,7 +3881,7 @@ int main(int argc, char *argv[])
ct_unsupp_cmd_file(cmd));
}
list_for_each_entry_safe(cmd, next, &cmd_list, list) {
- res |= do_command_ct(argv[0], cmd);
+ res |= do_command_ct(argv[0], cmd, sock);
list_del(&cmd->list);
free(cmd);
}
@@ -3907,10 +3891,12 @@ int main(int argc, char *argv[])
exit_error(OTHER_PROBLEM, "OOM");
do_parse(cmd, argc, argv);
- do_command_ct(argv[0], cmd);
+ do_command_ct(argv[0], cmd, sock);
res = print_stats(cmd);
free(cmd);
}
+ nfct_mnl_socket_close(sock);
+ nfct_mnl_socket_check_close(modifier_sock);
return res < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
diff --git a/src/filter.c b/src/filter.c
index 6577102..ee316e7 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -476,7 +476,7 @@ struct exp_filter *exp_filter_create(void)
struct exp_filter_item {
struct list_head head;
- char helper_name[NFCT_HELPER_NAME_MAX];
+ char helper_name[NFCT_HELPER_NAME_MAX + 1];
};
/* this is ugly, but it simplifies read_config_yy.y */
diff --git a/src/hash.c b/src/hash.c
index fe6a047..a0f240c 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -55,6 +55,7 @@ hashtable_create(int hashsize, int limit,
void hashtable_destroy(struct hashtable *h)
{
+ hashtable_flush(h);
free(h);
}
diff --git a/src/helpers.c b/src/helpers.c
index 3e4e6c8..8ca78dc 100644
--- a/src/helpers.c
+++ b/src/helpers.c
@@ -26,8 +26,7 @@ void helper_register(struct ctd_helper *helper)
list_add(&helper->head, &helper_list);
}
-static struct ctd_helper *
-__helper_find(const char *helper_name, uint8_t l4proto)
+struct ctd_helper *__helper_find(const char *helper_name, uint8_t l4proto)
{
struct ctd_helper *cur, *helper = NULL;
diff --git a/src/helpers/Makefile.am b/src/helpers/Makefile.am
index e4f10c9..e458ab4 100644
--- a/src/helpers/Makefile.am
+++ b/src/helpers/Makefile.am
@@ -11,7 +11,7 @@ pkglib_LTLIBRARIES = ct_helper_amanda.la \
ct_helper_slp.la \
ct_helper_ssdp.la
-HELPER_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS) $(LAZY_LDFLAGS)
+HELPER_LDFLAGS = -avoid-version -module $(LIBNETFILTER_CONNTRACK_LIBS)
HELPER_CFLAGS = $(AM_CFLAGS) $(LIBNETFILTER_CONNTRACK_CFLAGS)
ct_helper_amanda_la_SOURCES = amanda.c
diff --git a/src/helpers/ftp.c b/src/helpers/ftp.c
index 2505c71..2b34534 100644
--- a/src/helpers/ftp.c
+++ b/src/helpers/ftp.c
@@ -36,17 +36,9 @@
#include <libnetfilter_queue/pktbuff.h>
#include <linux/netfilter.h>
-static bool loose; /* XXX: export this as config option. */
-
-#define NUM_SEQ_TO_REMEMBER 2
+#include "helpers/ftp.h"
-/* This structure exists only once per master */
-struct ftp_info {
- /* Valid seq positions for cmd matching after newline */
- uint32_t seq_aft_nl[MYCT_DIR_MAX][NUM_SEQ_TO_REMEMBER];
- /* 0 means seq_match_aft_nl not set */
- int seq_aft_nl_num[MYCT_DIR_MAX];
-};
+static bool loose; /* XXX: export this as config option. */
enum nf_ct_ftp_type {
/* PORT command from client */
@@ -340,23 +332,21 @@ static int nf_nat_ftp_fmt_cmd(enum nf_ct_ftp_type type,
char *buffer, size_t buflen,
uint32_t addr, uint16_t port)
{
+ union {
+ unsigned char c[4];
+ uint32_t d;
+ } tmp;
+
+ tmp.d = addr;
switch (type) {
case NF_CT_FTP_PORT:
case NF_CT_FTP_PASV:
return snprintf(buffer, buflen, "%u,%u,%u,%u,%u,%u",
- ((unsigned char *)&addr)[0],
- ((unsigned char *)&addr)[1],
- ((unsigned char *)&addr)[2],
- ((unsigned char *)&addr)[3],
- port >> 8,
- port & 0xFF);
+ tmp.c[0], tmp.c[1], tmp.c[2], tmp.c[3],
+ port >> 8, port & 0xFF);
case NF_CT_FTP_EPRT:
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);
+ tmp.c[0], tmp.c[1], tmp.c[2], tmp.c[3], port);
case NF_CT_FTP_EPSV:
return snprintf(buffer, buflen, "|||%u|", port);
}
diff --git a/src/helpers/rpc.c b/src/helpers/rpc.c
index 3b3d0a7..732e9ba 100644
--- a/src/helpers/rpc.c
+++ b/src/helpers/rpc.c
@@ -41,21 +41,12 @@
#include <libnetfilter_queue/pktbuff.h>
#include <linux/netfilter.h>
+#include "helpers/rpc.h"
+
/* RFC 1050: RPC: Remote Procedure Call Protocol Specification Version 2 */
/* RFC 1014: XDR: External Data Representation Standard */
#define SUPPORTED_RPC_VERSION 2
-struct rpc_info {
- /* XID */
- uint32_t xid;
- /* program */
- uint32_t pm_prog;
- /* program version */
- uint32_t pm_vers;
- /* transport protocol: TCP|UDP */
- uint32_t pm_prot;
-};
-
/* So, this packet has hit the connection tracking matching code.
Mangle it, and change the expectation to match the new version. */
static unsigned int
diff --git a/src/helpers/sane.c b/src/helpers/sane.c
index 2c07099..ebcb24c 100644
--- a/src/helpers/sane.c
+++ b/src/helpers/sane.c
@@ -39,11 +39,7 @@
#include <libnetfilter_queue/libnetfilter_queue_tcp.h>
#include <libnetfilter_queue/pktbuff.h>
#include <linux/netfilter.h>
-
-enum sane_state {
- SANE_STATE_NORMAL,
- SANE_STATE_START_REQUESTED,
-};
+#include "helpers/sane.h"
struct sane_request {
uint32_t RPC_code;
@@ -61,10 +57,6 @@ struct sane_reply_net_start {
/* 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)
diff --git a/src/helpers/ssdp.c b/src/helpers/ssdp.c
index 0c6f563..527892c 100644
--- a/src/helpers/ssdp.c
+++ b/src/helpers/ssdp.c
@@ -256,7 +256,6 @@ static int find_hdr(const char *name, const uint8_t *data, int data_len,
data += i+2;
}
- data_len -= name_len;
data += name_len;
if (pos)
*pos = data;
diff --git a/src/helpers/tns.c b/src/helpers/tns.c
index 803f40a..5692f29 100644
--- a/src/helpers/tns.c
+++ b/src/helpers/tns.c
@@ -29,6 +29,8 @@
#include <libnetfilter_queue/pktbuff.h>
#include <linux/netfilter.h>
+#include "helpers/tns.h"
+
/* TNS SQL*Net Version 2 */
enum tns_types {
TNS_TYPE_CONNECT = 1,
@@ -58,11 +60,6 @@ struct tns_redirect {
uint16_t data_len;
};
-struct tns_info {
- /* Scan next DATA|REDIRECT packet */
- bool parse;
-};
-
static int try_number(const char *data, size_t dlen, uint32_t array[],
int array_size, char sep, char term)
{
diff --git a/src/main.c b/src/main.c
index 31e0eed..de4773d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -319,7 +319,7 @@ int main(int argc, char *argv[])
umask(0177);
- if ((ret = init_config(config_file)) == -1) {
+ if (init_config(config_file) == -1) {
dlog(LOG_ERR, "can't open config file `%s'", config_file);
exit(EXIT_FAILURE);
}
diff --git a/src/nfct-extensions/helper.c b/src/nfct-extensions/helper.c
index e5d8d0a..894bf26 100644
--- a/src/nfct-extensions/helper.c
+++ b/src/nfct-extensions/helper.c
@@ -180,7 +180,7 @@ static int nfct_cmd_helper_add(struct mnl_socket *nl, int argc, char *argv[])
return -1;
}
- helper = helper_find(CONNTRACKD_LIB_DIR, argv[3], l4proto, RTLD_LAZY);
+ helper = __helper_find(argv[3], l4proto);
if (helper == NULL) {
nfct_perror("that helper is not supported");
return -1;
@@ -430,7 +430,7 @@ nfct_cmd_helper_disable(struct mnl_socket *nl, int argc, char *argv[])
return -1;
}
- helper = helper_find(CONNTRACKD_LIB_DIR, argv[3], l4proto, RTLD_LAZY);
+ helper = __helper_find(argv[3], l4proto);
if (helper == NULL) {
nfct_perror("that helper is not supported");
return -1;
@@ -468,7 +468,187 @@ static struct nfct_extension helper = {
.parse_params = nfct_helper_parse_params,
};
+/*
+ * supported helpers: to set up helpers via nfct, the following definitions are
+ * provided for backward compatibility reasons since conntrackd does not depend
+ * on nfct anymore to set up the userspace helpers.
+ */
+
+static struct ctd_helper amanda_helper = {
+ .name = "amanda",
+ .l4proto = IPPROTO_UDP,
+ .policy = {
+ [0] = {
+ .name = "amanda",
+ .expect_max = 3,
+ .expect_timeout = 180,
+ },
+ },
+};
+
+static struct ctd_helper dhcpv6_helper = {
+ .name = "dhcpv6",
+ .l4proto = IPPROTO_UDP,
+ .policy = {
+ [0] = {
+ .name = "dhcpv6",
+ .expect_max = 1,
+ .expect_timeout = 300,
+ },
+ },
+};
+
+#include "helpers/ftp.h"
+
+static struct ctd_helper ftp_helper = {
+ .name = "ftp",
+ .l4proto = IPPROTO_TCP,
+ .priv_data_len = sizeof(struct ftp_info),
+ .policy = {
+ [0] = {
+ .name = "ftp",
+ .expect_max = 1,
+ .expect_timeout = 300,
+ },
+ },
+};
+
+static struct ctd_helper mdns_helper = {
+ .name = "mdns",
+ .l4proto = IPPROTO_UDP,
+ .priv_data_len = 0,
+ .policy = {
+ [0] = {
+ .name = "mdns",
+ .expect_max = 8,
+ .expect_timeout = 30,
+ },
+ },
+};
+
+#include "helpers/rpc.h"
+
+static struct ctd_helper rpc_helper_tcp = {
+ .name = "rpc",
+ .l4proto = IPPROTO_TCP,
+ .priv_data_len = sizeof(struct rpc_info),
+ .policy = {
+ {
+ .name = "rpc",
+ .expect_max = 1,
+ .expect_timeout = 300,
+ },
+ },
+};
+
+static struct ctd_helper rpc_helper_udp = {
+ .name = "rpc",
+ .l4proto = IPPROTO_UDP,
+ .priv_data_len = sizeof(struct rpc_info),
+ .policy = {
+ {
+ .name = "rpc",
+ .expect_max = 1,
+ .expect_timeout = 300,
+ },
+ },
+};
+
+#include "helpers/sane.h"
+
+static struct ctd_helper sane_helper = {
+ .name = "sane",
+ .l4proto = IPPROTO_TCP,
+ .priv_data_len = sizeof(struct nf_ct_sane_master),
+ .policy = {
+ [0] = {
+ .name = "sane",
+ .expect_max = 1,
+ .expect_timeout = 5 * 60,
+ },
+ },
+};
+
+static struct ctd_helper slp_helper = {
+ .name = "slp",
+ .l4proto = IPPROTO_UDP,
+ .priv_data_len = 0,
+ .policy = {
+ [0] = {
+ .name = "slp",
+ .expect_max = 8,
+ .expect_timeout = 16, /* default CONFIG_MC_MAX + 1 */
+ },
+ },
+};
+
+static struct ctd_helper ssdp_helper_udp = {
+ .name = "ssdp",
+ .l4proto = IPPROTO_UDP,
+ .priv_data_len = 0,
+ .policy = {
+ [0] = {
+ .name = "ssdp",
+ .expect_max = 8,
+ .expect_timeout = 5 * 60,
+ },
+ },
+};
+
+static struct ctd_helper ssdp_helper_tcp = {
+ .name = "ssdp",
+ .l4proto = IPPROTO_TCP,
+ .priv_data_len = 0,
+ .policy = {
+ [0] = {
+ .name = "ssdp",
+ .expect_max = 8,
+ .expect_timeout = 5 * 60,
+ },
+ },
+};
+
+static struct ctd_helper tftp_helper = {
+ .name = "tftp",
+ .l4proto = IPPROTO_UDP,
+ .policy = {
+ [0] = {
+ .name = "tftp",
+ .expect_max = 1,
+ .expect_timeout = 5 * 60,
+ },
+ },
+};
+
+#include "helpers/tns.h"
+
+static struct ctd_helper tns_helper = {
+ .name = "tns",
+ .l4proto = IPPROTO_TCP,
+ .priv_data_len = sizeof(struct tns_info),
+ .policy = {
+ [0] = {
+ .name = "tns",
+ .expect_max = 1,
+ .expect_timeout = 300,
+ },
+ },
+};
+
static void __init helper_init(void)
{
+ helper_register(&amanda_helper);
+ helper_register(&dhcpv6_helper);
+ helper_register(&ftp_helper);
+ helper_register(&mdns_helper);
+ helper_register(&rpc_helper_tcp);
+ helper_register(&rpc_helper_udp);
+ helper_register(&sane_helper);
+ helper_register(&slp_helper);
+ helper_register(&ssdp_helper_udp);
+ helper_register(&ssdp_helper_tcp);
+ helper_register(&tftp_helper);
+ helper_register(&tns_helper);
+
nfct_extension_register(&helper);
}
diff --git a/src/process.c b/src/process.c
index 3ddad5f..08598ee 100644
--- a/src/process.c
+++ b/src/process.c
@@ -84,7 +84,7 @@ void fork_process_dump(int fd)
int size = 0;
list_for_each_entry(this, &process_list, head) {
- size += snprintf(buf+size, sizeof(buf),
+ size += snprintf(buf + size, sizeof(buf) - size,
"PID=%u type=%s\n",
this->pid,
this->type < CTD_PROC_MAX ?
diff --git a/src/queue.c b/src/queue.c
index 76425b1..e94dc7c 100644
--- a/src/queue.c
+++ b/src/queue.c
@@ -69,12 +69,12 @@ void queue_stats_show(int fd)
int size = 0;
char buf[512];
- size += snprintf(buf+size, sizeof(buf),
+ size += snprintf(buf + size, sizeof(buf) - size,
"allocated queue nodes:\t\t%12u\n\n",
qobjects_num);
list_for_each_entry(this, &queue_list, list) {
- size += snprintf(buf+size, sizeof(buf),
+ size += snprintf(buf + size, sizeof(buf) - size,
"queue %s:\n"
"current elements:\t\t%12u\n"
"maximum elements:\t\t%12u\n"
diff --git a/src/read_config_yy.y b/src/read_config_yy.y
index 95845a1..5815d6a 100644
--- a/src/read_config_yy.y
+++ b/src/read_config_yy.y
@@ -121,7 +121,7 @@ logfile_path : T_LOG T_PATH_VAL
FILENAME_MAXLEN);
exit(EXIT_FAILURE);
}
- snprintf(conf.logfile, FILENAME_MAXLEN, "%s", $2);
+ snprintf(conf.logfile, sizeof(conf.logfile), "%s", $2);
free($2);
};
@@ -176,7 +176,7 @@ lock : T_LOCK T_PATH_VAL
FILENAME_MAXLEN);
exit(EXIT_FAILURE);
}
- snprintf(conf.lockfile, FILENAME_MAXLEN, "%s", $2);
+ snprintf(conf.lockfile, sizeof(conf.lockfile), "%s", $2);
free($2);
};
@@ -704,7 +704,7 @@ unix_option : T_PATH T_PATH_VAL
UNIX_PATH_MAX);
exit(EXIT_FAILURE);
}
- snprintf(conf.local.path, UNIX_PATH_MAX, "%s", $2);
+ snprintf(conf.local.path, sizeof(conf.local.path), "%s", $2);
free($2);
};
@@ -1052,7 +1052,7 @@ scheduler_line : T_PRIO T_NUMBER
{
conf.sched.prio = $2;
if (conf.sched.prio < 0 || conf.sched.prio > 99) {
- dlog(LOG_ERR, "`Priority' must be [0, 99]\n", $2);
+ dlog(LOG_ERR, "`Priority' must be [0, 99]\n");
exit(EXIT_FAILURE);
}
};
@@ -1396,7 +1396,7 @@ stat_logfile_path : T_LOG T_PATH_VAL
FILENAME_MAXLEN);
exit(EXIT_FAILURE);
}
- snprintf(conf.stats.logfile, FILENAME_MAXLEN, "%s", $2);
+ snprintf(conf.stats.logfile, sizeof(conf.stats.logfile), "%s", $2);
free($2);
};
@@ -1622,7 +1622,7 @@ helper_type: T_HELPER_POLICY T_STRING '{' helper_policy_list '}'
}
policy = (struct ctd_helper_policy *) &e->data;
- snprintf(policy->name, CTD_HELPER_NAME_LEN, "%s", $2);
+ snprintf(policy->name, sizeof(policy->name), "%s", $2);
free($2);
/* Now object is complete. */
e->type = SYMBOL_HELPER_POLICY_EXPECT_ROOT;
diff --git a/src/run.c b/src/run.c
index f11a532..37a0eb1 100644
--- a/src/run.c
+++ b/src/run.c
@@ -67,7 +67,7 @@ void killer(int signo)
close_log();
sd_ct_stop();
- exit(0);
+ _exit(0);
}
static void child(int foo)
diff --git a/tests/conntrack/testsuite/00create b/tests/conntrack/testsuite/00create
index 911e711..af22f18 100644
--- a/tests/conntrack/testsuite/00create
+++ b/tests/conntrack/testsuite/00create
@@ -34,3 +34,40 @@
-I -t 29 -u SEEN_REPLY -s 1.1.1.1 -d 2.2.2.2 -r 2.2.2.2 -q 1.1.1.1 -p icmp --icmp-type 8 --icmp-code 0 --icmp-id 1226 ; OK
# delete icmp ping request entry
-D -u SEEN_REPLY -s 1.1.1.1 -d 2.2.2.2 -r 2.2.2.2 -q 1.1.1.1 -p icmp --icmp-type 8 --icmp-code 0 --icmp-id 1226 ; OK
+# Test protocols unknown by the conntrack tool
+# IGMP
+-I -t 10 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 2 ; OK
+# Create again - should fail
+-I -t 10 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 2 ; BAD
+# repeat using protocol name instead of the value, should fail as well
+-I -t 10 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p igmp ; BAD
+# delete
+-D -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 2 ; OK
+# delete again should fail
+-D -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 2 ; BAD
+# create using protocol name instead of the value
+-I -t 10 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p igmp ; OK
+# update
+-U -t 11 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 2 ; OK
+# delete
+-D -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 2 ; OK
+# delete again should fail
+-D -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p igmp ; BAD
+# take some protocol that is not normally not in /etc/protocols
+-I -t 10 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 200 ; OK
+# update
+-U -t 11 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 200 ; OK
+# delete
+-D -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 200 ; OK
+# delete again
+-D -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 200 ; BAD
+# Invalid protocol values
+# 256 should fail
+-I -t 10 -s 1.1.1.1 -d 2.2.2.2 -r 2.2.2.2 -q 1.1.1.1 -p 256 ; BAD
+# take some invalid protocol name
+-I -t 10 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p foo ; BAD
+# take some other invalid protocol values
+-I -t 10 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p -10 ; BAD
+-I -t 10 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 2000 ; BAD
+-I -t 10 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 20foo ; BAD
+-I -t 10 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p foo20 ; BAD
diff --git a/tests/conntrack/testsuite/09dumpopt b/tests/conntrack/testsuite/09dumpopt
index 447590b..c1e0e6e 100644
--- a/tests/conntrack/testsuite/09dumpopt
+++ b/tests/conntrack/testsuite/09dumpopt
@@ -145,3 +145,29 @@
-D -w 11 -u SEEN_REPLY -s 1.1.1.1 -d 2.2.2.2 -r 2.2.2.2 -q 1.1.1.1 -p icmp --icmp-type 8 --icmp-code 0 --icmp-id 1226 ; OK
# clean up after yourself
-D -w 10 ; OK
+# Cover protocols unknown to the conntrack tool
+# Create a conntrack entries
+# IGMP
+-I -w 10 -t 59 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 2 ;
+# Some fency protocol
+-I -w 10 -t 59 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 200 ;
+# Some fency protocol with IPv6
+-I -w 10 -t 59 -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 -p 200 ;
+-R - ; OK
+# copy to zone 11
+-L -w 10 -o save ; |s/-w 10/-w 11/g
+-R - ; OK
+# Delete stuff in zone 10, should succeed
+# IGMP
+-D -w 10 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 2 ; OK
+# Some fency protocol
+-D -w 10 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 200 ; OK
+# Some fency protocol with IPv6
+-D -w 10 -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 -p 200 ; OK
+# Delete stuff in zone 11, should succeed
+# IGMP
+-D -w 11 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 2 ; OK
+# Some fency protocol
+-D -w 11 -s 0.0.0.0 -d 224.0.0.22 -r 224.0.0.22 -q 0.0.0.0 -p 200 ; OK
+# Some fency protocol with IPv6
+-D -w 11 -s 2001:DB8::1.1.1.1 -d 2001:DB8::2.2.2.2 -p 200 ; OK