From d773fb2afc097a08d51eae42740c63142b1752cf Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Mon, 16 Apr 2012 12:13:45 +0200 Subject: expect: add new API to build/parse ctnetlink messages using libmnl This patch adds support to build and to parse netlink messages from/to one user-space nf_conntrack object. It uses libmnl, thus libnetfilter_conntrack now depends on this library. Signed-off-by: Pablo Neira Ayuso --- src/conntrack/build_mnl.c | 2 +- src/conntrack/parse_mnl.c | 2 +- src/expect/Makefile.am | 5 ++- src/expect/build_mnl.c | 49 ++++++++++++++++++++++ src/expect/parse_mnl.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 src/expect/build_mnl.c create mode 100644 src/expect/parse_mnl.c (limited to 'src') diff --git a/src/conntrack/build_mnl.c b/src/conntrack/build_mnl.c index 7aceaf1..997c2c9 100644 --- a/src/conntrack/build_mnl.c +++ b/src/conntrack/build_mnl.c @@ -79,7 +79,7 @@ nfct_build_tuple_proto(struct nlmsghdr *nlh, const struct __nfct_tuple *t) return 0; } -static int +int nfct_build_tuple(struct nlmsghdr *nlh, const struct __nfct_tuple *t, int type) { struct nlattr *nest; diff --git a/src/conntrack/parse_mnl.c b/src/conntrack/parse_mnl.c index a4955a0..86d9c54 100644 --- a/src/conntrack/parse_mnl.c +++ b/src/conntrack/parse_mnl.c @@ -258,7 +258,7 @@ static int nfct_parse_tuple_attr_cb(const struct nlattr *attr, void *data) return MNL_CB_OK; } -static int +int nfct_parse_tuple(const struct nlattr *attr, struct __nfct_tuple *tuple, int dir, u_int32_t *set) { diff --git a/src/expect/Makefile.am b/src/expect/Makefile.am index e8a874a..61d5cbd 100644 --- a/src/expect/Makefile.am +++ b/src/expect/Makefile.am @@ -8,4 +8,7 @@ libnfexpect_la_SOURCES = api.c \ parse.c build.c \ snprintf.c \ snprintf_default.c \ - snprintf_xml.c + snprintf_xml.c \ + build_mnl.c \ + parse_mnl.c + diff --git a/src/expect/build_mnl.c b/src/expect/build_mnl.c new file mode 100644 index 0000000..6f33f05 --- /dev/null +++ b/src/expect/build_mnl.c @@ -0,0 +1,49 @@ +/* + * (C) 2005-2012 by Pablo Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This code has been sponsored by Vyatta Inc. + */ + +#include "internal/internal.h" +#include + +int +nfexp_nlmsg_build(struct nlmsghdr *nlh, const struct nf_expect *exp) +{ + u_int8_t l3num; + + if (test_bit(ATTR_ORIG_L3PROTO, exp->master.set)) + l3num = exp->master.orig.l3protonum; + else if (test_bit(ATTR_ORIG_L3PROTO, exp->expected.set)) + l3num = exp->expected.orig.l3protonum; + else + return -1; + + if (test_bit(ATTR_EXP_EXPECTED, exp->set)) + nfct_build_tuple(nlh, &exp->expected.orig, CTA_EXPECT_TUPLE); + + if (test_bit(ATTR_EXP_MASTER, exp->set)) + nfct_build_tuple(nlh, &exp->master.orig, CTA_EXPECT_MASTER); + + if (test_bit(ATTR_EXP_MASK, exp->set)) + nfct_build_tuple(nlh, &exp->mask.orig, CTA_EXPECT_MASK); + + if (test_bit(ATTR_EXP_TIMEOUT, exp->set)) + mnl_attr_put_u32(nlh, CTA_EXPECT_TIMEOUT, htonl(exp->timeout)); + + if (test_bit(ATTR_EXP_FLAGS, exp->set)) + mnl_attr_put_u32(nlh, CTA_EXPECT_FLAGS, htonl(exp->flags)); + + if (test_bit(ATTR_EXP_ZONE, exp->set)) + mnl_attr_put_u16(nlh, CTA_EXPECT_ZONE, htons(exp->zone)); + + if (test_bit(ATTR_EXP_HELPER_NAME, exp->set)) + mnl_attr_put_strz(nlh, CTA_EXPECT_HELP_NAME, exp->helper_name); + + return 0; +} diff --git a/src/expect/parse_mnl.c b/src/expect/parse_mnl.c new file mode 100644 index 0000000..741b46e --- /dev/null +++ b/src/expect/parse_mnl.c @@ -0,0 +1,104 @@ +/* + * (C) 2005-2012 by Pablo Neira Ayuso + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This code has been sponsored by Vyatta Inc. + */ + +#include "internal/internal.h" +#include + +static int nlmsg_parse_expection_attr_cb(const struct nlattr *attr, void *data) +{ + const struct nlattr **tb = data; + int type = mnl_attr_get_type(attr); + + /* skip unsupported attribute in user-space */ + if (mnl_attr_type_valid(attr, CTA_EXPECT_MAX) < 0) + return MNL_CB_OK; + + switch(type) { + case CTA_EXPECT_MASTER: + case CTA_EXPECT_TUPLE: + case CTA_EXPECT_MASK: + if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) + return MNL_CB_ERROR; + break; + case CTA_EXPECT_TIMEOUT: + case CTA_EXPECT_FLAGS: + case CTA_EXPECT_ID: + if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) + return MNL_CB_ERROR; + break; + case CTA_EXPECT_HELP_NAME: + if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0) + return MNL_CB_ERROR; + break; + case CTA_EXPECT_ZONE: + if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) + return MNL_CB_ERROR; + break; + } + tb[type] = attr; + return MNL_CB_OK; +} + +int nfexp_nlmsg_parse(const struct nlmsghdr *nlh, struct nf_expect *exp) +{ + struct nlattr *tb[CTA_EXPECT_MAX+1] = {}; + struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh); + + mnl_attr_parse(nlh, sizeof(struct nfgenmsg), + nlmsg_parse_expection_attr_cb, tb); + + if (tb[CTA_EXPECT_MASTER]) { + exp->expected.orig.l3protonum = nfg->nfgen_family; + set_bit(ATTR_ORIG_L3PROTO, exp->expected.set); + + nfct_parse_tuple(tb[CTA_EXPECT_MASTER], &exp->master.orig, + __DIR_ORIG, exp->master.set); + set_bit(ATTR_EXP_MASTER, exp->set); + } + if (tb[CTA_EXPECT_TUPLE]) { + exp->mask.orig.l3protonum = nfg->nfgen_family; + set_bit(ATTR_ORIG_L3PROTO, exp->mask.set); + + nfct_parse_tuple(tb[CTA_EXPECT_TUPLE], &exp->expected.orig, + __DIR_ORIG, exp->expected.set); + set_bit(ATTR_EXP_EXPECTED, exp->set); + } + if (tb[CTA_EXPECT_MASK]) { + exp->master.orig.l3protonum = nfg->nfgen_family; + set_bit(ATTR_ORIG_L3PROTO, exp->master.set); + + nfct_parse_tuple(tb[CTA_EXPECT_MASK], &exp->mask.orig, + __DIR_ORIG, exp->mask.set); + set_bit(ATTR_EXP_MASK, exp->set); + } + if (tb[CTA_EXPECT_TIMEOUT]) { + exp->timeout = ntohl(mnl_attr_get_u32(tb[CTA_EXPECT_TIMEOUT])); + set_bit(ATTR_EXP_TIMEOUT, exp->set); + } + + if (tb[CTA_EXPECT_ZONE]) { + exp->zone = ntohs(mnl_attr_get_u16(tb[CTA_EXPECT_ZONE])); + set_bit(ATTR_EXP_ZONE, exp->set); + } + + if (tb[CTA_EXPECT_FLAGS]) { + exp->flags = ntohl(mnl_attr_get_u32(tb[CTA_EXPECT_FLAGS])); + 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); + set_bit(ATTR_EXP_HELPER_NAME, exp->set); + } + return 0; +} -- cgit v1.2.3