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