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