2 * lib/route/route.c Routes
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
9 * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
14 * @defgroup route Routing
19 #include <netlink-local.h>
20 #include <netlink/netlink.h>
21 #include <netlink/cache.h>
22 #include <netlink/utils.h>
23 #include <netlink/data.h>
24 #include <netlink/route/rtnl.h>
25 #include <netlink/route/route.h>
26 #include <netlink/route/link.h>
29 #define ROUTE_ATTR_FAMILY 0x000001
30 #define ROUTE_ATTR_DST_LEN 0x000002
31 #define ROUTE_ATTR_SRC_LEN 0x000004
32 #define ROUTE_ATTR_TOS 0x000008
33 #define ROUTE_ATTR_TABLE 0x000010
34 #define ROUTE_ATTR_PROTOCOL 0x000020
35 #define ROUTE_ATTR_SCOPE 0x000040
36 #define ROUTE_ATTR_TYPE 0x000080
37 #define ROUTE_ATTR_FLAGS 0x000100
38 #define ROUTE_ATTR_DST 0x000200
39 #define ROUTE_ATTR_SRC 0x000400
40 #define ROUTE_ATTR_IIF 0x000800
41 #define ROUTE_ATTR_OIF 0x001000
42 #define ROUTE_ATTR_GATEWAY 0x002000
43 #define ROUTE_ATTR_PRIO 0x004000
44 #define ROUTE_ATTR_PREF_SRC 0x008000
45 #define ROUTE_ATTR_METRICS 0x010000
46 #define ROUTE_ATTR_MULTIPATH 0x020000
47 #define ROUTE_ATTR_REALMS 0x040000
48 #define ROUTE_ATTR_CACHEINFO 0x080000
49 #define ROUTE_ATTR_MP_ALGO 0x100000
51 #define NEXTHOP_HAS_FLAGS 0x000001
52 #define NEXTHOP_HAS_WEIGHT 0x000002
53 #define NEXTHOP_HAS_IFINDEX 0x000004
54 #define NEXTHOP_HAS_GATEWAY 0x000008
56 static struct nl_cache_ops rtnl_route_ops;
59 static void route_constructor(struct nl_object *c)
61 struct rtnl_route *r = (struct rtnl_route *) c;
63 nl_init_list_head(&r->rt_nexthops);
66 static void route_free_data(struct nl_object *c)
68 struct rtnl_route *r = (struct rtnl_route *) c;
69 struct rtnl_nexthop *nh, *tmp;
74 nl_addr_put(r->rt_dst);
75 nl_addr_put(r->rt_src);
76 nl_addr_put(r->rt_gateway);
77 nl_addr_put(r->rt_pref_src);
79 nl_list_for_each_entry_safe(nh, tmp, &r->rt_nexthops, rtnh_list) {
80 rtnl_route_remove_nexthop(nh);
81 rtnl_route_nh_free(nh);
85 static struct nla_policy route_policy[RTA_MAX+1] = {
86 [RTA_IIF] = { .type = NLA_STRING,
87 .maxlen = IFNAMSIZ, },
88 [RTA_OIF] = { .type = NLA_U32 },
89 [RTA_PRIORITY] = { .type = NLA_U32 },
90 [RTA_FLOW] = { .type = NLA_U32 },
91 [RTA_MP_ALGO] = { .type = NLA_U32 },
92 [RTA_CACHEINFO] = { .minlen = sizeof(struct rta_cacheinfo) },
93 [RTA_METRICS] = { .type = NLA_NESTED },
94 [RTA_MULTIPATH] = { .type = NLA_NESTED },
97 static void copy_rtmsg_into_route(struct rtmsg *rtmsg, struct rtnl_route *route)
99 route->rt_family = rtmsg->rtm_family;
100 route->rt_dst_len = rtmsg->rtm_dst_len;
101 route->rt_src_len = rtmsg->rtm_src_len;
102 route->rt_tos = rtmsg->rtm_tos;
103 route->rt_table = rtmsg->rtm_table;
104 route->rt_type = rtmsg->rtm_type;
105 route->rt_scope = rtmsg->rtm_scope;
106 route->rt_protocol = rtmsg->rtm_protocol;
107 route->rt_flags = rtmsg->rtm_flags;
109 route->rt_mask = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_DST_LEN |
110 ROUTE_ATTR_SRC_LEN | ROUTE_ATTR_TABLE |
111 ROUTE_ATTR_PROTOCOL| ROUTE_ATTR_SCOPE |
112 ROUTE_ATTR_TYPE | ROUTE_ATTR_FLAGS);
115 route->rt_mask |= ROUTE_ATTR_TOS;
118 static void copy_cacheinfo_into_route(struct rta_cacheinfo *ci,
119 struct rtnl_route *route)
121 route->rt_cacheinfo.rtci_clntref = ci->rta_clntref;
122 route->rt_cacheinfo.rtci_last_use = ci->rta_lastuse;
123 route->rt_cacheinfo.rtci_expires = ci->rta_expires;
124 route->rt_cacheinfo.rtci_error = ci->rta_error;
125 route->rt_cacheinfo.rtci_used = ci->rta_used;
126 route->rt_cacheinfo.rtci_id = ci->rta_id;
127 route->rt_cacheinfo.rtci_ts = ci->rta_ts;
128 route->rt_cacheinfo.rtci_tsage = ci->rta_tsage;
130 route->rt_mask |= ROUTE_ATTR_CACHEINFO;
133 static int route_msg_parser(struct sockaddr_nl *who, struct nlmsghdr *nlh,
136 struct nl_parser_param *pp = arg;
137 struct rtnl_route *route;
138 struct nlattr *tb[RTA_MAX + 1];
141 route = rtnl_route_alloc();
143 err = nl_errno(ENOMEM);
147 route->ce_msgtype = nlh->nlmsg_type;
149 err = nlmsg_parse(nlh, sizeof(struct rtmsg), tb, RTA_MAX,
154 copy_rtmsg_into_route((struct rtmsg *) nlmsg_data(nlh), route);
157 route->rt_dst = nla_get_addr(tb[RTA_DST], route->rt_family);
160 nl_addr_set_prefixlen(route->rt_dst, route->rt_dst_len);
161 route->rt_mask |= ROUTE_ATTR_DST;
165 route->rt_src = nla_get_addr(tb[RTA_SRC], route->rt_family);
168 nl_addr_set_prefixlen(route->rt_src, route->rt_src_len);
169 route->rt_mask |= ROUTE_ATTR_SRC;
173 nla_strlcpy(route->rt_iif, tb[RTA_IIF], IFNAMSIZ);
174 route->rt_mask |= ROUTE_ATTR_IIF;
178 route->rt_oif = nla_get_u32(tb[RTA_OIF]);
179 route->rt_mask |= ROUTE_ATTR_OIF;
182 if (tb[RTA_GATEWAY]) {
183 route->rt_gateway = nla_get_addr(tb[RTA_GATEWAY],
185 if (!route->rt_gateway)
187 route->rt_mask |= ROUTE_ATTR_GATEWAY;
190 if (tb[RTA_PRIORITY]) {
191 route->rt_prio = nla_get_u32(tb[RTA_PRIORITY]);
192 route->rt_mask |= ROUTE_ATTR_PRIO;
195 if (tb[RTA_PREFSRC]) {
196 route->rt_pref_src = nla_get_addr(tb[RTA_PREFSRC],
198 if (!route->rt_pref_src)
200 route->rt_mask |= ROUTE_ATTR_PREF_SRC;
203 if (tb[RTA_METRICS]) {
204 struct nlattr *mtb[RTAX_MAX + 1];
207 err = nla_parse_nested(mtb, RTAX_MAX, tb[RTA_METRICS], NULL);
211 for (i = 1; i <= RTAX_MAX; i++) {
212 if (mtb[i] && nla_len(mtb[i]) >= sizeof(uint32_t)) {
213 uint32_t m = nla_get_u32(mtb[i]);
214 route->rt_metrics[i-1] = m;
215 route->rt_metrics_mask |= (1 << (i - 1));
219 route->rt_mask |= ROUTE_ATTR_METRICS;
222 if (tb[RTA_MULTIPATH]) {
223 struct rtnl_nexthop *nh;
224 struct rtnexthop *rtnh = nla_data(tb[RTA_MULTIPATH]);
225 size_t tlen = nla_len(tb[RTA_MULTIPATH]);
227 while (tlen >= sizeof(*rtnh) && tlen >= rtnh->rtnh_len) {
228 nh = rtnl_route_nh_alloc();
232 rtnl_route_nh_set_weight(nh, rtnh->rtnh_hops);
233 rtnl_route_nh_set_ifindex(nh, rtnh->rtnh_ifindex);
234 rtnl_route_nh_set_flags(nh, rtnh->rtnh_flags);
236 if (rtnh->rtnh_len > sizeof(*rtnh)) {
237 struct nlattr *ntb[RTA_MAX + 1];
238 nla_parse(ntb, RTA_MAX, (struct nlattr *)
240 rtnh->rtnh_len - sizeof(*rtnh),
243 if (ntb[RTA_GATEWAY]) {
244 nh->rtnh_gateway = nla_get_addr(
247 nh->rtnh_mask = NEXTHOP_HAS_GATEWAY;
251 rtnl_route_add_nexthop(route, nh);
252 tlen -= RTNH_ALIGN(rtnh->rtnh_len);
253 rtnh = RTNH_NEXT(rtnh);
258 route->rt_realms = nla_get_u32(tb[RTA_FLOW]);
259 route->rt_mask |= ROUTE_ATTR_REALMS;
262 if (tb[RTA_CACHEINFO])
263 copy_cacheinfo_into_route(nla_data(tb[RTA_CACHEINFO]), route);
265 if (tb[RTA_MP_ALGO]) {
266 route->rt_mp_algo = nla_get_u32(tb[RTA_MP_ALGO]);
267 route->rt_mask |= ROUTE_ATTR_MP_ALGO;
270 err = pp->pp_cb((struct nl_object *) route, pp);
277 err = nl_get_errno();
279 rtnl_route_put(route);
284 static int route_request_update(struct nl_cache *c, struct nl_handle *h)
286 return nl_rtgen_request(h, RTM_GETROUTE, AF_UNSPEC, NLM_F_DUMP);
289 static int route_dump_brief(struct nl_object *a, struct nl_dump_params *p)
291 struct rtnl_route *r = (struct rtnl_route *) a;
292 struct nl_cache *link_cache;
295 link_cache = nl_cache_mngt_require("route/link");
297 if (r->rt_mask & ROUTE_ATTR_DST)
298 dp_dump(p, "%s ", nl_addr2str(r->rt_dst, buf, sizeof(buf)));
299 else if (r->rt_dst_len)
300 dp_dump(p, "0/%u ", r->rt_dst_len);
302 dp_dump(p, "default ");
304 if (r->rt_mask & ROUTE_ATTR_OIF) {
306 dp_dump(p, "dev %s ",
307 rtnl_link_i2name(link_cache, r->rt_oif,
310 dp_dump(p, "dev %d ", r->rt_oif);
313 if (r->rt_mask & ROUTE_ATTR_GATEWAY)
314 dp_dump(p, "via %s ", nl_addr2str(r->rt_gateway, buf,
316 else if (r->rt_mask & ROUTE_ATTR_MULTIPATH)
317 dp_dump(p, "via nexthops ");
319 if (r->rt_mask & ROUTE_ATTR_TABLE)
320 dp_dump(p, "table %s ",
321 rtnl_route_table2str(r->rt_table, buf, sizeof(buf)));
323 if (r->rt_mask & ROUTE_ATTR_SCOPE)
324 dp_dump(p, "scope %s ",
325 rtnl_scope2str(r->rt_scope, buf, sizeof(buf)));
327 if (r->rt_mask & ROUTE_ATTR_FLAGS && r->rt_flags) {
328 int flags = r->rt_flags;
332 #define PRINT_FLAG(f) if (flags & RTNH_F_##f) { \
333 flags &= ~RTNH_F_##f; dp_dump(p, #f "%s", flags ? "," : ""); }
336 PRINT_FLAG(PERVASIVE);
339 #define PRINT_FLAG(f) if (flags & RTM_F_##f) { \
340 flags &= ~RTM_F_##f; dp_dump(p, #f "%s", flags ? "," : ""); }
343 PRINT_FLAG(EQUALIZE);
355 static int route_dump_full(struct nl_object *a, struct nl_dump_params *p)
357 struct rtnl_route *r = (struct rtnl_route *) a;
358 struct nl_cache *link_cache;
362 link_cache = nl_cache_mngt_require("route/link");
363 line = route_dump_brief(a, p);
365 if (r->rt_mask & ROUTE_ATTR_MULTIPATH) {
366 struct rtnl_nexthop *nh;
368 dp_dump_line(p, line++, " ");
370 nl_list_for_each_entry(nh, &r->rt_nexthops, rtnh_list) {
373 if (nh->rtnh_mask & NEXTHOP_HAS_GATEWAY)
374 dp_dump(p, "via %s ",
375 nl_addr2str(nh->rtnh_gateway,
378 dp_dump(p, "dev %s ",
379 rtnl_link_i2name(link_cache,
383 dp_dump(p, "dev %d ", nh->rtnh_ifindex);
385 dp_dump(p, "weight %u <%s> ", nh->rtnh_weight,
386 rtnl_route_nh_flags2str(nh->rtnh_flags,
393 dp_dump_line(p, line++, " ");
395 if (r->rt_mask & ROUTE_ATTR_PREF_SRC)
396 dp_dump(p, "preferred-src %s ",
397 nl_addr2str(r->rt_pref_src, buf, sizeof(buf)));
399 if (r->rt_mask & ROUTE_ATTR_TYPE)
400 dp_dump(p, "type %s ",
401 nl_rtntype2str(r->rt_type, buf, sizeof(buf)));
403 if (r->rt_mask & ROUTE_ATTR_PRIO)
404 dp_dump(p, "metric %#x ", r->rt_prio);
406 if (r->rt_mask & ROUTE_ATTR_FAMILY)
407 dp_dump(p, "family %s ",
408 nl_af2str(r->rt_family, buf, sizeof(buf)));
410 if (r->rt_mask & ROUTE_ATTR_PROTOCOL)
411 dp_dump(p, "protocol %s ",
412 rtnl_route_proto2str(r->rt_protocol, buf, sizeof(buf)));
416 if ((r->rt_mask & (ROUTE_ATTR_IIF | ROUTE_ATTR_SRC | ROUTE_ATTR_TOS |
417 ROUTE_ATTR_REALMS)) || r->rt_src_len ||
418 ((r->rt_mask & ROUTE_ATTR_CACHEINFO) &&
419 r->rt_cacheinfo.rtci_error)) {
420 dp_dump_line(p, line++, " ");
422 if (r->rt_mask & ROUTE_ATTR_IIF)
423 dp_dump(p, "iif %s ", r->rt_iif);
425 if (r->rt_mask & ROUTE_ATTR_SRC)
426 dp_dump(p, "src %s ",
427 nl_addr2str(r->rt_src, buf, sizeof(buf)));
428 else if (r->rt_src_len)
429 dp_dump(p, "src 0/%u ", r->rt_src_len);
431 if (r->rt_mask & ROUTE_ATTR_TOS)
432 dp_dump(p, "tos %#x ", r->rt_tos);
434 if (r->rt_mask & ROUTE_ATTR_REALMS)
435 dp_dump(p, "realm %04x:%04x ",
436 RTNL_REALM_FROM(r->rt_realms),
437 RTNL_REALM_TO(r->rt_realms));
439 if ((r->rt_mask & ROUTE_ATTR_CACHEINFO) &&
440 r->rt_cacheinfo.rtci_error)
441 dp_dump(p, "error %d (%s) ", r->rt_cacheinfo.rtci_error,
442 strerror(-r->rt_cacheinfo.rtci_error));
447 if (r->rt_mask & ROUTE_ATTR_METRICS) {
448 dp_dump_line(p, line++, " ");
449 for (i = 0; i < RTAX_MAX; i++)
450 if (r->rt_metrics_mask & (1 << i))
452 rtnl_route_metric2str(i+1,
461 static int route_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
463 struct rtnl_route *route = (struct rtnl_route *) obj;
466 line = route_dump_full(obj, p);
468 if (route->rt_mask & ROUTE_ATTR_CACHEINFO) {
469 struct rtnl_rtcacheinfo *ci = &route->rt_cacheinfo;
470 dp_dump_line(p, line++, " used %u refcnt %u ",
471 ci->rtci_used, ci->rtci_clntref);
472 dp_dump_line(p, line++, "last-use %us expires %us\n",
473 ci->rtci_last_use / nl_get_hz(),
474 ci->rtci_expires / nl_get_hz());
480 static int route_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
482 struct rtnl_route *route = (struct rtnl_route *) obj;
486 dp_dump_line(p, line++, "<route>\n");
487 dp_dump_line(p, line++, " <family>%s</family>\n",
488 nl_af2str(route->rt_family, buf, sizeof(buf)));
490 if (route->rt_mask & ROUTE_ATTR_DST)
491 dp_dump_line(p, line++, " <dst>%s</dst>\n",
492 nl_addr2str(route->rt_dst, buf, sizeof(buf)));
494 if (route->rt_mask & ROUTE_ATTR_DST_LEN)
495 dp_dump_line(p, line++, " <dstlen>%u</dstlen>\n",
498 if (route->rt_mask & ROUTE_ATTR_SRC)
499 dp_dump_line(p, line++, " <src>%s</src>\n",
500 nl_addr2str(route->rt_src, buf, sizeof(buf)));
502 if (route->rt_mask & ROUTE_ATTR_SRC_LEN)
503 dp_dump_line(p, line++, " <srclen>%u</srclen>\n",
506 if (route->rt_mask & ROUTE_ATTR_GATEWAY)
507 dp_dump_line(p, line++, " <gateway>%s</gateway>\n",
508 nl_addr2str(route->rt_gateway, buf, sizeof(buf)));
510 if (route->rt_mask & ROUTE_ATTR_PREF_SRC)
511 dp_dump_line(p, line++, " <prefsrc>%s</prefsrc>\n",
512 nl_addr2str(route->rt_pref_src, buf, sizeof(buf)));
514 if (route->rt_mask & ROUTE_ATTR_IIF)
515 dp_dump_line(p, line++, " <iif>%s</iif>\n", route->rt_iif);
517 if (route->rt_mask & ROUTE_ATTR_REALMS)
518 dp_dump_line(p, line++, " <realms>%u</realms>\n",
521 if (route->rt_mask & ROUTE_ATTR_TOS)
522 dp_dump_line(p, line++, " <tos>%u</tos>\n", route->rt_tos);
524 if (route->rt_mask & ROUTE_ATTR_TABLE)
525 dp_dump_line(p, line++, " <table>%u</table>\n",
528 if (route->rt_mask & ROUTE_ATTR_SCOPE)
529 dp_dump_line(p, line++, " <scope>%s</scope>\n",
530 rtnl_scope2str(route->rt_scope, buf, sizeof(buf)));
532 if (route->rt_mask & ROUTE_ATTR_PRIO)
533 dp_dump_line(p, line++, " <metric>%u</metric>\n",
536 if (route->rt_mask & ROUTE_ATTR_OIF) {
537 struct nl_cache *link_cache;
539 link_cache = nl_cache_mngt_require("route/link");
541 dp_dump_line(p, line++, " <oif>%s</oif>\n",
542 rtnl_link_i2name(link_cache,
546 dp_dump_line(p, line++, " <oif>%u</oif>\n",
550 if (route->rt_mask & ROUTE_ATTR_TYPE)
551 dp_dump_line(p, line++, " <type>%s</type>\n",
552 nl_rtntype2str(route->rt_type, buf, sizeof(buf)));
554 dp_dump_line(p, line++, "</route>\n");
559 uint32_t rt_metrics[RTAX_MAX];
560 uint32_t rt_metrics_mask;
561 struct rtnl_nexthop * rt_nexthops;
562 struct rtnl_rtcacheinfo rt_cacheinfo;
570 static int route_dump_env(struct nl_object *obj, struct nl_dump_params *p)
572 struct rtnl_route *route = (struct rtnl_route *) obj;
576 dp_dump_line(p, line++, "ROUTE_FAMILY=%s\n",
577 nl_af2str(route->rt_family, buf, sizeof(buf)));
579 if (route->rt_mask & ROUTE_ATTR_DST)
580 dp_dump_line(p, line++, "ROUTE_DST=%s\n",
581 nl_addr2str(route->rt_dst, buf, sizeof(buf)));
583 if (route->rt_mask & ROUTE_ATTR_DST_LEN)
584 dp_dump_line(p, line++, "ROUTE_DSTLEN=%u\n",
587 if (route->rt_mask & ROUTE_ATTR_SRC)
588 dp_dump_line(p, line++, "ROUTE_SRC=%s\n",
589 nl_addr2str(route->rt_src, buf, sizeof(buf)));
591 if (route->rt_mask & ROUTE_ATTR_SRC_LEN)
592 dp_dump_line(p, line++, "ROUTE_SRCLEN=%u\n",
595 if (route->rt_mask & ROUTE_ATTR_GATEWAY)
596 dp_dump_line(p, line++, "ROUTE_GATEWAY=%s\n",
597 nl_addr2str(route->rt_gateway, buf, sizeof(buf)));
599 if (route->rt_mask & ROUTE_ATTR_PREF_SRC)
600 dp_dump_line(p, line++, "ROUTE_PREFSRC=%s\n",
601 nl_addr2str(route->rt_pref_src, buf, sizeof(buf)));
603 if (route->rt_mask & ROUTE_ATTR_IIF)
604 dp_dump_line(p, line++, "ROUTE_IIF=%s\n", route->rt_iif);
606 if (route->rt_mask & ROUTE_ATTR_REALMS)
607 dp_dump_line(p, line++, "ROUTE_REALM=%u\n",
610 if (route->rt_mask & ROUTE_ATTR_TOS)
611 dp_dump_line(p, line++, "ROUTE_TOS=%u\n", route->rt_tos);
613 if (route->rt_mask & ROUTE_ATTR_TABLE)
614 dp_dump_line(p, line++, "ROUTE_TABLE=%u\n",
617 if (route->rt_mask & ROUTE_ATTR_SCOPE)
618 dp_dump_line(p, line++, "ROUTE_SCOPE=%s\n",
619 rtnl_scope2str(route->rt_scope, buf, sizeof(buf)));
621 if (route->rt_mask & ROUTE_ATTR_PRIO)
622 dp_dump_line(p, line++, "ROUTE_METRIC=%u\n",
625 if (route->rt_mask & ROUTE_ATTR_OIF) {
626 struct nl_cache *link_cache;
628 dp_dump_line(p, line++, "ROUTE_OIF_IFINDEX=%u\n",
631 link_cache = nl_cache_mngt_require("route/link");
633 dp_dump_line(p, line++, "ROUTE_OIF_IFNAME=%s\n",
634 rtnl_link_i2name(link_cache,
639 if (route->rt_mask & ROUTE_ATTR_TYPE)
640 dp_dump_line(p, line++, "ROUTE_TYPE=%s\n",
641 nl_rtntype2str(route->rt_type, buf, sizeof(buf)));
646 static int route_filter(struct nl_object *obj, struct nl_object *filter)
648 struct rtnl_route *o = (struct rtnl_route *) obj;
649 struct rtnl_route *f = (struct rtnl_route *) filter;
651 #define REQ(F) (f->rt_mask & ROUTE_ATTR_##F)
652 #define AVAIL(F) (o->rt_mask & ROUTE_ATTR_##F)
653 #define _O(F, EXPR) (REQ(F) && (!AVAIL(F) || (EXPR)))
654 #define _C(F, N) (REQ(F) && (!AVAIL(F) || (o->N != f->N)))
655 if (_C(FAMILY, rt_family) ||
656 _C(DST_LEN, rt_dst_len) ||
657 _C(SRC_LEN, rt_src_len) ||
659 _C(TABLE, rt_table) ||
660 _C(PROTOCOL, rt_protocol) ||
661 _C(SCOPE, rt_scope) ||
665 _C(REALMS, rt_realms) ||
666 _C(MP_ALGO, rt_mp_algo) ||
667 _O(DST, nl_addr_cmp(o->rt_dst, f->rt_dst)) ||
668 _O(SRC, nl_addr_cmp(o->rt_src, f->rt_src)) ||
669 _O(IIF, strcmp(o->rt_iif, f->rt_iif)) ||
670 _O(PREF_SRC, nl_addr_cmp(o->rt_pref_src, f->rt_pref_src)) ||
671 _O(GATEWAY, nl_addr_cmp(o->rt_gateway, f->rt_gateway)) ||
672 _O(FLAGS, f->rt_flags ^ (o->rt_flags & f->rt_flag_mask)))
681 for (i = 0; i < RTAX_MAX; i++) {
682 if (f->rt_metrics_mask & (1 << i)) {
683 if (!(o->rt_metrics_mask & (1 << i)) ||
684 f->rt_metrics[i+1] != o->rt_metrics[i+1])
690 if (REQ(MULTIPATH)) {
704 * @name Route Object Allocation/Freeage
709 * Allocate a new route object
710 * @return New route object
712 struct rtnl_route *rtnl_route_alloc(void)
714 return (struct rtnl_route *) nl_object_alloc_from_ops(&rtnl_route_ops);
719 * @arg route Route object to be freed.
721 * @note Always use rtnl_route_put() unless you're absolutely sure
722 * that no other user may have a reference on this object.
724 void rtnl_route_free(struct rtnl_route *route)
726 nl_object_free((struct nl_object *) route);
732 * @name Route Object Reference Counting
736 void rtnl_route_get(struct rtnl_route *route)
738 nl_object_get((struct nl_object *) route);
741 void rtnl_route_put(struct rtnl_route *route)
743 nl_object_put((struct nl_object *) route);
749 * @name Route Cache Management
754 * Build a route cache holding all routes currently configured in the kernel
755 * @arg handle netlink handle
757 * Allocates a new cache, initializes it properly and updates it to
758 * contain all routes currently configured in the kernel.
760 * @note The caller is responsible for destroying and freeing the
761 * cache after using it.
762 * @return The cache or NULL if an error has occured.
764 struct nl_cache *rtnl_route_alloc_cache(struct nl_handle *handle)
766 struct nl_cache *cache = nl_cache_alloc_from_ops(&rtnl_route_ops);
771 if (nl_cache_update(handle, cache) < 0) {
782 * @name Route Addition
786 static struct nl_msg *build_route_msg(struct rtnl_route *tmpl, int cmd,
791 struct rtmsg rtmsg = {
792 .rtm_family = tmpl->rt_family,
794 route->rt_dst_len = rtmsg->rtm_dst_len;
795 route->rt_src_len = rtmsg->rtm_src_len;
796 route->rt_tos = rtmsg->rtm_tos;
797 route->rt_table = rtmsg->rtm_table;
798 route->rt_type = rtmsg->rtm_type;
799 route->rt_scope = rtmsg->rtm_scope;
800 route->rt_protocol = rtmsg->rtm_protocol;
801 route->rt_flags = rtmsg->rtm_flags;
803 route->rt_mask = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_DST_LEN |
804 ROUTE_ATTR_SRC_LEN | ROUTE_ATTR_TABLE |
805 ROUTE_ATTR_PROTOCOL| ROUTE_ATTR_SCOPE |
806 ROUTE_ATTR_TYPE | ROUTE_ATTR_FLAGS);
808 msg = nlmsg_build_simple(cmd, flags);
812 if (nlmsg_append(msg, &rtmsg, sizeof(rtmsg), 1) < 0)
813 goto nla_put_failure;
815 NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst);
817 if (tmpl->n_mask & NEIGH_ATTR_LLADDR)
818 NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr);
831 * Build netlink request message to add a new route
832 * @arg tmpl template with data of new route
833 * @arg flags additional netlink message flags
835 * Builds a new netlink message requesting a addition of a new route.
836 * The netlink message header isn't fully equipped with all relevant
837 * fields and must thus be sent out via nl_send_auto_complete() or
838 * supplemented as needed. \a tmpl must contain the attributes of the
839 * new route set via \c rtnl_route_set_* functions.
841 * The following attributes must be set in the template:
842 * - Interface index (rtnl_neigh_set_ifindex())
843 * - State (rtnl_neigh_set_state())
844 * - Destination address (rtnl_neigh_set_dst())
845 * - Link layer address (rtnl_neigh_set_lladdr())
847 * @return The netlink message
849 struct nl_msg *rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags)
851 return build_route_msg(tmpl, RTM_NEWROUTE, NLM_F_CREATE | flags);
856 * @name Attribute: Routing Table
861 * Set the table of a route to the specified value
862 * @arg route route to be changed
863 * @arg table new table value
865 void rtnl_route_set_table(struct rtnl_route *route, int table)
867 route->rt_table = table;
868 route->rt_mask |= ROUTE_ATTR_TABLE;
872 * Get the table of a route
873 * @arg route route handle
874 * @return Table id or -1 if not set
876 int rtnl_route_get_table(struct rtnl_route *route)
878 if (route->rt_mask & ROUTE_ATTR_TABLE)
879 return route->rt_table;
886 * @name Attribute: Scope
891 * Set the scope of a route to the specified value
892 * @arg route route to be changed
893 * @arg scope new scope
895 void rtnl_route_set_scope(struct rtnl_route *route, int scope)
897 route->rt_scope = scope;
898 route->rt_mask |= ROUTE_ATTR_SCOPE;
902 * Get the scope of a route
903 * @arg route route handle
904 * @return Scope or -1 if not set
906 int rtnl_route_get_scope(struct rtnl_route *route)
908 if (route->rt_mask & ROUTE_ATTR_SCOPE)
909 return route->rt_scope;
916 * @name Attribute: Type Of Service
921 * Set the TOS of a route to the specified value
922 * @arg route route to be changed
923 * @arg tos new TOS value
925 void rtnl_route_set_tos(struct rtnl_route *route, int tos)
928 route->rt_mask |= ROUTE_ATTR_TOS;
932 * Get the TOS of a route
933 * @arg route route handle
934 * @return TOS value or -1 if not set
936 int rtnl_route_get_tos(struct rtnl_route *route)
938 if (route->rt_mask & ROUTE_ATTR_TOS)
939 return route->rt_tos;
946 * @name Attribute: Realm
951 * Set the realms of a route to the specified value
952 * @arg route route to be changed
953 * @arg realms New realms value.
955 void rtnl_route_set_realms(struct rtnl_route *route, realm_t realms)
957 route->rt_realms = realms;
958 route->rt_mask |= ROUTE_ATTR_REALMS;
962 * Get realms of route object.
963 * @arg route Route object.
964 * @return Realms value or 0 if not set.
966 realm_t rtnl_route_get_realms(struct rtnl_route *route)
968 if (route->rt_mask & ROUTE_ATTR_REALMS)
969 return route->rt_realms;
976 * @name Attribute: Routing Protocol
981 * Set the protocol of a route to the specified value
982 * @arg route route to be changed
983 * @arg proto new protocol
985 void rtnl_route_set_protocol(struct rtnl_route *route, int proto)
987 route->rt_protocol = proto;
988 route->rt_mask |= ROUTE_ATTR_PROTOCOL;
992 * Get the protocol of a route
993 * @arg route route handle
994 * @return Protocol number or -1 if not set
996 int rtnl_route_get_protocol(struct rtnl_route *route)
998 if (route->rt_mask & ROUTE_ATTR_PROTOCOL)
999 return route->rt_protocol;
1006 * @name Attribute: Priority/Metric
1011 * Set the priority of a route to the specified value
1012 * @arg route route to be changed
1013 * @arg prio new priority
1015 void rtnl_route_set_prio(struct rtnl_route *route, int prio)
1017 route->rt_prio = prio;
1018 route->rt_mask |= ROUTE_ATTR_PRIO;
1022 * Get the priority of a route
1023 * @arg route route handle
1024 * @return Priority or -1 if not set
1026 int rtnl_route_get_prio(struct rtnl_route *route)
1028 if (route->rt_mask & ROUTE_ATTR_PRIO)
1029 return route->rt_prio;
1036 * @name Attribute: Address Family
1041 * Set the address family of a route to the specified value
1042 * @arg route route to be changed
1043 * @arg family new address family
1045 void rtnl_route_set_family(struct rtnl_route *route, int family)
1047 route->rt_family = family;
1048 route->rt_mask |= ROUTE_ATTR_FAMILY;
1052 * Get the address family of a route
1053 * @arg route route handle
1054 * @return Address family or AF_UNSPEC if not set
1056 int rtnl_route_get_family(struct rtnl_route *route)
1058 if (route->rt_mask & ROUTE_ATTR_FAMILY)
1059 return route->rt_family;
1066 * @name Attribute: Destination Address
1071 * Set the destination address of a route to the specified address
1072 * @arg route route to be changed
1073 * @arg addr new destination address
1075 * Assigns the new destination address to the specified \a route,
1076 * overwrites the destination address length (rtnl_route::rt_dst_len),
1077 * and sets the route's address family to the new address's family if
1078 * it is not set already.
1080 * If a address family has been specified already via either calling
1081 * rtnl_route_set_family() or by setting one of the other addresses,
1082 * the specified \a addr is automatically validated against this family
1083 * and the assignment fails in case of a mismatch.
1085 * @return 0 on success or a negative error code.
1087 int rtnl_route_set_dst(struct rtnl_route *route, struct nl_addr *addr)
1089 if (route->rt_mask & ROUTE_ATTR_FAMILY) {
1090 if (addr->a_family != route->rt_family)
1091 return nl_error(EINVAL, "Address family mismatch");
1093 route->rt_family = addr->a_family;
1096 nl_addr_put(route->rt_dst);
1099 route->rt_dst = addr;
1101 route->rt_mask |= (ROUTE_ATTR_DST|ROUTE_ATTR_FAMILY|ROUTE_ATTR_DST_LEN);
1107 * Get the destination address of a route
1108 * @arg route route handle
1109 * @return Destination address or NULL if not set
1111 struct nl_addr *rtnl_route_get_dst(struct rtnl_route *route)
1113 if (route->rt_mask & ROUTE_ATTR_DST)
1114 return route->rt_dst;
1120 * Set the destination address prefix length of a route to the specified value
1121 * @arg route route to be changed
1122 * @arg prefix new destination address prefix
1123 * @attention The destination address prefix gets overwritten by calls
1124 * to rtnl_route_set_dst() rtnl_route_set_dst_str().
1126 void rtnl_route_set_dst_len(struct rtnl_route *route, int prefix)
1128 route->rt_dst_len = prefix;
1129 route->rt_mask |= ROUTE_ATTR_DST_LEN;
1133 * Get the destination address prefix length of a route
1134 * @arg route route handle
1135 * @return Prefix length or -1 if not set
1137 int rtnl_route_get_dst_len(struct rtnl_route *route)
1139 if (route->rt_mask & ROUTE_ATTR_DST_LEN)
1140 return route->rt_dst_len;
1147 * @name Attribute: Source Address
1152 * Set the source address of a route to the specified address
1153 * @arg route route to be changed
1154 * @arg addr new source address
1156 * Assigns the new source address to the specified \a route,
1157 * overwrites the source address length (rtnl_route::rt_src_len),
1158 * and sets the route's address family to the new address's family if
1159 * it is not set already.
1161 * If a address family has been specified already via either calling
1162 * rtnl_route_set_family() or by setting one of the other addresses,
1163 * the specified \a addr is automatically validated against this family
1164 * and the assignment fails in case of a mismatch.
1166 * @return 0 on success or a negative error code.
1168 int rtnl_route_set_src(struct rtnl_route *route, struct nl_addr *addr)
1170 if (route->rt_mask & ROUTE_ATTR_FAMILY) {
1171 if (addr->a_family != route->rt_family)
1172 return nl_error(EINVAL, "Address family mismatch");
1174 route->rt_family = addr->a_family;
1177 nl_addr_put(route->rt_src);
1180 route->rt_src = addr;
1181 route->rt_mask |= (ROUTE_ATTR_SRC|ROUTE_ATTR_FAMILY|ROUTE_ATTR_SRC_LEN);
1187 * Get the source address of a route
1188 * @arg route route handle
1189 * @return Source address or NULL if not set
1191 struct nl_addr *rtnl_route_get_src(struct rtnl_route *route)
1193 if (route->rt_mask & ROUTE_ATTR_SRC)
1194 return route->rt_src;
1200 * Set the source address prefix length of a route to the specified value
1201 * @arg route route to be changed
1202 * @arg prefix new source address prefix
1203 * @attention The source address prefix gets overwritten by calls
1204 * to rtnl_route_src_dst() rtnl_route_set_src_str().
1206 void rtnl_route_set_src_len(struct rtnl_route *route, int prefix)
1208 route->rt_dst_len = prefix;
1209 route->rt_mask |= ROUTE_ATTR_SRC_LEN;
1213 * Get the source address prefix length of a route
1214 * @arg route route handle
1215 * @return Prefix length or -1 if not set
1217 int rtnl_route_get_src_len(struct rtnl_route *route)
1219 if (route->rt_mask & ROUTE_ATTR_SRC_LEN)
1220 return route->rt_src_len;
1227 * @name Attribute: Gateway Address
1232 * Set the gateway address of a route to the specified address
1233 * @arg route route to be changed
1234 * @arg addr new gateway address
1236 * Assigns the new gateway address to the specified \a route,
1237 * and sets the route's address family to the new address's family if
1238 * it is not set already.
1240 * If a address family has been specified already via either calling
1241 * rtnl_route_set_family() or by setting one of the other addresses,
1242 * the specified \a addr is automatically validated against this family
1243 * and the assignment fails in case of a mismatch.
1245 * @return 0 on success or a negative error code.
1247 int rtnl_route_set_gateway(struct rtnl_route *route, struct nl_addr *addr)
1249 if (route->rt_mask & ROUTE_ATTR_FAMILY) {
1250 if (addr->a_family != route->rt_family)
1251 return nl_error(EINVAL, "Address family mismatch");
1253 route->rt_family = addr->a_family;
1255 if (route->rt_gateway)
1256 nl_addr_put(route->rt_gateway);
1259 route->rt_gateway = addr;
1260 route->rt_mask |= (ROUTE_ATTR_GATEWAY | ROUTE_ATTR_FAMILY);
1266 * Get the gateway address of a route
1267 * @arg route route handle
1268 * @return Gateway address or NULL if not set
1270 struct nl_addr *rtnl_route_get_gateway(struct rtnl_route *route)
1272 if (route->rt_mask & ROUTE_ATTR_GATEWAY)
1273 return route->rt_gateway;
1280 * @name Attribute: Type
1285 * Set the type of a route to the specified value
1286 * @arg route route to be changed
1287 * @arg type new route type
1289 void rtnl_route_set_type(struct rtnl_route *route, int type)
1291 route->rt_type = type;
1292 route->rt_mask |= ROUTE_ATTR_TYPE;
1296 * Get the type of a route
1297 * @arg route route handle
1298 * @return Type of route or -1 if not set
1300 int rtnl_route_get_type(struct rtnl_route *route)
1302 if (route->rt_mask & ROUTE_ATTR_TYPE)
1303 return route->rt_type;
1310 * @name Attribute: Flags
1315 * Add flags to a route
1316 * @arg route route to be changed
1317 * @arg flags flags to set
1319 void rtnl_route_set_flags(struct rtnl_route *route, unsigned int flags)
1321 route->rt_flag_mask |= flags;
1322 route->rt_flags |= flags;
1323 route->rt_mask |= ROUTE_ATTR_FLAGS;
1327 * Remove flags from a route
1328 * @arg route route to be changed
1329 * @arg flags flags to unset
1331 void rtnl_route_unset_flags(struct rtnl_route *route, unsigned int flags)
1333 route->rt_flag_mask |= flags;
1334 route->rt_flags &= ~flags;
1335 route->rt_mask |= ROUTE_ATTR_FLAGS;
1339 * Get flags of a route
1340 * @arg route route handle
1342 unsigned int rtnl_route_get_flags(struct rtnl_route *route)
1344 return route->rt_flags;
1349 * @name Attribute: Routing Metrics
1354 * Set a metric of a route to the specified value
1355 * @arg route route to be changed
1356 * @arg metric metric to be changed (see XXX)
1357 * @arg value new metric value
1358 * @return 0 on sucess or a negative error code
1360 int rtnl_route_set_metric(struct rtnl_route *route, int metric, uint32_t value)
1362 if (metric <= RTAX_MAX || metric < 1)
1363 return nl_error(EINVAL, "Metric out of range (1..%d)",
1366 route->rt_metrics[metric - 1] = value;
1367 route->rt_metrics_mask |= (1 << (metric - 1));
1373 * Unset a metric of a route
1374 * @arg route route to be changed
1375 * @arg metric metric to be unset (see XXX)
1376 * @return 0 on sucess or a negative error code
1378 int rtnl_route_unset_metric(struct rtnl_route *route, int metric)
1380 if (metric <= RTAX_MAX || metric < 1)
1381 return nl_error(EINVAL, "Metric out of range (1..%d)",
1384 route->rt_metrics_mask &= ~(1 << (metric - 1));
1390 * Get a metric for a route
1391 * @arg route route handle
1392 * @arg metric metric to get
1393 * @return The value for the specified metric or UINT_MAX if not set
1395 unsigned int rtnl_route_get_metric(struct rtnl_route *route, int metric)
1397 if (metric <= RTAX_MAX || metric < 1)
1400 if (!(route->rt_metrics_mask & (1 << (metric - 1))))
1403 return route->rt_metrics[metric - 1];
1408 * @name Attribute: Preferred Source Address
1413 * Set the preferred source address of a route to the specified address
1414 * @arg route route to be changed
1415 * @arg addr new preferred source address
1417 * Assigns the new preferred source address to the specified \a route,
1418 * and sets the route's address family to the new address's family if
1419 * it is not set already.
1421 * If a address family has been specified already via either calling
1422 * rtnl_route_set_family() or by setting one of the other addresses,
1423 * the specified \a addr is automatically validated against this family
1424 * and the assignment fails in case of a mismatch.
1426 * @return 0 on success or a negative error code.
1428 int rtnl_route_set_pref_src(struct rtnl_route *route, struct nl_addr *addr)
1430 if (route->rt_mask & ROUTE_ATTR_FAMILY) {
1431 if (addr->a_family != route->rt_family)
1432 return nl_error(EINVAL, "Address family mismatch");
1434 route->rt_family = addr->a_family;
1436 if (route->rt_pref_src)
1437 nl_addr_put(route->rt_pref_src);
1440 route->rt_pref_src = addr;
1441 route->rt_mask |= (ROUTE_ATTR_PREF_SRC | ROUTE_ATTR_FAMILY);
1447 * Get the preferred source address of a route
1448 * @arg route route handle
1449 * @return Preferred source address or NULL if not set
1451 struct nl_addr *rtnl_route_get_pref_src(struct rtnl_route *route)
1453 if (route->rt_mask & ROUTE_ATTR_PREF_SRC)
1454 return route->rt_pref_src;
1461 * @name Attribute: Outgoing Interface Index
1466 * Set the outgoing interface of a route to the specified value
1467 * @arg route route to be changed
1468 * @arg ifindex interface index of new outoing interface
1470 void rtnl_route_set_oif(struct rtnl_route *route, int ifindex)
1472 route->rt_oif = ifindex;
1473 route->rt_mask |= ROUTE_ATTR_OIF;
1477 * Get the outgoing interface index of a route
1478 * @arg route route handle
1479 * @return interface index or RTNL_LINK_NOT_FOUND if not set
1481 int rtnl_route_get_oif(struct rtnl_route *route)
1483 if (route->rt_mask & ROUTE_ATTR_OIF)
1484 return route->rt_oif;
1486 return RTNL_LINK_NOT_FOUND;
1491 * @name Attribute: Incoming Interface
1496 * Set the incoming interface of a route to the specified value
1497 * @arg route route to be changed
1498 * @arg name interface name of the new incoming interface
1500 void rtnl_route_set_iif(struct rtnl_route *route, const char *name)
1502 strncpy(route->rt_iif, name, sizeof(route->rt_iif) - 1);
1503 route->rt_mask |= ROUTE_ATTR_IIF;
1507 * Get the incomming interface name of a route
1508 * @arg route route handle
1509 * @return interface name or NULL if not set
1511 char *rtnl_route_get_iif(struct rtnl_route *route)
1513 if (route->rt_mask & ROUTE_ATTR_IIF)
1514 return route->rt_iif;
1520 struct rtnl_rtcacheinfo rt_cacheinfo;
1525 * @name Attribute: Nexthop
1529 void rtnl_route_add_nexthop(struct rtnl_route *route, struct rtnl_nexthop *nh)
1531 nl_list_add_tail(&nh->rtnh_list, &route->rt_nexthops);
1532 route->rt_mask |= ROUTE_ATTR_MULTIPATH;
1535 void rtnl_route_remove_nexthop(struct rtnl_nexthop *nh)
1537 nl_list_del(&nh->rtnh_list);
1540 struct nl_list_head *rtnl_route_get_nexthops(struct rtnl_route *route)
1542 return &route->rt_nexthops;
1548 * @name Routing Table Identifier Translations
1552 static struct trans_tbl route_tables[] = {
1553 __ADD(RT_TABLE_UNSPEC, unspec)
1554 __ADD(RT_TABLE_DEFAULT, default)
1555 __ADD(RT_TABLE_MAIN, main)
1556 __ADD(RT_TABLE_LOCAL, local)
1560 * Convert routing table identifier to character string.
1561 * @arg table Routing table identifier.
1562 * @arg buf Destination buffer
1563 * @arg size Size of destination buffer.
1565 * Converts a routing table identifier to a character string and stores
1566 * it in the specified destination buffer.
1568 * @return The destination buffer or the type encoded in hexidecimal
1569 * form if the routing table identifier is unknown.
1571 char *rtnl_route_table2str(int table, char *buf, size_t size)
1573 return __type2str(table, buf, size, route_tables,
1574 ARRAY_SIZE(route_tables));
1578 * Convert character string to routing table identifier.
1579 * @arg name Name of routing table.
1581 * Converts the provided character string specifying a routing table
1582 * identifier to the corresponding numeric value.
1584 * @return Routing table identifier or a negative value if no match was found.
1586 int rtnl_route_str2table(const char *name)
1588 return __str2type(name, route_tables, ARRAY_SIZE(route_tables));
1595 * @name Routing Protocol Translations
1599 static struct trans_tbl route_protos[] = {
1600 __ADD(RTPROT_UNSPEC, unspec)
1601 __ADD(RTPROT_REDIRECT, redirect)
1602 __ADD(RTPROT_KERNEL, kernel)
1603 __ADD(RTPROT_BOOT, boot)
1604 __ADD(RTPROT_STATIC, static)
1608 * Convert routing protocol identifier to character string.
1609 * @arg proto Routing protocol identifier.
1610 * @arg buf Destination buffer
1611 * @arg size Size of destination buffer.
1613 * Converts a routing protocol identifier to a character string and stores
1614 * it in the specified destination buffer.
1616 * @return The destination buffer or the protocol encoded in hexidecimal
1617 * form if the routing protocol is unknown.
1619 char *rtnl_route_proto2str(int proto, char *buf, size_t size)
1621 return __type2str(proto, buf, size, route_protos,
1622 ARRAY_SIZE(route_protos));
1626 * Convert character string to routing protocol identifier.
1627 * @arg name Name of routing protocol.
1629 * Converts the provided character string specifying a routing protocl
1630 * identifier to the corresponding numeric value.
1632 * @return Routing protocol dentifier or a negative value if no match was found.
1634 int rtnl_route_str2proto(const char *name)
1636 return __str2type(name, route_protos, ARRAY_SIZE(route_protos));
1642 * @name Routing Metrices Translations
1646 static struct trans_tbl route_metrices[] = {
1647 __ADD(RTAX_UNSPEC, unspec)
1648 __ADD(RTAX_LOCK, lock)
1649 __ADD(RTAX_MTU, mtu)
1650 __ADD(RTAX_WINDOW, window)
1651 __ADD(RTAX_RTT, rtt)
1652 __ADD(RTAX_RTTVAR, rttvar)
1653 __ADD(RTAX_SSTHRESH, ssthresh)
1654 __ADD(RTAX_CWND, cwnd)
1655 __ADD(RTAX_ADVMSS, advmss)
1656 __ADD(RTAX_REORDERING, reordering)
1657 __ADD(RTAX_HOPLIMIT, hoplimit)
1658 __ADD(RTAX_INITCWND, initcwnd)
1659 __ADD(RTAX_FEATURES, features)
1663 * Convert routing metric identifier to character string.
1664 * @arg metric Routing metric identifier.
1665 * @arg buf Destination buffer
1666 * @arg size Size of destination buffer.
1668 * Converts a routing metric identifier to a character string and stores
1669 * it in the specified destination buffer.
1671 * @return The destination buffer or the metric encoded in hexidecimal
1672 * form if the routing metric identifier is unknown.
1674 char *rtnl_route_metric2str(int metric, char *buf, size_t size)
1676 return __type2str(metric, buf, size, route_metrices,
1677 ARRAY_SIZE(route_metrices));
1681 * Convert character string to routing metric identifier.
1682 * @arg name Name of routing metric.
1684 * Converts the provided character string specifying a routing metric
1685 * identifier to the corresponding numeric value.
1687 * @return Routing metric dentifier or a negative value if no match was found.
1689 int rtnl_route_str2metric(const char *name)
1691 return __str2type(name, route_metrices, ARRAY_SIZE(route_metrices));
1697 * @name Nexthop Flags Translations
1701 static struct trans_tbl nh_flags[] = {
1702 __ADD(RTNH_F_DEAD, dead)
1703 __ADD(RTNH_F_PERVASIVE, pervasive)
1704 __ADD(RTNH_F_ONLINK, onlink)
1708 * Convert nexthop flags to a character string.
1709 * @arg flags Nexthop flags.
1710 * @arg buf Destination buffer.
1711 * @arg len Length of destination buffer.
1713 * Converts nexthop flags to a character string separated by
1714 * commas and stores it in the specified destination buffer.
1716 * \return The destination buffer
1718 char * rtnl_route_nh_flags2str(int flags, char *buf, size_t len)
1720 return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags));
1724 * Convert a character string to a nexthop flag
1725 * @arg name Name of nexthop flag.
1727 * Converts the provided character string specifying a nexthop
1728 * flag to the corresponding numeric value.
1730 * \return Nexthop flag or a negative value if none was found.
1732 int rtnl_route_nh_str2flags(const char *name)
1734 return __str2flags(name, nh_flags, ARRAY_SIZE(nh_flags));
1739 static struct nl_cache_ops rtnl_route_ops = {
1740 .co_name = "route/route",
1741 .co_size = sizeof(struct rtnl_route),
1742 .co_hdrsize = sizeof(struct rtmsg),
1744 { RTM_NEWROUTE, "new" },
1745 { RTM_DELROUTE, "delete" },
1746 { RTM_GETROUTE, "get" },
1749 .co_protocol = NETLINK_ROUTE,
1750 .co_request_update = route_request_update,
1751 .co_msg_parser = route_msg_parser,
1752 .co_constructor = route_constructor,
1753 .co_free_data = route_free_data,
1754 .co_dump[NL_DUMP_BRIEF] = route_dump_brief,
1755 .co_dump[NL_DUMP_FULL] = route_dump_full,
1756 .co_dump[NL_DUMP_STATS] = route_dump_stats,
1757 .co_dump[NL_DUMP_XML] = route_dump_xml,
1758 .co_dump[NL_DUMP_ENV] = route_dump_env,
1759 .co_filter = route_filter,
1762 static void __init route_init(void)
1764 nl_cache_mngt_register(&rtnl_route_ops);
1767 static void __exit route_exit(void)
1769 nl_cache_mngt_unregister(&rtnl_route_ops);