summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore14
-rw-r--r--Make_global.am24
-rw-r--r--configure.ac13
-rw-r--r--examples/Makefile.am40
-rw-r--r--examples/nfct-mnl-create.c6
-rw-r--r--examples/nfct-mnl-del.c6
-rw-r--r--examples/nfct-mnl-get.c6
-rw-r--r--examples/nfct-mnl-set-label.c7
-rw-r--r--include/internal/Makefile.am2
-rw-r--r--include/internal/internal.h1
-rw-r--r--include/internal/object.h13
-rw-r--r--include/internal/proto.h1
-rw-r--r--include/internal/prototypes.h3
-rw-r--r--include/libnetfilter_conntrack/libnetfilter_conntrack.h13
-rw-r--r--include/libnetfilter_conntrack/libnetfilter_conntrack_sctp.h2
-rw-r--r--include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h39
-rw-r--r--src/conntrack/api.c34
-rw-r--r--src/conntrack/bsf.c17
-rw-r--r--src/conntrack/build.c2
-rw-r--r--src/conntrack/build_mnl.c106
-rw-r--r--src/conntrack/filter.c17
-rw-r--r--src/conntrack/filter_dump.c51
-rw-r--r--src/conntrack/labels.c2
-rw-r--r--src/conntrack/proto.c4
-rw-r--r--src/conntrack/snprintf.c2
-rw-r--r--src/conntrack/snprintf_default.c54
-rw-r--r--src/conntrack/stack.c4
-rw-r--r--src/expect/api.c4
-rw-r--r--src/expect/build.c2
-rw-r--r--tests/Makefile.am4
-rw-r--r--tests/test_connlabel.c8
-rw-r--r--utils/.gitignore2
-rw-r--r--utils/Makefile.am8
-rw-r--r--utils/conntrack_dump_filter.c2
-rw-r--r--utils/conntrack_dump_filter_tuple.c70
-rw-r--r--utils/conntrack_flush_filter.c60
36 files changed, 538 insertions, 105 deletions
diff --git a/.gitignore b/.gitignore
index e90dec6..d1226db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,8 +11,22 @@ Makefile.in
/build-aux/
/config.*
/configure
+/configure~
/libtool
/stamp-h1
/doxygen.cfg
/*.pc
+
+/examples/nfct-mnl-create
+/examples/nfct-mnl-del
+/examples/nfct-mnl-dump
+/examples/nfct-mnl-dump-labels
+/examples/nfct-mnl-event
+/examples/nfct-mnl-flush
+/examples/nfct-mnl-get
+/examples/nfct-mnl-set-label
+/examples/nfexp-mnl-dump
+/examples/nfexp-mnl-event
+/tests/test_connlabel
+/utils/expect_create_nat
diff --git a/Make_global.am b/Make_global.am
index 3a7cc05..bbb7b7b 100644
--- a/Make_global.am
+++ b/Make_global.am
@@ -1,8 +1,24 @@
# This is _NOT_ the library release version, it's an API version.
-# Please read Chapter 6 "Library interface versions" of the libtool
-# documentation before making any modification
-# http://sources.redhat.com/autobook/autobook/autobook_91.html
-LIBVERSION=10:0:7
+# Extracted from Chapter 6 "Library interface versions" of the libtool docs.
+#
+# <snippet>
+# Here are a set of rules to help you update your library version information:
+#
+# 1. Start with version information of `0:0:0' for each libtool library.
+# 2. Update the version information only immediately before a public release
+# of your software. More frequent updates are unnecessary, and only guarantee
+# that the current interface number gets larger faster.
+# 3. If the library source code has changed at all since the last update,
+# then increment revision (`c:r:a' becomes `c:r+1:a').
+# 4. If any interfaces have been added, removed, or changed since the last
+# update, increment current, and set revision to 0.
+# 5. If any interfaces have been added since the last public release, then
+# increment age.
+# 6. If any interfaces have been removed since the last public release, then
+# set age to 0.
+# </snippet>
+#
+LIBVERSION=11:0:8
AM_CPPFLAGS = -I$(top_srcdir)/include ${LIBNFNETLINK_CFLAGS} ${LIBMNL_CFLAGS}
AM_CFLAGS = -Wall
diff --git a/configure.ac b/configure.ac
index 060f307..3512794 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,21 +1,20 @@
dnl Process this file with autoconf to create configure.
-AC_INIT([libnetfilter_conntrack], [1.0.8])
+AC_INIT([libnetfilter_conntrack], [1.0.9])
AC_CONFIG_AUX_DIR([build-aux])
AC_CANONICAL_HOST
-AC_CONFIG_HEADER([config.h])
+AC_CONFIG_HEADERS([config.h])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE([-Wall foreign subdir-objects
- tar-pax no-dist-gzip dist-bzip2 1.6])
+ tar-pax no-dist-gzip dist-xz 1.6])
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
dnl kernel style compile messages
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_PROG_CC
-AC_DISABLE_STATIC
-AM_PROG_LIBTOOL
+LT_INIT([disable-static])
AC_PROG_INSTALL
AC_PROG_LN_S
@@ -55,9 +54,9 @@ int main()
struct in6_addr addr6;
char buf[128];
if (inet_ntop(AF_INET6, &addr6, buf, 128) == 0 && errno == EAFNOSUPPORT)
- exit(1);
+ return 1;
else
- exit(0);
+ return 0;
}
]])],[ AC_MSG_RESULT(yes)
AC_DEFINE_UNQUOTED(HAVE_INET_NTOP_IPV6, 1, [Define to 1 if inet_ntop supports IPv6.])
diff --git a/examples/Makefile.am b/examples/Makefile.am
index a366390..c3373db 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -12,41 +12,41 @@ check_PROGRAMS = nfct-mnl-create \
nfexp-mnl-event
nfct_mnl_create_SOURCES = nfct-mnl-create.c
-nfct_mnl_create_LDADD = ../src/libnetfilter_conntrack.la
-nfct_mnl_create_LDFLAGS = -dynamic -ldl -lmnl
+nfct_mnl_create_LDADD = ../src/libnetfilter_conntrack.la -ldl ${LIBMNL_LIBS}
+nfct_mnl_create_LDFLAGS = -dynamic
nfct_mnl_del_SOURCES = nfct-mnl-del.c
-nfct_mnl_del_LDADD = ../src/libnetfilter_conntrack.la
-nfct_mnl_del_LDFLAGS = -dynamic -ldl -lmnl
+nfct_mnl_del_LDADD = ../src/libnetfilter_conntrack.la -ldl ${LIBMNL_LIBS}
+nfct_mnl_del_LDFLAGS = -dynamic
nfct_mnl_dump_SOURCES = nfct-mnl-dump.c
-nfct_mnl_dump_LDADD = ../src/libnetfilter_conntrack.la
-nfct_mnl_dump_LDFLAGS = -dynamic -ldl -lmnl
+nfct_mnl_dump_LDADD = ../src/libnetfilter_conntrack.la -ldl ${LIBMNL_LIBS}
+nfct_mnl_dump_LDFLAGS = -dynamic
nfct_mnl_dump_labels_SOURCES = nfct-mnl-dump-labels.c
-nfct_mnl_dump_labels_LDADD = ../src/libnetfilter_conntrack.la
-nfct_mnl_dump_labels_LDFLAGS = -dynamic -ldl -lmnl
+nfct_mnl_dump_labels_LDADD = ../src/libnetfilter_conntrack.la -ldl ${LIBMNL_LIBS}
+nfct_mnl_dump_labels_LDFLAGS = -dynamic
nfct_mnl_set_label_SOURCES = nfct-mnl-set-label.c
-nfct_mnl_set_label_LDADD = ../src/libnetfilter_conntrack.la
-nfct_mnl_set_label_LDFLAGS = -dynamic -ldl -lmnl
+nfct_mnl_set_label_LDADD = ../src/libnetfilter_conntrack.la -ldl ${LIBMNL_LIBS}
+nfct_mnl_set_label_LDFLAGS = -dynamic
nfct_mnl_event_SOURCES = nfct-mnl-event.c
-nfct_mnl_event_LDADD = ../src/libnetfilter_conntrack.la
-nfct_mnl_event_LDFLAGS = -dynamic -ldl -lmnl
+nfct_mnl_event_LDADD = ../src/libnetfilter_conntrack.la -ldl ${LIBMNL_LIBS}
+nfct_mnl_event_LDFLAGS = -dynamic
nfct_mnl_flush_SOURCES = nfct-mnl-flush.c
-nfct_mnl_flush_LDADD = ../src/libnetfilter_conntrack.la
-nfct_mnl_flush_LDFLAGS = -dynamic -ldl -lmnl
+nfct_mnl_flush_LDADD = ../src/libnetfilter_conntrack.la -ldl ${LIBMNL_LIBS}
+nfct_mnl_flush_LDFLAGS = -dynamic
nfct_mnl_get_SOURCES = nfct-mnl-get.c
-nfct_mnl_get_LDADD = ../src/libnetfilter_conntrack.la
-nfct_mnl_get_LDFLAGS = -dynamic -ldl -lmnl
+nfct_mnl_get_LDADD = ../src/libnetfilter_conntrack.la -ldl ${LIBMNL_LIBS}
+nfct_mnl_get_LDFLAGS = -dynamic
nfexp_mnl_dump_SOURCES = nfexp-mnl-dump.c
-nfexp_mnl_dump_LDADD = ../src/libnetfilter_conntrack.la
-nfexp_mnl_dump_LDFLAGS = -dynamic -ldl -lmnl
+nfexp_mnl_dump_LDADD = ../src/libnetfilter_conntrack.la -ldl ${LIBMNL_LIBS}
+nfexp_mnl_dump_LDFLAGS = -dynamic
nfexp_mnl_event_SOURCES = nfexp-mnl-event.c
-nfexp_mnl_event_LDADD = ../src/libnetfilter_conntrack.la
-nfexp_mnl_event_LDFLAGS = -dynamic -ldl -lmnl
+nfexp_mnl_event_LDADD = ../src/libnetfilter_conntrack.la -ldl ${LIBMNL_LIBS}
+nfexp_mnl_event_LDFLAGS = -dynamic
diff --git a/examples/nfct-mnl-create.c b/examples/nfct-mnl-create.c
index 64387a7..7fd224d 100644
--- a/examples/nfct-mnl-create.c
+++ b/examples/nfct-mnl-create.c
@@ -60,7 +60,11 @@ int main(void)
nfct_set_attr_u8(ct, ATTR_TCP_STATE, TCP_CONNTRACK_SYN_SENT);
nfct_set_attr_u32(ct, ATTR_TIMEOUT, 100);
- nfct_nlmsg_build(nlh, ct);
+ ret = nfct_nlmsg_build(nlh, ct);
+ if (ret == -1) {
+ perror("nfct_nlmsg_build");
+ exit(EXIT_FAILURE);
+ }
ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len);
if (ret == -1) {
diff --git a/examples/nfct-mnl-del.c b/examples/nfct-mnl-del.c
index 91ad9e4..806d9f8 100644
--- a/examples/nfct-mnl-del.c
+++ b/examples/nfct-mnl-del.c
@@ -55,7 +55,11 @@ int main(void)
nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(20));
nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(10));
- nfct_nlmsg_build(nlh, ct);
+ ret = nfct_nlmsg_build(nlh, ct);
+ if (ret == -1) {
+ perror("nfct_nlmsg_build");
+ exit(EXIT_FAILURE);
+ }
ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len);
if (ret == -1) {
diff --git a/examples/nfct-mnl-get.c b/examples/nfct-mnl-get.c
index 4858acf..5be3331 100644
--- a/examples/nfct-mnl-get.c
+++ b/examples/nfct-mnl-get.c
@@ -74,7 +74,11 @@ int main(void)
nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(20));
nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(10));
- nfct_nlmsg_build(nlh, ct);
+ ret = nfct_nlmsg_build(nlh, ct);
+ if (ret == -1) {
+ perror("nfct_nlmsg_build");
+ exit(EXIT_FAILURE);
+ }
ret = mnl_socket_sendto(nl, nlh, nlh->nlmsg_len);
if (ret == -1) {
diff --git a/examples/nfct-mnl-set-label.c b/examples/nfct-mnl-set-label.c
index c52b267..50bebb0 100644
--- a/examples/nfct-mnl-set-label.c
+++ b/examples/nfct-mnl-set-label.c
@@ -19,6 +19,7 @@ static void set_label(struct nf_conntrack *ct, struct callback_args *cbargs)
char buf[MNL_SOCKET_BUFFER_SIZE];
struct nlmsghdr *nlh;
struct nfgenmsg *nfh;
+ int ret;
if (b) {
if (bit < 0)
@@ -55,7 +56,11 @@ static void set_label(struct nf_conntrack *ct, struct callback_args *cbargs)
nfh->version = NFNETLINK_V0;
nfh->res_id = 0;
- nfct_nlmsg_build(nlh, ct);
+ ret = nfct_nlmsg_build(nlh, ct);
+ if (ret == -1) {
+ perror("nfct_nlmsg_build");
+ exit(EXIT_FAILURE);
+ }
if (mnl_socket_sendto(cbargs->nl, nlh, nlh->nlmsg_len) < 0)
perror("mnl_socket_sendto");
diff --git a/include/internal/Makefile.am b/include/internal/Makefile.am
index d5c2be6..a60c6b5 100644
--- a/include/internal/Makefile.am
+++ b/include/internal/Makefile.am
@@ -1,2 +1,2 @@
noinst_HEADERS = bitops.h extern.h linux_list.h prototypes.h \
- internal.h object.h types.h stack.h
+ internal.h object.h types.h stack.h proto.h
diff --git a/include/internal/internal.h b/include/internal/internal.h
index 2ef8a90..7cd7c44 100644
--- a/include/internal/internal.h
+++ b/include/internal/internal.h
@@ -14,7 +14,6 @@
#include <arpa/inet.h>
#include <time.h>
#include <errno.h>
-#include <netinet/in.h>
#include <libnfnetlink/libnfnetlink.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
diff --git a/include/internal/object.h b/include/internal/object.h
index 3f6904f..8854ef2 100644
--- a/include/internal/object.h
+++ b/include/internal/object.h
@@ -6,6 +6,7 @@
#ifndef _NFCT_OBJECT_H_
#define _NFCT_OBJECT_H_
+#include <internal/bitops.h>
#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
/*
@@ -223,12 +224,13 @@ struct nfct_filter {
enum nfct_filter_logic logic[NFCT_FILTER_MAX];
/*
- * This the layer 4 protocol map for filtering. Not more than
- * 255 protocols (maximum is IPPROTO_MAX which is 256). Actually,
- * I doubt that anyone can reach such a limit.
+ * This the layer 4 protocol map for filtering. Not more than 255
+ * protocols. Although IPPROTO_MAX is currently 263, there are many
+ * fewer protocols defined in netinet/in.h, so no one should reach this
+ * limit.
*/
#define __FILTER_L4PROTO_MAX 255
- uint32_t l4proto_map[IPPROTO_MAX/32];
+ uint32_t l4proto_map[DIV_ROUND_UP(IPPROTO_MAX, 32)];
uint32_t l4proto_len;
struct {
@@ -286,9 +288,12 @@ struct nfct_filter {
*/
struct nfct_filter_dump {
+ struct nf_conntrack ct;
struct nfct_filter_dump_mark mark;
+ struct nfct_filter_dump_mark status;
uint8_t l3num;
uint32_t set;
+ uint16_t zone;
};
/*
diff --git a/include/internal/proto.h b/include/internal/proto.h
index 40e7bfe..60a5f4e 100644
--- a/include/internal/proto.h
+++ b/include/internal/proto.h
@@ -2,6 +2,7 @@
#define _NFCT_PROTO_H_
#include <stdint.h>
+#include <netinet/in.h>
#include <linux/icmp.h>
#include <linux/icmpv6.h>
diff --git a/include/internal/prototypes.h b/include/internal/prototypes.h
index c0047b3..82a3f29 100644
--- a/include/internal/prototypes.h
+++ b/include/internal/prototypes.h
@@ -35,7 +35,8 @@ void __copy_fast(struct nf_conntrack *ct1, const struct nf_conntrack *ct);
int __setup_netlink_socket_filter(int fd, struct nfct_filter *filter);
-void __build_filter_dump(struct nfnlhdr *req, size_t size, const struct nfct_filter_dump *filter_dump);
+int __build_filter_dump(struct nfnlhdr *req, size_t size, const struct nfct_filter_dump *filter_dump);
+int __build_filter_flush(struct nfnlhdr *req, size_t size, const struct nfct_filter_dump *filter_dump);
int nfct_build_tuple(struct nlmsghdr *nlh, const struct __nfct_tuple *t, int type);
int nfct_parse_tuple(const struct nlattr *attr, struct __nfct_tuple *tuple, int dir, uint32_t *set);
diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack.h b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
index c5c6b61..2e9458a 100644
--- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h
+++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h
@@ -137,11 +137,11 @@ enum nf_conntrack_attr {
ATTR_HELPER_INFO, /* variable length */
ATTR_CONNLABELS, /* variable length */
ATTR_CONNLABELS_MASK, /* variable length */
- ATTR_ORIG_ZONE, /* u16 bits */
+ ATTR_ORIG_ZONE = 68, /* u16 bits */
ATTR_REPL_ZONE, /* u16 bits */
ATTR_SNAT_IPV6, /* u128 bits */
ATTR_DNAT_IPV6, /* u128 bits */
- ATTR_SYNPROXY_ISN, /* u32 bits */
+ ATTR_SYNPROXY_ISN = 72, /* u32 bits */
ATTR_SYNPROXY_ITS, /* u32 bits */
ATTR_SYNPROXY_TSOFF, /* u32 bits */
ATTR_MAX
@@ -452,6 +452,7 @@ enum nf_conntrack_query {
NFCT_Q_CREATE_UPDATE,
NFCT_Q_DUMP_FILTER,
NFCT_Q_DUMP_FILTER_RESET,
+ NFCT_Q_FLUSH_FILTER,
};
extern int nfct_query(struct nfct_handle *h,
@@ -545,6 +546,9 @@ struct nfct_filter_dump_mark {
enum nfct_filter_dump_attr {
NFCT_FILTER_DUMP_MARK = 0, /* struct nfct_filter_dump_mark */
NFCT_FILTER_DUMP_L3NUM, /* uint8_t */
+ NFCT_FILTER_DUMP_STATUS, /* struct nfct_filter_dump_mark */
+ NFCT_FILTER_DUMP_ZONE, /* uint16_t */
+ NFCT_FILTER_DUMP_TUPLE,
NFCT_FILTER_DUMP_MAX
};
@@ -560,6 +564,10 @@ void nfct_filter_dump_set_attr_u8(struct nfct_filter_dump *filter_dump,
const enum nfct_filter_dump_attr type,
uint8_t data);
+void nfct_filter_dump_set_attr_u16(struct nfct_filter_dump *filter_dump,
+ const enum nfct_filter_dump_attr type,
+ uint16_t data);
+
/* low level API: netlink functions */
extern __attribute__((deprecated)) int
@@ -585,6 +593,7 @@ int nfct_build_query(struct nfnl_subsys_handle *ssh,
/* New low level API: netlink functions */
extern int nfct_nlmsg_build(struct nlmsghdr *nlh, const struct nf_conntrack *ct);
+extern int nfct_nlmsg_build_filter(struct nlmsghdr *nlh, const struct nfct_filter_dump *filter_dump);
extern int nfct_nlmsg_parse(const struct nlmsghdr *nlh, struct nf_conntrack *ct);
extern int nfct_payload_parse(const void *payload, size_t payload_len, uint16_t l3num, struct nf_conntrack *ct);
diff --git a/include/libnetfilter_conntrack/libnetfilter_conntrack_sctp.h b/include/libnetfilter_conntrack/libnetfilter_conntrack_sctp.h
index 1921259..4982066 100644
--- a/include/libnetfilter_conntrack/libnetfilter_conntrack_sctp.h
+++ b/include/libnetfilter_conntrack/libnetfilter_conntrack_sctp.h
@@ -14,6 +14,8 @@ enum sctp_state {
SCTP_CONNTRACK_SHUTDOWN_SENT,
SCTP_CONNTRACK_SHUTDOWN_RECD,
SCTP_CONNTRACK_SHUTDOWN_ACK_SENT,
+ SCTP_CONNTRACK_HEARTBEAT_SENT,
+ SCTP_CONNTRACK_HEARTBEAT_ACKED,
SCTP_CONNTRACK_MAX
};
diff --git a/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h b/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
index aa45723..b8ffe02 100644
--- a/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
+++ b/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h
@@ -58,6 +58,8 @@ enum ctattr_type {
CTA_LABELS,
CTA_LABELS_MASK,
CTA_SYNPROXY,
+ CTA_FILTER,
+ CTA_STATUS_MASK,
__CTA_MAX
};
#define CTA_MAX (__CTA_MAX - 1)
@@ -121,6 +123,7 @@ enum ctattr_protoinfo_dccp {
CTA_PROTOINFO_DCCP_STATE,
CTA_PROTOINFO_DCCP_ROLE,
CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
+ CTA_PROTOINFO_DCCP_PAD,
__CTA_PROTOINFO_DCCP_MAX,
};
#define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1)
@@ -140,6 +143,7 @@ enum ctattr_counters {
CTA_COUNTERS_BYTES, /* 64bit counters */
CTA_COUNTERS32_PACKETS, /* old 32bit counters, unused */
CTA_COUNTERS32_BYTES, /* old 32bit counters, unused */
+ CTA_COUNTERS_PAD,
__CTA_COUNTERS_MAX
};
#define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
@@ -148,6 +152,7 @@ enum ctattr_tstamp {
CTA_TIMESTAMP_UNSPEC,
CTA_TIMESTAMP_START,
CTA_TIMESTAMP_STOP,
+ CTA_TIMESTAMP_PAD,
__CTA_TIMESTAMP_MAX
};
#define CTA_TIMESTAMP_MAX (__CTA_TIMESTAMP_MAX - 1)
@@ -242,19 +247,21 @@ enum ctattr_secctx {
enum ctattr_stats_cpu {
CTA_STATS_UNSPEC,
- CTA_STATS_SEARCHED,
+ CTA_STATS_SEARCHED, /* no longer used */
CTA_STATS_FOUND,
- CTA_STATS_NEW,
+ CTA_STATS_NEW, /* no longer used */
CTA_STATS_INVALID,
- CTA_STATS_IGNORE,
- CTA_STATS_DELETE,
- CTA_STATS_DELETE_LIST,
+ CTA_STATS_IGNORE, /* no longer used */
+ CTA_STATS_DELETE, /* no longer used */
+ CTA_STATS_DELETE_LIST, /* no longer used */
CTA_STATS_INSERT,
CTA_STATS_INSERT_FAILED,
CTA_STATS_DROP,
CTA_STATS_EARLY_DROP,
CTA_STATS_ERROR,
CTA_STATS_SEARCH_RESTART,
+ CTA_STATS_CLASH_RESOLVE,
+ CTA_STATS_CHAIN_TOOLONG,
__CTA_STATS_MAX,
};
#define CTA_STATS_MAX (__CTA_STATS_MAX - 1)
@@ -262,6 +269,7 @@ enum ctattr_stats_cpu {
enum ctattr_stats_global {
CTA_STATS_GLOBAL_UNSPEC,
CTA_STATS_GLOBAL_ENTRIES,
+ CTA_STATS_GLOBAL_MAX_ENTRIES,
__CTA_STATS_GLOBAL_MAX,
};
#define CTA_STATS_GLOBAL_MAX (__CTA_STATS_GLOBAL_MAX - 1)
@@ -275,6 +283,27 @@ enum ctattr_expect_stats {
};
#define CTA_STATS_EXP_MAX (__CTA_STATS_EXP_MAX - 1)
+enum ctattr_filter {
+ CTA_FILTER_UNSPEC,
+ CTA_FILTER_ORIG_FLAGS,
+ CTA_FILTER_REPLY_FLAGS,
+ __CTA_FILTER_MAX
+};
+#define CTA_FILTER_MAX (__CTA_FILTER_MAX - 1)
+
+#define CTA_FILTER_FLAG_CTA_IP_SRC (1 << 0)
+#define CTA_FILTER_FLAG_CTA_IP_DST (1 << 1)
+#define CTA_FILTER_FLAG_CTA_TUPLE_ZONE (1 << 2)
+#define CTA_FILTER_FLAG_CTA_PROTO_NUM (1 << 3)
+#define CTA_FILTER_FLAG_CTA_PROTO_SRC_PORT (1 << 4)
+#define CTA_FILTER_FLAG_CTA_PROTO_DST_PORT (1 << 5)
+#define CTA_FILTER_FLAG_CTA_PROTO_ICMP_TYPE (1 << 6)
+#define CTA_FILTER_FLAG_CTA_PROTO_ICMP_CODE (1 << 7)
+#define CTA_FILTER_FLAG_CTA_PROTO_ICMP_ID (1 << 8)
+#define CTA_FILTER_FLAG_CTA_PROTO_ICMPV6_TYPE (1 << 9)
+#define CTA_FILTER_FLAG_CTA_PROTO_ICMPV6_CODE (1 << 10)
+#define CTA_FILTER_FLAG_CTA_PROTO_ICMPV6_ID (1 << 11)
+
#ifdef __cplusplus
}
#endif
diff --git a/src/conntrack/api.c b/src/conntrack/api.c
index 78d7d61..2efb175 100644
--- a/src/conntrack/api.c
+++ b/src/conntrack/api.c
@@ -307,7 +307,7 @@ int nfct_callback_register2(struct nfct_handle *h,
assert(h != NULL);
- container = calloc(sizeof(struct __data_container), 1);
+ container = calloc(1, sizeof(struct __data_container));
if (container == NULL)
return -1;
@@ -779,6 +779,8 @@ int nfct_build_conntrack(struct nfnl_subsys_handle *ssh,
assert(req != NULL);
assert(ct != NULL);
+ memset(req, 0, size);
+
return __build_conntrack(ssh, req, size, type, flags, ct);
}
@@ -812,7 +814,7 @@ __build_query_ct(struct nfnl_subsys_handle *ssh,
assert(data != NULL);
assert(req != NULL);
- memset(req, 0, size);
+ memset(buffer, 0, size);
switch(qt) {
case NFCT_Q_CREATE:
@@ -831,6 +833,11 @@ __build_query_ct(struct nfnl_subsys_handle *ssh,
nfct_fill_hdr(req, IPCTNL_MSG_CT_DELETE, NLM_F_ACK, *family,
NFNETLINK_V0);
break;
+ case NFCT_Q_FLUSH_FILTER:
+ nfct_fill_hdr(req, IPCTNL_MSG_CT_DELETE, NLM_F_ACK, *family, 1);
+ if (__build_filter_flush(req, size, data) < 0)
+ return -1;
+ break;
case NFCT_Q_DUMP:
nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, *family,
NFNETLINK_V0);
@@ -845,12 +852,14 @@ __build_query_ct(struct nfnl_subsys_handle *ssh,
case NFCT_Q_DUMP_FILTER:
nfct_fill_hdr(req, IPCTNL_MSG_CT_GET, NLM_F_DUMP, AF_UNSPEC,
NFNETLINK_V0);
- __build_filter_dump(req, size, data);
+ if (__build_filter_dump(req, size, data) < 0)
+ return -1;
break;
case NFCT_Q_DUMP_FILTER_RESET:
nfct_fill_hdr(req, IPCTNL_MSG_CT_GET_CTRZERO, NLM_F_DUMP,
AF_UNSPEC, NFNETLINK_V0);
- __build_filter_dump(req, size, data);
+ if (__build_filter_dump(req, size, data) < 0)
+ return -1;
break;
default:
errno = ENOTSUP;
@@ -1356,7 +1365,7 @@ void nfct_copy_attr(struct nf_conntrack *ct1,
*/
struct nfct_filter *nfct_filter_create(void)
{
- return calloc(sizeof(struct nfct_filter), 1);
+ return calloc(1, sizeof(struct nfct_filter));
}
/**
@@ -1495,7 +1504,7 @@ int nfct_filter_detach(int fd)
*/
struct nfct_filter_dump *nfct_filter_dump_create(void)
{
- return calloc(sizeof(struct nfct_filter_dump), 1);
+ return calloc(1, sizeof(struct nfct_filter_dump));
}
/**
@@ -1547,6 +1556,19 @@ void nfct_filter_dump_set_attr_u8(struct nfct_filter_dump *filter_dump,
}
/**
+ * nfct_filter_dump_attr_set_u16 - set u16 dump filter attribute
+ * \param filter dump filter object that we want to modify
+ * \param type filter attribute type
+ * \param value value of the filter attribute using unsigned int (32 bits).
+ */
+void nfct_filter_dump_set_attr_u16(struct nfct_filter_dump *filter_dump,
+ const enum nfct_filter_dump_attr type,
+ uint16_t value)
+{
+ nfct_filter_dump_set_attr(filter_dump, type, &value);
+}
+
+/**
* @}
*/
diff --git a/src/conntrack/bsf.c b/src/conntrack/bsf.c
index 1549815..48fd4fa 100644
--- a/src/conntrack/bsf.c
+++ b/src/conntrack/bsf.c
@@ -9,6 +9,7 @@
#include "internal/internal.h"
#include "internal/stack.h"
+#include <endian.h>
#include <linux/filter.h>
#include <stddef.h> /* offsetof */
@@ -162,7 +163,7 @@ struct jump {
static int
nfct_bsf_cmp_k_stack(struct sock_filter *this, int k,
- int jump_true, int pos, struct stack *s)
+ int jump_true, int pos, struct stack *s)
{
struct sock_filter __code = {
.code = BPF_JMP|BPF_JEQ|BPF_K,
@@ -301,10 +302,14 @@ bsf_cmp_subsys(struct sock_filter *this, int pos, uint8_t subsys)
[1] = {
/* A = skb->data[X+k:B] (subsys_id) */
.code = BPF_LD|BPF_B|BPF_IND,
+#if BYTE_ORDER == BIG_ENDIAN
+ .k = 0,
+#else
.k = sizeof(uint8_t),
+#endif
},
[2] = {
- /* A == subsys ? jump +1 : accept */
+ /* A == subsys ? jump + 1 : accept */
.code = BPF_JMP|BPF_JEQ|BPF_K,
.k = subsys,
.jt = 1,
@@ -635,8 +640,8 @@ bsf_add_addr_ipv6_filter(const struct nfct_filter *f,
j);
if (k < 3) {
j += nfct_bsf_cmp_k_stack_jf(this, ip,
- jf - j - 1,
- j, s);
+ (3 - k) * 3 + 1,
+ j, s);
} else {
/* last word: jump if true */
j += nfct_bsf_cmp_k_stack(this, ip, jf - j,
@@ -650,7 +655,7 @@ bsf_add_addr_ipv6_filter(const struct nfct_filter *f,
this[jmp.line].jt += jmp.jt + j;
}
if (jmp.jf) {
- this[jmp.line].jf += jmp.jf + j;
+ this[jmp.line].jf += jmp.jf;
}
}
@@ -778,7 +783,7 @@ int __setup_netlink_socket_filter(int fd, struct nfct_filter *f)
show_filter(bsf, from, j, "---- final verdict ----");
from = j;
- sf.len = (sizeof(struct sock_filter) * j) / sizeof(bsf[0]);
+ sf.len = j;
sf.filter = bsf;
return setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &sf, sizeof(sf));
diff --git a/src/conntrack/build.c b/src/conntrack/build.c
index b5a7061..f80cfc1 100644
--- a/src/conntrack/build.c
+++ b/src/conntrack/build.c
@@ -27,8 +27,6 @@ int __build_conntrack(struct nfnl_subsys_handle *ssh,
return -1;
}
- memset(req, 0, size);
-
buf = (char *)&req->nlh;
nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8) | type;
diff --git a/src/conntrack/build_mnl.c b/src/conntrack/build_mnl.c
index d9ad268..e563c4e 100644
--- a/src/conntrack/build_mnl.c
+++ b/src/conntrack/build_mnl.c
@@ -73,8 +73,7 @@ nfct_build_tuple_proto(struct nlmsghdr *nlh, const struct __nfct_tuple *t)
mnl_attr_put_u16(nlh, CTA_PROTO_ICMPV6_ID, t->l4src.icmp.id);
break;
default:
- mnl_attr_nest_cancel(nlh, nest);
- return -1;
+ break;
}
mnl_attr_nest_end(nlh, nest);
return 0;
@@ -496,10 +495,7 @@ nfct_nlmsg_build(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
test_bit(ATTR_REPL_PORT_DST, ct->head.set) ||
test_bit(ATTR_REPL_L3PROTO, ct->head.set) ||
test_bit(ATTR_REPL_L4PROTO, ct->head.set) ||
- test_bit(ATTR_REPL_ZONE, ct->head.set) ||
- test_bit(ATTR_ICMP_TYPE, ct->head.set) ||
- test_bit(ATTR_ICMP_CODE, ct->head.set) ||
- test_bit(ATTR_ICMP_ID, ct->head.set)) {
+ test_bit(ATTR_REPL_ZONE, ct->head.set)) {
const struct __nfct_tuple *t = &ct->repl;
struct nlattr *nest;
@@ -598,3 +594,101 @@ nfct_nlmsg_build(struct nlmsghdr *nlh, const struct nf_conntrack *ct)
return 0;
}
+
+static uint32_t get_flags_from_ct(const struct nf_conntrack *ct, int family)
+{
+ uint32_t tuple_flags = 0;
+
+ if (family == AF_INET) {
+ if (test_bit(ATTR_ORIG_IPV4_SRC, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_IP_SRC;
+ if (test_bit(ATTR_ORIG_IPV4_DST, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_IP_DST;
+
+ if (test_bit(ATTR_ICMP_TYPE, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_ICMP_TYPE;
+ if (test_bit(ATTR_ICMP_CODE, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_ICMP_CODE;
+ if (test_bit(ATTR_ICMP_ID, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_ICMP_ID;
+ } else if (family == AF_INET6) {
+ if (test_bit(ATTR_ORIG_IPV6_SRC, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_IP_SRC;
+ if (test_bit(ATTR_ORIG_IPV6_DST, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_IP_DST;
+
+ if (test_bit(ATTR_ICMP_TYPE, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_ICMPV6_TYPE;
+ if (test_bit(ATTR_ICMP_CODE, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_ICMPV6_CODE;
+ if (test_bit(ATTR_ICMP_ID, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_ICMPV6_ID;
+ }
+
+ if (test_bit(ATTR_ORIG_ZONE, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_TUPLE_ZONE;
+
+ if (test_bit(ATTR_ORIG_L4PROTO, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_NUM;
+ if (test_bit(ATTR_ORIG_PORT_SRC, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_SRC_PORT;
+ if (test_bit(ATTR_ORIG_PORT_DST, ct->head.set))
+ tuple_flags |= CTA_FILTER_FLAG_CTA_PROTO_DST_PORT;
+
+ return tuple_flags;
+}
+
+int nfct_nlmsg_build_filter(struct nlmsghdr *nlh,
+ const struct nfct_filter_dump *filter_dump)
+{
+ struct nfgenmsg *nfg;
+
+ if (filter_dump->set & (1 << NFCT_FILTER_DUMP_MARK)) {
+ mnl_attr_put_u32(nlh, CTA_MARK, htonl(filter_dump->mark.val));
+ mnl_attr_put_u32(nlh, CTA_MARK_MASK, htonl(filter_dump->mark.mask));
+ }
+ if (filter_dump->set & (1 << NFCT_FILTER_DUMP_L3NUM)) {
+ nfg = mnl_nlmsg_get_payload(nlh);
+ nfg->nfgen_family = filter_dump->l3num;
+ }
+ if (filter_dump->set & (1 << NFCT_FILTER_DUMP_STATUS)) {
+ mnl_attr_put_u32(nlh, CTA_STATUS, htonl(filter_dump->status.val));
+ mnl_attr_put_u32(nlh, CTA_STATUS_MASK,
+ htonl(filter_dump->status.mask));
+ }
+ if (filter_dump->set & (1 << NFCT_FILTER_DUMP_ZONE)) {
+ mnl_attr_put_u16(nlh, CTA_ZONE, htons(filter_dump->zone));
+ }
+ if (filter_dump->set & (1 << NFCT_FILTER_DUMP_TUPLE)) {
+ const struct nf_conntrack *ct = &filter_dump->ct;
+ struct nlattr *nest;
+ int ret;
+
+ ret = nfct_nlmsg_build(nlh, ct);
+ if (ret == -1)
+ return -1;
+
+ nest = mnl_attr_nest_start(nlh, CTA_FILTER);
+ if (nest == NULL)
+ return -1;
+
+ nfg = mnl_nlmsg_get_payload(nlh);
+
+ if (test_bit(ATTR_ORIG_L3PROTO, ct->head.set)) {
+ if (filter_dump->set & (1 << NFCT_FILTER_DUMP_L3NUM) &&
+ filter_dump->l3num != ct->head.orig.l3protonum) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ nfg->nfgen_family = ct->head.orig.l3protonum;
+ }
+
+ mnl_attr_put_u32(nlh, CTA_FILTER_ORIG_FLAGS,
+ get_flags_from_ct(&filter_dump->ct,
+ nfg->nfgen_family));
+ mnl_attr_put_u32(nlh, CTA_FILTER_REPLY_FLAGS, 0);
+ mnl_attr_nest_end(nlh, nest);
+ }
+ return 0;
+}
diff --git a/src/conntrack/filter.c b/src/conntrack/filter.c
index 4cbc116..57b2294 100644
--- a/src/conntrack/filter.c
+++ b/src/conntrack/filter.c
@@ -11,18 +11,31 @@
static void filter_attr_l4proto(struct nfct_filter *filter, const void *value)
{
+ int protonum;
+
if (filter->l4proto_len >= __FILTER_L4PROTO_MAX)
return;
- set_bit(*((int *) value), filter->l4proto_map);
+ protonum = *(int *)value;
+ if (protonum >= IPPROTO_MAX)
+ return;
+
+ set_bit(protonum, filter->l4proto_map);
filter->l4proto_len++;
}
-static void
+#ifndef BITS_PER_BYTE
+#define BITS_PER_BYTE 8
+#endif
+
+static void
filter_attr_l4proto_state(struct nfct_filter *filter, const void *value)
{
const struct nfct_filter_proto *this = value;
+ if (this->state >= sizeof(filter->l4proto_state[0].map) * BITS_PER_BYTE)
+ return;
+
set_bit_u16(this->state, &filter->l4proto_state[this->proto].map);
filter->l4proto_state[this->proto].len++;
}
diff --git a/src/conntrack/filter_dump.c b/src/conntrack/filter_dump.c
index 158b4cb..fd2d002 100644
--- a/src/conntrack/filter_dump.c
+++ b/src/conntrack/filter_dump.c
@@ -8,6 +8,7 @@
*/
#include "internal/internal.h"
+#include <libmnl/libmnl.h>
static void
set_filter_dump_attr_mark(struct nfct_filter_dump *filter_dump,
@@ -20,28 +21,56 @@ set_filter_dump_attr_mark(struct nfct_filter_dump *filter_dump,
}
static void
+set_filter_dump_attr_status(struct nfct_filter_dump *filter_dump,
+ const void *value)
+{
+ const struct nfct_filter_dump_mark *this = value;
+
+ filter_dump->status.val = this->val;
+ filter_dump->status.mask = this->mask;
+}
+
+static void
set_filter_dump_attr_family(struct nfct_filter_dump *filter_dump,
const void *value)
{
filter_dump->l3num = *((uint8_t *)value);
}
+static void
+set_filter_dump_attr_zone(struct nfct_filter_dump *filter_dump,
+ const void *value)
+{
+ filter_dump->zone = *((uint16_t *)value);
+}
+
+static void
+set_filter_dump_attr_tuple(struct nfct_filter_dump *filter_dump,
+ const void *value)
+{
+ memcpy(&filter_dump->ct, value, sizeof(struct nf_conntrack));
+}
+
const set_filter_dump_attr set_filter_dump_attr_array[NFCT_FILTER_DUMP_MAX] = {
[NFCT_FILTER_DUMP_MARK] = set_filter_dump_attr_mark,
[NFCT_FILTER_DUMP_L3NUM] = set_filter_dump_attr_family,
+ [NFCT_FILTER_DUMP_STATUS] = set_filter_dump_attr_status,
+ [NFCT_FILTER_DUMP_ZONE] = set_filter_dump_attr_zone,
+ [NFCT_FILTER_DUMP_TUPLE] = set_filter_dump_attr_tuple,
};
-void __build_filter_dump(struct nfnlhdr *req, size_t size,
- const struct nfct_filter_dump *filter_dump)
+int __build_filter_dump(struct nfnlhdr *req, size_t size,
+ const struct nfct_filter_dump *filter_dump)
{
- if (filter_dump->set & (1 << NFCT_FILTER_DUMP_MARK)) {
- nfnl_addattr32(&req->nlh, size, CTA_MARK,
- htonl(filter_dump->mark.val));
- nfnl_addattr32(&req->nlh, size, CTA_MARK_MASK,
- htonl(filter_dump->mark.mask));
- }
- if (filter_dump->set & (1 << NFCT_FILTER_DUMP_L3NUM)) {
- struct nfgenmsg *nfg = NLMSG_DATA(&req->nlh);
- nfg->nfgen_family = filter_dump->l3num;
+ return nfct_nlmsg_build_filter(&req->nlh, filter_dump);
+}
+
+int __build_filter_flush(struct nfnlhdr *req, size_t size,
+ const struct nfct_filter_dump *filter_dump)
+{
+ if (filter_dump->set & (1 << NFCT_FILTER_DUMP_TUPLE)) {
+ errno = ENOTSUP;
+ return -1;
}
+ return nfct_nlmsg_build_filter(&req->nlh, filter_dump);
}
diff --git a/src/conntrack/labels.c b/src/conntrack/labels.c
index ef85b6e..5f50194 100644
--- a/src/conntrack/labels.c
+++ b/src/conntrack/labels.c
@@ -268,7 +268,7 @@ struct nfct_labelmap *__labelmap_new(const char *name)
if (added) {
map->namecount = maxbit + 1;
- map->bit_to_name = calloc(sizeof(char *), map->namecount);
+ map->bit_to_name = calloc(map->namecount, sizeof(char *));
if (!map->bit_to_name)
goto err;
make_name_table(map);
diff --git a/src/conntrack/proto.c b/src/conntrack/proto.c
index ba79b9b..03b37c0 100644
--- a/src/conntrack/proto.c
+++ b/src/conntrack/proto.c
@@ -15,8 +15,8 @@ static const uint8_t invmap_icmp[] = {
static const uint8_t invmap_icmpv6[] = {
[ICMPV6_ECHO_REQUEST - 128] = ICMPV6_ECHO_REPLY + 1,
[ICMPV6_ECHO_REPLY - 128] = ICMPV6_ECHO_REQUEST + 1,
- [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_QUERY + 1,
- [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_REPLY + 1
+ [ICMPV6_NI_QUERY - 128] = ICMPV6_NI_REPLY + 1,
+ [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_QUERY + 1
};
uint8_t __icmp_reply_type(uint8_t type)
diff --git a/src/conntrack/snprintf.c b/src/conntrack/snprintf.c
index eb26af4..82ca4e7 100644
--- a/src/conntrack/snprintf.c
+++ b/src/conntrack/snprintf.c
@@ -48,6 +48,8 @@ const char *const sctp_states[SCTP_CONNTRACK_MAX] = {
[SCTP_CONNTRACK_SHUTDOWN_SENT] = "SHUTDOWN_SENT",
[SCTP_CONNTRACK_SHUTDOWN_RECD] = "SHUTDOWN_RECD",
[SCTP_CONNTRACK_SHUTDOWN_ACK_SENT] = "SHUTDOWN_ACK_SENT",
+ [SCTP_CONNTRACK_HEARTBEAT_SENT] = "HEARTBEAT_SENT",
+ [SCTP_CONNTRACK_HEARTBEAT_ACKED] = "HEARTBEAT_ACKED",
};
const char *const dccp_states[DCCP_CONNTRACK_MAX] = {
diff --git a/src/conntrack/snprintf_default.c b/src/conntrack/snprintf_default.c
index 64a05aa..4fe2a2d 100644
--- a/src/conntrack/snprintf_default.c
+++ b/src/conntrack/snprintf_default.c
@@ -15,6 +15,9 @@ static int __snprintf_l3protocol(char *buf,
{
uint8_t num = ct->head.orig.l3protonum;
+ if (!test_bit(ATTR_ORIG_L3PROTO, ct->head.set))
+ return -1;
+
return snprintf(buf, len, "%-8s %u ", __l3proto2str(num), num);
}
@@ -24,6 +27,9 @@ int __snprintf_protocol(char *buf,
{
uint8_t num = ct->head.orig.protonum;
+ if (!test_bit(ATTR_ORIG_L4PROTO, ct->head.set))
+ return -1;
+
return snprintf(buf, len, "%-8s %u ", __proto2str(num), num);
}
@@ -38,30 +44,48 @@ static int __snprintf_protoinfo(char *buf,
unsigned int len,
const struct nf_conntrack *ct)
{
- return snprintf(buf, len, "%s ",
- ct->protoinfo.tcp.state < TCP_CONNTRACK_MAX ?
- states[ct->protoinfo.tcp.state] :
- states[TCP_CONNTRACK_NONE]);
+ uint8_t state = ct->protoinfo.tcp.state;
+ const char *str = NULL;
+
+ if (state < ARRAY_SIZE(states))
+ str = states[state];
+
+ if (str == NULL)
+ str = states[TCP_CONNTRACK_NONE];
+
+ return snprintf(buf, len, "%s ", str);
}
static int __snprintf_protoinfo_sctp(char *buf,
unsigned int len,
const struct nf_conntrack *ct)
{
- return snprintf(buf, len, "%s ",
- ct->protoinfo.sctp.state < SCTP_CONNTRACK_MAX ?
- sctp_states[ct->protoinfo.sctp.state] :
- sctp_states[SCTP_CONNTRACK_NONE]);
+ uint8_t state = ct->protoinfo.sctp.state;
+ const char *str = NULL;
+
+ if (state < ARRAY_SIZE(sctp_states))
+ str = sctp_states[state];
+
+ if (str == NULL)
+ str = sctp_states[SCTP_CONNTRACK_NONE];
+
+ return snprintf(buf, len, "%s ", str);
}
static int __snprintf_protoinfo_dccp(char *buf,
unsigned int len,
const struct nf_conntrack *ct)
{
- return snprintf(buf, len, "%s ",
- ct->protoinfo.dccp.state < DCCP_CONNTRACK_MAX ?
- sctp_states[ct->protoinfo.dccp.state] :
- sctp_states[DCCP_CONNTRACK_NONE]);
+ const char *str = NULL;
+ uint8_t state = ct->protoinfo.dccp.state;
+
+ if (state < ARRAY_SIZE(dccp_states))
+ str = dccp_states[state];
+
+ if (str == NULL)
+ str = dccp_states[DCCP_CONNTRACK_NONE];
+
+ return snprintf(buf, len, "%s ", str);
}
static int __snprintf_address_ipv4(char *buf,
@@ -134,7 +158,7 @@ int __snprintf_address(char *buf,
return size;
}
-int __snprintf_proto(char *buf,
+int __snprintf_proto(char *buf,
unsigned int len,
const struct __nfct_tuple *tuple)
{
@@ -197,7 +221,7 @@ static int __snprintf_status_not_seen_reply(char *buf,
const struct nf_conntrack *ct)
{
int size = 0;
-
+
if (!(ct->status & IPS_SEEN_REPLY))
size = snprintf(buf, len, "[UNREPLIED] ");
@@ -345,7 +369,7 @@ __snprintf_clabels(char *buf, unsigned int len,
return size;
}
-int __snprintf_conntrack_default(char *buf,
+int __snprintf_conntrack_default(char *buf,
unsigned int len,
const struct nf_conntrack *ct,
unsigned int msg_type,
diff --git a/src/conntrack/stack.c b/src/conntrack/stack.c
index ac3f437..66ccf1f 100644
--- a/src/conntrack/stack.c
+++ b/src/conntrack/stack.c
@@ -25,11 +25,11 @@ struct stack *stack_create(size_t elem_size, int max_elems)
{
struct stack *s;
- s = calloc(sizeof(struct stack), 1);
+ s = calloc(1, sizeof(struct stack));
if (s == NULL)
return NULL;
- s->data = calloc(elem_size * max_elems, 1);
+ s->data = calloc(max_elems, elem_size);
if (s->data == NULL) {
free(s);
return NULL;
diff --git a/src/expect/api.c b/src/expect/api.c
index 39cd092..b100c72 100644
--- a/src/expect/api.c
+++ b/src/expect/api.c
@@ -513,6 +513,8 @@ int nfexp_build_expect(struct nfnl_subsys_handle *ssh,
assert(req != NULL);
assert(exp != NULL);
+ memset(req, 0, size);
+
return __build_expect(ssh, req, size, type, flags, exp);
}
@@ -546,7 +548,7 @@ __build_query_exp(struct nfnl_subsys_handle *ssh,
assert(data != NULL);
assert(req != NULL);
- memset(req, 0, size);
+ memset(buffer, 0, size);
switch(qt) {
case NFCT_Q_CREATE:
diff --git a/src/expect/build.c b/src/expect/build.c
index 2e0f968..1807adc 100644
--- a/src/expect/build.c
+++ b/src/expect/build.c
@@ -29,8 +29,6 @@ int __build_expect(struct nfnl_subsys_handle *ssh,
else
return -1;
- memset(req, 0, size);
-
buf = (char *)&req->nlh;
nlh = mnl_nlmsg_put_header(buf);
nlh->nlmsg_type = (NFNL_SUBSYS_CTNETLINK_EXP << 8) | type;
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 20ebaf2..16fbe6a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -3,6 +3,10 @@ include $(top_srcdir)/Make_global.am
check_PROGRAMS = test_api test_filter test_connlabel ct_stress \
ct_events_reliable
+EXTRA_DIST = qa-connlabel.conf
+
+TESTS = test_api test_filter test_connlabel
+
test_api_SOURCES = test_api.c
test_api_LDADD = ../src/libnetfilter_conntrack.la
diff --git a/tests/test_connlabel.c b/tests/test_connlabel.c
index 99b1171..f6f222b 100644
--- a/tests/test_connlabel.c
+++ b/tests/test_connlabel.c
@@ -1,4 +1,5 @@
#include <assert.h>
+#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
@@ -60,6 +61,13 @@ int main(void)
l = nfct_labelmap_new("qa-connlabel.conf");
if (!l)
l = nfct_labelmap_new("tests/qa-connlabel.conf");
+ if (!l) {
+ char testconf[PATH_MAX];
+
+ snprintf(testconf, PATH_MAX,
+ "%s/qa-connlabel.conf", getenv("srcdir"));
+ l = nfct_labelmap_new(testconf);
+ }
assert(l);
puts("qa-connlabel.conf:");
dump_map(l);
diff --git a/utils/.gitignore b/utils/.gitignore
index 63dfcb2..c63fd8b 100644
--- a/utils/.gitignore
+++ b/utils/.gitignore
@@ -3,9 +3,11 @@
/conntrack_delete
/conntrack_dump
/conntrack_dump_filter
+/conntrack_dump_filter_tuple
/conntrack_events
/conntrack_filter
/conntrack_flush
+/conntrack_flush_filter
/conntrack_get
/conntrack_grp_create
/conntrack_master
diff --git a/utils/Makefile.am b/utils/Makefile.am
index 69bafe6..7e7aef4 100644
--- a/utils/Makefile.am
+++ b/utils/Makefile.am
@@ -9,6 +9,8 @@ check_PROGRAMS = expect_dump expect_create expect_get expect_delete \
conntrack_master conntrack_filter \
conntrack_grp_create \
conntrack_dump_filter \
+ conntrack_dump_filter_tuple \
+ conntrack_flush_filter \
ctexp_events
conntrack_grp_create_SOURCES = conntrack_grp_create.c
@@ -35,9 +37,15 @@ conntrack_dump_LDADD = ../src/libnetfilter_conntrack.la
conntrack_dump_filter_SOURCES = conntrack_dump_filter.c
conntrack_dump_filter_LDADD = ../src/libnetfilter_conntrack.la
+conntrack_dump_filter_tuple_SOURCES = conntrack_dump_filter_tuple.c
+conntrack_dump_filter_tuple_LDADD = ../src/libnetfilter_conntrack.la
+
conntrack_flush_SOURCES = conntrack_flush.c
conntrack_flush_LDADD = ../src/libnetfilter_conntrack.la
+conntrack_flush_filter_SOURCES = conntrack_flush_filter.c
+conntrack_flush_filter_LDADD = ../src/libnetfilter_conntrack.la
+
conntrack_events_SOURCES = conntrack_events.c
conntrack_events_LDADD = ../src/libnetfilter_conntrack.la
diff --git a/utils/conntrack_dump_filter.c b/utils/conntrack_dump_filter.c
index 41e3f0c..16492ac 100644
--- a/utils/conntrack_dump_filter.c
+++ b/utils/conntrack_dump_filter.c
@@ -40,6 +40,8 @@ int main(void)
&filter_dump_mark);
nfct_filter_dump_set_attr_u8(filter_dump, NFCT_FILTER_DUMP_L3NUM,
AF_INET);
+ nfct_filter_dump_set_attr_u16(filter_dump, NFCT_FILTER_DUMP_ZONE,
+ 123);
nfct_callback_register(h, NFCT_T_ALL, cb, NULL);
ret = nfct_query(h, NFCT_Q_DUMP_FILTER, filter_dump);
diff --git a/utils/conntrack_dump_filter_tuple.c b/utils/conntrack_dump_filter_tuple.c
new file mode 100644
index 0000000..44633da
--- /dev/null
+++ b/utils/conntrack_dump_filter_tuple.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <arpa/inet.h>
+
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+
+static int cb(const struct nlmsghdr *nlh,
+ enum nf_conntrack_msg_type type,
+ struct nf_conntrack *ct,
+ void *data)
+{
+ char buf[1024];
+
+ if (!(nlh->nlmsg_flags & NLM_F_DUMP_FILTERED))
+ {
+ fprintf(stderr, "No filtering in kernel, do filtering in userspace\n");
+ return NFCT_CB_FAILURE;
+ }
+
+ nfct_snprintf(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, NFCT_OF_SHOW_LAYER3 | NFCT_OF_TIMESTAMP);
+ printf("%s\n", buf);
+
+ return NFCT_CB_CONTINUE;
+}
+
+int main(void)
+{
+ int ret;
+ struct nfct_handle *h;
+
+ h = nfct_open(CONNTRACK, 0);
+ if (!h) {
+ perror("nfct_open");
+ return -1;
+ }
+ struct nfct_filter_dump *filter_dump = nfct_filter_dump_create();
+ if (filter_dump == NULL) {
+ perror("nfct_filter_dump_alloc");
+ return -1;
+ }
+
+ struct nf_conntrack *ct;
+ ct = nfct_new();
+ if (!ct) {
+ perror("nfct_new");
+ return 0;
+ }
+
+ nfct_set_attr_u8(ct, ATTR_ORIG_L3PROTO, AF_INET);
+ nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_ICMP);
+ nfct_set_attr_u32(ct, ATTR_ORIG_IPV4_DST, inet_addr("203.0.113.55"));
+ nfct_filter_dump_set_attr(filter_dump, NFCT_FILTER_DUMP_TUPLE, ct);
+
+ nfct_callback_register2(h, NFCT_T_ALL, cb, NULL);
+ ret = nfct_query(h, NFCT_Q_DUMP_FILTER, filter_dump);
+
+ nfct_filter_dump_destroy(filter_dump);
+
+ printf("TEST: get conntrack ");
+ if (ret == -1)
+ printf("(%d)(%s)\n", ret, strerror(errno));
+ else
+ printf("(OK)\n");
+
+ nfct_close(h);
+
+ ret == -1 ? exit(EXIT_FAILURE) : exit(EXIT_SUCCESS);
+}
diff --git a/utils/conntrack_flush_filter.c b/utils/conntrack_flush_filter.c
new file mode 100644
index 0000000..6e8d93b
--- /dev/null
+++ b/utils/conntrack_flush_filter.c
@@ -0,0 +1,60 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <libnetfilter_conntrack/libnetfilter_conntrack.h>
+
+static int cb(enum nf_conntrack_msg_type type,
+ struct nf_conntrack *ct,
+ void *data)
+{
+ char buf[1024];
+
+ nfct_snprintf(buf, sizeof(buf), ct, NFCT_T_UNKNOWN, NFCT_O_DEFAULT, NFCT_OF_SHOW_LAYER3 | NFCT_OF_TIMESTAMP);
+ printf("%s\n", buf);
+
+ return NFCT_CB_CONTINUE;
+}
+
+int main(void)
+{
+ int ret;
+ struct nfct_handle *h;
+
+ h = nfct_open(CONNTRACK, 0);
+ if (!h) {
+ perror("nfct_open");
+ return -1;
+ }
+ struct nfct_filter_dump *filter_dump = nfct_filter_dump_create();
+ if (filter_dump == NULL) {
+ perror("nfct_filter_dump_alloc");
+ return -1;
+ }
+ struct nfct_filter_dump_mark filter_dump_mark = {
+ .val = 1,
+ .mask = 0xffffffff,
+ };
+ nfct_filter_dump_set_attr(filter_dump, NFCT_FILTER_DUMP_MARK,
+ &filter_dump_mark);
+ nfct_filter_dump_set_attr_u8(filter_dump, NFCT_FILTER_DUMP_L3NUM,
+ AF_INET);
+ nfct_filter_dump_set_attr_u16(filter_dump, NFCT_FILTER_DUMP_ZONE,
+ 123);
+
+ nfct_callback_register(h, NFCT_T_ALL, cb, NULL);
+ ret = nfct_query(h, NFCT_Q_FLUSH_FILTER, filter_dump);
+
+ nfct_filter_dump_destroy(filter_dump);
+
+ printf("TEST: get conntrack ");
+ if (ret == -1)
+ printf("(%d)(%s)\n", ret, strerror(errno));
+ else
+ printf("(OK)\n");
+
+ nfct_close(h);
+
+ ret == -1 ? exit(EXIT_FAILURE) : exit(EXIT_SUCCESS);
+}