libnl  3.3.0
rule.c
1 /*
2  * lib/route/rule.c Routing Rules
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation version 2.1
7  * of the License.
8  *
9  * Copyright (c) 2003-2010 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 /**
13  * @ingroup rtnl
14  * @defgroup rule Routing Rules
15  * @brief
16  * @{
17  */
18 
19 #include <netlink-private/netlink.h>
20 #include <netlink/netlink.h>
21 #include <netlink/utils.h>
22 #include <netlink/route/rtnl.h>
23 #include <netlink/route/rule.h>
24 #include <inttypes.h>
25 #include <linux/fib_rules.h>
26 
27 /** @cond SKIP */
28 #define RULE_ATTR_FAMILY 0x0001
29 #define RULE_ATTR_TABLE 0x0002
30 #define RULE_ATTR_ACTION 0x0004
31 #define RULE_ATTR_FLAGS 0x0008
32 #define RULE_ATTR_IIFNAME 0x0010
33 #define RULE_ATTR_OIFNAME 0x0020
34 #define RULE_ATTR_PRIO 0x0040
35 #define RULE_ATTR_MARK 0x0080
36 #define RULE_ATTR_MASK 0x0100
37 #define RULE_ATTR_GOTO 0x0200
38 #define RULE_ATTR_SRC 0x0400
39 #define RULE_ATTR_DST 0x0800
40 #define RULE_ATTR_DSFIELD 0x1000
41 #define RULE_ATTR_FLOW 0x2000
42 
43 static struct nl_cache_ops rtnl_rule_ops;
44 static struct nl_object_ops rule_obj_ops;
45 /** @endcond */
46 
47 static void rule_free_data(struct nl_object *c)
48 {
49  struct rtnl_rule *rule = nl_object_priv(c);
50 
51  if (!rule)
52  return;
53 
54  nl_addr_put(rule->r_src);
55  nl_addr_put(rule->r_dst);
56 }
57 
58 static int rule_clone(struct nl_object *_dst, struct nl_object *_src)
59 {
60  struct rtnl_rule *dst = nl_object_priv(_dst);
61  struct rtnl_rule *src = nl_object_priv(_src);
62 
63  if (src->r_src)
64  if (!(dst->r_src = nl_addr_clone(src->r_src)))
65  return -NLE_NOMEM;
66 
67  if (src->r_dst)
68  if (!(dst->r_dst = nl_addr_clone(src->r_dst)))
69  return -NLE_NOMEM;
70 
71  return 0;
72 }
73 
74 static struct nla_policy rule_policy[FRA_MAX+1] = {
75  [FRA_TABLE] = { .type = NLA_U32 },
76  [FRA_IIFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ },
77  [FRA_OIFNAME] = { .type = NLA_STRING, .maxlen = IFNAMSIZ },
78  [FRA_PRIORITY] = { .type = NLA_U32 },
79  [FRA_FWMARK] = { .type = NLA_U32 },
80  [FRA_FWMASK] = { .type = NLA_U32 },
81  [FRA_GOTO] = { .type = NLA_U32 },
82  [FRA_FLOW] = { .type = NLA_U32 },
83 };
84 
85 static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
86  struct nlmsghdr *n, struct nl_parser_param *pp)
87 {
88  struct rtnl_rule *rule;
89  struct fib_rule_hdr *frh;
90  struct nlattr *tb[FRA_MAX+1];
91  int err = 1, family;
92 
93  rule = rtnl_rule_alloc();
94  if (!rule) {
95  err = -NLE_NOMEM;
96  goto errout;
97  }
98 
99  rule->ce_msgtype = n->nlmsg_type;
100  frh = nlmsg_data(n);
101 
102  err = nlmsg_parse(n, sizeof(*frh), tb, FRA_MAX, rule_policy);
103  if (err < 0)
104  goto errout;
105 
106  rule->r_family = family = frh->family;
107  rule->r_table = frh->table;
108  rule->r_action = frh->action;
109  rule->r_flags = frh->flags;
110 
111  rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TABLE | RULE_ATTR_ACTION |
112  RULE_ATTR_FLAGS);
113 
114  /* ipv4 only */
115  if (frh->tos) {
116  rule->r_dsfield = frh->tos;
117  rule->ce_mask |= RULE_ATTR_DSFIELD;
118  }
119 
120  if (tb[FRA_TABLE]) {
121  rule->r_table = nla_get_u32(tb[FRA_TABLE]);
122  rule->ce_mask |= RULE_ATTR_TABLE;
123  }
124 
125  if (tb[FRA_IIFNAME]) {
126  nla_strlcpy(rule->r_iifname, tb[FRA_IIFNAME], IFNAMSIZ);
127  rule->ce_mask |= RULE_ATTR_IIFNAME;
128  }
129 
130  if (tb[FRA_OIFNAME]) {
131  nla_strlcpy(rule->r_oifname, tb[FRA_OIFNAME], IFNAMSIZ);
132  rule->ce_mask |= RULE_ATTR_OIFNAME;
133  }
134 
135  if (tb[FRA_PRIORITY]) {
136  rule->r_prio = nla_get_u32(tb[FRA_PRIORITY]);
137  rule->ce_mask |= RULE_ATTR_PRIO;
138  }
139 
140  if (tb[FRA_FWMARK]) {
141  rule->r_mark = nla_get_u32(tb[FRA_FWMARK]);
142  rule->ce_mask |= RULE_ATTR_MARK;
143  }
144 
145  if (tb[FRA_FWMASK]) {
146  rule->r_mask = nla_get_u32(tb[FRA_FWMASK]);
147  rule->ce_mask |= RULE_ATTR_MASK;
148  }
149 
150  if (tb[FRA_GOTO]) {
151  rule->r_goto = nla_get_u32(tb[FRA_GOTO]);
152  rule->ce_mask |= RULE_ATTR_GOTO;
153  }
154 
155  if (tb[FRA_SRC]) {
156  if (!(rule->r_src = nl_addr_alloc_attr(tb[FRA_SRC], family)))
157  goto errout_enomem;
158 
159  nl_addr_set_prefixlen(rule->r_src, frh->src_len);
160  rule->ce_mask |= RULE_ATTR_SRC;
161  }
162 
163  if (tb[FRA_DST]) {
164  if (!(rule->r_dst = nl_addr_alloc_attr(tb[FRA_DST], family)))
165  goto errout_enomem;
166  nl_addr_set_prefixlen(rule->r_dst, frh->dst_len);
167  rule->ce_mask |= RULE_ATTR_DST;
168  }
169 
170  /* ipv4 only */
171  if (tb[FRA_FLOW]) {
172  rule->r_flow = nla_get_u32(tb[FRA_FLOW]);
173  rule->ce_mask |= RULE_ATTR_FLOW;
174  }
175 
176  err = pp->pp_cb((struct nl_object *) rule, pp);
177 errout:
178  rtnl_rule_put(rule);
179  return err;
180 
181 errout_enomem:
182  err = -NLE_NOMEM;
183  goto errout;
184 }
185 
186 static int rule_request_update(struct nl_cache *c, struct nl_sock *h)
187 {
188  return nl_rtgen_request(h, RTM_GETRULE, AF_UNSPEC, NLM_F_DUMP);
189 }
190 
191 static void rule_dump_line(struct nl_object *o, struct nl_dump_params *p)
192 {
193  struct rtnl_rule *r = (struct rtnl_rule *) o;
194  char buf[128];
195 
196  nl_dump_line(p, "%8d ", (r->ce_mask & RULE_ATTR_PRIO) ? r->r_prio : 0);
197  nl_dump(p, "%s ", nl_af2str(r->r_family, buf, sizeof(buf)));
198 
199  if (r->ce_mask & RULE_ATTR_SRC)
200  nl_dump(p, "from %s ",
201  nl_addr2str(r->r_src, buf, sizeof(buf)));
202 
203  if (r->ce_mask & RULE_ATTR_DST)
204  nl_dump(p, "to %s ",
205  nl_addr2str(r->r_dst, buf, sizeof(buf)));
206 
207  if (r->ce_mask & RULE_ATTR_DSFIELD)
208  nl_dump(p, "tos %u ", r->r_dsfield);
209 
210  if (r->ce_mask & (RULE_ATTR_MARK | RULE_ATTR_MASK))
211  nl_dump(p, "mark %#x/%#x", r->r_mark, r->r_mask);
212 
213  if (r->ce_mask & RULE_ATTR_IIFNAME)
214  nl_dump(p, "iif %s ", r->r_iifname);
215 
216  if (r->ce_mask & RULE_ATTR_OIFNAME)
217  nl_dump(p, "oif %s ", r->r_oifname);
218 
219  if (r->ce_mask & RULE_ATTR_TABLE)
220  nl_dump(p, "lookup %s ",
221  rtnl_route_table2str(r->r_table, buf, sizeof(buf)));
222 
223  if (r->ce_mask & RULE_ATTR_FLOW)
224  nl_dump(p, "flow %s ",
225  rtnl_realms2str(r->r_flow, buf, sizeof(buf)));
226 
227  if (r->ce_mask & RULE_ATTR_GOTO)
228  nl_dump(p, "goto %u ", r->r_goto);
229 
230  if (r->ce_mask & RULE_ATTR_ACTION)
231  nl_dump(p, "action %s",
232  nl_rtntype2str(r->r_action, buf, sizeof(buf)));
233 
234  nl_dump(p, "\n");
235 }
236 
237 static void rule_dump_details(struct nl_object *obj, struct nl_dump_params *p)
238 {
239  rule_dump_line(obj, p);
240 }
241 
242 static void rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
243 {
244  rule_dump_details(obj, p);
245 }
246 
247 #define RULE_ATTR_FLAGS 0x0008
248 
249 static uint64_t rule_compare(struct nl_object *_a, struct nl_object *_b,
250  uint64_t attrs, int flags)
251 {
252  struct rtnl_rule *a = (struct rtnl_rule *) _a;
253  struct rtnl_rule *b = (struct rtnl_rule *) _b;
254  uint64_t diff = 0;
255 
256 #define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR)
257 
258  diff |= RULE_DIFF(FAMILY, a->r_family != b->r_family);
259  diff |= RULE_DIFF(TABLE, a->r_table != b->r_table);
260  diff |= RULE_DIFF(ACTION, a->r_action != b->r_action);
261  diff |= RULE_DIFF(IIFNAME, strcmp(a->r_iifname, b->r_iifname));
262  diff |= RULE_DIFF(OIFNAME, strcmp(a->r_oifname, b->r_oifname));
263  diff |= RULE_DIFF(PRIO, a->r_prio != b->r_prio);
264  diff |= RULE_DIFF(MARK, a->r_mark != b->r_mark);
265  diff |= RULE_DIFF(MASK, a->r_mask != b->r_mask);
266  diff |= RULE_DIFF(GOTO, a->r_goto != b->r_goto);
267  diff |= RULE_DIFF(SRC, nl_addr_cmp(a->r_src, b->r_src));
268  diff |= RULE_DIFF(DST, nl_addr_cmp(a->r_dst, b->r_dst));
269  diff |= RULE_DIFF(DSFIELD, a->r_dsfield != b->r_dsfield);
270  diff |= RULE_DIFF(FLOW, a->r_flow != b->r_flow);
271 
272 #undef RULE_DIFF
273 
274  return diff;
275 }
276 
277 static const struct trans_tbl rule_attrs[] = {
278  __ADD(RULE_ATTR_FAMILY, family),
279  __ADD(RULE_ATTR_TABLE, table),
280  __ADD(RULE_ATTR_ACTION, action),
281  __ADD(RULE_ATTR_IIFNAME, iifname),
282  __ADD(RULE_ATTR_OIFNAME, oifname),
283  __ADD(RULE_ATTR_PRIO, prio),
284  __ADD(RULE_ATTR_MARK, mark),
285  __ADD(RULE_ATTR_MASK, mask),
286  __ADD(RULE_ATTR_GOTO, goto),
287  __ADD(RULE_ATTR_SRC, src),
288  __ADD(RULE_ATTR_DST, dst),
289  __ADD(RULE_ATTR_DSFIELD, dsfield),
290  __ADD(RULE_ATTR_FLOW, flow),
291 };
292 
293 static char *rule_attrs2str(int attrs, char *buf, size_t len)
294 {
295  return __flags2str(attrs, buf, len, rule_attrs,
296  ARRAY_SIZE(rule_attrs));
297 }
298 
299 /**
300  * @name Allocation/Freeing
301  * @{
302  */
303 
304 struct rtnl_rule *rtnl_rule_alloc(void)
305 {
306  return (struct rtnl_rule *) nl_object_alloc(&rule_obj_ops);
307 }
308 
309 void rtnl_rule_put(struct rtnl_rule *rule)
310 {
311  nl_object_put((struct nl_object *) rule);
312 }
313 
314 /** @} */
315 
316 /**
317  * @name Cache Management
318  * @{
319  */
320 
321 /**
322  * Build a rule cache including all rules currently configured in the kernel.
323  * @arg sock Netlink socket.
324  * @arg family Address family or AF_UNSPEC.
325  * @arg result Pointer to store resulting cache.
326  *
327  * Allocates a new rule cache, initializes it properly and updates it
328  * to include all rules currently configured in the kernel.
329  *
330  * @return 0 on success or a negative error code.
331  */
332 int rtnl_rule_alloc_cache(struct nl_sock *sock, int family,
333  struct nl_cache **result)
334 {
335  struct nl_cache * cache;
336  int err;
337 
338  if (!(cache = nl_cache_alloc(&rtnl_rule_ops)))
339  return -NLE_NOMEM;
340 
341  cache->c_iarg1 = family;
342 
343  if (sock && (err = nl_cache_refill(sock, cache)) < 0) {
344  free(cache);
345  return err;
346  }
347 
348  *result = cache;
349  return 0;
350 }
351 
352 /** @} */
353 
354 /**
355  * @name Rule Addition
356  * @{
357  */
358 
359 static int build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags,
360  struct nl_msg **result)
361 {
362  struct nl_msg *msg;
363  struct fib_rule_hdr frh = {
364  .family = tmpl->r_family,
365  .table = tmpl->r_table,
366  .action = tmpl->r_action,
367  .flags = tmpl->r_flags,
368  .tos = tmpl->r_dsfield,
369  };
370 
371  if (!(tmpl->ce_mask & RULE_ATTR_FAMILY))
372  return -NLE_MISSING_ATTR;
373 
374  msg = nlmsg_alloc_simple(cmd, flags);
375  if (!msg)
376  return -NLE_NOMEM;
377 
378  if (tmpl->ce_mask & RULE_ATTR_SRC)
379  frh.src_len = nl_addr_get_prefixlen(tmpl->r_src);
380 
381  if (tmpl->ce_mask & RULE_ATTR_DST)
382  frh.dst_len = nl_addr_get_prefixlen(tmpl->r_dst);
383 
384  if (nlmsg_append(msg, &frh, sizeof(frh), NLMSG_ALIGNTO) < 0)
385  goto nla_put_failure;
386 
387  /* Additional table attribute replacing the 8bit in the header, was
388  * required to allow more than 256 tables. */
389  NLA_PUT_U32(msg, FRA_TABLE, tmpl->r_table);
390 
391  if (tmpl->ce_mask & RULE_ATTR_SRC)
392  NLA_PUT_ADDR(msg, FRA_SRC, tmpl->r_src);
393 
394  if (tmpl->ce_mask & RULE_ATTR_DST)
395  NLA_PUT_ADDR(msg, FRA_DST, tmpl->r_dst);
396 
397  if (tmpl->ce_mask & RULE_ATTR_IIFNAME)
398  NLA_PUT_STRING(msg, FRA_IIFNAME, tmpl->r_iifname);
399 
400  if (tmpl->ce_mask & RULE_ATTR_OIFNAME)
401  NLA_PUT_STRING(msg, FRA_OIFNAME, tmpl->r_oifname);
402 
403  if (tmpl->ce_mask & RULE_ATTR_PRIO)
404  NLA_PUT_U32(msg, FRA_PRIORITY, tmpl->r_prio);
405 
406  if (tmpl->ce_mask & RULE_ATTR_MARK)
407  NLA_PUT_U32(msg, FRA_FWMARK, tmpl->r_mark);
408 
409  if (tmpl->ce_mask & RULE_ATTR_MASK)
410  NLA_PUT_U32(msg, FRA_FWMASK, tmpl->r_mask);
411 
412  if (tmpl->ce_mask & RULE_ATTR_GOTO)
413  NLA_PUT_U32(msg, FRA_GOTO, tmpl->r_goto);
414 
415  if (tmpl->ce_mask & RULE_ATTR_FLOW)
416  NLA_PUT_U32(msg, FRA_FLOW, tmpl->r_flow);
417 
418 
419  *result = msg;
420  return 0;
421 
422 nla_put_failure:
423  nlmsg_free(msg);
424  return -NLE_MSGSIZE;
425 }
426 
427 /**
428  * Build netlink request message to add a new rule
429  * @arg tmpl template with data of new rule
430  * @arg flags additional netlink message flags
431  * @arg result Result pointer
432  *
433  * Builds a new netlink message requesting a addition of a new
434  * rule. The netlink message header isn't fully equipped with
435  * all relevant fields and must thus be sent out via nl_send_auto_complete()
436  * or supplemented as needed. \a tmpl must contain the attributes of the new
437  * address set via \c rtnl_rule_set_* functions.
438  *
439  * @return 0 on success or a negative error code.
440  */
441 int rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags,
442  struct nl_msg **result)
443 {
444  return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags,
445  result);
446 }
447 
448 /**
449  * Add a new rule
450  * @arg sk Netlink socket.
451  * @arg tmpl template with requested changes
452  * @arg flags additional netlink message flags
453  *
454  * Builds a netlink message by calling rtnl_rule_build_add_request(),
455  * sends the request to the kernel and waits for the next ACK to be
456  * received and thus blocks until the request has been fullfilled.
457  *
458  * @return 0 on sucess or a negative error if an error occured.
459  */
460 int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags)
461 {
462  struct nl_msg *msg;
463  int err;
464 
465  if ((err = rtnl_rule_build_add_request(tmpl, flags, &msg)) < 0)
466  return err;
467 
468  err = nl_send_auto_complete(sk, msg);
469  nlmsg_free(msg);
470  if (err < 0)
471  return err;
472 
473  return wait_for_ack(sk);
474 }
475 
476 /** @} */
477 
478 /**
479  * @name Rule Deletion
480  * @{
481  */
482 
483 /**
484  * Build a netlink request message to delete a rule
485  * @arg rule rule to delete
486  * @arg flags additional netlink message flags
487  * @arg result Result pointer
488  *
489  * Builds a new netlink message requesting a deletion of a rule.
490  * The netlink message header isn't fully equipped with all relevant
491  * fields and must thus be sent out via nl_send_auto_complete()
492  * or supplemented as needed. \a rule must point to an existing
493  * address.
494  *
495  * @return 0 on success or a negative error code.
496  */
497 int rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags,
498  struct nl_msg **result)
499 {
500  return build_rule_msg(rule, RTM_DELRULE, flags, result);
501 }
502 
503 /**
504  * Delete a rule
505  * @arg sk Netlink socket.
506  * @arg rule rule to delete
507  * @arg flags additional netlink message flags
508  *
509  * Builds a netlink message by calling rtnl_rule_build_delete_request(),
510  * sends the request to the kernel and waits for the next ACK to be
511  * received and thus blocks until the request has been fullfilled.
512  *
513  * @return 0 on sucess or a negative error if an error occured.
514  */
515 int rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags)
516 {
517  struct nl_msg *msg;
518  int err;
519 
520  if ((err = rtnl_rule_build_delete_request(rule, flags, &msg)) < 0)
521  return err;
522 
523  err = nl_send_auto_complete(sk, msg);
524  nlmsg_free(msg);
525  if (err < 0)
526  return err;
527 
528  return wait_for_ack(sk);
529 }
530 
531 /** @} */
532 
533 /**
534  * @name Attribute Modification
535  * @{
536  */
537 
538 void rtnl_rule_set_family(struct rtnl_rule *rule, int family)
539 {
540  rule->r_family = family;
541  rule->ce_mask |= RULE_ATTR_FAMILY;
542 }
543 
544 int rtnl_rule_get_family(struct rtnl_rule *rule)
545 {
546  if (rule->ce_mask & RULE_ATTR_FAMILY)
547  return rule->r_family;
548  else
549  return AF_UNSPEC;
550 }
551 
552 void rtnl_rule_set_prio(struct rtnl_rule *rule, uint32_t prio)
553 {
554  rule->r_prio = prio;
555  rule->ce_mask |= RULE_ATTR_PRIO;
556 }
557 
558 uint32_t rtnl_rule_get_prio(struct rtnl_rule *rule)
559 {
560  return rule->r_prio;
561 }
562 
563 void rtnl_rule_set_mark(struct rtnl_rule *rule, uint32_t mark)
564 {
565  rule->r_mark = mark;
566  rule->ce_mask |= RULE_ATTR_MARK;
567 }
568 
569 uint32_t rtnl_rule_get_mark(struct rtnl_rule *rule)
570 {
571  return rule->r_mark;
572 }
573 
574 void rtnl_rule_set_mask(struct rtnl_rule *rule, uint32_t mask)
575 {
576  rule->r_mask = mask;
577  rule->ce_mask |= RULE_ATTR_MASK;
578 }
579 
580 uint32_t rtnl_rule_get_mask(struct rtnl_rule *rule)
581 {
582  return rule->r_mask;
583 }
584 
585 void rtnl_rule_set_table(struct rtnl_rule *rule, uint32_t table)
586 {
587  rule->r_table = table;
588  rule->ce_mask |= RULE_ATTR_TABLE;
589 }
590 
591 uint32_t rtnl_rule_get_table(struct rtnl_rule *rule)
592 {
593  return rule->r_table;
594 }
595 
596 void rtnl_rule_set_dsfield(struct rtnl_rule *rule, uint8_t dsfield)
597 {
598  rule->r_dsfield = dsfield;
599  rule->ce_mask |= RULE_ATTR_DSFIELD;
600 }
601 
602 uint8_t rtnl_rule_get_dsfield(struct rtnl_rule *rule)
603 {
604  return rule->r_dsfield;
605 }
606 
607 static inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos,
608  struct nl_addr *new, int flag)
609 {
610  if (rule->ce_mask & RULE_ATTR_FAMILY) {
611  if (new->a_family != rule->r_family)
612  return -NLE_AF_MISMATCH;
613  } else
614  rule->r_family = new->a_family;
615 
616  if (*pos)
617  nl_addr_put(*pos);
618 
619  nl_addr_get(new);
620  *pos = new;
621 
622  rule->ce_mask |= (flag | RULE_ATTR_FAMILY);
623 
624  return 0;
625 }
626 
627 int rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src)
628 {
629  return __assign_addr(rule, &rule->r_src, src, RULE_ATTR_SRC);
630 }
631 
632 struct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule)
633 {
634  return rule->r_src;
635 }
636 
637 int rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst)
638 {
639  return __assign_addr(rule, &rule->r_dst, dst, RULE_ATTR_DST);
640 }
641 
642 struct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule)
643 {
644  return rule->r_dst;
645 }
646 
647 int rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev)
648 {
649  if (strlen(dev) > IFNAMSIZ-1)
650  return -NLE_RANGE;
651 
652  strcpy(rule->r_iifname, dev);
653  rule->ce_mask |= RULE_ATTR_IIFNAME;
654  return 0;
655 }
656 
657 char *rtnl_rule_get_iif(struct rtnl_rule *rule)
658 {
659  if (rule->ce_mask & RULE_ATTR_IIFNAME)
660  return rule->r_iifname;
661  else
662  return NULL;
663 }
664 
665 int rtnl_rule_set_oif(struct rtnl_rule *rule, const char *dev)
666 {
667  if (strlen(dev) > IFNAMSIZ-1)
668  return -NLE_RANGE;
669 
670  strcpy(rule->r_oifname, dev);
671  rule->ce_mask |= RULE_ATTR_OIFNAME;
672  return 0;
673 }
674 
675 char *rtnl_rule_get_oif(struct rtnl_rule *rule)
676 {
677  if (rule->ce_mask & RULE_ATTR_OIFNAME)
678  return rule->r_oifname;
679  else
680  return NULL;
681 }
682 
683 void rtnl_rule_set_action(struct rtnl_rule *rule, uint8_t action)
684 {
685  rule->r_action = action;
686  rule->ce_mask |= RULE_ATTR_ACTION;
687 }
688 
689 uint8_t rtnl_rule_get_action(struct rtnl_rule *rule)
690 {
691  return rule->r_action;
692 }
693 
694 void rtnl_rule_set_realms(struct rtnl_rule *rule, uint32_t realms)
695 {
696  rule->r_flow = realms;
697  rule->ce_mask |= RULE_ATTR_FLOW;
698 }
699 
700 uint32_t rtnl_rule_get_realms(struct rtnl_rule *rule)
701 {
702  return rule->r_flow;
703 }
704 
705 void rtnl_rule_set_goto(struct rtnl_rule *rule, uint32_t ref)
706 {
707  rule->r_goto = ref;
708  rule->ce_mask |= RULE_ATTR_GOTO;
709 }
710 
711 uint32_t rtnl_rule_get_goto(struct rtnl_rule *rule)
712 {
713  return rule->r_goto;
714 }
715 
716 /** @} */
717 
718 static struct nl_object_ops rule_obj_ops = {
719  .oo_name = "route/rule",
720  .oo_size = sizeof(struct rtnl_rule),
721  .oo_free_data = rule_free_data,
722  .oo_clone = rule_clone,
723  .oo_dump = {
724  [NL_DUMP_LINE] = rule_dump_line,
725  [NL_DUMP_DETAILS] = rule_dump_details,
726  [NL_DUMP_STATS] = rule_dump_stats,
727  },
728  .oo_compare = rule_compare,
729  .oo_attrs2str = rule_attrs2str,
730  .oo_id_attrs = ~0,
731 };
732 
733 static struct nl_cache_ops rtnl_rule_ops = {
734  .co_name = "route/rule",
735  .co_hdrsize = sizeof(struct fib_rule_hdr),
736  .co_msgtypes = {
737  { RTM_NEWRULE, NL_ACT_NEW, "new" },
738  { RTM_DELRULE, NL_ACT_DEL, "del" },
739  { RTM_GETRULE, NL_ACT_GET, "get" },
740  END_OF_MSGTYPES_LIST,
741  },
742  .co_protocol = NETLINK_ROUTE,
743  .co_request_update = rule_request_update,
744  .co_msg_parser = rule_msg_parser,
745  .co_obj_ops = &rule_obj_ops,
746 };
747 
748 static void __init rule_init(void)
749 {
750  nl_cache_mngt_register(&rtnl_rule_ops);
751 }
752 
753 static void __exit rule_exit(void)
754 {
755  nl_cache_mngt_unregister(&rtnl_rule_ops);
756 }
757 
758 /** @} */
int rtnl_rule_alloc_cache(struct nl_sock *sock, int family, struct nl_cache **result)
Build a rule cache including all rules currently configured in the kernel.
Definition: rule.c:332
int nl_send_auto_complete(struct nl_sock *sk, struct nl_msg *msg)
Definition: nl.c:1247
struct nl_addr * nl_addr_clone(const struct nl_addr *addr)
Clone existing abstract address object.
Definition: addr.c:471
Dump object briefly on one line.
Definition: types.h:22
int rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags, struct nl_msg **result)
Build a netlink request message to delete a rule.
Definition: rule.c:497
void nl_addr_set_prefixlen(struct nl_addr *addr, int prefixlen)
Set the prefix length of an abstract address.
Definition: addr.c:929
void nlmsg_free(struct nl_msg *msg)
Release a reference from an netlink message.
Definition: msg.c:562
int nl_addr_cmp(const struct nl_addr *a, const struct nl_addr *b)
Compare abstract addresses.
Definition: addr.c:563
void * nlmsg_data(const struct nlmsghdr *nlh)
Return pointer to message payload.
Definition: msg.c:106
#define NLA_PUT_ADDR(msg, attrtype, addr)
Add address attribute to netlink message.
Definition: attr.h:288
unsigned int nl_addr_get_prefixlen(const struct nl_addr *addr)
Return prefix length of abstract address object.
Definition: addr.c:940
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
Definition: object.c:54
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:287
Attribute validation policy.
Definition: attr.h:69
uint32_t nla_get_u32(const struct nlattr *nla)
Return payload of 32 bit integer attribute.
Definition: attr.c:706
int nlmsg_parse(struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, struct nla_policy *policy)
parse attributes of a netlink message
Definition: msg.c:214
struct nl_addr * nl_addr_get(struct nl_addr *addr)
Increase the reference counter of an abstract address.
Definition: addr.c:501
struct nl_addr * nl_addr_alloc_attr(const struct nlattr *nla, int family)
Allocate abstract address based on Netlink attribute.
Definition: addr.c:255
NUL terminated character string.
Definition: attr.h:45
Dump all attributes but no statistics.
Definition: types.h:23
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:252
int rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags, struct nl_msg **result)
Build netlink request message to add a new rule.
Definition: rule.c:441
int nl_rtgen_request(struct nl_sock *sk, int type, int family, int flags)
Send routing netlink request message.
Definition: rtnl.c:41
#define NLA_PUT_U32(msg, attrtype, value)
Add 32 bit integer attribute to netlink message.
Definition: attr.h:235
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:446
int nl_cache_refill(struct nl_sock *sk, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
Definition: cache.c:1040
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition: object.c:215
#define NLA_PUT_STRING(msg, attrtype, value)
Add string attribute to netlink message.
Definition: attr.h:262
int rtnl_rule_delete(struct nl_sock *sk, struct rtnl_rule *rule, int flags)
Delete a rule.
Definition: rule.c:515
void nl_addr_put(struct nl_addr *addr)
Decrease the reference counter of an abstract address.
Definition: addr.c:517
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:71
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
Definition: msg.c:347
32 bit integer
Definition: attr.h:43
Dumping parameters.
Definition: types.h:33
void nl_dump(struct nl_dump_params *params, const char *fmt,...)
Dump a formatted character string.
Definition: utils.c:961
int rtnl_rule_add(struct nl_sock *sk, struct rtnl_rule *tmpl, int flags)
Add a new rule.
Definition: rule.c:460
Dump all attributes including statistics.
Definition: types.h:24
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload to a buffer.
Definition: attr.c:378
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate new cache.
Definition: cache.c:183
char * nl_addr2str(const struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition: addr.c:963