vlan_util.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * hostapd / VLAN netlink api
  3. * Copyright (c) 2012, Michael Braun <michael-dev@fami-braun.de>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "utils/includes.h"
  9. #include <sys/ioctl.h>
  10. #include <linux/sockios.h>
  11. #include <linux/if_vlan.h>
  12. #include <netlink/genl/genl.h>
  13. #include <netlink/genl/family.h>
  14. #include <netlink/genl/ctrl.h>
  15. #include <netlink/route/link.h>
  16. #include <netlink/route/link/vlan.h>
  17. #include "utils/common.h"
  18. #include "utils/eloop.h"
  19. #include "hostapd.h"
  20. #include "vlan_util.h"
  21. /*
  22. * Add a vlan interface with name 'vlan_if_name', VLAN ID 'vid' and
  23. * tagged interface 'if_name'.
  24. *
  25. * returns -1 on error
  26. * returns 1 if the interface already exists
  27. * returns 0 otherwise
  28. */
  29. int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
  30. {
  31. int err, ret = -1;
  32. struct nl_sock *handle = NULL;
  33. struct nl_cache *cache = NULL;
  34. struct rtnl_link *rlink = NULL;
  35. int if_idx = 0;
  36. wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d, "
  37. "vlan_if_name=%s)", if_name, vid, vlan_if_name);
  38. if ((os_strlen(if_name) + 1) > IFNAMSIZ) {
  39. wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
  40. if_name);
  41. return -1;
  42. }
  43. if ((os_strlen(vlan_if_name) + 1) > IFNAMSIZ) {
  44. wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
  45. vlan_if_name);
  46. return -1;
  47. }
  48. handle = nl_socket_alloc();
  49. if (!handle) {
  50. wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
  51. goto vlan_add_error;
  52. }
  53. err = nl_connect(handle, NETLINK_ROUTE);
  54. if (err < 0) {
  55. wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s",
  56. nl_geterror(err));
  57. goto vlan_add_error;
  58. }
  59. err = rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache);
  60. if (err < 0) {
  61. cache = NULL;
  62. wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache: %s",
  63. nl_geterror(err));
  64. goto vlan_add_error;
  65. }
  66. if (!(if_idx = rtnl_link_name2i(cache, if_name))) {
  67. /* link does not exist */
  68. wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist",
  69. if_name);
  70. goto vlan_add_error;
  71. }
  72. if ((rlink = rtnl_link_get_by_name(cache, vlan_if_name))) {
  73. /* link does exist */
  74. rtnl_link_put(rlink);
  75. rlink = NULL;
  76. wpa_printf(MSG_ERROR, "VLAN: interface %s already exists",
  77. vlan_if_name);
  78. ret = 1;
  79. goto vlan_add_error;
  80. }
  81. rlink = rtnl_link_alloc();
  82. if (!rlink) {
  83. wpa_printf(MSG_ERROR, "VLAN: failed to allocate new link");
  84. goto vlan_add_error;
  85. }
  86. err = rtnl_link_set_type(rlink, "vlan");
  87. if (err < 0) {
  88. wpa_printf(MSG_ERROR, "VLAN: failed to set link type: %s",
  89. nl_geterror(err));
  90. goto vlan_add_error;
  91. }
  92. rtnl_link_set_link(rlink, if_idx);
  93. rtnl_link_set_name(rlink, vlan_if_name);
  94. err = rtnl_link_vlan_set_id(rlink, vid);
  95. if (err < 0) {
  96. wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id: %s",
  97. nl_geterror(err));
  98. goto vlan_add_error;
  99. }
  100. err = rtnl_link_add(handle, rlink, NLM_F_CREATE);
  101. if (err < 0) {
  102. wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for "
  103. "vlan %d on %s (%d): %s",
  104. vlan_if_name, vid, if_name, if_idx,
  105. nl_geterror(err));
  106. goto vlan_add_error;
  107. }
  108. ret = 0;
  109. vlan_add_error:
  110. if (rlink)
  111. rtnl_link_put(rlink);
  112. if (cache)
  113. nl_cache_free(cache);
  114. if (handle)
  115. nl_socket_free(handle);
  116. return ret;
  117. }
  118. int vlan_rem(const char *if_name)
  119. {
  120. int err, ret = -1;
  121. struct nl_sock *handle = NULL;
  122. struct nl_cache *cache = NULL;
  123. struct rtnl_link *rlink = NULL;
  124. wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name);
  125. handle = nl_socket_alloc();
  126. if (!handle) {
  127. wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
  128. goto vlan_rem_error;
  129. }
  130. err = nl_connect(handle, NETLINK_ROUTE);
  131. if (err < 0) {
  132. wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink: %s",
  133. nl_geterror(err));
  134. goto vlan_rem_error;
  135. }
  136. err = rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache);
  137. if (err < 0) {
  138. cache = NULL;
  139. wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache: %s",
  140. nl_geterror(err));
  141. goto vlan_rem_error;
  142. }
  143. if (!(rlink = rtnl_link_get_by_name(cache, if_name))) {
  144. /* link does not exist */
  145. wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists",
  146. if_name);
  147. goto vlan_rem_error;
  148. }
  149. err = rtnl_link_delete(handle, rlink);
  150. if (err < 0) {
  151. wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s: %s",
  152. if_name, nl_geterror(err));
  153. goto vlan_rem_error;
  154. }
  155. ret = 0;
  156. vlan_rem_error:
  157. if (rlink)
  158. rtnl_link_put(rlink);
  159. if (cache)
  160. nl_cache_free(cache);
  161. if (handle)
  162. nl_socket_free(handle);
  163. return ret;
  164. }