libnl  3.5.0
ct.c
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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  */
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 
420 static int ct_request_update(struct nl_cache *cache, struct nl_sock *sk)
421 {
422  return nfnl_ct_dump_request(sk);
423 }
424 
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 
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 
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 
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 
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 
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 
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 
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  */
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 
669 static void __init ct_init(void)
670 {
671  nl_cache_mngt_register(&nfnl_ct_ops);
672 }
673 
674 static void __exit ct_exit(void)
675 {
676  nl_cache_mngt_unregister(&nfnl_ct_ops);
677 }
678 
679 /** @} */
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
Definition: nl.c:1248
8 bit integer
Definition: attr.h:41
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition: msg.c:565
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:215
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
Definition: attr.h:289
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:631
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:288
Attribute validation policy.
Definition: attr.h:69
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition: attr.c:607
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:707
uint8_t nfnlmsg_subtype(struct nlmsghdr *nlh)
Get netfilter message type from message.
Definition: nfnl.c:144
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
Definition: addr.c:263
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition: attr.h:200
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:966
int nfnl_ct_dump_request(struct nl_sock *sk)
Send nfnl ct dump request.
Definition: ct.c:414
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:253
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:1021
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:111
16 bit integer
Definition: attr.h:42
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:236
uint8_t nfnlmsg_family(struct nlmsghdr *nlh)
Get netfilter family from message.
Definition: nfnl.c:153
64 bit integer
Definition: attr.h:44
Nested attributes.
Definition: attr.h:48
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition: addr.c:540
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:71
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:657
32 bit integer
Definition: attr.h:43
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:218
uint64_t nla_get_u64(const struct nlattr *nla)
Return payload of u64 attribute.
Definition: attr.c:762
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:204
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
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:903