libnl  3.7.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 <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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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 
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  */
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 
454 static int ct_request_update(struct nl_cache *cache, struct nl_sock *sk)
455 {
456  return nfnl_ct_dump_request(sk);
457 }
458 
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 
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 
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 
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 
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 
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 
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 
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  */
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 
707 static void __init ct_init(void)
708 {
709  nl_cache_mngt_register(&nfnl_ct_ops);
710 }
711 
712 static void __exit ct_exit(void)
713 {
714  nl_cache_mngt_unregister(&nfnl_ct_ops);
715 }
716 
717 /** @} */
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
Definition: addr.c:256
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition: addr.c:533
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:699
uint16_t nla_get_u16(const struct nlattr *nla)
Return payload of 16 bit integer attribute.
Definition: attr.c:649
#define NLA_PUT_U16(msg, attrtype, value)
Add 16 bit integer attribute to netlink message.
Definition: attr.h:212
#define NLA_PUT_U8(msg, attrtype, value)
Add 8 bit integer attribute to netlink message.
Definition: attr.h:194
uint64_t nla_get_u64(const struct nlattr *nla)
Return payload of u64 attribute.
Definition: attr.c:754
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
Definition: attr.h:283
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:230
uint8_t nla_get_u8(const struct nlattr *nla)
Return value of 8 bit integer attribute.
Definition: attr.c:599
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition: attr.c:895
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:1013
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:958
@ 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:281
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:246
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:228
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:669
int nfnl_ct_dump_request(struct nl_sock *sk)
Send nfnl ct dump request.
Definition: ct.c:448
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition: msg.c:558
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:208
uint8_t nfnlmsg_family(struct nlmsghdr *nlh)
Get netfilter family from message.
Definition: nfnl.c:146
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:104
uint8_t nfnlmsg_subtype(struct nlmsghdr *nlh)
Get netfilter message type from message.
Definition: nfnl.c:137
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:197
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
Definition: nl.c:1241
Attribute validation policy.
Definition: attr.h:63
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:65