23 #include <sys/types.h>
24 #include <linux/netfilter/nfnetlink_conntrack.h>
26 #include <netlink-private/netlink.h>
27 #include <netlink/attr.h>
28 #include <netlink/netfilter/nfnl.h>
29 #include <netlink/netfilter/ct.h>
31 static struct nl_cache_ops nfnl_ct_ops;
33 #if __BYTE_ORDER == __BIG_ENDIAN
34 static uint64_t ntohll(uint64_t x)
38 static uint64_t htonll(uint64_t x)
42 #elif __BYTE_ORDER == __LITTLE_ENDIAN
43 static uint64_t ntohll(uint64_t x)
47 static uint64_t htonll(uint64_t x)
53 static struct nla_policy ct_policy[CTA_MAX+1] = {
56 [CTA_STATUS] = { .type =
NLA_U32 },
60 [CTA_TIMEOUT] = { .type =
NLA_U32 },
61 [CTA_MARK] = { .type =
NLA_U32 },
64 [CTA_USE] = { .type =
NLA_U32 },
66 [CTA_ZONE] = { .type =
NLA_U16 },
70 static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = {
75 static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = {
77 [CTA_IP_V4_DST] = { .type =
NLA_U32 },
78 [CTA_IP_V6_SRC] = { .minlen = 16 },
79 [CTA_IP_V6_DST] = { .minlen = 16 },
82 static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = {
84 [CTA_PROTO_SRC_PORT] = { .type =
NLA_U16 },
85 [CTA_PROTO_DST_PORT] = { .type =
NLA_U16 },
86 [CTA_PROTO_ICMP_ID] = { .type =
NLA_U16 },
87 [CTA_PROTO_ICMP_TYPE] = { .type =
NLA_U8 },
88 [CTA_PROTO_ICMP_CODE] = { .type =
NLA_U8 },
89 [CTA_PROTO_ICMPV6_ID] = { .type =
NLA_U16 },
90 [CTA_PROTO_ICMPV6_TYPE] = { .type =
NLA_U8 },
91 [CTA_PROTO_ICMPV6_CODE] = { .type =
NLA_U8 },
94 static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
98 static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = {
99 [CTA_PROTOINFO_TCP_STATE] = { .
type =
NLA_U8 },
100 [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type =
NLA_U8 },
101 [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type =
NLA_U8 },
102 [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .minlen = 2 },
103 [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .minlen = 2 },
107 static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = {
109 [CTA_COUNTERS_BYTES] = { .type =
NLA_U64 },
110 [CTA_COUNTERS32_PACKETS]= { .type =
NLA_U32 },
111 [CTA_COUNTERS32_BYTES] = { .type =
NLA_U32 },
114 static struct nla_policy ct_timestamp_policy[CTA_TIMESTAMP_MAX + 1] = {
116 [CTA_TIMESTAMP_STOP] = { .type =
NLA_U64 },
119 static int ct_parse_ip(
struct nfnl_ct *ct,
int repl,
struct nlattr *attr)
121 struct nlattr *tb[CTA_IP_MAX+1];
122 struct nl_addr *addr;
129 if (tb[CTA_IP_V4_SRC]) {
133 err = nfnl_ct_set_src(ct, repl, addr);
138 if (tb[CTA_IP_V4_DST]) {
142 err = nfnl_ct_set_dst(ct, repl, addr);
147 if (tb[CTA_IP_V6_SRC]) {
151 err = nfnl_ct_set_src(ct, repl, addr);
156 if (tb[CTA_IP_V6_DST]) {
160 err = nfnl_ct_set_dst(ct, repl, addr);
174 static int ct_parse_proto(
struct nfnl_ct *ct,
int repl,
struct nlattr *attr)
176 struct nlattr *tb[CTA_PROTO_MAX+1];
183 if (!repl && tb[CTA_PROTO_NUM])
184 nfnl_ct_set_proto(ct,
nla_get_u8(tb[CTA_PROTO_NUM]));
185 if (tb[CTA_PROTO_SRC_PORT])
186 nfnl_ct_set_src_port(ct, repl,
188 if (tb[CTA_PROTO_DST_PORT])
189 nfnl_ct_set_dst_port(ct, repl,
192 if (ct->ct_family == AF_INET) {
193 if (tb[CTA_PROTO_ICMP_ID])
194 nfnl_ct_set_icmp_id(ct, repl,
196 if (tb[CTA_PROTO_ICMP_TYPE])
197 nfnl_ct_set_icmp_type(ct, repl,
199 if (tb[CTA_PROTO_ICMP_CODE])
200 nfnl_ct_set_icmp_code(ct, repl,
202 }
else if (ct->ct_family == AF_INET6) {
203 if (tb[CTA_PROTO_ICMPV6_ID])
204 nfnl_ct_set_icmp_id(ct, repl,
206 if (tb[CTA_PROTO_ICMPV6_TYPE])
207 nfnl_ct_set_icmp_type(ct, repl,
209 if (tb[CTA_PROTO_ICMPV6_CODE])
210 nfnl_ct_set_icmp_code(ct, repl,
217 static int ct_parse_tuple(
struct nfnl_ct *ct,
int repl,
struct nlattr *attr)
219 struct nlattr *tb[CTA_TUPLE_MAX+1];
226 if (tb[CTA_TUPLE_IP]) {
227 err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]);
232 if (tb[CTA_TUPLE_PROTO]) {
233 err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]);
241 static int ct_parse_protoinfo_tcp(
struct nfnl_ct *ct,
struct nlattr *attr)
243 struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1];
247 ct_protoinfo_tcp_policy);
251 if (tb[CTA_PROTOINFO_TCP_STATE])
252 nfnl_ct_set_tcp_state(ct,
258 static int ct_parse_protoinfo(
struct nfnl_ct *ct,
struct nlattr *attr)
260 struct nlattr *tb[CTA_PROTOINFO_MAX+1];
264 ct_protoinfo_policy);
268 if (tb[CTA_PROTOINFO_TCP]) {
269 err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]);
277 static int ct_parse_counters(
struct nfnl_ct *ct,
int repl,
struct nlattr *attr)
279 struct nlattr *tb[CTA_COUNTERS_MAX+1];
286 if (tb[CTA_COUNTERS_PACKETS])
287 nfnl_ct_set_packets(ct, repl,
289 if (tb[CTA_COUNTERS32_PACKETS])
290 nfnl_ct_set_packets(ct, repl,
292 if (tb[CTA_COUNTERS_BYTES])
293 nfnl_ct_set_bytes(ct, repl,
295 if (tb[CTA_COUNTERS32_BYTES])
296 nfnl_ct_set_bytes(ct, repl,
302 int nfnlmsg_ct_group(
struct nlmsghdr *nlh)
305 case IPCTNL_MSG_CT_NEW:
306 if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
307 return NFNLGRP_CONNTRACK_NEW;
309 return NFNLGRP_CONNTRACK_UPDATE;
310 case IPCTNL_MSG_CT_DELETE:
311 return NFNLGRP_CONNTRACK_DESTROY;
317 static int ct_parse_timestamp(
struct nfnl_ct *ct,
struct nlattr *attr)
319 struct nlattr *tb[CTA_TIMESTAMP_MAX + 1];
323 ct_timestamp_policy);
327 if (tb[CTA_TIMESTAMP_START] && tb[CTA_TIMESTAMP_STOP])
328 nfnl_ct_set_timestamp(ct,
335 int nfnlmsg_ct_parse(
struct nlmsghdr *nlh,
struct nfnl_ct **result)
338 struct nlattr *tb[CTA_MAX+1];
341 ct = nfnl_ct_alloc();
345 ct->ce_msgtype = nlh->nlmsg_type;
347 err =
nlmsg_parse(nlh,
sizeof(
struct nfgenmsg), tb, CTA_MAX,
354 if (tb[CTA_TUPLE_ORIG]) {
355 err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]);
359 if (tb[CTA_TUPLE_REPLY]) {
360 err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]);
365 if (tb[CTA_PROTOINFO]) {
366 err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]);
372 nfnl_ct_set_status(ct, ntohl(
nla_get_u32(tb[CTA_STATUS])));
374 nfnl_ct_set_timeout(ct, ntohl(
nla_get_u32(tb[CTA_TIMEOUT])));
376 nfnl_ct_set_mark(ct, ntohl(
nla_get_u32(tb[CTA_MARK])));
378 nfnl_ct_set_use(ct, ntohl(
nla_get_u32(tb[CTA_USE])));
380 nfnl_ct_set_id(ct, ntohl(
nla_get_u32(tb[CTA_ID])));
382 nfnl_ct_set_zone(ct, ntohs(
nla_get_u16(tb[CTA_ZONE])));
384 if (tb[CTA_COUNTERS_ORIG]) {
385 err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]);
390 if (tb[CTA_COUNTERS_REPLY]) {
391 err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]);
396 if (tb[CTA_TIMESTAMP]) {
397 err = ct_parse_timestamp(ct, tb[CTA_TIMESTAMP]);
410 static int ct_msg_parser(
struct nl_cache_ops *ops,
struct sockaddr_nl *who,
411 struct nlmsghdr *nlh,
struct nl_parser_param *pp)
416 if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0)
419 err = pp->pp_cb((
struct nl_object *) ct, pp);
424 int nfnl_ct_dump_request(
struct nl_sock *sk)
427 NLM_F_DUMP, AF_UNSPEC, 0);
430 static int ct_request_update(
struct nl_cache *cache,
struct nl_sock *sk)
432 return nfnl_ct_dump_request(sk);
435 static int nfnl_ct_build_tuple(
struct nl_msg *msg,
const struct nfnl_ct *ct,
438 struct nlattr *tuple, *ip, *proto;
439 struct nl_addr *addr;
442 family = nfnl_ct_get_family(ct);
444 tuple =
nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG);
446 goto nla_put_failure;
450 goto nla_put_failure;
452 addr = nfnl_ct_get_src(ct, repl);
455 family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
458 addr = nfnl_ct_get_dst(ct, repl);
461 family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
468 goto nla_put_failure;
470 if (nfnl_ct_test_proto(ct))
471 NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct));
473 if (nfnl_ct_test_src_port(ct, repl))
475 htons(nfnl_ct_get_src_port(ct, repl)));
477 if (nfnl_ct_test_dst_port(ct, repl))
479 htons(nfnl_ct_get_dst_port(ct, repl)));
481 if (family == AF_INET) {
482 if (nfnl_ct_test_icmp_id(ct, repl))
484 htons(nfnl_ct_get_icmp_id(ct, repl)));
486 if (nfnl_ct_test_icmp_type(ct, repl))
488 nfnl_ct_get_icmp_type(ct, repl));
490 if (nfnl_ct_test_icmp_code(ct, repl))
492 nfnl_ct_get_icmp_code(ct, repl));
493 }
else if (family == AF_INET6) {
494 if (nfnl_ct_test_icmp_id(ct, repl))
496 htons(nfnl_ct_get_icmp_id(ct, repl)));
498 if (nfnl_ct_test_icmp_type(ct, repl))
500 nfnl_ct_get_icmp_type(ct, repl));
502 if (nfnl_ct_test_icmp_code(ct, repl))
504 nfnl_ct_get_icmp_code(ct, repl));
516 static int nfnl_ct_build_message(
const struct nfnl_ct *ct,
int cmd,
int flags,
517 struct nl_msg **result)
523 nfnl_ct_get_family(ct), 0);
527 if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0)
532 if ( nfnl_ct_get_src(ct, 1) && nfnl_ct_get_dst(ct, 1) )
533 if ((err = nfnl_ct_build_tuple(msg, ct, 1)) < 0)
536 if (nfnl_ct_test_status(ct))
537 NLA_PUT_U32(msg, CTA_STATUS, htonl(nfnl_ct_get_status(ct)));
539 if (nfnl_ct_test_timeout(ct))
540 NLA_PUT_U32(msg, CTA_TIMEOUT, htonl(nfnl_ct_get_timeout(ct)));
542 if (nfnl_ct_test_mark(ct))
543 NLA_PUT_U32(msg, CTA_MARK, htonl(nfnl_ct_get_mark(ct)));
545 if (nfnl_ct_test_id(ct))
546 NLA_PUT_U32(msg, CTA_ID, htonl(nfnl_ct_get_id(ct)));
548 if (nfnl_ct_test_zone(ct))
549 NLA_PUT_U16(msg, CTA_ZONE, htons(nfnl_ct_get_zone(ct)));
560 int nfnl_ct_build_add_request(
const struct nfnl_ct *ct,
int flags,
561 struct nl_msg **result)
563 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result);
566 int nfnl_ct_add(
struct nl_sock *sk,
const struct nfnl_ct *ct,
int flags)
571 if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0)
579 return wait_for_ack(sk);
582 int nfnl_ct_build_delete_request(
const struct nfnl_ct *ct,
int flags,
583 struct nl_msg **result)
585 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result);
588 int nfnl_ct_del(
struct nl_sock *sk,
const struct nfnl_ct *ct,
int flags)
593 if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0)
601 return wait_for_ack(sk);
604 int nfnl_ct_build_query_request(
const struct nfnl_ct *ct,
int flags,
605 struct nl_msg **result)
607 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result);
610 int nfnl_ct_query(
struct nl_sock *sk,
const struct nfnl_ct *ct,
int flags)
615 if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0)
623 return wait_for_ack(sk);
655 static struct nl_af_group ct_groups[] = {
656 { AF_UNSPEC, NFNLGRP_CONNTRACK_NEW },
657 { AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE },
658 { AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY },
659 { END_OF_GROUP_LIST },
662 #define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type))
663 static struct nl_cache_ops nfnl_ct_ops = {
664 .co_name =
"netfilter/ct",
665 .co_hdrsize = NFNL_HDRLEN,
667 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW,
"new" },
668 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET,
"get" },
669 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL,
"del" },
670 END_OF_MSGTYPES_LIST,
672 .co_protocol = NETLINK_NETFILTER,
673 .co_groups = ct_groups,
674 .co_request_update = ct_request_update,
675 .co_msg_parser = ct_msg_parser,
676 .co_obj_ops = &ct_obj_ops,
679 static void __init ct_init(
void)
684 static void __exit ct_exit(
void)
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
uint16_t nla_get_u16(struct nlattr *nla)
Return payload of 16 bit integer attribute.
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
int nfnl_ct_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
Build a conntrack cache holding all conntrack currently in the kernel.
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Attribute validation policy.
struct nl_addr * nl_addr_alloc_attr(struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
uint8_t nfnlmsg_subtype(struct nlmsghdr *nlh)
Get netfilter message type from message.
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, struct nla_policy *policy)
parse attributes of a netlink message
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
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 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.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
Create attribute index based on nested attribute.
uint8_t nla_get_u8(struct nlattr *nla)
Return value of 8 bit integer attribute.
#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.
uint64_t nla_get_u64(struct nlattr *nla)
Return payload of u64 attribute.
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.
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
uint32_t nla_get_u32(struct nlattr *nla)
Return payload of 32 bit integer attribute.
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.