summaryrefslogtreecommitdiffstats
path: root/src/conntrack
diff options
context:
space:
mode:
Diffstat (limited to 'src/conntrack')
-rw-r--r--src/conntrack/Makefile.am3
-rw-r--r--src/conntrack/api.c40
-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/copy.c4
-rw-r--r--src/conntrack/filter.c17
-rw-r--r--src/conntrack/filter_dump.c51
-rw-r--r--src/conntrack/grp_setter.c34
-rw-r--r--src/conntrack/labels.c2
-rw-r--r--src/conntrack/parse_mnl.c5
-rw-r--r--src/conntrack/proto.c36
-rw-r--r--src/conntrack/setter.c40
-rw-r--r--src/conntrack/snprintf.c5
-rw-r--r--src/conntrack/snprintf_default.c74
-rw-r--r--src/conntrack/snprintf_xml.c20
-rw-r--r--src/conntrack/stack.c4
17 files changed, 323 insertions, 137 deletions
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 765ce72..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)
{
@@ -184,7 +206,9 @@ static int __snprintf_status_assured(char *buf,
{
int size = 0;
- if (ct->status & IPS_OFFLOAD)
+ 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] ");
@@ -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/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;