libnl 1.1
|
00001 /* 00002 * lib/route/route_obj.c Route Object 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 route 00014 * @defgroup route_obj Route Object 00015 * 00016 * @par Attributes 00017 * @code 00018 * Name Default 00019 * ------------------------------------------------------------- 00020 * routing table RT_TABLE_MAIN 00021 * scope RT_SCOPE_NOWHERE 00022 * tos 0 00023 * realms 0 00024 * protocol RTPROT_STATIC 00025 * prio 0 00026 * family AF_UNSPEC 00027 * type RTN_UNICAST 00028 * oif RTNL_LINK_NOT_FOUND 00029 * iif NULL 00030 * mpalgo IP_MP_ALG_NONE 00031 * @endcode 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 /** @cond SKIP */ 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 /** @endcond */ 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 /* FIXME: Compare metrics, multipath config */ 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 * @name Allocation/Freeing 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 * @name Attributes 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 /** @} */