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