00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
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
00692 }
00693
00694 #undef REQ
00695 #undef AVAIL
00696 #undef _O
00697 #undef _C
00698
00699 return 1;
00700
00701 }
00702
00703
00704
00705
00706
00707
00708
00709
00710
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
00719
00720
00721
00722
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
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
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
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
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
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
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
00857
00858
00859
00860
00861
00862
00863
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
00873
00874
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
00887
00888
00889
00890
00891
00892
00893
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
00903
00904
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
00917
00918
00919
00920
00921
00922
00923
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
00933
00934
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
00947
00948
00949
00950
00951
00952
00953
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
00963
00964
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
00977
00978
00979
00980
00981
00982
00983
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
00993
00994
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
01007
01008
01009
01010
01011
01012
01013
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
01023
01024
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
01037
01038
01039
01040
01041
01042
01043
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
01053
01054
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
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
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
01108
01109
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
01121
01122
01123
01124
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
01134
01135
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
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
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
01188
01189
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
01201
01202
01203
01204
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
01214
01215
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
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
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
01267
01268
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
01281
01282
01283
01284
01285
01286
01287
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
01297
01298
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
01311
01312
01313
01314
01315
01316
01317
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
01328
01329
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
01340
01341
01342 unsigned int rtnl_route_get_flags(struct rtnl_route *route)
01343 {
01344 return route->rt_flags;
01345 }
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
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
01374
01375
01376
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
01391
01392
01393
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
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
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
01448
01449
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
01462
01463
01464
01465
01466
01467
01468
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
01478
01479
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
01492
01493
01494
01495
01496
01497
01498
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
01508
01509
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
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
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
01561
01562
01563
01564
01565
01566
01567
01568
01569
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
01579
01580
01581
01582
01583
01584
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
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
01609
01610
01611
01612
01613
01614
01615
01616
01617
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
01627
01628
01629
01630
01631
01632
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
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
01664
01665
01666
01667
01668
01669
01670
01671
01672
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
01682
01683
01684
01685
01686
01687
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
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
01709
01710
01711
01712
01713
01714
01715
01716
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
01725
01726
01727
01728
01729
01730
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