libnl  3.4.0
exp.c
1 /*
2  * lib/netfilter/exp.c Conntrack Expectation
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  * Copyright (c) 2012 Rich Fought <rich.fought@watchguard.com>
14  */
15 
16 /**
17  * @ingroup nfnl
18  * @defgroup exp Expectation
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/exp.h>
31 
32 static struct nl_cache_ops nfnl_exp_ops;
33 
34 static struct nla_policy exp_policy[CTA_EXPECT_MAX+1] = {
35  [CTA_EXPECT_MASTER] = { .type = NLA_NESTED },
36  [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED },
37  [CTA_EXPECT_MASK] = { .type = NLA_NESTED },
38  [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 },
39  [CTA_EXPECT_ID] = { .type = NLA_U32 },
40  [CTA_EXPECT_HELP_NAME] = { .type = NLA_STRING },
41  [CTA_EXPECT_ZONE] = { .type = NLA_U16 },
42  [CTA_EXPECT_FLAGS] = { .type = NLA_U32 }, // Added in kernel 2.6.37
43  [CTA_EXPECT_CLASS] = { .type = NLA_U32 }, // Added in kernel 3.5
44  [CTA_EXPECT_NAT] = { .type = NLA_NESTED }, // Added in kernel 3.5
45  [CTA_EXPECT_FN] = { .type = NLA_STRING }, // Added in kernel 3.5
46 };
47 
48 static struct nla_policy exp_tuple_policy[CTA_TUPLE_MAX+1] = {
49  [CTA_TUPLE_IP] = { .type = NLA_NESTED },
50  [CTA_TUPLE_PROTO] = { .type = NLA_NESTED },
51 };
52 
53 static struct nla_policy exp_ip_policy[CTA_IP_MAX+1] = {
54  [CTA_IP_V4_SRC] = { .type = NLA_U32 },
55  [CTA_IP_V4_DST] = { .type = NLA_U32 },
56  [CTA_IP_V6_SRC] = { .minlen = 16 },
57  [CTA_IP_V6_DST] = { .minlen = 16 },
58 };
59 
60 static struct nla_policy exp_proto_policy[CTA_PROTO_MAX+1] = {
61  [CTA_PROTO_NUM] = { .type = NLA_U8 },
62  [CTA_PROTO_SRC_PORT] = { .type = NLA_U16 },
63  [CTA_PROTO_DST_PORT] = { .type = NLA_U16 },
64  [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 },
65  [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 },
66  [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 },
67  [CTA_PROTO_ICMPV6_ID] = { .type = NLA_U16 },
68  [CTA_PROTO_ICMPV6_TYPE] = { .type = NLA_U8 },
69  [CTA_PROTO_ICMPV6_CODE] = { .type = NLA_U8 },
70 };
71 
72 static struct nla_policy exp_nat_policy[CTA_EXPECT_NAT_MAX+1] = {
73  [CTA_EXPECT_NAT_DIR] = { .type = NLA_U32 },
74  [CTA_EXPECT_NAT_TUPLE] = { .type = NLA_NESTED },
75 };
76 
77 static int exp_parse_ip(struct nfnl_exp *exp, int tuple, struct nlattr *attr)
78 {
79  struct nlattr *tb[CTA_IP_MAX+1];
80  struct nl_addr *addr;
81  int err;
82 
83  err = nla_parse_nested(tb, CTA_IP_MAX, attr, exp_ip_policy);
84  if (err < 0)
85  goto errout;
86 
87  if (tb[CTA_IP_V4_SRC]) {
88  addr = nl_addr_alloc_attr(tb[CTA_IP_V4_SRC], AF_INET);
89  if (addr == NULL)
90  goto errout_enomem;
91  err = nfnl_exp_set_src(exp, tuple, addr);
92  nl_addr_put(addr);
93  if (err < 0)
94  goto errout;
95  }
96  if (tb[CTA_IP_V4_DST]) {
97  addr = nl_addr_alloc_attr(tb[CTA_IP_V4_DST], AF_INET);
98  if (addr == NULL)
99  goto errout_enomem;
100  err = nfnl_exp_set_dst(exp, tuple, addr);
101  nl_addr_put(addr);
102  if (err < 0)
103  goto errout;
104  }
105  if (tb[CTA_IP_V6_SRC]) {
106  addr = nl_addr_alloc_attr(tb[CTA_IP_V6_SRC], AF_INET6);
107  if (addr == NULL)
108  goto errout_enomem;
109  err = nfnl_exp_set_src(exp, tuple, addr);
110  nl_addr_put(addr);
111  if (err < 0)
112  goto errout;
113  }
114  if (tb[CTA_IP_V6_DST]) {
115  addr = nl_addr_alloc_attr(tb[CTA_IP_V6_DST], AF_INET6);
116  if (addr == NULL)
117  goto errout_enomem;
118  err = nfnl_exp_set_dst(exp, tuple, addr);
119  nl_addr_put(addr);
120  if (err < 0)
121  goto errout;
122  }
123 
124  return 0;
125 
126 errout_enomem:
127  err = -NLE_NOMEM;
128 errout:
129  return err;
130 }
131 
132 static int exp_parse_proto(struct nfnl_exp *exp, int tuple, struct nlattr *attr)
133 {
134  struct nlattr *tb[CTA_PROTO_MAX+1];
135  int err;
136  uint16_t srcport = 0, dstport = 0, icmpid = 0;
137  uint8_t icmptype = 0, icmpcode = 0;
138 
139  err = nla_parse_nested(tb, CTA_PROTO_MAX, attr, exp_proto_policy);
140  if (err < 0)
141  return err;
142 
143  if (tb[CTA_PROTO_NUM])
144  nfnl_exp_set_l4protonum(exp, tuple, nla_get_u8(tb[CTA_PROTO_NUM]));
145 
146  if (tb[CTA_PROTO_SRC_PORT])
147  srcport = ntohs(nla_get_u16(tb[CTA_PROTO_SRC_PORT]));
148  if (tb[CTA_PROTO_DST_PORT])
149  dstport = ntohs(nla_get_u16(tb[CTA_PROTO_DST_PORT]));
150  if (tb[CTA_PROTO_SRC_PORT] || tb[CTA_PROTO_DST_PORT])
151  nfnl_exp_set_ports(exp, tuple, srcport, dstport);
152 
153  if (tb[CTA_PROTO_ICMP_ID])
154  icmpid = ntohs(nla_get_u16(tb[CTA_PROTO_ICMP_ID]));
155  if (tb[CTA_PROTO_ICMP_TYPE])
156  icmptype = nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]);
157  if (tb[CTA_PROTO_ICMP_CODE])
158  icmpcode = nla_get_u8(tb[CTA_PROTO_ICMP_CODE]);
159  if (tb[CTA_PROTO_ICMP_ID] || tb[CTA_PROTO_ICMP_TYPE] || tb[CTA_PROTO_ICMP_CODE])
160  nfnl_exp_set_icmp(exp, tuple, icmpid, icmptype, icmpcode);
161  return 0;
162 }
163 
164 static int exp_parse_tuple(struct nfnl_exp *exp, int tuple, struct nlattr *attr)
165 {
166  struct nlattr *tb[CTA_TUPLE_MAX+1];
167  int err;
168 
169  err = nla_parse_nested(tb, CTA_TUPLE_MAX, attr, exp_tuple_policy);
170  if (err < 0)
171  return err;
172 
173  if (tb[CTA_TUPLE_IP]) {
174  err = exp_parse_ip(exp, tuple, tb[CTA_TUPLE_IP]);
175  if (err < 0)
176  return err;
177  }
178 
179  if (tb[CTA_TUPLE_PROTO]) {
180  err = exp_parse_proto(exp, tuple, tb[CTA_TUPLE_PROTO]);
181  if (err < 0)
182  return err;
183  }
184 
185  return 0;
186 }
187 
188 static int exp_parse_nat(struct nfnl_exp *exp, struct nlattr *attr)
189 {
190  struct nlattr *tb[CTA_EXPECT_NAT_MAX+1];
191  int err;
192 
193  err = nla_parse_nested(tb, CTA_EXPECT_NAT_MAX, attr, exp_nat_policy);
194  if (err < 0)
195  return err;
196 
197  if (tb[CTA_EXPECT_NAT_DIR])
198  nfnl_exp_set_nat_dir(exp, nla_get_u32(tb[CTA_EXPECT_NAT_DIR]));
199 
200  if (tb[CTA_EXPECT_NAT_TUPLE]) {
201  err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_NAT, tb[CTA_EXPECT_NAT_TUPLE]);
202  if (err < 0)
203  return err;
204  }
205 
206  return 0;
207 }
208 
209 int nfnlmsg_exp_group(struct nlmsghdr *nlh)
210 {
211  switch (nfnlmsg_subtype(nlh)) {
212  case IPCTNL_MSG_EXP_NEW:
213  if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
214  return NFNLGRP_CONNTRACK_EXP_NEW;
215  else
216  return NFNLGRP_CONNTRACK_EXP_UPDATE;
217  case IPCTNL_MSG_EXP_DELETE:
218  return NFNLGRP_CONNTRACK_EXP_DESTROY;
219  default:
220  return NFNLGRP_NONE;
221  }
222 }
223 
224 int nfnlmsg_exp_parse(struct nlmsghdr *nlh, struct nfnl_exp **result)
225 {
226  struct nfnl_exp *exp;
227  struct nlattr *tb[CTA_MAX+1];
228  int err;
229 
230  exp = nfnl_exp_alloc();
231  if (!exp)
232  return -NLE_NOMEM;
233 
234  exp->ce_msgtype = nlh->nlmsg_type;
235 
236  err = nlmsg_parse(nlh, sizeof(struct nfgenmsg), tb, CTA_EXPECT_MAX,
237  exp_policy);
238  if (err < 0)
239  goto errout;
240 
241  nfnl_exp_set_family(exp, nfnlmsg_family(nlh));
242 
243  if (tb[CTA_EXPECT_TUPLE]) {
244  err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_EXPECT, tb[CTA_EXPECT_TUPLE]);
245  if (err < 0)
246  goto errout;
247  }
248  if (tb[CTA_EXPECT_MASTER]) {
249  err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASTER, tb[CTA_EXPECT_MASTER]);
250  if (err < 0)
251  goto errout;
252  }
253  if (tb[CTA_EXPECT_MASK]) {
254  err = exp_parse_tuple(exp, NFNL_EXP_TUPLE_MASK, tb[CTA_EXPECT_MASK]);
255  if (err < 0)
256  goto errout;
257  }
258 
259  if (tb[CTA_EXPECT_NAT]) {
260  err = exp_parse_nat(exp, tb[CTA_EXPECT_MASK]);
261  if (err < 0)
262  goto errout;
263  }
264 
265  if (tb[CTA_EXPECT_CLASS])
266  nfnl_exp_set_class(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_CLASS])));
267 
268  if (tb[CTA_EXPECT_FN])
269  nfnl_exp_set_fn(exp, nla_data(tb[CTA_EXPECT_FN]));
270 
271  if (tb[CTA_EXPECT_TIMEOUT])
272  nfnl_exp_set_timeout(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_TIMEOUT])));
273 
274  if (tb[CTA_EXPECT_ID])
275  nfnl_exp_set_id(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_ID])));
276 
277  if (tb[CTA_EXPECT_HELP_NAME])
278  nfnl_exp_set_helper_name(exp, nla_data(tb[CTA_EXPECT_HELP_NAME]));
279 
280  if (tb[CTA_EXPECT_ZONE])
281  nfnl_exp_set_zone(exp, ntohs(nla_get_u16(tb[CTA_EXPECT_ZONE])));
282 
283  if (tb[CTA_EXPECT_FLAGS])
284  nfnl_exp_set_flags(exp, ntohl(nla_get_u32(tb[CTA_EXPECT_FLAGS])));
285 
286  *result = exp;
287  return 0;
288 
289 errout:
290  nfnl_exp_put(exp);
291  return err;
292 }
293 
294 static int exp_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
295  struct nlmsghdr *nlh, struct nl_parser_param *pp)
296 {
297  struct nfnl_exp *exp;
298  int err;
299 
300  if ((err = nfnlmsg_exp_parse(nlh, &exp)) < 0)
301  return err;
302 
303  err = pp->pp_cb((struct nl_object *) exp, pp);
304  nfnl_exp_put(exp);
305  return err;
306 }
307 
308 /**
309  * Send nfnl exp dump request
310  * @arg sk Netlink socket.
311  *
312  * @return 0 on success or a negative error code. Due to a bug, this function
313  * returns the number of bytes sent. Treat any non-negative number as success.
314  */
315 int nfnl_exp_dump_request(struct nl_sock *sk)
316 {
317  return nfnl_send_simple(sk, NFNL_SUBSYS_CTNETLINK_EXP, IPCTNL_MSG_EXP_GET,
318  NLM_F_DUMP, AF_UNSPEC, 0);
319 }
320 
321 static int exp_request_update(struct nl_cache *cache, struct nl_sock *sk)
322 {
323  return nfnl_exp_dump_request(sk);
324 }
325 
326 static int exp_get_tuple_attr(int tuple)
327 {
328  int attr = 0;
329 
330  switch (tuple) {
331  case CTA_EXPECT_MASTER:
332  attr = NFNL_EXP_TUPLE_MASTER;
333  break;
334  case CTA_EXPECT_MASK:
335  attr = NFNL_EXP_TUPLE_MASK;
336  break;
337  case CTA_EXPECT_NAT:
338  attr = NFNL_EXP_TUPLE_NAT;
339  break;
340  case CTA_EXPECT_TUPLE:
341  default :
342  attr = NFNL_EXP_TUPLE_EXPECT;
343  break;
344  }
345 
346  return attr;
347 }
348 
349 static int nfnl_exp_build_tuple(struct nl_msg *msg, const struct nfnl_exp *exp,
350  int cta)
351 {
352  struct nlattr *tuple, *ip, *proto;
353  struct nl_addr *addr;
354  int family;
355 
356  family = nfnl_exp_get_family(exp);
357 
358  int type = exp_get_tuple_attr(cta);
359 
360  if (cta == CTA_EXPECT_NAT)
361  tuple = nla_nest_start(msg, CTA_EXPECT_NAT_TUPLE);
362  else
363  tuple = nla_nest_start(msg, cta);
364 
365  if (!tuple)
366  goto nla_put_failure;
367 
368  ip = nla_nest_start(msg, CTA_TUPLE_IP);
369  if (!ip)
370  goto nla_put_failure;
371 
372  addr = nfnl_exp_get_src(exp, type);
373  if (addr)
374  NLA_PUT_ADDR(msg,
375  family == AF_INET ? CTA_IP_V4_SRC : CTA_IP_V6_SRC,
376  addr);
377 
378  addr = nfnl_exp_get_dst(exp, type);
379  if (addr)
380  NLA_PUT_ADDR(msg,
381  family == AF_INET ? CTA_IP_V4_DST : CTA_IP_V6_DST,
382  addr);
383 
384  nla_nest_end(msg, ip);
385 
386  proto = nla_nest_start(msg, CTA_TUPLE_PROTO);
387  if (!proto)
388  goto nla_put_failure;
389 
390  if (nfnl_exp_test_l4protonum(exp, type))
391  NLA_PUT_U8(msg, CTA_PROTO_NUM, nfnl_exp_get_l4protonum(exp, type));
392 
393  if (nfnl_exp_test_ports(exp, type)) {
394  NLA_PUT_U16(msg, CTA_PROTO_SRC_PORT,
395  htons(nfnl_exp_get_src_port(exp, type)));
396 
397  NLA_PUT_U16(msg, CTA_PROTO_DST_PORT,
398  htons(nfnl_exp_get_dst_port(exp, type)));
399  }
400 
401  if (nfnl_exp_test_icmp(exp, type)) {
402  NLA_PUT_U16(msg, CTA_PROTO_ICMP_ID,
403  htons(nfnl_exp_get_icmp_id(exp, type)));
404 
405  NLA_PUT_U8(msg, CTA_PROTO_ICMP_TYPE,
406  nfnl_exp_get_icmp_type(exp, type));
407 
408  NLA_PUT_U8(msg, CTA_PROTO_ICMP_CODE,
409  nfnl_exp_get_icmp_code(exp, type));
410  }
411 
412  nla_nest_end(msg, proto);
413 
414  nla_nest_end(msg, tuple);
415  return 0;
416 
417 nla_put_failure:
418  return -NLE_MSGSIZE;
419 }
420 
421 static int nfnl_exp_build_nat(struct nl_msg *msg, const struct nfnl_exp *exp)
422 {
423  struct nlattr *nat;
424  int err;
425 
426  nat = nla_nest_start(msg, CTA_EXPECT_NAT);
427 
428  if (nfnl_exp_test_nat_dir(exp)) {
429  NLA_PUT_U32(msg, CTA_EXPECT_NAT_DIR,
430  nfnl_exp_get_nat_dir(exp));
431  }
432 
433  if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_NAT)) < 0)
434  goto nla_put_failure;
435 
436  nla_nest_end(msg, nat);
437  return 0;
438 
439 nla_put_failure:
440  return -NLE_MSGSIZE;
441 }
442 
443 static int nfnl_exp_build_message(const struct nfnl_exp *exp, int cmd, int flags,
444  struct nl_msg **result)
445 {
446  struct nl_msg *msg;
447  int err;
448 
449  msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_CTNETLINK_EXP, cmd, flags,
450  nfnl_exp_get_family(exp), 0);
451  if (msg == NULL)
452  return -NLE_NOMEM;
453 
454  if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_TUPLE)) < 0)
455  goto err_out;
456 
457  if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASTER)) < 0)
458  goto err_out;
459 
460  if ((err = nfnl_exp_build_tuple(msg, exp, CTA_EXPECT_MASK)) < 0)
461  goto err_out;
462 
463  if (nfnl_exp_test_src(exp, NFNL_EXP_TUPLE_NAT)) {
464  if ((err = nfnl_exp_build_nat(msg, exp)) < 0)
465  goto err_out;
466  }
467 
468  if (nfnl_exp_test_class(exp))
469  NLA_PUT_U32(msg, CTA_EXPECT_CLASS, htonl(nfnl_exp_get_class(exp)));
470 
471  if (nfnl_exp_test_fn(exp))
472  NLA_PUT_STRING(msg, CTA_EXPECT_FN, nfnl_exp_get_fn(exp));
473 
474  if (nfnl_exp_test_id(exp))
475  NLA_PUT_U32(msg, CTA_EXPECT_ID, htonl(nfnl_exp_get_id(exp)));
476 
477  if (nfnl_exp_test_timeout(exp))
478  NLA_PUT_U32(msg, CTA_EXPECT_TIMEOUT, htonl(nfnl_exp_get_timeout(exp)));
479 
480  if (nfnl_exp_test_helper_name(exp))
481  NLA_PUT_STRING(msg, CTA_EXPECT_HELP_NAME, nfnl_exp_get_helper_name(exp));
482 
483  if (nfnl_exp_test_zone(exp))
484  NLA_PUT_U16(msg, CTA_EXPECT_ZONE, htons(nfnl_exp_get_zone(exp)));
485 
486  if (nfnl_exp_test_flags(exp))
487  NLA_PUT_U32(msg, CTA_EXPECT_FLAGS, htonl(nfnl_exp_get_flags(exp)));
488 
489  *result = msg;
490  return 0;
491 
492 nla_put_failure:
493 err_out:
494  nlmsg_free(msg);
495  return err;
496 }
497 
498 int nfnl_exp_build_add_request(const struct nfnl_exp *exp, int flags,
499  struct nl_msg **result)
500 {
501  return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_NEW, flags, result);
502 }
503 
504 int nfnl_exp_add(struct nl_sock *sk, const struct nfnl_exp *exp, int flags)
505 {
506  struct nl_msg *msg;
507  int err;
508 
509  if ((err = nfnl_exp_build_add_request(exp, flags, &msg)) < 0)
510  return err;
511 
512  err = nl_send_auto_complete(sk, msg);
513  nlmsg_free(msg);
514  if (err < 0)
515  return err;
516 
517  return wait_for_ack(sk);
518 }
519 
520 int nfnl_exp_build_delete_request(const struct nfnl_exp *exp, int flags,
521  struct nl_msg **result)
522 {
523  return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_DELETE, flags, result);
524 }
525 
526 int nfnl_exp_del(struct nl_sock *sk, const struct nfnl_exp *exp, int flags)
527 {
528  struct nl_msg *msg;
529  int err;
530 
531  if ((err = nfnl_exp_build_delete_request(exp, flags, &msg)) < 0)
532  return err;
533 
534  err = nl_send_auto_complete(sk, msg);
535  nlmsg_free(msg);
536  if (err < 0)
537  return err;
538 
539  return wait_for_ack(sk);
540 }
541 
542 int nfnl_exp_build_query_request(const struct nfnl_exp *exp, int flags,
543  struct nl_msg **result)
544 {
545  return nfnl_exp_build_message(exp, IPCTNL_MSG_EXP_GET, flags, result);
546 }
547 
548 int nfnl_exp_query(struct nl_sock *sk, const struct nfnl_exp *exp, int flags)
549 {
550  struct nl_msg *msg;
551  int err;
552 
553  if ((err = nfnl_exp_build_query_request(exp, flags, &msg)) < 0)
554  return err;
555 
556  err = nl_send_auto_complete(sk, msg);
557  nlmsg_free(msg);
558  if (err < 0)
559  return err;
560 
561  return wait_for_ack(sk);
562 }
563 
564 /**
565  * @name Cache Management
566  * @{
567  */
568 
569 /**
570  * Build a expectation cache holding all expectations currently in the kernel
571  * @arg sk Netlink socket.
572  * @arg result Pointer to store resulting cache.
573  *
574  * Allocates a new cache, initializes it properly and updates it to
575  * contain all expectations currently in the kernel.
576  *
577  * @return 0 on success or a negative error code.
578  */
579 int nfnl_exp_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
580 {
581  return nl_cache_alloc_and_fill(&nfnl_exp_ops, sk, result);
582 }
583 
584 /** @} */
585 
586 /**
587  * @name Expectation Addition
588  * @{
589  */
590 
591 /** @} */
592 
593 static struct nl_af_group exp_groups[] = {
594  { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_NEW },
595  { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_UPDATE },
596  { AF_UNSPEC, NFNLGRP_CONNTRACK_EXP_DESTROY },
597  { END_OF_GROUP_LIST },
598 };
599 
600 #define NFNLMSG_EXP_TYPE(type) NFNLMSG_TYPE(NFNL_SUBSYS_CTNETLINK_EXP, (type))
601 static struct nl_cache_ops nfnl_exp_ops = {
602  .co_name = "netfilter/exp",
603  .co_hdrsize = NFNL_HDRLEN,
604  .co_msgtypes = {
605  { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_NEW), NL_ACT_NEW, "new" },
606  { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_GET), NL_ACT_GET, "get" },
607  { NFNLMSG_EXP_TYPE(IPCTNL_MSG_EXP_DELETE), NL_ACT_DEL, "del" },
608  END_OF_MSGTYPES_LIST,
609  },
610  .co_protocol = NETLINK_NETFILTER,
611  .co_groups = exp_groups,
612  .co_request_update = exp_request_update,
613  .co_msg_parser = exp_msg_parser,
614  .co_obj_ops = &exp_obj_ops,
615 };
616 
617 static void __init exp_init(void)
618 {
619  nl_cache_mngt_register(&nfnl_exp_ops);
620 }
621 
622 static void __exit exp_exit(void)
623 {
624  nl_cache_mngt_unregister(&nfnl_exp_ops);
625 }
626 
627 /** @} */
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
int nfnl_exp_dump_request(struct nl_sock *sk)
Send nfnl exp dump request.
Definition: exp.c:315
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
Definition: attr.h:288
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
int nfnl_exp_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
Build a expectation cache holding all expectations currently in the kernel.
Definition: exp.c:579
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
NUL terminated character string.
Definition: attr.h:45
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition: attr.c:924
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
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition: attr.c:120
#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
#define NLA_PUT_STRING(msg, attrtype, value)
Add string attribute to netlink message.
Definition: attr.h:262
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
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