22 #include <sys/types.h> 23 #include <linux/netfilter/nfnetlink_conntrack.h> 25 #include <netlink-local.h> 26 #include <netlink/attr.h> 27 #include <netlink/netfilter/nfnl.h> 28 #include <netlink/netfilter/ct.h> 32 #if __BYTE_ORDER == __BIG_ENDIAN 33 static uint64_t ntohll(uint64_t x)
37 #elif __BYTE_ORDER == __LITTLE_ENDIAN 38 static uint64_t ntohll(uint64_t x)
44 static struct nla_policy ct_policy[CTA_MAX+1] = {
47 [CTA_STATUS] = { .type =
NLA_U32 },
51 [CTA_TIMEOUT] = { .type =
NLA_U32 },
52 [CTA_MARK] = { .type =
NLA_U32 },
55 [CTA_USE] = { .type =
NLA_U32 },
60 static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = {
65 static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = {
67 [CTA_IP_V4_DST] = { .type =
NLA_U32 },
68 [CTA_IP_V6_SRC] = { .minlen = 16 },
69 [CTA_IP_V6_DST] = { .minlen = 16 },
72 static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = {
74 [CTA_PROTO_SRC_PORT] = { .type =
NLA_U16 },
75 [CTA_PROTO_DST_PORT] = { .type =
NLA_U16 },
76 [CTA_PROTO_ICMP_ID] = { .type =
NLA_U16 },
77 [CTA_PROTO_ICMP_TYPE] = { .type =
NLA_U8 },
78 [CTA_PROTO_ICMP_CODE] = { .type =
NLA_U8 },
79 [CTA_PROTO_ICMPV6_ID] = { .type =
NLA_U16 },
80 [CTA_PROTO_ICMPV6_TYPE] = { .type =
NLA_U8 },
81 [CTA_PROTO_ICMPV6_CODE] = { .type =
NLA_U8 },
84 static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
88 static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = {
89 [CTA_PROTOINFO_TCP_STATE] = { .
type =
NLA_U8 },
90 [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type =
NLA_U8 },
91 [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type =
NLA_U8 },
92 [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .minlen = 2 },
93 [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .minlen = 2 },
97 static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = {
99 [CTA_COUNTERS_BYTES] = { .type =
NLA_U64 },
100 [CTA_COUNTERS32_PACKETS]= { .type =
NLA_U32 },
101 [CTA_COUNTERS32_BYTES] = { .type =
NLA_U32 },
104 static int ct_parse_ip(
struct nfnl_ct *ct,
int repl,
struct nlattr *attr)
106 struct nlattr *tb[CTA_IP_MAX+1];
107 struct nl_addr *addr;
114 if (tb[CTA_IP_V4_SRC]) {
118 err = nfnl_ct_set_src(ct, repl, addr);
123 if (tb[CTA_IP_V4_DST]) {
127 err = nfnl_ct_set_dst(ct, repl, addr);
132 if (tb[CTA_IP_V6_SRC]) {
136 err = nfnl_ct_set_src(ct, repl, addr);
141 if (tb[CTA_IP_V6_DST]) {
145 err = nfnl_ct_set_dst(ct, repl, addr);
154 return nl_get_errno();
159 static int ct_parse_proto(
struct nfnl_ct *ct,
int repl,
struct nlattr *attr)
161 struct nlattr *tb[CTA_PROTO_MAX+1];
168 if (!repl && tb[CTA_PROTO_NUM])
169 nfnl_ct_set_proto(ct,
nla_get_u8(tb[CTA_PROTO_NUM]));
170 if (tb[CTA_PROTO_SRC_PORT])
171 nfnl_ct_set_src_port(ct, repl,
173 if (tb[CTA_PROTO_DST_PORT])
174 nfnl_ct_set_dst_port(ct, repl,
176 if (tb[CTA_PROTO_ICMP_ID])
177 nfnl_ct_set_icmp_id(ct, repl,
179 if (tb[CTA_PROTO_ICMP_TYPE])
180 nfnl_ct_set_icmp_type(ct, repl,
182 if (tb[CTA_PROTO_ICMP_CODE])
183 nfnl_ct_set_icmp_code(ct, repl,
189 static int ct_parse_tuple(
struct nfnl_ct *ct,
int repl,
struct nlattr *attr)
191 struct nlattr *tb[CTA_TUPLE_MAX+1];
198 if (tb[CTA_TUPLE_IP]) {
199 err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]);
204 if (tb[CTA_TUPLE_PROTO]) {
205 err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]);
213 static int ct_parse_protoinfo_tcp(
struct nfnl_ct *ct,
struct nlattr *attr)
215 struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1];
219 ct_protoinfo_tcp_policy);
223 if (tb[CTA_PROTOINFO_TCP_STATE])
224 nfnl_ct_set_tcp_state(ct,
230 static int ct_parse_protoinfo(
struct nfnl_ct *ct,
struct nlattr *attr)
232 struct nlattr *tb[CTA_PROTOINFO_MAX+1];
236 ct_protoinfo_policy);
240 if (tb[CTA_PROTOINFO_TCP]) {
241 err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]);
249 static int ct_parse_counters(
struct nfnl_ct *ct,
int repl,
struct nlattr *attr)
251 struct nlattr *tb[CTA_COUNTERS_MAX+1];
258 if (tb[CTA_COUNTERS_PACKETS])
259 nfnl_ct_set_packets(ct, repl,
261 if (tb[CTA_COUNTERS32_PACKETS])
262 nfnl_ct_set_packets(ct, repl,
264 if (tb[CTA_COUNTERS_BYTES])
265 nfnl_ct_set_bytes(ct, repl,
267 if (tb[CTA_COUNTERS32_BYTES])
268 nfnl_ct_set_bytes(ct, repl,
274 int nfnlmsg_ct_group(
struct nlmsghdr *nlh)
277 case IPCTNL_MSG_CT_NEW:
279 return NFNLGRP_CONNTRACK_NEW;
281 return NFNLGRP_CONNTRACK_UPDATE;
282 case IPCTNL_MSG_CT_DELETE:
283 return NFNLGRP_CONNTRACK_DESTROY;
289 struct nfnl_ct *nfnlmsg_ct_parse(
struct nlmsghdr *nlh)
292 struct nlattr *tb[CTA_MAX+1];
295 ct = nfnl_ct_alloc();
301 err =
nlmsg_parse(nlh,
sizeof(
struct nfgenmsg), tb, CTA_MAX,
308 if (tb[CTA_TUPLE_ORIG]) {
309 err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]);
313 if (tb[CTA_TUPLE_REPLY]) {
314 err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]);
319 if (tb[CTA_PROTOINFO]) {
320 err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]);
326 nfnl_ct_set_status(ct, ntohl(
nla_get_u32(tb[CTA_STATUS])));
328 nfnl_ct_set_timeout(ct, ntohl(
nla_get_u32(tb[CTA_TIMEOUT])));
330 nfnl_ct_set_mark(ct, ntohl(
nla_get_u32(tb[CTA_MARK])));
332 nfnl_ct_set_use(ct, ntohl(
nla_get_u32(tb[CTA_USE])));
334 nfnl_ct_set_id(ct, ntohl(
nla_get_u32(tb[CTA_ID])));
336 if (tb[CTA_COUNTERS_ORIG]) {
337 err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]);
342 if (tb[CTA_COUNTERS_REPLY]) {
343 err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]);
361 ct = nfnlmsg_ct_parse(nlh);
365 err = pp->pp_cb((
struct nl_object *) ct, pp);
376 err = nl_get_errno();
380 int nfnl_ct_dump_request(
struct nl_handle *h)
386 static int ct_request_update(
struct nl_cache *c,
struct nl_handle *h)
388 return nfnl_ct_dump_request(h);
409 struct nl_cache *cache;
433 { AF_UNSPEC, NFNLGRP_CONNTRACK_NEW },
434 { AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE },
435 { AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY },
436 { END_OF_GROUP_LIST },
439 #define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type)) 441 .co_name =
"netfilter/ct",
442 .co_hdrsize = NFNL_HDRLEN,
444 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW,
"new" },
445 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET,
"get" },
446 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL,
"del" },
447 END_OF_MSGTYPES_LIST,
449 .co_protocol = NETLINK_NETFILTER,
450 .co_groups = ct_groups,
451 .co_request_update = ct_request_update,
452 .co_msg_parser = ct_msg_parser,
453 .co_obj_ops = &ct_obj_ops,
456 static void __init ct_init(
void)
461 static void __exit ct_exit(
void)
uint16_t nla_get_u16(struct nlattr *nla)
Return payload of u16 attribute.
uint16_t nlmsg_type
Message type (content type)
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
attribute validation policy
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
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
int nl_cache_refill(struct nl_handle *handle, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
#define NLM_F_CREATE
Create config object if it doesn't already exist.
#define NLM_F_EXCL
Don't replace the config object if it already exists.
#define NLM_F_DUMP
Dump all entries.
int nla_parse_nested(struct nlattr *tb[], int maxtype, struct nlattr *nla, struct nla_policy *policy)
parse nested attributes
uint8_t nla_get_u8(struct nlattr *nla)
Return payload of u8 attribute.
struct nl_addr * nla_get_addr(struct nlattr *nla, int family)
Return payload of address attribute.
uint8_t nfnlmsg_family(struct nlmsghdr *nlh)
Get netfilter family from message.
uint16_t nlmsg_flags
Message flags.
int nfnl_send_simple(struct nl_handle *handle, uint8_t subsys_id, uint8_t type, int flags, uint8_t family, uint16_t res_id)
Send trivial netfilter netlink message.
uint64_t nla_get_u64(struct nlattr *nla)
Return payload of u64 attribute.
uint16_t type
Type of attribute or NLA_UNSPEC.
struct nl_cache * nfnl_ct_alloc_cache(struct nl_handle *handle)
Build a conntrack cache holding all conntrack currently in the kernel.
uint32_t nla_get_u32(struct nlattr *nla)
Return payload of u32 attribute.
Address family to netlink group association.
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate an empty cache.