Checkpoint before compilation attempt
This commit is contained in:
parent
e8b3356dd2
commit
c675bf0486
5 changed files with 399 additions and 377 deletions
|
@ -16,6 +16,7 @@ nobase_libnlinclude_HEADERS = \
|
|||
netlink/netfilter/nfnl.h \
|
||||
netlink/netfilter/queue.h \
|
||||
netlink/netfilter/queue_msg.h \
|
||||
netlink/netfilter/exp.h \
|
||||
netlink/addr.h \
|
||||
netlink/attr.h \
|
||||
netlink/cache-api.h \
|
||||
|
|
|
@ -60,10 +60,6 @@ extern int nfnl_exp_query(struct nl_sock *, const struct nfnl_exp *, int);
|
|||
extern void nfnl_exp_set_family(struct nfnl_exp *, uint8_t);
|
||||
extern uint8_t nfnl_exp_get_family(const struct nfnl_exp *);
|
||||
|
||||
extern void nfnl_exp_set_proto(struct nfnl_exp *, uint8_t);
|
||||
extern int nfnl_exp_test_proto(const struct nfnl_exp *);
|
||||
extern uint8_t nfnl_exp_get_proto(const struct nfnl_exp *);
|
||||
|
||||
extern void nfnl_exp_set_timeout(struct nfnl_exp *, uint32_t);
|
||||
extern int nfnl_exp_test_timeout(const struct nfnl_exp *);
|
||||
extern uint32_t nfnl_exp_get_timeout(const struct nfnl_exp *);
|
||||
|
|
|
@ -29,7 +29,8 @@ libnl_nf_3_la_SOURCES = \
|
|||
netfilter/ct.c netfilter/ct_obj.c netfilter/log.c \
|
||||
netfilter/log_msg.c netfilter/log_msg_obj.c netfilter/log_obj.c \
|
||||
netfilter/netfilter.c netfilter/nfnl.c netfilter/queue.c \
|
||||
netfilter/queue_msg.c netfilter/queue_msg_obj.c netfilter/queue_obj.c
|
||||
netfilter/queue_msg.c netfilter/queue_msg_obj.c netfilter/queue_obj.c \
|
||||
netfilter/exp.c netfilter/exp_obj.c
|
||||
|
||||
CLEANFILES = \
|
||||
route/pktloc_grammar.c route/pktloc_grammar.h \
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* lib/netfilter/ct.c Conntrack
|
||||
* lib/netfilter/ct.c Conntrack Expectation
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -14,7 +14,7 @@
|
|||
|
||||
/**
|
||||
* @ingroup nfnl
|
||||
* @defgroup ct Conntrack
|
||||
* @defgroup exp Expectation
|
||||
* @brief
|
||||
* @{
|
||||
*/
|
||||
|
@ -26,9 +26,9 @@
|
|||
#include <netlink-local.h>
|
||||
#include <netlink/attr.h>
|
||||
#include <netlink/netfilter/nfnl.h>
|
||||
#include <netlink/netfilter/ct.h>
|
||||
#include <netlink/netfilter/exp.h>
|
||||
|
||||
static struct nl_cache_ops nfnl_ct_ops;
|
||||
static struct nl_cache_ops nfnl_exp_ops;
|
||||
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
static uint64_t ntohll(uint64_t x)
|
||||
|
@ -42,35 +42,33 @@ static uint64_t ntohll(uint64_t x)
|
|||
}
|
||||
#endif
|
||||
|
||||
static struct nla_policy ct_policy[CTA_MAX+1] = {
|
||||
[CTA_TUPLE_ORIG] = { .type = NLA_NESTED },
|
||||
[CTA_TUPLE_REPLY] = { .type = NLA_NESTED },
|
||||
[CTA_STATUS] = { .type = NLA_U32 },
|
||||
[CTA_PROTOINFO] = { .type = NLA_NESTED },
|
||||
//[CTA_HELP]
|
||||
//[CTA_NAT_SRC]
|
||||
[CTA_TIMEOUT] = { .type = NLA_U32 },
|
||||
[CTA_MARK] = { .type = NLA_U32 },
|
||||
[CTA_COUNTERS_ORIG] = { .type = NLA_NESTED },
|
||||
[CTA_COUNTERS_REPLY] = { .type = NLA_NESTED },
|
||||
[CTA_USE] = { .type = NLA_U32 },
|
||||
[CTA_ID] = { .type = NLA_U32 },
|
||||
//[CTA_NAT_DST]
|
||||
static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = {
|
||||
[CTA_EXPECT_MASTER] = { .type = NLA_NESTED },
|
||||
[CTA_EXPECT_TUPLE] = { .type = NLA_NESTED },
|
||||
[CTA_EXPECT_MASK] = { .type = NLA_NESTED },
|
||||
[CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 },
|
||||
[CTA_EXPECT_ID] = { .type = NLA_U32 },
|
||||
[CTA_EXPECT_HELP_NAME] = { .type = NLA_STRING },
|
||||
//[CTA_EXPECT_ZONE] = { .type = NLA_U16 }, // In latest kernel header
|
||||
//[CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // In latest kernel header
|
||||
//[CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h
|
||||
//[CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h
|
||||
//[CTA_EXPECT_FN] = { .type = NLA_STRING }, // In libnetfilter_conntrack include/linux/linux_nfnetlink_conntrack.h
|
||||
};
|
||||
|
||||
static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = {
|
||||
static struct nla_policy exp_tuple_policy[CTA_TUPLE_MAX+1] = {
|
||||
[CTA_TUPLE_IP] = { .type = NLA_NESTED },
|
||||
[CTA_TUPLE_PROTO] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = {
|
||||
static struct nla_policy exp_ip_policy[CTA_IP_MAX+1] = {
|
||||
[CTA_IP_V4_SRC] = { .type = NLA_U32 },
|
||||
[CTA_IP_V4_DST] = { .type = NLA_U32 },
|
||||
[CTA_IP_V6_SRC] = { .minlen = 16 },
|
||||
[CTA_IP_V6_DST] = { .minlen = 16 },
|
||||
};
|
||||
|
||||
static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = {
|
||||
static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = {
|
||||
[CTA_PROTO_NUM] = { .type = NLA_U8 },
|
||||
[CTA_PROTO_SRC_PORT] = { .type = NLA_U16 },
|
||||
[CTA_PROTO_DST_PORT] = { .type = NLA_U16 },
|
||||
|
@ -82,33 +80,14 @@ static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = {
|
|||
[CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
|
||||
[CTA_PROTOINFO_TCP] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = {
|
||||
[CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 },
|
||||
[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 },
|
||||
[CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 },
|
||||
[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .minlen = 2 },
|
||||
[CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .minlen = 2 },
|
||||
|
||||
};
|
||||
|
||||
static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = {
|
||||
[CTA_COUNTERS_PACKETS] = { .type = NLA_U64 },
|
||||
[CTA_COUNTERS_BYTES] = { .type = NLA_U64 },
|
||||
[CTA_COUNTERS32_PACKETS]= { .type = NLA_U32 },
|
||||
[CTA_COUNTERS32_BYTES] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr)
|
||||
static int exp_parse_ip(struct nfnl_exp *exp, int tuple, struct nlattr *attr)
|
||||
{
|
||||
struct nlattr *tb[CTA_IP_MAX+1];
|
||||
struct nl_addr *addr;
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy);
|
||||
err = nla_parse_nested(tb, CTA_IP_MAX, attr, exp_ip_policy);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
|
@ -116,7 +95,7 @@ static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr)
|
|||
addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET);
|
||||
if (addr == NULL)
|
||||
goto errout_enomem;
|
||||
err = nfnl_ct_set_src(ct, repl, addr);
|
||||
err = nfnl_exp_set_src(exp, tuple, addr);
|
||||
nl_addr_put(addr);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
@ -125,7 +104,7 @@ static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr)
|
|||
addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET);
|
||||
if (addr == NULL)
|
||||
goto errout_enomem;
|
||||
err = nfnl_ct_set_dst(ct, repl, addr);
|
||||
err = nfnl_exp_set_dst(exp, tuple, addr);
|
||||
nl_addr_put(addr);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
@ -134,7 +113,7 @@ static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr)
|
|||
addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6);
|
||||
if (addr == NULL)
|
||||
goto errout_enomem;
|
||||
err = nfnl_ct_set_src(ct, repl, addr);
|
||||
err = nfnl_exp_set_src(exp, tuple, addr);
|
||||
nl_addr_put(addr);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
@ -143,7 +122,7 @@ static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr)
|
|||
addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6);
|
||||
if (addr == NULL)
|
||||
goto errout_enomem;
|
||||
err = nfnl_ct_set_dst(ct, repl, addr);
|
||||
err = nfnl_exp_set_dst(exp, tuple, addr);
|
||||
nl_addr_put(addr);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
@ -157,53 +136,55 @@ errout:
|
|||
return err;
|
||||
}
|
||||
|
||||
static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr)
|
||||
static int exp_parse_proto(struct nfnl_exp *exp, int tuple, struct nlattr *attr)
|
||||
{
|
||||
struct nlattr *tb[CTA_PROTO_MAX+1];
|
||||
int err;
|
||||
uint16_t srcport = 0, dstport = 0, icmpid = 0;
|
||||
uint8_t icmptype = 0, icmpcode = 0;
|
||||
|
||||
err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy);
|
||||
err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, exp_proto_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (!repl && tb[CTA_PROTO_NUM])
|
||||
nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM]));
|
||||
if (tb[CTA_PROTO_SRC_PORT])
|
||||
nfnl_ct_set_src_port(ct, repl,
|
||||
ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT])));
|
||||
if (tb[CTA_PROTO_DST_PORT])
|
||||
nfnl_ct_set_dst_port(ct, repl,
|
||||
ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT])));
|
||||
if (tb[CTA_PROTO_ICMP_ID])
|
||||
nfnl_ct_set_icmp_id(ct, repl,
|
||||
ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])));
|
||||
if (tb[CTA_PROTO_ICMP_TYPE])
|
||||
nfnl_ct_set_icmp_type(ct, repl,
|
||||
nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
|
||||
if (tb[CTA_PROTO_ICMP_CODE])
|
||||
nfnl_ct_set_icmp_code(ct, repl,
|
||||
nla_get_u8(tb[CTA_PROTO_ICMP_CODE]));
|
||||
if (tb[CTA_PROTO_NUM])
|
||||
nfnl_exp_set_l4protonum(exp, tuple, nla_get_u8(tb[CTA_PROTO_NUM]));
|
||||
|
||||
if (tb[CTA_PROTO_SRC_PORT])
|
||||
srcport = ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT]));
|
||||
if (tb[CTA_PROTO_DST_PORT])
|
||||
dstport = ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT]));
|
||||
if (tb[CTA_PROTO_SRC_PORT] || tb[CTA_PROTO_DST_PORT])
|
||||
nfnl_exp_set_ports(exp, tuple, srcport, dstport);
|
||||
|
||||
if (tb[CTA_PROTO_ICMP_ID])
|
||||
icmpid = ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID]));
|
||||
if (tb[CTA_PROTO_ICMP_TYPE])
|
||||
icmptype = nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]);
|
||||
if (tb[CTA_PROTO_ICMP_CODE])
|
||||
icmpcode = nla_get_u8(tb[CTA_PROTO_ICMP_CODE]);
|
||||
if (tb[CTA_PROTO_ICMP_ID] || tb[CTA_PROTO_ICMP_TYPE] || tb[CTA_PROTO_ICMP_CODE])
|
||||
nfnl_exp_set_icmp(exp, tuple, icmpid, icmptype, icmpcode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr)
|
||||
static int exp_parse_tuple(struct nfnl_exp *exp, int tuple, struct nlattr *attr)
|
||||
{
|
||||
struct nlattr *tb[CTA_TUPLE_MAX+1];
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy);
|
||||
err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, exp_tuple_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[CTA_TUPLE_IP]) {
|
||||
err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]);
|
||||
err = exp_parse_ip(exp, tuple, tb[CTA_TUPLE_IP]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (tb[CTA_TUPLE_PROTO]) {
|
||||
err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]);
|
||||
err = exp_parse_proto(exp, tuple, tb[CTA_TUPLE_PROTO]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
@ -211,185 +192,132 @@ static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr)
|
||||
{
|
||||
struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1];
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr,
|
||||
ct_protoinfo_tcp_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[CTA_PROTOINFO_TCP_STATE])
|
||||
nfnl_ct_set_tcp_state(ct,
|
||||
nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr)
|
||||
{
|
||||
struct nlattr *tb[CTA_PROTOINFO_MAX+1];
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr,
|
||||
ct_protoinfo_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[CTA_PROTOINFO_TCP]) {
|
||||
err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr)
|
||||
{
|
||||
struct nlattr *tb[CTA_COUNTERS_MAX+1];
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[CTA_COUNTERS_PACKETS])
|
||||
nfnl_ct_set_packets(ct, repl,
|
||||
ntohll(nla_get_u64(tb[CTA_COUNTERS_PACKETS])));
|
||||
if (tb[CTA_COUNTERS32_PACKETS])
|
||||
nfnl_ct_set_packets(ct, repl,
|
||||
ntohl(nla_get_u32(tb[CTA_COUNTERS32_PACKETS])));
|
||||
if (tb[CTA_COUNTERS_BYTES])
|
||||
nfnl_ct_set_bytes(ct, repl,
|
||||
ntohll(nla_get_u64(tb[CTA_COUNTERS_BYTES])));
|
||||
if (tb[CTA_COUNTERS32_BYTES])
|
||||
nfnl_ct_set_bytes(ct, repl,
|
||||
ntohl(nla_get_u32(tb[CTA_COUNTERS32_BYTES])));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfnlmsg_ct_group(struct nlmsghdr *nlh)
|
||||
int nfnlmsg_exp_group(struct nlmsghdr *nlh)
|
||||
{
|
||||
switch (nfnlmsg_subtype(nlh)) {
|
||||
case IPCTNL_MSG_CT_NEW:
|
||||
case IPCTNL_MSG_EXP_NEW:
|
||||
if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
|
||||
return NFNLGRP_CONNTRACK_NEW;
|
||||
return NFNLGRP_CONNTRACK_EXP_NEW;
|
||||
else
|
||||
return NFNLGRP_CONNTRACK_UPDATE;
|
||||
case IPCTNL_MSG_CT_DELETE:
|
||||
return NFNLGRP_CONNTRACK_DESTROY;
|
||||
return NFNLGRP_CONNTRACK_EXP_UPDATE;
|
||||
case IPCTNL_MSG_EXP_DELETE:
|
||||
return NFNLGRP_CONNTRACK_EXP_DESTROY;
|
||||
default:
|
||||
return NFNLGRP_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result)
|
||||
int nfnlmsg_exp_parse(struct nlmsghdr *nlh, struct nfnl_exp **result)
|
||||
{
|
||||
struct nfnl_ct *ct;
|
||||
struct nfnl_exp *exp;
|
||||
struct nlattr *tb[CTA_MAX+1];
|
||||
int err;
|
||||
|
||||
ct = nfnl_ct_alloc();
|
||||
if (!ct)
|
||||
exp = nfnl_exp_alloc();
|
||||
if (!exp)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
ct->ce_msgtype = nlh->nlmsg_type;
|
||||
exp->ce_msgtype = nlh->nlmsg_type;
|
||||
|
||||
err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX,
|
||||
ct_policy);
|
||||
err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_EXPECT_MAX,
|
||||
exp_policy);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
nfnl_ct_set_family(ct, nfnlmsg_family(nlh));
|
||||
nfnl_exp_set_family(exp, nfnlmsg_family(nlh));
|
||||
|
||||
if (tb[CTA_TUPLE_ORIG]) {
|
||||
err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]);
|
||||
if (tb[CTA_EXPECT_TUPLE]) {
|
||||
err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_EXPECT, tb[CTA_EXPECT_TUPLE]);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
if (tb[CTA_EXPECT_MASTER]) {
|
||||
err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASTER, tb[CTA_EXPECT_MASTER]);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
if (tb[CTA_TUPLE_REPLY]) {
|
||||
err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]);
|
||||
if (tb[CTA_EXPECT_MASK]) {
|
||||
err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASK, tb[CTA_EXPECT_MASK]);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (tb[CTA_PROTOINFO]) {
|
||||
err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
if (tb[CTA_EXPECT_TIMEOUT])
|
||||
nfnl_exp_set_timeout(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_TIMEOUT])));
|
||||
if (tb[CTA_EXPECT_ID])
|
||||
nfnl_exp_set_id(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_ID])));
|
||||
if (tb[CTA_EXPECT_HELP_NAME])
|
||||
nfnl_exp_set_helper_name(exp, nla_data(tb[CTA_EXPECT_HELP_NAME]));
|
||||
|
||||
if (tb[CTA_STATUS])
|
||||
nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS])));
|
||||
if (tb[CTA_TIMEOUT])
|
||||
nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT])));
|
||||
if (tb[CTA_MARK])
|
||||
nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK])));
|
||||
if (tb[CTA_USE])
|
||||
nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE])));
|
||||
if (tb[CTA_ID])
|
||||
nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID])));
|
||||
|
||||
if (tb[CTA_COUNTERS_ORIG]) {
|
||||
err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (tb[CTA_COUNTERS_REPLY]) {
|
||||
err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
*result = ct;
|
||||
*result = exp;
|
||||
return 0;
|
||||
|
||||
errout:
|
||||
nfnl_ct_put(ct);
|
||||
nfnl_exp_put(exp);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
||||
static int exp_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
||||
struct nlmsghdr *nlh, struct nl_parser_param *pp)
|
||||
{
|
||||
struct nfnl_ct *ct;
|
||||
struct nfnl_exp *exp;
|
||||
int err;
|
||||
|
||||
if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0)
|
||||
if ((err = nfnlmsg_exp_parse(nlh, &exp)) < 0)
|
||||
goto errout;
|
||||
|
||||
err = pp->pp_cb((struct nl_object *) ct, pp);
|
||||
err = pp->pp_cb((struct nl_object *) exp, pp);
|
||||
errout:
|
||||
nfnl_ct_put(ct);
|
||||
nfnl_exp_put(exp);
|
||||
return err;
|
||||
}
|
||||
|
||||
int nfnl_ct_dump_request(struct nl_sock *sk)
|
||||
int nfnl_exp_dump_request(struct nl_sock *sk)
|
||||
{
|
||||
return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET,
|
||||
return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK_EXP, IPCTNL_MSG_EXP_GET,
|
||||
NLM_F_DUMP, AF_UNSPEC, 0);
|
||||
}
|
||||
|
||||
static int ct_request_update(struct nl_cache *cache, struct nl_sock *sk)
|
||||
static int exp_request_update(struct nl_cache *cache, struct nl_sock *sk)
|
||||
{
|
||||
return nfnl_ct_dump_request(sk);
|
||||
return nfnl_exp_dump_request(sk);
|
||||
}
|
||||
|
||||
static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
|
||||
int repl)
|
||||
static int exp_get_tuple_attr(int tuple)
|
||||
{
|
||||
int attr = 0;
|
||||
|
||||
switch (tuple) {
|
||||
case NFNL_EXP_TUPLE_MASTER:
|
||||
attr = CTA_EXPECT_MASTER;
|
||||
break;
|
||||
case NFNL_EXP_TUPLE_MASK:
|
||||
attr = CTA_EXPECT_MASK;
|
||||
break;
|
||||
//case NFNL_EXP_TUPLE_NAT:
|
||||
// attr = EXP_ATTR_NAT_L4PROTO_NUM;
|
||||
// break;
|
||||
case NFNL_EXP_TUPLE_EXPECT:
|
||||
default :
|
||||
attr = CTA_EXPECT_TUPLE;
|
||||
break;
|
||||
}
|
||||
|
||||
return attr;
|
||||
}
|
||||
|
||||
static int nfnl_exp_build_tuple(struct nl_msg *msg, const struct nfnl_exp *exp,
|
||||
int type)
|
||||
{
|
||||
struct nlattr *tuple, *ip, *proto;
|
||||
struct nl_addr *addr;
|
||||
int family;
|
||||
|
||||
family = nfnl_ct_get_family(ct);
|
||||
int tupattr = exp_get_tuple_attr(type);
|
||||
|
||||
tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG);
|
||||
family = nfnl_exp_get_family(exp);
|
||||
|
||||
tuple = nla_nest_start(msg, tupattr);
|
||||
if (!tuple)
|
||||
goto nla_put_failure;
|
||||
|
||||
|
@ -397,13 +325,13 @@ static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
|
|||
if (!ip)
|
||||
goto nla_put_failure;
|
||||
|
||||
addr = nfnl_ct_get_src(ct, repl);
|
||||
addr = nfnl_exp_get_src(exp, type);
|
||||
if (addr)
|
||||
NLA_PUT_ADDR(msg,
|
||||
family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
|
||||
addr);
|
||||
|
||||
addr = nfnl_ct_get_dst(ct, repl);
|
||||
addr = nfnl_exp_get_dst(exp, type);
|
||||
if (addr)
|
||||
NLA_PUT_ADDR(msg,
|
||||
family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
|
||||
|
@ -415,28 +343,27 @@ static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
|
|||
if (!proto)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (nfnl_ct_test_proto(ct))
|
||||
NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct));
|
||||
if (nfnl_exp_test_l4protonum(exp, type))
|
||||
NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_exp_get_l4protonum(exp, type));
|
||||
|
||||
if (nfnl_ct_test_src_port(ct, repl))
|
||||
if (nfnl_exp_test_ports(exp, type)) {
|
||||
NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT,
|
||||
htons(nfnl_ct_get_src_port(ct, repl)));
|
||||
htons(nfnl_exp_get_src_port(exp, type)));
|
||||
|
||||
if (nfnl_ct_test_dst_port(ct, repl))
|
||||
NLA_PUT_U16(msg, CTA_PROTO_DST_PORT,
|
||||
htons(nfnl_ct_get_dst_port(ct, repl)));
|
||||
htons(nfnl_exp_get_dst_port(exp, type)));
|
||||
}
|
||||
|
||||
if (nfnl_ct_test_icmp_id(ct, repl))
|
||||
if (nfnl_exp_test_icmp(exp, type)) {
|
||||
NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
|
||||
htons(nfnl_ct_get_icmp_id(ct, repl)));
|
||||
htons(nfnl_exp_get_icmp_id(exp, type)));
|
||||
|
||||
if (nfnl_ct_test_icmp_type(ct, repl))
|
||||
NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
|
||||
nfnl_ct_get_icmp_type(ct, repl));
|
||||
nfnl_exp_get_icmp_type(exp, type));
|
||||
|
||||
if (nfnl_ct_test_icmp_code(ct, repl))
|
||||
NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
|
||||
nfnl_ct_get_icmp_code(ct, repl));
|
||||
nfnl_exp_get_icmp_code(exp, type));
|
||||
}
|
||||
|
||||
nla_nest_end(msg, proto);
|
||||
|
||||
|
@ -447,20 +374,36 @@ nla_put_failure:
|
|||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags,
|
||||
static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags,
|
||||
nfnl_ct_get_family(ct), 0);
|
||||
msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK_EXP, cmd, flags,
|
||||
nfnl_exp_get_family(exp), 0);
|
||||
if (msg == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0)
|
||||
if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_TUPLE)) < 0)
|
||||
goto err_out;
|
||||
|
||||
if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASTER)) < 0)
|
||||
goto err_out;
|
||||
|
||||
if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0)
|
||||
goto err_out;
|
||||
|
||||
// FIXME timeout and helper name
|
||||
if (nfnl_exp_test_id(exp))
|
||||
NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp)));
|
||||
|
||||
if (nfnl_exp_test_timeout(exp))
|
||||
NLA_PUT_U32(msg, CTA_EXPECT_TIMEOUT, htonl(nfnl_exp_get_timeout(exp)));
|
||||
|
||||
if (nfnl_exp_test_helper_name(exp))
|
||||
NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp));
|
||||
|
||||
*result = msg;
|
||||
return 0;
|
||||
|
||||
|
@ -469,18 +412,18 @@ err_out:
|
|||
return err;
|
||||
}
|
||||
|
||||
int nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags,
|
||||
int nfnl_exp_build_add_request(const struct nfnl_exp *exp, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result);
|
||||
return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_NEW, flags, result);
|
||||
}
|
||||
|
||||
int nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
|
||||
int nfnl_exp_add(struct nl_sock *sk, const struct nfnl_exp *exp, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0)
|
||||
if ((err = nfnl_exp_build_add_request(exp, flags, &msg)) < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
|
@ -491,18 +434,18 @@ int nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
|
|||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
int nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags,
|
||||
int nfnl_exp_build_delete_request(const struct nfnl_exp *exp, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result);
|
||||
return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_DELETE, flags, result);
|
||||
}
|
||||
|
||||
int nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
|
||||
int nfnl_exp_del(struct nl_sock *sk, const struct nfnl_exp *exp, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0)
|
||||
if ((err = nfnl_exp_build_delete_request(exp, flags, &msg)) < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
|
@ -513,18 +456,18 @@ int nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
|
|||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
int nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags,
|
||||
int nfnl_exp_build_query_request(const struct nfnl_exp *exp, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result);
|
||||
return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_GET, flags, result);
|
||||
}
|
||||
|
||||
int nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
|
||||
int nfnl_exp_query(struct nl_sock *sk, const struct nfnl_exp *exp, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0)
|
||||
if ((err = nfnl_exp_build_query_request(exp, flags, &msg)) < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
|
@ -541,61 +484,61 @@ int nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
|
|||
*/
|
||||
|
||||
/**
|
||||
* Build a conntrack cache holding all conntrack currently in the kernel
|
||||
* Build a expectation cache holding all expectations currently in the kernel
|
||||
* @arg sk Netlink socket.
|
||||
* @arg result Pointer to store resulting cache.
|
||||
*
|
||||
* Allocates a new cache, initializes it properly and updates it to
|
||||
* contain all conntracks currently in the kernel.
|
||||
* contain all expectations currently in the kernel.
|
||||
*
|
||||
* @return 0 on success or a negative error code.
|
||||
*/
|
||||
int nfnl_ct_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
|
||||
int nfnl_exp_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
|
||||
{
|
||||
return nl_cache_alloc_and_fill(&nfnl_ct_ops, sk, result);
|
||||
return nl_cache_alloc_and_fill(&nfnl_exp_ops, sk, result);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Conntrack Addition
|
||||
* @name Expectation Addition
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @} */
|
||||
|
||||
static struct nl_af_group ct_groups[] = {
|
||||
{ AF_UNSPEC, NFNLGRP_CONNTRACK_NEW },
|
||||
{ AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE },
|
||||
{ AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY },
|
||||
static struct nl_af_group exp_groups[] = {
|
||||
{ AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_NEW },
|
||||
{ AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_UPDATE },
|
||||
{ AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_DESTROY },
|
||||
{ END_OF_GROUP_LIST },
|
||||
};
|
||||
|
||||
#define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type))
|
||||
static struct nl_cache_ops nfnl_ct_ops = {
|
||||
.co_name = "netfilter/ct",
|
||||
#define NFNLMSG_EXP_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK_EXP, (type))
|
||||
static struct nl_cache_ops nfnl_exp_ops = {
|
||||
.co_name = "netfilter/exp",
|
||||
.co_hdrsize = NFNL_HDRLEN,
|
||||
.co_msgtypes = {
|
||||
{ NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" },
|
||||
{ NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" },
|
||||
{ NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" },
|
||||
{ NFNLMSG_CT_TYPE(IPCTNL_MSG_EXP_NEW), NL_ACT_NEW, "new" },
|
||||
{ NFNLMSG_CT_TYPE(IPCTNL_MSG_EXP_GET), NL_ACT_GET, "get" },
|
||||
{ NFNLMSG_CT_TYPE(IPCTNL_MSG_EXP_DELETE), NL_ACT_DEL, "del" },
|
||||
END_OF_MSGTYPES_LIST,
|
||||
},
|
||||
.co_protocol = NETLINK_NETFILTER,
|
||||
.co_groups = ct_groups,
|
||||
.co_request_update = ct_request_update,
|
||||
.co_msg_parser = ct_msg_parser,
|
||||
.co_obj_ops = &ct_obj_ops,
|
||||
.co_groups = exp_groups,
|
||||
.co_request_update = exp_request_update,
|
||||
.co_msg_parser = exp_msg_parser,
|
||||
.co_obj_ops = &exp_obj_ops,
|
||||
};
|
||||
|
||||
static void __init ct_init(void)
|
||||
static void __init exp_init(void)
|
||||
{
|
||||
nl_cache_mngt_register(&nfnl_ct_ops);
|
||||
nl_cache_mngt_register(&nfnl_exp_ops);
|
||||
}
|
||||
|
||||
static void __exit ct_exit(void)
|
||||
static void __exit exp_exit(void)
|
||||
{
|
||||
nl_cache_mngt_unregister(&nfnl_ct_ops);
|
||||
nl_cache_mngt_unregister(&nfnl_exp_ops);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
|
|
@ -33,9 +33,9 @@
|
|||
#define EXP_ATTR_ID (1UL << 2) // 32-bit
|
||||
#define EXP_ATTR_HELPER_NAME (1UL << 3) // string (16 bytes max)
|
||||
#define EXP_ATTR_ZONE (1UL << 4) // 16-bit
|
||||
#define EXP_ATTR_CLASS (1UL << 5) // 32-bit
|
||||
#define EXP_ATTR_CLASS (1UL << 5) // 32-bit ???
|
||||
#define EXP_ATTR_FLAGS (1UL << 6) // 32-bit
|
||||
#define EXP_ATTR_FN (1UL << 7) // String
|
||||
#define EXP_ATTR_FN (1UL << 7) // String ???
|
||||
|
||||
// Tuples
|
||||
#define EXP_ATTR_EXPECT_IP_SRC (1UL << 8)
|
||||
|
@ -59,7 +59,7 @@
|
|||
#define EXP_ATTR_NAT_L4PROTO_PORTS (1UL << 26)
|
||||
#define EXP_ATTR_NAT_L4PROTO_ICMP (1UL << 27)
|
||||
|
||||
#define EXP_ATTR_NAT_DIR (1UL << 28)
|
||||
#define EXP_ATTR_NAT_DIR (1UL << 28) // 8-bit
|
||||
/** @endcond */
|
||||
|
||||
static void exp_free_data(struct nl_object *c)
|
||||
|
@ -150,7 +150,7 @@ static int exp_clone(struct nl_object *_dst, struct nl_object *_src)
|
|||
}
|
||||
|
||||
if (src->exp_fn)
|
||||
dst->exp_fn = strdup(src->exp_fn)
|
||||
dst->exp_fn = strdup(src->exp_fn);
|
||||
|
||||
if (src->exp_helper_name)
|
||||
dst->exp_helper_name = strdup(src->exp_helper_name);
|
||||
|
@ -171,23 +171,26 @@ static void dump_addr(struct nl_dump_params *p, struct nl_addr *addr, int port)
|
|||
nl_dump(p, " ");
|
||||
}
|
||||
|
||||
static void dump_icmp(struct nl_dump_params *p, struct nfnl_ct *ct, int tuple)
|
||||
static void dump_icmp(struct nl_dump_params *p, struct nfnl_exp *exp, int tuple)
|
||||
{
|
||||
nl_dump(p, "icmp type %d ", nfnl_exp_get_icmp_type(ct, tuple));
|
||||
if (nfnl_exp_test_icmp(exp, tuple)) {
|
||||
|
||||
nl_dump(p, "code %d ", nfnl_exp_get_icmp_code(ct, tuple));
|
||||
nl_dump(p, "icmp type %d ", nfnl_exp_get_icmp_type(exp, tuple));
|
||||
|
||||
nl_dump(p, "id %d ", nfnl_exp_get_icmp_id(ct, tuple));
|
||||
nl_dump(p, "code %d ", nfnl_exp_get_icmp_code(exp, tuple));
|
||||
|
||||
nl_dump(p, "id %d ", nfnl_exp_get_icmp_id(exp, tuple));
|
||||
}
|
||||
}
|
||||
|
||||
static void ct_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p)
|
||||
static void exp_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p)
|
||||
{
|
||||
struct nl_addr *tuple_src, *tuple_dst;
|
||||
int tuple_sport = 0, tuple_dport = 0;
|
||||
int i = NFNL_EXP_TUPLE_EXPECT;
|
||||
int icmp = 0;
|
||||
int i = 0;
|
||||
char buf[64];
|
||||
|
||||
for (i; i <= NFNL_EXP_TUPLE_NAT; i++) {
|
||||
for (i = NFNL_EXP_TUPLE_EXPECT; i <= NFNL_EXP_TUPLE_NAT; i++) {
|
||||
|
||||
// Test needed for NAT case
|
||||
if (nfnl_exp_test_src(exp, i))
|
||||
|
@ -196,65 +199,68 @@ static void ct_dump_tuples(struct nfnl_exp *exp, struct nl_dump_params *p)
|
|||
tuple_dst = nfnl_exp_get_dst(exp, i);
|
||||
|
||||
// Don't have tests for individual ports/types/codes/ids,
|
||||
// just test L4 Proto. Ugly, but can't do much else without
|
||||
// more mask bits
|
||||
if (nfnl_exp_test_l4protonum(exp)) {
|
||||
nl_dump(p, "%s ",
|
||||
nl_ip_proto2str(nfnl_exp_get_l4protonum(exp), buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
if (nfnl_exp_test_l4proto(exp, i)) {
|
||||
int l4proto = nfnl_exp_get_l4proto(exp, i);
|
||||
if ( !(l4proto == IPPROTO_ICMP ||
|
||||
l4proto == IPPROTO_ICMPV6) ) {
|
||||
tuple_sport = nfnl_exp_get_src_port(exp, i);
|
||||
tuple_dport = nfnl_exp_get_dst_port(exp, i);
|
||||
} else {
|
||||
icmp = 1;
|
||||
}
|
||||
if (nfnl_exp_test_ports(exp, i)) {
|
||||
tuple_sport = nfnl_exp_get_src_port(exp, i);
|
||||
tuple_dport = nfnl_exp_get_dst_port(exp, i);
|
||||
}
|
||||
dump_addr(p, tuple_src, tuple_sport);
|
||||
dump_addr(p, tuple_dst, tuple_dport);
|
||||
if (icmp)
|
||||
dump_icmp(p, exp, 0);
|
||||
dump_icmp(p, exp, 0);
|
||||
}
|
||||
|
||||
if (nfnl_exp_test_nat_dir(exp))
|
||||
nl_dump(p, "nat dir %s ", exp->exp_nat_dir);
|
||||
|
||||
}
|
||||
|
||||
/* Compatible with /proc/net/nf_conntrack */
|
||||
static void ct_dump_line(struct nl_object *a, struct nl_dump_params *p)
|
||||
/* FIXME Compatible with /proc/net/nf_conntrack */
|
||||
static void exp_dump_line(struct nl_object *a, struct nl_dump_params *p)
|
||||
{
|
||||
struct nfnl_ct *ct = (struct nfnl_ct *) a;
|
||||
char buf[64];
|
||||
struct nfnl_exp *exp = (struct nfnl_exp *) a;
|
||||
|
||||
nl_new_line(p);
|
||||
|
||||
if (nfnl_ct_test_proto(ct))
|
||||
nl_dump(p, "%s ",
|
||||
nl_ip_proto2str(nfnl_ct_get_proto(ct), buf, sizeof(buf)));
|
||||
|
||||
ct_dump_tuples(ct, p);
|
||||
exp_dump_tuples(exp, p);
|
||||
|
||||
nl_dump(p, "\n");
|
||||
}
|
||||
|
||||
static void ct_dump_details(struct nl_object *a, struct nl_dump_params *p)
|
||||
static void exp_dump_details(struct nl_object *a, struct nl_dump_params *p)
|
||||
{
|
||||
struct nfnl_ct *ct = (struct nfnl_ct *) a;
|
||||
struct nfnl_exp *exp = (struct nfnl_exp *) a;
|
||||
char buf[64];
|
||||
int fp = 0;
|
||||
|
||||
ct_dump_line(a, p);
|
||||
|
||||
nl_dump(p, " id 0x%x ", ct->ct_id);
|
||||
nl_dump(p, " id 0x%x ", exp->exp_id);
|
||||
nl_dump_line(p, "family %s ",
|
||||
nl_af2str(ct->ct_family, buf, sizeof(buf)));
|
||||
nl_af2str(exp->exp_family, buf, sizeof(buf)));
|
||||
|
||||
if (nfnl_ct_test_use(ct))
|
||||
nl_dump(p, "refcnt %u ", nfnl_ct_get_use(ct));
|
||||
|
||||
if (nfnl_ct_test_timeout(ct)) {
|
||||
uint64_t timeout_ms = nfnl_ct_get_timeout(ct) * 1000UL;
|
||||
if (nfnl_exp_test_timeout(exp)) {
|
||||
uint64_t timeout_ms = nfnl_ct_get_timeout(exp) * 1000UL;
|
||||
nl_dump(p, "timeout %s ",
|
||||
nl_msec2str(timeout_ms, buf, sizeof(buf)));
|
||||
}
|
||||
|
||||
if (ct->ct_status)
|
||||
if (nfnl_exp_test_helper_name(exp))
|
||||
nl_dump(p, "helper %s ", exp->exp_helper_name);
|
||||
|
||||
if (nfnl_exp_test_fn(exp))
|
||||
nl_dump(p, "fn %s ", exp->exp_fn);
|
||||
|
||||
if (nfnl_exp_test_zone(exp))
|
||||
nl_dump(p, "zone %u ", nfnl_exp_get_zone(exp));
|
||||
|
||||
if (nfnl_exp_test_class(exp))
|
||||
nl_dump(p, "class %u ", nfnl_exp_get_class(exp));
|
||||
|
||||
if (nfnl_exp_test_flags(exp))
|
||||
nl_dump(p, "<");
|
||||
|
||||
#define PRINT_FLAG(str) \
|
||||
|
@ -268,7 +274,7 @@ static void ct_dump_details(struct nl_object *a, struct nl_dump_params *p)
|
|||
PRINT_FLAG("USERSPACE");
|
||||
#undef PRINT_FLAG
|
||||
|
||||
if (exp->exp_flags)
|
||||
if (nfnl_exp_test_flags(exp))
|
||||
nl_dump(p, ">");
|
||||
nl_dump(p, "\n");
|
||||
}
|
||||
|
@ -360,23 +366,23 @@ static int exp_compare(struct nl_object *_a, struct nl_object *_b,
|
|||
diff |= EXP_DIFF_L4PROTO_PORTS(EXPECT_L4PROTO_PORTS, exp_expect.proto.l4protodata.port);
|
||||
diff |= EXP_DIFF_L4PROTO_ICMP(EXPECT_L4PROTO_ICMP, exp_expect.proto.l4protodata.icmp);
|
||||
|
||||
diff |= EXP_DIFF_ADDR(MASTER_IP_SRC, exp_master.src);
|
||||
diff |= EXP_DIFF_ADDR(MASTER_IP_DST, exp_master.dst);
|
||||
diff |= EXP_DIFF_ADDR(MASTER_IP_SRC, exp_master.src);
|
||||
diff |= EXP_DIFF_ADDR(MASTER_IP_DST, exp_master.dst);
|
||||
diff |= EXP_DIFF_VAL(MASTER_L4PROTO_NUM, exp_master.proto.l4protonum);
|
||||
diff |= EXP_DIFF_L4PROTO_PORTS(MASTER_L4PROTO_PORTS, exp_master.proto.l4protodata.port);
|
||||
diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata.icmp);
|
||||
diff |= EXP_DIFF_L4PROTO_ICMP(MASTER_L4PROTO_ICMP, exp_master.proto.l4protodata.icmp);
|
||||
|
||||
diff |= EXP_DIFF_ADDR(MASK_IP_SRC, exp_mask.src);
|
||||
diff |= EXP_DIFF_ADDR(MASK_IP_DST, exp_mask.dst);
|
||||
diff |= EXP_DIFF_ADDR(MASK_IP_SRC, exp_mask.src);
|
||||
diff |= EXP_DIFF_ADDR(MASK_IP_DST, exp_mask.dst);
|
||||
diff |= EXP_DIFF_VAL(MASK_L4PROTO_NUM, exp_mask.proto.l4protonum);
|
||||
diff |= EXP_DIFF_L4PROTO_PORTS(MASK_L4PROTO_PORTS, exp_mask.proto.l4protodata.port);
|
||||
diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata.icmp);
|
||||
diff |= EXP_DIFF_L4PROTO_ICMP(MASK_L4PROTO_ICMP, exp_mask.proto.l4protodata.icmp);
|
||||
|
||||
diff |= EXP_DIFF_ADDR(NAT_IP_SRC, exp_nat.src);
|
||||
diff |= EXP_DIFF_ADDR(NAT_IP_DST, exp_nat.dst);
|
||||
diff |= EXP_DIFF_ADDR(NAT_IP_SRC, exp_nat.src);
|
||||
diff |= EXP_DIFF_ADDR(NAT_IP_DST, exp_nat.dst);
|
||||
diff |= EXP_DIFF_VAL(NAT_L4PROTO_NUM, exp_nat.proto.l4protonum);
|
||||
diff |= EXP_DIFF_L4PROTO_PORTS(NAT_L4PROTO_PORTS, exp_nat.proto.l4protodata.port);
|
||||
diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata.icmp);
|
||||
diff |= EXP_DIFF_L4PROTO_ICMP(NAT_L4PROTO_ICMP, exp_nat.proto.l4protodata.icmp);
|
||||
|
||||
#undef EXP_DIFF
|
||||
#undef EXP_DIFF_VAL
|
||||
|
@ -390,35 +396,35 @@ static int exp_compare(struct nl_object *_a, struct nl_object *_b,
|
|||
|
||||
// CLI arguments?
|
||||
static const struct trans_tbl exp_attrs[] = {
|
||||
__ADD(EXP_ATTR_FAMILY, family)
|
||||
__ADD(EXP_ATTR_TIMEOUT, timeout)
|
||||
__ADD(EXP_ATTR_ID, id)
|
||||
__ADD(EXP_ATTR_HELPER_NAME, helpername)
|
||||
__ADD(EXP_ATTR_ZONE, zone)
|
||||
__ADD(EXP_ATTR_CLASS, class)
|
||||
__ADD(EXP_ATTR_FLAGS, flags)
|
||||
__ADD(EXP_ATTR_FN, function)
|
||||
__ADD(EXP_ATTR_EXPECT_IP_SRC, expectipsrc)
|
||||
__ADD(EXP_ATTR_EXPECT_IP_DST, expectipdst)
|
||||
__ADD(EXP_ATTR_EXPECT_L4PROTO_NUM, expectprotonum)
|
||||
__ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS,expectports)
|
||||
__ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP ,expecticmp)
|
||||
__ADD(EXP_ATTR_MASTER_IP_SRC, masteripsrc)
|
||||
__ADD(EXP_ATTR_MASTER_IP_DST, masteripdst)
|
||||
__ADD(EXP_ATTR_MASTER_L4PROTO_NUM, masterprotonum)
|
||||
__ADD(EXP_ATTR_MASTER_L4PROTO_PORTS,masterports)
|
||||
__ADD(EXP_ATTR_MASTER_L4PROTO_ICMP ,mastericmp)
|
||||
__ADD(EXP_ATTR_MASK_IP_SRC, maskipsrc)
|
||||
__ADD(EXP_ATTR_MASK_IP_DST, maskipdst)
|
||||
__ADD(EXP_ATTR_MASK_L4PROTO_NUM, maskprotonum)
|
||||
__ADD(EXP_ATTR_MASK_L4PROTO_PORTS, maskports)
|
||||
__ADD(EXP_ATTR_MASK_L4PROTO_ICMP , maskicmp)
|
||||
__ADD(EXP_ATTR_NAT_IP_SRC, natipsrc)
|
||||
__ADD(EXP_ATTR_NAT_IP_DST, natipdst)
|
||||
__ADD(EXP_ATTR_NAT_L4PROTO_NUM, natprotonum)
|
||||
__ADD(EXP_ATTR_NAT_L4PROTO_PORTS, natports)
|
||||
__ADD(EXP_ATTR_NAT_L4PROTO_ICMP, naticmp)
|
||||
__ADD(EXP_ATTR_NAT_DIR, natdir)
|
||||
__ADD(EXP_ATTR_FAMILY, family)
|
||||
__ADD(EXP_ATTR_TIMEOUT, timeout)
|
||||
__ADD(EXP_ATTR_ID, id)
|
||||
__ADD(EXP_ATTR_HELPER_NAME, helpername)
|
||||
__ADD(EXP_ATTR_ZONE, zone)
|
||||
__ADD(EXP_ATTR_CLASS, class)
|
||||
__ADD(EXP_ATTR_FLAGS, flags)
|
||||
__ADD(EXP_ATTR_FN, function)
|
||||
__ADD(EXP_ATTR_EXPECT_IP_SRC, expectipsrc)
|
||||
__ADD(EXP_ATTR_EXPECT_IP_DST, expectipdst)
|
||||
__ADD(EXP_ATTR_EXPECT_L4PROTO_NUM, expectprotonum)
|
||||
__ADD(EXP_ATTR_EXPECT_L4PROTO_PORTS, expectports)
|
||||
__ADD(EXP_ATTR_EXPECT_L4PROTO_ICMP , expecticmp)
|
||||
__ADD(EXP_ATTR_MASTER_IP_SRC, masteripsrc)
|
||||
__ADD(EXP_ATTR_MASTER_IP_DST, masteripdst)
|
||||
__ADD(EXP_ATTR_MASTER_L4PROTO_NUM, masterprotonum)
|
||||
__ADD(EXP_ATTR_MASTER_L4PROTO_PORTS, masterports)
|
||||
__ADD(EXP_ATTR_MASTER_L4PROTO_ICMP , mastericmp)
|
||||
__ADD(EXP_ATTR_MASK_IP_SRC, maskipsrc)
|
||||
__ADD(EXP_ATTR_MASK_IP_DST, maskipdst)
|
||||
__ADD(EXP_ATTR_MASK_L4PROTO_NUM, maskprotonum)
|
||||
__ADD(EXP_ATTR_MASK_L4PROTO_PORTS, maskports)
|
||||
__ADD(EXP_ATTR_MASK_L4PROTO_ICMP , maskicmp)
|
||||
__ADD(EXP_ATTR_NAT_IP_SRC, natipsrc)
|
||||
__ADD(EXP_ATTR_NAT_IP_DST, natipdst)
|
||||
__ADD(EXP_ATTR_NAT_L4PROTO_NUM, natprotonum)
|
||||
__ADD(EXP_ATTR_NAT_L4PROTO_PORTS, natports)
|
||||
__ADD(EXP_ATTR_NAT_L4PROTO_ICMP, naticmp)
|
||||
__ADD(EXP_ATTR_NAT_DIR, natdir)
|
||||
};
|
||||
|
||||
static char *exp_attrs2str(int attrs, char *buf, size_t len)
|
||||
|
@ -533,6 +539,112 @@ uint32_t nfnl_exp_get_id(const struct nfnl_exp *exp)
|
|||
return exp->exp_id;
|
||||
}
|
||||
|
||||
int nfnl_exp_set_helper_name(struct nfnl_exp *exp, void *name)
|
||||
{
|
||||
free(exp->exp_helper_name);
|
||||
exp->exp_helper_name = strdup(name);
|
||||
if (!exp->exp_helper_name)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
exp->ce_mask |= EXP_ATTR_HELPER_NAME;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfnl_exp_test_helper_name(const struct nfnl_exp *exp)
|
||||
{
|
||||
return !!(exp->ce_mask & EXP_ATTR_HELPER_NAME);
|
||||
}
|
||||
|
||||
const char * nfnl_exp_get_helper_name(const struct nfnl_exp *exp)
|
||||
{
|
||||
return exp->exp_helper_name;
|
||||
}
|
||||
|
||||
void nfnl_exp_set_zone(struct nfnl_exp *exp, uint16_t zone)
|
||||
{
|
||||
exp->exp_zone = zone;
|
||||
exp->ce_mask |= EXP_ATTR_ZONE;
|
||||
}
|
||||
|
||||
int nfnl_exp_test_zone(const struct nfnl_exp *exp)
|
||||
{
|
||||
return !!(exp->ce_mask & EXP_ATTR_ZONE);
|
||||
}
|
||||
|
||||
uint16_t nfnl_exp_get_zone(const struct nfnl_exp *exp)
|
||||
{
|
||||
return exp->exp_zone;
|
||||
}
|
||||
|
||||
void nfnl_exp_set_class(struct nfnl_exp *exp, uint32_t class)
|
||||
{
|
||||
exp->exp_class = class;
|
||||
exp->ce_mask |= EXP_ATTR_CLASS;
|
||||
}
|
||||
|
||||
int nfnl_exp_test_class(const struct nfnl_exp *exp)
|
||||
{
|
||||
return !!(exp->ce_mask & EXP_ATTR_CLASS);
|
||||
}
|
||||
|
||||
uint32_t nfnl_exp_get_class(const struct nfnl_exp *exp)
|
||||
{
|
||||
return exp->exp_class;
|
||||
}
|
||||
|
||||
void nfnl_exp_set_flags(struct nfnl_exp *exp, uint32_t flags)
|
||||
{
|
||||
exp->exp_flags = flags;
|
||||
exp->ce_mask |= EXP_ATTR_FLAGS;
|
||||
}
|
||||
|
||||
int nfnl_exp_test_flags(const struct nfnl_exp *exp)
|
||||
{
|
||||
return !!(exp->ce_mask & EXP_ATTR_FLAGS);
|
||||
}
|
||||
|
||||
uint32_t nfnl_exp_get_flags(const struct nfnl_exp *exp)
|
||||
{
|
||||
return exp->exp_flags;
|
||||
}
|
||||
|
||||
int nfnl_exp_set_fn(struct nfnl_exp *exp, void *fn)
|
||||
{
|
||||
free(exp->exp_fn);
|
||||
exp->exp_fn = strdup(fn);
|
||||
if (!exp->exp_fn)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
exp->ce_mask |= EXP_ATTR_FN;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nfnl_exp_test_fn(const struct nfnl_exp *exp)
|
||||
{
|
||||
return !!(exp->ce_mask & EXP_ATTR_FN);
|
||||
}
|
||||
|
||||
const char * nfnl_exp_get_fn(const struct nfnl_exp *exp)
|
||||
{
|
||||
return exp->exp_fn;
|
||||
}
|
||||
|
||||
void nfnl_exp_set_nat_dir(struct nfnl_exp *exp, uint8_t nat_dir)
|
||||
{
|
||||
exp->exp_nat_dir = nat_dir;
|
||||
exp->ce_mask |= EXP_ATTR_NAT_DIR;
|
||||
}
|
||||
|
||||
int nfnl_exp_test_nat_dir(const struct nfnl_exp *exp)
|
||||
{
|
||||
return !!(exp->ce_mask & EXP_ATTR_NAT_DIR);
|
||||
}
|
||||
|
||||
uint8_t nfnl_exp_get_nat_dir(const struct nfnl_exp *exp)
|
||||
{
|
||||
return exp->exp_nat_dir;
|
||||
}
|
||||
|
||||
static struct nfnl_exp_dir *exp_get_dir(struct nfnl_exp *exp, int tuple)
|
||||
{
|
||||
struct nfnl_exp_dir *dir = NULL;
|
||||
|
@ -729,7 +841,7 @@ static int exp_get_l4ports_attr(int tuple)
|
|||
return attr;
|
||||
}
|
||||
|
||||
void nfnl_exp_set_src_ports(struct nfnl_exp *exp, int tuple, uint16_t srcport, uint16_t dstport)
|
||||
void nfnl_exp_set_ports(struct nfnl_exp *exp, int tuple, uint16_t srcport, uint16_t dstport)
|
||||
{
|
||||
struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
|
||||
|
||||
|
@ -780,7 +892,7 @@ static int exp_get_l4icmp_attr(int tuple)
|
|||
return attr;
|
||||
}
|
||||
|
||||
void nfnl_ct_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type, uint8_t, code)
|
||||
void nfnl_exp_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type, uint8_t, code)
|
||||
{
|
||||
struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
|
||||
|
||||
|
@ -791,61 +903,31 @@ void nfnl_ct_set_icmp(struct nfnl_exp *exp, int tuple, uint16_t id, uint8_t type
|
|||
exp->ce_mask |= exp_get_l4icmp_attr(tuple);
|
||||
}
|
||||
|
||||
int nfnl_ct_test_icmp_id(const struct nfnl_ct *ct, int repl)
|
||||
int nfnl_exp_test_icmp(const struct nfnl_exp *exp, int tuple)
|
||||
{
|
||||
int attr = repl ? CT_ATTR_REPL_ICMP_ID : CT_ATTR_ORIG_ICMP_ID;
|
||||
return !!(ct->ce_mask & attr);
|
||||
int attr = exp_get_l4icmp_attr(tuple);
|
||||
return !!(exp->ce_mask & attr);
|
||||
}
|
||||
|
||||
uint16_t nfnl_ct_get_icmp_id(const struct nfnl_ct *ct, int repl)
|
||||
uint16_t nfnl_exp_get_icmp_id(const struct nfnl_exp *exp, int tuple)
|
||||
{
|
||||
const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
|
||||
const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
|
||||
|
||||
return dir->proto.icmp.id;
|
||||
return dir->proto.l4protodata.icmp.id;
|
||||
}
|
||||
|
||||
void nfnl_ct_set_icmp_type(struct nfnl_ct *ct, int repl, uint8_t type)
|
||||
uint8_t nfnl_exp_get_icmp_type(const struct nfnl_exp *exp, int tuple)
|
||||
{
|
||||
struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
|
||||
int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE;
|
||||
const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
|
||||
|
||||
dir->proto.icmp.type = type;
|
||||
ct->ce_mask |= attr;
|
||||
return dir->proto.l4protodata.icmp.type;
|
||||
}
|
||||
|
||||
int nfnl_ct_test_icmp_type(const struct nfnl_ct *ct, int repl)
|
||||
uint8_t nfnl_ct_get_icmp_code(const struct nfnl_exp *exp, int tuple)
|
||||
{
|
||||
int attr = repl ? CT_ATTR_REPL_ICMP_TYPE : CT_ATTR_ORIG_ICMP_TYPE;
|
||||
return !!(ct->ce_mask & attr);
|
||||
}
|
||||
const struct nfnl_exp_dir *dir = exp_get_dir(exp, tuple);
|
||||
|
||||
uint8_t nfnl_ct_get_icmp_type(const struct nfnl_ct *ct, int repl)
|
||||
{
|
||||
const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
|
||||
|
||||
return dir->proto.icmp.type;
|
||||
}
|
||||
|
||||
void nfnl_ct_set_icmp_code(struct nfnl_ct *ct, int repl, uint8_t code)
|
||||
{
|
||||
struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
|
||||
int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE;
|
||||
|
||||
dir->proto.icmp.code = code;
|
||||
ct->ce_mask |= attr;
|
||||
}
|
||||
|
||||
int nfnl_ct_test_icmp_code(const struct nfnl_ct *ct, int repl)
|
||||
{
|
||||
int attr = repl ? CT_ATTR_REPL_ICMP_CODE : CT_ATTR_ORIG_ICMP_CODE;
|
||||
return !!(ct->ce_mask & attr);
|
||||
}
|
||||
|
||||
uint8_t nfnl_ct_get_icmp_code(const struct nfnl_ct *ct, int tuple)
|
||||
{
|
||||
const struct nfnl_ct_dir *dir = repl ? &ct->ct_repl : &ct->ct_orig;
|
||||
|
||||
return dir->proto.icmp.code;
|
||||
return dir->proto.l4protodata.icmp.code;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
@ -858,7 +940,6 @@ struct nl_object_ops exp_obj_ops = {
|
|||
.oo_dump = {
|
||||
[NL_DUMP_LINE] = exp_dump_line,
|
||||
[NL_DUMP_DETAILS] = exp_dump_details,
|
||||
[NL_DUMP_STATS] = exp_dump_stats,
|
||||
},
|
||||
.oo_compare = exp_compare,
|
||||
.oo_attrs2str = exp_attrs2str,
|
||||
|
|
Loading…
Add table
Reference in a new issue