2 * lib/netfilter/ct.c Conntrack
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation version 2.1
9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
10 * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
11 * Copyright (c) 2007 Secure Computing Corporation
12 * Copyright (c= 2008 Patrick McHardy <kaber@trash.net>
17 * @defgroup ct Conntrack
23 #include <sys/types.h>
24 #include <linux/netfilter/nfnetlink_conntrack.h>
26 #include <netlink-local.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 #elif __BYTE_ORDER == __LITTLE_ENDIAN
39 static uint64_t ntohll(uint64_t x)
45 static struct nla_policy ct_policy[CTA_MAX+1] = {
46 [CTA_TUPLE_ORIG] = { .type = NLA_NESTED },
47 [CTA_TUPLE_REPLY] = { .type = NLA_NESTED },
48 [CTA_STATUS] = { .type = NLA_U32 },
49 [CTA_PROTOINFO] = { .type = NLA_NESTED },
52 [CTA_TIMEOUT] = { .type = NLA_U32 },
53 [CTA_MARK] = { .type = NLA_U32 },
54 [CTA_COUNTERS_ORIG] = { .type = NLA_NESTED },
55 [CTA_COUNTERS_REPLY] = { .type = NLA_NESTED },
56 [CTA_USE] = { .type = NLA_U32 },
57 [CTA_ID] = { .type = NLA_U32 },
61 static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = {
62 [CTA_TUPLE_IP] = { .type = NLA_NESTED },
63 [CTA_TUPLE_PROTO] = { .type = NLA_NESTED },
66 static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = {
67 [CTA_IP_V4_SRC] = { .type = NLA_U32 },
68 [CTA_IP_V4_DST] = { .type = NLA_U32 },
69 [CTA_IP_V6_SRC] = { .minlen = 16 },
70 [CTA_IP_V6_DST] = { .minlen = 16 },
73 static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = {
74 [CTA_PROTO_NUM] = { .type = NLA_U8 },
75 [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 },
76 [CTA_PROTO_DST_PORT] = { .type = NLA_U16 },
77 [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 },
78 [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 },
79 [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 },
80 [CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 },
81 [CTA_PROTO_ICMPV6_TYPE] = { .type = NLA_U8 },
82 [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 },
85 static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
86 [CTA_PROTOINFO_TCP] = { .type = NLA_NESTED },
89 static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = {
90 [CTA_PROTOINFO_TCP_STATE] = { .type = NLA_U8 },
91 [CTA_PROTOINFO_TCP_WSCALE_ORIGINAL] = { .type = NLA_U8 },
92 [CTA_PROTOINFO_TCP_WSCALE_REPLY] = { .type = NLA_U8 },
93 [CTA_PROTOINFO_TCP_FLAGS_ORIGINAL] = { .minlen = 2 },
94 [CTA_PROTOINFO_TCP_FLAGS_REPLY] = { .minlen = 2 },
98 static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = {
99 [CTA_COUNTERS_PACKETS] = { .type = NLA_U64 },
100 [CTA_COUNTERS_BYTES] = { .type = NLA_U64 },
101 [CTA_COUNTERS32_PACKETS]= { .type = NLA_U32 },
102 [CTA_COUNTERS32_BYTES] = { .type = NLA_U32 },
105 static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr)
107 struct nlattr *tb[CTA_IP_MAX+1];
108 struct nl_addr *addr;
111 err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy);
115 if (tb[CTA_IP_V4_SRC]) {
116 addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET);
119 err = nfnl_ct_set_src(ct, repl, addr);
124 if (tb[CTA_IP_V4_DST]) {
125 addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET);
128 err = nfnl_ct_set_dst(ct, repl, addr);
133 if (tb[CTA_IP_V6_SRC]) {
134 addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6);
137 err = nfnl_ct_set_src(ct, repl, addr);
142 if (tb[CTA_IP_V6_DST]) {
143 addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6);
146 err = nfnl_ct_set_dst(ct, repl, addr);
160 static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr)
162 struct nlattr *tb[CTA_PROTO_MAX+1];
165 err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy);
169 if (!repl && tb[CTA_PROTO_NUM])
170 nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM]));
171 if (tb[CTA_PROTO_SRC_PORT])
172 nfnl_ct_set_src_port(ct, repl,
173 ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT])));
174 if (tb[CTA_PROTO_DST_PORT])
175 nfnl_ct_set_dst_port(ct, repl,
176 ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT])));
177 if (tb[CTA_PROTO_ICMP_ID])
178 nfnl_ct_set_icmp_id(ct, repl,
179 ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])));
180 if (tb[CTA_PROTO_ICMP_TYPE])
181 nfnl_ct_set_icmp_type(ct, repl,
182 nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
183 if (tb[CTA_PROTO_ICMP_CODE])
184 nfnl_ct_set_icmp_code(ct, repl,
185 nla_get_u8(tb[CTA_PROTO_ICMP_CODE]));
190 static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr)
192 struct nlattr *tb[CTA_TUPLE_MAX+1];
195 err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy);
199 if (tb[CTA_TUPLE_IP]) {
200 err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]);
205 if (tb[CTA_TUPLE_PROTO]) {
206 err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]);
214 static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr)
216 struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1];
219 err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr,
220 ct_protoinfo_tcp_policy);
224 if (tb[CTA_PROTOINFO_TCP_STATE])
225 nfnl_ct_set_tcp_state(ct,
226 nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]));
231 static int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr)
233 struct nlattr *tb[CTA_PROTOINFO_MAX+1];
236 err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr,
237 ct_protoinfo_policy);
241 if (tb[CTA_PROTOINFO_TCP]) {
242 err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]);
250 static int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr)
252 struct nlattr *tb[CTA_COUNTERS_MAX+1];
255 err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy);
259 if (tb[CTA_COUNTERS_PACKETS])
260 nfnl_ct_set_packets(ct, repl,
261 ntohll(nla_get_u64(tb[CTA_COUNTERS_PACKETS])));
262 if (tb[CTA_COUNTERS32_PACKETS])
263 nfnl_ct_set_packets(ct, repl,
264 ntohl(nla_get_u32(tb[CTA_COUNTERS32_PACKETS])));
265 if (tb[CTA_COUNTERS_BYTES])
266 nfnl_ct_set_bytes(ct, repl,
267 ntohll(nla_get_u64(tb[CTA_COUNTERS_BYTES])));
268 if (tb[CTA_COUNTERS32_BYTES])
269 nfnl_ct_set_bytes(ct, repl,
270 ntohl(nla_get_u32(tb[CTA_COUNTERS32_BYTES])));
275 int nfnlmsg_ct_group(struct nlmsghdr *nlh)
277 switch (nfnlmsg_subtype(nlh)) {
278 case IPCTNL_MSG_CT_NEW:
279 if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
280 return NFNLGRP_CONNTRACK_NEW;
282 return NFNLGRP_CONNTRACK_UPDATE;
283 case IPCTNL_MSG_CT_DELETE:
284 return NFNLGRP_CONNTRACK_DESTROY;
290 int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result)
293 struct nlattr *tb[CTA_MAX+1];
296 ct = nfnl_ct_alloc();
300 ct->ce_msgtype = nlh->nlmsg_type;
302 err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX,
307 nfnl_ct_set_family(ct, nfnlmsg_family(nlh));
309 if (tb[CTA_TUPLE_ORIG]) {
310 err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]);
314 if (tb[CTA_TUPLE_REPLY]) {
315 err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]);
320 if (tb[CTA_PROTOINFO]) {
321 err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]);
327 nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS])));
329 nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT])));
331 nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK])));
333 nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE])));
335 nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID])));
337 if (tb[CTA_COUNTERS_ORIG]) {
338 err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]);
343 if (tb[CTA_COUNTERS_REPLY]) {
344 err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]);
357 static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
358 struct nlmsghdr *nlh, struct nl_parser_param *pp)
363 if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0)
366 err = pp->pp_cb((struct nl_object *) ct, pp);
372 int nfnl_ct_dump_request(struct nl_sock *sk)
374 return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET,
375 NLM_F_DUMP, AF_UNSPEC, 0);
378 static int ct_request_update(struct nl_cache *cache, struct nl_sock *sk)
380 return nfnl_ct_dump_request(sk);
383 static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
386 struct nlattr *tuple, *ip, *proto;
387 struct nl_addr *addr;
390 family = nfnl_ct_get_family(ct);
392 tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG);
394 goto nla_put_failure;
396 ip = nla_nest_start(msg, CTA_TUPLE_IP);
398 goto nla_put_failure;
400 addr = nfnl_ct_get_src(ct, repl);
403 family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
406 addr = nfnl_ct_get_dst(ct, repl);
409 family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
412 nla_nest_end(msg, ip);
414 proto = nla_nest_start(msg, CTA_TUPLE_PROTO);
416 goto nla_put_failure;
418 if (nfnl_ct_test_proto(ct))
419 NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct));
421 if (nfnl_ct_test_src_port(ct, repl))
422 NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT,
423 htons(nfnl_ct_get_src_port(ct, repl)));
425 if (nfnl_ct_test_dst_port(ct, repl))
426 NLA_PUT_U16(msg, CTA_PROTO_DST_PORT,
427 htons(nfnl_ct_get_dst_port(ct, repl)));
429 if (nfnl_ct_test_icmp_id(ct, repl))
430 NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
431 htons(nfnl_ct_get_icmp_id(ct, repl)));
433 if (nfnl_ct_test_icmp_type(ct, repl))
434 NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
435 nfnl_ct_get_icmp_type(ct, repl));
437 if (nfnl_ct_test_icmp_code(ct, repl))
438 NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
439 nfnl_ct_get_icmp_code(ct, repl));
441 nla_nest_end(msg, proto);
443 nla_nest_end(msg, tuple);
450 static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags,
451 struct nl_msg **result)
456 msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags,
457 nfnl_ct_get_family(ct), 0);
461 if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0)
472 int nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags,
473 struct nl_msg **result)
475 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result);
478 int nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
483 if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0)
486 err = nl_send_auto_complete(sk, msg);
491 return wait_for_ack(sk);
494 int nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags,
495 struct nl_msg **result)
497 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result);
500 int nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
505 if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0)
508 err = nl_send_auto_complete(sk, msg);
513 return wait_for_ack(sk);
516 int nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags,
517 struct nl_msg **result)
519 return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result);
522 int nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
527 if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0)
530 err = nl_send_auto_complete(sk, msg);
535 return wait_for_ack(sk);
539 * @name Cache Management
544 * Build a conntrack cache holding all conntrack currently in the kernel
545 * @arg sk Netlink socket.
546 * @arg result Pointer to store resulting cache.
548 * Allocates a new cache, initializes it properly and updates it to
549 * contain all conntracks currently in the kernel.
551 * @return 0 on success or a negative error code.
553 int nfnl_ct_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
555 return nl_cache_alloc_and_fill(&nfnl_ct_ops, sk, result);
561 * @name Conntrack Addition
567 static struct nl_af_group ct_groups[] = {
568 { AF_UNSPEC, NFNLGRP_CONNTRACK_NEW },
569 { AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE },
570 { AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY },
571 { END_OF_GROUP_LIST },
574 #define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type))
575 static struct nl_cache_ops nfnl_ct_ops = {
576 .co_name = "netfilter/ct",
577 .co_hdrsize = NFNL_HDRLEN,
579 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" },
580 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" },
581 { NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" },
582 END_OF_MSGTYPES_LIST,
584 .co_protocol = NETLINK_NETFILTER,
585 .co_groups = ct_groups,
586 .co_request_update = ct_request_update,
587 .co_msg_parser = ct_msg_parser,
588 .co_obj_ops = &ct_obj_ops,
591 static void __init ct_init(void)
593 nl_cache_mngt_register(&nfnl_ct_ops);
596 static void __exit ct_exit(void)
598 nl_cache_mngt_unregister(&nfnl_ct_ops);