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