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 
31 static struct nl_cache_ops nfnl_ct_ops;
32 
33 #if __BYTE_ORDER == __BIG_ENDIAN
ntohll(uint64_t x)34 static uint64_t ntohll(uint64_t x)
35 {
36 	return x;
37 }
38 #elif __BYTE_ORDER == __LITTLE_ENDIAN
ntohll(uint64_t x)39 static uint64_t ntohll(uint64_t x)
40 {
41 	return __bswap_64(x);
42 }
43 #endif
44 
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 },
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 
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 },
64 };
65 
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 },
71 };
72 
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 },
83 };
84 
85 static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
86 	[CTA_PROTOINFO_TCP]	= { .type = NLA_NESTED },
87 };
88 
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 },
95 
96 };
97 
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 },
103 };
104 
ct_parse_ip(struct nfnl_ct * ct,int repl,struct nlattr * attr)105 static 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 
154 errout_enomem:
155 	err = -NLE_NOMEM;
156 errout:
157 	return err;
158 }
159 
ct_parse_proto(struct nfnl_ct * ct,int repl,struct nlattr * attr)160 static 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 			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]));
186 
187 	return 0;
188 }
189 
ct_parse_tuple(struct nfnl_ct * ct,int repl,struct nlattr * attr)190 static 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 
ct_parse_protoinfo_tcp(struct nfnl_ct * ct,struct nlattr * attr)214 static 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 
ct_parse_protoinfo(struct nfnl_ct * ct,struct nlattr * attr)231 static 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 
ct_parse_counters(struct nfnl_ct * ct,int repl,struct nlattr * attr)250 static 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 
nfnlmsg_ct_group(struct nlmsghdr * nlh)275 int 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 
nfnlmsg_ct_parse(struct nlmsghdr * nlh,struct nfnl_ct ** result)290 int 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 
352 errout:
353 	nfnl_ct_put(ct);
354 	return err;
355 }
356 
ct_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * nlh,struct nl_parser_param * pp)357 static 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 errout:
368 	nfnl_ct_put(ct);
369 	return err;
370 }
371 
nfnl_ct_dump_request(struct nl_sock * sk)372 int nfnl_ct_dump_request(struct nl_sock *sk)
373 {
374 	return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET,
375 				NLM_F_DUMP, AF_UNSPEC, 0);
376 }
377 
ct_request_update(struct nl_cache * cache,struct nl_sock * sk)378 static int ct_request_update(struct nl_cache *cache, struct nl_sock *sk)
379 {
380 	return nfnl_ct_dump_request(sk);
381 }
382 
nfnl_ct_build_tuple(struct nl_msg * msg,const struct nfnl_ct * ct,int repl)383 static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
384 			       int repl)
385 {
386 	struct nlattr *tuple, *ip, *proto;
387 	struct nl_addr *addr;
388 	int family;
389 
390 	family = nfnl_ct_get_family(ct);
391 
392 	tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG);
393 	if (!tuple)
394 		goto nla_put_failure;
395 
396 	ip = nla_nest_start(msg, CTA_TUPLE_IP);
397 	if (!ip)
398 		goto nla_put_failure;
399 
400 	addr = nfnl_ct_get_src(ct, repl);
401 	if (addr)
402 		NLA_PUT_ADDR(msg,
403 			     family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
404 			     addr);
405 
406 	addr = nfnl_ct_get_dst(ct, repl);
407 	if (addr)
408 		NLA_PUT_ADDR(msg,
409 			     family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
410 			     addr);
411 
412 	nla_nest_end(msg, ip);
413 
414 	proto = nla_nest_start(msg, CTA_TUPLE_PROTO);
415 	if (!proto)
416 		goto nla_put_failure;
417 
418 	if (nfnl_ct_test_proto(ct))
419 		NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct));
420 
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)));
424 
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)));
428 
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)));
432 
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));
436 
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));
440 
441 	nla_nest_end(msg, proto);
442 
443 	nla_nest_end(msg, tuple);
444 	return 0;
445 
446 nla_put_failure:
447 	return -NLE_MSGSIZE;
448 }
449 
nfnl_ct_build_message(const struct nfnl_ct * ct,int cmd,int flags,struct nl_msg ** result)450 static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags,
451 				 struct nl_msg **result)
452 {
453 	struct nl_msg *msg;
454 	int err;
455 
456 	msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags,
457 				   nfnl_ct_get_family(ct), 0);
458 	if (msg == NULL)
459 		return -NLE_NOMEM;
460 
461 	if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0)
462 		goto err_out;
463 
464 	*result = msg;
465 	return 0;
466 
467 err_out:
468 	nlmsg_free(msg);
469 	return err;
470 }
471 
nfnl_ct_build_add_request(const struct nfnl_ct * ct,int flags,struct nl_msg ** result)472 int nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags,
473 			      struct nl_msg **result)
474 {
475 	return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result);
476 }
477 
nfnl_ct_add(struct nl_sock * sk,const struct nfnl_ct * ct,int flags)478 int nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
479 {
480 	struct nl_msg *msg;
481 	int err;
482 
483 	if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0)
484 		return err;
485 
486 	err = nl_send_auto_complete(sk, msg);
487 	nlmsg_free(msg);
488 	if (err < 0)
489 		return err;
490 
491 	return wait_for_ack(sk);
492 }
493 
nfnl_ct_build_delete_request(const struct nfnl_ct * ct,int flags,struct nl_msg ** result)494 int nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags,
495 				 struct nl_msg **result)
496 {
497 	return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result);
498 }
499 
nfnl_ct_del(struct nl_sock * sk,const struct nfnl_ct * ct,int flags)500 int nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
501 {
502 	struct nl_msg *msg;
503 	int err;
504 
505 	if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0)
506 		return err;
507 
508 	err = nl_send_auto_complete(sk, msg);
509 	nlmsg_free(msg);
510 	if (err < 0)
511 		return err;
512 
513 	return wait_for_ack(sk);
514 }
515 
nfnl_ct_build_query_request(const struct nfnl_ct * ct,int flags,struct nl_msg ** result)516 int nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags,
517 				struct nl_msg **result)
518 {
519 	return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result);
520 }
521 
nfnl_ct_query(struct nl_sock * sk,const struct nfnl_ct * ct,int flags)522 int nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
523 {
524 	struct nl_msg *msg;
525 	int err;
526 
527 	if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0)
528 		return err;
529 
530 	err = nl_send_auto_complete(sk, msg);
531 	nlmsg_free(msg);
532 	if (err < 0)
533 		return err;
534 
535 	return wait_for_ack(sk);
536 }
537 
538 /**
539  * @name Cache Management
540  * @{
541  */
542 
543 /**
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.
547  *
548  * Allocates a new cache, initializes it properly and updates it to
549  * contain all conntracks currently in the kernel.
550  *
551  * @return 0 on success or a negative error code.
552  */
nfnl_ct_alloc_cache(struct nl_sock * sk,struct nl_cache ** result)553 int nfnl_ct_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
554 {
555 	return nl_cache_alloc_and_fill(&nfnl_ct_ops, sk, result);
556 }
557 
558 /** @} */
559 
560 /**
561  * @name Conntrack Addition
562  * @{
563  */
564 
565 /** @} */
566 
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 },
572 };
573 
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,
578 	.co_msgtypes		= {
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,
583 	},
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,
589 };
590 
ct_init(void)591 static void __init ct_init(void)
592 {
593 	nl_cache_mngt_register(&nfnl_ct_ops);
594 }
595 
ct_exit(void)596 static void __exit ct_exit(void)
597 {
598 	nl_cache_mngt_unregister(&nfnl_ct_ops);
599 }
600 
601 /** @} */
602