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