/build/buildd/libnl-1.0~pre6/lib/route/route.c

00001 /*
00002  * lib/route/route.c    Routes
00003  *
00004  *      This library is free software; you can redistribute it and/or
00005  *      modify it under the terms of the GNU Lesser General Public
00006  *      License as published by the Free Software Foundation version 2.1
00007  *      of the License.
00008  *
00009  * Copyright (c) 2003-2006 Thomas Graf <tgraf@suug.ch>
00010  */
00011 
00012 /**
00013  * @ingroup rtnl
00014  * @defgroup route Routing
00015  * @brief
00016  * @{
00017  */
00018 
00019 #include <netlink-local.h>
00020 #include <netlink/netlink.h>
00021 #include <netlink/cache.h>
00022 #include <netlink/utils.h>
00023 #include <netlink/data.h>
00024 #include <netlink/route/rtnl.h>
00025 #include <netlink/route/route.h>
00026 #include <netlink/route/link.h>
00027 
00028 /** @cond SKIP */
00029 #define ROUTE_ATTR_FAMILY    0x000001
00030 #define ROUTE_ATTR_DST_LEN   0x000002
00031 #define ROUTE_ATTR_SRC_LEN   0x000004
00032 #define ROUTE_ATTR_TOS       0x000008
00033 #define ROUTE_ATTR_TABLE     0x000010
00034 #define ROUTE_ATTR_PROTOCOL  0x000020
00035 #define ROUTE_ATTR_SCOPE     0x000040
00036 #define ROUTE_ATTR_TYPE      0x000080
00037 #define ROUTE_ATTR_FLAGS     0x000100
00038 #define ROUTE_ATTR_DST       0x000200
00039 #define ROUTE_ATTR_SRC       0x000400
00040 #define ROUTE_ATTR_IIF       0x000800
00041 #define ROUTE_ATTR_OIF       0x001000
00042 #define ROUTE_ATTR_GATEWAY   0x002000
00043 #define ROUTE_ATTR_PRIO      0x004000
00044 #define ROUTE_ATTR_PREF_SRC  0x008000
00045 #define ROUTE_ATTR_METRICS   0x010000
00046 #define ROUTE_ATTR_MULTIPATH 0x020000
00047 #define ROUTE_ATTR_REALMS    0x040000
00048 #define ROUTE_ATTR_CACHEINFO 0x080000
00049 #define ROUTE_ATTR_MP_ALGO   0x100000
00050 
00051 #define NEXTHOP_HAS_FLAGS   0x000001
00052 #define NEXTHOP_HAS_WEIGHT  0x000002
00053 #define NEXTHOP_HAS_IFINDEX 0x000004
00054 #define NEXTHOP_HAS_GATEWAY 0x000008
00055 
00056 static struct nl_cache_ops rtnl_route_ops;
00057 /** @endcond */
00058 
00059 static void route_constructor(struct nl_object *c)
00060 {
00061         struct rtnl_route *r = (struct rtnl_route *) c;
00062 
00063         nl_init_list_head(&r->rt_nexthops);
00064 }
00065 
00066 static void route_free_data(struct nl_object *c)
00067 {
00068         struct rtnl_route *r = (struct rtnl_route *) c;
00069         struct rtnl_nexthop *nh, *tmp;
00070 
00071         if (r == NULL)
00072                 return;
00073 
00074         nl_addr_put(r->rt_dst);
00075         nl_addr_put(r->rt_src);
00076         nl_addr_put(r->rt_gateway);
00077         nl_addr_put(r->rt_pref_src);
00078 
00079         nl_list_for_each_entry_safe(nh, tmp, &r->rt_nexthops, rtnh_list) {
00080                 rtnl_route_remove_nexthop(nh);
00081                 rtnl_route_nh_free(nh);
00082         }
00083 }
00084 
00085 static struct nla_policy route_policy[RTA_MAX+1] = {
00086         [RTA_IIF]       = { .type = NLA_STRING,
00087                             .maxlen = IFNAMSIZ, },
00088         [RTA_OIF]       = { .type = NLA_U32 },
00089         [RTA_PRIORITY]  = { .type = NLA_U32 },
00090         [RTA_FLOW]      = { .type = NLA_U32 },
00091         [RTA_MP_ALGO]   = { .type = NLA_U32 },
00092         [RTA_CACHEINFO] = { .minlen = sizeof(struct rta_cacheinfo) },
00093         [RTA_METRICS]   = { .type = NLA_NESTED },
00094         [RTA_MULTIPATH] = { .type = NLA_NESTED },
00095 };
00096 
00097 static void copy_rtmsg_into_route(struct rtmsg *rtmsg, struct rtnl_route *route)
00098 {
00099         route->rt_family        = rtmsg->rtm_family;
00100         route->rt_dst_len       = rtmsg->rtm_dst_len;
00101         route->rt_src_len       = rtmsg->rtm_src_len;
00102         route->rt_tos           = rtmsg->rtm_tos;
00103         route->rt_table         = rtmsg->rtm_table;
00104         route->rt_type          = rtmsg->rtm_type;
00105         route->rt_scope         = rtmsg->rtm_scope;
00106         route->rt_protocol      = rtmsg->rtm_protocol;
00107         route->rt_flags         = rtmsg->rtm_flags;
00108 
00109         route->rt_mask = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_DST_LEN | 
00110                           ROUTE_ATTR_SRC_LEN | ROUTE_ATTR_TABLE |
00111                           ROUTE_ATTR_PROTOCOL| ROUTE_ATTR_SCOPE |
00112                           ROUTE_ATTR_TYPE | ROUTE_ATTR_FLAGS);
00113 
00114         if (route->rt_tos)
00115                 route->rt_mask |= ROUTE_ATTR_TOS;
00116 }
00117 
00118 static void copy_cacheinfo_into_route(struct rta_cacheinfo *ci,
00119                                       struct rtnl_route *route)
00120 {
00121         route->rt_cacheinfo.rtci_clntref  = ci->rta_clntref;
00122         route->rt_cacheinfo.rtci_last_use = ci->rta_lastuse;
00123         route->rt_cacheinfo.rtci_expires  = ci->rta_expires;
00124         route->rt_cacheinfo.rtci_error    = ci->rta_error;
00125         route->rt_cacheinfo.rtci_used     = ci->rta_used;
00126         route->rt_cacheinfo.rtci_id       = ci->rta_id;
00127         route->rt_cacheinfo.rtci_ts       = ci->rta_ts;
00128         route->rt_cacheinfo.rtci_tsage    = ci->rta_tsage;
00129 
00130         route->rt_mask |= ROUTE_ATTR_CACHEINFO;
00131 }
00132 
00133 static int route_msg_parser(struct sockaddr_nl *who, struct nlmsghdr *nlh,
00134                             void *arg)
00135 {
00136         struct nl_parser_param *pp = arg;
00137         struct rtnl_route *route;
00138         struct nlattr *tb[RTA_MAX + 1];
00139         int err;
00140 
00141         route = rtnl_route_alloc();
00142         if (!route) {
00143                 err = nl_errno(ENOMEM);
00144                 goto errout;
00145         }
00146 
00147         route->ce_msgtype = nlh->nlmsg_type;
00148 
00149         err = nlmsg_parse(nlh, sizeof(struct rtmsg), tb, RTA_MAX,
00150                           route_policy);
00151         if (err < 0)
00152                 goto errout;
00153 
00154         copy_rtmsg_into_route((struct rtmsg *) nlmsg_data(nlh), route);
00155 
00156         if (tb[RTA_DST]) {
00157                 route->rt_dst = nla_get_addr(tb[RTA_DST], route->rt_family);
00158                 if (!route->rt_dst)
00159                         goto errout_errno;
00160                 nl_addr_set_prefixlen(route->rt_dst, route->rt_dst_len);
00161                 route->rt_mask |= ROUTE_ATTR_DST;
00162         }
00163 
00164         if (tb[RTA_SRC]) {
00165                 route->rt_src = nla_get_addr(tb[RTA_SRC], route->rt_family);
00166                 if (!route->rt_src)
00167                         goto errout_errno;
00168                 nl_addr_set_prefixlen(route->rt_src, route->rt_src_len);
00169                 route->rt_mask |= ROUTE_ATTR_SRC;
00170         }
00171 
00172         if (tb[RTA_IIF]) {
00173                 nla_strlcpy(route->rt_iif, tb[RTA_IIF], IFNAMSIZ);
00174                 route->rt_mask |= ROUTE_ATTR_IIF;
00175         }
00176 
00177         if (tb[RTA_OIF]) {
00178                 route->rt_oif = nla_get_u32(tb[RTA_OIF]);
00179                 route->rt_mask |= ROUTE_ATTR_OIF;
00180         }
00181 
00182         if (tb[RTA_GATEWAY]) {
00183                 route->rt_gateway = nla_get_addr(tb[RTA_GATEWAY],
00184                                                  route->rt_family);
00185                 if (!route->rt_gateway)
00186                         goto errout_errno;
00187                 route->rt_mask |= ROUTE_ATTR_GATEWAY;
00188         }
00189 
00190         if (tb[RTA_PRIORITY]) {
00191                 route->rt_prio = nla_get_u32(tb[RTA_PRIORITY]);
00192                 route->rt_mask |= ROUTE_ATTR_PRIO;
00193         }
00194 
00195         if (tb[RTA_PREFSRC]) {
00196                 route->rt_pref_src = nla_get_addr(tb[RTA_PREFSRC],
00197                                                   route->rt_family);
00198                 if (!route->rt_pref_src)
00199                         goto errout_errno;
00200                 route->rt_mask |= ROUTE_ATTR_PREF_SRC;
00201         }
00202 
00203         if (tb[RTA_METRICS]) {
00204                 struct nlattr *mtb[RTAX_MAX + 1];
00205                 int i;
00206 
00207                 err = nla_parse_nested(mtb, RTAX_MAX, tb[RTA_METRICS], NULL);
00208                 if (err < 0)
00209                         goto errout;
00210 
00211                 for (i = 1; i <= RTAX_MAX; i++) {
00212                         if (mtb[i] && nla_len(mtb[i]) >= sizeof(uint32_t)) {
00213                                 uint32_t m = nla_get_u32(mtb[i]);
00214                                 route->rt_metrics[i-1] = m;
00215                                 route->rt_metrics_mask |= (1 << (i - 1));
00216                         }
00217                 }
00218                 
00219                 route->rt_mask |= ROUTE_ATTR_METRICS;
00220         }
00221 
00222         if (tb[RTA_MULTIPATH]) {
00223                 struct rtnl_nexthop *nh;
00224                 struct rtnexthop *rtnh = nla_data(tb[RTA_MULTIPATH]);
00225                 size_t tlen = nla_len(tb[RTA_MULTIPATH]);
00226 
00227                 while (tlen >= sizeof(*rtnh) && tlen >= rtnh->rtnh_len) {
00228                         nh = rtnl_route_nh_alloc();
00229                         if (!nh)
00230                                 goto errout;
00231 
00232                         rtnl_route_nh_set_weight(nh, rtnh->rtnh_hops);
00233                         rtnl_route_nh_set_ifindex(nh, rtnh->rtnh_ifindex);
00234                         rtnl_route_nh_set_flags(nh, rtnh->rtnh_flags);
00235 
00236                         if (rtnh->rtnh_len > sizeof(*rtnh)) {
00237                                 struct nlattr *ntb[RTA_MAX + 1];
00238                                 nla_parse(ntb, RTA_MAX, (struct nlattr *)
00239                                           RTNH_DATA(rtnh),
00240                                           rtnh->rtnh_len - sizeof(*rtnh),
00241                                           route_policy);
00242 
00243                                 if (ntb[RTA_GATEWAY]) {
00244                                         nh->rtnh_gateway = nla_get_addr(
00245                                                         ntb[RTA_GATEWAY],
00246                                                         route->rt_family);
00247                                         nh->rtnh_mask = NEXTHOP_HAS_GATEWAY;
00248                                 }
00249                         }
00250 
00251                         rtnl_route_add_nexthop(route, nh);
00252                         tlen -= RTNH_ALIGN(rtnh->rtnh_len);
00253                         rtnh = RTNH_NEXT(rtnh);
00254                 }
00255         }
00256 
00257         if (tb[RTA_FLOW]) {
00258                 route->rt_realms = nla_get_u32(tb[RTA_FLOW]);
00259                 route->rt_mask |= ROUTE_ATTR_REALMS;
00260         }
00261 
00262         if (tb[RTA_CACHEINFO])
00263                 copy_cacheinfo_into_route(nla_data(tb[RTA_CACHEINFO]), route);
00264 
00265         if (tb[RTA_MP_ALGO]) {
00266                 route->rt_mp_algo = nla_get_u32(tb[RTA_MP_ALGO]);
00267                 route->rt_mask |= ROUTE_ATTR_MP_ALGO;
00268         }
00269 
00270         err = pp->pp_cb((struct nl_object *) route, pp);
00271         if (err < 0)
00272                 goto errout;
00273 
00274         return P_ACCEPT;
00275 
00276 errout_errno:
00277         err = nl_get_errno();
00278 errout:
00279         rtnl_route_put(route);
00280         return err;
00281 
00282 }
00283 
00284 static int route_request_update(struct nl_cache *c, struct nl_handle *h)
00285 {
00286         return nl_rtgen_request(h, RTM_GETROUTE, AF_UNSPEC, NLM_F_DUMP);
00287 }
00288 
00289 static int route_dump_brief(struct nl_object *a, struct nl_dump_params *p)
00290 {
00291         struct rtnl_route *r = (struct rtnl_route *) a;
00292         struct nl_cache *link_cache;
00293         char buf[64];
00294 
00295         link_cache = nl_cache_mngt_require("route/link");
00296 
00297         if (r->rt_mask & ROUTE_ATTR_DST)
00298                 dp_dump(p, "%s ", nl_addr2str(r->rt_dst, buf, sizeof(buf)));
00299         else if (r->rt_dst_len)
00300                 dp_dump(p, "0/%u ", r->rt_dst_len);
00301         else
00302                 dp_dump(p, "default ");
00303 
00304         if (r->rt_mask & ROUTE_ATTR_OIF) {
00305                 if (link_cache)
00306                         dp_dump(p, "dev %s ",
00307                                 rtnl_link_i2name(link_cache, r->rt_oif,
00308                                                  buf, sizeof(buf)));
00309                 else
00310                         dp_dump(p, "dev %d ", r->rt_oif);
00311         }
00312 
00313         if (r->rt_mask & ROUTE_ATTR_GATEWAY)
00314                 dp_dump(p, "via %s ", nl_addr2str(r->rt_gateway, buf,
00315                                                   sizeof(buf)));
00316         else if (r->rt_mask & ROUTE_ATTR_MULTIPATH)
00317                 dp_dump(p, "via nexthops ");
00318 
00319         if (r->rt_mask & ROUTE_ATTR_TABLE)
00320                 dp_dump(p, "table %s ",
00321                         rtnl_route_table2str(r->rt_table, buf, sizeof(buf)));
00322 
00323         if (r->rt_mask & ROUTE_ATTR_SCOPE)
00324                 dp_dump(p, "scope %s ",
00325                         rtnl_scope2str(r->rt_scope, buf, sizeof(buf)));
00326 
00327         if (r->rt_mask & ROUTE_ATTR_FLAGS && r->rt_flags) {
00328                 int flags = r->rt_flags;
00329 
00330                 dp_dump(p, "<");
00331                 
00332 #define PRINT_FLAG(f) if (flags & RTNH_F_##f) { \
00333                 flags &= ~RTNH_F_##f; dp_dump(p, #f "%s", flags ? "," : ""); }
00334                 PRINT_FLAG(DEAD);
00335                 PRINT_FLAG(ONLINK);
00336                 PRINT_FLAG(PERVASIVE);
00337 #undef PRINT_FLAG
00338 
00339 #define PRINT_FLAG(f) if (flags & RTM_F_##f) { \
00340                 flags &= ~RTM_F_##f; dp_dump(p, #f "%s", flags ? "," : ""); }
00341                 PRINT_FLAG(NOTIFY);
00342                 PRINT_FLAG(CLONED);
00343                 PRINT_FLAG(EQUALIZE);
00344                 PRINT_FLAG(PREFIX);
00345 #undef PRINT_FLAG
00346 
00347                 dp_dump(p, ">");
00348         }
00349 
00350         dp_dump(p, "\n");
00351 
00352         return 1;
00353 }
00354 
00355 static int route_dump_full(struct nl_object *a, struct nl_dump_params *p)
00356 {
00357         struct rtnl_route *r = (struct rtnl_route *) a;
00358         struct nl_cache *link_cache;
00359         char buf[128];
00360         int i, line;
00361 
00362         link_cache = nl_cache_mngt_require("route/link");
00363         line = route_dump_brief(a, p);
00364 
00365         if (r->rt_mask & ROUTE_ATTR_MULTIPATH) {
00366                 struct rtnl_nexthop *nh;
00367 
00368                 dp_dump_line(p, line++, "  ");
00369 
00370                 nl_list_for_each_entry(nh, &r->rt_nexthops, rtnh_list) {
00371                         dp_dump(p, "nh ");
00372 
00373                         if (nh->rtnh_mask & NEXTHOP_HAS_GATEWAY)
00374                                 dp_dump(p, "via %s ",
00375                                         nl_addr2str(nh->rtnh_gateway,
00376                                                     buf, sizeof(buf)));
00377                         if (link_cache)
00378                                 dp_dump(p, "dev %s ",
00379                                         rtnl_link_i2name(link_cache,
00380                                                          nh->rtnh_ifindex,
00381                                                          buf, sizeof(buf)));
00382                         else
00383                                 dp_dump(p, "dev %d ", nh->rtnh_ifindex);
00384 
00385                         dp_dump(p, "weight %u <%s> ", nh->rtnh_weight,
00386                                 rtnl_route_nh_flags2str(nh->rtnh_flags,
00387                                                         buf, sizeof(buf)));
00388                 }
00389 
00390                 dp_dump(p, "\n");
00391         }
00392 
00393         dp_dump_line(p, line++, "  ");
00394 
00395         if (r->rt_mask & ROUTE_ATTR_PREF_SRC)
00396                 dp_dump(p, "preferred-src %s ",
00397                         nl_addr2str(r->rt_pref_src, buf, sizeof(buf)));
00398 
00399         if (r->rt_mask & ROUTE_ATTR_TYPE)
00400                 dp_dump(p, "type %s ",
00401                         nl_rtntype2str(r->rt_type, buf, sizeof(buf)));
00402 
00403         if (r->rt_mask & ROUTE_ATTR_PRIO)
00404                 dp_dump(p, "metric %#x ", r->rt_prio);
00405 
00406         if (r->rt_mask & ROUTE_ATTR_FAMILY)
00407                 dp_dump(p, "family %s ",
00408                         nl_af2str(r->rt_family, buf, sizeof(buf)));
00409 
00410         if (r->rt_mask & ROUTE_ATTR_PROTOCOL)
00411                 dp_dump(p, "protocol %s ",
00412                         rtnl_route_proto2str(r->rt_protocol, buf, sizeof(buf)));
00413 
00414         dp_dump(p, "\n");
00415 
00416         if ((r->rt_mask & (ROUTE_ATTR_IIF | ROUTE_ATTR_SRC | ROUTE_ATTR_TOS |
00417                            ROUTE_ATTR_REALMS)) || r->rt_src_len ||
00418             ((r->rt_mask & ROUTE_ATTR_CACHEINFO) &&
00419              r->rt_cacheinfo.rtci_error)) {
00420                 dp_dump_line(p, line++, "  ");
00421 
00422                 if (r->rt_mask & ROUTE_ATTR_IIF)
00423                         dp_dump(p, "iif %s ", r->rt_iif);
00424 
00425                 if (r->rt_mask & ROUTE_ATTR_SRC)
00426                         dp_dump(p, "src %s ",
00427                                 nl_addr2str(r->rt_src, buf, sizeof(buf)));
00428                 else if (r->rt_src_len)
00429                         dp_dump(p, "src 0/%u ", r->rt_src_len);
00430 
00431                 if (r->rt_mask & ROUTE_ATTR_TOS)
00432                         dp_dump(p, "tos %#x ", r->rt_tos);
00433 
00434                 if (r->rt_mask & ROUTE_ATTR_REALMS)
00435                         dp_dump(p, "realm %04x:%04x ",
00436                                 RTNL_REALM_FROM(r->rt_realms),
00437                                 RTNL_REALM_TO(r->rt_realms));
00438 
00439                 if ((r->rt_mask & ROUTE_ATTR_CACHEINFO) &&
00440                     r->rt_cacheinfo.rtci_error)
00441                         dp_dump(p, "error %d (%s) ", r->rt_cacheinfo.rtci_error,
00442                                 strerror(-r->rt_cacheinfo.rtci_error));
00443 
00444                 dp_dump(p, "\n");
00445         }
00446 
00447         if (r->rt_mask & ROUTE_ATTR_METRICS) {
00448                 dp_dump_line(p, line++, "  ");
00449                 for (i = 0; i < RTAX_MAX; i++)
00450                         if (r->rt_metrics_mask & (1 << i))
00451                                 dp_dump(p, "%s %u ",
00452                                         rtnl_route_metric2str(i+1,
00453                                                               buf, sizeof(buf)),
00454                                         r->rt_metrics[i]);
00455                 dp_dump(p, "\n");
00456         }
00457 
00458         return line;
00459 }
00460 
00461 static int route_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00462 {
00463         struct rtnl_route *route = (struct rtnl_route *) obj;
00464         int line;
00465 
00466         line = route_dump_full(obj, p);
00467 
00468         if (route->rt_mask & ROUTE_ATTR_CACHEINFO) {
00469                 struct rtnl_rtcacheinfo *ci = &route->rt_cacheinfo;
00470                 dp_dump_line(p, line++, "  used %u refcnt %u ",
00471                              ci->rtci_used, ci->rtci_clntref);
00472                 dp_dump_line(p, line++, "last-use %us expires %us\n",
00473                              ci->rtci_last_use / nl_get_hz(),
00474                              ci->rtci_expires / nl_get_hz());
00475         }
00476 
00477         return line;
00478 }
00479 
00480 static int route_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
00481 {
00482         struct rtnl_route *route = (struct rtnl_route *) obj;
00483         char buf[128];
00484         int line = 0;
00485         
00486         dp_dump_line(p, line++, "<route>\n");
00487         dp_dump_line(p, line++, "  <family>%s</family>\n",
00488                      nl_af2str(route->rt_family, buf, sizeof(buf)));
00489 
00490         if (route->rt_mask & ROUTE_ATTR_DST)
00491                 dp_dump_line(p, line++, "  <dst>%s</dst>\n",
00492                              nl_addr2str(route->rt_dst, buf, sizeof(buf)));
00493 
00494         if (route->rt_mask & ROUTE_ATTR_DST_LEN)
00495                 dp_dump_line(p, line++, "  <dstlen>%u</dstlen>\n",
00496                              route->rt_dst_len);
00497 
00498         if (route->rt_mask & ROUTE_ATTR_SRC)
00499                 dp_dump_line(p, line++, "  <src>%s</src>\n",
00500                              nl_addr2str(route->rt_src, buf, sizeof(buf)));
00501 
00502         if (route->rt_mask & ROUTE_ATTR_SRC_LEN)
00503                 dp_dump_line(p, line++, "  <srclen>%u</srclen>\n",
00504                              route->rt_src_len);
00505 
00506         if (route->rt_mask & ROUTE_ATTR_GATEWAY)
00507                 dp_dump_line(p, line++, "  <gateway>%s</gateway>\n",
00508                              nl_addr2str(route->rt_gateway, buf, sizeof(buf)));
00509 
00510         if (route->rt_mask & ROUTE_ATTR_PREF_SRC)
00511                 dp_dump_line(p, line++, "  <prefsrc>%s</prefsrc>\n",
00512                              nl_addr2str(route->rt_pref_src, buf, sizeof(buf)));
00513 
00514         if (route->rt_mask & ROUTE_ATTR_IIF)
00515                 dp_dump_line(p, line++, "  <iif>%s</iif>\n", route->rt_iif);
00516 
00517         if (route->rt_mask & ROUTE_ATTR_REALMS)
00518                 dp_dump_line(p, line++, "  <realms>%u</realms>\n",
00519                              route->rt_realms);
00520 
00521         if (route->rt_mask & ROUTE_ATTR_TOS)
00522                 dp_dump_line(p, line++, "  <tos>%u</tos>\n", route->rt_tos);
00523 
00524         if (route->rt_mask & ROUTE_ATTR_TABLE)
00525                 dp_dump_line(p, line++, "  <table>%u</table>\n",
00526                              route->rt_table);
00527 
00528         if (route->rt_mask & ROUTE_ATTR_SCOPE)
00529                 dp_dump_line(p, line++, "  <scope>%s</scope>\n",
00530                              rtnl_scope2str(route->rt_scope, buf, sizeof(buf)));
00531 
00532         if (route->rt_mask & ROUTE_ATTR_PRIO)
00533                 dp_dump_line(p, line++, "  <metric>%u</metric>\n",
00534                              route->rt_prio);
00535 
00536         if (route->rt_mask & ROUTE_ATTR_OIF) {
00537                 struct nl_cache *link_cache;
00538         
00539                 link_cache = nl_cache_mngt_require("route/link");
00540                 if (link_cache)
00541                         dp_dump_line(p, line++, "  <oif>%s</oif>\n",
00542                                      rtnl_link_i2name(link_cache,
00543                                                       route->rt_oif,
00544                                                       buf, sizeof(buf)));
00545                 else
00546                         dp_dump_line(p, line++, "  <oif>%u</oif>\n",
00547                                      route->rt_oif);
00548         }
00549 
00550         if (route->rt_mask & ROUTE_ATTR_TYPE)
00551                 dp_dump_line(p, line++, "  <type>%s</type>\n",
00552                              nl_rtntype2str(route->rt_type, buf, sizeof(buf)));
00553 
00554         dp_dump_line(p, line++, "</route>\n");
00555 
00556 #if 0
00557         uint8_t                 rt_protocol;
00558         uint32_t                rt_flags;
00559         uint32_t                rt_metrics[RTAX_MAX];
00560         uint32_t                rt_metrics_mask;
00561         struct rtnl_nexthop *   rt_nexthops;
00562         struct rtnl_rtcacheinfo rt_cacheinfo;
00563         uint32_t                rt_mp_algo;
00564 
00565 #endif
00566 
00567         return line;
00568 }
00569 
00570 static int route_dump_env(struct nl_object *obj, struct nl_dump_params *p)
00571 {
00572         struct rtnl_route *route = (struct rtnl_route *) obj;
00573         char buf[128];
00574         int line = 0;
00575 
00576         dp_dump_line(p, line++, "ROUTE_FAMILY=%s\n",
00577                      nl_af2str(route->rt_family, buf, sizeof(buf)));
00578 
00579         if (route->rt_mask & ROUTE_ATTR_DST)
00580                 dp_dump_line(p, line++, "ROUTE_DST=%s\n",
00581                              nl_addr2str(route->rt_dst, buf, sizeof(buf)));
00582 
00583         if (route->rt_mask & ROUTE_ATTR_DST_LEN)
00584                 dp_dump_line(p, line++, "ROUTE_DSTLEN=%u\n",
00585                              route->rt_dst_len);
00586 
00587         if (route->rt_mask & ROUTE_ATTR_SRC)
00588                 dp_dump_line(p, line++, "ROUTE_SRC=%s\n",
00589                              nl_addr2str(route->rt_src, buf, sizeof(buf)));
00590 
00591         if (route->rt_mask & ROUTE_ATTR_SRC_LEN)
00592                 dp_dump_line(p, line++, "ROUTE_SRCLEN=%u\n",
00593                              route->rt_src_len);
00594 
00595         if (route->rt_mask & ROUTE_ATTR_GATEWAY)
00596                 dp_dump_line(p, line++, "ROUTE_GATEWAY=%s\n",
00597                              nl_addr2str(route->rt_gateway, buf, sizeof(buf)));
00598 
00599         if (route->rt_mask & ROUTE_ATTR_PREF_SRC)
00600                 dp_dump_line(p, line++, "ROUTE_PREFSRC=%s\n",
00601                              nl_addr2str(route->rt_pref_src, buf, sizeof(buf)));
00602 
00603         if (route->rt_mask & ROUTE_ATTR_IIF)
00604                 dp_dump_line(p, line++, "ROUTE_IIF=%s\n", route->rt_iif);
00605 
00606         if (route->rt_mask & ROUTE_ATTR_REALMS)
00607                 dp_dump_line(p, line++, "ROUTE_REALM=%u\n",
00608                              route->rt_realms);
00609 
00610         if (route->rt_mask & ROUTE_ATTR_TOS)
00611                 dp_dump_line(p, line++, "ROUTE_TOS=%u\n", route->rt_tos);
00612 
00613         if (route->rt_mask & ROUTE_ATTR_TABLE)
00614                 dp_dump_line(p, line++, "ROUTE_TABLE=%u\n",
00615                              route->rt_table);
00616 
00617         if (route->rt_mask & ROUTE_ATTR_SCOPE)
00618                 dp_dump_line(p, line++, "ROUTE_SCOPE=%s\n",
00619                              rtnl_scope2str(route->rt_scope, buf, sizeof(buf)));
00620 
00621         if (route->rt_mask & ROUTE_ATTR_PRIO)
00622                 dp_dump_line(p, line++, "ROUTE_METRIC=%u\n",
00623                              route->rt_prio);
00624 
00625         if (route->rt_mask & ROUTE_ATTR_OIF) {
00626                 struct nl_cache *link_cache;
00627 
00628                 dp_dump_line(p, line++, "ROUTE_OIF_IFINDEX=%u\n",
00629                              route->rt_oif);
00630 
00631                 link_cache = nl_cache_mngt_require("route/link");
00632                 if (link_cache)
00633                         dp_dump_line(p, line++, "ROUTE_OIF_IFNAME=%s\n",
00634                                      rtnl_link_i2name(link_cache,
00635                                                       route->rt_oif,
00636                                                       buf, sizeof(buf)));
00637         }
00638 
00639         if (route->rt_mask & ROUTE_ATTR_TYPE)
00640                 dp_dump_line(p, line++, "ROUTE_TYPE=%s\n",
00641                              nl_rtntype2str(route->rt_type, buf, sizeof(buf)));
00642 
00643         return line;
00644 }
00645 
00646 static int route_filter(struct nl_object *obj, struct nl_object *filter)
00647 {
00648         struct rtnl_route *o = (struct rtnl_route *) obj;
00649         struct rtnl_route *f = (struct rtnl_route *) filter;
00650 
00651 #define REQ(F) (f->rt_mask & ROUTE_ATTR_##F)
00652 #define AVAIL(F) (o->rt_mask & ROUTE_ATTR_##F)
00653 #define _O(F, EXPR) (REQ(F) && (!AVAIL(F) || (EXPR)))
00654 #define _C(F, N) (REQ(F) && (!AVAIL(F) || (o->N != f->N)))
00655         if (_C(FAMILY,    rt_family)                                    ||
00656             _C(DST_LEN,   rt_dst_len)                                   ||
00657             _C(SRC_LEN,   rt_src_len)                                   ||
00658             _C(TOS,       rt_tos)                                       ||
00659             _C(TABLE,     rt_table)                                     ||
00660             _C(PROTOCOL,  rt_protocol)                                  ||
00661             _C(SCOPE,     rt_scope)                                     ||
00662             _C(TYPE,      rt_type)                                      ||
00663             _C(OIF,       rt_oif)                                       ||
00664             _C(PRIO,      rt_prio)                                      ||
00665             _C(REALMS,    rt_realms)                                    ||
00666             _C(MP_ALGO,   rt_mp_algo)                                   ||
00667             _O(DST,       nl_addr_cmp(o->rt_dst, f->rt_dst))            ||
00668             _O(SRC,       nl_addr_cmp(o->rt_src, f->rt_src))            ||
00669             _O(IIF,       strcmp(o->rt_iif, f->rt_iif))                 ||
00670             _O(PREF_SRC,  nl_addr_cmp(o->rt_pref_src, f->rt_pref_src))  ||
00671             _O(GATEWAY,   nl_addr_cmp(o->rt_gateway, f->rt_gateway))    ||
00672             _O(FLAGS,     f->rt_flags ^ (o->rt_flags & f->rt_flag_mask)))
00673                 return 0;
00674 
00675         if (REQ(METRICS)) {
00676                 int i;
00677 
00678                 if (!AVAIL(METRICS))
00679                         return 0;
00680 
00681                 for (i = 0; i < RTAX_MAX; i++) {
00682                         if (f->rt_metrics_mask & (1 << i)) {
00683                                 if (!(o->rt_metrics_mask & (1 << i)) ||
00684                                     f->rt_metrics[i+1] != o->rt_metrics[i+1])
00685                                         return 0;
00686                         }
00687                 }
00688         }
00689 
00690         if (REQ(MULTIPATH)) {
00691                 /* FIXME */
00692         }
00693         
00694 #undef REQ
00695 #undef AVAIL
00696 #undef _O
00697 #undef _C
00698 
00699         return 1;
00700 
00701 }
00702 
00703 /**
00704  * @name Route Object Allocation/Freeage
00705  * @{
00706  */
00707 
00708 /**
00709  * Allocate a new route object
00710  * @return New route object
00711  */
00712 struct rtnl_route *rtnl_route_alloc(void)
00713 {
00714         return (struct rtnl_route *) nl_object_alloc_from_ops(&rtnl_route_ops);
00715 }
00716 
00717 /**
00718  * Free route object.
00719  * @arg route           Route object to be freed.
00720  *
00721  * @note Always use rtnl_route_put() unless you're absolutely sure
00722  *       that no other user may have a reference on this object.
00723  */
00724 void rtnl_route_free(struct rtnl_route *route)
00725 {
00726         nl_object_free((struct nl_object *) route);
00727 }
00728 
00729 /** @} */
00730 
00731 /**
00732  * @name Route Object Reference Counting
00733  * @{
00734  */
00735 
00736 void rtnl_route_get(struct rtnl_route *route)
00737 {
00738         nl_object_get((struct nl_object *) route);
00739 }
00740 
00741 void rtnl_route_put(struct rtnl_route *route)
00742 {
00743         nl_object_put((struct nl_object *) route);
00744 }
00745 
00746 /** @} */
00747 
00748 /**
00749  * @name Route Cache Management
00750  * @{
00751  */
00752 
00753 /**
00754  * Build a route cache holding all routes currently configured in the kernel
00755  * @arg handle          netlink handle
00756  *
00757  * Allocates a new cache, initializes it properly and updates it to
00758  * contain all routes currently configured in the kernel.
00759  *
00760  * @note The caller is responsible for destroying and freeing the
00761  *       cache after using it.
00762  * @return The cache or NULL if an error has occured.
00763  */
00764 struct nl_cache *rtnl_route_alloc_cache(struct nl_handle *handle)
00765 {
00766         struct nl_cache *cache = nl_cache_alloc_from_ops(&rtnl_route_ops);
00767 
00768         if (!cache)
00769                 return NULL;
00770 
00771         if (nl_cache_update(handle, cache) < 0) {
00772                 free(cache);
00773                 return NULL;
00774         }
00775 
00776         return cache;
00777 }
00778 
00779 /** @} */
00780 
00781 /**
00782  * @name Route Addition
00783  * @{
00784  */
00785 
00786 static struct nl_msg *build_route_msg(struct rtnl_route *tmpl, int cmd,
00787                                       int flags)
00788 {
00789 #if 0
00790         struct nl_msg *msg;
00791         struct rtmsg rtmsg = {
00792                 .rtm_family = tmpl->rt_family,
00793         };
00794         route->rt_dst_len       = rtmsg->rtm_dst_len;
00795         route->rt_src_len       = rtmsg->rtm_src_len;
00796         route->rt_tos           = rtmsg->rtm_tos;
00797         route->rt_table         = rtmsg->rtm_table;
00798         route->rt_type          = rtmsg->rtm_type;
00799         route->rt_scope         = rtmsg->rtm_scope;
00800         route->rt_protocol      = rtmsg->rtm_protocol;
00801         route->rt_flags         = rtmsg->rtm_flags;
00802 
00803         route->rt_mask = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_DST_LEN | 
00804                           ROUTE_ATTR_SRC_LEN | ROUTE_ATTR_TABLE |
00805                           ROUTE_ATTR_PROTOCOL| ROUTE_ATTR_SCOPE |
00806                           ROUTE_ATTR_TYPE | ROUTE_ATTR_FLAGS);
00807 
00808         msg = nlmsg_build_simple(cmd, flags);
00809         if (!msg)
00810                 return NULL;
00811 
00812         if (nlmsg_append(msg, &rtmsg, sizeof(rtmsg), 1) < 0)
00813                 goto nla_put_failure;
00814 
00815         NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst);
00816 
00817         if (tmpl->n_mask & NEIGH_ATTR_LLADDR)
00818                 NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr);
00819 
00820         return msg;
00821 
00822 nla_put_failure:
00823         nlmsg_free(msg);
00824         return NULL;
00825 #endif
00826 
00827         return NULL;
00828 }
00829 
00830 /**
00831  * Build netlink request message to add a new route
00832  * @arg tmpl            template with data of new route
00833  * @arg flags           additional netlink message flags
00834  *
00835  * Builds a new netlink message requesting a addition of a new route.
00836  * The netlink message header isn't fully equipped with all relevant
00837  * fields and must thus be sent out via nl_send_auto_complete() or
00838  * supplemented as needed. \a tmpl must contain the attributes of the
00839  * new route set via \c rtnl_route_set_* functions.
00840  * 
00841  * The following attributes must be set in the template:
00842  *  - Interface index (rtnl_neigh_set_ifindex())
00843  *  - State (rtnl_neigh_set_state())
00844  *  - Destination address (rtnl_neigh_set_dst())
00845  *  - Link layer address (rtnl_neigh_set_lladdr())
00846  *
00847  * @return The netlink message
00848  */
00849 struct nl_msg *rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags)
00850 {
00851         return build_route_msg(tmpl, RTM_NEWROUTE, NLM_F_CREATE | flags);
00852 }
00853 
00854 /** @} */
00855 /**
00856  * @name Attribute: Routing Table
00857  * @{
00858  */
00859 
00860 /**
00861  * Set the table of a route to the specified value
00862  * @arg route           route to be changed
00863  * @arg table           new table value
00864  */
00865 void rtnl_route_set_table(struct rtnl_route *route, int table)
00866 {
00867         route->rt_table = table;
00868         route->rt_mask |= ROUTE_ATTR_TABLE;
00869 }
00870 
00871 /**
00872  * Get the table of a route
00873  * @arg route           route handle
00874  * @return Table id or -1 if not set
00875  */
00876 int rtnl_route_get_table(struct rtnl_route *route)
00877 {
00878         if (route->rt_mask & ROUTE_ATTR_TABLE)
00879                 return route->rt_table;
00880         else
00881                 return -1;
00882 }
00883 
00884 /** @} */
00885 /**
00886  * @name Attribute: Scope
00887  * @{
00888  */
00889 
00890 /**
00891  * Set the scope of a route to the specified value
00892  * @arg route           route to be changed
00893  * @arg scope           new scope
00894  */
00895 void rtnl_route_set_scope(struct rtnl_route *route, int scope)
00896 {
00897         route->rt_scope = scope;
00898         route->rt_mask |= ROUTE_ATTR_SCOPE;
00899 }
00900 
00901 /**
00902  * Get the scope of a route
00903  * @arg route           route handle
00904  * @return Scope or -1 if not set
00905  */
00906 int rtnl_route_get_scope(struct rtnl_route *route)
00907 {
00908         if (route->rt_mask & ROUTE_ATTR_SCOPE)
00909                 return route->rt_scope;
00910         else
00911                 return -1;
00912 }
00913 
00914 /** @} */
00915 /**
00916  * @name Attribute: Type Of Service
00917  * @{
00918  */
00919 
00920 /**
00921  * Set the TOS of a route to the specified value
00922  * @arg route           route to be changed
00923  * @arg tos             new TOS value
00924  */
00925 void rtnl_route_set_tos(struct rtnl_route *route, int tos)
00926 {
00927         route->rt_tos = tos;
00928         route->rt_mask |= ROUTE_ATTR_TOS;
00929 }
00930 
00931 /**
00932  * Get the TOS of a route
00933  * @arg route           route handle
00934  * @return TOS value or -1 if not set
00935  */
00936 int rtnl_route_get_tos(struct rtnl_route *route)
00937 {
00938         if (route->rt_mask & ROUTE_ATTR_TOS)
00939                 return route->rt_tos;
00940         else
00941                 return -1;
00942 }
00943 
00944 /** @} */
00945 /**
00946  * @name Attribute: Realm
00947  * @{
00948  */
00949 
00950 /**
00951  * Set the realms of a route to the specified value
00952  * @arg route           route to be changed
00953  * @arg realms          New realms value.
00954  */
00955 void rtnl_route_set_realms(struct rtnl_route *route, realm_t realms)
00956 {
00957         route->rt_realms = realms;
00958         route->rt_mask |= ROUTE_ATTR_REALMS;
00959 }
00960 
00961 /**
00962  * Get realms of route object.
00963  * @arg route           Route object.
00964  * @return Realms value or 0 if not set.
00965  */
00966 realm_t rtnl_route_get_realms(struct rtnl_route *route)
00967 {
00968         if (route->rt_mask & ROUTE_ATTR_REALMS)
00969                 return route->rt_realms;
00970         else
00971                 return 0;
00972 }
00973 
00974 /** @} */
00975 /**
00976  * @name Attribute: Routing Protocol
00977  * @{
00978  */
00979 
00980 /**
00981  * Set the protocol of a route to the specified value
00982  * @arg route           route to be changed
00983  * @arg proto           new protocol
00984  */
00985 void rtnl_route_set_protocol(struct rtnl_route *route, int proto)
00986 {
00987         route->rt_protocol = proto;
00988         route->rt_mask |= ROUTE_ATTR_PROTOCOL;
00989 }
00990 
00991 /**
00992  * Get the protocol of a route
00993  * @arg route           route handle
00994  * @return Protocol number or -1 if not set
00995  */
00996 int rtnl_route_get_protocol(struct rtnl_route *route)
00997 {
00998         if (route->rt_mask & ROUTE_ATTR_PROTOCOL)
00999                 return route->rt_protocol;
01000         else
01001                 return -1;
01002 }
01003 
01004 /** @} */
01005 /**
01006  * @name Attribute: Priority/Metric
01007  * @{
01008  */
01009 
01010 /**
01011  * Set the priority of a route to the specified value
01012  * @arg route           route to be changed
01013  * @arg prio            new priority
01014  */
01015 void rtnl_route_set_prio(struct rtnl_route *route, int prio)
01016 {
01017         route->rt_prio = prio;
01018         route->rt_mask |= ROUTE_ATTR_PRIO;
01019 }
01020 
01021 /**
01022  * Get the priority of a route
01023  * @arg route           route handle
01024  * @return Priority or -1 if not set
01025  */
01026 int rtnl_route_get_prio(struct rtnl_route *route)
01027 {
01028         if (route->rt_mask & ROUTE_ATTR_PRIO)
01029                 return route->rt_prio;
01030         else
01031                 return -1;
01032 }
01033 
01034 /** @} */
01035 /**
01036  * @name Attribute: Address Family
01037  * @{
01038  */
01039 
01040 /**
01041  * Set the address family of a route to the specified value
01042  * @arg route           route to be changed
01043  * @arg family          new address family
01044  */
01045 void rtnl_route_set_family(struct rtnl_route *route, int family)
01046 {
01047         route->rt_family = family;
01048         route->rt_mask |= ROUTE_ATTR_FAMILY;
01049 }
01050 
01051 /**
01052  * Get the address family of a route
01053  * @arg route           route handle
01054  * @return Address family or AF_UNSPEC if not set
01055  */
01056 int rtnl_route_get_family(struct rtnl_route *route)
01057 {
01058         if (route->rt_mask & ROUTE_ATTR_FAMILY)
01059                 return route->rt_family;
01060         else
01061                 return AF_UNSPEC;
01062 }
01063 
01064 /** @} */
01065 /**
01066  * @name Attribute: Destination Address
01067  * @{
01068  */
01069 
01070 /**
01071  * Set the destination address of a route to the specified address
01072  * @arg route           route to be changed
01073  * @arg addr            new destination address
01074  *
01075  * Assigns the new destination address to the specified \a route,
01076  * overwrites the destination address length (rtnl_route::rt_dst_len),
01077  * and sets the route's address family to the new address's family if
01078  * it is not set already.
01079  *
01080  * If a address family has been specified already via either calling
01081  * rtnl_route_set_family() or by setting one of the other addresses,
01082  * the specified \a addr is automatically validated against this family
01083  * and the assignment fails in case of a mismatch.
01084  * 
01085  * @return 0 on success or a negative error code.
01086  */
01087 int rtnl_route_set_dst(struct rtnl_route *route, struct nl_addr *addr)
01088 {
01089         if (route->rt_mask & ROUTE_ATTR_FAMILY) {
01090                 if (addr->a_family != route->rt_family)
01091                         return nl_error(EINVAL, "Address family mismatch");
01092         } else
01093                 route->rt_family = addr->a_family;
01094 
01095         if (route->rt_dst)
01096                 nl_addr_put(route->rt_dst);
01097 
01098         nl_addr_get(addr);
01099         route->rt_dst = addr;
01100         
01101         route->rt_mask |= (ROUTE_ATTR_DST|ROUTE_ATTR_FAMILY|ROUTE_ATTR_DST_LEN);
01102 
01103         return 0;
01104 }
01105 
01106 /**
01107  * Get the destination address of a route
01108  * @arg route           route handle
01109  * @return Destination address or NULL if not set
01110  */
01111 struct nl_addr *rtnl_route_get_dst(struct rtnl_route *route)
01112 {
01113         if (route->rt_mask & ROUTE_ATTR_DST)
01114                 return route->rt_dst;
01115         else
01116                 return NULL;
01117 }
01118 
01119 /**
01120  * Set the destination address prefix length of a route to the specified value
01121  * @arg route           route to be changed
01122  * @arg prefix          new destination address prefix
01123  * @attention The destination address prefix gets overwritten by calls
01124  *            to rtnl_route_set_dst() rtnl_route_set_dst_str().
01125  */
01126 void rtnl_route_set_dst_len(struct rtnl_route *route, int prefix)
01127 {
01128         route->rt_dst_len = prefix;
01129         route->rt_mask |= ROUTE_ATTR_DST_LEN;
01130 }
01131 
01132 /**
01133  * Get the destination address prefix length of a route
01134  * @arg route           route handle
01135  * @return Prefix length or -1 if not set
01136  */
01137 int rtnl_route_get_dst_len(struct rtnl_route *route)
01138 {
01139         if (route->rt_mask & ROUTE_ATTR_DST_LEN)
01140                 return route->rt_dst_len;
01141         else
01142                 return -1;
01143 }
01144 
01145 /** @} */
01146 /**
01147  * @name Attribute: Source Address
01148  * @{
01149  */
01150 
01151 /**
01152  * Set the source address of a route to the specified address
01153  * @arg route           route to be changed
01154  * @arg addr            new source address
01155  *
01156  * Assigns the new source address to the specified \a route,
01157  * overwrites the source address length (rtnl_route::rt_src_len),
01158  * and sets the route's address family to the new address's family if
01159  * it is not set already.
01160  *
01161  * If a address family has been specified already via either calling
01162  * rtnl_route_set_family() or by setting one of the other addresses,
01163  * the specified \a addr is automatically validated against this family
01164  * and the assignment fails in case of a mismatch.
01165  * 
01166  * @return 0 on success or a negative error code.
01167  */
01168 int rtnl_route_set_src(struct rtnl_route *route, struct nl_addr *addr)
01169 {
01170         if (route->rt_mask & ROUTE_ATTR_FAMILY) {
01171                 if (addr->a_family != route->rt_family)
01172                         return nl_error(EINVAL, "Address family mismatch");
01173         } else
01174                 route->rt_family = addr->a_family;
01175 
01176         if (route->rt_src)
01177                 nl_addr_put(route->rt_src);
01178 
01179         nl_addr_get(addr);
01180         route->rt_src = addr;
01181         route->rt_mask |= (ROUTE_ATTR_SRC|ROUTE_ATTR_FAMILY|ROUTE_ATTR_SRC_LEN);
01182 
01183         return 0;
01184 }
01185 
01186 /**
01187  * Get the source address of a route
01188  * @arg route           route handle
01189  * @return Source address or NULL if not set
01190  */
01191 struct nl_addr *rtnl_route_get_src(struct rtnl_route *route)
01192 {
01193         if (route->rt_mask & ROUTE_ATTR_SRC)
01194                 return route->rt_src;
01195         else
01196                 return NULL;
01197 }
01198 
01199 /**
01200  * Set the source address prefix length of a route to the specified value
01201  * @arg route           route to be changed
01202  * @arg prefix          new source address prefix
01203  * @attention The source address prefix gets overwritten by calls
01204  *            to rtnl_route_src_dst() rtnl_route_set_src_str().
01205  */
01206 void rtnl_route_set_src_len(struct rtnl_route *route, int prefix)
01207 {
01208         route->rt_dst_len = prefix;
01209         route->rt_mask |= ROUTE_ATTR_SRC_LEN;
01210 }
01211 
01212 /**
01213  * Get the source address prefix length of a route
01214  * @arg route           route handle
01215  * @return Prefix length or -1 if not set
01216  */
01217 int rtnl_route_get_src_len(struct rtnl_route *route)
01218 {
01219         if (route->rt_mask & ROUTE_ATTR_SRC_LEN)
01220                 return route->rt_src_len;
01221         else
01222                 return -1;
01223 }
01224 
01225 /** @} */
01226 /**
01227  * @name Attribute: Gateway Address
01228  * @{
01229  */
01230 
01231 /**
01232  * Set the gateway address of a route to the specified address
01233  * @arg route           route to be changed
01234  * @arg addr            new gateway address
01235  *
01236  * Assigns the new gateway address to the specified \a route,
01237  * and sets the route's address family to the new address's family if
01238  * it is not set already.
01239  *
01240  * If a address family has been specified already via either calling
01241  * rtnl_route_set_family() or by setting one of the other addresses,
01242  * the specified \a addr is automatically validated against this family
01243  * and the assignment fails in case of a mismatch.
01244  * 
01245  * @return 0 on success or a negative error code.
01246  */
01247 int rtnl_route_set_gateway(struct rtnl_route *route, struct nl_addr *addr)
01248 {
01249         if (route->rt_mask & ROUTE_ATTR_FAMILY) {
01250                 if (addr->a_family != route->rt_family)
01251                         return nl_error(EINVAL, "Address family mismatch");
01252         } else
01253                 route->rt_family = addr->a_family;
01254 
01255         if (route->rt_gateway)
01256                 nl_addr_put(route->rt_gateway);
01257 
01258         nl_addr_get(addr);
01259         route->rt_gateway = addr;
01260         route->rt_mask |= (ROUTE_ATTR_GATEWAY | ROUTE_ATTR_FAMILY);
01261 
01262         return 0;
01263 }
01264 
01265 /**
01266  * Get the gateway address of a route
01267  * @arg route           route handle
01268  * @return Gateway address or NULL if not set
01269  */
01270 struct nl_addr *rtnl_route_get_gateway(struct rtnl_route *route)
01271 {
01272         if (route->rt_mask & ROUTE_ATTR_GATEWAY)
01273                 return route->rt_gateway;
01274         else
01275                 return NULL;
01276 }
01277 
01278 /** @} */
01279 /**
01280  * @name Attribute: Type
01281  * @{
01282  */
01283 
01284 /**
01285  * Set the type of a route to the specified value
01286  * @arg route           route to be changed
01287  * @arg type            new route type
01288  */
01289 void rtnl_route_set_type(struct rtnl_route *route, int type)
01290 {
01291         route->rt_type = type;
01292         route->rt_mask |= ROUTE_ATTR_TYPE;
01293 }
01294 
01295 /**
01296  * Get the type of a route
01297  * @arg route           route handle
01298  * @return Type of route or -1 if not set
01299  */
01300 int rtnl_route_get_type(struct rtnl_route *route)
01301 {
01302         if (route->rt_mask & ROUTE_ATTR_TYPE)
01303                 return route->rt_type;
01304         else
01305                 return -1;
01306 }
01307 
01308 /** @} */
01309 /**
01310  * @name Attribute: Flags
01311  * @{
01312  */
01313 
01314 /**
01315  * Add flags to a route 
01316  * @arg route           route to be changed
01317  * @arg flags           flags to set
01318  */
01319 void rtnl_route_set_flags(struct rtnl_route *route, unsigned int flags)
01320 {
01321         route->rt_flag_mask |= flags;
01322         route->rt_flags |= flags;
01323         route->rt_mask |= ROUTE_ATTR_FLAGS;
01324 }
01325 
01326 /**
01327  * Remove flags from a route 
01328  * @arg route           route to be changed
01329  * @arg flags           flags to unset
01330  */
01331 void rtnl_route_unset_flags(struct rtnl_route *route, unsigned int flags)
01332 {
01333         route->rt_flag_mask |= flags;
01334         route->rt_flags &= ~flags;
01335         route->rt_mask |= ROUTE_ATTR_FLAGS;
01336 }
01337 
01338 /**
01339  * Get flags of a route
01340  * @arg route           route handle
01341  */
01342 unsigned int rtnl_route_get_flags(struct rtnl_route *route)
01343 {
01344         return route->rt_flags;
01345 }
01346 
01347 /** @} */
01348 /**
01349  * @name Attribute: Routing Metrics
01350  * @{
01351  */
01352 
01353 /**
01354  * Set a metric of a route to the specified value
01355  * @arg route           route to be changed
01356  * @arg metric          metric to be changed (see XXX)
01357  * @arg value           new metric value
01358  * @return 0 on sucess or a negative error code
01359  */
01360 int rtnl_route_set_metric(struct rtnl_route *route, int metric, uint32_t value)
01361 {
01362         if (metric <= RTAX_MAX || metric < 1)
01363                 return nl_error(EINVAL, "Metric out of range (1..%d)",
01364                     RTAX_MAX);
01365 
01366         route->rt_metrics[metric - 1] = value;
01367         route->rt_metrics_mask |= (1 << (metric - 1));
01368 
01369         return 0;
01370 }
01371 
01372 /**
01373  * Unset a metric of a route
01374  * @arg route           route to be changed
01375  * @arg metric          metric to be unset (see XXX)
01376  * @return 0 on sucess or a negative error code
01377  */
01378 int rtnl_route_unset_metric(struct rtnl_route *route, int metric)
01379 {
01380         if (metric <= RTAX_MAX || metric < 1)
01381                 return nl_error(EINVAL, "Metric out of range (1..%d)",
01382                     RTAX_MAX);
01383 
01384         route->rt_metrics_mask &= ~(1 << (metric - 1));
01385 
01386         return 0;
01387 }
01388 
01389 /**
01390  * Get a metric for a route
01391  * @arg route           route handle
01392  * @arg metric          metric to get
01393  * @return The value for the specified metric or UINT_MAX if not set
01394  */
01395 unsigned int rtnl_route_get_metric(struct rtnl_route *route, int metric)
01396 {
01397         if (metric <= RTAX_MAX || metric < 1)
01398                 return UINT_MAX;
01399 
01400         if (!(route->rt_metrics_mask & (1 << (metric - 1))))
01401                 return UINT_MAX;
01402 
01403         return route->rt_metrics[metric - 1];
01404 }
01405 
01406 /** @} */
01407 /**
01408  * @name Attribute: Preferred Source Address
01409  * @{
01410  */
01411 
01412 /**
01413  * Set the preferred source address of a route to the specified address
01414  * @arg route           route to be changed
01415  * @arg addr            new preferred source address
01416  *
01417  * Assigns the new preferred source address to the specified \a route,
01418  * and sets the route's address family to the new address's family if
01419  * it is not set already.
01420  *
01421  * If a address family has been specified already via either calling
01422  * rtnl_route_set_family() or by setting one of the other addresses,
01423  * the specified \a addr is automatically validated against this family
01424  * and the assignment fails in case of a mismatch.
01425  * 
01426  * @return 0 on success or a negative error code.
01427  */
01428 int rtnl_route_set_pref_src(struct rtnl_route *route, struct nl_addr *addr)
01429 {
01430         if (route->rt_mask & ROUTE_ATTR_FAMILY) {
01431                 if (addr->a_family != route->rt_family)
01432                         return nl_error(EINVAL, "Address family mismatch");
01433         } else
01434                 route->rt_family = addr->a_family;
01435 
01436         if (route->rt_pref_src)
01437                 nl_addr_put(route->rt_pref_src);
01438 
01439         nl_addr_get(addr);
01440         route->rt_pref_src = addr;
01441         route->rt_mask |= (ROUTE_ATTR_PREF_SRC | ROUTE_ATTR_FAMILY);
01442 
01443         return 0;
01444 }
01445 
01446 /**
01447  * Get the preferred source address of a route
01448  * @arg route           route handle
01449  * @return Preferred source address or NULL if not set
01450  */
01451 struct nl_addr *rtnl_route_get_pref_src(struct rtnl_route *route)
01452 {
01453         if (route->rt_mask & ROUTE_ATTR_PREF_SRC)
01454                 return route->rt_pref_src;
01455         else
01456                 return NULL;
01457 }
01458 
01459 /** @} */
01460 /**
01461  * @name Attribute: Outgoing Interface Index
01462  * @{
01463  */
01464 
01465 /**
01466  * Set the outgoing interface of a route to the specified value
01467  * @arg route           route to be changed
01468  * @arg ifindex         interface index of new outoing interface
01469  */
01470 void rtnl_route_set_oif(struct rtnl_route *route, int ifindex)
01471 {
01472         route->rt_oif = ifindex;
01473         route->rt_mask |= ROUTE_ATTR_OIF;
01474 }
01475 
01476 /**
01477  * Get the outgoing interface index of a route
01478  * @arg route           route handle
01479  * @return interface index or RTNL_LINK_NOT_FOUND if not set
01480  */
01481 int rtnl_route_get_oif(struct rtnl_route *route)
01482 {
01483         if (route->rt_mask & ROUTE_ATTR_OIF)
01484                 return route->rt_oif;
01485         else
01486                 return RTNL_LINK_NOT_FOUND;
01487 }
01488 
01489 /** @} */
01490 /**
01491  * @name Attribute: Incoming Interface
01492  * @{
01493  */
01494 
01495 /**
01496  * Set the incoming interface of a route to the specified value
01497  * @arg route           route to be changed
01498  * @arg name            interface name of the new incoming interface
01499  */
01500 void rtnl_route_set_iif(struct rtnl_route *route, const char *name)
01501 {
01502         strncpy(route->rt_iif, name, sizeof(route->rt_iif) - 1);
01503         route->rt_mask |= ROUTE_ATTR_IIF;
01504 }
01505 
01506 /**
01507  * Get the incomming interface name of a route
01508  * @arg route           route handle
01509  * @return interface name or NULL if not set
01510  */
01511 char *rtnl_route_get_iif(struct rtnl_route *route)
01512 {
01513         if (route->rt_mask & ROUTE_ATTR_IIF)
01514                 return route->rt_iif;
01515         else
01516                 return NULL;
01517 }
01518 
01519 #if 0
01520         struct rtnl_rtcacheinfo rt_cacheinfo;
01521 #endif
01522 
01523 /** @} */
01524 /**
01525  * @name Attribute: Nexthop
01526  * @{
01527  */
01528 
01529 void rtnl_route_add_nexthop(struct rtnl_route *route, struct rtnl_nexthop *nh)
01530 {
01531         nl_list_add_tail(&nh->rtnh_list, &route->rt_nexthops);
01532         route->rt_mask |= ROUTE_ATTR_MULTIPATH;
01533 }
01534 
01535 void rtnl_route_remove_nexthop(struct rtnl_nexthop *nh)
01536 {
01537         nl_list_del(&nh->rtnh_list);
01538 }
01539 
01540 struct nl_list_head *rtnl_route_get_nexthops(struct rtnl_route *route)
01541 {
01542         return &route->rt_nexthops;
01543 }
01544 
01545 /** @} */
01546         
01547 /**
01548  * @name Routing Table Identifier Translations
01549  * @{
01550  */
01551 
01552 static struct trans_tbl route_tables[] = {
01553         __ADD(RT_TABLE_UNSPEC, unspec)
01554         __ADD(RT_TABLE_DEFAULT, default)
01555         __ADD(RT_TABLE_MAIN, main)
01556         __ADD(RT_TABLE_LOCAL, local)
01557 };
01558 
01559 /**
01560  * Convert routing table identifier to character string.
01561  * @arg table           Routing table identifier.
01562  * @arg buf             Destination buffer
01563  * @arg size            Size of destination buffer.
01564  *
01565  * Converts a routing table identifier to a character string and stores
01566  * it in the specified destination buffer.
01567  *
01568  * @return The destination buffer or the type encoded in hexidecimal
01569  *         form if the routing table identifier is unknown.
01570  */
01571 char *rtnl_route_table2str(int table, char *buf, size_t size)
01572 {
01573         return __type2str(table, buf, size, route_tables,
01574                           ARRAY_SIZE(route_tables));
01575 }
01576 
01577 /**
01578  * Convert character string to routing table identifier.
01579  * @arg name            Name of routing table.
01580  *
01581  * Converts the provided character string specifying a routing table
01582  * identifier to the corresponding numeric value.
01583  *
01584  * @return Routing table identifier or a negative value if no match was found.
01585  */
01586 int rtnl_route_str2table(const char *name)
01587 {
01588         return __str2type(name, route_tables, ARRAY_SIZE(route_tables));
01589 }
01590 
01591 
01592 /** @} */
01593 
01594 /**
01595  * @name Routing Protocol Translations
01596  * @{
01597  */
01598 
01599 static struct trans_tbl route_protos[] = {
01600         __ADD(RTPROT_UNSPEC, unspec)
01601         __ADD(RTPROT_REDIRECT, redirect)
01602         __ADD(RTPROT_KERNEL, kernel)
01603         __ADD(RTPROT_BOOT, boot)
01604         __ADD(RTPROT_STATIC, static)
01605 };
01606 
01607 /**
01608  * Convert routing protocol identifier to character string.
01609  * @arg proto           Routing protocol identifier.
01610  * @arg buf             Destination buffer
01611  * @arg size            Size of destination buffer.
01612  *
01613  * Converts a routing protocol identifier to a character string and stores
01614  * it in the specified destination buffer.
01615  *
01616  * @return The destination buffer or the protocol encoded in hexidecimal
01617  *         form if the routing protocol is unknown.
01618  */
01619 char *rtnl_route_proto2str(int proto, char *buf, size_t size)
01620 {
01621         return __type2str(proto, buf, size, route_protos,
01622                           ARRAY_SIZE(route_protos));
01623 }
01624 
01625 /**
01626  * Convert character string to routing protocol identifier.
01627  * @arg name            Name of routing protocol.
01628  *
01629  * Converts the provided character string specifying a routing protocl
01630  * identifier to the corresponding numeric value.
01631  *
01632  * @return Routing protocol dentifier or a negative value if no match was found.
01633  */
01634 int rtnl_route_str2proto(const char *name)
01635 {
01636         return __str2type(name, route_protos, ARRAY_SIZE(route_protos));
01637 }
01638 
01639 /** @} */
01640 
01641 /**
01642  * @name Routing Metrices Translations
01643  * @{
01644  */
01645 
01646 static struct trans_tbl route_metrices[] = {
01647         __ADD(RTAX_UNSPEC, unspec)
01648         __ADD(RTAX_LOCK, lock)
01649         __ADD(RTAX_MTU, mtu)
01650         __ADD(RTAX_WINDOW, window)
01651         __ADD(RTAX_RTT, rtt)
01652         __ADD(RTAX_RTTVAR, rttvar)
01653         __ADD(RTAX_SSTHRESH, ssthresh)
01654         __ADD(RTAX_CWND, cwnd)
01655         __ADD(RTAX_ADVMSS, advmss)
01656         __ADD(RTAX_REORDERING, reordering)
01657         __ADD(RTAX_HOPLIMIT, hoplimit)
01658         __ADD(RTAX_INITCWND, initcwnd)
01659         __ADD(RTAX_FEATURES, features)
01660 };
01661 
01662 /**
01663  * Convert routing metric identifier to character string.
01664  * @arg metric          Routing metric identifier.
01665  * @arg buf             Destination buffer
01666  * @arg size            Size of destination buffer.
01667  *
01668  * Converts a routing metric identifier to a character string and stores
01669  * it in the specified destination buffer.
01670  *
01671  * @return The destination buffer or the metric encoded in hexidecimal
01672  *         form if the routing metric identifier is unknown.
01673  */
01674 char *rtnl_route_metric2str(int metric, char *buf, size_t size)
01675 {
01676         return __type2str(metric, buf, size, route_metrices,
01677                           ARRAY_SIZE(route_metrices));
01678 }
01679 
01680 /**
01681  * Convert character string to routing metric identifier.
01682  * @arg name            Name of routing metric.
01683  *
01684  * Converts the provided character string specifying a routing metric
01685  * identifier to the corresponding numeric value.
01686  *
01687  * @return Routing metric dentifier or a negative value if no match was found.
01688  */
01689 int rtnl_route_str2metric(const char *name)
01690 {
01691         return __str2type(name, route_metrices, ARRAY_SIZE(route_metrices));
01692 }
01693 
01694 /** @} */
01695 
01696 /**
01697  * @name Nexthop Flags Translations
01698  * @{
01699  */
01700 
01701 static struct trans_tbl nh_flags[] = {
01702         __ADD(RTNH_F_DEAD, dead)
01703         __ADD(RTNH_F_PERVASIVE, pervasive)
01704         __ADD(RTNH_F_ONLINK, onlink)
01705 };
01706 
01707 /**
01708  * Convert nexthop flags to a character string.
01709  * @arg flags           Nexthop flags.
01710  * @arg buf             Destination buffer.
01711  * @arg len             Length of destination buffer.
01712  *
01713  * Converts nexthop flags to a character string separated by
01714  * commas and stores it in the specified destination buffer.
01715  *
01716  * \return The destination buffer
01717  */
01718 char * rtnl_route_nh_flags2str(int flags, char *buf, size_t len)
01719 {
01720         return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags));
01721 }
01722 
01723 /**
01724  * Convert a character string to a nexthop flag
01725  * @arg name            Name of nexthop flag.
01726  *
01727  * Converts the provided character string specifying a nexthop
01728  * flag to the corresponding numeric value.
01729  *
01730  * \return Nexthop flag or a negative value if none was found.
01731  */
01732 int rtnl_route_nh_str2flags(const char *name)
01733 {
01734         return __str2flags(name, nh_flags, ARRAY_SIZE(nh_flags));
01735 }
01736 
01737 /** @} */
01738 
01739 static struct nl_cache_ops rtnl_route_ops = {
01740         .co_name                = "route/route",
01741         .co_size                = sizeof(struct rtnl_route),
01742         .co_hdrsize             = sizeof(struct rtmsg),
01743         .co_msgtypes            = {
01744                                         { RTM_NEWROUTE, "new" },
01745                                         { RTM_DELROUTE, "delete" },
01746                                         { RTM_GETROUTE, "get" },
01747                                         { -1, NULL },
01748                                   },
01749         .co_protocol            = NETLINK_ROUTE,
01750         .co_request_update      = route_request_update,
01751         .co_msg_parser          = route_msg_parser,
01752         .co_constructor         = route_constructor,
01753         .co_free_data           = route_free_data,
01754         .co_dump[NL_DUMP_BRIEF] = route_dump_brief,
01755         .co_dump[NL_DUMP_FULL]  = route_dump_full,
01756         .co_dump[NL_DUMP_STATS] = route_dump_stats,
01757         .co_dump[NL_DUMP_XML]   = route_dump_xml,
01758         .co_dump[NL_DUMP_ENV]   = route_dump_env,
01759         .co_filter              = route_filter,
01760 };
01761 
01762 static void __init route_init(void)
01763 {
01764         nl_cache_mngt_register(&rtnl_route_ops);
01765 }
01766 
01767 static void __exit route_exit(void)
01768 {
01769         nl_cache_mngt_unregister(&rtnl_route_ops);
01770 }
01771 
01772 /** @} */

Generated on Fri Apr 27 14:14:07 2007 for libnl by  doxygen 1.5.1