36 #include <netlink-local.h>
37 #include <netlink/netlink.h>
38 #include <netlink/cache.h>
39 #include <netlink/utils.h>
40 #include <netlink/data.h>
41 #include <netlink/route/rtnl.h>
42 #include <netlink/route/route.h>
43 #include <netlink/route/link.h>
46 #define ROUTE_ATTR_FAMILY 0x000001
47 #define ROUTE_ATTR_TOS 0x000002
48 #define ROUTE_ATTR_TABLE 0x000004
49 #define ROUTE_ATTR_PROTOCOL 0x000008
50 #define ROUTE_ATTR_SCOPE 0x000010
51 #define ROUTE_ATTR_TYPE 0x000020
52 #define ROUTE_ATTR_FLAGS 0x000040
53 #define ROUTE_ATTR_DST 0x000080
54 #define ROUTE_ATTR_SRC 0x000100
55 #define ROUTE_ATTR_IIF 0x000200
56 #define ROUTE_ATTR_OIF 0x000400
57 #define ROUTE_ATTR_GATEWAY 0x000800
58 #define ROUTE_ATTR_PRIO 0x001000
59 #define ROUTE_ATTR_PREF_SRC 0x002000
60 #define ROUTE_ATTR_METRICS 0x004000
61 #define ROUTE_ATTR_MULTIPATH 0x008000
62 #define ROUTE_ATTR_REALMS 0x010000
63 #define ROUTE_ATTR_CACHEINFO 0x020000
64 #define ROUTE_ATTR_MP_ALGO 0x040000
67 static int route_dump_brief(
struct nl_object *a,
struct nl_dump_params *p);
69 static void route_constructor(
struct nl_object *c)
71 struct rtnl_route *r = (
struct rtnl_route *) c;
73 nl_init_list_head(&r->rt_nexthops);
76 static void route_free_data(
struct nl_object *c)
78 struct rtnl_route *r = (
struct rtnl_route *) c;
79 struct rtnl_nexthop *nh, *tmp;
84 nl_addr_put(r->rt_dst);
85 nl_addr_put(r->rt_src);
86 nl_addr_put(r->rt_gateway);
87 nl_addr_put(r->rt_pref_src);
89 nl_list_for_each_entry_safe(nh, tmp, &r->rt_nexthops, rtnh_list) {
90 rtnl_route_remove_nexthop(nh);
91 rtnl_route_nh_free(nh);
95 static int route_clone(
struct nl_object *_dst,
struct nl_object *_src)
97 struct rtnl_route *dst = (
struct rtnl_route *) _dst;
98 struct rtnl_route *src = (
struct rtnl_route *) _src;
99 struct rtnl_nexthop *nh, *
new;
113 if (src->rt_pref_src)
117 nl_init_list_head(&dst->rt_nexthops);
118 nl_list_for_each_entry(nh, &src->rt_nexthops, rtnh_list) {
119 new = rtnl_route_nh_clone(nh);
123 rtnl_route_add_nexthop(dst,
new);
128 return nl_get_errno();
131 static int route_dump_brief(
struct nl_object *a,
struct nl_dump_params *p)
133 struct rtnl_route *r = (
struct rtnl_route *) a;
134 struct nl_cache *link_cache;
139 if (!(r->ce_mask & ROUTE_ATTR_DST) ||
141 dp_dump(p,
"default ");
143 dp_dump(p,
"%s ",
nl_addr2str(r->rt_dst, buf,
sizeof(buf)));
145 if (r->ce_mask & ROUTE_ATTR_OIF) {
147 dp_dump(p,
"dev %s ",
151 dp_dump(p,
"dev %d ", r->rt_oif);
154 if (r->ce_mask & ROUTE_ATTR_GATEWAY)
155 dp_dump(p,
"via %s ",
nl_addr2str(r->rt_gateway, buf,
157 else if (r->ce_mask & ROUTE_ATTR_MULTIPATH)
158 dp_dump(p,
"via nexthops ");
160 if (r->ce_mask & ROUTE_ATTR_SCOPE)
161 dp_dump(p,
"scope %s ",
162 rtnl_scope2str(r->rt_scope, buf,
sizeof(buf)));
164 if (r->ce_mask & ROUTE_ATTR_FLAGS && r->rt_flags) {
165 int flags = r->rt_flags;
169 #define PRINT_FLAG(f) if (flags & RTNH_F_##f) { \
170 flags &= ~RTNH_F_##f; dp_dump(p, #f "%s", flags ? "," : ""); }
173 PRINT_FLAG(PERVASIVE);
176 #define PRINT_FLAG(f) if (flags & RTM_F_##f) { \
177 flags &= ~RTM_F_##f; dp_dump(p, #f "%s", flags ? "," : ""); }
180 PRINT_FLAG(EQUALIZE);
192 static int route_dump_full(
struct nl_object *a,
struct nl_dump_params *p)
194 struct rtnl_route *r = (
struct rtnl_route *) a;
195 struct nl_cache *link_cache;
200 line = route_dump_brief(a, p);
202 if (r->ce_mask & ROUTE_ATTR_MULTIPATH) {
203 struct rtnl_nexthop *nh;
205 nl_list_for_each_entry(nh, &r->rt_nexthops, rtnh_list) {
206 dp_dump_line(p, line++,
" via ");
208 if (nh->rtnh_mask & NEXTHOP_HAS_GATEWAY)
213 dp_dump(p,
"dev %s ",
218 dp_dump(p,
"dev %d ", nh->rtnh_ifindex);
220 dp_dump(p,
"weight %u <%s>\n", nh->rtnh_weight,
221 rtnl_route_nh_flags2str(nh->rtnh_flags,
226 dp_dump_line(p, line++,
" ");
228 if (r->ce_mask & ROUTE_ATTR_PREF_SRC)
229 dp_dump(p,
"preferred-src %s ",
232 if (r->ce_mask & ROUTE_ATTR_TABLE)
233 dp_dump(p,
"table %s ",
234 rtnl_route_table2str(r->rt_table, buf,
sizeof(buf)));
236 if (r->ce_mask & ROUTE_ATTR_TYPE)
237 dp_dump(p,
"type %s ",
238 nl_rtntype2str(r->rt_type, buf,
sizeof(buf)));
240 if (r->ce_mask & ROUTE_ATTR_PRIO)
241 dp_dump(p,
"metric %#x ", r->rt_prio);
243 if (r->ce_mask & ROUTE_ATTR_FAMILY)
244 dp_dump(p,
"family %s ",
245 nl_af2str(r->rt_family, buf,
sizeof(buf)));
247 if (r->ce_mask & ROUTE_ATTR_PROTOCOL)
248 dp_dump(p,
"protocol %s ",
249 rtnl_route_proto2str(r->rt_protocol, buf,
sizeof(buf)));
253 if ((r->ce_mask & (ROUTE_ATTR_IIF | ROUTE_ATTR_SRC | ROUTE_ATTR_TOS |
254 ROUTE_ATTR_REALMS)) ||
255 ((r->ce_mask & ROUTE_ATTR_CACHEINFO) &&
256 r->rt_cacheinfo.rtci_error)) {
257 dp_dump_line(p, line++,
" ");
259 if (r->ce_mask & ROUTE_ATTR_IIF)
260 dp_dump(p,
"iif %s ", r->rt_iif);
262 if (r->ce_mask & ROUTE_ATTR_SRC)
263 dp_dump(p,
"src %s ",
266 if (r->ce_mask & ROUTE_ATTR_TOS)
267 dp_dump(p,
"tos %#x ", r->rt_tos);
269 if (r->ce_mask & ROUTE_ATTR_REALMS)
270 dp_dump(p,
"realm %04x:%04x ",
274 if ((r->ce_mask & ROUTE_ATTR_CACHEINFO) &&
275 r->rt_cacheinfo.rtci_error)
276 dp_dump(p,
"error %d (%s) ", r->rt_cacheinfo.rtci_error,
277 strerror(-r->rt_cacheinfo.rtci_error));
282 if (r->ce_mask & ROUTE_ATTR_METRICS) {
283 dp_dump_line(p, line++,
" ");
284 for (i = 0; i < RTAX_MAX; i++)
285 if (r->rt_metrics_mask & (1 << i))
287 rtnl_route_metric2str(i+1,
296 static int route_dump_stats(
struct nl_object *obj,
struct nl_dump_params *p)
298 struct rtnl_route *route = (
struct rtnl_route *) obj;
301 line = route_dump_full(obj, p);
303 if (route->ce_mask & ROUTE_ATTR_CACHEINFO) {
305 dp_dump_line(p, line++,
" used %u refcnt %u ",
306 ci->rtci_used, ci->rtci_clntref);
307 dp_dump_line(p, line++,
"last-use %us expires %us\n",
315 static int route_dump_xml(
struct nl_object *obj,
struct nl_dump_params *p)
317 struct rtnl_route *route = (
struct rtnl_route *) obj;
321 dp_dump_line(p, line++,
"<route>\n");
322 dp_dump_line(p, line++,
" <family>%s</family>\n",
323 nl_af2str(route->rt_family, buf,
sizeof(buf)));
325 if (route->ce_mask & ROUTE_ATTR_DST)
326 dp_dump_line(p, line++,
" <dst>%s</dst>\n",
329 if (route->ce_mask & ROUTE_ATTR_SRC)
330 dp_dump_line(p, line++,
" <src>%s</src>\n",
333 if (route->ce_mask & ROUTE_ATTR_GATEWAY)
334 dp_dump_line(p, line++,
" <gateway>%s</gateway>\n",
337 if (route->ce_mask & ROUTE_ATTR_PREF_SRC)
338 dp_dump_line(p, line++,
" <prefsrc>%s</prefsrc>\n",
339 nl_addr2str(route->rt_pref_src, buf,
sizeof(buf)));
341 if (route->ce_mask & ROUTE_ATTR_IIF)
342 dp_dump_line(p, line++,
" <iif>%s</iif>\n", route->rt_iif);
344 if (route->ce_mask & ROUTE_ATTR_REALMS)
345 dp_dump_line(p, line++,
" <realms>%u</realms>\n",
348 if (route->ce_mask & ROUTE_ATTR_TOS)
349 dp_dump_line(p, line++,
" <tos>%u</tos>\n", route->rt_tos);
351 if (route->ce_mask & ROUTE_ATTR_TABLE)
352 dp_dump_line(p, line++,
" <table>%u</table>\n",
355 if (route->ce_mask & ROUTE_ATTR_SCOPE)
356 dp_dump_line(p, line++,
" <scope>%s</scope>\n",
357 rtnl_scope2str(route->rt_scope, buf,
sizeof(buf)));
359 if (route->ce_mask & ROUTE_ATTR_PRIO)
360 dp_dump_line(p, line++,
" <metric>%u</metric>\n",
363 if (route->ce_mask & ROUTE_ATTR_OIF) {
364 struct nl_cache *link_cache;
368 dp_dump_line(p, line++,
" <oif>%s</oif>\n",
373 dp_dump_line(p, line++,
" <oif>%u</oif>\n",
377 if (route->ce_mask & ROUTE_ATTR_TYPE)
378 dp_dump_line(p, line++,
" <type>%s</type>\n",
379 nl_rtntype2str(route->rt_type, buf,
sizeof(buf)));
381 dp_dump_line(p, line++,
"</route>\n");
386 uint32_t rt_metrics[RTAX_MAX];
387 uint32_t rt_metrics_mask;
388 struct rtnl_nexthop * rt_nexthops;
397 static int route_dump_env(
struct nl_object *obj,
struct nl_dump_params *p)
399 struct rtnl_route *route = (
struct rtnl_route *) obj;
403 dp_dump_line(p, line++,
"ROUTE_FAMILY=%s\n",
404 nl_af2str(route->rt_family, buf,
sizeof(buf)));
406 if (route->ce_mask & ROUTE_ATTR_DST)
407 dp_dump_line(p, line++,
"ROUTE_DST=%s\n",
410 if (route->ce_mask & ROUTE_ATTR_SRC)
411 dp_dump_line(p, line++,
"ROUTE_SRC=%s\n",
414 if (route->ce_mask & ROUTE_ATTR_GATEWAY)
415 dp_dump_line(p, line++,
"ROUTE_GATEWAY=%s\n",
418 if (route->ce_mask & ROUTE_ATTR_PREF_SRC)
419 dp_dump_line(p, line++,
"ROUTE_PREFSRC=%s\n",
420 nl_addr2str(route->rt_pref_src, buf,
sizeof(buf)));
422 if (route->ce_mask & ROUTE_ATTR_IIF)
423 dp_dump_line(p, line++,
"ROUTE_IIF=%s\n", route->rt_iif);
425 if (route->ce_mask & ROUTE_ATTR_REALMS)
426 dp_dump_line(p, line++,
"ROUTE_REALM=%u\n",
429 if (route->ce_mask & ROUTE_ATTR_TOS)
430 dp_dump_line(p, line++,
"ROUTE_TOS=%u\n", route->rt_tos);
432 if (route->ce_mask & ROUTE_ATTR_TABLE)
433 dp_dump_line(p, line++,
"ROUTE_TABLE=%u\n",
436 if (route->ce_mask & ROUTE_ATTR_SCOPE)
437 dp_dump_line(p, line++,
"ROUTE_SCOPE=%s\n",
438 rtnl_scope2str(route->rt_scope, buf,
sizeof(buf)));
440 if (route->ce_mask & ROUTE_ATTR_PRIO)
441 dp_dump_line(p, line++,
"ROUTE_METRIC=%u\n",
444 if (route->ce_mask & ROUTE_ATTR_OIF) {
445 struct nl_cache *link_cache;
447 dp_dump_line(p, line++,
"ROUTE_OIF_IFINDEX=%u\n",
452 dp_dump_line(p, line++,
"ROUTE_OIF_IFNAME=%s\n",
458 if (route->ce_mask & ROUTE_ATTR_TYPE)
459 dp_dump_line(p, line++,
"ROUTE_TYPE=%s\n",
460 nl_rtntype2str(route->rt_type, buf,
sizeof(buf)));
465 static int route_compare(
struct nl_object *_a,
struct nl_object *_b,
466 uint32_t attrs,
int flags)
468 struct rtnl_route *a = (
struct rtnl_route *) _a;
469 struct rtnl_route *b = (
struct rtnl_route *) _b;
472 #define ROUTE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ROUTE_ATTR_##ATTR, a, b, EXPR)
474 diff |= ROUTE_DIFF(FAMILY, a->rt_family != b->rt_family);
475 diff |= ROUTE_DIFF(TOS, a->rt_tos != b->rt_tos);
476 diff |= ROUTE_DIFF(TABLE, a->rt_table != b->rt_table);
477 diff |= ROUTE_DIFF(PROTOCOL, a->rt_protocol != b->rt_protocol);
478 diff |= ROUTE_DIFF(SCOPE, a->rt_scope != b->rt_scope);
479 diff |= ROUTE_DIFF(TYPE, a->rt_type != b->rt_type);
480 diff |= ROUTE_DIFF(OIF, a->rt_oif != b->rt_oif);
481 diff |= ROUTE_DIFF(PRIO, a->rt_prio != b->rt_prio);
482 diff |= ROUTE_DIFF(REALMS, a->rt_realms != b->rt_realms);
483 diff |= ROUTE_DIFF(MP_ALGO, a->rt_mp_algo != b->rt_mp_algo);
484 diff |= ROUTE_DIFF(DST,
nl_addr_cmp(a->rt_dst, b->rt_dst));
485 diff |= ROUTE_DIFF(SRC,
nl_addr_cmp(a->rt_src, b->rt_src));
486 diff |= ROUTE_DIFF(IIF, strcmp(a->rt_iif, b->rt_iif));
487 diff |= ROUTE_DIFF(PREF_SRC,
nl_addr_cmp(a->rt_pref_src,
489 diff |= ROUTE_DIFF(GATEWAY,
nl_addr_cmp(a->rt_gateway,
494 if (flags & LOOSE_FLAG_COMPARISON)
495 diff |= ROUTE_DIFF(FLAGS,
496 (a->rt_flags ^ b->rt_flags) & b->rt_flag_mask);
498 diff |= ROUTE_DIFF(FLAGS, a->rt_flags != b->rt_flags);
505 static struct trans_tbl route_attrs[] = {
506 __ADD(ROUTE_ATTR_FAMILY, family)
507 __ADD(ROUTE_ATTR_TOS, tos)
508 __ADD(ROUTE_ATTR_TABLE, table)
509 __ADD(ROUTE_ATTR_PROTOCOL, protocol)
510 __ADD(ROUTE_ATTR_SCOPE, scope)
511 __ADD(ROUTE_ATTR_TYPE, type)
512 __ADD(ROUTE_ATTR_FLAGS, flags)
513 __ADD(ROUTE_ATTR_DST, dst)
514 __ADD(ROUTE_ATTR_SRC, src)
515 __ADD(ROUTE_ATTR_IIF, iif)
516 __ADD(ROUTE_ATTR_OIF, oif)
517 __ADD(ROUTE_ATTR_GATEWAY, gateway)
518 __ADD(ROUTE_ATTR_PRIO, prio)
519 __ADD(ROUTE_ATTR_PREF_SRC, pref_src)
520 __ADD(ROUTE_ATTR_METRICS, metrics)
521 __ADD(ROUTE_ATTR_MULTIPATH, multipath)
522 __ADD(ROUTE_ATTR_REALMS, realms)
523 __ADD(ROUTE_ATTR_CACHEINFO, cacheinfo)
524 __ADD(ROUTE_ATTR_MP_ALGO, mp_algo)
527 static
char *route_attrs2str(
int attrs,
char *buf,
size_t len)
529 return __flags2str(attrs, buf, len, route_attrs,
530 ARRAY_SIZE(route_attrs));
538 struct rtnl_route *rtnl_route_alloc(
void)
543 void rtnl_route_get(
struct rtnl_route *route)
548 void rtnl_route_put(
struct rtnl_route *route)
560 void rtnl_route_set_table(
struct rtnl_route *route,
int table)
562 route->rt_table = table;
563 route->ce_mask |= ROUTE_ATTR_TABLE;
566 int rtnl_route_get_table(
struct rtnl_route *route)
568 if (route->ce_mask & ROUTE_ATTR_TABLE)
569 return route->rt_table;
571 return RT_TABLE_MAIN;
574 void rtnl_route_set_scope(
struct rtnl_route *route,
int scope)
576 route->rt_scope = scope;
577 route->ce_mask |= ROUTE_ATTR_SCOPE;
580 int rtnl_route_get_scope(
struct rtnl_route *route)
582 if (route->ce_mask & ROUTE_ATTR_SCOPE)
583 return route->rt_scope;
585 return RT_SCOPE_NOWHERE;
588 void rtnl_route_set_tos(
struct rtnl_route *route,
int tos)
591 route->ce_mask |= ROUTE_ATTR_TOS;
594 int rtnl_route_get_tos(
struct rtnl_route *route)
596 return route->rt_tos;
599 void rtnl_route_set_realms(
struct rtnl_route *route, realm_t realms)
601 route->rt_realms = realms;
602 route->ce_mask |= ROUTE_ATTR_REALMS;
605 realm_t rtnl_route_get_realms(
struct rtnl_route *route)
607 return route->rt_realms;
610 void rtnl_route_set_protocol(
struct rtnl_route *route,
int proto)
612 route->rt_protocol = proto;
613 route->ce_mask |= ROUTE_ATTR_PROTOCOL;
616 int rtnl_route_get_protocol(
struct rtnl_route *route)
618 if (route->ce_mask & ROUTE_ATTR_PROTOCOL)
619 return route->rt_protocol;
621 return RTPROT_STATIC;
624 void rtnl_route_set_prio(
struct rtnl_route *route,
int prio)
626 route->rt_prio = prio;
627 route->ce_mask |= ROUTE_ATTR_PRIO;
630 int rtnl_route_get_prio(
struct rtnl_route *route)
632 return route->rt_prio;
635 void rtnl_route_set_family(
struct rtnl_route *route,
int family)
637 route->rt_family = family;
638 route->ce_mask |= ROUTE_ATTR_FAMILY;
641 int rtnl_route_get_family(
struct rtnl_route *route)
643 if (route->ce_mask & ROUTE_ATTR_FAMILY)
644 return route->rt_family;
649 int rtnl_route_set_dst(
struct rtnl_route *route,
struct nl_addr *addr)
651 if (route->ce_mask & ROUTE_ATTR_FAMILY) {
652 if (addr->a_family != route->rt_family)
653 return nl_error(EINVAL,
"Address family mismatch");
655 route->rt_family = addr->a_family;
658 nl_addr_put(route->rt_dst);
661 route->rt_dst = addr;
663 route->ce_mask |= (ROUTE_ATTR_DST | ROUTE_ATTR_FAMILY);
668 struct nl_addr *rtnl_route_get_dst(
struct rtnl_route *route)
670 return route->rt_dst;
673 int rtnl_route_get_dst_len(
struct rtnl_route *route)
675 if (route->ce_mask & ROUTE_ATTR_DST)
681 int rtnl_route_set_src(
struct rtnl_route *route,
struct nl_addr *addr)
683 if (route->ce_mask & ROUTE_ATTR_FAMILY) {
684 if (addr->a_family != route->rt_family)
685 return nl_error(EINVAL,
"Address family mismatch");
687 route->rt_family = addr->a_family;
690 nl_addr_put(route->rt_src);
693 route->rt_src = addr;
694 route->ce_mask |= (ROUTE_ATTR_SRC | ROUTE_ATTR_FAMILY);
699 struct nl_addr *rtnl_route_get_src(
struct rtnl_route *route)
701 return route->rt_src;
704 int rtnl_route_get_src_len(
struct rtnl_route *route)
706 if (route->ce_mask & ROUTE_ATTR_SRC)
712 int rtnl_route_set_gateway(
struct rtnl_route *route,
struct nl_addr *addr)
714 if (route->ce_mask & ROUTE_ATTR_FAMILY) {
715 if (addr->a_family != route->rt_family)
716 return nl_error(EINVAL,
"Address family mismatch");
718 route->rt_family = addr->a_family;
720 if (route->rt_gateway)
721 nl_addr_put(route->rt_gateway);
724 route->rt_gateway = addr;
725 route->ce_mask |= (ROUTE_ATTR_GATEWAY | ROUTE_ATTR_FAMILY);
730 struct nl_addr *rtnl_route_get_gateway(
struct rtnl_route *route)
732 return route->rt_gateway;
735 void rtnl_route_set_type(
struct rtnl_route *route,
int type)
737 route->rt_type = type;
738 route->ce_mask |= ROUTE_ATTR_TYPE;
741 int rtnl_route_get_type(
struct rtnl_route *route)
743 if (route->ce_mask & ROUTE_ATTR_TYPE)
744 return route->rt_type;
749 void rtnl_route_set_flags(
struct rtnl_route *route,
unsigned int flags)
751 route->rt_flag_mask |= flags;
752 route->rt_flags |= flags;
753 route->ce_mask |= ROUTE_ATTR_FLAGS;
756 void rtnl_route_unset_flags(
struct rtnl_route *route,
unsigned int flags)
758 route->rt_flag_mask |= flags;
759 route->rt_flags &= ~flags;
760 route->ce_mask |= ROUTE_ATTR_FLAGS;
763 unsigned int rtnl_route_get_flags(
struct rtnl_route *route)
765 return route->rt_flags;
768 int rtnl_route_set_metric(
struct rtnl_route *route,
int metric, uint32_t value)
770 if (metric > RTAX_MAX || metric < 1)
771 return nl_error(EINVAL,
"Metric out of range (1..%d)",
774 route->rt_metrics[metric - 1] = value;
775 route->rt_metrics_mask |= (1 << (metric - 1));
780 int rtnl_route_unset_metric(
struct rtnl_route *route,
int metric)
782 if (metric > RTAX_MAX || metric < 1)
783 return nl_error(EINVAL,
"Metric out of range (1..%d)",
786 route->rt_metrics_mask &= ~(1 << (metric - 1));
791 unsigned int rtnl_route_get_metric(
struct rtnl_route *route,
int metric)
793 if (metric > RTAX_MAX || metric < 1)
796 if (!(route->rt_metrics_mask & (1 << (metric - 1))))
799 return route->rt_metrics[metric - 1];
802 int rtnl_route_set_pref_src(
struct rtnl_route *route,
struct nl_addr *addr)
804 if (route->ce_mask & ROUTE_ATTR_FAMILY) {
805 if (addr->a_family != route->rt_family)
806 return nl_error(EINVAL,
"Address family mismatch");
808 route->rt_family = addr->a_family;
810 if (route->rt_pref_src)
811 nl_addr_put(route->rt_pref_src);
814 route->rt_pref_src = addr;
815 route->ce_mask |= (ROUTE_ATTR_PREF_SRC | ROUTE_ATTR_FAMILY);
820 struct nl_addr *rtnl_route_get_pref_src(
struct rtnl_route *route)
822 return route->rt_pref_src;
825 void rtnl_route_set_oif(
struct rtnl_route *route,
int ifindex)
827 route->rt_oif = ifindex;
828 route->ce_mask |= ROUTE_ATTR_OIF;
831 int rtnl_route_get_oif(
struct rtnl_route *route)
833 if (route->ce_mask & ROUTE_ATTR_OIF)
834 return route->rt_oif;
839 void rtnl_route_set_iif(
struct rtnl_route *route,
const char *name)
841 strncpy(route->rt_iif, name,
sizeof(route->rt_iif) - 1);
842 route->ce_mask |= ROUTE_ATTR_IIF;
845 char *rtnl_route_get_iif(
struct rtnl_route *route)
847 if (route->ce_mask & ROUTE_ATTR_IIF)
848 return route->rt_iif;
853 void rtnl_route_add_nexthop(
struct rtnl_route *route,
struct rtnl_nexthop *nh)
855 nl_list_add_tail(&nh->rtnh_list, &route->rt_nexthops);
856 route->ce_mask |= ROUTE_ATTR_MULTIPATH;
859 void rtnl_route_remove_nexthop(
struct rtnl_nexthop *nh)
861 nl_list_del(&nh->rtnh_list);
864 struct nl_list_head *rtnl_route_get_nexthops(
struct rtnl_route *route)
866 return &route->rt_nexthops;
869 void rtnl_route_set_cacheinfo(
struct rtnl_route *route,
872 memcpy(&route->rt_cacheinfo, ci,
sizeof(*ci));
873 route->ce_mask |= ROUTE_ATTR_CACHEINFO;
876 uint32_t rtnl_route_get_mp_algo(
struct rtnl_route *route)
878 if (route->ce_mask & ROUTE_ATTR_MP_ALGO)
879 return route->rt_mp_algo;
881 return IP_MP_ALG_NONE;
884 void rtnl_route_set_mp_algo(
struct rtnl_route *route, uint32_t algo)
886 route->rt_mp_algo = algo;
887 route->ce_mask |= ROUTE_ATTR_MP_ALGO;
894 .oo_size =
sizeof(
struct rtnl_route),
895 .oo_constructor = route_constructor,
896 .oo_free_data = route_free_data,
897 .oo_clone = route_clone,
903 .oo_compare = route_compare,
904 .oo_attrs2str = route_attrs2str,
905 .oo_id_attrs = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_TOS |
906 ROUTE_ATTR_TABLE | ROUTE_ATTR_DST),
Dump object in a brief one-liner.
#define RTNL_LINK_NOT_FOUND
Special interface index stating the link was not found.
char * nl_addr2str(struct nl_addr *addr, char *buf, size_t size)
Convert abstract address object to character string.
#define RTNL_REALM_TO(realm)
Extract TO realm from a realms field.
#define RTNL_REALM_FROM(realm)
Extract FROM realm from a realms field.
struct nl_object * nl_object_alloc(struct nl_object_ops *ops)
Allocate a new object of kind specified by the operations handle.
struct nl_addr * nl_addr_clone(struct nl_addr *addr)
Clone existing abstract address object.
void nl_object_get(struct nl_object *obj)
Acquire a reference on a object.
unsigned int nl_addr_get_len(struct nl_addr *addr)
Get length of binary address of abstract address object.
Dump all attribtes in XML format.
struct nl_cache * nl_cache_mngt_require(const char *name)
Demand the use of a global cache.
unsigned int nl_addr_get_prefixlen(struct nl_addr *addr)
Get prefix length of abstract address object.
int nl_addr_cmp(struct nl_addr *a, struct nl_addr *b)
Compares two abstract address objects.
void nl_object_put(struct nl_object *obj)
Release a reference from an object.
char * rtnl_link_i2name(struct nl_cache *cache, int ifindex, char *dst, size_t len)
Translate an interface index to the corresponding link name.
int nl_get_hz(void)
Return the value of HZ.
char * oo_name
Unique name of object type.
Dump all attributes but no statistics.
Dump all attributes including statistics.
Dump all attribtues as env variables.