ct.c revision eed2afaab7aa72fae393a395a8879b91a922ff5e
1/*
2 * lib/netfilter/ct.c	Conntrack
3 *
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
7 *	of the License.
8 *
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>
13 */
14
15/**
16 * @ingroup nfnl
17 * @defgroup ct Conntrack
18 * @brief
19 * @{
20 */
21
22#include <byteswap.h>
23#include <sys/types.h>
24#include <linux/netfilter/nfnetlink_conntrack.h>
25
26#include <netlink-local.h>
27#include <netlink/attr.h>
28#include <netlink/netfilter/nfnl.h>
29#include <netlink/netfilter/ct.h>
30
31static struct nl_cache_ops nfnl_ct_ops;
32
33#if __BYTE_ORDER == __BIG_ENDIAN
34static uint64_t ntohll(uint64_t x)
35{
36	return x;
37}
38#elif __BYTE_ORDER == __LITTLE_ENDIAN
39static uint64_t ntohll(uint64_t x)
40{
41	return __bswap_64(x);
42}
43#endif
44
45static 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 },
50	//[CTA_HELP]
51	//[CTA_NAT_SRC]
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 },
58	//[CTA_NAT_DST]
59};
60
61static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = {
62	[CTA_TUPLE_IP]		= { .type = NLA_NESTED },
63	[CTA_TUPLE_PROTO]	= { .type = NLA_NESTED },
64};
65
66static 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 },
71};
72
73static 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 },
83};
84
85static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
86	[CTA_PROTOINFO_TCP]	= { .type = NLA_NESTED },
87};
88
89static 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 },
95
96};
97
98static 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 },
103};
104
105static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr)
106{
107	struct nlattr *tb[CTA_IP_MAX+1];
108	struct nl_addr *addr;
109	int err;
110
111        err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy);
112	if (err < 0)
113		goto errout;
114
115	if (tb[CTA_IP_V4_SRC]) {
116		addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET);
117		if (addr == NULL)
118			goto errout_enomem;
119		err = nfnl_ct_set_src(ct, repl, addr);
120		nl_addr_put(addr);
121		if (err < 0)
122			goto errout;
123	}
124	if (tb[CTA_IP_V4_DST]) {
125		addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET);
126		if (addr == NULL)
127			goto errout_enomem;
128		err = nfnl_ct_set_dst(ct, repl, addr);
129		nl_addr_put(addr);
130		if (err < 0)
131			goto errout;
132	}
133	if (tb[CTA_IP_V6_SRC]) {
134		addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6);
135		if (addr == NULL)
136			goto errout_enomem;
137		err = nfnl_ct_set_src(ct, repl, addr);
138		nl_addr_put(addr);
139		if (err < 0)
140			goto errout;
141	}
142	if (tb[CTA_IP_V6_DST]) {
143		addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6);
144		if (addr == NULL)
145			goto errout_enomem;
146		err = nfnl_ct_set_dst(ct, repl, addr);
147		nl_addr_put(addr);
148		if (err < 0)
149			goto errout;
150	}
151
152	return 0;
153
154errout_enomem:
155	err = -NLE_NOMEM;
156errout:
157	return err;
158}
159
160static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr)
161{
162	struct nlattr *tb[CTA_PROTO_MAX+1];
163	int err;
164
165	err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy);
166	if (err < 0)
167		return err;
168
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				nla_get_u16(tb[CTA_PROTO_SRC_PORT]));
174	if (tb[CTA_PROTO_DST_PORT])
175		nfnl_ct_set_dst_port(ct, repl,
176				nla_get_u16(tb[CTA_PROTO_DST_PORT]));
177	if (tb[CTA_PROTO_ICMP_ID])
178		nfnl_ct_set_icmp_id(ct, repl,
179				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]));
186
187	return 0;
188}
189
190static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr)
191{
192	struct nlattr *tb[CTA_TUPLE_MAX+1];
193	int err;
194
195	err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy);
196	if (err < 0)
197		return err;
198
199	if (tb[CTA_TUPLE_IP]) {
200		err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]);
201		if (err < 0)
202			return err;
203	}
204
205	if (tb[CTA_TUPLE_PROTO]) {
206		err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]);
207		if (err < 0)
208			return err;
209	}
210
211	return 0;
212}
213
214static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr)
215{
216	struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1];
217	int err;
218
219	err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr,
220			       ct_protoinfo_tcp_policy);
221	if (err < 0)
222		return err;
223
224	if (tb[CTA_PROTOINFO_TCP_STATE])
225		nfnl_ct_set_tcp_state(ct,
226				nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]));
227
228	return 0;
229}
230
231static int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr)
232{
233	struct nlattr *tb[CTA_PROTOINFO_MAX+1];
234	int err;
235
236	err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr,
237			       ct_protoinfo_policy);
238	if (err < 0)
239		return err;
240
241	if (tb[CTA_PROTOINFO_TCP]) {
242		err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]);
243		if (err < 0)
244			return err;
245	}
246
247	return 0;
248}
249
250static int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr)
251{
252	struct nlattr *tb[CTA_COUNTERS_MAX+1];
253	int err;
254
255	err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy);
256	if (err < 0)
257		return err;
258
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])));
271
272	return 0;
273}
274
275int nfnlmsg_ct_group(struct nlmsghdr *nlh)
276{
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;
281		else
282			return NFNLGRP_CONNTRACK_UPDATE;
283	case IPCTNL_MSG_CT_DELETE:
284		return NFNLGRP_CONNTRACK_DESTROY;
285	default:
286		return NFNLGRP_NONE;
287	}
288}
289
290int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result)
291{
292	struct nfnl_ct *ct;
293	struct nlattr *tb[CTA_MAX+1];
294	int err;
295
296	ct = nfnl_ct_alloc();
297	if (!ct)
298		return -NLE_NOMEM;
299
300	ct->ce_msgtype = nlh->nlmsg_type;
301
302	err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX,
303			  ct_policy);
304	if (err < 0)
305		goto errout;
306
307	nfnl_ct_set_family(ct, nfnlmsg_family(nlh));
308
309	if (tb[CTA_TUPLE_ORIG]) {
310		err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]);
311		if (err < 0)
312			goto errout;
313	}
314	if (tb[CTA_TUPLE_REPLY]) {
315		err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]);
316		if (err < 0)
317			goto errout;
318	}
319
320	if (tb[CTA_PROTOINFO]) {
321		err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]);
322		if (err < 0)
323			goto errout;
324	}
325
326	if (tb[CTA_STATUS])
327		nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS])));
328	if (tb[CTA_TIMEOUT])
329		nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT])));
330	if (tb[CTA_MARK])
331		nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK])));
332	if (tb[CTA_USE])
333		nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE])));
334	if (tb[CTA_ID])
335		nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID])));
336
337	if (tb[CTA_COUNTERS_ORIG]) {
338		err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]);
339		if (err < 0)
340			goto errout;
341	}
342
343	if (tb[CTA_COUNTERS_REPLY]) {
344		err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]);
345		if (err < 0)
346			goto errout;
347	}
348
349	*result = ct;
350	return 0;
351
352errout:
353	nfnl_ct_put(ct);
354	return err;
355}
356
357static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
358			 struct nlmsghdr *nlh, struct nl_parser_param *pp)
359{
360	struct nfnl_ct *ct;
361	int err;
362
363	if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0)
364		goto errout;
365
366	err = pp->pp_cb((struct nl_object *) ct, pp);
367	if (err < 0)
368		goto errout;
369
370	err = P_ACCEPT;
371
372errout:
373	nfnl_ct_put(ct);
374	return err;
375}
376
377int nfnl_ct_dump_request(struct nl_handle *h)
378{
379	return nfnl_send_simple(h, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET,
380				NLM_F_DUMP, AF_UNSPEC, 0);
381}
382
383static int ct_request_update(struct nl_cache *c, struct nl_handle *h)
384{
385	return nfnl_ct_dump_request(h);
386}
387
388static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
389			       int repl)
390{
391	struct nlattr *tuple, *ip, *proto;
392	struct nl_addr *addr;
393	int family;
394
395	family = nfnl_ct_get_family(ct);
396
397	tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG);
398	if (!tuple)
399		goto nla_put_failure;
400
401	ip = nla_nest_start(msg, CTA_TUPLE_IP);
402	if (!ip)
403		goto nla_put_failure;
404
405	addr = nfnl_ct_get_src(ct, repl);
406	if (addr)
407		NLA_PUT_ADDR(msg,
408			     family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
409			     addr);
410
411	addr = nfnl_ct_get_dst(ct, repl);
412	if (addr)
413		NLA_PUT_ADDR(msg,
414			     family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
415			     addr);
416
417	nla_nest_end(msg, ip);
418
419	proto = nla_nest_start(msg, CTA_TUPLE_PROTO);
420	if (!proto)
421		goto nla_put_failure;
422
423	if (nfnl_ct_test_proto(ct))
424		NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct));
425
426	if (nfnl_ct_test_src_port(ct, repl))
427		NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT,
428			    nfnl_ct_get_src_port(ct, repl));
429
430	if (nfnl_ct_test_dst_port(ct, repl))
431		NLA_PUT_U16(msg, CTA_PROTO_DST_PORT,
432			    nfnl_ct_get_dst_port(ct, repl));
433
434	if (nfnl_ct_test_icmp_id(ct, repl))
435		NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
436			    nfnl_ct_get_icmp_id(ct, repl));
437
438	if (nfnl_ct_test_icmp_type(ct, repl))
439		NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
440			    nfnl_ct_get_icmp_type(ct, repl));
441
442	if (nfnl_ct_test_icmp_code(ct, repl))
443		NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
444			    nfnl_ct_get_icmp_code(ct, repl));
445
446	nla_nest_end(msg, proto);
447
448	nla_nest_end(msg, tuple);
449	return 0;
450
451nla_put_failure:
452	return -NLE_MSGSIZE;
453}
454
455static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags,
456				 struct nl_msg **result)
457{
458	struct nl_msg *msg;
459	int err;
460
461	msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags,
462				   nfnl_ct_get_family(ct), 0);
463	if (msg == NULL)
464		return -NLE_NOMEM;
465
466	if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0)
467		goto err_out;
468
469	*result = msg;
470	return 0;
471
472err_out:
473	nlmsg_free(msg);
474	return err;
475}
476
477int nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags,
478			      struct nl_msg **result)
479{
480	return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result);
481}
482
483int nfnl_ct_add(struct nl_handle *h, const struct nfnl_ct *ct, int flags)
484{
485	struct nl_msg *msg;
486	int err;
487
488	if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0)
489		return err;
490
491	err = nl_send_auto_complete(h, msg);
492	nlmsg_free(msg);
493	if (err < 0)
494		return err;
495
496	return nl_wait_for_ack(h);
497}
498
499int nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags,
500				 struct nl_msg **result)
501{
502	return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result);
503}
504
505int nfnl_ct_del(struct nl_handle *h, const struct nfnl_ct *ct, int flags)
506{
507	struct nl_msg *msg;
508	int err;
509
510	if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0)
511		return err;
512
513	err = nl_send_auto_complete(h, msg);
514	nlmsg_free(msg);
515	if (err < 0)
516		return err;
517
518	return nl_wait_for_ack(h);
519}
520
521int nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags,
522				struct nl_msg **result)
523{
524	return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result);
525}
526
527int nfnl_ct_query(struct nl_handle *h, const struct nfnl_ct *ct, int flags)
528{
529	struct nl_msg *msg;
530	int err;
531
532	if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0)
533		return err;
534
535	err = nl_send_auto_complete(h, msg);
536	nlmsg_free(msg);
537	if (err < 0)
538		return err;
539
540	return nl_wait_for_ack(h);
541}
542
543/**
544 * @name Cache Management
545 * @{
546 */
547
548/**
549 * Build a conntrack cache holding all conntrack currently in the kernel
550 * @arg handle		netlink handle
551 * @arg result		Pointer to store resulting cache.
552 *
553 * Allocates a new cache, initializes it properly and updates it to
554 * contain all conntracks currently in the kernel.
555 *
556 * @return 0 on success or a negative error code.
557 */
558int nfnl_ct_alloc_cache(struct nl_handle *sock, struct nl_cache **result)
559{
560	return nl_cache_alloc_and_fill(&nfnl_ct_ops, sock, result);
561}
562
563/** @} */
564
565/**
566 * @name Conntrack Addition
567 * @{
568 */
569
570/** @} */
571
572static struct nl_af_group ct_groups[] = {
573	{ AF_UNSPEC, NFNLGRP_CONNTRACK_NEW },
574	{ AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE },
575	{ AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY },
576	{ END_OF_GROUP_LIST },
577};
578
579#define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type))
580static struct nl_cache_ops nfnl_ct_ops = {
581	.co_name		= "netfilter/ct",
582	.co_hdrsize		= NFNL_HDRLEN,
583	.co_msgtypes		= {
584		{ NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" },
585		{ NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" },
586		{ NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" },
587		END_OF_MSGTYPES_LIST,
588	},
589	.co_protocol		= NETLINK_NETFILTER,
590	.co_groups		= ct_groups,
591	.co_request_update	= ct_request_update,
592	.co_msg_parser		= ct_msg_parser,
593	.co_obj_ops		= &ct_obj_ops,
594};
595
596static void __init ct_init(void)
597{
598	nl_cache_mngt_register(&nfnl_ct_ops);
599}
600
601static void __exit ct_exit(void)
602{
603	nl_cache_mngt_unregister(&nfnl_ct_ops);
604}
605
606/** @} */
607