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