diff options
47 files changed, 701 insertions, 205 deletions
@@ -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 6940c38..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.7]) +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 bb44e12..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> @@ -27,6 +26,7 @@ #include "internal/types.h" #include "internal/extern.h" #include "internal/bitops.h" +#include "internal/proto.h" #ifndef IPPROTO_SCTP #define IPPROTO_SCTP 132 @@ -40,7 +40,11 @@ #define IPPROTO_DCCP 33 #endif +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) + #define BUFFER_SIZE(ret, size, len, offset) \ + if (ret < 0) \ + return -1; \ size += ret; \ if (ret > len) \ ret = len; \ 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 new file mode 100644 index 0000000..60a5f4e --- /dev/null +++ b/include/internal/proto.h @@ -0,0 +1,20 @@ +#ifndef _NFCT_PROTO_H_ +#define _NFCT_PROTO_H_ + +#include <stdint.h> +#include <netinet/in.h> +#include <linux/icmp.h> +#include <linux/icmpv6.h> + +#ifndef ICMPV6_NI_QUERY +#define ICMPV6_NI_QUERY 139 +#endif + +#ifndef ICMPV6_NI_REPLY +#define ICMPV6_NI_REPLY 140 +#endif + +uint8_t __icmp_reply_type(uint8_t type); +uint8_t __icmpv6_reply_type(uint8_t type); + +#endif 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_nf_conntrack_common.h b/include/libnetfilter_conntrack/linux_nf_conntrack_common.h index 21015c7..131ca25 100644 --- a/include/libnetfilter_conntrack/linux_nf_conntrack_common.h +++ b/include/libnetfilter_conntrack/linux_nf_conntrack_common.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef _NF_CONNTRACK_COMMON_H #define _NF_CONNTRACK_COMMON_H @@ -33,12 +34,14 @@ enum ip_conntrack_info { /* only for userspace compatibility */ #ifndef __KERNEL__ IP_CT_NEW_REPLY = IP_CT_NUMBER, +#else + IP_CT_UNTRACKED = 7, #endif }; #define NF_CT_STATE_INVALID_BIT (1 << 0) #define NF_CT_STATE_BIT(ctinfo) (1 << ((ctinfo) % IP_CT_IS_REPLY + 1)) -#define NF_CT_STATE_UNTRACKED_BIT (1 << (IP_CT_NUMBER + 1)) +#define NF_CT_STATE_UNTRACKED_BIT (1 << 6) /* Bitset representing status of connection. */ enum ip_conntrack_status { @@ -95,13 +98,40 @@ enum ip_conntrack_status { IPS_TEMPLATE_BIT = 11, IPS_TEMPLATE = (1 << IPS_TEMPLATE_BIT), - /* Conntrack is a fake untracked entry */ + /* Conntrack is a fake untracked entry. Obsolete and not used anymore */ IPS_UNTRACKED_BIT = 12, IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT), +#ifdef __KERNEL__ + /* Re-purposed for in-kernel use: + * Tags a conntrack entry that clashed with an existing entry + * on insert. + */ + IPS_NAT_CLASH_BIT = IPS_UNTRACKED_BIT, + IPS_NAT_CLASH = IPS_UNTRACKED, +#endif + /* Conntrack got a helper explicitly attached via CT target. */ IPS_HELPER_BIT = 13, IPS_HELPER = (1 << IPS_HELPER_BIT), + + /* Conntrack has been offloaded to flow table. */ + IPS_OFFLOAD_BIT = 14, + IPS_OFFLOAD = (1 << IPS_OFFLOAD_BIT), + + /* Conntrack has been offloaded to hardware. */ + IPS_HW_OFFLOAD_BIT = 15, + IPS_HW_OFFLOAD = (1 << IPS_HW_OFFLOAD_BIT), + + /* Be careful here, modifying these bits can make things messy, + * so don't let users modify them directly. + */ + IPS_UNCHANGEABLE_MASK = (IPS_NAT_DONE_MASK | IPS_NAT_MASK | + IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING | + IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_UNTRACKED | + IPS_OFFLOAD | IPS_HW_OFFLOAD), + + __IPS_MAX_BIT = 16, }; /* Connection tracking event types */ @@ -118,6 +148,10 @@ enum ip_conntrack_events { IPCT_NATSEQADJ = IPCT_SEQADJ, IPCT_SECMARK, /* new security mark has been set */ IPCT_LABEL, /* new connlabel has been set */ + IPCT_SYNPROXY, /* synproxy has been set */ +#ifdef __KERNEL__ + __IPCT_MAX +#endif }; enum ip_conntrack_expect_events { 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/libnetfilter_conntrack.pc.in b/libnetfilter_conntrack.pc.in index 857f993..fbd7132 100644 --- a/libnetfilter_conntrack.pc.in +++ b/libnetfilter_conntrack.pc.in @@ -12,5 +12,5 @@ Version: @VERSION@ Requires: libnfnetlink Conflicts: Libs: -L${libdir} -lnetfilter_conntrack -Libs.private: @LIBNFNETLINK_LIBS@ +Libs.private: @LIBNFNETLINK_LIBS@ @LIBMNL_LIBS@ Cflags: -I${includedir} diff --git a/src/conntrack/Makefile.am b/src/conntrack/Makefile.am index 602ed33..1fbf176 100644 --- a/src/conntrack/Makefile.am +++ b/src/conntrack/Makefile.am @@ -14,4 +14,5 @@ libnfconntrack_la_SOURCES = api.c \ copy.c \ filter.c bsf.c filter_dump.c \ grp.c grp_getter.c grp_setter.c \ - stack.c + stack.c \ + proto.c diff --git a/src/conntrack/api.c b/src/conntrack/api.c index ffa5216..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; @@ -1099,9 +1108,9 @@ int nfct_catch(struct nfct_handle *h) * print the message just after you receive the destroy event. If you want * more accurate timestamping, use NFCT_OF_TIMESTAMP. * - * This function returns the size of the information that _would_ have been - * written to the buffer, even if there was no room for it. Thus, the - * behaviour is similar to snprintf. + * On error, -1 is returned and errno is set appropiately. Otherwise the + * size of what _would_ be written is returned, even if the size of the + * buffer is insufficient. This behaviour is similar to snprintf. */ int nfct_snprintf(char *buf, unsigned int size, @@ -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/copy.c b/src/conntrack/copy.c index eca202e..402f994 100644 --- a/src/conntrack/copy.c +++ b/src/conntrack/copy.c @@ -427,8 +427,8 @@ static void copy_attr_repl_off_aft(struct nf_conntrack *dest, static void copy_attr_helper_name(struct nf_conntrack *dest, const struct nf_conntrack *orig) { - strncpy(dest->helper_name, orig->helper_name, NFCT_HELPER_NAME_MAX); - dest->helper_name[NFCT_HELPER_NAME_MAX-1] = '\0'; + snprintf(dest->helper_name, NFCT_HELPER_NAME_MAX, "%s", + orig->helper_name); } static void copy_attr_zone(struct nf_conntrack *dest, 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/grp_setter.c b/src/conntrack/grp_setter.c index fccf578..9bcf19e 100644 --- a/src/conntrack/grp_setter.c +++ b/src/conntrack/grp_setter.c @@ -8,34 +8,6 @@ */ #include "internal/internal.h" -#include <linux/icmp.h> -#include <linux/icmpv6.h> - -static const uint8_t invmap_icmp[] = { - [ICMP_ECHO] = ICMP_ECHOREPLY + 1, - [ICMP_ECHOREPLY] = ICMP_ECHO + 1, - [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, - [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1, - [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1, - [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1, - [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1, - [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1 -}; - -#ifndef ICMPV6_NI_QUERY -#define ICMPV6_NI_QUERY 139 -#endif - -#ifndef ICMPV6_NI_REPLY -#define ICMPV6_NI_REPLY 140 -#endif - -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 -}; static void set_attr_grp_orig_ipv4(struct nf_conntrack *ct, const void *value) { @@ -85,18 +57,18 @@ static void set_attr_grp_repl_port(struct nf_conntrack *ct, const void *value) static void set_attr_grp_icmp(struct nf_conntrack *ct, const void *value) { - uint8_t rtype; const struct nfct_attr_grp_icmp *this = value; + uint8_t rtype = 0; ct->head.orig.l4dst.icmp.type = this->type; switch(ct->head.orig.l3protonum) { case AF_INET: - rtype = invmap_icmp[this->type]; + rtype = __icmp_reply_type(this->type); break; case AF_INET6: - rtype = invmap_icmpv6[this->type - 128]; + rtype = __icmpv6_reply_type(this->type); break; default: 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/parse_mnl.c b/src/conntrack/parse_mnl.c index 515deff..3cbfc6a 100644 --- a/src/conntrack/parse_mnl.c +++ b/src/conntrack/parse_mnl.c @@ -690,9 +690,8 @@ nfct_parse_helper(const struct nlattr *attr, struct nf_conntrack *ct) if (!tb[CTA_HELP_NAME]) return 0; - strncpy(ct->helper_name, mnl_attr_get_str(tb[CTA_HELP_NAME]), - NFCT_HELPER_NAME_MAX); - ct->helper_name[NFCT_HELPER_NAME_MAX-1] = '\0'; + snprintf(ct->helper_name, NFCT_HELPER_NAME_MAX, "%s", + mnl_attr_get_str(tb[CTA_HELP_NAME])); set_bit(ATTR_HELPER_NAME, ct->head.set); if (!tb[CTA_HELP_INFO]) diff --git a/src/conntrack/proto.c b/src/conntrack/proto.c new file mode 100644 index 0000000..03b37c0 --- /dev/null +++ b/src/conntrack/proto.c @@ -0,0 +1,36 @@ +#include <internal/proto.h> +#include <internal/internal.h> + +static const uint8_t invmap_icmp[] = { + [ICMP_ECHO] = ICMP_ECHOREPLY + 1, + [ICMP_ECHOREPLY] = ICMP_ECHO + 1, + [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, + [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1, + [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1, + [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1, + [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1, + [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1 +}; + +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_REPLY + 1, + [ICMPV6_NI_REPLY - 128] = ICMPV6_NI_QUERY + 1 +}; + +uint8_t __icmp_reply_type(uint8_t type) +{ + if (type < ARRAY_SIZE(invmap_icmp)) + return invmap_icmp[type]; + + return 0; +} + +uint8_t __icmpv6_reply_type(uint8_t type) +{ + if (type - 128 < ARRAY_SIZE(invmap_icmpv6)) + return invmap_icmpv6[type - 128]; + + return 0; +} diff --git a/src/conntrack/setter.c b/src/conntrack/setter.c index 7b96936..cee81f1 100644 --- a/src/conntrack/setter.c +++ b/src/conntrack/setter.c @@ -8,34 +8,6 @@ */ #include "internal/internal.h" -#include <linux/icmp.h> -#include <linux/icmpv6.h> - -static const uint8_t invmap_icmp[] = { - [ICMP_ECHO] = ICMP_ECHOREPLY + 1, - [ICMP_ECHOREPLY] = ICMP_ECHO + 1, - [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, - [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1, - [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1, - [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1, - [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1, - [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1 -}; - -#ifndef ICMPV6_NI_QUERY -#define ICMPV6_NI_QUERY 139 -#endif - -#ifndef ICMPV6_NI_REPLY -#define ICMPV6_NI_REPLY 140 -#endif - -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 -}; static void set_attr_orig_ipv4_src(struct nf_conntrack *ct, const void *value, size_t len) @@ -124,17 +96,18 @@ set_attr_repl_zone(struct nf_conntrack *ct, const void *value, size_t len) static void set_attr_icmp_type(struct nf_conntrack *ct, const void *value, size_t len) { - uint8_t rtype; + uint8_t type = *((uint8_t *) value); + uint8_t rtype = 0; - ct->head.orig.l4dst.icmp.type = *((uint8_t *) value); + ct->head.orig.l4dst.icmp.type = type; switch(ct->head.orig.l3protonum) { case AF_INET: - rtype = invmap_icmp[*((uint8_t *) value)]; + rtype = __icmp_reply_type(type); break; case AF_INET6: - rtype = invmap_icmpv6[*((uint8_t *) value) - 128]; + rtype = __icmpv6_reply_type(type); break; default: @@ -389,8 +362,7 @@ set_attr_repl_off_aft(struct nf_conntrack *ct, const void *value, size_t len) static void set_attr_helper_name(struct nf_conntrack *ct, const void *value, size_t len) { - strncpy(ct->helper_name, value, NFCT_HELPER_NAME_MAX); - ct->helper_name[NFCT_HELPER_NAME_MAX-1] = '\0'; + snprintf(ct->helper_name, NFCT_HELPER_NAME_MAX, "%s", (char *)value); } static void diff --git a/src/conntrack/snprintf.c b/src/conntrack/snprintf.c index 17ad885..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] = { @@ -85,6 +87,9 @@ int __snprintf_conntrack(char *buf, return -1; } + if (size < 0) + return size; + /* NULL terminated string */ buf[size+1 > len ? len-1 : size] = '\0'; diff --git a/src/conntrack/snprintf_default.c b/src/conntrack/snprintf_default.c index 06466b1..4fe2a2d 100644 --- a/src/conntrack/snprintf_default.c +++ b/src/conntrack/snprintf_default.c @@ -13,20 +13,24 @@ static int __snprintf_l3protocol(char *buf, unsigned int len, const struct nf_conntrack *ct) { - return (snprintf(buf, len, "%-8s %u ", - l3proto2str[ct->head.orig.l3protonum] == NULL ? - "unknown" : l3proto2str[ct->head.orig.l3protonum], - ct->head.orig.l3protonum)); + 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); } int __snprintf_protocol(char *buf, unsigned int len, const struct nf_conntrack *ct) { - return (snprintf(buf, len, "%-8s %u ", - proto2str[ct->head.orig.protonum] == NULL ? - "unknown" : proto2str[ct->head.orig.protonum], - ct->head.orig.protonum)); + 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); } static int __snprintf_timeout(char *buf, @@ -40,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, @@ -108,7 +130,7 @@ static int __snprintf_address_ipv6(char *buf, if (!inet_ntop(AF_INET6, &dst, tmp, sizeof(tmp))) return -1; - ret = snprintf(buf+offset, len-size, "%s=%s ", dst_tag, tmp); + ret = snprintf(buf + offset, len, "%s=%s ", dst_tag, tmp); BUFFER_SIZE(ret, size, len, offset); return size; @@ -136,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) { @@ -183,8 +205,12 @@ static int __snprintf_status_assured(char *buf, const struct nf_conntrack *ct) { int size = 0; - - if (ct->status & IPS_ASSURED) + + if (ct->status & IPS_HW_OFFLOAD) + size = snprintf(buf, len, "[HW_OFFLOAD] "); + else if (ct->status & IPS_OFFLOAD) + size = snprintf(buf, len, "[OFFLOAD] "); + else if (ct->status & IPS_ASSURED) size = snprintf(buf, len, "[ASSURED] "); return size; @@ -195,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] "); @@ -343,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/snprintf_xml.c b/src/conntrack/snprintf_xml.c index c3a836a..e557df2 100644 --- a/src/conntrack/snprintf_xml.c +++ b/src/conntrack/snprintf_xml.c @@ -55,12 +55,28 @@ const char *__proto2str(uint8_t protonum) { - return proto2str[protonum] ? proto2str[protonum] : "unknown"; + const char *str = NULL; + + if (protonum < ARRAY_SIZE(proto2str)) + str = proto2str[protonum]; + + if (str == NULL) + str = "unknown"; + + return str; } const char *__l3proto2str(uint8_t protonum) { - return l3proto2str[protonum] ? l3proto2str[protonum] : "unknown"; + const char *str = NULL; + + if (protonum < ARRAY_SIZE(l3proto2str)) + str = l3proto2str[protonum]; + + if (str == NULL) + str = "unknown"; + + return str; } static int __snprintf_ipv4_xml(char *buf, 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 33099d8..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: @@ -795,8 +797,9 @@ int nfexp_catch(struct nfct_handle *h) * - NFEXP_O_LAYER: include layer 3 information in the output, this is * *only* required by NFEXP_O_DEFAULT. * - * On error, -1 is returned and errno is set appropiately. Otherwise, - * 0 is returned. + * On error, -1 is returned and errno is set appropiately. Otherwise the + * size of what _would_ be written is returned, even if the size of the + * buffer is insufficient. This behaviour is similar to snprintf. */ int nfexp_snprintf(char *buf, unsigned int size, 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/src/expect/parse_mnl.c b/src/expect/parse_mnl.c index e7bbc16..fb4bdb7 100644 --- a/src/expect/parse_mnl.c +++ b/src/expect/parse_mnl.c @@ -10,6 +10,7 @@ */ #include "internal/internal.h" +#include <assert.h> #include <libmnl/libmnl.h> static int nlmsg_parse_expection_attr_cb(const struct nlattr *attr, void *data) @@ -139,9 +140,8 @@ int nfexp_nlmsg_parse(const struct nlmsghdr *nlh, struct nf_expect *exp) set_bit(ATTR_EXP_FLAGS, exp->set); } if (tb[CTA_EXPECT_HELP_NAME]) { - strncpy(exp->helper_name, - mnl_attr_get_str(tb[CTA_EXPECT_HELP_NAME]), - NFCT_HELPER_NAME_MAX); + snprintf(exp->helper_name, NFCT_HELPER_NAME_MAX, "%s", + mnl_attr_get_str(tb[CTA_EXPECT_HELP_NAME])); set_bit(ATTR_EXP_HELPER_NAME, exp->set); } if (tb[CTA_EXPECT_CLASS]) { @@ -152,9 +152,11 @@ int nfexp_nlmsg_parse(const struct nlmsghdr *nlh, struct nf_expect *exp) nfexp_nlmsg_parse_nat(nfg, tb[CTA_EXPECT_NAT], exp); if (tb[CTA_EXPECT_FN]) { - strncpy(exp->expectfn, mnl_attr_get_payload(tb[CTA_EXPECT_FN]), - __NFCT_EXPECTFN_MAX); - exp->expectfn[__NFCT_EXPECTFN_MAX - 1] = '\0'; + int len = mnl_attr_get_payload_len(tb[CTA_EXPECT_FN]); + /* the kernel doesn't impose a max length on this str */ + assert(len <= __NFCT_EXPECTFN_MAX); + snprintf(exp->expectfn, __NFCT_EXPECTFN_MAX, "%s", + (char *)mnl_attr_get_payload(tb[CTA_EXPECT_FN])); set_bit(ATTR_EXP_FN, exp->set); } diff --git a/src/expect/setter.c b/src/expect/setter.c index 18c925a..c2ca412 100644 --- a/src/expect/setter.c +++ b/src/expect/setter.c @@ -46,8 +46,7 @@ static void set_exp_attr_class(struct nf_expect *exp, const void *value) static void set_exp_attr_helper_name(struct nf_expect *exp, const void *value) { - strncpy(exp->helper_name, value, NFCT_HELPER_NAME_MAX); - exp->helper_name[NFCT_HELPER_NAME_MAX-1] = '\0'; + snprintf(exp->helper_name, NFCT_HELPER_NAME_MAX, "%s", (char *)value); } static void set_exp_attr_nat_dir(struct nf_expect *exp, const void *value) @@ -62,8 +61,7 @@ static void set_exp_attr_nat_tuple(struct nf_expect *exp, const void *value) static void set_exp_attr_expectfn(struct nf_expect *exp, const void *value) { - strncpy(exp->expectfn, value, __NFCT_EXPECTFN_MAX); - exp->expectfn[__NFCT_EXPECTFN_MAX-1] = '\0'; + snprintf(exp->expectfn, __NFCT_EXPECTFN_MAX, "%s", (char *)value); } const set_exp_attr set_exp_attr_array[ATTR_EXP_MAX] = { diff --git a/src/expect/snprintf.c b/src/expect/snprintf.c index 3a104b5..8c2f3e4 100644 --- a/src/expect/snprintf.c +++ b/src/expect/snprintf.c @@ -30,6 +30,9 @@ int __snprintf_expect(char *buf, return -1; } + if (size < 0) + return size; + /* NULL terminated string */ buf[size+1 > len ? len-1 : size] = '\0'; 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); +} |