diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | include/internal/object.h | 12 | ||||
-rw-r--r-- | include/internal/prototypes.h | 3 | ||||
-rw-r--r-- | include/libnetfilter_conntrack/libnetfilter_conntrack.h | 6 | ||||
-rw-r--r-- | include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h | 13 | ||||
-rw-r--r-- | src/conntrack/api.c | 31 | ||||
-rw-r--r-- | src/conntrack/bsf.c | 29 | ||||
-rw-r--r-- | src/conntrack/build.c | 2 | ||||
-rw-r--r-- | src/conntrack/build_mnl.c | 76 | ||||
-rw-r--r-- | src/conntrack/filter.c | 17 | ||||
-rw-r--r-- | src/conntrack/filter_dump.c | 32 | ||||
-rw-r--r-- | src/conntrack/labels.c | 2 | ||||
-rw-r--r-- | src/conntrack/stack.c | 4 | ||||
-rw-r--r-- | src/expect/api.c | 4 | ||||
-rw-r--r-- | src/expect/build.c | 2 | ||||
-rw-r--r-- | utils/.gitignore | 2 | ||||
-rw-r--r-- | utils/Makefile.am | 8 | ||||
-rw-r--r-- | utils/conntrack_dump_filter.c | 2 | ||||
-rw-r--r-- | utils/conntrack_dump_filter_tuple.c | 70 | ||||
-rw-r--r-- | utils/conntrack_flush_filter.c | 60 |
21 files changed, 343 insertions, 39 deletions
@@ -11,6 +11,7 @@ Makefile.in /build-aux/ /config.* /configure +/configure~ /libtool /stamp-h1 diff --git a/configure.ac b/configure.ac index 9ae6cc6..3512794 100644 --- a/configure.ac +++ b/configure.ac @@ -7,7 +7,7 @@ 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 @@ -54,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/include/internal/object.h b/include/internal/object.h index 75ffdbe..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,10 +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/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 e229472..2e9458a 100644 --- a/include/libnetfilter_conntrack/libnetfilter_conntrack.h +++ b/include/libnetfilter_conntrack/libnetfilter_conntrack.h @@ -547,6 +547,8 @@ 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 }; @@ -562,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 diff --git a/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h b/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h index a365cf5..b8ffe02 100644 --- a/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h +++ b/include/libnetfilter_conntrack/linux_nfnetlink_conntrack.h @@ -291,6 +291,19 @@ enum ctattr_filter { }; #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 b7f64fb..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: @@ -833,6 +835,8 @@ __build_query_ct(struct nfnl_subsys_handle *ssh, 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, @@ -848,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; @@ -1359,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)); } /** @@ -1498,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)); } /** @@ -1550,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..1e78bad 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, @@ -331,7 +336,7 @@ add_state_filter_cta(struct sock_filter *this, s = stack_create(sizeof(struct jump), 3 + 32); if (s == NULL) { errno = ENOMEM; - return -1; + return 0; } jt = 1; @@ -398,7 +403,7 @@ add_state_filter(struct sock_filter *this, if (cta[proto].cta_protoinfo == 0 && cta[proto].cta_state == 0) { errno = ENOTSUP; - return -1; + return 0; } return add_state_filter_cta(this, @@ -443,7 +448,7 @@ bsf_add_proto_filter(const struct nfct_filter *f, struct sock_filter *this) s = stack_create(sizeof(struct jump), 3 + 255); if (s == NULL) { errno = ENOMEM; - return -1; + return 0; } jt = 1; @@ -515,7 +520,7 @@ bsf_add_addr_ipv4_filter(const struct nfct_filter *f, s = stack_create(sizeof(struct jump), 3 + 127); if (s == NULL) { errno = ENOMEM; - return -1; + return 0; } jt = 1; @@ -600,7 +605,7 @@ bsf_add_addr_ipv6_filter(const struct nfct_filter *f, s = stack_create(sizeof(struct jump), 3 + 80); if (s == NULL) { errno = ENOMEM; - return -1; + return 0; } jf = 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; } } @@ -699,7 +704,7 @@ bsf_add_mark_filter(const struct nfct_filter *f, struct sock_filter *this) s = stack_create(sizeof(struct jump), 3 + 127); if (s == NULL) { errno = ENOMEM; - return -1; + return 0; } jt = 1; @@ -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 af5d0e7..e563c4e 100644 --- a/src/conntrack/build_mnl.c +++ b/src/conntrack/build_mnl.c @@ -595,6 +595,49 @@ 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) { @@ -613,6 +656,39 @@ int nfct_nlmsg_build_filter(struct nlmsghdr *nlh, 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 9bf9296..fd2d002 100644 --- a/src/conntrack/filter_dump.c +++ b/src/conntrack/filter_dump.c @@ -37,14 +37,40 @@ set_filter_dump_attr_family(struct nfct_filter_dump *filter_dump, 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) +{ + 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) { - nfct_nlmsg_build_filter(&req->nlh, 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/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/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); +} |