route.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * lib/route/route.c Routes
  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 rtnl
  13. * @defgroup route Routing
  14. * @brief
  15. * @{
  16. */
  17. #include <netlink-private/netlink.h>
  18. #include <netlink/netlink.h>
  19. #include <netlink/cache.h>
  20. #include <netlink/utils.h>
  21. #include <netlink/data.h>
  22. #include <netlink/route/rtnl.h>
  23. #include <netlink/route/route.h>
  24. #include <netlink/route/link.h>
  25. static struct nl_cache_ops rtnl_route_ops;
  26. static int route_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
  27. struct nlmsghdr *nlh, struct nl_parser_param *pp)
  28. {
  29. struct rtnl_route *route;
  30. int err;
  31. if ((err = rtnl_route_parse(nlh, &route)) < 0)
  32. return err;
  33. err = pp->pp_cb((struct nl_object *) route, pp);
  34. rtnl_route_put(route);
  35. return err;
  36. }
  37. static int route_request_update(struct nl_cache *c, struct nl_sock *h)
  38. {
  39. struct rtmsg rhdr = {
  40. .rtm_family = c->c_iarg1,
  41. };
  42. if (c->c_iarg2 & ROUTE_CACHE_CONTENT)
  43. rhdr.rtm_flags |= RTM_F_CLONED;
  44. return nl_send_simple(h, RTM_GETROUTE, NLM_F_DUMP, &rhdr, sizeof(rhdr));
  45. }
  46. /**
  47. * @name Cache Management
  48. * @{
  49. */
  50. /**
  51. * Build a route cache holding all routes currently configured in the kernel
  52. * @arg sk Netlink socket.
  53. * @arg family Address family of routes to cover or AF_UNSPEC
  54. * @arg flags Flags
  55. * @arg result Result pointer
  56. *
  57. * Allocates a new cache, initializes it properly and updates it to
  58. * contain all routes currently configured in the kernel.
  59. *
  60. * Valid flags:
  61. * * ROUTE_CACHE_CONTENT - Cache will contain contents of routing cache
  62. * instead of actual routes.
  63. *
  64. * @note The caller is responsible for destroying and freeing the
  65. * cache after using it.
  66. * @return 0 on success or a negative error code.
  67. */
  68. int rtnl_route_alloc_cache(struct nl_sock *sk, int family, int flags,
  69. struct nl_cache **result)
  70. {
  71. struct nl_cache *cache;
  72. int err;
  73. if (!(cache = nl_cache_alloc(&rtnl_route_ops)))
  74. return -NLE_NOMEM;
  75. cache->c_iarg1 = family;
  76. cache->c_iarg2 = flags;
  77. if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
  78. free(cache);
  79. return err;
  80. }
  81. *result = cache;
  82. return 0;
  83. }
  84. /** @} */
  85. /**
  86. * @name Route Addition
  87. * @{
  88. */
  89. static int build_route_msg(struct rtnl_route *tmpl, int cmd, int flags,
  90. struct nl_msg **result)
  91. {
  92. struct nl_msg *msg;
  93. int err;
  94. if (!(msg = nlmsg_alloc_simple(cmd, flags)))
  95. return -NLE_NOMEM;
  96. if ((err = rtnl_route_build_msg(msg, tmpl)) < 0) {
  97. nlmsg_free(msg);
  98. return err;
  99. }
  100. *result = msg;
  101. return 0;
  102. }
  103. int rtnl_route_build_add_request(struct rtnl_route *tmpl, int flags,
  104. struct nl_msg **result)
  105. {
  106. return build_route_msg(tmpl, RTM_NEWROUTE, NLM_F_CREATE | flags,
  107. result);
  108. }
  109. int rtnl_route_add(struct nl_sock *sk, struct rtnl_route *route, int flags)
  110. {
  111. struct nl_msg *msg;
  112. int err;
  113. if ((err = rtnl_route_build_add_request(route, flags, &msg)) < 0)
  114. return err;
  115. err = nl_send_auto_complete(sk, msg);
  116. nlmsg_free(msg);
  117. if (err < 0)
  118. return err;
  119. return wait_for_ack(sk);
  120. }
  121. int rtnl_route_build_del_request(struct rtnl_route *tmpl, int flags,
  122. struct nl_msg **result)
  123. {
  124. return build_route_msg(tmpl, RTM_DELROUTE, flags, result);
  125. }
  126. int rtnl_route_delete(struct nl_sock *sk, struct rtnl_route *route, int flags)
  127. {
  128. struct nl_msg *msg;
  129. int err;
  130. if ((err = rtnl_route_build_del_request(route, flags, &msg)) < 0)
  131. return err;
  132. err = nl_send_auto_complete(sk, msg);
  133. nlmsg_free(msg);
  134. if (err < 0)
  135. return err;
  136. return wait_for_ack(sk);
  137. }
  138. /** @} */
  139. static struct nl_af_group route_groups[] = {
  140. { AF_INET, RTNLGRP_IPV4_ROUTE },
  141. { AF_INET6, RTNLGRP_IPV6_ROUTE },
  142. { AF_DECnet, RTNLGRP_DECnet_ROUTE },
  143. { END_OF_GROUP_LIST },
  144. };
  145. static struct nl_cache_ops rtnl_route_ops = {
  146. .co_name = "route/route",
  147. .co_hdrsize = sizeof(struct rtmsg),
  148. .co_msgtypes = {
  149. { RTM_NEWROUTE, NL_ACT_NEW, "new" },
  150. { RTM_DELROUTE, NL_ACT_DEL, "del" },
  151. { RTM_GETROUTE, NL_ACT_GET, "get" },
  152. END_OF_MSGTYPES_LIST,
  153. },
  154. .co_protocol = NETLINK_ROUTE,
  155. .co_groups = route_groups,
  156. .co_request_update = route_request_update,
  157. .co_msg_parser = route_msg_parser,
  158. .co_obj_ops = &route_obj_ops,
  159. };
  160. static void __init route_init(void)
  161. {
  162. nl_cache_mngt_register(&rtnl_route_ops);
  163. }
  164. static void __exit route_exit(void)
  165. {
  166. nl_cache_mngt_unregister(&rtnl_route_ops);
  167. }
  168. /** @} */