2 * lib/route/route_obj.c Route Object
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_obj Route Object
19 * -------------------------------------------------------------
20 * routing table RT_TABLE_MAIN
21 * scope RT_SCOPE_NOWHERE
24 * protocol RTPROT_STATIC
28 * oif RTNL_LINK_NOT_FOUND
30 * mpalgo IP_MP_ALG_NONE
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;
102 if (!(dst->rt_dst = nl_addr_clone(src->rt_dst)))
106 if (!(dst->rt_src = nl_addr_clone(src->rt_src)))
110 if (!(dst->rt_gateway = nl_addr_clone(src->rt_gateway)))
113 if (src->rt_pref_src)
114 if (!(dst->rt_pref_src = nl_addr_clone(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;
137 link_cache = nl_cache_mngt_require("route/link");
139 if (!(r->ce_mask & ROUTE_ATTR_DST) ||
140 nl_addr_get_len(r->rt_dst) == 0)
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 ",
148 rtnl_link_i2name(link_cache, r->rt_oif,
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;
199 link_cache = nl_cache_mngt_require("route/link");
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)
210 nl_addr2str(nh->rtnh_gateway,
213 dp_dump(p, "dev %s ",
214 rtnl_link_i2name(link_cache,
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 ",
230 nl_addr2str(r->rt_pref_src, buf, sizeof(buf)));
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 ",
264 nl_addr2str(r->rt_src, buf, sizeof(buf)));
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 ",
271 RTNL_REALM_FROM(r->rt_realms),
272 RTNL_REALM_TO(r->rt_realms));
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) {
304 struct rtnl_rtcacheinfo *ci = &route->rt_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",
308 ci->rtci_last_use / nl_get_hz(),
309 ci->rtci_expires / nl_get_hz());
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",
327 nl_addr2str(route->rt_dst, buf, sizeof(buf)));
329 if (route->ce_mask & ROUTE_ATTR_SRC)
330 dp_dump_line(p, line++, " <src>%s</src>\n",
331 nl_addr2str(route->rt_src, buf, sizeof(buf)));
333 if (route->ce_mask & ROUTE_ATTR_GATEWAY)
334 dp_dump_line(p, line++, " <gateway>%s</gateway>\n",
335 nl_addr2str(route->rt_gateway, buf, sizeof(buf)));
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;
366 link_cache = nl_cache_mngt_require("route/link");
368 dp_dump_line(p, line++, " <oif>%s</oif>\n",
369 rtnl_link_i2name(link_cache,
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;
389 struct rtnl_rtcacheinfo rt_cacheinfo;
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",
408 nl_addr2str(route->rt_dst, buf, sizeof(buf)));
410 if (route->ce_mask & ROUTE_ATTR_SRC)
411 dp_dump_line(p, line++, "ROUTE_SRC=%s\n",
412 nl_addr2str(route->rt_src, buf, sizeof(buf)));
414 if (route->ce_mask & ROUTE_ATTR_GATEWAY)
415 dp_dump_line(p, line++, "ROUTE_GATEWAY=%s\n",
416 nl_addr2str(route->rt_gateway, buf, sizeof(buf)));
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",
450 link_cache = nl_cache_mngt_require("route/link");
452 dp_dump_line(p, line++, "ROUTE_OIF_IFNAME=%s\n",
453 rtnl_link_i2name(link_cache,
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,
492 /* FIXME: Compare metrics, multipath config */
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));
534 * @name Allocation/Freeing
538 struct rtnl_route *rtnl_route_alloc(void)
540 return (struct rtnl_route *) nl_object_alloc(&route_obj_ops);
543 void rtnl_route_get(struct rtnl_route *route)
545 nl_object_get((struct nl_object *) route);
548 void rtnl_route_put(struct rtnl_route *route)
550 nl_object_put((struct nl_object *) 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)
676 return nl_addr_get_prefixlen(route->rt_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)
707 return nl_addr_get_prefixlen(route->rt_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;
836 return RTNL_LINK_NOT_FOUND;
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,
870 struct rtnl_rtcacheinfo *ci)
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;
892 struct nl_object_ops route_obj_ops = {
893 .oo_name = "route/route",
894 .oo_size = sizeof(struct rtnl_route),
895 .oo_constructor = route_constructor,
896 .oo_free_data = route_free_data,
897 .oo_clone = route_clone,
898 .oo_dump[NL_DUMP_BRIEF] = route_dump_brief,
899 .oo_dump[NL_DUMP_FULL] = route_dump_full,
900 .oo_dump[NL_DUMP_STATS] = route_dump_stats,
901 .oo_dump[NL_DUMP_XML] = route_dump_xml,
902 .oo_dump[NL_DUMP_ENV] = route_dump_env,
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),