libnl
3.2.3
|
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 void rtnl_route_nh_dump(struct rtnl_nexthop *nh, struct nl_dump_params *dp) 00170 { 00171 switch (dp->dp_type) { 00172 case NL_DUMP_LINE: 00173 nh_dump_line(nh, dp); 00174 break; 00175 00176 case NL_DUMP_DETAILS: 00177 case NL_DUMP_STATS: 00178 if (dp->dp_ivar == NH_DUMP_FROM_DETAILS) 00179 nh_dump_details(nh, dp); 00180 break; 00181 00182 default: 00183 break; 00184 } 00185 } 00186 00187 /** 00188 * @name Attributes 00189 * @{ 00190 */ 00191 00192 void rtnl_route_nh_set_weight(struct rtnl_nexthop *nh, uint8_t weight) 00193 { 00194 nh->rtnh_weight = weight; 00195 nh->ce_mask |= NH_ATTR_WEIGHT; 00196 } 00197 00198 uint8_t rtnl_route_nh_get_weight(struct rtnl_nexthop *nh) 00199 { 00200 return nh->rtnh_weight; 00201 } 00202 00203 void rtnl_route_nh_set_ifindex(struct rtnl_nexthop *nh, int ifindex) 00204 { 00205 nh->rtnh_ifindex = ifindex; 00206 nh->ce_mask |= NH_ATTR_IFINDEX; 00207 } 00208 00209 int rtnl_route_nh_get_ifindex(struct rtnl_nexthop *nh) 00210 { 00211 return nh->rtnh_ifindex; 00212 } 00213 00214 void rtnl_route_nh_set_gateway(struct rtnl_nexthop *nh, struct nl_addr *addr) 00215 { 00216 struct nl_addr *old = nh->rtnh_gateway; 00217 00218 if (addr) { 00219 nh->rtnh_gateway = nl_addr_get(addr); 00220 nh->ce_mask |= NH_ATTR_GATEWAY; 00221 } else { 00222 nh->ce_mask &= ~NH_ATTR_GATEWAY; 00223 nh->rtnh_gateway = NULL; 00224 } 00225 00226 if (old) 00227 nl_addr_put(old); 00228 } 00229 00230 struct nl_addr *rtnl_route_nh_get_gateway(struct rtnl_nexthop *nh) 00231 { 00232 return nh->rtnh_gateway; 00233 } 00234 00235 void rtnl_route_nh_set_flags(struct rtnl_nexthop *nh, unsigned int flags) 00236 { 00237 nh->rtnh_flag_mask |= flags; 00238 nh->rtnh_flags |= flags; 00239 nh->ce_mask |= NH_ATTR_FLAGS; 00240 } 00241 00242 void rtnl_route_nh_unset_flags(struct rtnl_nexthop *nh, unsigned int flags) 00243 { 00244 nh->rtnh_flag_mask |= flags; 00245 nh->rtnh_flags &= ~flags; 00246 nh->ce_mask |= NH_ATTR_FLAGS; 00247 } 00248 00249 unsigned int rtnl_route_nh_get_flags(struct rtnl_nexthop *nh) 00250 { 00251 return nh->rtnh_flags; 00252 } 00253 00254 void rtnl_route_nh_set_realms(struct rtnl_nexthop *nh, uint32_t realms) 00255 { 00256 nh->rtnh_realms = realms; 00257 nh->ce_mask |= NH_ATTR_REALMS; 00258 } 00259 00260 uint32_t rtnl_route_nh_get_realms(struct rtnl_nexthop *nh) 00261 { 00262 return nh->rtnh_realms; 00263 } 00264 00265 /** @} */ 00266 00267 /** 00268 * @name Nexthop Flags Translations 00269 * @{ 00270 */ 00271 00272 static const struct trans_tbl nh_flags[] = { 00273 __ADD(RTNH_F_DEAD, dead) 00274 __ADD(RTNH_F_PERVASIVE, pervasive) 00275 __ADD(RTNH_F_ONLINK, onlink) 00276 }; 00277 00278 char *rtnl_route_nh_flags2str(int flags, char *buf, size_t len) 00279 { 00280 return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags)); 00281 } 00282 00283 int rtnl_route_nh_str2flags(const char *name) 00284 { 00285 return __str2flags(name, nh_flags, ARRAY_SIZE(nh_flags)); 00286 } 00287 00288 /** @} */ 00289 00290 /** @} */