libnl 3.11.0
ematch.c
1/* SPDX-License-Identifier: LGPL-2.1-only */
2/*
3 * Copyright (c) 2008-2013 Thomas Graf <tgraf@suug.ch>
4 */
5
6/**
7 * @ingroup cls
8 * @defgroup ematch Extended Match
9 *
10 * @{
11 */
12
13#include "nl-default.h"
14
15#include <linux/tc_ematch/tc_em_cmp.h>
16
17#include <netlink/netlink.h>
18#include <netlink/route/classifier.h>
19#include <netlink/route/cls/ematch.h>
20#include <netlink/route/cls/ematch/cmp.h>
21
22#include "nl-route.h"
23#include "nl-aux-core/nl-core.h"
24
25#include "ematch_syntax.h"
26#include "ematch_grammar.h"
27
28/**
29 * @name Module API
30 * @{
31 */
32
33static NL_LIST_HEAD(ematch_ops_list);
34
35/**
36 * Register ematch module
37 * @arg ops Module operations.
38 *
39 * This function must be called by each ematch module at initialization
40 * time. It registers the calling module as available module.
41 *
42 * @return 0 on success or a negative error code.
43 */
45{
46 if (rtnl_ematch_lookup_ops(ops->eo_kind))
47 return -NLE_EXIST;
48
49 NL_DBG(1, "ematch module \"%s\" registered\n", ops->eo_name);
50
51 nl_list_add_tail(&ops->eo_list, &ematch_ops_list);
52
53 return 0;
54}
55
56/**
57 * Lookup ematch module by identification number.
58 * @arg kind Module kind.
59 *
60 * Searches the list of registered ematch modules for match and returns it.
61 *
62 * @return Module operations or NULL if not found.
63 */
65{
66 struct rtnl_ematch_ops *ops;
67
68 nl_list_for_each_entry(ops, &ematch_ops_list, eo_list)
69 if (ops->eo_kind == kind)
70 return ops;
71
72 return NULL;
73}
74
75/**
76 * Lookup ematch module by name
77 * @arg name Name of ematch module.
78 *
79 * Searches the list of registered ematch modules for a match and returns it.
80 *
81 * @return Module operations or NULL if not fuond.
82 */
84{
85 struct rtnl_ematch_ops *ops;
86
87 nl_list_for_each_entry(ops, &ematch_ops_list, eo_list)
88 if (!strcasecmp(ops->eo_name, name))
89 return ops;
90
91 return NULL;
92}
93
94/** @} */
95
96/**
97 * @name Match
98 */
99
100/**
101 * Allocate ematch object.
102 *
103 * Allocates and initializes an ematch object.
104 *
105 * @return New ematch object or NULL.
106 */
107struct rtnl_ematch *rtnl_ematch_alloc(void)
108{
109 struct rtnl_ematch *e;
110
111 if (!(e = calloc(1, sizeof(*e))))
112 return NULL;
113
114 NL_DBG(2, "allocated ematch %p\n", e);
115
116 NL_INIT_LIST_HEAD(&e->e_list);
117 NL_INIT_LIST_HEAD(&e->e_childs);
118
119 return e;
120}
121
122/**
123 * Add ematch to the end of the parent's list of children.
124 * @arg parent parent ematch object
125 * @arg child ematch object to be added to parent
126 *
127 * The parent must be a container ematch.
128 */
129int rtnl_ematch_add_child(struct rtnl_ematch *parent,
130 struct rtnl_ematch *child)
131{
132 if (parent->e_kind != TCF_EM_CONTAINER)
133 return -NLE_OPNOTSUPP;
134
135 NL_DBG(2, "added ematch %p \"%s\" to container %p\n",
136 child, child->e_ops->eo_name, parent);
137
138 nl_list_add_tail(&child->e_list, &parent->e_childs);
139
140 return 0;
141}
142
143/**
144 * Remove ematch from the list of ematches it is linked to.
145 * @arg ematch ematch object
146 */
147void rtnl_ematch_unlink(struct rtnl_ematch *ematch)
148{
149 NL_DBG(2, "unlinked ematch %p from any lists\n", ematch);
150
151 if (!nl_list_empty(&ematch->e_childs))
152 NL_DBG(1, "warning: ematch %p with childs was unlinked\n",
153 ematch);
154
155 nl_list_del(&ematch->e_list);
156 nl_init_list_head(&ematch->e_list);
157}
158
159void rtnl_ematch_free(struct rtnl_ematch *ematch)
160{
161 NL_DBG(2, "freed ematch %p\n", ematch);
162 rtnl_ematch_unlink(ematch);
163 free(ematch->e_data);
164 free(ematch);
165}
166
167int rtnl_ematch_set_ops(struct rtnl_ematch *ematch, struct rtnl_ematch_ops *ops)
168{
169 if (ematch->e_ops)
170 return -NLE_EXIST;
171
172 ematch->e_ops = ops;
173 ematch->e_kind = ops->eo_kind;
174
175 if (ops->eo_datalen) {
176 ematch->e_data = calloc(1, ops->eo_datalen);
177 if (!ematch->e_data)
178 return -NLE_NOMEM;
179
180 ematch->e_datalen = ops->eo_datalen;
181 }
182
183 return 0;
184}
185
186int rtnl_ematch_set_kind(struct rtnl_ematch *ematch, uint16_t kind)
187{
188 struct rtnl_ematch_ops *ops;
189
190 if (ematch->e_kind)
191 return -NLE_EXIST;
192
193 ematch->e_kind = kind;
194
195 if ((ops = rtnl_ematch_lookup_ops(kind)))
196 rtnl_ematch_set_ops(ematch, ops);
197
198 return 0;
199}
200
201int rtnl_ematch_set_name(struct rtnl_ematch *ematch, const char *name)
202{
203 struct rtnl_ematch_ops *ops;
204
205 if (ematch->e_kind)
206 return -NLE_EXIST;
207
208 if (!(ops = rtnl_ematch_lookup_ops_by_name(name)))
209 return -NLE_OPNOTSUPP;
210
211 rtnl_ematch_set_ops(ematch, ops);
212
213 return 0;
214}
215
216void rtnl_ematch_set_flags(struct rtnl_ematch *ematch, uint16_t flags)
217{
218 ematch->e_flags |= flags;
219}
220
221void rtnl_ematch_unset_flags(struct rtnl_ematch *ematch, uint16_t flags)
222{
223 ematch->e_flags &= ~flags;
224}
225
226uint16_t rtnl_ematch_get_flags(struct rtnl_ematch *ematch)
227{
228 return ematch->e_flags;
229}
230
231void *rtnl_ematch_data(struct rtnl_ematch *ematch)
232{
233 return ematch->e_data;
234}
235
236/** @} */
237
238/**
239 * @name Tree
240 */
241
242/**
243 * Allocate ematch tree object
244 * @arg progid program id
245 */
246struct rtnl_ematch_tree *rtnl_ematch_tree_alloc(uint16_t progid)
247{
248 struct rtnl_ematch_tree *tree;
249
250 if (!(tree = calloc(1, sizeof(*tree))))
251 return NULL;
252
253 NL_INIT_LIST_HEAD(&tree->et_list);
254 tree->et_progid = progid;
255
256 NL_DBG(2, "allocated new ematch tree %p, progid=%u\n", tree, progid);
257
258 return tree;
259}
260
261static void free_ematch_list(struct nl_list_head *head)
262{
263 struct rtnl_ematch *pos, *next;
264
265 nl_list_for_each_entry_safe(pos, next, head, e_list) {
266 if (!nl_list_empty(&pos->e_childs))
267 free_ematch_list(&pos->e_childs);
268 rtnl_ematch_free(pos);
269 }
270}
271
272/**
273 * Free ematch tree object
274 * @arg tree ematch tree object
275 *
276 * This function frees the ematch tree and all ematches attached to it.
277 */
278void rtnl_ematch_tree_free(struct rtnl_ematch_tree *tree)
279{
280 if (!tree)
281 return;
282
283 free_ematch_list(&tree->et_list);
284
285 NL_DBG(2, "Freed ematch tree %p\n", tree);
286
287 free(tree);
288}
289
290static int clone_ematch_list(struct nl_list_head *dst, struct nl_list_head *src)
291{
292 struct rtnl_ematch *new = NULL, *pos = NULL;
293
294 nl_list_for_each_entry(pos, src, e_list) {
295 new = rtnl_ematch_alloc();
296 if (!new)
297 goto nomem;
298
299 new->e_id = pos->e_id;
300 new->e_kind = pos->e_kind;
301 new->e_flags = pos->e_flags;
302 new->e_index = pos->e_index;
303 new->e_datalen = pos->e_datalen;
304
305 if (pos->e_ops) {
306 if (rtnl_ematch_set_ops(new, pos->e_ops))
307 goto nomem;
308 }
309
310 if (!nl_list_empty(&pos->e_childs)) {
311 if (clone_ematch_list(&new->e_childs, &pos->e_childs) < 0)
312 goto nomem;
313 }
314 nl_list_add_tail(&new->e_list, dst);
315 }
316
317 return 0;
318
319nomem:
320 if (new)
321 free(new);
322 free_ematch_list(dst);
323 return -NLE_NOMEM;
324}
325
326/**
327 * Clone ematch tree object
328 * @arg src ematch tree object
329 *
330 * This function clones the ematch tree and all ematches attached to it.
331 */
332struct rtnl_ematch_tree *rtnl_ematch_tree_clone(struct rtnl_ematch_tree *src)
333{
334 struct rtnl_ematch_tree *dst = NULL;
335
336 if (!src)
337 return NULL;
338
339 if (!(dst = rtnl_ematch_tree_alloc(src->et_progid)))
340 return NULL;
341
342 clone_ematch_list(&dst->et_list, &src->et_list);
343
344 return dst;
345}
346
347/**
348 * Add ematch object to the end of the ematch tree
349 * @arg tree ematch tree object
350 * @arg ematch ematch object to add
351 */
352void rtnl_ematch_tree_add(struct rtnl_ematch_tree *tree,
353 struct rtnl_ematch *ematch)
354{
355 nl_list_add_tail(&ematch->e_list, &tree->et_list);
356}
357
358static inline uint32_t container_ref(struct rtnl_ematch *ematch)
359{
360 return *((uint32_t *) rtnl_ematch_data(ematch));
361}
362
363static int link_tree(struct rtnl_ematch *index[], int nmatches, int pos,
364 struct nl_list_head *root)
365{
366 struct rtnl_ematch *ematch;
367 int i;
368
369 for (i = pos; i < nmatches; i++) {
370 ematch = index[i];
371
372 nl_list_add_tail(&ematch->e_list, root);
373
374 if (ematch->e_kind == TCF_EM_CONTAINER)
375 link_tree(index, nmatches, container_ref(ematch),
376 &ematch->e_childs);
377
378 if (!(ematch->e_flags & TCF_EM_REL_MASK))
379 return 0;
380 }
381
382 /* Last entry in chain can't possibly have no relation */
383 return -NLE_INVAL;
384}
385
386static struct nla_policy tree_policy[TCA_EMATCH_TREE_MAX+1] = {
387 [TCA_EMATCH_TREE_HDR] = { .minlen=sizeof(struct tcf_ematch_tree_hdr) },
388 [TCA_EMATCH_TREE_LIST] = { .type = NLA_NESTED },
389};
390
391/**
392 * Parse ematch netlink attributes
393 *
394 * @return 0 on success or a negative error code.
395 */
396int rtnl_ematch_parse_attr(struct nlattr *attr, struct rtnl_ematch_tree **result)
397{
398 struct nlattr *a, *tb[TCA_EMATCH_TREE_MAX+1];
399 struct tcf_ematch_tree_hdr *thdr;
400 struct rtnl_ematch_tree *tree;
401 struct rtnl_ematch **index;
402 int nmatches = 0, err, remaining;
403
404 NL_DBG(2, "Parsing attribute %p as ematch tree\n", attr);
405
406 err = nla_parse_nested(tb, TCA_EMATCH_TREE_MAX, attr, tree_policy);
407 if (err < 0)
408 return err;
409
410 if (!tb[TCA_EMATCH_TREE_HDR])
411 return -NLE_MISSING_ATTR;
412
413 thdr = nla_data(tb[TCA_EMATCH_TREE_HDR]);
414
415 /* Ignore empty trees */
416 if (thdr->nmatches == 0) {
417 NL_DBG(2, "Ignoring empty ematch configuration\n");
418 return 0;
419 }
420
421 if (!tb[TCA_EMATCH_TREE_LIST])
422 return -NLE_MISSING_ATTR;
423
424 NL_DBG(2, "ematch tree found with nmatches=%u, progid=%u\n",
425 thdr->nmatches, thdr->progid);
426
427 /*
428 * Do some basic sanity checking since we will allocate
429 * index[thdr->nmatches]. Calculate how many ematch headers fit into
430 * the provided data and make sure nmatches does not exceed it.
431 */
432 if (thdr->nmatches > (nla_len(tb[TCA_EMATCH_TREE_LIST]) /
433 nla_total_size(sizeof(struct tcf_ematch_hdr))))
434 return -NLE_INVAL;
435
436 if (!(index = calloc(thdr->nmatches, sizeof(struct rtnl_ematch *))))
437 return -NLE_NOMEM;
438
439 if (!(tree = rtnl_ematch_tree_alloc(thdr->progid))) {
440 err = -NLE_NOMEM;
441 goto errout;
442 }
443
444 nla_for_each_nested(a, tb[TCA_EMATCH_TREE_LIST], remaining) {
445 struct rtnl_ematch_ops *ops;
446 struct tcf_ematch_hdr *hdr;
447 struct rtnl_ematch *ematch;
448 void *data;
449 size_t len;
450
451 NL_DBG(3, "parsing ematch attribute %d, len=%u\n",
452 nmatches+1, nla_len(a));
453
454 if (_nla_len(a) < sizeof(*hdr)) {
455 err = -NLE_INVAL;
456 goto errout;
457 }
458
459 /* Quit as soon as we've parsed more matches than expected */
460 if (nmatches >= thdr->nmatches) {
461 err = -NLE_RANGE;
462 goto errout;
463 }
464
465 hdr = nla_data(a);
466 data = (char *) nla_data(a) + NLA_ALIGN(sizeof(*hdr));
467 len = nla_len(a) - NLA_ALIGN(sizeof(*hdr));
468
469 NL_DBG(3, "ematch attribute matchid=%u, kind=%u, flags=%u\n",
470 hdr->matchid, hdr->kind, hdr->flags);
471
472 /*
473 * Container matches contain a reference to another sequence
474 * of matches. Ensure that the reference is within boundries.
475 */
476 if (hdr->kind == TCF_EM_CONTAINER &&
477 *((uint32_t *) data) >= thdr->nmatches) {
478 err = -NLE_INVAL;
479 goto errout;
480 }
481
482 if (!(ematch = rtnl_ematch_alloc())) {
483 err = -NLE_NOMEM;
484 goto errout;
485 }
486
487 ematch->e_id = hdr->matchid;
488 ematch->e_kind = hdr->kind;
489 ematch->e_flags = hdr->flags;
490
491 if ((ops = rtnl_ematch_lookup_ops(hdr->kind))) {
492 if (ops->eo_minlen && len < ops->eo_minlen) {
493 rtnl_ematch_free(ematch);
494 err = -NLE_INVAL;
495 goto errout;
496 }
497
498 rtnl_ematch_set_ops(ematch, ops);
499
500 if (ops->eo_parse &&
501 (err = ops->eo_parse(ematch, data, len)) < 0) {
502 rtnl_ematch_free(ematch);
503 goto errout;
504 }
505 }
506
507 NL_DBG(3, "index[%d] = %p\n", nmatches, ematch);
508 index[nmatches++] = ematch;
509 }
510
511 if (nmatches != thdr->nmatches) {
512 err = -NLE_INVAL;
513 goto errout;
514 }
515
516 err = link_tree(index, nmatches, 0, &tree->et_list);
517 if (err < 0)
518 goto errout;
519
520 free(index);
521 *result = tree;
522
523 return 0;
524
525errout:
527 free(index);
528 return err;
529}
530
531static void dump_ematch_sequence(struct nl_list_head *head,
532 struct nl_dump_params *p)
533{
534 struct rtnl_ematch *match;
535
536 nl_list_for_each_entry(match, head, e_list) {
537 if (match->e_flags & TCF_EM_INVERT)
538 nl_dump(p, "!");
539
540 if (match->e_kind == TCF_EM_CONTAINER) {
541 nl_dump(p, "(");
542 dump_ematch_sequence(&match->e_childs, p);
543 nl_dump(p, ")");
544 } else if (!match->e_ops) {
545 nl_dump(p, "[unknown ematch %d]", match->e_kind);
546 } else {
547 if (match->e_ops->eo_dump)
548 match->e_ops->eo_dump(match, p);
549 else
550 nl_dump(p, "[data]");
551 }
552
553 switch (match->e_flags & TCF_EM_REL_MASK) {
554 case TCF_EM_REL_AND:
555 nl_dump(p, " AND ");
556 break;
557 case TCF_EM_REL_OR:
558 nl_dump(p, " OR ");
559 break;
560 default:
561 /* end of first level ematch sequence */
562 return;
563 }
564 }
565}
566
567void rtnl_ematch_tree_dump(struct rtnl_ematch_tree *tree,
568 struct nl_dump_params *p)
569{
570 if (!tree)
571 BUG();
572
573 dump_ematch_sequence(&tree->et_list, p);
574 nl_dump(p, "\n");
575}
576
577static int update_container_index(struct nl_list_head *list, int *index)
578{
579 struct rtnl_ematch *e;
580
581 nl_list_for_each_entry(e, list, e_list)
582 e->e_index = (*index)++;
583
584 nl_list_for_each_entry(e, list, e_list) {
585 if (e->e_kind == TCF_EM_CONTAINER) {
586 int err;
587
588 if (nl_list_empty(&e->e_childs))
589 return -NLE_OBJ_NOTFOUND;
590
591 *((uint32_t *) e->e_data) = *index;
592
593 err = update_container_index(&e->e_childs, index);
594 if (err < 0)
595 return err;
596 }
597 }
598
599 return 0;
600}
601
602static int fill_ematch_sequence(struct nl_msg *msg, struct nl_list_head *list)
603{
604 struct rtnl_ematch *e;
605
606 nl_list_for_each_entry(e, list, e_list) {
607 struct tcf_ematch_hdr match = {
608 .matchid = e->e_id,
609 .kind = e->e_kind,
610 .flags = e->e_flags,
611 };
612 struct nlattr *attr;
613 int err = 0;
614
615 if (!(attr = nla_nest_start(msg, e->e_index + 1)))
616 return -NLE_NOMEM;
617
618 if (nlmsg_append(msg, &match, sizeof(match), 0) < 0)
619 return -NLE_NOMEM;
620
621 if (e->e_ops->eo_fill)
622 err = e->e_ops->eo_fill(e, msg);
623 else if (e->e_flags & TCF_EM_SIMPLE)
624 err = nlmsg_append(msg, e->e_data, 4, 0);
625 else if (e->e_datalen > 0)
626 err = nlmsg_append(msg, e->e_data, e->e_datalen, 0);
627
628 NL_DBG(3, "msg %p: added ematch [%d] id=%d kind=%d flags=%d\n",
629 msg, e->e_index, match.matchid, match.kind, match.flags);
630
631 if (err < 0)
632 return -NLE_NOMEM;
633
634 nla_nest_end(msg, attr);
635 }
636
637 nl_list_for_each_entry(e, list, e_list) {
638 if (e->e_kind == TCF_EM_CONTAINER &&
639 fill_ematch_sequence(msg, &e->e_childs) < 0)
640 return -NLE_NOMEM;
641 }
642
643 return 0;
644}
645
646int rtnl_ematch_fill_attr(struct nl_msg *msg, int attrid,
647 struct rtnl_ematch_tree *tree)
648{
649 struct tcf_ematch_tree_hdr thdr = {
650 .progid = tree->et_progid,
651 };
652 struct nlattr *list, *topattr;
653 int err, index = 0;
654
655 /* Assign index number to each ematch to allow for references
656 * to be made while constructing the sequence of matches. */
657 err = update_container_index(&tree->et_list, &index);
658 if (err < 0)
659 return err;
660
661 if (!(topattr = nla_nest_start(msg, attrid)))
662 goto nla_put_failure;
663
664 thdr.nmatches = index;
665 NLA_PUT(msg, TCA_EMATCH_TREE_HDR, sizeof(thdr), &thdr);
666
667 if (!(list = nla_nest_start(msg, TCA_EMATCH_TREE_LIST)))
668 goto nla_put_failure;
669
670 if (fill_ematch_sequence(msg, &tree->et_list) < 0)
671 goto nla_put_failure;
672
673 nla_nest_end(msg, list);
674
675 nla_nest_end(msg, topattr);
676
677 return 0;
678
679nla_put_failure:
680 return -NLE_NOMEM;
681}
682
683/** @} */
684
685extern int ematch_parse(void *, char **, struct nl_list_head *);
686
687int rtnl_ematch_parse_expr(const char *expr, char **errp,
688 struct rtnl_ematch_tree **result)
689{
690 struct rtnl_ematch_tree *tree;
691 YY_BUFFER_STATE buf = NULL;
692 yyscan_t scanner = NULL;
693 int err;
694
695 NL_DBG(2, "Parsing ematch expression \"%s\"\n", expr);
696
697 if (!(tree = rtnl_ematch_tree_alloc(RTNL_EMATCH_PROGID)))
698 return -NLE_FAILURE;
699
700 if (ematch_lex_init(&scanner) < 0) {
701 err = -NLE_FAILURE;
702 goto errout;
703 }
704
705 buf = ematch__scan_string(expr, scanner);
706
707 if (ematch_parse(scanner, errp, &tree->et_list) != 0) {
708 ematch__delete_buffer(buf, scanner);
709 err = -NLE_PARSE_ERR;
710 goto errout;
711 }
712
713 ematch_lex_destroy(scanner);
714 *result = tree;
715
716 return 0;
717
718errout:
719 if (scanner)
720 ematch_lex_destroy(scanner);
721
723
724 return err;
725}
726
727static const char *layer_txt[] = {
728 [TCF_LAYER_LINK] = "eth",
729 [TCF_LAYER_NETWORK] = "ip",
730 [TCF_LAYER_TRANSPORT] = "tcp",
731};
732
733char *rtnl_ematch_offset2txt(uint8_t layer, uint16_t offset, char *buf, size_t len)
734{
735 snprintf(buf, len, "%s+%u",
736 (layer <= TCF_LAYER_MAX) ? layer_txt[layer] : "?",
737 offset);
738
739 return buf;
740}
741
742static const char *operand_txt[] = {
743 [TCF_EM_OPND_EQ] = "=",
744 [TCF_EM_OPND_LT] = "<",
745 [TCF_EM_OPND_GT] = ">",
746};
747
748char *rtnl_ematch_opnd2txt(uint8_t opnd, char *buf, size_t len)
749{
750 snprintf(buf, len, "%s",
751 opnd < ARRAY_SIZE(operand_txt) ? operand_txt[opnd] : "?");
752
753 return buf;
754}
755
756/** @} */
void * nla_data(const struct nlattr *nla)
Return pointer to the payload section.
Definition attr.c:119
#define NLA_PUT(msg, attrtype, attrlen, data)
Add unspecific attribute to netlink message.
Definition attr.h:166
struct nlattr * nla_nest_start(struct nl_msg *msg, int attrtype)
Start a new level of nested attributes.
Definition attr.c:974
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
#define nla_for_each_nested(pos, nla, rem)
Iterate over a stream of nested attributes.
Definition attr.h:331
int nla_len(const struct nlattr *nla)
Return length of the payload .
Definition attr.c:130
int nla_nest_end(struct nl_msg *msg, struct nlattr *start)
Finalize nesting of attributes.
Definition attr.c:1037
int nla_total_size(int payload)
Return size of attribute including padding.
Definition attr.c:72
@ NLA_NESTED
Nested attributes.
Definition attr.h:42
struct rtnl_ematch_ops * rtnl_ematch_lookup_ops(int kind)
Lookup ematch module by identification number.
Definition ematch.c:64
void rtnl_ematch_tree_add(struct rtnl_ematch_tree *tree, struct rtnl_ematch *ematch)
Add ematch object to the end of the ematch tree.
Definition ematch.c:352
void rtnl_ematch_tree_free(struct rtnl_ematch_tree *tree)
Free ematch tree object.
Definition ematch.c:278
struct rtnl_ematch_tree * rtnl_ematch_tree_alloc(uint16_t progid)
Allocate ematch tree object.
Definition ematch.c:246
struct rtnl_ematch * rtnl_ematch_alloc(void)
Allocate ematch object.
Definition ematch.c:107
int rtnl_ematch_register(struct rtnl_ematch_ops *ops)
Register ematch module.
Definition ematch.c:44
int rtnl_ematch_parse_attr(struct nlattr *attr, struct rtnl_ematch_tree **result)
Parse ematch netlink attributes.
Definition ematch.c:396
void rtnl_ematch_unlink(struct rtnl_ematch *ematch)
Remove ematch from the list of ematches it is linked to.
Definition ematch.c:147
int rtnl_ematch_add_child(struct rtnl_ematch *parent, struct rtnl_ematch *child)
Add ematch to the end of the parent's list of children.
Definition ematch.c:129
struct rtnl_ematch_ops * rtnl_ematch_lookup_ops_by_name(const char *name)
Lookup ematch module by name.
Definition ematch.c:83
struct rtnl_ematch_tree * rtnl_ematch_tree_clone(struct rtnl_ematch_tree *src)
Clone ematch tree object.
Definition ematch.c:332
int nlmsg_append(struct nl_msg *n, void *data, size_t len, int pad)
Append data to tail of a netlink message.
Definition msg.c:456
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition utils.c:1015
Dumping parameters.
Definition types.h:32
Attribute validation policy.
Definition attr.h:66
uint16_t minlen
Minimal length of payload required.
Definition attr.h:71
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition attr.h:68
Extended Match Operations.
Definition ematch.h:28