libnl 2.0

/tmp/buildd/libnl2-2.0/lib/route/nexthop.c

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 /** @} */