libnl  1.1
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-2006 Thomas Graf <tgraf@suug.ch>
10  */
11 
12 /**
13  * @ingroup rtnl
14  * @defgroup rule Routing Rules
15  * @brief
16  * @{
17  */
18 
19 #include <netlink-local.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 
26 /** @cond SKIP */
27 #define RULE_ATTR_FAMILY 0x0001
28 #define RULE_ATTR_PRIO 0x0002
29 #define RULE_ATTR_MARK 0x0004
30 #define RULE_ATTR_IIF 0x0008
31 #define RULE_ATTR_REALMS 0x0010
32 #define RULE_ATTR_SRC 0x0020
33 #define RULE_ATTR_DST 0x0040
34 #define RULE_ATTR_DSFIELD 0x0080
35 #define RULE_ATTR_TABLE 0x0100
36 #define RULE_ATTR_TYPE 0x0200
37 #define RULE_ATTR_SRC_LEN 0x0400
38 #define RULE_ATTR_DST_LEN 0x0800
39 #define RULE_ATTR_SRCMAP 0x1000
40 
41 static struct nl_cache_ops rtnl_rule_ops;
42 static struct nl_object_ops rule_obj_ops;
43 /** @endcond */
44 
45 static void rule_free_data(struct nl_object *c)
46 {
47  struct rtnl_rule *rule = nl_object_priv(c);
48 
49  if (!rule)
50  return;
51 
52  nl_addr_put(rule->r_src);
53  nl_addr_put(rule->r_dst);
54 }
55 
56 static int rule_clone(struct nl_object *_dst, struct nl_object *_src)
57 {
58  struct rtnl_rule *dst = nl_object_priv(_dst);
59  struct rtnl_rule *src = nl_object_priv(_src);
60 
61  if (src->r_src)
62  if (!(dst->r_src = nl_addr_clone(src->r_src)))
63  goto errout;
64 
65  if (src->r_dst)
66  if (!(dst->r_dst = nl_addr_clone(src->r_dst)))
67  goto errout;
68 
69  return 0;
70 errout:
71  return nl_get_errno();
72 }
73 
74 static struct nla_policy rule_policy[RTA_MAX+1] = {
75  [RTA_PRIORITY] = { .type = NLA_U32 },
76  [RTA_FLOW] = { .type = NLA_U32 },
77  [RTA_PROTOINFO] = { .type = NLA_U32 },
78  [RTA_IIF] = { .type = NLA_STRING,
79  .maxlen = IFNAMSIZ, },
80 };
81 
82 static int rule_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
83  struct nlmsghdr *n, struct nl_parser_param *pp)
84 {
85  struct rtnl_rule *rule;
86  struct rtmsg *r;
87  struct nlattr *tb[RTA_MAX+1];
88  int err = 1;
89 
90  rule = rtnl_rule_alloc();
91  if (!rule) {
92  err = nl_errno(ENOMEM);
93  goto errout;
94  }
95 
96  rule->ce_msgtype = n->nlmsg_type;
97  r = nlmsg_data(n);
98 
99  err = nlmsg_parse(n, sizeof(*r), tb, RTA_MAX, rule_policy);
100  if (err < 0)
101  goto errout;
102 
103  rule->r_family = r->rtm_family;
104  rule->r_type = r->rtm_type;
105  rule->r_dsfield = r->rtm_tos;
106  rule->r_src_len = r->rtm_src_len;
107  rule->r_dst_len = r->rtm_dst_len;
108  rule->r_table = r->rtm_table;
109  rule->ce_mask = (RULE_ATTR_FAMILY | RULE_ATTR_TYPE | RULE_ATTR_DSFIELD |
110  RULE_ATTR_SRC_LEN | RULE_ATTR_DST_LEN |RULE_ATTR_TYPE);
111 
112  if (tb[RTA_PRIORITY]) {
113  rule->r_prio = nla_get_u32(tb[RTA_PRIORITY]);
114  rule->ce_mask |= RULE_ATTR_PRIO;
115  }
116 
117  if (tb[RTA_SRC]) {
118  rule->r_src = nla_get_addr(tb[RTA_SRC], r->rtm_family);
119  if (!rule->r_src) {
120  err = nl_errno(ENOMEM);
121  goto errout;
122  }
123  nl_addr_set_prefixlen(rule->r_src, r->rtm_src_len);
124  rule->ce_mask |= RULE_ATTR_SRC;
125  }
126 
127  if (tb[RTA_DST]) {
128  rule->r_dst = nla_get_addr(tb[RTA_DST], r->rtm_family);
129  if (!rule->r_dst) {
130  err = nl_errno(ENOMEM);
131  goto errout;
132  }
133  nl_addr_set_prefixlen(rule->r_dst, r->rtm_dst_len);
134  rule->ce_mask |= RULE_ATTR_DST;
135  }
136 
137  if (tb[RTA_PROTOINFO]) {
138  rule->r_mark = nla_get_u32(tb[RTA_PROTOINFO]);
139  rule->ce_mask |= RULE_ATTR_MARK;
140  }
141 
142  if (tb[RTA_IIF]) {
143  nla_strlcpy(rule->r_iif, tb[RTA_IIF], IFNAMSIZ);
144  rule->ce_mask |= RULE_ATTR_IIF;
145  }
146 
147  if (tb[RTA_FLOW]) {
148  rule->r_realms = nla_get_u32(tb[RTA_FLOW]);
149  rule->ce_mask |= RULE_ATTR_REALMS;
150  }
151 
152  if (tb[RTA_GATEWAY]) {
153  rule->r_srcmap = nla_get_addr(tb[RTA_GATEWAY], r->rtm_family);
154  if (!rule->r_srcmap) {
155  err = nl_errno(ENOMEM);
156  goto errout;
157  }
158  rule->ce_mask |= RULE_ATTR_SRCMAP;
159  }
160 
161  err = pp->pp_cb((struct nl_object *) rule, pp);
162  if (err < 0)
163  goto errout;
164 
165  err = P_ACCEPT;
166 
167 errout:
168  rtnl_rule_put(rule);
169  return err;
170 }
171 
172 static int rule_request_update(struct nl_cache *c, struct nl_handle *h)
173 {
174  return nl_rtgen_request(h, RTM_GETRULE, AF_UNSPEC, NLM_F_DUMP);
175 }
176 
177 static int rule_dump_brief(struct nl_object *o, struct nl_dump_params *p)
178 {
179  struct rtnl_rule *r = (struct rtnl_rule *) o;
180  char buf[128];
181 
182  if (r->ce_mask & RULE_ATTR_PRIO)
183  dp_dump(p, "%d:\t", r->r_prio);
184  else
185  dp_dump(p, "0:\t");
186 
187  if (r->ce_mask & RULE_ATTR_SRC)
188  dp_dump(p, "from %s ",
189  nl_addr2str(r->r_src, buf, sizeof(buf)));
190  else if (r->ce_mask & RULE_ATTR_SRC_LEN && r->r_src_len)
191  dp_dump(p, "from 0/%d ", r->r_src_len);
192 
193  if (r->ce_mask & RULE_ATTR_DST)
194  dp_dump(p, "to %s ",
195  nl_addr2str(r->r_dst, buf, sizeof(buf)));
196  else if (r->ce_mask & RULE_ATTR_DST_LEN && r->r_dst_len)
197  dp_dump(p, "to 0/%d ", r->r_dst_len);
198 
199  if (r->ce_mask & RULE_ATTR_DSFIELD && r->r_dsfield)
200  dp_dump(p, "tos %d ", r->r_dsfield);
201 
202  if (r->ce_mask & RULE_ATTR_MARK)
203  dp_dump(p, "mark %" PRIx64 , r->r_mark);
204 
205  if (r->ce_mask & RULE_ATTR_IIF)
206  dp_dump(p, "iif %s ", r->r_iif);
207 
208  if (r->ce_mask & RULE_ATTR_TABLE)
209  dp_dump(p, "lookup %s ",
210  rtnl_route_table2str(r->r_table, buf, sizeof(buf)));
211 
212  if (r->ce_mask & RULE_ATTR_REALMS)
213  dp_dump(p, "realms %s ",
214  rtnl_realms2str(r->r_realms, buf, sizeof(buf)));
215 
216  dp_dump(p, "action %s\n",
217  nl_rtntype2str(r->r_type, buf, sizeof(buf)));
218 
219  return 1;
220 }
221 
222 static int rule_dump_full(struct nl_object *obj, struct nl_dump_params *p)
223 {
224  struct rtnl_rule *rule = (struct rtnl_rule *) obj;
225  char buf[128];
226  int line;
227 
228  line = rule_dump_brief(obj, p);
229 
230  dp_dump_line(p, line++, " family %s",
231  nl_af2str(rule->r_family, buf, sizeof(buf)));
232 
233  if (rule->ce_mask & RULE_ATTR_SRCMAP)
234  dp_dump(p, " srcmap %s",
235  nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
236 
237  dp_dump(p, "\n");
238 
239  return line;
240 }
241 
242 static int rule_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
243 {
244  return rule_dump_full(obj, p);
245 }
246 
247 static int rule_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
248 {
249  struct rtnl_rule *rule = (struct rtnl_rule *) obj;
250  char buf[128];
251  int line = 0;
252 
253  dp_dump_line(p, line++, "<rule>\n");
254 
255  dp_dump_line(p, line++, " <priority>%u</priority>\n",
256  rule->r_prio);
257  dp_dump_line(p, line++, " <family>%s</family>\n",
258  nl_af2str(rule->r_family, buf, sizeof(buf)));
259 
260  if (rule->ce_mask & RULE_ATTR_DST)
261  dp_dump_line(p, line++, " <dst>%s</dst>\n",
262  nl_addr2str(rule->r_dst, buf, sizeof(buf)));
263 
264  if (rule->ce_mask & RULE_ATTR_DST_LEN)
265  dp_dump_line(p, line++, " <dstlen>%u</dstlen>\n",
266  rule->r_dst_len);
267 
268  if (rule->ce_mask & RULE_ATTR_SRC)
269  dp_dump_line(p, line++, " <src>%s</src>\n",
270  nl_addr2str(rule->r_src, buf, sizeof(buf)));
271 
272  if (rule->ce_mask & RULE_ATTR_SRC_LEN)
273  dp_dump_line(p, line++, " <srclen>%u</srclen>\n",
274  rule->r_src_len);
275 
276  if (rule->ce_mask & RULE_ATTR_IIF)
277  dp_dump_line(p, line++, " <iif>%s</iif>\n", rule->r_iif);
278 
279  if (rule->ce_mask & RULE_ATTR_TABLE)
280  dp_dump_line(p, line++, " <table>%u</table>\n",
281  rule->r_table);
282 
283  if (rule->ce_mask & RULE_ATTR_REALMS)
284  dp_dump_line(p, line++, " <realms>%u</realms>\n",
285  rule->r_realms);
286 
287  if (rule->ce_mask & RULE_ATTR_MARK)
288  dp_dump_line(p, line++, " <mark>%" PRIx64 "</mark>\n",
289  rule->r_mark);
290 
291  if (rule->ce_mask & RULE_ATTR_DSFIELD)
292  dp_dump_line(p, line++, " <dsfield>%u</dsfield>\n",
293  rule->r_dsfield);
294 
295  if (rule->ce_mask & RULE_ATTR_TYPE)
296  dp_dump_line(p, line++, "<type>%s</type>\n",
297  nl_rtntype2str(rule->r_type, buf, sizeof(buf)));
298 
299  if (rule->ce_mask & RULE_ATTR_SRCMAP)
300  dp_dump_line(p, line++, "<srcmap>%s</srcmap>\n",
301  nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
302 
303  dp_dump_line(p, line++, "</rule>\n");
304 
305  return line;
306 }
307 
308 static int rule_dump_env(struct nl_object *obj, struct nl_dump_params *p)
309 {
310  struct rtnl_rule *rule = (struct rtnl_rule *) obj;
311  char buf[128];
312  int line = 0;
313 
314  dp_dump_line(p, line++, "RULE_PRIORITY=%u\n",
315  rule->r_prio);
316  dp_dump_line(p, line++, "RULE_FAMILY=%s\n",
317  nl_af2str(rule->r_family, buf, sizeof(buf)));
318 
319  if (rule->ce_mask & RULE_ATTR_DST)
320  dp_dump_line(p, line++, "RULE_DST=%s\n",
321  nl_addr2str(rule->r_dst, buf, sizeof(buf)));
322 
323  if (rule->ce_mask & RULE_ATTR_DST_LEN)
324  dp_dump_line(p, line++, "RULE_DSTLEN=%u\n",
325  rule->r_dst_len);
326 
327  if (rule->ce_mask & RULE_ATTR_SRC)
328  dp_dump_line(p, line++, "RULE_SRC=%s\n",
329  nl_addr2str(rule->r_src, buf, sizeof(buf)));
330 
331  if (rule->ce_mask & RULE_ATTR_SRC_LEN)
332  dp_dump_line(p, line++, "RULE_SRCLEN=%u\n",
333  rule->r_src_len);
334 
335  if (rule->ce_mask & RULE_ATTR_IIF)
336  dp_dump_line(p, line++, "RULE_IIF=%s\n", rule->r_iif);
337 
338  if (rule->ce_mask & RULE_ATTR_TABLE)
339  dp_dump_line(p, line++, "RULE_TABLE=%u\n",
340  rule->r_table);
341 
342  if (rule->ce_mask & RULE_ATTR_REALMS)
343  dp_dump_line(p, line++, "RULE_REALM=%u\n",
344  rule->r_realms);
345 
346  if (rule->ce_mask & RULE_ATTR_MARK)
347  dp_dump_line(p, line++, "RULE_MARK=0x%" PRIx64 "\n",
348  rule->r_mark);
349 
350  if (rule->ce_mask & RULE_ATTR_DSFIELD)
351  dp_dump_line(p, line++, "RULE_DSFIELD=%u\n",
352  rule->r_dsfield);
353 
354  if (rule->ce_mask & RULE_ATTR_TYPE)
355  dp_dump_line(p, line++, "RULE_TYPE=%s\n",
356  nl_rtntype2str(rule->r_type, buf, sizeof(buf)));
357 
358  if (rule->ce_mask & RULE_ATTR_SRCMAP)
359  dp_dump_line(p, line++, "RULE_SRCMAP=%s\n",
360  nl_addr2str(rule->r_srcmap, buf, sizeof(buf)));
361 
362  return line;
363 }
364 
365 static int rule_compare(struct nl_object *_a, struct nl_object *_b,
366  uint32_t attrs, int flags)
367 {
368  struct rtnl_rule *a = (struct rtnl_rule *) _a;
369  struct rtnl_rule *b = (struct rtnl_rule *) _b;
370  int diff = 0;
371 
372 #define RULE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, RULE_ATTR_##ATTR, a, b, EXPR)
373 
374  diff |= RULE_DIFF(FAMILY, a->r_family != b->r_family);
375  diff |= RULE_DIFF(TABLE, a->r_table != b->r_table);
376  diff |= RULE_DIFF(REALMS, a->r_realms != b->r_realms);
377  diff |= RULE_DIFF(DSFIELD, a->r_dsfield != b->r_dsfield);
378  diff |= RULE_DIFF(TYPE, a->r_type != b->r_type);
379  diff |= RULE_DIFF(PRIO, a->r_prio != b->r_prio);
380  diff |= RULE_DIFF(MARK, a->r_mark != b->r_mark);
381  diff |= RULE_DIFF(SRC_LEN, a->r_src_len != b->r_src_len);
382  diff |= RULE_DIFF(DST_LEN, a->r_dst_len != b->r_dst_len);
383  diff |= RULE_DIFF(SRC, nl_addr_cmp(a->r_src, b->r_src));
384  diff |= RULE_DIFF(DST, nl_addr_cmp(a->r_dst, b->r_dst));
385  diff |= RULE_DIFF(IIF, strcmp(a->r_iif, b->r_iif));
386 
387 #undef RULE_DIFF
388 
389  return diff;
390 }
391 
392 static struct trans_tbl rule_attrs[] = {
393  __ADD(RULE_ATTR_FAMILY, family)
394  __ADD(RULE_ATTR_PRIO, prio)
395  __ADD(RULE_ATTR_MARK, mark)
396  __ADD(RULE_ATTR_IIF, iif)
397  __ADD(RULE_ATTR_REALMS, realms)
398  __ADD(RULE_ATTR_SRC, src)
399  __ADD(RULE_ATTR_DST, dst)
400  __ADD(RULE_ATTR_DSFIELD, dsfield)
401  __ADD(RULE_ATTR_TABLE, table)
402  __ADD(RULE_ATTR_TYPE, type)
403  __ADD(RULE_ATTR_SRC_LEN, src_len)
404  __ADD(RULE_ATTR_DST_LEN, dst_len)
405  __ADD(RULE_ATTR_SRCMAP, srcmap)
406 };
407 
408 static char *rule_attrs2str(int attrs, char *buf, size_t len)
409 {
410  return __flags2str(attrs, buf, len, rule_attrs,
411  ARRAY_SIZE(rule_attrs));
412 }
413 
414 /**
415  * @name Allocation/Freeing
416  * @{
417  */
418 
419 struct rtnl_rule *rtnl_rule_alloc(void)
420 {
421  return (struct rtnl_rule *) nl_object_alloc(&rule_obj_ops);
422 }
423 
424 void rtnl_rule_put(struct rtnl_rule *rule)
425 {
426  nl_object_put((struct nl_object *) rule);
427 }
428 
429 /** @} */
430 
431 /**
432  * @name Cache Management
433  * @{
434  */
435 
436 /**
437  * Build a rule cache including all rules of the specified family currently configured in the kernel.
438  * @arg handle netlink handle
439  * @arg family address family
440  *
441  * Allocates a new rule cache, initializes it properly and updates it
442  * to include all rules of the specified address family currently
443  * configured in the kernel.
444  *
445  * @note The caller is responsible for destroying and freeing the
446  * cache after using it. (nl_cache_destroy_and_free())
447  * @return The new cache or NULL if an error occured.
448  */
449 struct nl_cache * rtnl_rule_alloc_cache_by_family(struct nl_handle *handle,
450  int family)
451 {
452  struct nl_cache * cache;
453 
454  cache = nl_cache_alloc(&rtnl_rule_ops);
455  if (cache == NULL)
456  return NULL;
457 
458  /* XXX RULE_CACHE_FAMILY(cache) = family; */
459 
460  if (handle && nl_cache_refill(handle, cache) < 0) {
461  free(cache);
462  return NULL;
463  }
464 
465  return cache;
466 }
467 
468 /**
469  * Build a rule cache including all rules currently configured in the kernel.
470  * @arg handle netlink handle
471  *
472  * Allocates a new rule cache, initializes it properly and updates it
473  * to include all rules currently configured in the kernel.
474  *
475  * @note The caller is responsible for destroying and freeing the
476  * cache after using it. (nl_cache_destroy_and_free())
477  * @return The new cache or NULL if an error occured.
478  */
479 struct nl_cache * rtnl_rule_alloc_cache(struct nl_handle *handle)
480 {
481  return rtnl_rule_alloc_cache_by_family(handle, AF_UNSPEC);
482 }
483 
484 /** @} */
485 
486 /**
487  * @name Rule Addition
488  * @{
489  */
490 
491 static struct nl_msg *build_rule_msg(struct rtnl_rule *tmpl, int cmd, int flags)
492 {
493  struct nl_msg *msg;
494  struct rtmsg rtm = {
495  .rtm_type = RTN_UNSPEC
496  };
497 
498  if (cmd == RTM_NEWRULE)
499  rtm.rtm_type = RTN_UNICAST;
500 
501  if (tmpl->ce_mask & RULE_ATTR_FAMILY)
502  rtm.rtm_family = tmpl->r_family;
503 
504  if (tmpl->ce_mask & RULE_ATTR_TABLE)
505  rtm.rtm_table = tmpl->r_table;
506 
507  if (tmpl->ce_mask & RULE_ATTR_DSFIELD)
508  rtm.rtm_tos = tmpl->r_dsfield;
509 
510  if (tmpl->ce_mask & RULE_ATTR_TYPE)
511  rtm.rtm_type = tmpl->r_type;
512 
513  if (tmpl->ce_mask & RULE_ATTR_SRC_LEN)
514  rtm.rtm_src_len = tmpl->r_src_len;
515 
516  if (tmpl->ce_mask & RULE_ATTR_DST_LEN)
517  rtm.rtm_dst_len = tmpl->r_dst_len;
518 
519  msg = nlmsg_alloc_simple(cmd, flags);
520  if (!msg)
521  goto nla_put_failure;
522 
523  if (nlmsg_append(msg, &rtm, sizeof(rtm), NLMSG_ALIGNTO) < 0)
524  goto nla_put_failure;
525 
526  if (tmpl->ce_mask & RULE_ATTR_SRC)
527  NLA_PUT_ADDR(msg, RTA_SRC, tmpl->r_src);
528 
529  if (tmpl->ce_mask & RULE_ATTR_DST)
530  NLA_PUT_ADDR(msg, RTA_DST, tmpl->r_dst);
531 
532  if (tmpl->ce_mask & RULE_ATTR_PRIO)
533  NLA_PUT_U32(msg, RTA_PRIORITY, tmpl->r_prio);
534 
535  if (tmpl->ce_mask & RULE_ATTR_MARK)
536  NLA_PUT_U32(msg, RTA_PROTOINFO, tmpl->r_mark);
537 
538  if (tmpl->ce_mask & RULE_ATTR_REALMS)
539  NLA_PUT_U32(msg, RTA_FLOW, tmpl->r_realms);
540 
541  if (tmpl->ce_mask & RULE_ATTR_IIF)
542  NLA_PUT_STRING(msg, RTA_IIF, tmpl->r_iif);
543 
544  return msg;
545 
546 nla_put_failure:
547  nlmsg_free(msg);
548  return NULL;
549 }
550 
551 /**
552  * Build netlink request message to add a new rule
553  * @arg tmpl template with data of new rule
554  * @arg flags additional netlink message flags
555  *
556  * Builds a new netlink message requesting a addition of a new
557  * rule. The netlink message header isn't fully equipped with
558  * all relevant fields and must thus be sent out via nl_send_auto_complete()
559  * or supplemented as needed. \a tmpl must contain the attributes of the new
560  * address set via \c rtnl_rule_set_* functions.
561  *
562  * @return The netlink message
563  */
564 struct nl_msg *rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags)
565 {
566  return build_rule_msg(tmpl, RTM_NEWRULE, NLM_F_CREATE | flags);
567 }
568 
569 /**
570  * Add a new rule
571  * @arg handle netlink handle
572  * @arg tmpl template with requested changes
573  * @arg flags additional netlink message flags
574  *
575  * Builds a netlink message by calling rtnl_rule_build_add_request(),
576  * sends the request to the kernel and waits for the next ACK to be
577  * received and thus blocks until the request has been fullfilled.
578  *
579  * @return 0 on sucess or a negative error if an error occured.
580  */
581 int rtnl_rule_add(struct nl_handle *handle, struct rtnl_rule *tmpl, int flags)
582 {
583  int err;
584  struct nl_msg *msg;
585 
586  msg = rtnl_rule_build_add_request(tmpl, flags);
587  if (!msg)
588  return nl_errno(ENOMEM);
589 
590  err = nl_send_auto_complete(handle, msg);
591  if (err < 0)
592  return err;
593 
594  nlmsg_free(msg);
595  return nl_wait_for_ack(handle);
596 }
597 
598 /** @} */
599 
600 /**
601  * @name Rule Deletion
602  * @{
603  */
604 
605 /**
606  * Build a netlink request message to delete a rule
607  * @arg rule rule to delete
608  * @arg flags additional netlink message flags
609  *
610  * Builds a new netlink message requesting a deletion of a rule.
611  * The netlink message header isn't fully equipped with all relevant
612  * fields and must thus be sent out via nl_send_auto_complete()
613  * or supplemented as needed. \a rule must point to an existing
614  * address.
615  *
616  * @return The netlink message
617  */
618 struct nl_msg *rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags)
619 {
620  return build_rule_msg(rule, RTM_DELRULE, flags);
621 }
622 
623 /**
624  * Delete a rule
625  * @arg handle netlink handle
626  * @arg rule rule to delete
627  * @arg flags additional netlink message flags
628  *
629  * Builds a netlink message by calling rtnl_rule_build_delete_request(),
630  * sends the request to the kernel and waits for the next ACK to be
631  * received and thus blocks until the request has been fullfilled.
632  *
633  * @return 0 on sucess or a negative error if an error occured.
634  */
635 int rtnl_rule_delete(struct nl_handle *handle, struct rtnl_rule *rule,
636  int flags)
637 {
638  int err;
639  struct nl_msg *msg;
640 
641  msg = rtnl_rule_build_delete_request(rule, flags);
642  if (!msg)
643  return nl_errno(ENOMEM);
644 
645  err = nl_send_auto_complete(handle, msg);
646  if (err < 0)
647  return err;
648 
649  nlmsg_free(msg);
650  return nl_wait_for_ack(handle);
651 }
652 
653 /** @} */
654 
655 /**
656  * @name Attribute Modification
657  * @{
658  */
659 
660 void rtnl_rule_set_family(struct rtnl_rule *rule, int family)
661 {
662  rule->r_family = family;
663  rule->ce_mask |= RULE_ATTR_FAMILY;
664 }
665 
666 int rtnl_rule_get_family(struct rtnl_rule *rule)
667 {
668  if (rule->ce_mask & RULE_ATTR_FAMILY)
669  return rule->r_family;
670  else
671  return AF_UNSPEC;
672 }
673 
674 void rtnl_rule_set_prio(struct rtnl_rule *rule, int prio)
675 {
676  rule->r_prio = prio;
677  rule->ce_mask |= RULE_ATTR_PRIO;
678 }
679 
680 int rtnl_rule_get_prio(struct rtnl_rule *rule)
681 {
682  if (rule->ce_mask & RULE_ATTR_PRIO)
683  return rule->r_prio;
684  else
685  return -1;
686 }
687 
688 void rtnl_rule_set_mark(struct rtnl_rule *rule, uint64_t mark)
689 {
690  rule->r_mark = mark;
691  rule->ce_mask |= RULE_ATTR_MARK;
692 }
693 
694 uint64_t rtnl_rule_get_mark(struct rtnl_rule *rule)
695 {
696  if (rule->ce_mask & RULE_ATTR_MARK)
697  return rule->r_mark;
698  else
699  return UINT_LEAST64_MAX;
700 }
701 
702 void rtnl_rule_set_table(struct rtnl_rule *rule, int table)
703 {
704  rule->r_table = table;
705  rule->ce_mask |= RULE_ATTR_TABLE;
706 }
707 
708 int rtnl_rule_get_table(struct rtnl_rule *rule)
709 {
710  if (rule->ce_mask & RULE_ATTR_TABLE)
711  return rule->r_table;
712  else
713  return -1;
714 }
715 
716 void rtnl_rule_set_dsfield(struct rtnl_rule *rule, int dsfield)
717 {
718  rule->r_dsfield = dsfield;
719  rule->ce_mask |= RULE_ATTR_DSFIELD;
720 }
721 
722 int rtnl_rule_get_dsfield(struct rtnl_rule *rule)
723 {
724  if (rule->ce_mask & RULE_ATTR_DSFIELD)
725  return rule->r_dsfield;
726  else
727  return -1;
728 }
729 
730 void rtnl_rule_set_src_len(struct rtnl_rule *rule, int len)
731 {
732  rule->r_src_len = len;
733  if (rule->ce_mask & RULE_ATTR_SRC)
734  nl_addr_set_prefixlen(rule->r_src, len);
735  rule->ce_mask |= RULE_ATTR_SRC_LEN;
736 }
737 
738 int rtnl_rule_get_src_len(struct rtnl_rule *rule)
739 {
740  if (rule->ce_mask & RULE_ATTR_SRC_LEN)
741  return rule->r_src_len;
742  else
743  return -1;
744 }
745 
746 void rtnl_rule_set_dst_len(struct rtnl_rule *rule, int len)
747 {
748  rule->r_dst_len = len;
749  if (rule->ce_mask & RULE_ATTR_DST)
750  nl_addr_set_prefixlen(rule->r_dst, len);
751  rule->ce_mask |= RULE_ATTR_DST_LEN;
752 }
753 
754 int rtnl_rule_get_dst_len(struct rtnl_rule *rule)
755 {
756  if (rule->ce_mask & RULE_ATTR_DST_LEN)
757  return rule->r_dst_len;
758  else
759  return -1;
760 }
761 
762 static inline int __assign_addr(struct rtnl_rule *rule, struct nl_addr **pos,
763  struct nl_addr *new, uint8_t *len, int flag)
764 {
765  if (rule->ce_mask & RULE_ATTR_FAMILY) {
766  if (new->a_family != rule->r_family)
767  return nl_error(EINVAL, "Address family mismatch");
768  } else
769  rule->r_family = new->a_family;
770 
771  if (*pos)
772  nl_addr_put(*pos);
773 
774  nl_addr_get(new);
775  *pos = new;
776  *len = nl_addr_get_prefixlen(new);
777 
778  rule->ce_mask |= (flag | RULE_ATTR_FAMILY);
779 
780  return 0;
781 }
782 
783 int rtnl_rule_set_src(struct rtnl_rule *rule, struct nl_addr *src)
784 {
785  return __assign_addr(rule, &rule->r_src, src, &rule->r_src_len,
786  RULE_ATTR_SRC | RULE_ATTR_SRC_LEN);
787 }
788 
789 struct nl_addr *rtnl_rule_get_src(struct rtnl_rule *rule)
790 {
791  if (rule->ce_mask & RULE_ATTR_SRC)
792  return rule->r_src;
793  else
794  return NULL;
795 }
796 
797 int rtnl_rule_set_dst(struct rtnl_rule *rule, struct nl_addr *dst)
798 {
799  return __assign_addr(rule, &rule->r_dst, dst, &rule->r_dst_len,
800  RULE_ATTR_DST | RULE_ATTR_DST_LEN);
801 }
802 
803 struct nl_addr *rtnl_rule_get_dst(struct rtnl_rule *rule)
804 {
805  if (rule->ce_mask & RULE_ATTR_DST)
806  return rule->r_dst;
807  else
808  return NULL;
809 }
810 
811 int rtnl_rule_set_iif(struct rtnl_rule *rule, const char *dev)
812 {
813  if (strlen(dev) > IFNAMSIZ-1)
814  return nl_errno(ERANGE);
815 
816  strcpy(rule->r_iif, dev);
817  rule->ce_mask |= RULE_ATTR_IIF;
818  return 0;
819 }
820 
821 char *rtnl_rule_get_iif(struct rtnl_rule *rule)
822 {
823  if (rule->ce_mask & RULE_ATTR_IIF)
824  return rule->r_iif;
825  else
826  return NULL;
827 }
828 
829 void rtnl_rule_set_action(struct rtnl_rule *rule, int type)
830 {
831  rule->r_type = type;
832  rule->ce_mask |= RULE_ATTR_TYPE;
833 }
834 
835 int rtnl_rule_get_action(struct rtnl_rule *rule)
836 {
837  if (rule->ce_mask & RULE_ATTR_TYPE)
838  return rule->r_type;
839  else
840  return nl_errno(ENOENT);
841 }
842 
843 void rtnl_rule_set_realms(struct rtnl_rule *rule, realm_t realms)
844 {
845  rule->r_realms = realms;
846  rule->ce_mask |= RULE_ATTR_REALMS;
847 }
848 
849 realm_t rtnl_rule_get_realms(struct rtnl_rule *rule)
850 {
851  if (rule->ce_mask & RULE_ATTR_REALMS)
852  return rule->r_realms;
853  else
854  return 0;
855 }
856 
857 /** @} */
858 
859 static struct nl_object_ops rule_obj_ops = {
860  .oo_name = "route/rule",
861  .oo_size = sizeof(struct rtnl_rule),
862  .oo_free_data = rule_free_data,
863  .oo_clone = rule_clone,
864  .oo_dump[NL_DUMP_BRIEF] = rule_dump_brief,
865  .oo_dump[NL_DUMP_FULL] = rule_dump_full,
866  .oo_dump[NL_DUMP_STATS] = rule_dump_stats,
867  .oo_dump[NL_DUMP_XML] = rule_dump_xml,
868  .oo_dump[NL_DUMP_ENV] = rule_dump_env,
869  .oo_compare = rule_compare,
870  .oo_attrs2str = rule_attrs2str,
871  .oo_id_attrs = ~0,
872 };
873 
874 static struct nl_cache_ops rtnl_rule_ops = {
875  .co_name = "route/rule",
876  .co_hdrsize = sizeof(struct rtmsg),
877  .co_msgtypes = {
878  { RTM_NEWRULE, NL_ACT_NEW, "new" },
879  { RTM_DELRULE, NL_ACT_DEL, "del" },
880  { RTM_GETRULE, NL_ACT_GET, "get" },
881  END_OF_MSGTYPES_LIST,
882  },
883  .co_protocol = NETLINK_ROUTE,
884  .co_request_update = rule_request_update,
885  .co_msg_parser = rule_msg_parser,
886  .co_obj_ops = &rule_obj_ops,
887 };
888 
889 static void __init rule_init(void)
890 {
891  nl_cache_mngt_register(&rtnl_rule_ops);
892 }
893 
894 static void __exit rule_exit(void)
895 {
896  nl_cache_mngt_unregister(&rtnl_rule_ops);
897 }
898 
899 /** @} */
32bit integer
Definition: attr.h:39
Dump object in a brief one-liner.
Definition: types.h:22
char * nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
Definition: addr.c:802
void * nlmsg_data(const struct nlmsghdr *nlh)
head of message payload
Definition: msg.c:218
uint16_t nlmsg_type
Message type (content type)
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:42
int nl_cache_mngt_unregister(struct nl_cache_ops *ops)
Unregister a set of cache operations.
Definition: cache_mngt.c:157
attribute validation policy
Definition: attr.h:73
struct nl_msg * rtnl_rule_build_add_request(struct rtnl_rule *tmpl, int flags)
Build netlink request message to add a new rule.
Definition: rule.c:564
struct nl_addr * nl_addr_clone(struct nl_addr *addr)
Clone existing abstract address object.
Definition: addr.c:406
int nl_wait_for_ack(struct nl_handle *handle)
Wait for ACK.
Definition: nl.c:800
void nlmsg_free(struct nl_msg *n)
Free a netlink message.
Definition: msg.c:659
Netlink message header.
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:319
int rtnl_rule_delete(struct nl_handle *handle, struct rtnl_rule *rule, int flags)
Delete a rule.
Definition: rule.c:635
#define NLA_PUT_STRING(n, attrtype, value)
Add a character string netlink attribute to a netlink message.
Definition: attr.h:219
character string
Definition: attr.h:41
struct nl_cache * rtnl_rule_alloc_cache_by_family(struct nl_handle *handle, int family)
Build a rule cache including all rules of the specified family currently configured in the kernel...
Definition: rule.c:449
int nl_send_auto_complete(struct nl_handle *handle, struct nl_msg *msg)
Send netlink message and check & extend header values as needed.
Definition: nl.c:373
int nl_cache_mngt_register(struct nl_cache_ops *ops)
Register a set of cache operations.
Definition: cache_mngt.c:127
int nl_cache_refill(struct nl_handle *handle, struct nl_cache *cache)
(Re)fill a cache with the contents in the kernel.
Definition: cache.c:662
Dump all attribtes in XML format.
Definition: types.h:25
#define NLM_F_CREATE
Create config object if it doesn't already exist.
#define NLM_F_DUMP
Dump all entries.
Cache Operations.
Definition: cache-api.h:163
int nl_rtgen_request(struct nl_handle *handle, int type, int family, int flags)
Send routing netlink request message.
Definition: rtnl.c:40
struct nl_addr * nla_get_addr(struct nlattr *nla, int family)
Return payload of address attribute.
Definition: attr.c:766
#define NLA_PUT_ADDR(n, attrtype, addr)
Add a address attribute to a netlink message.
Definition: attr.h:245
Object Operations.
Definition: object-api.h:254
unsigned int nl_addr_get_prefixlen(struct nl_addr *addr)
Get prefix length of abstract address object.
Definition: addr.c:779
Netlink socket address.
Definition: netlink-kernel.h:8
int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b)
Compares two abstract address objects.
Definition: addr.c:489
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:552
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
Definition: object.c:173
uint16_t type
Type of attribute or NLA_UNSPEC.
Definition: attr.h:75
struct nl_msg * nlmsg_alloc_simple(int nlmsgtype, int flags)
Allocate a new netlink message.
Definition: msg.c:448
Dumping parameters.
Definition: types.h:36
uint32_t nla_get_u32(struct nlattr *nla)
Return payload of u32 attribute.
Definition: attr.c:694
int rtnl_rule_add(struct nl_handle *handle, struct rtnl_rule *tmpl, int flags)
Add a new rule.
Definition: rule.c:581
struct nl_msg * rtnl_rule_build_delete_request(struct rtnl_rule *rule, int flags)
Build a netlink request message to delete a rule.
Definition: rule.c:618
char * oo_name
Unique name of object type.
Definition: object-api.h:261
Dump all attributes but no statistics.
Definition: types.h:23
Dump all attributes including statistics.
Definition: types.h:24
struct nl_cache * rtnl_rule_alloc_cache(struct nl_handle *handle)
Build a rule cache including all rules currently configured in the kernel.
Definition: rule.c:479
size_t nla_strlcpy(char *dst, const struct nlattr *nla, size_t dstsize)
Copy string attribute payload into a sized buffer.
Definition: attr.c:408
#define NLA_PUT_U32(n, attrtype, value)
Add a u32 netlink attribute to a netlink message.
Definition: attr.h:201
struct nl_cache * nl_cache_alloc(struct nl_cache_ops *ops)
Allocate an empty cache.
Definition: cache.c:173
Dump all attribtues as env variables.
Definition: types.h:26