24 #include <sys/types.h>
25 #include <linux/netfilter/nfnetlink_conntrack.h>
27 #include <netlink-private/netlink.h>
28 #include <netlink/attr.h>
29 #include <netlink/netfilter/nfnl.h>
30 #include <netlink/netfilter/exp.h>
32 static struct nl_cache_ops nfnl_exp_ops;
34 static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = {
38 [CTA_EXPECT_TIMEOUT] = { .type =
NLA_U32 },
39 [CTA_EXPECT_ID] = { .type =
NLA_U32 },
40 [CTA_EXPECT_HELP_NAME] = { .type =
NLA_STRING },
41 [CTA_EXPECT_ZONE] = { .type =
NLA_U16 },
42 [CTA_EXPECT_FLAGS] = { .type =
NLA_U32 },
43 [CTA_EXPECT_CLASS] = { .type =
NLA_U32 },
48 static struct nla_policy exp_tuple_policy[CTA_TUPLE_MAX+1] = {
53 static struct nla_policy exp_ip_policy[CTA_IP_MAX+1] = {
55 [CTA_IP_V4_DST] = { .type =
NLA_U32 },
56 [CTA_IP_V6_SRC] = { .minlen = 16 },
57 [CTA_IP_V6_DST] = { .minlen = 16 },
60 static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = {
62 [CTA_PROTO_SRC_PORT] = { .type =
NLA_U16 },
63 [CTA_PROTO_DST_PORT] = { .type =
NLA_U16 },
64 [CTA_PROTO_ICMP_ID] = { .type =
NLA_U16 },
65 [CTA_PROTO_ICMP_TYPE] = { .type =
NLA_U8 },
66 [CTA_PROTO_ICMP_CODE] = { .type =
NLA_U8 },
67 [CTA_PROTO_ICMPV6_ID] = { .type =
NLA_U16 },
68 [CTA_PROTO_ICMPV6_TYPE] = { .type =
NLA_U8 },
69 [CTA_PROTO_ICMPV6_CODE] = { .type =
NLA_U8 },
72 static struct nla_policy exp_nat_policy[CTA_EXPECT_NAT_MAX+1] = {
74 [CTA_EXPECT_NAT_TUPLE] = { .type =
NLA_NESTED },
77 static int exp_parse_ip(
struct nfnl_exp *exp,
int tuple,
struct nlattr *attr)
79 struct nlattr *tb[CTA_IP_MAX+1];
87 if (tb[CTA_IP_V4_SRC]) {
91 err = nfnl_exp_set_src(exp, tuple, addr);
96 if (tb[CTA_IP_V4_DST]) {
100 err = nfnl_exp_set_dst(exp, tuple, addr);
105 if (tb[CTA_IP_V6_SRC]) {
109 err = nfnl_exp_set_src(exp, tuple, addr);
114 if (tb[CTA_IP_V6_DST]) {
118 err = nfnl_exp_set_dst(exp, tuple, addr);
132 static int exp_parse_proto(
struct nfnl_exp *exp,
int tuple,
struct nlattr *attr)
134 struct nlattr *tb[CTA_PROTO_MAX+1];
136 uint16_t srcport = 0, dstport = 0, icmpid = 0;
137 uint8_t icmptype = 0, icmpcode = 0;
143 if (tb[CTA_PROTO_NUM])
144 nfnl_exp_set_l4protonum(exp, tuple,
nla_get_u8(tb[CTA_PROTO_NUM]));
146 if (tb[CTA_PROTO_SRC_PORT])
147 srcport = ntohs(
nla_get_u16(tb[CTA_PROTO_SRC_PORT]));
148 if (tb[CTA_PROTO_DST_PORT])
149 dstport = ntohs(
nla_get_u16(tb[CTA_PROTO_DST_PORT]));
150 if (tb[CTA_PROTO_SRC_PORT] || tb[CTA_PROTO_DST_PORT])
151 nfnl_exp_set_ports(exp, tuple, srcport, dstport);
153 if (tb[CTA_PROTO_ICMP_ID])
154 icmpid = ntohs(
nla_get_u16(tb[CTA_PROTO_ICMP_ID]));
155 if (tb[CTA_PROTO_ICMP_TYPE])
156 icmptype =
nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]);
157 if (tb[CTA_PROTO_ICMP_CODE])
158 icmpcode =
nla_get_u8(tb[CTA_PROTO_ICMP_CODE]);
159 if (tb[CTA_PROTO_ICMP_ID] || tb[CTA_PROTO_ICMP_TYPE] || tb[CTA_PROTO_ICMP_CODE])
160 nfnl_exp_set_icmp(exp, tuple, icmpid, icmptype, icmpcode);
164 static int exp_parse_tuple(
struct nfnl_exp *exp,
int tuple,
struct nlattr *attr)
166 struct nlattr *tb[CTA_TUPLE_MAX+1];
173 if (tb[CTA_TUPLE_IP]) {
174 err = exp_parse_ip(exp, tuple, tb[CTA_TUPLE_IP]);
179 if (tb[CTA_TUPLE_PROTO]) {
180 err = exp_parse_proto(exp, tuple, tb[CTA_TUPLE_PROTO]);
188 static int exp_parse_nat(
struct nfnl_exp *exp,
struct nlattr *attr)
190 struct nlattr *tb[CTA_EXPECT_NAT_MAX+1];
197 if (tb[CTA_EXPECT_NAT_DIR])
198 nfnl_exp_set_nat_dir(exp,
nla_get_u32(tb[CTA_EXPECT_NAT_DIR]));
200 if (tb[CTA_EXPECT_NAT_TUPLE]) {
201 err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_NAT, tb[CTA_EXPECT_NAT_TUPLE]);
209 int nfnlmsg_exp_group(
struct nlmsghdr *nlh)
212 case IPCTNL_MSG_EXP_NEW:
213 if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
214 return NFNLGRP_CONNTRACK_EXP_NEW;
216 return NFNLGRP_CONNTRACK_EXP_UPDATE;
217 case IPCTNL_MSG_EXP_DELETE:
218 return NFNLGRP_CONNTRACK_EXP_DESTROY;
224 int nfnlmsg_exp_parse(
struct nlmsghdr *nlh,
struct nfnl_exp **result)
226 struct nfnl_exp *exp;
227 struct nlattr *tb[CTA_MAX+1];
230 exp = nfnl_exp_alloc();
234 exp->ce_msgtype = nlh->nlmsg_type;
236 err =
nlmsg_parse(nlh,
sizeof(
struct nfgenmsg), tb, CTA_EXPECT_MAX,
243 if (tb[CTA_EXPECT_TUPLE]) {
244 err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_EXPECT, tb[CTA_EXPECT_TUPLE]);
248 if (tb[CTA_EXPECT_MASTER]) {
249 err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASTER, tb[CTA_EXPECT_MASTER]);
253 if (tb[CTA_EXPECT_MASK]) {
254 err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASK, tb[CTA_EXPECT_MASK]);
259 if (tb[CTA_EXPECT_NAT]) {
260 err = exp_parse_nat(exp, tb[CTA_EXPECT_MASK]);
265 if (tb[CTA_EXPECT_CLASS])
266 nfnl_exp_set_class(exp, ntohl(
nla_get_u32(tb[CTA_EXPECT_CLASS])));
268 if (tb[CTA_EXPECT_FN])
269 nfnl_exp_set_fn(exp,
nla_data(tb[CTA_EXPECT_FN]));
271 if (tb[CTA_EXPECT_TIMEOUT])
272 nfnl_exp_set_timeout(exp, ntohl(
nla_get_u32(tb[CTA_EXPECT_TIMEOUT])));
274 if (tb[CTA_EXPECT_ID])
275 nfnl_exp_set_id(exp, ntohl(
nla_get_u32(tb[CTA_EXPECT_ID])));
277 if (tb[CTA_EXPECT_HELP_NAME])
278 nfnl_exp_set_helper_name(exp,
nla_data(tb[CTA_EXPECT_HELP_NAME]));
280 if (tb[CTA_EXPECT_ZONE])
281 nfnl_exp_set_zone(exp, ntohs(
nla_get_u16(tb[CTA_EXPECT_ZONE])));
283 if (tb[CTA_EXPECT_FLAGS])
284 nfnl_exp_set_flags(exp, ntohl(
nla_get_u32(tb[CTA_EXPECT_FLAGS])));
294 static int exp_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
295 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
297 struct nfnl_exp *exp;
300 if ((err = nfnlmsg_exp_parse(nlh, &exp)) < 0)
303 err = pp->pp_cb((
struct nl_object *) exp, pp);
309 int nfnl_exp_dump_request(
struct nl_sock *sk)
312 NLM_F_DUMP, AF_UNSPEC, 0);
315 static int exp_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
317 return nfnl_exp_dump_request(sk);
320 static int exp_get_tuple_attr(
int tuple)
325 case CTA_EXPECT_MASTER:
326 attr = NFNL_EXP_TUPLE_MASTER;
328 case CTA_EXPECT_MASK:
329 attr = NFNL_EXP_TUPLE_MASK;
332 attr = NFNL_EXP_TUPLE_NAT;
334 case CTA_EXPECT_TUPLE:
336 attr = NFNL_EXP_TUPLE_EXPECT;
343 static int nfnl_exp_build_tuple(
struct nl_msg *msg,
const struct nfnl_exp *exp,
346 struct nlattr *tuple, *ip, *proto;
347 struct nl_addr *addr;
350 family = nfnl_exp_get_family(exp);
352 int type = exp_get_tuple_attr(cta);
354 if (cta == CTA_EXPECT_NAT)
360 goto nla_put_failure;
364 goto nla_put_failure;
366 addr = nfnl_exp_get_src(exp, type);
369 family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
372 addr = nfnl_exp_get_dst(exp, type);
375 family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
382 goto nla_put_failure;
384 if (nfnl_exp_test_l4protonum(exp, type))
385 NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_exp_get_l4protonum(exp, type));
387 if (nfnl_exp_test_ports(exp, type)) {
389 htons(nfnl_exp_get_src_port(exp, type)));
392 htons(nfnl_exp_get_dst_port(exp, type)));
395 if (nfnl_exp_test_icmp(exp, type)) {
397 htons(nfnl_exp_get_icmp_id(exp, type)));
400 nfnl_exp_get_icmp_type(exp, type));
403 nfnl_exp_get_icmp_code(exp, type));
415 static int nfnl_exp_build_nat(
struct nl_msg *msg,
const struct nfnl_exp *exp)
422 if (nfnl_exp_test_nat_dir(exp)) {
424 nfnl_exp_get_nat_dir(exp));
427 if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT)) < 0)
428 goto nla_put_failure;
437 static int nfnl_exp_build_message(
const struct nfnl_exp *exp,
int cmd,
int flags,
438 struct nl_msg **result)
444 nfnl_exp_get_family(exp), 0);
448 if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_TUPLE)) < 0)
451 if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASTER)) < 0)
454 if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0)
457 if (nfnl_exp_test_src(exp, NFNL_EXP_TUPLE_NAT)) {
458 if ((err = nfnl_exp_build_nat(msg, exp)) < 0)
462 if (nfnl_exp_test_class(exp))
463 NLA_PUT_U32(msg, CTA_EXPECT_CLASS, htonl(nfnl_exp_get_class(exp)));
465 if (nfnl_exp_test_fn(exp))
468 if (nfnl_exp_test_id(exp))
469 NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp)));
471 if (nfnl_exp_test_timeout(exp))
472 NLA_PUT_U32(msg, CTA_EXPECT_TIMEOUT, htonl(nfnl_exp_get_timeout(exp)));
474 if (nfnl_exp_test_helper_name(exp))
475 NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp));
477 if (nfnl_exp_test_zone(exp))
478 NLA_PUT_U16(msg, CTA_EXPECT_ZONE, htons(nfnl_exp_get_zone(exp)));
480 if (nfnl_exp_test_flags(exp))
481 NLA_PUT_U32(msg, CTA_EXPECT_FLAGS, htonl(nfnl_exp_get_flags(exp)));
492 int nfnl_exp_build_add_request(
const struct nfnl_exp *exp,
int flags,
493 struct nl_msg **result)
495 return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_NEW, flags, result);
498 int nfnl_exp_add(
struct nl_sock *sk,
const struct nfnl_exp *exp,
int flags)
503 if ((err = nfnl_exp_build_add_request(exp, flags, &msg)) < 0)
511 return wait_for_ack(sk);
514 int nfnl_exp_build_delete_request(
const struct nfnl_exp *exp,
int flags,
515 struct nl_msg **result)
517 return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_DELETE, flags, result);
520 int nfnl_exp_del(
struct nl_sock *sk,
const struct nfnl_exp *exp,
int flags)
525 if ((err = nfnl_exp_build_delete_request(exp, flags, &msg)) < 0)
533 return wait_for_ack(sk);
536 int nfnl_exp_build_query_request(
const struct nfnl_exp *exp,
int flags,
537 struct nl_msg **result)
539 return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_GET, flags, result);
542 int nfnl_exp_query(
struct nl_sock *sk,
const struct nfnl_exp *exp,
int flags)
547 if ((err = nfnl_exp_build_query_request(exp, flags, &msg)) < 0)
555 return wait_for_ack(sk);
587 static struct nl_af_group exp_groups[] = {
588 { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_NEW },
589 { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_UPDATE },
590 { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_DESTROY },
591 { END_OF_GROUP_LIST },
594 #define NFNLMSG_EXP_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK_EXP, (type))
595 static struct nl_cache_ops nfnl_exp_ops = {
596 .co_name =
"netfilter/exp",
597 .co_hdrsize = NFNL_HDRLEN,
599 { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_NEW), NL_ACT_NEW,
"new" },
600 { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_GET), NL_ACT_GET,
"get" },
601 { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_DELETE), NL_ACT_DEL,
"del" },
602 END_OF_MSGTYPES_LIST,
604 .co_protocol = NETLINK_NETFILTER,
605 .co_groups = exp_groups,
606 .co_request_update = exp_request_update,
607 .co_msg_parser = exp_msg_parser,
608 .co_obj_ops = &exp_obj_ops,
611 static void __init exp_init(
void)
616 static void __exit exp_exit(
void)