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