25 #include <sys/types.h> 26 #include <linux/netfilter/nfnetlink_conntrack.h> 28 #include <netlink-private/netlink.h> 29 #include <netlink/attr.h> 30 #include <netlink/netfilter/nfnl.h> 31 #include <netlink/netfilter/exp.h> 33 static struct nl_cache_ops nfnl_exp_ops;
35 static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = {
39 [CTA_EXPECT_TIMEOUT] = { .type =
NLA_U32 },
40 [CTA_EXPECT_ID] = { .type =
NLA_U32 },
41 [CTA_EXPECT_HELP_NAME] = { .type =
NLA_STRING },
42 [CTA_EXPECT_ZONE] = { .type =
NLA_U16 },
43 [CTA_EXPECT_FLAGS] = { .type =
NLA_U32 },
44 [CTA_EXPECT_CLASS] = { .type =
NLA_U32 },
49 static struct nla_policy exp_tuple_policy[CTA_TUPLE_MAX+1] = {
54 static struct nla_policy exp_ip_policy[CTA_IP_MAX+1] = {
56 [CTA_IP_V4_DST] = { .type =
NLA_U32 },
57 [CTA_IP_V6_SRC] = { .minlen = 16 },
58 [CTA_IP_V6_DST] = { .minlen = 16 },
61 static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = {
63 [CTA_PROTO_SRC_PORT] = { .type =
NLA_U16 },
64 [CTA_PROTO_DST_PORT] = { .type =
NLA_U16 },
65 [CTA_PROTO_ICMP_ID] = { .type =
NLA_U16 },
66 [CTA_PROTO_ICMP_TYPE] = { .type =
NLA_U8 },
67 [CTA_PROTO_ICMP_CODE] = { .type =
NLA_U8 },
68 [CTA_PROTO_ICMPV6_ID] = { .type =
NLA_U16 },
69 [CTA_PROTO_ICMPV6_TYPE] = { .type =
NLA_U8 },
70 [CTA_PROTO_ICMPV6_CODE] = { .type =
NLA_U8 },
73 static struct nla_policy exp_nat_policy[CTA_EXPECT_NAT_MAX+1] = {
75 [CTA_EXPECT_NAT_TUPLE] = { .type =
NLA_NESTED },
78 static int exp_parse_ip(
struct nfnl_exp *exp,
int tuple,
struct nlattr *attr)
80 struct nlattr *tb[CTA_IP_MAX+1];
88 if (tb[CTA_IP_V4_SRC]) {
92 err = nfnl_exp_set_src(exp, tuple, addr);
97 if (tb[CTA_IP_V4_DST]) {
101 err = nfnl_exp_set_dst(exp, tuple, addr);
106 if (tb[CTA_IP_V6_SRC]) {
110 err = nfnl_exp_set_src(exp, tuple, addr);
115 if (tb[CTA_IP_V6_DST]) {
119 err = nfnl_exp_set_dst(exp, tuple, addr);
133 static int exp_parse_proto(
struct nfnl_exp *exp,
int tuple,
struct nlattr *attr)
135 struct nlattr *tb[CTA_PROTO_MAX+1];
137 uint16_t srcport = 0, dstport = 0, icmpid = 0;
138 uint8_t icmptype = 0, icmpcode = 0;
144 if (tb[CTA_PROTO_NUM])
145 nfnl_exp_set_l4protonum(exp, tuple,
nla_get_u8(tb[CTA_PROTO_NUM]));
147 if (tb[CTA_PROTO_SRC_PORT])
148 srcport = ntohs(
nla_get_u16(tb[CTA_PROTO_SRC_PORT]));
149 if (tb[CTA_PROTO_DST_PORT])
150 dstport = ntohs(
nla_get_u16(tb[CTA_PROTO_DST_PORT]));
151 if (tb[CTA_PROTO_SRC_PORT] || tb[CTA_PROTO_DST_PORT])
152 nfnl_exp_set_ports(exp, tuple, srcport, dstport);
154 if (tb[CTA_PROTO_ICMP_ID])
155 icmpid = ntohs(
nla_get_u16(tb[CTA_PROTO_ICMP_ID]));
156 if (tb[CTA_PROTO_ICMP_TYPE])
157 icmptype =
nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]);
158 if (tb[CTA_PROTO_ICMP_CODE])
159 icmpcode =
nla_get_u8(tb[CTA_PROTO_ICMP_CODE]);
160 if (tb[CTA_PROTO_ICMP_ID] || tb[CTA_PROTO_ICMP_TYPE] || tb[CTA_PROTO_ICMP_CODE])
161 nfnl_exp_set_icmp(exp, tuple, icmpid, icmptype, icmpcode);
165 static int exp_parse_tuple(
struct nfnl_exp *exp,
int tuple,
struct nlattr *attr)
167 struct nlattr *tb[CTA_TUPLE_MAX+1];
174 if (tb[CTA_TUPLE_IP]) {
175 err = exp_parse_ip(exp, tuple, tb[CTA_TUPLE_IP]);
180 if (tb[CTA_TUPLE_PROTO]) {
181 err = exp_parse_proto(exp, tuple, tb[CTA_TUPLE_PROTO]);
189 static int exp_parse_nat(
struct nfnl_exp *exp,
struct nlattr *attr)
191 struct nlattr *tb[CTA_EXPECT_NAT_MAX+1];
198 if (tb[CTA_EXPECT_NAT_DIR])
199 nfnl_exp_set_nat_dir(exp,
nla_get_u32(tb[CTA_EXPECT_NAT_DIR]));
201 if (tb[CTA_EXPECT_NAT_TUPLE]) {
202 err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_NAT, tb[CTA_EXPECT_NAT_TUPLE]);
210 int nfnlmsg_exp_group(
struct nlmsghdr *nlh)
213 case IPCTNL_MSG_EXP_NEW:
214 if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
215 return NFNLGRP_CONNTRACK_EXP_NEW;
217 return NFNLGRP_CONNTRACK_EXP_UPDATE;
218 case IPCTNL_MSG_EXP_DELETE:
219 return NFNLGRP_CONNTRACK_EXP_DESTROY;
225 int nfnlmsg_exp_parse(
struct nlmsghdr *nlh,
struct nfnl_exp **result)
227 struct nfnl_exp *exp;
228 struct nlattr *tb[CTA_MAX+1];
231 exp = nfnl_exp_alloc();
235 exp->ce_msgtype = nlh->nlmsg_type;
237 err =
nlmsg_parse(nlh,
sizeof(
struct nfgenmsg), tb, CTA_EXPECT_MAX,
244 if (tb[CTA_EXPECT_TUPLE]) {
245 err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_EXPECT, tb[CTA_EXPECT_TUPLE]);
249 if (tb[CTA_EXPECT_MASTER]) {
250 err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASTER, tb[CTA_EXPECT_MASTER]);
254 if (tb[CTA_EXPECT_MASK]) {
255 err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASK, tb[CTA_EXPECT_MASK]);
260 if (tb[CTA_EXPECT_NAT]) {
261 err = exp_parse_nat(exp, tb[CTA_EXPECT_MASK]);
266 if (tb[CTA_EXPECT_CLASS])
267 nfnl_exp_set_class(exp, ntohl(
nla_get_u32(tb[CTA_EXPECT_CLASS])));
269 if (tb[CTA_EXPECT_FN])
270 nfnl_exp_set_fn(exp,
nla_data(tb[CTA_EXPECT_FN]));
272 if (tb[CTA_EXPECT_TIMEOUT])
273 nfnl_exp_set_timeout(exp, ntohl(
nla_get_u32(tb[CTA_EXPECT_TIMEOUT])));
275 if (tb[CTA_EXPECT_ID])
276 nfnl_exp_set_id(exp, ntohl(
nla_get_u32(tb[CTA_EXPECT_ID])));
278 if (tb[CTA_EXPECT_HELP_NAME])
279 nfnl_exp_set_helper_name(exp,
nla_data(tb[CTA_EXPECT_HELP_NAME]));
281 if (tb[CTA_EXPECT_ZONE])
282 nfnl_exp_set_zone(exp, ntohs(
nla_get_u16(tb[CTA_EXPECT_ZONE])));
284 if (tb[CTA_EXPECT_FLAGS])
285 nfnl_exp_set_flags(exp, ntohl(
nla_get_u32(tb[CTA_EXPECT_FLAGS])));
295 static int exp_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
296 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
298 struct nfnl_exp *exp;
301 if ((err = nfnlmsg_exp_parse(nlh, &exp)) < 0)
304 err = pp->pp_cb((
struct nl_object *) exp, pp);
319 NLM_F_DUMP, AF_UNSPEC, 0);
322 static int exp_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
327 static int exp_get_tuple_attr(
int tuple)
332 case CTA_EXPECT_MASTER:
333 attr = NFNL_EXP_TUPLE_MASTER;
335 case CTA_EXPECT_MASK:
336 attr = NFNL_EXP_TUPLE_MASK;
339 attr = NFNL_EXP_TUPLE_NAT;
341 case CTA_EXPECT_TUPLE:
343 attr = NFNL_EXP_TUPLE_EXPECT;
350 static int nfnl_exp_build_tuple(
struct nl_msg *msg,
const struct nfnl_exp *exp,
353 struct nlattr *tuple, *ip, *proto;
354 struct nl_addr *addr;
358 family = nfnl_exp_get_family(exp);
360 type = exp_get_tuple_attr(cta);
362 if (cta == CTA_EXPECT_NAT)
368 goto nla_put_failure;
372 goto nla_put_failure;
374 addr = nfnl_exp_get_src(exp, type);
377 family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
380 addr = nfnl_exp_get_dst(exp, type);
383 family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
390 goto nla_put_failure;
392 if (nfnl_exp_test_l4protonum(exp, type))
393 NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_exp_get_l4protonum(exp, type));
395 if (nfnl_exp_test_ports(exp, type)) {
397 htons(nfnl_exp_get_src_port(exp, type)));
400 htons(nfnl_exp_get_dst_port(exp, type)));
403 if (nfnl_exp_test_icmp(exp, type)) {
405 htons(nfnl_exp_get_icmp_id(exp, type)));
408 nfnl_exp_get_icmp_type(exp, type));
411 nfnl_exp_get_icmp_code(exp, type));
423 static int nfnl_exp_build_nat(
struct nl_msg *msg,
const struct nfnl_exp *exp)
430 if (nfnl_exp_test_nat_dir(exp)) {
432 nfnl_exp_get_nat_dir(exp));
435 if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT)) < 0)
436 goto nla_put_failure;
445 static int nfnl_exp_build_message(
const struct nfnl_exp *exp,
int cmd,
int flags,
446 struct nl_msg **result)
452 nfnl_exp_get_family(exp), 0);
456 if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_TUPLE)) < 0)
459 if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASTER)) < 0)
462 if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0)
465 if (nfnl_exp_test_src(exp, NFNL_EXP_TUPLE_NAT)) {
466 if ((err = nfnl_exp_build_nat(msg, exp)) < 0)
470 if (nfnl_exp_test_class(exp))
471 NLA_PUT_U32(msg, CTA_EXPECT_CLASS, htonl(nfnl_exp_get_class(exp)));
473 if (nfnl_exp_test_fn(exp))
476 if (nfnl_exp_test_id(exp))
477 NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp)));
479 if (nfnl_exp_test_timeout(exp))
480 NLA_PUT_U32(msg, CTA_EXPECT_TIMEOUT, htonl(nfnl_exp_get_timeout(exp)));
482 if (nfnl_exp_test_helper_name(exp))
483 NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp));
485 if (nfnl_exp_test_zone(exp))
486 NLA_PUT_U16(msg, CTA_EXPECT_ZONE, htons(nfnl_exp_get_zone(exp)));
488 if (nfnl_exp_test_flags(exp))
489 NLA_PUT_U32(msg, CTA_EXPECT_FLAGS, htonl(nfnl_exp_get_flags(exp)));
502 int nfnl_exp_build_add_request(
const struct nfnl_exp *exp,
int flags,
503 struct nl_msg **result)
505 return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_NEW, flags, result);
508 int nfnl_exp_add(
struct nl_sock *sk,
const struct nfnl_exp *exp,
int flags)
513 if ((err = nfnl_exp_build_add_request(exp, flags, &msg)) < 0)
521 return wait_for_ack(sk);
524 int nfnl_exp_build_delete_request(
const struct nfnl_exp *exp,
int flags,
525 struct nl_msg **result)
527 return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_DELETE, flags, result);
530 int nfnl_exp_del(
struct nl_sock *sk,
const struct nfnl_exp *exp,
int flags)
535 if ((err = nfnl_exp_build_delete_request(exp, flags, &msg)) < 0)
543 return wait_for_ack(sk);
546 int nfnl_exp_build_query_request(
const struct nfnl_exp *exp,
int flags,
547 struct nl_msg **result)
549 return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_GET, flags, result);
552 int nfnl_exp_query(
struct nl_sock *sk,
const struct nfnl_exp *exp,
int flags)
557 if ((err = nfnl_exp_build_query_request(exp, flags, &msg)) < 0)
565 return wait_for_ack(sk);
597 static struct nl_af_group exp_groups[] = {
598 { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_NEW },
599 { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_UPDATE },
600 { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_DESTROY },
601 { END_OF_GROUP_LIST },
604 #define NFNLMSG_EXP_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK_EXP, (type)) 605 static struct nl_cache_ops nfnl_exp_ops = {
606 .co_name =
"netfilter/exp",
607 .co_hdrsize = NFNL_HDRLEN,
609 { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_NEW), NL_ACT_NEW,
"new" },
610 { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_GET), NL_ACT_GET,
"get" },
611 { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_DELETE), NL_ACT_DEL,
"del" },
612 END_OF_MSGTYPES_LIST,
614 .co_protocol = NETLINK_NETFILTER,
615 .co_groups = exp_groups,
616 .co_request_update = exp_request_update,
617 .co_msg_parser = exp_msg_parser,
618 .co_obj_ops = &exp_obj_ops,
621 static void __init exp_init(
void)
626 static void __exit exp_exit(
void)
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy)
parse attributes of a netlink message
int nfnl_exp_dump_request(struct nl_sock *sk)
Send nfnl exp dump request.
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Attribute validation policy.
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
int nfnl_exp_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
Build a expectation cache holding all expectations currently in the kernel.
uint8_t nfnlmsg_subtype(struct nlmsghdr *nlh)
Get netfilter message type from message.
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
NUL terminated character string.
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, const struct nla_policy *policy)
Create attribute index based on nested attribute.
int nfnl_send_simple(struct nl_sock *sk, uint8_t subsys_id, uint8_t type, int flags, uint8_t family, uint16_t res_id)
Send trivial netfilter netlink message.
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
uint8_t nfnlmsg_family(struct nlmsghdr *nlh)
Get netfilter family from message.
#define NLA_PUT_STRING(msg, attrtype, value)
Add string attribute to netlink message.
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
uint16_t type
Type of attribute or NLA_UNSPEC.
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
struct nl_msg * nfnlmsg_alloc_simple(uint8_t subsys_id, uint8_t type, int flags, uint8_t family, uint16_t res_id)
Allocate a new netfilter netlink message.
int nl_cache_alloc_and_fill(struct nl_cache_ops *ops, struct nl_sock *sock, struct nl_cache **result)
Allocate new cache and fill it.
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.