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