00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <netlink-local.h>
00037 #include <netlink/netlink.h>
00038 #include <netlink/cache.h>
00039 #include <netlink/utils.h>
00040 #include <netlink/data.h>
00041 #include <netlink/route/rtnl.h>
00042 #include <netlink/route/route.h>
00043 #include <netlink/route/link.h>
00044
00045
00046 #define ROUTE_ATTR_FAMILY 0x000001
00047 #define ROUTE_ATTR_TOS 0x000002
00048 #define ROUTE_ATTR_TABLE 0x000004
00049 #define ROUTE_ATTR_PROTOCOL 0x000008
00050 #define ROUTE_ATTR_SCOPE 0x000010
00051 #define ROUTE_ATTR_TYPE 0x000020
00052 #define ROUTE_ATTR_FLAGS 0x000040
00053 #define ROUTE_ATTR_DST 0x000080
00054 #define ROUTE_ATTR_SRC 0x000100
00055 #define ROUTE_ATTR_IIF 0x000200
00056 #define ROUTE_ATTR_OIF 0x000400
00057 #define ROUTE_ATTR_GATEWAY 0x000800
00058 #define ROUTE_ATTR_PRIO 0x001000
00059 #define ROUTE_ATTR_PREF_SRC 0x002000
00060 #define ROUTE_ATTR_METRICS 0x004000
00061 #define ROUTE_ATTR_MULTIPATH 0x008000
00062 #define ROUTE_ATTR_REALMS 0x010000
00063 #define ROUTE_ATTR_CACHEINFO 0x020000
00064 #define ROUTE_ATTR_MP_ALGO 0x040000
00065
00066
00067 static int route_dump_brief(struct nl_object *a, struct nl_dump_params *p);
00068
00069 static void route_constructor(struct nl_object *c)
00070 {
00071 struct rtnl_route *r = (struct rtnl_route *) c;
00072
00073 nl_init_list_head(&r->rt_nexthops);
00074 }
00075
00076 static void route_free_data(struct nl_object *c)
00077 {
00078 struct rtnl_route *r = (struct rtnl_route *) c;
00079 struct rtnl_nexthop *nh, *tmp;
00080
00081 if (r == NULL)
00082 return;
00083
00084 nl_addr_put(r->rt_dst);
00085 nl_addr_put(r->rt_src);
00086 nl_addr_put(r->rt_gateway);
00087 nl_addr_put(r->rt_pref_src);
00088
00089 nl_list_for_each_entry_safe(nh, tmp, &r->rt_nexthops, rtnh_list) {
00090 rtnl_route_remove_nexthop(nh);
00091 rtnl_route_nh_free(nh);
00092 }
00093 }
00094
00095 static int route_clone(struct nl_object *_dst, struct nl_object *_src)
00096 {
00097 struct rtnl_route *dst = (struct rtnl_route *) _dst;
00098 struct rtnl_route *src = (struct rtnl_route *) _src;
00099 struct rtnl_nexthop *nh, *new;
00100
00101 if (src->rt_dst)
00102 if (!(dst->rt_dst = nl_addr_clone(src->rt_dst)))
00103 goto errout;
00104
00105 if (src->rt_src)
00106 if (!(dst->rt_src = nl_addr_clone(src->rt_src)))
00107 goto errout;
00108
00109 if (src->rt_gateway)
00110 if (!(dst->rt_gateway = nl_addr_clone(src->rt_gateway)))
00111 goto errout;
00112
00113 if (src->rt_pref_src)
00114 if (!(dst->rt_pref_src = nl_addr_clone(src->rt_pref_src)))
00115 goto errout;
00116
00117 nl_init_list_head(&dst->rt_nexthops);
00118 nl_list_for_each_entry(nh, &src->rt_nexthops, rtnh_list) {
00119 new = rtnl_route_nh_clone(nh);
00120 if (!new)
00121 goto errout;
00122
00123 rtnl_route_add_nexthop(dst, new);
00124 }
00125
00126 return 0;
00127 errout:
00128 return nl_get_errno();
00129 }
00130
00131 static int route_dump_brief(struct nl_object *a, struct nl_dump_params *p)
00132 {
00133 struct rtnl_route *r = (struct rtnl_route *) a;
00134 struct nl_cache *link_cache;
00135 char buf[64];
00136
00137 link_cache = nl_cache_mngt_require("route/link");
00138
00139 if (!(r->ce_mask & ROUTE_ATTR_DST) ||
00140 nl_addr_get_len(r->rt_dst) == 0)
00141 dp_dump(p, "default ");
00142 else
00143 dp_dump(p, "%s ", nl_addr2str(r->rt_dst, buf, sizeof(buf)));
00144
00145 if (r->ce_mask & ROUTE_ATTR_OIF) {
00146 if (link_cache)
00147 dp_dump(p, "dev %s ",
00148 rtnl_link_i2name(link_cache, r->rt_oif,
00149 buf, sizeof(buf)));
00150 else
00151 dp_dump(p, "dev %d ", r->rt_oif);
00152 }
00153
00154 if (r->ce_mask & ROUTE_ATTR_GATEWAY)
00155 dp_dump(p, "via %s ", nl_addr2str(r->rt_gateway, buf,
00156 sizeof(buf)));
00157 else if (r->ce_mask & ROUTE_ATTR_MULTIPATH)
00158 dp_dump(p, "via nexthops ");
00159
00160 if (r->ce_mask & ROUTE_ATTR_SCOPE)
00161 dp_dump(p, "scope %s ",
00162 rtnl_scope2str(r->rt_scope, buf, sizeof(buf)));
00163
00164 if (r->ce_mask & ROUTE_ATTR_FLAGS && r->rt_flags) {
00165 int flags = r->rt_flags;
00166
00167 dp_dump(p, "<");
00168
00169 #define PRINT_FLAG(f) if (flags & RTNH_F_##f) { \
00170 flags &= ~RTNH_F_##f; dp_dump(p, #f "%s", flags ? "," : ""); }
00171 PRINT_FLAG(DEAD);
00172 PRINT_FLAG(ONLINK);
00173 PRINT_FLAG(PERVASIVE);
00174 #undef PRINT_FLAG
00175
00176 #define PRINT_FLAG(f) if (flags & RTM_F_##f) { \
00177 flags &= ~RTM_F_##f; dp_dump(p, #f "%s", flags ? "," : ""); }
00178 PRINT_FLAG(NOTIFY);
00179 PRINT_FLAG(CLONED);
00180 PRINT_FLAG(EQUALIZE);
00181 PRINT_FLAG(PREFIX);
00182 #undef PRINT_FLAG
00183
00184 dp_dump(p, ">");
00185 }
00186
00187 dp_dump(p, "\n");
00188
00189 return 1;
00190 }
00191
00192 static int route_dump_full(struct nl_object *a, struct nl_dump_params *p)
00193 {
00194 struct rtnl_route *r = (struct rtnl_route *) a;
00195 struct nl_cache *link_cache;
00196 char buf[128];
00197 int i, line;
00198
00199 link_cache = nl_cache_mngt_require("route/link");
00200 line = route_dump_brief(a, p);
00201
00202 if (r->ce_mask & ROUTE_ATTR_MULTIPATH) {
00203 struct rtnl_nexthop *nh;
00204
00205 nl_list_for_each_entry(nh, &r->rt_nexthops, rtnh_list) {
00206 dp_dump_line(p, line++, " via ");
00207
00208 if (nh->rtnh_mask & NEXTHOP_HAS_GATEWAY)
00209 dp_dump(p, "%s ",
00210 nl_addr2str(nh->rtnh_gateway,
00211 buf, sizeof(buf)));
00212 if (link_cache) {
00213 dp_dump(p, "dev %s ",
00214 rtnl_link_i2name(link_cache,
00215 nh->rtnh_ifindex,
00216 buf, sizeof(buf)));
00217 } else
00218 dp_dump(p, "dev %d ", nh->rtnh_ifindex);
00219
00220 dp_dump(p, "weight %u <%s>\n", nh->rtnh_weight,
00221 rtnl_route_nh_flags2str(nh->rtnh_flags,
00222 buf, sizeof(buf)));
00223 }
00224 }
00225
00226 dp_dump_line(p, line++, " ");
00227
00228 if (r->ce_mask & ROUTE_ATTR_PREF_SRC)
00229 dp_dump(p, "preferred-src %s ",
00230 nl_addr2str(r->rt_pref_src, buf, sizeof(buf)));
00231
00232 if (r->ce_mask & ROUTE_ATTR_TABLE)
00233 dp_dump(p, "table %s ",
00234 rtnl_route_table2str(r->rt_table, buf, sizeof(buf)));
00235
00236 if (r->ce_mask & ROUTE_ATTR_TYPE)
00237 dp_dump(p, "type %s ",
00238 nl_rtntype2str(r->rt_type, buf, sizeof(buf)));
00239
00240 if (r->ce_mask & ROUTE_ATTR_PRIO)
00241 dp_dump(p, "metric %#x ", r->rt_prio);
00242
00243 if (r->ce_mask & ROUTE_ATTR_FAMILY)
00244 dp_dump(p, "family %s ",
00245 nl_af2str(r->rt_family, buf, sizeof(buf)));
00246
00247 if (r->ce_mask & ROUTE_ATTR_PROTOCOL)
00248 dp_dump(p, "protocol %s ",
00249 rtnl_route_proto2str(r->rt_protocol, buf, sizeof(buf)));
00250
00251 dp_dump(p, "\n");
00252
00253 if ((r->ce_mask & (ROUTE_ATTR_IIF | ROUTE_ATTR_SRC | ROUTE_ATTR_TOS |
00254 ROUTE_ATTR_REALMS)) ||
00255 ((r->ce_mask & ROUTE_ATTR_CACHEINFO) &&
00256 r->rt_cacheinfo.rtci_error)) {
00257 dp_dump_line(p, line++, " ");
00258
00259 if (r->ce_mask & ROUTE_ATTR_IIF)
00260 dp_dump(p, "iif %s ", r->rt_iif);
00261
00262 if (r->ce_mask & ROUTE_ATTR_SRC)
00263 dp_dump(p, "src %s ",
00264 nl_addr2str(r->rt_src, buf, sizeof(buf)));
00265
00266 if (r->ce_mask & ROUTE_ATTR_TOS)
00267 dp_dump(p, "tos %#x ", r->rt_tos);
00268
00269 if (r->ce_mask & ROUTE_ATTR_REALMS)
00270 dp_dump(p, "realm %04x:%04x ",
00271 RTNL_REALM_FROM(r->rt_realms),
00272 RTNL_REALM_TO(r->rt_realms));
00273
00274 if ((r->ce_mask & ROUTE_ATTR_CACHEINFO) &&
00275 r->rt_cacheinfo.rtci_error)
00276 dp_dump(p, "error %d (%s) ", r->rt_cacheinfo.rtci_error,
00277 strerror(-r->rt_cacheinfo.rtci_error));
00278
00279 dp_dump(p, "\n");
00280 }
00281
00282 if (r->ce_mask & ROUTE_ATTR_METRICS) {
00283 dp_dump_line(p, line++, " ");
00284 for (i = 0; i < RTAX_MAX; i++)
00285 if (r->rt_metrics_mask & (1 << i))
00286 dp_dump(p, "%s %u ",
00287 rtnl_route_metric2str(i+1,
00288 buf, sizeof(buf)),
00289 r->rt_metrics[i]);
00290 dp_dump(p, "\n");
00291 }
00292
00293 return line;
00294 }
00295
00296 static int route_dump_stats(struct nl_object *obj, struct nl_dump_params *p)
00297 {
00298 struct rtnl_route *route = (struct rtnl_route *) obj;
00299 int line;
00300
00301 line = route_dump_full(obj, p);
00302
00303 if (route->ce_mask & ROUTE_ATTR_CACHEINFO) {
00304 struct rtnl_rtcacheinfo *ci = &route->rt_cacheinfo;
00305 dp_dump_line(p, line++, " used %u refcnt %u ",
00306 ci->rtci_used, ci->rtci_clntref);
00307 dp_dump_line(p, line++, "last-use %us expires %us\n",
00308 ci->rtci_last_use / nl_get_hz(),
00309 ci->rtci_expires / nl_get_hz());
00310 }
00311
00312 return line;
00313 }
00314
00315 static int route_dump_xml(struct nl_object *obj, struct nl_dump_params *p)
00316 {
00317 struct rtnl_route *route = (struct rtnl_route *) obj;
00318 char buf[128];
00319 int line = 0;
00320
00321 dp_dump_line(p, line++, "<route>\n");
00322 dp_dump_line(p, line++, " <family>%s</family>\n",
00323 nl_af2str(route->rt_family, buf, sizeof(buf)));
00324
00325 if (route->ce_mask & ROUTE_ATTR_DST)
00326 dp_dump_line(p, line++, " <dst>%s</dst>\n",
00327 nl_addr2str(route->rt_dst, buf, sizeof(buf)));
00328
00329 if (route->ce_mask & ROUTE_ATTR_SRC)
00330 dp_dump_line(p, line++, " <src>%s</src>\n",
00331 nl_addr2str(route->rt_src, buf, sizeof(buf)));
00332
00333 if (route->ce_mask & ROUTE_ATTR_GATEWAY)
00334 dp_dump_line(p, line++, " <gateway>%s</gateway>\n",
00335 nl_addr2str(route->rt_gateway, buf, sizeof(buf)));
00336
00337 if (route->ce_mask & ROUTE_ATTR_PREF_SRC)
00338 dp_dump_line(p, line++, " <prefsrc>%s</prefsrc>\n",
00339 nl_addr2str(route->rt_pref_src, buf, sizeof(buf)));
00340
00341 if (route->ce_mask & ROUTE_ATTR_IIF)
00342 dp_dump_line(p, line++, " <iif>%s</iif>\n", route->rt_iif);
00343
00344 if (route->ce_mask & ROUTE_ATTR_REALMS)
00345 dp_dump_line(p, line++, " <realms>%u</realms>\n",
00346 route->rt_realms);
00347
00348 if (route->ce_mask & ROUTE_ATTR_TOS)
00349 dp_dump_line(p, line++, " <tos>%u</tos>\n", route->rt_tos);
00350
00351 if (route->ce_mask & ROUTE_ATTR_TABLE)
00352 dp_dump_line(p, line++, " <table>%u</table>\n",
00353 route->rt_table);
00354
00355 if (route->ce_mask & ROUTE_ATTR_SCOPE)
00356 dp_dump_line(p, line++, " <scope>%s</scope>\n",
00357 rtnl_scope2str(route->rt_scope, buf, sizeof(buf)));
00358
00359 if (route->ce_mask & ROUTE_ATTR_PRIO)
00360 dp_dump_line(p, line++, " <metric>%u</metric>\n",
00361 route->rt_prio);
00362
00363 if (route->ce_mask & ROUTE_ATTR_OIF) {
00364 struct nl_cache *link_cache;
00365
00366 link_cache = nl_cache_mngt_require("route/link");
00367 if (link_cache)
00368 dp_dump_line(p, line++, " <oif>%s</oif>\n",
00369 rtnl_link_i2name(link_cache,
00370 route->rt_oif,
00371 buf, sizeof(buf)));
00372 else
00373 dp_dump_line(p, line++, " <oif>%u</oif>\n",
00374 route->rt_oif);
00375 }
00376
00377 if (route->ce_mask & ROUTE_ATTR_TYPE)
00378 dp_dump_line(p, line++, " <type>%s</type>\n",
00379 nl_rtntype2str(route->rt_type, buf, sizeof(buf)));
00380
00381 dp_dump_line(p, line++, "</route>\n");
00382
00383 #if 0
00384 uint8_t rt_protocol;
00385 uint32_t rt_flags;
00386 uint32_t rt_metrics[RTAX_MAX];
00387 uint32_t rt_metrics_mask;
00388 struct rtnl_nexthop * rt_nexthops;
00389 struct rtnl_rtcacheinfo rt_cacheinfo;
00390 uint32_t rt_mp_algo;
00391
00392 #endif
00393
00394 return line;
00395 }
00396
00397 static int route_dump_env(struct nl_object *obj, struct nl_dump_params *p)
00398 {
00399 struct rtnl_route *route = (struct rtnl_route *) obj;
00400 char buf[128];
00401 int line = 0;
00402
00403 dp_dump_line(p, line++, "ROUTE_FAMILY=%s\n",
00404 nl_af2str(route->rt_family, buf, sizeof(buf)));
00405
00406 if (route->ce_mask & ROUTE_ATTR_DST)
00407 dp_dump_line(p, line++, "ROUTE_DST=%s\n",
00408 nl_addr2str(route->rt_dst, buf, sizeof(buf)));
00409
00410 if (route->ce_mask & ROUTE_ATTR_SRC)
00411 dp_dump_line(p, line++, "ROUTE_SRC=%s\n",
00412 nl_addr2str(route->rt_src, buf, sizeof(buf)));
00413
00414 if (route->ce_mask & ROUTE_ATTR_GATEWAY)
00415 dp_dump_line(p, line++, "ROUTE_GATEWAY=%s\n",
00416 nl_addr2str(route->rt_gateway, buf, sizeof(buf)));
00417
00418 if (route->ce_mask & ROUTE_ATTR_PREF_SRC)
00419 dp_dump_line(p, line++, "ROUTE_PREFSRC=%s\n",
00420 nl_addr2str(route->rt_pref_src, buf, sizeof(buf)));
00421
00422 if (route->ce_mask & ROUTE_ATTR_IIF)
00423 dp_dump_line(p, line++, "ROUTE_IIF=%s\n", route->rt_iif);
00424
00425 if (route->ce_mask & ROUTE_ATTR_REALMS)
00426 dp_dump_line(p, line++, "ROUTE_REALM=%u\n",
00427 route->rt_realms);
00428
00429 if (route->ce_mask & ROUTE_ATTR_TOS)
00430 dp_dump_line(p, line++, "ROUTE_TOS=%u\n", route->rt_tos);
00431
00432 if (route->ce_mask & ROUTE_ATTR_TABLE)
00433 dp_dump_line(p, line++, "ROUTE_TABLE=%u\n",
00434 route->rt_table);
00435
00436 if (route->ce_mask & ROUTE_ATTR_SCOPE)
00437 dp_dump_line(p, line++, "ROUTE_SCOPE=%s\n",
00438 rtnl_scope2str(route->rt_scope, buf, sizeof(buf)));
00439
00440 if (route->ce_mask & ROUTE_ATTR_PRIO)
00441 dp_dump_line(p, line++, "ROUTE_METRIC=%u\n",
00442 route->rt_prio);
00443
00444 if (route->ce_mask & ROUTE_ATTR_OIF) {
00445 struct nl_cache *link_cache;
00446
00447 dp_dump_line(p, line++, "ROUTE_OIF_IFINDEX=%u\n",
00448 route->rt_oif);
00449
00450 link_cache = nl_cache_mngt_require("route/link");
00451 if (link_cache)
00452 dp_dump_line(p, line++, "ROUTE_OIF_IFNAME=%s\n",
00453 rtnl_link_i2name(link_cache,
00454 route->rt_oif,
00455 buf, sizeof(buf)));
00456 }
00457
00458 if (route->ce_mask & ROUTE_ATTR_TYPE)
00459 dp_dump_line(p, line++, "ROUTE_TYPE=%s\n",
00460 nl_rtntype2str(route->rt_type, buf, sizeof(buf)));
00461
00462 return line;
00463 }
00464
00465 static int route_compare(struct nl_object *_a, struct nl_object *_b,
00466 uint32_t attrs, int flags)
00467 {
00468 struct rtnl_route *a = (struct rtnl_route *) _a;
00469 struct rtnl_route *b = (struct rtnl_route *) _b;
00470 int diff = 0;
00471
00472 #define ROUTE_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ROUTE_ATTR_##ATTR, a, b, EXPR)
00473
00474 diff |= ROUTE_DIFF(FAMILY, a->rt_family != b->rt_family);
00475 diff |= ROUTE_DIFF(TOS, a->rt_tos != b->rt_tos);
00476 diff |= ROUTE_DIFF(TABLE, a->rt_table != b->rt_table);
00477 diff |= ROUTE_DIFF(PROTOCOL, a->rt_protocol != b->rt_protocol);
00478 diff |= ROUTE_DIFF(SCOPE, a->rt_scope != b->rt_scope);
00479 diff |= ROUTE_DIFF(TYPE, a->rt_type != b->rt_type);
00480 diff |= ROUTE_DIFF(OIF, a->rt_oif != b->rt_oif);
00481 diff |= ROUTE_DIFF(PRIO, a->rt_prio != b->rt_prio);
00482 diff |= ROUTE_DIFF(REALMS, a->rt_realms != b->rt_realms);
00483 diff |= ROUTE_DIFF(MP_ALGO, a->rt_mp_algo != b->rt_mp_algo);
00484 diff |= ROUTE_DIFF(DST, nl_addr_cmp(a->rt_dst, b->rt_dst));
00485 diff |= ROUTE_DIFF(SRC, nl_addr_cmp(a->rt_src, b->rt_src));
00486 diff |= ROUTE_DIFF(IIF, strcmp(a->rt_iif, b->rt_iif));
00487 diff |= ROUTE_DIFF(PREF_SRC, nl_addr_cmp(a->rt_pref_src,
00488 b->rt_pref_src));
00489 diff |= ROUTE_DIFF(GATEWAY, nl_addr_cmp(a->rt_gateway,
00490 b->rt_gateway));
00491
00492
00493
00494 if (flags & LOOSE_FLAG_COMPARISON)
00495 diff |= ROUTE_DIFF(FLAGS,
00496 (a->rt_flags ^ b->rt_flags) & b->rt_flag_mask);
00497 else
00498 diff |= ROUTE_DIFF(FLAGS, a->rt_flags != b->rt_flags);
00499
00500 #undef ROUTE_DIFF
00501
00502 return diff;
00503 }
00504
00505 static struct trans_tbl route_attrs[] = {
00506 __ADD(ROUTE_ATTR_FAMILY, family)
00507 __ADD(ROUTE_ATTR_TOS, tos)
00508 __ADD(ROUTE_ATTR_TABLE, table)
00509 __ADD(ROUTE_ATTR_PROTOCOL, protocol)
00510 __ADD(ROUTE_ATTR_SCOPE, scope)
00511 __ADD(ROUTE_ATTR_TYPE, type)
00512 __ADD(ROUTE_ATTR_FLAGS, flags)
00513 __ADD(ROUTE_ATTR_DST, dst)
00514 __ADD(ROUTE_ATTR_SRC, src)
00515 __ADD(ROUTE_ATTR_IIF, iif)
00516 __ADD(ROUTE_ATTR_OIF, oif)
00517 __ADD(ROUTE_ATTR_GATEWAY, gateway)
00518 __ADD(ROUTE_ATTR_PRIO, prio)
00519 __ADD(ROUTE_ATTR_PREF_SRC, pref_src)
00520 __ADD(ROUTE_ATTR_METRICS, metrics)
00521 __ADD(ROUTE_ATTR_MULTIPATH, multipath)
00522 __ADD(ROUTE_ATTR_REALMS, realms)
00523 __ADD(ROUTE_ATTR_CACHEINFO, cacheinfo)
00524 __ADD(ROUTE_ATTR_MP_ALGO, mp_algo)
00525 };
00526
00527 static char *route_attrs2str(int attrs, char *buf, size_t len)
00528 {
00529 return __flags2str(attrs, buf, len, route_attrs,
00530 ARRAY_SIZE(route_attrs));
00531 }
00532
00533
00534
00535
00536
00537
00538 struct rtnl_route *rtnl_route_alloc(void)
00539 {
00540 return (struct rtnl_route *) nl_object_alloc(&route_obj_ops);
00541 }
00542
00543 void rtnl_route_get(struct rtnl_route *route)
00544 {
00545 nl_object_get((struct nl_object *) route);
00546 }
00547
00548 void rtnl_route_put(struct rtnl_route *route)
00549 {
00550 nl_object_put((struct nl_object *) route);
00551 }
00552
00553
00554
00555
00556
00557
00558
00559
00560 void rtnl_route_set_table(struct rtnl_route *route, int table)
00561 {
00562 route->rt_table = table;
00563 route->ce_mask |= ROUTE_ATTR_TABLE;
00564 }
00565
00566 int rtnl_route_get_table(struct rtnl_route *route)
00567 {
00568 if (route->ce_mask & ROUTE_ATTR_TABLE)
00569 return route->rt_table;
00570 else
00571 return RT_TABLE_MAIN;
00572 }
00573
00574 void rtnl_route_set_scope(struct rtnl_route *route, int scope)
00575 {
00576 route->rt_scope = scope;
00577 route->ce_mask |= ROUTE_ATTR_SCOPE;
00578 }
00579
00580 int rtnl_route_get_scope(struct rtnl_route *route)
00581 {
00582 if (route->ce_mask & ROUTE_ATTR_SCOPE)
00583 return route->rt_scope;
00584 else
00585 return RT_SCOPE_NOWHERE;
00586 }
00587
00588 void rtnl_route_set_tos(struct rtnl_route *route, int tos)
00589 {
00590 route->rt_tos = tos;
00591 route->ce_mask |= ROUTE_ATTR_TOS;
00592 }
00593
00594 int rtnl_route_get_tos(struct rtnl_route *route)
00595 {
00596 return route->rt_tos;
00597 }
00598
00599 void rtnl_route_set_realms(struct rtnl_route *route, realm_t realms)
00600 {
00601 route->rt_realms = realms;
00602 route->ce_mask |= ROUTE_ATTR_REALMS;
00603 }
00604
00605 realm_t rtnl_route_get_realms(struct rtnl_route *route)
00606 {
00607 return route->rt_realms;
00608 }
00609
00610 void rtnl_route_set_protocol(struct rtnl_route *route, int proto)
00611 {
00612 route->rt_protocol = proto;
00613 route->ce_mask |= ROUTE_ATTR_PROTOCOL;
00614 }
00615
00616 int rtnl_route_get_protocol(struct rtnl_route *route)
00617 {
00618 if (route->ce_mask & ROUTE_ATTR_PROTOCOL)
00619 return route->rt_protocol;
00620 else
00621 return RTPROT_STATIC;
00622 }
00623
00624 void rtnl_route_set_prio(struct rtnl_route *route, int prio)
00625 {
00626 route->rt_prio = prio;
00627 route->ce_mask |= ROUTE_ATTR_PRIO;
00628 }
00629
00630 int rtnl_route_get_prio(struct rtnl_route *route)
00631 {
00632 return route->rt_prio;
00633 }
00634
00635 void rtnl_route_set_family(struct rtnl_route *route, int family)
00636 {
00637 route->rt_family = family;
00638 route->ce_mask |= ROUTE_ATTR_FAMILY;
00639 }
00640
00641 int rtnl_route_get_family(struct rtnl_route *route)
00642 {
00643 if (route->ce_mask & ROUTE_ATTR_FAMILY)
00644 return route->rt_family;
00645 else
00646 return AF_UNSPEC;
00647 }
00648
00649 int rtnl_route_set_dst(struct rtnl_route *route, struct nl_addr *addr)
00650 {
00651 if (route->ce_mask & ROUTE_ATTR_FAMILY) {
00652 if (addr->a_family != route->rt_family)
00653 return nl_error(EINVAL, "Address family mismatch");
00654 } else
00655 route->rt_family = addr->a_family;
00656
00657 if (route->rt_dst)
00658 nl_addr_put(route->rt_dst);
00659
00660 nl_addr_get(addr);
00661 route->rt_dst = addr;
00662
00663 route->ce_mask |= (ROUTE_ATTR_DST | ROUTE_ATTR_FAMILY);
00664
00665 return 0;
00666 }
00667
00668 struct nl_addr *rtnl_route_get_dst(struct rtnl_route *route)
00669 {
00670 return route->rt_dst;
00671 }
00672
00673 int rtnl_route_get_dst_len(struct rtnl_route *route)
00674 {
00675 if (route->ce_mask & ROUTE_ATTR_DST)
00676 return nl_addr_get_prefixlen(route->rt_dst);
00677 else
00678 return 0;
00679 }
00680
00681 int rtnl_route_set_src(struct rtnl_route *route, struct nl_addr *addr)
00682 {
00683 if (route->ce_mask & ROUTE_ATTR_FAMILY) {
00684 if (addr->a_family != route->rt_family)
00685 return nl_error(EINVAL, "Address family mismatch");
00686 } else
00687 route->rt_family = addr->a_family;
00688
00689 if (route->rt_src)
00690 nl_addr_put(route->rt_src);
00691
00692 nl_addr_get(addr);
00693 route->rt_src = addr;
00694 route->ce_mask |= (ROUTE_ATTR_SRC | ROUTE_ATTR_FAMILY);
00695
00696 return 0;
00697 }
00698
00699 struct nl_addr *rtnl_route_get_src(struct rtnl_route *route)
00700 {
00701 return route->rt_src;
00702 }
00703
00704 int rtnl_route_get_src_len(struct rtnl_route *route)
00705 {
00706 if (route->ce_mask & ROUTE_ATTR_SRC)
00707 return nl_addr_get_prefixlen(route->rt_src);
00708 else
00709 return 0;
00710 }
00711
00712 int rtnl_route_set_gateway(struct rtnl_route *route, struct nl_addr *addr)
00713 {
00714 if (route->ce_mask & ROUTE_ATTR_FAMILY) {
00715 if (addr->a_family != route->rt_family)
00716 return nl_error(EINVAL, "Address family mismatch");
00717 } else
00718 route->rt_family = addr->a_family;
00719
00720 if (route->rt_gateway)
00721 nl_addr_put(route->rt_gateway);
00722
00723 nl_addr_get(addr);
00724 route->rt_gateway = addr;
00725 route->ce_mask |= (ROUTE_ATTR_GATEWAY | ROUTE_ATTR_FAMILY);
00726
00727 return 0;
00728 }
00729
00730 struct nl_addr *rtnl_route_get_gateway(struct rtnl_route *route)
00731 {
00732 return route->rt_gateway;
00733 }
00734
00735 void rtnl_route_set_type(struct rtnl_route *route, int type)
00736 {
00737 route->rt_type = type;
00738 route->ce_mask |= ROUTE_ATTR_TYPE;
00739 }
00740
00741 int rtnl_route_get_type(struct rtnl_route *route)
00742 {
00743 if (route->ce_mask & ROUTE_ATTR_TYPE)
00744 return route->rt_type;
00745 else
00746 return RTN_UNICAST;
00747 }
00748
00749 void rtnl_route_set_flags(struct rtnl_route *route, unsigned int flags)
00750 {
00751 route->rt_flag_mask |= flags;
00752 route->rt_flags |= flags;
00753 route->ce_mask |= ROUTE_ATTR_FLAGS;
00754 }
00755
00756 void rtnl_route_unset_flags(struct rtnl_route *route, unsigned int flags)
00757 {
00758 route->rt_flag_mask |= flags;
00759 route->rt_flags &= ~flags;
00760 route->ce_mask |= ROUTE_ATTR_FLAGS;
00761 }
00762
00763 unsigned int rtnl_route_get_flags(struct rtnl_route *route)
00764 {
00765 return route->rt_flags;
00766 }
00767
00768 int rtnl_route_set_metric(struct rtnl_route *route, int metric, uint32_t value)
00769 {
00770 if (metric > RTAX_MAX || metric < 1)
00771 return nl_error(EINVAL, "Metric out of range (1..%d)",
00772 RTAX_MAX);
00773
00774 route->rt_metrics[metric - 1] = value;
00775 route->rt_metrics_mask |= (1 << (metric - 1));
00776
00777 return 0;
00778 }
00779
00780 int rtnl_route_unset_metric(struct rtnl_route *route, int metric)
00781 {
00782 if (metric > RTAX_MAX || metric < 1)
00783 return nl_error(EINVAL, "Metric out of range (1..%d)",
00784 RTAX_MAX);
00785
00786 route->rt_metrics_mask &= ~(1 << (metric - 1));
00787
00788 return 0;
00789 }
00790
00791 unsigned int rtnl_route_get_metric(struct rtnl_route *route, int metric)
00792 {
00793 if (metric > RTAX_MAX || metric < 1)
00794 return UINT_MAX;
00795
00796 if (!(route->rt_metrics_mask & (1 << (metric - 1))))
00797 return UINT_MAX;
00798
00799 return route->rt_metrics[metric - 1];
00800 }
00801
00802 int rtnl_route_set_pref_src(struct rtnl_route *route, struct nl_addr *addr)
00803 {
00804 if (route->ce_mask & ROUTE_ATTR_FAMILY) {
00805 if (addr->a_family != route->rt_family)
00806 return nl_error(EINVAL, "Address family mismatch");
00807 } else
00808 route->rt_family = addr->a_family;
00809
00810 if (route->rt_pref_src)
00811 nl_addr_put(route->rt_pref_src);
00812
00813 nl_addr_get(addr);
00814 route->rt_pref_src = addr;
00815 route->ce_mask |= (ROUTE_ATTR_PREF_SRC | ROUTE_ATTR_FAMILY);
00816
00817 return 0;
00818 }
00819
00820 struct nl_addr *rtnl_route_get_pref_src(struct rtnl_route *route)
00821 {
00822 return route->rt_pref_src;
00823 }
00824
00825 void rtnl_route_set_oif(struct rtnl_route *route, int ifindex)
00826 {
00827 route->rt_oif = ifindex;
00828 route->ce_mask |= ROUTE_ATTR_OIF;
00829 }
00830
00831 int rtnl_route_get_oif(struct rtnl_route *route)
00832 {
00833 if (route->ce_mask & ROUTE_ATTR_OIF)
00834 return route->rt_oif;
00835 else
00836 return RTNL_LINK_NOT_FOUND;
00837 }
00838
00839 void rtnl_route_set_iif(struct rtnl_route *route, const char *name)
00840 {
00841 strncpy(route->rt_iif, name, sizeof(route->rt_iif) - 1);
00842 route->ce_mask |= ROUTE_ATTR_IIF;
00843 }
00844
00845 char *rtnl_route_get_iif(struct rtnl_route *route)
00846 {
00847 if (route->ce_mask & ROUTE_ATTR_IIF)
00848 return route->rt_iif;
00849 else
00850 return NULL;
00851 }
00852
00853 void rtnl_route_add_nexthop(struct rtnl_route *route, struct rtnl_nexthop *nh)
00854 {
00855 nl_list_add_tail(&nh->rtnh_list, &route->rt_nexthops);
00856 route->ce_mask |= ROUTE_ATTR_MULTIPATH;
00857 }
00858
00859 void rtnl_route_remove_nexthop(struct rtnl_nexthop *nh)
00860 {
00861 nl_list_del(&nh->rtnh_list);
00862 }
00863
00864 struct nl_list_head *rtnl_route_get_nexthops(struct rtnl_route *route)
00865 {
00866 return &route->rt_nexthops;
00867 }
00868
00869 void rtnl_route_set_cacheinfo(struct rtnl_route *route,
00870 struct rtnl_rtcacheinfo *ci)
00871 {
00872 memcpy(&route->rt_cacheinfo, ci, sizeof(*ci));
00873 route->ce_mask |= ROUTE_ATTR_CACHEINFO;
00874 }
00875
00876 uint32_t rtnl_route_get_mp_algo(struct rtnl_route *route)
00877 {
00878 if (route->ce_mask & ROUTE_ATTR_MP_ALGO)
00879 return route->rt_mp_algo;
00880 else
00881 return IP_MP_ALG_NONE;
00882 }
00883
00884 void rtnl_route_set_mp_algo(struct rtnl_route *route, uint32_t algo)
00885 {
00886 route->rt_mp_algo = algo;
00887 route->ce_mask |= ROUTE_ATTR_MP_ALGO;
00888 }
00889
00890
00891
00892 struct nl_object_ops route_obj_ops = {
00893 .oo_name = "route/route",
00894 .oo_size = sizeof(struct rtnl_route),
00895 .oo_constructor = route_constructor,
00896 .oo_free_data = route_free_data,
00897 .oo_clone = route_clone,
00898 .oo_dump[NL_DUMP_BRIEF] = route_dump_brief,
00899 .oo_dump[NL_DUMP_FULL] = route_dump_full,
00900 .oo_dump[NL_DUMP_STATS] = route_dump_stats,
00901 .oo_dump[NL_DUMP_XML] = route_dump_xml,
00902 .oo_dump[NL_DUMP_ENV] = route_dump_env,
00903 .oo_compare = route_compare,
00904 .oo_attrs2str = route_attrs2str,
00905 .oo_id_attrs = (ROUTE_ATTR_FAMILY | ROUTE_ATTR_TOS |
00906 ROUTE_ATTR_TABLE | ROUTE_ATTR_DST),
00907 };
00908
00909