nexthop.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. * lib/route/nexthop.c Routing Nexthop
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation version 2.1
  7. * of the License.
  8. *
  9. * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch>
  10. */
  11. /**
  12. * @ingroup route_obj
  13. * @defgroup nexthop Nexthop
  14. * @{
  15. */
  16. #include <netlink-private/netlink.h>
  17. #include <netlink/netlink.h>
  18. #include <netlink/utils.h>
  19. #include <netlink/route/rtnl.h>
  20. #include <netlink/route/route.h>
  21. /** @cond SKIP */
  22. #define NH_ATTR_FLAGS 0x000001
  23. #define NH_ATTR_WEIGHT 0x000002
  24. #define NH_ATTR_IFINDEX 0x000004
  25. #define NH_ATTR_GATEWAY 0x000008
  26. #define NH_ATTR_REALMS 0x000010
  27. /** @endcond */
  28. /**
  29. * @name Allocation/Freeing
  30. * @{
  31. */
  32. struct rtnl_nexthop *rtnl_route_nh_alloc(void)
  33. {
  34. struct rtnl_nexthop *nh;
  35. nh = calloc(1, sizeof(*nh));
  36. if (!nh)
  37. return NULL;
  38. nl_init_list_head(&nh->rtnh_list);
  39. return nh;
  40. }
  41. struct rtnl_nexthop *rtnl_route_nh_clone(struct rtnl_nexthop *src)
  42. {
  43. struct rtnl_nexthop *nh;
  44. nh = rtnl_route_nh_alloc();
  45. if (!nh)
  46. return NULL;
  47. nh->rtnh_flags = src->rtnh_flags;
  48. nh->rtnh_flag_mask = src->rtnh_flag_mask;
  49. nh->rtnh_weight = src->rtnh_weight;
  50. nh->rtnh_ifindex = src->rtnh_ifindex;
  51. nh->ce_mask = src->ce_mask;
  52. if (src->rtnh_gateway) {
  53. nh->rtnh_gateway = nl_addr_clone(src->rtnh_gateway);
  54. if (!nh->rtnh_gateway) {
  55. free(nh);
  56. return NULL;
  57. }
  58. }
  59. return nh;
  60. }
  61. void rtnl_route_nh_free(struct rtnl_nexthop *nh)
  62. {
  63. nl_addr_put(nh->rtnh_gateway);
  64. free(nh);
  65. }
  66. /** @} */
  67. int rtnl_route_nh_compare(struct rtnl_nexthop *a, struct rtnl_nexthop *b,
  68. uint32_t attrs, int loose)
  69. {
  70. int diff = 0;
  71. #define NH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NH_ATTR_##ATTR, a, b, EXPR)
  72. diff |= NH_DIFF(IFINDEX, a->rtnh_ifindex != b->rtnh_ifindex);
  73. diff |= NH_DIFF(WEIGHT, a->rtnh_weight != b->rtnh_weight);
  74. diff |= NH_DIFF(REALMS, a->rtnh_realms != b->rtnh_realms);
  75. diff |= NH_DIFF(GATEWAY, nl_addr_cmp(a->rtnh_gateway,
  76. b->rtnh_gateway));
  77. if (loose)
  78. diff |= NH_DIFF(FLAGS,
  79. (a->rtnh_flags ^ b->rtnh_flags) & b->rtnh_flag_mask);
  80. else
  81. diff |= NH_DIFF(FLAGS, a->rtnh_flags != b->rtnh_flags);
  82. #undef NH_DIFF
  83. return diff;
  84. }
  85. static void nh_dump_line(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
  86. {
  87. struct nl_cache *link_cache;
  88. char buf[128];
  89. link_cache = nl_cache_mngt_require_safe("route/link");
  90. nl_dump(dp, "via");
  91. if (nh->ce_mask & NH_ATTR_GATEWAY)
  92. nl_dump(dp, " %s", nl_addr2str(nh->rtnh_gateway,
  93. buf, sizeof(buf)));
  94. if(nh->ce_mask & NH_ATTR_IFINDEX) {
  95. if (link_cache) {
  96. nl_dump(dp, " dev %s",
  97. rtnl_link_i2name(link_cache,
  98. nh->rtnh_ifindex,
  99. buf, sizeof(buf)));
  100. } else
  101. nl_dump(dp, " dev %d", nh->rtnh_ifindex);
  102. }
  103. nl_dump(dp, " ");
  104. if (link_cache)
  105. nl_cache_put(link_cache);
  106. }
  107. static void nh_dump_details(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
  108. {
  109. struct nl_cache *link_cache;
  110. char buf[128];
  111. link_cache = nl_cache_mngt_require_safe("route/link");
  112. nl_dump(dp, "nexthop");
  113. if (nh->ce_mask & NH_ATTR_GATEWAY)
  114. nl_dump(dp, " via %s", nl_addr2str(nh->rtnh_gateway,
  115. buf, sizeof(buf)));
  116. if(nh->ce_mask & NH_ATTR_IFINDEX) {
  117. if (link_cache) {
  118. nl_dump(dp, " dev %s",
  119. rtnl_link_i2name(link_cache,
  120. nh->rtnh_ifindex,
  121. buf, sizeof(buf)));
  122. } else
  123. nl_dump(dp, " dev %d", nh->rtnh_ifindex);
  124. }
  125. if (nh->ce_mask & NH_ATTR_WEIGHT)
  126. nl_dump(dp, " weight %u", nh->rtnh_weight);
  127. if (nh->ce_mask & NH_ATTR_REALMS)
  128. nl_dump(dp, " realm %04x:%04x",
  129. RTNL_REALM_FROM(nh->rtnh_realms),
  130. RTNL_REALM_TO(nh->rtnh_realms));
  131. if (nh->ce_mask & NH_ATTR_FLAGS)
  132. nl_dump(dp, " <%s>", rtnl_route_nh_flags2str(nh->rtnh_flags,
  133. buf, sizeof(buf)));
  134. if (link_cache)
  135. nl_cache_put(link_cache);
  136. }
  137. void rtnl_route_nh_dump(struct rtnl_nexthop *nh, struct nl_dump_params *dp)
  138. {
  139. switch (dp->dp_type) {
  140. case NL_DUMP_LINE:
  141. nh_dump_line(nh, dp);
  142. break;
  143. case NL_DUMP_DETAILS:
  144. case NL_DUMP_STATS:
  145. if (dp->dp_ivar == NH_DUMP_FROM_DETAILS)
  146. nh_dump_details(nh, dp);
  147. break;
  148. default:
  149. break;
  150. }
  151. }
  152. /**
  153. * @name Attributes
  154. * @{
  155. */
  156. void rtnl_route_nh_set_weight(struct rtnl_nexthop *nh, uint8_t weight)
  157. {
  158. nh->rtnh_weight = weight;
  159. nh->ce_mask |= NH_ATTR_WEIGHT;
  160. }
  161. uint8_t rtnl_route_nh_get_weight(struct rtnl_nexthop *nh)
  162. {
  163. return nh->rtnh_weight;
  164. }
  165. void rtnl_route_nh_set_ifindex(struct rtnl_nexthop *nh, int ifindex)
  166. {
  167. nh->rtnh_ifindex = ifindex;
  168. nh->ce_mask |= NH_ATTR_IFINDEX;
  169. }
  170. int rtnl_route_nh_get_ifindex(struct rtnl_nexthop *nh)
  171. {
  172. return nh->rtnh_ifindex;
  173. }
  174. /* FIXME: Convert to return an int */
  175. void rtnl_route_nh_set_gateway(struct rtnl_nexthop *nh, struct nl_addr *addr)
  176. {
  177. struct nl_addr *old = nh->rtnh_gateway;
  178. if (addr) {
  179. nh->rtnh_gateway = nl_addr_get(addr);
  180. nh->ce_mask |= NH_ATTR_GATEWAY;
  181. } else {
  182. nh->ce_mask &= ~NH_ATTR_GATEWAY;
  183. nh->rtnh_gateway = NULL;
  184. }
  185. if (old)
  186. nl_addr_put(old);
  187. }
  188. struct nl_addr *rtnl_route_nh_get_gateway(struct rtnl_nexthop *nh)
  189. {
  190. return nh->rtnh_gateway;
  191. }
  192. void rtnl_route_nh_set_flags(struct rtnl_nexthop *nh, unsigned int flags)
  193. {
  194. nh->rtnh_flag_mask |= flags;
  195. nh->rtnh_flags |= flags;
  196. nh->ce_mask |= NH_ATTR_FLAGS;
  197. }
  198. void rtnl_route_nh_unset_flags(struct rtnl_nexthop *nh, unsigned int flags)
  199. {
  200. nh->rtnh_flag_mask |= flags;
  201. nh->rtnh_flags &= ~flags;
  202. nh->ce_mask |= NH_ATTR_FLAGS;
  203. }
  204. unsigned int rtnl_route_nh_get_flags(struct rtnl_nexthop *nh)
  205. {
  206. return nh->rtnh_flags;
  207. }
  208. void rtnl_route_nh_set_realms(struct rtnl_nexthop *nh, uint32_t realms)
  209. {
  210. nh->rtnh_realms = realms;
  211. nh->ce_mask |= NH_ATTR_REALMS;
  212. }
  213. uint32_t rtnl_route_nh_get_realms(struct rtnl_nexthop *nh)
  214. {
  215. return nh->rtnh_realms;
  216. }
  217. /** @} */
  218. /**
  219. * @name Nexthop Flags Translations
  220. * @{
  221. */
  222. static const struct trans_tbl nh_flags[] = {
  223. __ADD(RTNH_F_DEAD, dead)
  224. __ADD(RTNH_F_PERVASIVE, pervasive)
  225. __ADD(RTNH_F_ONLINK, onlink)
  226. };
  227. char *rtnl_route_nh_flags2str(int flags, char *buf, size_t len)
  228. {
  229. return __flags2str(flags, buf, len, nh_flags, ARRAY_SIZE(nh_flags));
  230. }
  231. int rtnl_route_nh_str2flags(const char *name)
  232. {
  233. return __str2flags(name, nh_flags, ARRAY_SIZE(nh_flags));
  234. }
  235. /** @} */
  236. /** @} */