X-Git-Url: http://git.onelab.eu/?p=libnl.git;a=blobdiff_plain;f=lib%2Froute%2Froute.c;fp=lib%2Froute%2Froute.c;h=0000000000000000000000000000000000000000;hp=7602853485f8e42d4fc8d257fdabb6f01c4dc344;hb=332c8b7561dcac7ac95cc0d07328b1cb22d780a6;hpb=eabdd897b75ecc1fac5e255229a899126085e57a diff --git a/lib/route/route.c b/lib/route/route.c deleted file mode 100644 index 7602853..0000000 --- a/lib/route/route.c +++ /dev/null @@ -1,1772 +0,0 @@ -/* - * lib/route/route.c Routes - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * Copyright (c) 2003-2006 Thomas Graf - */ - -/** - * @ingroup rtnl - * @defgroup route Routing - * @brief - * @{ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/** @cond SKIP */ -#define ROUTE_ATTR_FAMILY 0x000001 -#define ROUTE_ATTR_DST_LEN 0x000002 -#define ROUTE_ATTR_SRC_LEN 0x000004 -#define ROUTE_ATTR_TOS 0x000008 -#define ROUTE_ATTR_TABLE 0x000010 -#define ROUTE_ATTR_PROTOCOL 0x000020 -#define ROUTE_ATTR_SCOPE 0x000040 -#define ROUTE_ATTR_TYPE 0x000080 -#define ROUTE_ATTR_FLAGS 0x000100 -#define ROUTE_ATTR_DST 0x000200 -#define ROUTE_ATTR_SRC 0x000400 -#define ROUTE_ATTR_IIF 0x000800 -#define ROUTE_ATTR_OIF 0x001000 -#define ROUTE_ATTR_GATEWAY 0x002000 -#define ROUTE_ATTR_PRIO 0x004000 -#define ROUTE_ATTR_PREF_SRC 0x008000 -#define ROUTE_ATTR_METRICS 0x010000 -#define ROUTE_ATTR_MULTIPATH 0x020000 -#define ROUTE_ATTR_REALMS 0x040000 -#define ROUTE_ATTR_CACHEINFO 0x080000 -#define ROUTE_ATTR_MP_ALGO 0x100000 - -#define NEXTHOP_HAS_FLAGS 0x000001 -#define NEXTHOP_HAS_WEIGHT 0x000002 -#define NEXTHOP_HAS_IFINDEX 0x000004 -#define NEXTHOP_HAS_GATEWAY 0x000008 - -static struct nl_cache_ops rtnl_route_ops; -/** @endcond */ - -static void route_constructor(struct nl_object *c) -{ - struct rtnl_route *r = (struct rtnl_route *) c; - - nl_init_list_head(&r->rt_nexthops); -} - -static void route_free_data(struct nl_object *c) -{ - struct rtnl_route *r = (struct rtnl_route *) c; - struct rtnl_nexthop *nh, *tmp; - - if (r == NULL) - return; - - nl_addr_put(r->rt_dst); - nl_addr_put(r->rt_src); - nl_addr_put(r->rt_gateway); - nl_addr_put(r->rt_pref_src); - - nl_list_for_each_entry_safe(nh, tmp, &r->rt_nexthops, rtnh_list) { - rtnl_route_remove_nexthop(nh); - rtnl_route_nh_free(nh); - } -} - -static struct nla_policy route_policy[RTA_MAX+1] = { - [RTA_IIF] = { .type = NLA_STRING, - .maxlen = IFNAMSIZ, }, - [RTA_OIF] = { .type = NLA_U32 }, - [RTA_PRIORITY] = { .type = NLA_U32 }, - [RTA_FLOW] = { .type = NLA_U32 }, - [RTA_MP_ALGO] = { .type = NLA_U32 }, - [RTA_CACHEINFO] = { .minlen = sizeof(struct rta_cacheinfo) }, - [RTA_METRICS] = { .type = NLA_NESTED }, - [RTA_MULTIPATH] = { .type = NLA_NESTED }, -}; - -static void copy_rtmsg_into_route(struct rtmsg *rtmsg, struct rtnl_route *route) -{ - route->rt_family = rtmsg->rtm_family; - route->rt_dst_len = rtmsg->rtm_dst_len; - route->rt_src_len = rtmsg->rtm_src_len; - route->rt_tos = rtmsg->rtm_tos; - route->rt_table = rtmsg->rtm_table; - route->rt_type = rtmsg->rtm_type; - route->rt_scope = rtmsg->rtm_scope; - route->rt_protocol = rtmsg->rtm_protocol; - route->rt_flags = rtmsg->rtm_flags; - - route->rt_mask = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_DST_LEN | - ROUTE_ATTR_SRC_LEN | ROUTE_ATTR_TABLE | - ROUTE_ATTR_PROTOCOL| ROUTE_ATTR_SCOPE | - ROUTE_ATTR_TYPE | ROUTE_ATTR_FLAGS); - - if (route->rt_tos) - route->rt_mask |= ROUTE_ATTR_TOS; -} - -static void copy_cacheinfo_into_route(struct rta_cacheinfo *ci, - struct rtnl_route *route) -{ - route->rt_cacheinfo.rtci_clntref = ci->rta_clntref; - route->rt_cacheinfo.rtci_last_use = ci->rta_lastuse; - route->rt_cacheinfo.rtci_expires = ci->rta_expires; - route->rt_cacheinfo.rtci_error = ci->rta_error; - route->rt_cacheinfo.rtci_used = ci->rta_used; - route->rt_cacheinfo.rtci_id = ci->rta_id; - route->rt_cacheinfo.rtci_ts = ci->rta_ts; - route->rt_cacheinfo.rtci_tsage = ci->rta_tsage; - - route->rt_mask |= ROUTE_ATTR_CACHEINFO; -} - -static int route_msg_parser(struct sockaddr_nl *who, struct nlmsghdr *nlh, - void *arg) -{ - struct nl_parser_param *pp = arg; - struct rtnl_route *route; - struct nlattr *tb[RTA_MAX + 1]; - int err; - - route = rtnl_route_alloc(); - if (!route) { - err = nl_errno(ENOMEM); - goto errout; - } - - route->ce_msgtype = nlh->nlmsg_type; - - err = nlmsg_parse(nlh, sizeof(struct rtmsg), tb, RTA_MAX, - route_policy); - if (err < 0) - goto errout; - - copy_rtmsg_into_route((struct rtmsg *) nlmsg_data(nlh), route); - - if (tb[RTA_DST]) { - route->rt_dst = nla_get_addr(tb[RTA_DST], route->rt_family); - if (!route->rt_dst) - goto errout_errno; - nl_addr_set_prefixlen(route->rt_dst, route->rt_dst_len); - route->rt_mask |= ROUTE_ATTR_DST; - } - - if (tb[RTA_SRC]) { - route->rt_src = nla_get_addr(tb[RTA_SRC], route->rt_family); - if (!route->rt_src) - goto errout_errno; - nl_addr_set_prefixlen(route->rt_src, route->rt_src_len); - route->rt_mask |= ROUTE_ATTR_SRC; - } - - if (tb[RTA_IIF]) { - nla_strlcpy(route->rt_iif, tb[RTA_IIF], IFNAMSIZ); - route->rt_mask |= ROUTE_ATTR_IIF; - } - - if (tb[RTA_OIF]) { - route->rt_oif = nla_get_u32(tb[RTA_OIF]); - route->rt_mask |= ROUTE_ATTR_OIF; - } - - if (tb[RTA_GATEWAY]) { - route->rt_gateway = nla_get_addr(tb[RTA_GATEWAY], - route->rt_family); - if (!route->rt_gateway) - goto errout_errno; - route->rt_mask |= ROUTE_ATTR_GATEWAY; - } - - if (tb[RTA_PRIORITY]) { - route->rt_prio = nla_get_u32(tb[RTA_PRIORITY]); - route->rt_mask |= ROUTE_ATTR_PRIO; - } - - if (tb[RTA_PREFSRC]) { - route->rt_pref_src = nla_get_addr(tb[RTA_PREFSRC], - route->rt_family); - if (!route->rt_pref_src) - goto errout_errno; - route->rt_mask |= ROUTE_ATTR_PREF_SRC; - } - - if (tb[RTA_METRICS]) { - struct nlattr *mtb[RTAX_MAX + 1]; - int i; - - err = nla_parse_nested(mtb, RTAX_MAX, tb[RTA_METRICS], NULL); - if (err < 0) - goto errout; - - for (i = 1; i <= RTAX_MAX; i++) { - if (mtb[i] && nla_len(mtb[i]) >= sizeof(uint32_t)) { - uint32_t m = nla_get_u32(mtb[i]); - route->rt_metrics[i-1] = m; - route->rt_metrics_mask |= (1 << (i - 1)); - } - } - - route->rt_mask |= ROUTE_ATTR_METRICS; - } - - if (tb[RTA_MULTIPATH]) { - struct rtnl_nexthop *nh; - struct rtnexthop *rtnh = nla_data(tb[RTA_MULTIPATH]); - size_t tlen = nla_len(tb[RTA_MULTIPATH]); - - while (tlen >= sizeof(*rtnh) && tlen >= rtnh->rtnh_len) { - nh = rtnl_route_nh_alloc(); - if (!nh) - goto errout; - - rtnl_route_nh_set_weight(nh, rtnh->rtnh_hops); - rtnl_route_nh_set_ifindex(nh, rtnh->rtnh_ifindex); - rtnl_route_nh_set_flags(nh, rtnh->rtnh_flags); - - if (rtnh->rtnh_len > sizeof(*rtnh)) { - struct nlattr *ntb[RTA_MAX + 1]; - nla_parse(ntb, RTA_MAX, (struct nlattr *) - RTNH_DATA(rtnh), - rtnh->rtnh_len - sizeof(*rtnh), - route_policy); - - if (ntb[RTA_GATEWAY]) { - nh->rtnh_gateway = nla_get_addr( - ntb[RTA_GATEWAY], - route->rt_family); - nh->rtnh_mask = NEXTHOP_HAS_GATEWAY; - } - } - - rtnl_route_add_nexthop(route, nh); - tlen -= RTNH_ALIGN(rtnh->rtnh_len); - rtnh = RTNH_NEXT(rtnh); - } - } - - if (tb[RTA_FLOW]) { - route->rt_realms = nla_get_u32(tb[RTA_FLOW]); - route->rt_mask |= ROUTE_ATTR_REALMS; - } - - if (tb[RTA_CACHEINFO]) - copy_cacheinfo_into_route(nla_data(tb[RTA_CACHEINFO]), route); - - if (tb[RTA_MP_ALGO]) { - route->rt_mp_algo = nla_get_u32(tb[RTA_MP_ALGO]); - route->rt_mask |= ROUTE_ATTR_MP_ALGO; - } - - err = pp->pp_cb((struct nl_object *) route, pp); - if (err < 0) - goto errout; - - return P_ACCEPT; - -errout_errno: - err = nl_get_errno(); -errout: - rtnl_route_put(route); - return err; - -} - -static int route_request_update(struct nl_cache *c, struct nl_handle *h) -{ - return nl_rtgen_request(h, RTM_GETROUTE, AF_UNSPEC, NLM_F_DUMP); -} - -static int route_dump_brief(struct nl_object *a, struct nl_dump_params *p) -{ - struct rtnl_route *r = (struct rtnl_route *) a; - struct nl_cache *link_cache; - char buf[64]; - - link_cache = nl_cache_mngt_require("route/link"); - - if (r->rt_mask & ROUTE_ATTR_DST) - dp_dump(p, "%s ", nl_addr2str(r->rt_dst, buf, sizeof(buf))); - else if (r->rt_dst_len) - dp_dump(p, "0/%u ", r->rt_dst_len); - else - dp_dump(p, "default "); - - if (r->rt_mask & ROUTE_ATTR_OIF) { - if (link_cache) - dp_dump(p, "dev %s ", - rtnl_link_i2name(link_cache, r->rt_oif, - buf, sizeof(buf))); - else - dp_dump(p, "dev %d ", r->rt_oif); - } - - if (r->rt_mask & ROUTE_ATTR_GATEWAY) - dp_dump(p, "via %s ", nl_addr2str(r->rt_gateway, buf, - sizeof(buf))); - else if (r->rt_mask & ROUTE_ATTR_MULTIPATH) - dp_dump(p, "via nexthops "); - - if (r->rt_mask & ROUTE_ATTR_TABLE) - dp_dump(p, "table %s ", - rtnl_route_table2str(r->rt_table, buf, sizeof(buf))); - - if (r->rt_mask & ROUTE_ATTR_SCOPE) - dp_dump(p, "scope %s ", - rtnl_scope2str(r->rt_scope, buf, sizeof(buf))); - - if (r->rt_mask & ROUTE_ATTR_FLAGS && r->rt_flags) { - int flags = r->rt_flags; - - dp_dump(p, "<"); - -#define PRINT_FLAG(f) if (flags & RTNH_F_##f) { \ - flags &= ~RTNH_F_##f; dp_dump(p, #f "%s", flags ? "," : ""); } - PRINT_FLAG(DEAD); - PRINT_FLAG(ONLINK); - PRINT_FLAG(PERVASIVE); -#undef PRINT_FLAG - -#define PRINT_FLAG(f) if (flags & RTM_F_##f) { \ - flags &= ~RTM_F_##f; dp_dump(p, #f "%s", flags ? "," : ""); } - PRINT_FLAG(NOTIFY); - PRINT_FLAG(CLONED); - PRINT_FLAG(EQUALIZE); - PRINT_FLAG(PREFIX); -#undef PRINT_FLAG - - dp_dump(p, ">"); - } - - dp_dump(p, "\n"); - - return 1; -} - -static int route_dump_full(struct nl_object *a, struct nl_dump_params *p) -{ - struct rtnl_route *r = (struct rtnl_route *) a; - struct nl_cache *link_cache; - char buf[128]; - int i, line; - - link_cache = nl_cache_mngt_require("route/link"); - line = route_dump_brief(a, p); - - if (r->rt_mask & ROUTE_ATTR_MULTIPATH) { - struct rtnl_nexthop *nh; - - dp_dump_line(p, line++, " "); - - nl_list_for_each_entry(nh, &r->rt_nexthops, rtnh_list) { - dp_dump(p, "nh "); - - if (nh->rtnh_mask & NEXTHOP_HAS_GATEWAY) - dp_dump(p, "via %s ", - nl_addr2str(nh->rtnh_gateway, - buf, sizeof(buf))); - if (link_cache) - dp_dump(p, "dev %s ", - rtnl_link_i2name(link_cache, - nh->rtnh_ifindex, - buf, sizeof(buf))); - else - dp_dump(p, "dev %d ", nh->rtnh_ifindex); - - dp_dump(p, "weight %u <%s> ", nh->rtnh_weight, - rtnl_route_nh_flags2str(nh->rtnh_flags, - buf, sizeof(buf))); - } - - dp_dump(p, "\n"); - } - - dp_dump_line(p, line++, " "); - - if (r->rt_mask & ROUTE_ATTR_PREF_SRC) - dp_dump(p, "preferred-src %s ", - nl_addr2str(r->rt_pref_src, buf, sizeof(buf))); - - if (r->rt_mask & ROUTE_ATTR_TYPE) - dp_dump(p, "type %s ", - nl_rtntype2str(r->rt_type, buf, sizeof(buf))); - - if (r->rt_mask & ROUTE_ATTR_PRIO) - dp_dump(p, "metric %#x ", r->rt_prio); - - if (r->rt_mask & ROUTE_ATTR_FAMILY) - dp_dump(p, "family %s ", - nl_af2str(r->rt_family, buf, sizeof(buf))); - - if (r->rt_mask & ROUTE_ATTR_PROTOCOL) - dp_dump(p, "protocol %s ", - rtnl_route_proto2str(r->rt_protocol, buf, sizeof(buf))); - - dp_dump(p, "\n"); - - if ((r->rt_mask & (ROUTE_ATTR_IIF | ROUTE_ATTR_SRC | ROUTE_ATTR_TOS | - ROUTE_ATTR_REALMS)) || r->rt_src_len || - ((r->rt_mask & ROUTE_ATTR_CACHEINFO) && - r->rt_cacheinfo.rtci_error)) { - dp_dump_line(p, line++, " "); - - if (r->rt_mask & ROUTE_ATTR_IIF) - dp_dump(p, "iif %s ", r->rt_iif); - - if (r->rt_mask & ROUTE_ATTR_SRC) - dp_dump(p, "src %s ", - nl_addr2str(r->rt_src, buf, sizeof(buf))); - else if (r->rt_src_len) - dp_dump(p, "src 0/%u ", r->rt_src_len); - - if (r->rt_mask & ROUTE_ATTR_TOS) - dp_dump(p, "tos %#x ", r->rt_tos); - - if (r->rt_mask & ROUTE_ATTR_REALMS) - dp_dump(p, "realm %04x:%04x ", - RTNL_REALM_FROM(r->rt_realms), - RTNL_REALM_TO(r->rt_realms)); - - if ((r->rt_mask & ROUTE_ATTR_CACHEINFO) && - r->rt_cacheinfo.rtci_error) - dp_dump(p, "error %d (%s) ", r->rt_cacheinfo.rtci_error, - strerror(-r->rt_cacheinfo.rtci_error)); - - dp_dump(p, "\n"); - } - - if (r->rt_mask & ROUTE_ATTR_METRICS) { - dp_dump_line(p, line++, " "); - for (i = 0; i < RTAX_MAX; i++) - if (r->rt_metrics_mask & (1 << i)) - dp_dump(p, "%s %u ", - rtnl_route_metric2str(i+1, - buf, sizeof(buf)), - r->rt_metrics[i]); - dp_dump(p, "\n"); - } - - return line; -} - -static int route_dump_stats(struct nl_object *obj, struct nl_dump_params *p) -{ - struct rtnl_route *route = (struct rtnl_route *) obj; - int line; - - line = route_dump_full(obj, p); - - if (route->rt_mask & ROUTE_ATTR_CACHEINFO) { - struct rtnl_rtcacheinfo *ci = &route->rt_cacheinfo; - dp_dump_line(p, line++, " used %u refcnt %u ", - ci->rtci_used, ci->rtci_clntref); - dp_dump_line(p, line++, "last-use %us expires %us\n", - ci->rtci_last_use / nl_get_hz(), - ci->rtci_expires / nl_get_hz()); - } - - return line; -} - -static int route_dump_xml(struct nl_object *obj, struct nl_dump_params *p) -{ - struct rtnl_route *route = (struct rtnl_route *) obj; - char buf[128]; - int line = 0; - - dp_dump_line(p, line++, "\n"); - dp_dump_line(p, line++, " %s\n", - nl_af2str(route->rt_family, buf, sizeof(buf))); - - if (route->rt_mask & ROUTE_ATTR_DST) - dp_dump_line(p, line++, " %s\n", - nl_addr2str(route->rt_dst, buf, sizeof(buf))); - - if (route->rt_mask & ROUTE_ATTR_DST_LEN) - dp_dump_line(p, line++, " %u\n", - route->rt_dst_len); - - if (route->rt_mask & ROUTE_ATTR_SRC) - dp_dump_line(p, line++, " %s\n", - nl_addr2str(route->rt_src, buf, sizeof(buf))); - - if (route->rt_mask & ROUTE_ATTR_SRC_LEN) - dp_dump_line(p, line++, " %u\n", - route->rt_src_len); - - if (route->rt_mask & ROUTE_ATTR_GATEWAY) - dp_dump_line(p, line++, " %s\n", - nl_addr2str(route->rt_gateway, buf, sizeof(buf))); - - if (route->rt_mask & ROUTE_ATTR_PREF_SRC) - dp_dump_line(p, line++, " %s\n", - nl_addr2str(route->rt_pref_src, buf, sizeof(buf))); - - if (route->rt_mask & ROUTE_ATTR_IIF) - dp_dump_line(p, line++, " %s\n", route->rt_iif); - - if (route->rt_mask & ROUTE_ATTR_REALMS) - dp_dump_line(p, line++, " %u\n", - route->rt_realms); - - if (route->rt_mask & ROUTE_ATTR_TOS) - dp_dump_line(p, line++, " %u\n", route->rt_tos); - - if (route->rt_mask & ROUTE_ATTR_TABLE) - dp_dump_line(p, line++, " %u
\n", - route->rt_table); - - if (route->rt_mask & ROUTE_ATTR_SCOPE) - dp_dump_line(p, line++, " %s\n", - rtnl_scope2str(route->rt_scope, buf, sizeof(buf))); - - if (route->rt_mask & ROUTE_ATTR_PRIO) - dp_dump_line(p, line++, " %u\n", - route->rt_prio); - - if (route->rt_mask & ROUTE_ATTR_OIF) { - struct nl_cache *link_cache; - - link_cache = nl_cache_mngt_require("route/link"); - if (link_cache) - dp_dump_line(p, line++, " %s\n", - rtnl_link_i2name(link_cache, - route->rt_oif, - buf, sizeof(buf))); - else - dp_dump_line(p, line++, " %u\n", - route->rt_oif); - } - - if (route->rt_mask & ROUTE_ATTR_TYPE) - dp_dump_line(p, line++, " %s\n", - nl_rtntype2str(route->rt_type, buf, sizeof(buf))); - - dp_dump_line(p, line++, "
\n"); - -#if 0 - uint8_t rt_protocol; - uint32_t rt_flags; - uint32_t rt_metrics[RTAX_MAX]; - uint32_t rt_metrics_mask; - struct rtnl_nexthop * rt_nexthops; - struct rtnl_rtcacheinfo rt_cacheinfo; - uint32_t rt_mp_algo; - -#endif - - return line; -} - -static int route_dump_env(struct nl_object *obj, struct nl_dump_params *p) -{ - struct rtnl_route *route = (struct rtnl_route *) obj; - char buf[128]; - int line = 0; - - dp_dump_line(p, line++, "ROUTE_FAMILY=%s\n", - nl_af2str(route->rt_family, buf, sizeof(buf))); - - if (route->rt_mask & ROUTE_ATTR_DST) - dp_dump_line(p, line++, "ROUTE_DST=%s\n", - nl_addr2str(route->rt_dst, buf, sizeof(buf))); - - if (route->rt_mask & ROUTE_ATTR_DST_LEN) - dp_dump_line(p, line++, "ROUTE_DSTLEN=%u\n", - route->rt_dst_len); - - if (route->rt_mask & ROUTE_ATTR_SRC) - dp_dump_line(p, line++, "ROUTE_SRC=%s\n", - nl_addr2str(route->rt_src, buf, sizeof(buf))); - - if (route->rt_mask & ROUTE_ATTR_SRC_LEN) - dp_dump_line(p, line++, "ROUTE_SRCLEN=%u\n", - route->rt_src_len); - - if (route->rt_mask & ROUTE_ATTR_GATEWAY) - dp_dump_line(p, line++, "ROUTE_GATEWAY=%s\n", - nl_addr2str(route->rt_gateway, buf, sizeof(buf))); - - if (route->rt_mask & ROUTE_ATTR_PREF_SRC) - dp_dump_line(p, line++, "ROUTE_PREFSRC=%s\n", - nl_addr2str(route->rt_pref_src, buf, sizeof(buf))); - - if (route->rt_mask & ROUTE_ATTR_IIF) - dp_dump_line(p, line++, "ROUTE_IIF=%s\n", route->rt_iif); - - if (route->rt_mask & ROUTE_ATTR_REALMS) - dp_dump_line(p, line++, "ROUTE_REALM=%u\n", - route->rt_realms); - - if (route->rt_mask & ROUTE_ATTR_TOS) - dp_dump_line(p, line++, "ROUTE_TOS=%u\n", route->rt_tos); - - if (route->rt_mask & ROUTE_ATTR_TABLE) - dp_dump_line(p, line++, "ROUTE_TABLE=%u\n", - route->rt_table); - - if (route->rt_mask & ROUTE_ATTR_SCOPE) - dp_dump_line(p, line++, "ROUTE_SCOPE=%s\n", - rtnl_scope2str(route->rt_scope, buf, sizeof(buf))); - - if (route->rt_mask & ROUTE_ATTR_PRIO) - dp_dump_line(p, line++, "ROUTE_METRIC=%u\n", - route->rt_prio); - - if (route->rt_mask & ROUTE_ATTR_OIF) { - struct nl_cache *link_cache; - - dp_dump_line(p, line++, "ROUTE_OIF_IFINDEX=%u\n", - route->rt_oif); - - link_cache = nl_cache_mngt_require("route/link"); - if (link_cache) - dp_dump_line(p, line++, "ROUTE_OIF_IFNAME=%s\n", - rtnl_link_i2name(link_cache, - route->rt_oif, - buf, sizeof(buf))); - } - - if (route->rt_mask & ROUTE_ATTR_TYPE) - dp_dump_line(p, line++, "ROUTE_TYPE=%s\n", - nl_rtntype2str(route->rt_type, buf, sizeof(buf))); - - return line; -} - -static int route_filter(struct nl_object *obj, struct nl_object *filter) -{ - struct rtnl_route *o = (struct rtnl_route *) obj; - struct rtnl_route *f = (struct rtnl_route *) filter; - -#define REQ(F) (f->rt_mask & ROUTE_ATTR_##F) -#define AVAIL(F) (o->rt_mask & ROUTE_ATTR_##F) -#define _O(F, EXPR) (REQ(F) && (!AVAIL(F) || (EXPR))) -#define _C(F, N) (REQ(F) && (!AVAIL(F) || (o->N != f->N))) - if (_C(FAMILY, rt_family) || - _C(DST_LEN, rt_dst_len) || - _C(SRC_LEN, rt_src_len) || - _C(TOS, rt_tos) || - _C(TABLE, rt_table) || - _C(PROTOCOL, rt_protocol) || - _C(SCOPE, rt_scope) || - _C(TYPE, rt_type) || - _C(OIF, rt_oif) || - _C(PRIO, rt_prio) || - _C(REALMS, rt_realms) || - _C(MP_ALGO, rt_mp_algo) || - _O(DST, nl_addr_cmp(o->rt_dst, f->rt_dst)) || - _O(SRC, nl_addr_cmp(o->rt_src, f->rt_src)) || - _O(IIF, strcmp(o->rt_iif, f->rt_iif)) || - _O(PREF_SRC, nl_addr_cmp(o->rt_pref_src, f->rt_pref_src)) || - _O(GATEWAY, nl_addr_cmp(o->rt_gateway, f->rt_gateway)) || - _O(FLAGS, f->rt_flags ^ (o->rt_flags & f->rt_flag_mask))) - return 0; - - if (REQ(METRICS)) { - int i; - - if (!AVAIL(METRICS)) - return 0; - - for (i = 0; i < RTAX_MAX; i++) { - if (f->rt_metrics_mask & (1 << i)) { - if (!(o->rt_metrics_mask & (1 << i)) || - f->rt_metrics[i+1] != o->rt_metrics[i+1]) - return 0; - } - } - } - - if (REQ(MULTIPATH)) { - /* FIXME */ - } - -#undef REQ -#undef AVAIL -#undef _O -#undef _C - - return 1; - -} - -/** - * @name Route Object Allocation/Freeage - * @{ - */ - -/** - * Allocate a new route object - * @return New route object - */ -struct rtnl_route *rtnl_route_alloc(void) -{ - return (struct rtnl_route *) nl_object_alloc_from_ops(&rtnl_route_ops); -} - -/** - * Free route object. - * @arg route Route object to be freed. - * - * @note Always use rtnl_route_put() unless you're absolutely sure - * that no other user may have a reference on this object. - */ -void rtnl_route_free(struct rtnl_route *route) -{ - nl_object_free((struct nl_object *) route); -} - -/** @} */ - -/** - * @name Route Object Reference Counting - * @{ - */ - -void rtnl_route_get(struct rtnl_route *route) -{ - nl_object_get((struct nl_object *) route); -} - -void rtnl_route_put(struct rtnl_route *route) -{ - nl_object_put((struct nl_object *) route); -} - -/** @} */ - -/** - * @name Route Cache Management - * @{ - */ - -/** - * Build a route cache holding all routes currently configured in the kernel - * @arg handle netlink handle - * - * Allocates a new cache, initializes it properly and updates it to - * contain all routes currently configured in the kernel. - * - * @note The caller is responsible for destroying and freeing the - * cache after using it. - * @return The cache or NULL if an error has occured. - */ -struct nl_cache *rtnl_route_alloc_cache(struct nl_handle *handle) -{ - struct nl_cache *cache = nl_cache_alloc_from_ops(&rtnl_route_ops); - - if (!cache) - return NULL; - - if (nl_cache_update(handle, cache) < 0) { - free(cache); - return NULL; - } - - return cache; -} - -/** @} */ - -/** - * @name Route Addition - * @{ - */ - -static struct nl_msg *build_route_msg(struct rtnl_route *tmpl, int cmd, - int flags) -{ -#if 0 - struct nl_msg *msg; - struct rtmsg rtmsg = { - .rtm_family = tmpl->rt_family, - }; - route->rt_dst_len = rtmsg->rtm_dst_len; - route->rt_src_len = rtmsg->rtm_src_len; - route->rt_tos = rtmsg->rtm_tos; - route->rt_table = rtmsg->rtm_table; - route->rt_type = rtmsg->rtm_type; - route->rt_scope = rtmsg->rtm_scope; - route->rt_protocol = rtmsg->rtm_protocol; - route->rt_flags = rtmsg->rtm_flags; - - route->rt_mask = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_DST_LEN | - ROUTE_ATTR_SRC_LEN | ROUTE_ATTR_TABLE | - ROUTE_ATTR_PROTOCOL| ROUTE_ATTR_SCOPE | - ROUTE_ATTR_TYPE | ROUTE_ATTR_FLAGS); - - msg = nlmsg_build_simple(cmd, flags); - if (!msg) - return NULL; - - if (nlmsg_append(msg, &rtmsg, sizeof(rtmsg), 1) < 0) - goto nla_put_failure; - - NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst); - - if (tmpl->n_mask & NEIGH_ATTR_LLADDR) - NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr); - - return msg; - -nla_put_failure: - nlmsg_free(msg); - return NULL; -#endif - - return NULL; -} - -/** - * Build netlink request message to add a new route - * @arg tmpl template with data of new route - * @arg flags additional netlink message flags - * - * Builds a new netlink message requesting a addition of a new route. - * The netlink message header isn't fully equipped with all relevant - * fields and must thus be sent out via nl_send_auto_complete() or - * supplemented as needed. \a tmpl must contain the attributes of the - * new route set via \c rtnl_route_set_* functions. - * - * The following attributes must be set in the template: - * - Interface index (rtnl_neigh_set_ifindex()) - * - State (rtnl_neigh_set_state()) - * - Destination address (rtnl_neigh_set_dst()) - * - Link layer address (rtnl_neigh_set_lladdr()) - * - * @return The netlink message - */ -struct nl_msg *rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags) -{ - return build_route_msg(tmpl, RTM_NEWROUTE, NLM_F_CREATE | flags); -} - -/** @} */ -/** - * @name Attribute: Routing Table - * @{ - */ - -/** - * Set the table of a route to the specified value - * @arg route route to be changed - * @arg table new table value - */ -void rtnl_route_set_table(struct rtnl_route *route, int table) -{ - route->rt_table = table; - route->rt_mask |= ROUTE_ATTR_TABLE; -} - -/** - * Get the table of a route - * @arg route route handle - * @return Table id or -1 if not set - */ -int rtnl_route_get_table(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_TABLE) - return route->rt_table; - else - return -1; -} - -/** @} */ -/** - * @name Attribute: Scope - * @{ - */ - -/** - * Set the scope of a route to the specified value - * @arg route route to be changed - * @arg scope new scope - */ -void rtnl_route_set_scope(struct rtnl_route *route, int scope) -{ - route->rt_scope = scope; - route->rt_mask |= ROUTE_ATTR_SCOPE; -} - -/** - * Get the scope of a route - * @arg route route handle - * @return Scope or -1 if not set - */ -int rtnl_route_get_scope(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_SCOPE) - return route->rt_scope; - else - return -1; -} - -/** @} */ -/** - * @name Attribute: Type Of Service - * @{ - */ - -/** - * Set the TOS of a route to the specified value - * @arg route route to be changed - * @arg tos new TOS value - */ -void rtnl_route_set_tos(struct rtnl_route *route, int tos) -{ - route->rt_tos = tos; - route->rt_mask |= ROUTE_ATTR_TOS; -} - -/** - * Get the TOS of a route - * @arg route route handle - * @return TOS value or -1 if not set - */ -int rtnl_route_get_tos(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_TOS) - return route->rt_tos; - else - return -1; -} - -/** @} */ -/** - * @name Attribute: Realm - * @{ - */ - -/** - * Set the realms of a route to the specified value - * @arg route route to be changed - * @arg realms New realms value. - */ -void rtnl_route_set_realms(struct rtnl_route *route, realm_t realms) -{ - route->rt_realms = realms; - route->rt_mask |= ROUTE_ATTR_REALMS; -} - -/** - * Get realms of route object. - * @arg route Route object. - * @return Realms value or 0 if not set. - */ -realm_t rtnl_route_get_realms(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_REALMS) - return route->rt_realms; - else - return 0; -} - -/** @} */ -/** - * @name Attribute: Routing Protocol - * @{ - */ - -/** - * Set the protocol of a route to the specified value - * @arg route route to be changed - * @arg proto new protocol - */ -void rtnl_route_set_protocol(struct rtnl_route *route, int proto) -{ - route->rt_protocol = proto; - route->rt_mask |= ROUTE_ATTR_PROTOCOL; -} - -/** - * Get the protocol of a route - * @arg route route handle - * @return Protocol number or -1 if not set - */ -int rtnl_route_get_protocol(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_PROTOCOL) - return route->rt_protocol; - else - return -1; -} - -/** @} */ -/** - * @name Attribute: Priority/Metric - * @{ - */ - -/** - * Set the priority of a route to the specified value - * @arg route route to be changed - * @arg prio new priority - */ -void rtnl_route_set_prio(struct rtnl_route *route, int prio) -{ - route->rt_prio = prio; - route->rt_mask |= ROUTE_ATTR_PRIO; -} - -/** - * Get the priority of a route - * @arg route route handle - * @return Priority or -1 if not set - */ -int rtnl_route_get_prio(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_PRIO) - return route->rt_prio; - else - return -1; -} - -/** @} */ -/** - * @name Attribute: Address Family - * @{ - */ - -/** - * Set the address family of a route to the specified value - * @arg route route to be changed - * @arg family new address family - */ -void rtnl_route_set_family(struct rtnl_route *route, int family) -{ - route->rt_family = family; - route->rt_mask |= ROUTE_ATTR_FAMILY; -} - -/** - * Get the address family of a route - * @arg route route handle - * @return Address family or AF_UNSPEC if not set - */ -int rtnl_route_get_family(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_FAMILY) - return route->rt_family; - else - return AF_UNSPEC; -} - -/** @} */ -/** - * @name Attribute: Destination Address - * @{ - */ - -/** - * Set the destination address of a route to the specified address - * @arg route route to be changed - * @arg addr new destination address - * - * Assigns the new destination address to the specified \a route, - * overwrites the destination address length (rtnl_route::rt_dst_len), - * and sets the route's address family to the new address's family if - * it is not set already. - * - * If a address family has been specified already via either calling - * rtnl_route_set_family() or by setting one of the other addresses, - * the specified \a addr is automatically validated against this family - * and the assignment fails in case of a mismatch. - * - * @return 0 on success or a negative error code. - */ -int rtnl_route_set_dst(struct rtnl_route *route, struct nl_addr *addr) -{ - if (route->rt_mask & ROUTE_ATTR_FAMILY) { - if (addr->a_family != route->rt_family) - return nl_error(EINVAL, "Address family mismatch"); - } else - route->rt_family = addr->a_family; - - if (route->rt_dst) - nl_addr_put(route->rt_dst); - - nl_addr_get(addr); - route->rt_dst = addr; - - route->rt_mask |= (ROUTE_ATTR_DST|ROUTE_ATTR_FAMILY|ROUTE_ATTR_DST_LEN); - - return 0; -} - -/** - * Get the destination address of a route - * @arg route route handle - * @return Destination address or NULL if not set - */ -struct nl_addr *rtnl_route_get_dst(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_DST) - return route->rt_dst; - else - return NULL; -} - -/** - * Set the destination address prefix length of a route to the specified value - * @arg route route to be changed - * @arg prefix new destination address prefix - * @attention The destination address prefix gets overwritten by calls - * to rtnl_route_set_dst() rtnl_route_set_dst_str(). - */ -void rtnl_route_set_dst_len(struct rtnl_route *route, int prefix) -{ - route->rt_dst_len = prefix; - route->rt_mask |= ROUTE_ATTR_DST_LEN; -} - -/** - * Get the destination address prefix length of a route - * @arg route route handle - * @return Prefix length or -1 if not set - */ -int rtnl_route_get_dst_len(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_DST_LEN) - return route->rt_dst_len; - else - return -1; -} - -/** @} */ -/** - * @name Attribute: Source Address - * @{ - */ - -/** - * Set the source address of a route to the specified address - * @arg route route to be changed - * @arg addr new source address - * - * Assigns the new source address to the specified \a route, - * overwrites the source address length (rtnl_route::rt_src_len), - * and sets the route's address family to the new address's family if - * it is not set already. - * - * If a address family has been specified already via either calling - * rtnl_route_set_family() or by setting one of the other addresses, - * the specified \a addr is automatically validated against this family - * and the assignment fails in case of a mismatch. - * - * @return 0 on success or a negative error code. - */ -int rtnl_route_set_src(struct rtnl_route *route, struct nl_addr *addr) -{ - if (route->rt_mask & ROUTE_ATTR_FAMILY) { - if (addr->a_family != route->rt_family) - return nl_error(EINVAL, "Address family mismatch"); - } else - route->rt_family = addr->a_family; - - if (route->rt_src) - nl_addr_put(route->rt_src); - - nl_addr_get(addr); - route->rt_src = addr; - route->rt_mask |= (ROUTE_ATTR_SRC|ROUTE_ATTR_FAMILY|ROUTE_ATTR_SRC_LEN); - - return 0; -} - -/** - * Get the source address of a route - * @arg route route handle - * @return Source address or NULL if not set - */ -struct nl_addr *rtnl_route_get_src(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_SRC) - return route->rt_src; - else - return NULL; -} - -/** - * Set the source address prefix length of a route to the specified value - * @arg route route to be changed - * @arg prefix new source address prefix - * @attention The source address prefix gets overwritten by calls - * to rtnl_route_src_dst() rtnl_route_set_src_str(). - */ -void rtnl_route_set_src_len(struct rtnl_route *route, int prefix) -{ - route->rt_dst_len = prefix; - route->rt_mask |= ROUTE_ATTR_SRC_LEN; -} - -/** - * Get the source address prefix length of a route - * @arg route route handle - * @return Prefix length or -1 if not set - */ -int rtnl_route_get_src_len(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_SRC_LEN) - return route->rt_src_len; - else - return -1; -} - -/** @} */ -/** - * @name Attribute: Gateway Address - * @{ - */ - -/** - * Set the gateway address of a route to the specified address - * @arg route route to be changed - * @arg addr new gateway address - * - * Assigns the new gateway address to the specified \a route, - * and sets the route's address family to the new address's family if - * it is not set already. - * - * If a address family has been specified already via either calling - * rtnl_route_set_family() or by setting one of the other addresses, - * the specified \a addr is automatically validated against this family - * and the assignment fails in case of a mismatch. - * - * @return 0 on success or a negative error code. - */ -int rtnl_route_set_gateway(struct rtnl_route *route, struct nl_addr *addr) -{ - if (route->rt_mask & ROUTE_ATTR_FAMILY) { - if (addr->a_family != route->rt_family) - return nl_error(EINVAL, "Address family mismatch"); - } else - route->rt_family = addr->a_family; - - if (route->rt_gateway) - nl_addr_put(route->rt_gateway); - - nl_addr_get(addr); - route->rt_gateway = addr; - route->rt_mask |= (ROUTE_ATTR_GATEWAY | ROUTE_ATTR_FAMILY); - - return 0; -} - -/** - * Get the gateway address of a route - * @arg route route handle - * @return Gateway address or NULL if not set - */ -struct nl_addr *rtnl_route_get_gateway(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_GATEWAY) - return route->rt_gateway; - else - return NULL; -} - -/** @} */ -/** - * @name Attribute: Type - * @{ - */ - -/** - * Set the type of a route to the specified value - * @arg route route to be changed - * @arg type new route type - */ -void rtnl_route_set_type(struct rtnl_route *route, int type) -{ - route->rt_type = type; - route->rt_mask |= ROUTE_ATTR_TYPE; -} - -/** - * Get the type of a route - * @arg route route handle - * @return Type of route or -1 if not set - */ -int rtnl_route_get_type(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_TYPE) - return route->rt_type; - else - return -1; -} - -/** @} */ -/** - * @name Attribute: Flags - * @{ - */ - -/** - * Add flags to a route - * @arg route route to be changed - * @arg flags flags to set - */ -void rtnl_route_set_flags(struct rtnl_route *route, unsigned int flags) -{ - route->rt_flag_mask |= flags; - route->rt_flags |= flags; - route->rt_mask |= ROUTE_ATTR_FLAGS; -} - -/** - * Remove flags from a route - * @arg route route to be changed - * @arg flags flags to unset - */ -void rtnl_route_unset_flags(struct rtnl_route *route, unsigned int flags) -{ - route->rt_flag_mask |= flags; - route->rt_flags &= ~flags; - route->rt_mask |= ROUTE_ATTR_FLAGS; -} - -/** - * Get flags of a route - * @arg route route handle - */ -unsigned int rtnl_route_get_flags(struct rtnl_route *route) -{ - return route->rt_flags; -} - -/** @} */ -/** - * @name Attribute: Routing Metrics - * @{ - */ - -/** - * Set a metric of a route to the specified value - * @arg route route to be changed - * @arg metric metric to be changed (see XXX) - * @arg value new metric value - * @return 0 on sucess or a negative error code - */ -int rtnl_route_set_metric(struct rtnl_route *route, int metric, uint32_t value) -{ - if (metric <= RTAX_MAX || metric < 1) - return nl_error(EINVAL, "Metric out of range (1..%d)", - RTAX_MAX); - - route->rt_metrics[metric - 1] = value; - route->rt_metrics_mask |= (1 << (metric - 1)); - - return 0; -} - -/** - * Unset a metric of a route - * @arg route route to be changed - * @arg metric metric to be unset (see XXX) - * @return 0 on sucess or a negative error code - */ -int rtnl_route_unset_metric(struct rtnl_route *route, int metric) -{ - if (metric <= RTAX_MAX || metric < 1) - return nl_error(EINVAL, "Metric out of range (1..%d)", - RTAX_MAX); - - route->rt_metrics_mask &= ~(1 << (metric - 1)); - - return 0; -} - -/** - * Get a metric for a route - * @arg route route handle - * @arg metric metric to get - * @return The value for the specified metric or UINT_MAX if not set - */ -unsigned int rtnl_route_get_metric(struct rtnl_route *route, int metric) -{ - if (metric <= RTAX_MAX || metric < 1) - return UINT_MAX; - - if (!(route->rt_metrics_mask & (1 << (metric - 1)))) - return UINT_MAX; - - return route->rt_metrics[metric - 1]; -} - -/** @} */ -/** - * @name Attribute: Preferred Source Address - * @{ - */ - -/** - * Set the preferred source address of a route to the specified address - * @arg route route to be changed - * @arg addr new preferred source address - * - * Assigns the new preferred source address to the specified \a route, - * and sets the route's address family to the new address's family if - * it is not set already. - * - * If a address family has been specified already via either calling - * rtnl_route_set_family() or by setting one of the other addresses, - * the specified \a addr is automatically validated against this family - * and the assignment fails in case of a mismatch. - * - * @return 0 on success or a negative error code. - */ -int rtnl_route_set_pref_src(struct rtnl_route *route, struct nl_addr *addr) -{ - if (route->rt_mask & ROUTE_ATTR_FAMILY) { - if (addr->a_family != route->rt_family) - return nl_error(EINVAL, "Address family mismatch"); - } else - route->rt_family = addr->a_family; - - if (route->rt_pref_src) - nl_addr_put(route->rt_pref_src); - - nl_addr_get(addr); - route->rt_pref_src = addr; - route->rt_mask |= (ROUTE_ATTR_PREF_SRC | ROUTE_ATTR_FAMILY); - - return 0; -} - -/** - * Get the preferred source address of a route - * @arg route route handle - * @return Preferred source address or NULL if not set - */ -struct nl_addr *rtnl_route_get_pref_src(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_PREF_SRC) - return route->rt_pref_src; - else - return NULL; -} - -/** @} */ -/** - * @name Attribute: Outgoing Interface Index - * @{ - */ - -/** - * Set the outgoing interface of a route to the specified value - * @arg route route to be changed - * @arg ifindex interface index of new outoing interface - */ -void rtnl_route_set_oif(struct rtnl_route *route, int ifindex) -{ - route->rt_oif = ifindex; - route->rt_mask |= ROUTE_ATTR_OIF; -} - -/** - * Get the outgoing interface index of a route - * @arg route route handle - * @return interface index or RTNL_LINK_NOT_FOUND if not set - */ -int rtnl_route_get_oif(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_OIF) - return route->rt_oif; - else - return RTNL_LINK_NOT_FOUND; -} - -/** @} */ -/** - * @name Attribute: Incoming Interface - * @{ - */ - -/** - * Set the incoming interface of a route to the specified value - * @arg route route to be changed - * @arg name interface name of the new incoming interface - */ -void rtnl_route_set_iif(struct rtnl_route *route, const char *name) -{ - strncpy(route->rt_iif, name, sizeof(route->rt_iif) - 1); - route->rt_mask |= ROUTE_ATTR_IIF; -} - -/** - * Get the incomming interface name of a route - * @arg route route handle - * @return interface name or NULL if not set - */ -char *rtnl_route_get_iif(struct rtnl_route *route) -{ - if (route->rt_mask & ROUTE_ATTR_IIF) - return route->rt_iif; - else - return NULL; -} - -#if 0 - struct rtnl_rtcacheinfo rt_cacheinfo; -#endif - -/** @} */ -/** - * @name Attribute: Nexthop - * @{ - */ - -void rtnl_route_add_nexthop(struct rtnl_route *route, struct rtnl_nexthop *nh) -{ - nl_list_add_tail(&nh->rtnh_list, &route->rt_nexthops); - route->rt_mask |= ROUTE_ATTR_MULTIPATH; -} - -void rtnl_route_remove_nexthop(struct rtnl_nexthop *nh) -{ - nl_list_del(&nh->rtnh_list); -} - -struct nl_list_head *rtnl_route_get_nexthops(struct rtnl_route *route) -{ - return &route->rt_nexthops; -} - -/** @} */ - -/** - * @name Routing Table Identifier Translations - * @{ - */ - -static struct trans_tbl route_tables[] = { - __ADD(RT_TABLE_UNSPEC, unspec) - __ADD(RT_TABLE_DEFAULT, default) - __ADD(RT_TABLE_MAIN, main) - __ADD(RT_TABLE_LOCAL, local) -}; - -/** - * Convert routing table identifier to character string. - * @arg table Routing table identifier. - * @arg buf Destination buffer - * @arg size Size of destination buffer. - * - * Converts a routing table identifier to a character string and stores - * it in the specified destination buffer. - * - * @return The destination buffer or the type encoded in hexidecimal - * form if the routing table identifier is unknown. - */ -char *rtnl_route_table2str(int table, char *buf, size_t size) -{ - return __type2str(table, buf, size, route_tables, - ARRAY_SIZE(route_tables)); -} - -/** - * Convert character string to routing table identifier. - * @arg name Name of routing table. - * - * Converts the provided character string specifying a routing table - * identifier to the corresponding numeric value. - * - * @return Routing table identifier or a negative value if no match was found. - */ -int rtnl_route_str2table(const char *name) -{ - return __str2type(name, route_tables, ARRAY_SIZE(route_tables)); -} - - -/** @} */ - -/** - * @name Routing Protocol Translations - * @{ - */ - -static struct trans_tbl route_protos[] = { - __ADD(RTPROT_UNSPEC, unspec) - __ADD(RTPROT_REDIRECT, redirect) - __ADD(RTPROT_KERNEL, kernel) - __ADD(RTPROT_BOOT, boot) - __ADD(RTPROT_STATIC, static) -}; - -/** - * Convert routing protocol identifier to character string. - * @arg proto Routing protocol identifier. - * @arg buf Destination buffer - * @arg size Size of destination buffer. - * - * Converts a routing protocol identifier to a character string and stores - * it in the specified destination buffer. - * - * @return The destination buffer or the protocol encoded in hexidecimal - * form if the routing protocol is unknown. - */ -char *rtnl_route_proto2str(int proto, char *buf, size_t size) -{ - return __type2str(proto, buf, size, route_protos, - ARRAY_SIZE(route_protos)); -} - -/** - * Convert character string to routing protocol identifier. - * @arg name Name of routing protocol. - * - * Converts the provided character string specifying a routing protocl - * identifier to the corresponding numeric value. - * - * @return Routing protocol dentifier or a negative value if no match was found. - */ -int rtnl_route_str2proto(const char *name) -{ - return __str2type(name, route_protos, ARRAY_SIZE(route_protos)); -} - -/** @} */ - -/** - * @name Routing Metrices Translations - * @{ - */ - -static struct trans_tbl route_metrices[] = { - __ADD(RTAX_UNSPEC, unspec) - __ADD(RTAX_LOCK, lock) - __ADD(RTAX_MTU, mtu) - __ADD(RTAX_WINDOW, window) - __ADD(RTAX_RTT, rtt) - __ADD(RTAX_RTTVAR, rttvar) - __ADD(RTAX_SSTHRESH, ssthresh) - __ADD(RTAX_CWND, cwnd) - __ADD(RTAX_ADVMSS, advmss) - __ADD(RTAX_REORDERING, reordering) - __ADD(RTAX_HOPLIMIT, hoplimit) - __ADD(RTAX_INITCWND, initcwnd) - __ADD(RTAX_FEATURES, features) -}; - -/** - * Convert routing metric identifier to character string. - * @arg metric Routing metric identifier. - * @arg buf Destination buffer - * @arg size Size of destination buffer. - * - * Converts a routing metric identifier to a character string and stores - * it in the specified destination buffer. - * - * @return The destination buffer or the metric encoded in hexidecimal - * form if the routing metric identifier is unknown. - */ -char *rtnl_route_metric2str(int metric, char *buf, size_t size) -{ - return __type2str(metric, buf, size, route_metrices, - ARRAY_SIZE(route_metrices)); -} - -/** - * Convert character string to routing metric identifier. - * @arg name Name of routing metric. - * - * Converts the provided character string specifying a routing metric - * identifier to the corresponding numeric value. - * - * @return Routing metric dentifier or a negative value if no match was found. - */ -int rtnl_route_str2metric(const char *name) -{ - return __str2type(name, route_metrices, ARRAY_SIZE(route_metrices)); -} - -/** @} */ - -/** - * @name Nexthop Flags Translations - * @{ - */ - -static struct trans_tbl nh_flags[] = { - __ADD(RTNH_F_DEAD, dead) - __ADD(RTNH_F_PERVASIVE, pervasive) - __ADD(RTNH_F_ONLINK, onlink) -}; - -/** - * Convert nexthop flags to a character string. - * @arg flags Nexthop flags. - * @arg buf Destination buffer. - * @arg len Length of destination buffer. - * - * Converts nexthop flags to a character string separated by - * commas and stores it in the specified destination buffer. - * - * \return The destination buffer - */ -char * rtnl_route_nh_flags2str(int flags, char *buf, size_t len) -{ - return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags)); -} - -/** - * Convert a character string to a nexthop flag - * @arg name Name of nexthop flag. - * - * Converts the provided character string specifying a nexthop - * flag to the corresponding numeric value. - * - * \return Nexthop flag or a negative value if none was found. - */ -int rtnl_route_nh_str2flags(const char *name) -{ - return __str2flags(name, nh_flags, ARRAY_SIZE(nh_flags)); -} - -/** @} */ - -static struct nl_cache_ops rtnl_route_ops = { - .co_name = "route/route", - .co_size = sizeof(struct rtnl_route), - .co_hdrsize = sizeof(struct rtmsg), - .co_msgtypes = { - { RTM_NEWROUTE, "new" }, - { RTM_DELROUTE, "delete" }, - { RTM_GETROUTE, "get" }, - { -1, NULL }, - }, - .co_protocol = NETLINK_ROUTE, - .co_request_update = route_request_update, - .co_msg_parser = route_msg_parser, - .co_constructor = route_constructor, - .co_free_data = route_free_data, - .co_dump[NL_DUMP_BRIEF] = route_dump_brief, - .co_dump[NL_DUMP_FULL] = route_dump_full, - .co_dump[NL_DUMP_STATS] = route_dump_stats, - .co_dump[NL_DUMP_XML] = route_dump_xml, - .co_dump[NL_DUMP_ENV] = route_dump_env, - .co_filter = route_filter, -}; - -static void __init route_init(void) -{ - nl_cache_mngt_register(&rtnl_route_ops); -} - -static void __exit route_exit(void) -{ - nl_cache_mngt_unregister(&rtnl_route_ops); -} - -/** @} */