• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: LGPL-2.1-only */
2 /*
3  * lib/netfilter/ct.c	Conntrack
4  *
5  *	This library is free software; you can redistribute it and/or
6  *	modify it under the terms of the GNU Lesser General Public
7  *	License as published by the Free Software Foundation version 2.1
8  *	of the License.
9  *
10  * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
11  * Copyright (c) 2007 Philip Craig <philipc@snapgear.com>
12  * Copyright (c) 2007 Secure Computing Corporation
13  * Copyright (c= 2008 Patrick McHardy <kaber@trash.net>
14  */
15 
16 /**
17  * @ingroup nfnl
18  * @defgroup ct Conntrack
19  * @brief
20  * @{
21  */
22 
23 #include <byteswap.h>
24 #include <sys/types.h>
25 #include <linux/netfilter/nfnetlink_conntrack.h>
26 
27 #include <netlink-private/netlink.h>
28 #include <netlink/attr.h>
29 #include <netlink/netfilter/nfnl.h>
30 #include <netlink/netfilter/ct.h>
31 #include <netlink-private/utils.h>
32 
33 static struct nl_cache_ops nfnl_ct_ops;
34 
35 
36 static struct nla_policy ct_policy[CTA_MAX+1] = {
37 	[CTA_TUPLE_ORIG]	= { .type = NLA_NESTED },
38 	[CTA_TUPLE_REPLY]	= { .type = NLA_NESTED },
39 	[CTA_STATUS]		= { .type = NLA_U32 },
40 	[CTA_PROTOINFO]		= { .type = NLA_NESTED },
41 	//[CTA_HELP]
42 	//[CTA_NAT_SRC]
43 	[CTA_TIMEOUT]		= { .type = NLA_U32 },
44 	[CTA_MARK]		= { .type = NLA_U32 },
45 	[CTA_COUNTERS_ORIG]	= { .type = NLA_NESTED },
46 	[CTA_COUNTERS_REPLY]	= { .type = NLA_NESTED },
47 	[CTA_USE]		= { .type = NLA_U32 },
48 	[CTA_ID]		= { .type = NLA_U32 },
49 	[CTA_ZONE]		= { .type = NLA_U16 },
50 	//[CTA_NAT_DST]
51 };
52 
53 static struct nla_policy ct_tuple_policy[CTA_TUPLE_MAX+1] = {
54 	[CTA_TUPLE_IP]		= { .type = NLA_NESTED },
55 	[CTA_TUPLE_PROTO]	= { .type = NLA_NESTED },
56 };
57 
58 static struct nla_policy ct_ip_policy[CTA_IP_MAX+1] = {
59 	[CTA_IP_V4_SRC]		= { .type = NLA_U32 },
60 	[CTA_IP_V4_DST]		= { .type = NLA_U32 },
61 	[CTA_IP_V6_SRC]		= { .minlen = 16 },
62 	[CTA_IP_V6_DST]		= { .minlen = 16 },
63 };
64 
65 static struct nla_policy ct_proto_policy[CTA_PROTO_MAX+1] = {
66 	[CTA_PROTO_NUM]		= { .type = NLA_U8 },
67 	[CTA_PROTO_SRC_PORT]	= { .type = NLA_U16 },
68 	[CTA_PROTO_DST_PORT]	= { .type = NLA_U16 },
69 	[CTA_PROTO_ICMP_ID]	= { .type = NLA_U16 },
70 	[CTA_PROTO_ICMP_TYPE]	= { .type = NLA_U8 },
71 	[CTA_PROTO_ICMP_CODE]	= { .type = NLA_U8 },
72 	[CTA_PROTO_ICMPV6_ID]	= { .type = NLA_U16 },
73 	[CTA_PROTO_ICMPV6_TYPE]	= { .type = NLA_U8 },
74 	[CTA_PROTO_ICMPV6_CODE]	= { .type = NLA_U8 },
75 };
76 
77 static struct nla_policy ct_protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
78 	[CTA_PROTOINFO_TCP]	= { .type = NLA_NESTED },
79 };
80 
81 static struct nla_policy ct_protoinfo_tcp_policy[CTA_PROTOINFO_TCP_MAX+1] = {
82 	[CTA_PROTOINFO_TCP_STATE]		= { .type = NLA_U8 },
83 	[CTA_PROTOINFO_TCP_WSCALE_ORIGINAL]	= { .type = NLA_U8 },
84 	[CTA_PROTOINFO_TCP_WSCALE_REPLY]	= { .type = NLA_U8 },
85 	[CTA_PROTOINFO_TCP_FLAGS_ORIGINAL]	= { .minlen = 2 },
86 	[CTA_PROTOINFO_TCP_FLAGS_REPLY]		= { .minlen = 2 },
87 
88 };
89 
90 static struct nla_policy ct_counters_policy[CTA_COUNTERS_MAX+1] = {
91 	[CTA_COUNTERS_PACKETS]	= { .type = NLA_U64 },
92 	[CTA_COUNTERS_BYTES]	= { .type = NLA_U64 },
93 	[CTA_COUNTERS32_PACKETS]= { .type = NLA_U32 },
94 	[CTA_COUNTERS32_BYTES]	= { .type = NLA_U32 },
95 };
96 
97 static struct nla_policy ct_timestamp_policy[CTA_TIMESTAMP_MAX + 1] = {
98 	[CTA_TIMESTAMP_START]	= { .type = NLA_U64 },
99 	[CTA_TIMESTAMP_STOP]	= { .type = NLA_U64 },
100 };
101 
ct_parse_ip(struct nfnl_ct * ct,int repl,struct nlattr * attr)102 static int ct_parse_ip(struct nfnl_ct *ct, int repl, struct nlattr *attr)
103 {
104 	struct nlattr *tb[CTA_IP_MAX+1];
105 	struct nl_addr *addr;
106 	int err;
107 
108 	err = nla_parse_nested(tb, CTA_IP_MAX, attr, ct_ip_policy);
109 	if (err < 0)
110 		goto errout;
111 
112 	if (tb[CTA_IP_V4_SRC]) {
113 		addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET);
114 		if (addr == NULL)
115 			goto errout_enomem;
116 		err = nfnl_ct_set_src(ct, repl, addr);
117 		nl_addr_put(addr);
118 		if (err < 0)
119 			goto errout;
120 	}
121 	if (tb[CTA_IP_V4_DST]) {
122 		addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET);
123 		if (addr == NULL)
124 			goto errout_enomem;
125 		err = nfnl_ct_set_dst(ct, repl, addr);
126 		nl_addr_put(addr);
127 		if (err < 0)
128 			goto errout;
129 	}
130 	if (tb[CTA_IP_V6_SRC]) {
131 		addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6);
132 		if (addr == NULL)
133 			goto errout_enomem;
134 		err = nfnl_ct_set_src(ct, repl, addr);
135 		nl_addr_put(addr);
136 		if (err < 0)
137 			goto errout;
138 	}
139 	if (tb[CTA_IP_V6_DST]) {
140 		addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6);
141 		if (addr == NULL)
142 			goto errout_enomem;
143 		err = nfnl_ct_set_dst(ct, repl, addr);
144 		nl_addr_put(addr);
145 		if (err < 0)
146 			goto errout;
147 	}
148 
149 	return 0;
150 
151 errout_enomem:
152 	err = -NLE_NOMEM;
153 errout:
154 	return err;
155 }
156 
ct_parse_proto(struct nfnl_ct * ct,int repl,struct nlattr * attr)157 static int ct_parse_proto(struct nfnl_ct *ct, int repl, struct nlattr *attr)
158 {
159 	struct nlattr *tb[CTA_PROTO_MAX+1];
160 	int err;
161 
162 	err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, ct_proto_policy);
163 	if (err < 0)
164 		return err;
165 
166 	if (!repl && tb[CTA_PROTO_NUM])
167 		nfnl_ct_set_proto(ct, nla_get_u8(tb[CTA_PROTO_NUM]));
168 	if (tb[CTA_PROTO_SRC_PORT])
169 		nfnl_ct_set_src_port(ct, repl,
170 			ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT])));
171 	if (tb[CTA_PROTO_DST_PORT])
172 		nfnl_ct_set_dst_port(ct, repl,
173 			ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT])));
174 
175 	if (ct->ct_family == AF_INET) {
176 		if (tb[CTA_PROTO_ICMP_ID])
177 			nfnl_ct_set_icmp_id(ct, repl,
178 				ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID])));
179 		if (tb[CTA_PROTO_ICMP_TYPE])
180 			nfnl_ct_set_icmp_type(ct, repl,
181 				nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
182 		if (tb[CTA_PROTO_ICMP_CODE])
183 			nfnl_ct_set_icmp_code(ct, repl,
184 				nla_get_u8(tb[CTA_PROTO_ICMP_CODE]));
185 	} else if (ct->ct_family == AF_INET6) {
186 		if (tb[CTA_PROTO_ICMPV6_ID])
187 			nfnl_ct_set_icmp_id(ct, repl,
188 			    ntohs(nla_get_u16(tb[CTA_PROTO_ICMPV6_ID])));
189 		if (tb[CTA_PROTO_ICMPV6_TYPE])
190 			nfnl_ct_set_icmp_type(ct, repl,
191 				nla_get_u8(tb[CTA_PROTO_ICMPV6_TYPE]));
192 		if (tb[CTA_PROTO_ICMPV6_CODE])
193 			nfnl_ct_set_icmp_code(ct, repl,
194 				nla_get_u8(tb[CTA_PROTO_ICMPV6_CODE]));
195 	}
196 
197 	return 0;
198 }
199 
ct_parse_tuple(struct nfnl_ct * ct,int repl,struct nlattr * attr)200 static int ct_parse_tuple(struct nfnl_ct *ct, int repl, struct nlattr *attr)
201 {
202 	struct nlattr *tb[CTA_TUPLE_MAX+1];
203 	int err;
204 
205 	err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, ct_tuple_policy);
206 	if (err < 0)
207 		return err;
208 
209 	if (tb[CTA_TUPLE_IP]) {
210 		err = ct_parse_ip(ct, repl, tb[CTA_TUPLE_IP]);
211 		if (err < 0)
212 			return err;
213 	}
214 
215 	if (tb[CTA_TUPLE_PROTO]) {
216 		err = ct_parse_proto(ct, repl, tb[CTA_TUPLE_PROTO]);
217 		if (err < 0)
218 			return err;
219 	}
220 
221 	return 0;
222 }
223 
ct_parse_protoinfo_tcp(struct nfnl_ct * ct,struct nlattr * attr)224 static int ct_parse_protoinfo_tcp(struct nfnl_ct *ct, struct nlattr *attr)
225 {
226 	struct nlattr *tb[CTA_PROTOINFO_TCP_MAX+1];
227 	int err;
228 
229 	err = nla_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr,
230 			       ct_protoinfo_tcp_policy);
231 	if (err < 0)
232 		return err;
233 
234 	if (tb[CTA_PROTOINFO_TCP_STATE])
235 		nfnl_ct_set_tcp_state(ct,
236 				nla_get_u8(tb[CTA_PROTOINFO_TCP_STATE]));
237 
238 	return 0;
239 }
240 
ct_parse_protoinfo(struct nfnl_ct * ct,struct nlattr * attr)241 static int ct_parse_protoinfo(struct nfnl_ct *ct, struct nlattr *attr)
242 {
243 	struct nlattr *tb[CTA_PROTOINFO_MAX+1];
244 	int err;
245 
246 	err = nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr,
247 			       ct_protoinfo_policy);
248 	if (err < 0)
249 		return err;
250 
251 	if (tb[CTA_PROTOINFO_TCP]) {
252 		err = ct_parse_protoinfo_tcp(ct, tb[CTA_PROTOINFO_TCP]);
253 		if (err < 0)
254 			return err;
255 	}
256 
257 	return 0;
258 }
259 
ct_parse_counters(struct nfnl_ct * ct,int repl,struct nlattr * attr)260 static int ct_parse_counters(struct nfnl_ct *ct, int repl, struct nlattr *attr)
261 {
262 	struct nlattr *tb[CTA_COUNTERS_MAX+1];
263 	int err;
264 
265 	err = nla_parse_nested(tb, CTA_COUNTERS_MAX, attr, ct_counters_policy);
266 	if (err < 0)
267 		return err;
268 
269 	if (tb[CTA_COUNTERS_PACKETS])
270 		nfnl_ct_set_packets(ct, repl,
271 			ntohll(nla_get_u64(tb[CTA_COUNTERS_PACKETS])));
272 	if (tb[CTA_COUNTERS32_PACKETS])
273 		nfnl_ct_set_packets(ct, repl,
274 			ntohl(nla_get_u32(tb[CTA_COUNTERS32_PACKETS])));
275 	if (tb[CTA_COUNTERS_BYTES])
276 		nfnl_ct_set_bytes(ct, repl,
277 			ntohll(nla_get_u64(tb[CTA_COUNTERS_BYTES])));
278 	if (tb[CTA_COUNTERS32_BYTES])
279 		nfnl_ct_set_bytes(ct, repl,
280 			ntohl(nla_get_u32(tb[CTA_COUNTERS32_BYTES])));
281 
282 	return 0;
283 }
284 
nfnlmsg_ct_group(struct nlmsghdr * nlh)285 int nfnlmsg_ct_group(struct nlmsghdr *nlh)
286 {
287 	switch (nfnlmsg_subtype(nlh)) {
288 	case IPCTNL_MSG_CT_NEW:
289 		if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
290 			return NFNLGRP_CONNTRACK_NEW;
291 		else
292 			return NFNLGRP_CONNTRACK_UPDATE;
293 	case IPCTNL_MSG_CT_DELETE:
294 		return NFNLGRP_CONNTRACK_DESTROY;
295 	default:
296 		return NFNLGRP_NONE;
297 	}
298 }
299 
ct_parse_timestamp(struct nfnl_ct * ct,struct nlattr * attr)300 static int ct_parse_timestamp(struct nfnl_ct *ct, struct nlattr *attr)
301 {
302 	struct nlattr *tb[CTA_TIMESTAMP_MAX + 1];
303 	int err;
304 
305 	err = nla_parse_nested(tb, CTA_TIMESTAMP_MAX, attr,
306 			       ct_timestamp_policy);
307 	if (err < 0)
308 		return err;
309 
310 	if (tb[CTA_TIMESTAMP_START] && tb[CTA_TIMESTAMP_STOP])
311 		nfnl_ct_set_timestamp(ct,
312 			      ntohll(nla_get_u64(tb[CTA_TIMESTAMP_START])),
313 			      ntohll(nla_get_u64(tb[CTA_TIMESTAMP_STOP])));
314 
315 	return 0;
316 }
317 
nfnlmsg_ct_parse(struct nlmsghdr * nlh,struct nfnl_ct ** result)318 int nfnlmsg_ct_parse(struct nlmsghdr *nlh, struct nfnl_ct **result)
319 {
320 	struct nfnl_ct *ct;
321 	struct nlattr *tb[CTA_MAX+1];
322 	int err;
323 
324 	ct = nfnl_ct_alloc();
325 	if (!ct)
326 		return -NLE_NOMEM;
327 
328 	ct->ce_msgtype = nlh->nlmsg_type;
329 
330 	err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_MAX,
331 			  ct_policy);
332 	if (err < 0)
333 		goto errout;
334 
335 	nfnl_ct_set_family(ct, nfnlmsg_family(nlh));
336 
337 	if (tb[CTA_TUPLE_ORIG]) {
338 		err = ct_parse_tuple(ct, 0, tb[CTA_TUPLE_ORIG]);
339 		if (err < 0)
340 			goto errout;
341 	}
342 	if (tb[CTA_TUPLE_REPLY]) {
343 		err = ct_parse_tuple(ct, 1, tb[CTA_TUPLE_REPLY]);
344 		if (err < 0)
345 			goto errout;
346 	}
347 
348 	if (tb[CTA_PROTOINFO]) {
349 		err = ct_parse_protoinfo(ct, tb[CTA_PROTOINFO]);
350 		if (err < 0)
351 			goto errout;
352 	}
353 
354 	if (tb[CTA_STATUS])
355 		nfnl_ct_set_status(ct, ntohl(nla_get_u32(tb[CTA_STATUS])));
356 	if (tb[CTA_TIMEOUT])
357 		nfnl_ct_set_timeout(ct, ntohl(nla_get_u32(tb[CTA_TIMEOUT])));
358 	if (tb[CTA_MARK])
359 		nfnl_ct_set_mark(ct, ntohl(nla_get_u32(tb[CTA_MARK])));
360 	if (tb[CTA_USE])
361 		nfnl_ct_set_use(ct, ntohl(nla_get_u32(tb[CTA_USE])));
362 	if (tb[CTA_ID])
363 		nfnl_ct_set_id(ct, ntohl(nla_get_u32(tb[CTA_ID])));
364 	if (tb[CTA_ZONE])
365 		nfnl_ct_set_zone(ct, ntohs(nla_get_u16(tb[CTA_ZONE])));
366 
367 	if (tb[CTA_COUNTERS_ORIG]) {
368 		err = ct_parse_counters(ct, 0, tb[CTA_COUNTERS_ORIG]);
369 		if (err < 0)
370 			goto errout;
371 	}
372 
373 	if (tb[CTA_COUNTERS_REPLY]) {
374 		err = ct_parse_counters(ct, 1, tb[CTA_COUNTERS_REPLY]);
375 		if (err < 0)
376 			goto errout;
377 	}
378 
379 	if (tb[CTA_TIMESTAMP]) {
380 		err = ct_parse_timestamp(ct, tb[CTA_TIMESTAMP]);
381 		if (err < 0)
382 			goto errout;
383 	}
384 
385 	*result = ct;
386 	return 0;
387 
388 errout:
389 	nfnl_ct_put(ct);
390 	return err;
391 }
392 
ct_msg_parser(struct nl_cache_ops * ops,struct sockaddr_nl * who,struct nlmsghdr * nlh,struct nl_parser_param * pp)393 static int ct_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
394 			 struct nlmsghdr *nlh, struct nl_parser_param *pp)
395 {
396 	struct nfnl_ct *ct;
397 	int err;
398 
399 	if ((err = nfnlmsg_ct_parse(nlh, &ct)) < 0)
400 		return err;
401 
402 	err = pp->pp_cb((struct nl_object *) ct, pp);
403 	nfnl_ct_put(ct);
404 	return err;
405 }
406 
407 /**
408  * Send nfnl ct dump request
409  * @arg sk    Netlink socket.
410  *
411  * @return 0 on success or a negative error code. Due to a bug, this function
412  * returns the number of bytes sent. Treat any non-negative number as success.
413  */
nfnl_ct_dump_request(struct nl_sock * sk)414 int nfnl_ct_dump_request(struct nl_sock *sk)
415 {
416 	return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK, IPCTNL_MSG_CT_GET,
417 				NLM_F_DUMP, AF_UNSPEC, 0);
418 }
419 
ct_request_update(struct nl_cache * cache,struct nl_sock * sk)420 static int ct_request_update(struct nl_cache *cache, struct nl_sock *sk)
421 {
422 	return nfnl_ct_dump_request(sk);
423 }
424 
nfnl_ct_build_tuple(struct nl_msg * msg,const struct nfnl_ct * ct,int repl)425 static int nfnl_ct_build_tuple(struct nl_msg *msg, const struct nfnl_ct *ct,
426 			       int repl)
427 {
428 	struct nlattr *tuple, *ip, *proto;
429 	struct nl_addr *addr;
430 	int family;
431 
432 	family = nfnl_ct_get_family(ct);
433 
434 	tuple = nla_nest_start(msg, repl ? CTA_TUPLE_REPLY : CTA_TUPLE_ORIG);
435 	if (!tuple)
436 		goto nla_put_failure;
437 
438 	ip = nla_nest_start(msg, CTA_TUPLE_IP);
439 	if (!ip)
440 		goto nla_put_failure;
441 
442 	addr = nfnl_ct_get_src(ct, repl);
443 	if (addr)
444 		NLA_PUT_ADDR(msg,
445 			     family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
446 			     addr);
447 
448 	addr = nfnl_ct_get_dst(ct, repl);
449 	if (addr)
450 		NLA_PUT_ADDR(msg,
451 			     family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
452 			     addr);
453 
454 	nla_nest_end(msg, ip);
455 
456 	proto = nla_nest_start(msg, CTA_TUPLE_PROTO);
457 	if (!proto)
458 		goto nla_put_failure;
459 
460 	if (nfnl_ct_test_proto(ct))
461 		NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_ct_get_proto(ct));
462 
463 	if (nfnl_ct_test_src_port(ct, repl))
464 		NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT,
465 			htons(nfnl_ct_get_src_port(ct, repl)));
466 
467 	if (nfnl_ct_test_dst_port(ct, repl))
468 		NLA_PUT_U16(msg, CTA_PROTO_DST_PORT,
469 			htons(nfnl_ct_get_dst_port(ct, repl)));
470 
471 	if (family == AF_INET) {
472 		if (nfnl_ct_test_icmp_id(ct, repl))
473 			NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
474 						htons(nfnl_ct_get_icmp_id(ct, repl)));
475 
476 		if (nfnl_ct_test_icmp_type(ct, repl))
477 			NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
478 					   nfnl_ct_get_icmp_type(ct, repl));
479 
480 		if (nfnl_ct_test_icmp_code(ct, repl))
481 			NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
482 					   nfnl_ct_get_icmp_code(ct, repl));
483 	} else if (family == AF_INET6) {
484 		if (nfnl_ct_test_icmp_id(ct, repl))
485 			NLA_PUT_U16(msg, CTA_PROTO_ICMPV6_ID,
486 						htons(nfnl_ct_get_icmp_id(ct, repl)));
487 
488 		if (nfnl_ct_test_icmp_type(ct, repl))
489 			NLA_PUT_U8(msg, CTA_PROTO_ICMPV6_TYPE,
490 					   nfnl_ct_get_icmp_type(ct, repl));
491 
492 		if (nfnl_ct_test_icmp_code(ct, repl))
493 			NLA_PUT_U8(msg, CTA_PROTO_ICMPV6_CODE,
494 					   nfnl_ct_get_icmp_code(ct, repl));
495 	}
496 
497 	nla_nest_end(msg, proto);
498 
499 	nla_nest_end(msg, tuple);
500 	return 0;
501 
502 nla_put_failure:
503 	return -NLE_MSGSIZE;
504 }
505 
nfnl_ct_build_message(const struct nfnl_ct * ct,int cmd,int flags,struct nl_msg ** result)506 static int nfnl_ct_build_message(const struct nfnl_ct *ct, int cmd, int flags,
507 				 struct nl_msg **result)
508 {
509 	struct nl_msg *msg;
510 	int err;
511 
512 	msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK, cmd, flags,
513 				   nfnl_ct_get_family(ct), 0);
514 	if (msg == NULL)
515 		return -NLE_NOMEM;
516 
517 	if ((err = nfnl_ct_build_tuple(msg, ct, 0)) < 0)
518 		goto err_out;
519 
520 	/* REPLY tuple is optional, dont add unless at least src/dst specified */
521 
522 	if ( nfnl_ct_get_src(ct, 1) && nfnl_ct_get_dst(ct, 1) )
523 		if ((err = nfnl_ct_build_tuple(msg, ct, 1)) < 0)
524 			goto err_out;
525 
526 	if (nfnl_ct_test_status(ct))
527 		NLA_PUT_U32(msg, CTA_STATUS, htonl(nfnl_ct_get_status(ct)));
528 
529 	if (nfnl_ct_test_timeout(ct))
530 		NLA_PUT_U32(msg, CTA_TIMEOUT, htonl(nfnl_ct_get_timeout(ct)));
531 
532 	if (nfnl_ct_test_mark(ct))
533 		NLA_PUT_U32(msg, CTA_MARK, htonl(nfnl_ct_get_mark(ct)));
534 
535 	if (nfnl_ct_test_id(ct))
536 		NLA_PUT_U32(msg, CTA_ID, htonl(nfnl_ct_get_id(ct)));
537 
538 	if (nfnl_ct_test_zone(ct))
539 		NLA_PUT_U16(msg, CTA_ZONE, htons(nfnl_ct_get_zone(ct)));
540 
541 	*result = msg;
542 	return 0;
543 
544 nla_put_failure:
545 err_out:
546 	nlmsg_free(msg);
547 	return err;
548 }
549 
nfnl_ct_build_add_request(const struct nfnl_ct * ct,int flags,struct nl_msg ** result)550 int nfnl_ct_build_add_request(const struct nfnl_ct *ct, int flags,
551 			      struct nl_msg **result)
552 {
553 	return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_NEW, flags, result);
554 }
555 
nfnl_ct_add(struct nl_sock * sk,const struct nfnl_ct * ct,int flags)556 int nfnl_ct_add(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
557 {
558 	struct nl_msg *msg;
559 	int err;
560 
561 	if ((err = nfnl_ct_build_add_request(ct, flags, &msg)) < 0)
562 		return err;
563 
564 	err = nl_send_auto_complete(sk, msg);
565 	nlmsg_free(msg);
566 	if (err < 0)
567 		return err;
568 
569 	return wait_for_ack(sk);
570 }
571 
nfnl_ct_build_delete_request(const struct nfnl_ct * ct,int flags,struct nl_msg ** result)572 int nfnl_ct_build_delete_request(const struct nfnl_ct *ct, int flags,
573 				 struct nl_msg **result)
574 {
575 	return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_DELETE, flags, result);
576 }
577 
nfnl_ct_del(struct nl_sock * sk,const struct nfnl_ct * ct,int flags)578 int nfnl_ct_del(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
579 {
580 	struct nl_msg *msg;
581 	int err;
582 
583 	if ((err = nfnl_ct_build_delete_request(ct, flags, &msg)) < 0)
584 		return err;
585 
586 	err = nl_send_auto_complete(sk, msg);
587 	nlmsg_free(msg);
588 	if (err < 0)
589 		return err;
590 
591 	return wait_for_ack(sk);
592 }
593 
nfnl_ct_build_query_request(const struct nfnl_ct * ct,int flags,struct nl_msg ** result)594 int nfnl_ct_build_query_request(const struct nfnl_ct *ct, int flags,
595 				struct nl_msg **result)
596 {
597 	return nfnl_ct_build_message(ct, IPCTNL_MSG_CT_GET, flags, result);
598 }
599 
nfnl_ct_query(struct nl_sock * sk,const struct nfnl_ct * ct,int flags)600 int nfnl_ct_query(struct nl_sock *sk, const struct nfnl_ct *ct, int flags)
601 {
602 	struct nl_msg *msg;
603 	int err;
604 
605 	if ((err = nfnl_ct_build_query_request(ct, flags, &msg)) < 0)
606 		return err;
607 
608 	err = nl_send_auto_complete(sk, msg);
609 	nlmsg_free(msg);
610 	if (err < 0)
611 		return err;
612 
613 	return wait_for_ack(sk);
614 }
615 
616 /**
617  * @name Cache Management
618  * @{
619  */
620 
621 /**
622  * Build a conntrack cache holding all conntrack currently in the kernel
623  * @arg sk		Netlink socket.
624  * @arg result		Pointer to store resulting cache.
625  *
626  * Allocates a new cache, initializes it properly and updates it to
627  * contain all conntracks currently in the kernel.
628  *
629  * @return 0 on success or a negative error code.
630  */
nfnl_ct_alloc_cache(struct nl_sock * sk,struct nl_cache ** result)631 int nfnl_ct_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
632 {
633 	return nl_cache_alloc_and_fill(&nfnl_ct_ops, sk, result);
634 }
635 
636 /** @} */
637 
638 /**
639  * @name Conntrack Addition
640  * @{
641  */
642 
643 /** @} */
644 
645 static struct nl_af_group ct_groups[] = {
646 	{ AF_UNSPEC, NFNLGRP_CONNTRACK_NEW },
647 	{ AF_UNSPEC, NFNLGRP_CONNTRACK_UPDATE },
648 	{ AF_UNSPEC, NFNLGRP_CONNTRACK_DESTROY },
649 	{ END_OF_GROUP_LIST },
650 };
651 
652 #define NFNLMSG_CT_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK, (type))
653 static struct nl_cache_ops nfnl_ct_ops = {
654 	.co_name		= "netfilter/ct",
655 	.co_hdrsize		= NFNL_HDRLEN,
656 	.co_msgtypes		= {
657 		{ NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_NEW), NL_ACT_NEW, "new" },
658 		{ NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_GET), NL_ACT_GET, "get" },
659 		{ NFNLMSG_CT_TYPE(IPCTNL_MSG_CT_DELETE), NL_ACT_DEL, "del" },
660 		END_OF_MSGTYPES_LIST,
661 	},
662 	.co_protocol		= NETLINK_NETFILTER,
663 	.co_groups		= ct_groups,
664 	.co_request_update	= ct_request_update,
665 	.co_msg_parser		= ct_msg_parser,
666 	.co_obj_ops		= &ct_obj_ops,
667 };
668 
ct_init(void)669 static void __init ct_init(void)
670 {
671 	nl_cache_mngt_register(&nfnl_ct_ops);
672 }
673 
ct_exit(void)674 static void __exit ct_exit(void)
675 {
676 	nl_cache_mngt_unregister(&nfnl_ct_ops);
677 }
678 
679 /** @} */
680