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

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