libnl 2.0
|
00001 /* 00002 * lib/route/nexthop.c Routing Nexthop 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-2008 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 /** 00013 * @ingroup route_obj 00014 * @defgroup nexthop Nexthop 00015 * @{ 00016 */ 00017 00018 #include <netlink-local.h> 00019 #include <netlink/netlink.h> 00020 #include <netlink/utils.h> 00021 #include <netlink/route/rtnl.h> 00022 #include <netlink/route/route.h> 00023 00024 /** @cond SKIP */ 00025 #define NH_ATTR_FLAGS 0x000001 00026 #define NH_ATTR_WEIGHT 0x000002 00027 #define NH_ATTR_IFINDEX 0x000004 00028 #define NH_ATTR_GATEWAY 0x000008 00029 #define NH_ATTR_REALMS 0x000010 00030 /** @endcond */ 00031 00032 /** 00033 * @name Allocation/Freeing 00034 * @{ 00035 */ 00036 00037 struct rtnl_nexthop *rtnl_route_nh_alloc(void) 00038 { 00039 struct rtnl_nexthop *nh; 00040 00041 nh = calloc(1, sizeof(*nh)); 00042 if (!nh) 00043 return NULL; 00044 00045 nl_init_list_head(&nh->rtnh_list); 00046 00047 return nh; 00048 } 00049 00050 struct rtnl_nexthop *rtnl_route_nh_clone(struct rtnl_nexthop *src) 00051 { 00052 struct rtnl_nexthop *nh; 00053 00054 nh = rtnl_route_nh_alloc(); 00055 if (!nh) 00056 return NULL; 00057 00058 nh->rtnh_flags = src->rtnh_flags; 00059 nh->rtnh_flag_mask = src->rtnh_flag_mask; 00060 nh->rtnh_weight = src->rtnh_weight; 00061 nh->rtnh_ifindex = src->rtnh_ifindex; 00062 nh->ce_mask = src->ce_mask; 00063 00064 if (src->rtnh_gateway) { 00065 nh->rtnh_gateway = nl_addr_clone(src->rtnh_gateway); 00066 if (!nh->rtnh_gateway) { 00067 free(nh); 00068 return NULL; 00069 } 00070 } 00071 00072 return nh; 00073 } 00074 00075 void rtnl_route_nh_free(struct rtnl_nexthop *nh) 00076 { 00077 nl_addr_put(nh->rtnh_gateway); 00078 free(nh); 00079 } 00080 00081 /** @} */ 00082 00083 int rtnl_route_nh_compare(struct rtnl_nexthop *a, struct rtnl_nexthop *b, 00084 uint32_t attrs, int loose) 00085 { 00086 int diff = 0; 00087 00088 #define NH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NH_ATTR_##ATTR, a, b, EXPR) 00089 00090 diff |= NH_DIFF(IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex); 00091 diff |= NH_DIFF(WEIGHT, a->rtnh_weight != b->rtnh_weight); 00092 diff |= NH_DIFF(REALMS, a->rtnh_realms != b->rtnh_realms); 00093 diff |= NH_DIFF(GATEWAY, nl_addr_cmp(a->rtnh_gateway, 00094 b->rtnh_gateway)); 00095 00096 if (loose) 00097 diff |= NH_DIFF(FLAGS, 00098 (a->rtnh_flags ^ b->rtnh_flags) & b->rtnh_flag_mask); 00099 else 00100 diff |= NH_DIFF(FLAGS, a->rtnh_flags != b->rtnh_flags); 00101 00102 #undef NH_DIFF 00103 00104 return diff; 00105 } 00106 00107 static void nh_dump_line(struct rtnl_nexthop *nh, struct nl_dump_params *dp) 00108 { 00109 struct nl_cache *link_cache; 00110 char buf[128]; 00111 00112 link_cache = nl_cache_mngt_require("route/link"); 00113 00114 nl_dump(dp, "via"); 00115 00116 if (nh->ce_mask & NH_ATTR_GATEWAY) 00117 nl_dump(dp, " %s", nl_addr2str(nh->rtnh_gateway, 00118 buf, sizeof(buf))); 00119 00120 if(nh->ce_mask & NH_ATTR_IFINDEX) { 00121 if (link_cache) { 00122 nl_dump(dp, " dev %s", 00123 rtnl_link_i2name(link_cache, 00124 nh->rtnh_ifindex, 00125 buf, sizeof(buf))); 00126 } else 00127 nl_dump(dp, " dev %d", nh->rtnh_ifindex); 00128 } 00129 00130 nl_dump(dp, " "); 00131 } 00132 00133 static void nh_dump_details(struct rtnl_nexthop *nh, struct nl_dump_params *dp) 00134 { 00135 struct nl_cache *link_cache; 00136 char buf[128]; 00137 00138 link_cache = nl_cache_mngt_require("route/link"); 00139 00140 nl_dump(dp, "nexthop"); 00141 00142 if (nh->ce_mask & NH_ATTR_GATEWAY) 00143 nl_dump(dp, " via %s", nl_addr2str(nh->rtnh_gateway, 00144 buf, sizeof(buf))); 00145 00146 if(nh->ce_mask & NH_ATTR_IFINDEX) { 00147 if (link_cache) { 00148 nl_dump(dp, " dev %s", 00149 rtnl_link_i2name(link_cache, 00150 nh->rtnh_ifindex, 00151 buf, sizeof(buf))); 00152 } else 00153 nl_dump(dp, " dev %d", nh->rtnh_ifindex); 00154 } 00155 00156 if (nh->ce_mask & NH_ATTR_WEIGHT) 00157 nl_dump(dp, " weight %u", nh->rtnh_weight); 00158 00159 if (nh->ce_mask & NH_ATTR_REALMS) 00160 nl_dump(dp, " realm %04x:%04x", 00161 RTNL_REALM_FROM(nh->rtnh_realms), 00162 RTNL_REALM_TO(nh->rtnh_realms)); 00163 00164 if (nh->ce_mask & NH_ATTR_FLAGS) 00165 nl_dump(dp, " <%s>", rtnl_route_nh_flags2str(nh->rtnh_flags, 00166 buf, sizeof(buf))); 00167 } 00168 00169 static void nh_dump_env(struct rtnl_nexthop *nh, struct nl_dump_params *dp) 00170 { 00171 struct nl_cache *link_cache; 00172 char buf[128]; 00173 00174 link_cache = nl_cache_mngt_require("route/link"); 00175 00176 if (nh->ce_mask & NH_ATTR_GATEWAY) 00177 nl_dump_line(dp, "ROUTE_NH%d_VIA=%s\n", dp->dp_ivar, 00178 nl_addr2str(nh->rtnh_gateway, buf, sizeof(buf))); 00179 00180 if(nh->ce_mask & NH_ATTR_IFINDEX) { 00181 if (link_cache) { 00182 nl_dump_line(dp, "ROUTE_NH%d_DEV=%s\n", dp->dp_ivar, 00183 rtnl_link_i2name(link_cache, 00184 nh->rtnh_ifindex, 00185 buf, sizeof(buf))); 00186 } else 00187 nl_dump_line(dp, "ROUTE_NH%d_DEV=%d\n", dp->dp_ivar, 00188 nh->rtnh_ifindex); 00189 } 00190 00191 if (nh->ce_mask & NH_ATTR_WEIGHT) 00192 nl_dump_line(dp, "ROUTE_NH%d_WEIGHT=%u\n", dp->dp_ivar, 00193 nh->rtnh_weight); 00194 00195 if (nh->ce_mask & NH_ATTR_REALMS) 00196 nl_dump_line(dp, "ROUTE_NH%d_REALM=%04x:%04x\n", dp->dp_ivar, 00197 RTNL_REALM_FROM(nh->rtnh_realms), 00198 RTNL_REALM_TO(nh->rtnh_realms)); 00199 00200 if (nh->ce_mask & NH_ATTR_FLAGS) 00201 nl_dump_line(dp, "ROUTE_NH%d_FLAGS=<%s>\n", dp->dp_ivar, 00202 rtnl_route_nh_flags2str(nh->rtnh_flags, 00203 buf, sizeof(buf))); 00204 } 00205 void rtnl_route_nh_dump(struct rtnl_nexthop *nh, struct nl_dump_params *dp) 00206 { 00207 switch (dp->dp_type) { 00208 case NL_DUMP_LINE: 00209 nh_dump_line(nh, dp); 00210 break; 00211 00212 case NL_DUMP_DETAILS: 00213 case NL_DUMP_STATS: 00214 if (dp->dp_ivar == NH_DUMP_FROM_DETAILS) 00215 nh_dump_details(nh, dp); 00216 break; 00217 00218 case NL_DUMP_ENV: 00219 nh_dump_env(nh, dp); 00220 break; 00221 00222 default: 00223 break; 00224 } 00225 } 00226 00227 /** 00228 * @name Attributes 00229 * @{ 00230 */ 00231 00232 void rtnl_route_nh_set_weight(struct rtnl_nexthop *nh, uint8_t weight) 00233 { 00234 nh->rtnh_weight = weight; 00235 nh->ce_mask |= NH_ATTR_WEIGHT; 00236 } 00237 00238 uint8_t rtnl_route_nh_get_weight(struct rtnl_nexthop *nh) 00239 { 00240 return nh->rtnh_weight; 00241 } 00242 00243 void rtnl_route_nh_set_ifindex(struct rtnl_nexthop *nh, int ifindex) 00244 { 00245 nh->rtnh_ifindex = ifindex; 00246 nh->ce_mask |= NH_ATTR_IFINDEX; 00247 } 00248 00249 int rtnl_route_nh_get_ifindex(struct rtnl_nexthop *nh) 00250 { 00251 return nh->rtnh_ifindex; 00252 } 00253 00254 void rtnl_route_nh_set_gateway(struct rtnl_nexthop *nh, struct nl_addr *addr) 00255 { 00256 struct nl_addr *old = nh->rtnh_gateway; 00257 00258 if (addr) { 00259 nh->rtnh_gateway = nl_addr_get(addr); 00260 nh->ce_mask |= NH_ATTR_GATEWAY; 00261 } else { 00262 nh->ce_mask &= ~NH_ATTR_GATEWAY; 00263 nh->rtnh_gateway = NULL; 00264 } 00265 00266 if (old) 00267 nl_addr_put(old); 00268 } 00269 00270 struct nl_addr *rtnl_route_nh_get_gateway(struct rtnl_nexthop *nh) 00271 { 00272 return nh->rtnh_gateway; 00273 } 00274 00275 void rtnl_route_nh_set_flags(struct rtnl_nexthop *nh, unsigned int flags) 00276 { 00277 nh->rtnh_flag_mask |= flags; 00278 nh->rtnh_flags |= flags; 00279 nh->ce_mask |= NH_ATTR_FLAGS; 00280 } 00281 00282 void rtnl_route_nh_unset_flags(struct rtnl_nexthop *nh, unsigned int flags) 00283 { 00284 nh->rtnh_flag_mask |= flags; 00285 nh->rtnh_flags &= ~flags; 00286 nh->ce_mask |= NH_ATTR_FLAGS; 00287 } 00288 00289 unsigned int rtnl_route_nh_get_flags(struct rtnl_nexthop *nh) 00290 { 00291 return nh->rtnh_flags; 00292 } 00293 00294 void rtnl_route_nh_set_realms(struct rtnl_nexthop *nh, uint32_t realms) 00295 { 00296 nh->rtnh_realms = realms; 00297 nh->ce_mask |= NH_ATTR_REALMS; 00298 } 00299 00300 uint32_t rtnl_route_nh_get_realms(struct rtnl_nexthop *nh) 00301 { 00302 return nh->rtnh_realms; 00303 } 00304 00305 /** @} */ 00306 00307 /** 00308 * @name Nexthop Flags Translations 00309 * @{ 00310 */ 00311 00312 static struct trans_tbl nh_flags[] = { 00313 __ADD(RTNH_F_DEAD, dead) 00314 __ADD(RTNH_F_PERVASIVE, pervasive) 00315 __ADD(RTNH_F_ONLINK, onlink) 00316 }; 00317 00318 char *rtnl_route_nh_flags2str(int flags, char *buf, size_t len) 00319 { 00320 return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags)); 00321 } 00322 00323 int rtnl_route_nh_str2flags(const char *name) 00324 { 00325 return __str2flags(name, nh_flags, ARRAY_SIZE(nh_flags)); 00326 } 00327 00328 /** @} */ 00329 00330 /** @} */