libnl: /data/src/libnl/lib/netfilter/exp.c Source File

libnl 3.12.0

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