vlan_util.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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 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. if (nl_connect(handle, NETLINK_ROUTE) < 0) {
  54. wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink");
  55. goto vlan_add_error;
  56. }
  57. if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) {
  58. cache = NULL;
  59. wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache");
  60. goto vlan_add_error;
  61. }
  62. if (!(if_idx = rtnl_link_name2i(cache, if_name))) {
  63. /* link does not exist */
  64. wpa_printf(MSG_ERROR, "VLAN: interface %s does not exist",
  65. if_name);
  66. goto vlan_add_error;
  67. }
  68. if ((rlink = rtnl_link_get_by_name(cache, vlan_if_name))) {
  69. /* link does exist */
  70. rtnl_link_put(rlink);
  71. rlink = NULL;
  72. wpa_printf(MSG_ERROR, "VLAN: interface %s already exists",
  73. vlan_if_name);
  74. ret = 1;
  75. goto vlan_add_error;
  76. }
  77. rlink = rtnl_link_alloc();
  78. if (!rlink) {
  79. wpa_printf(MSG_ERROR, "VLAN: failed to allocate new link");
  80. goto vlan_add_error;
  81. }
  82. if (rtnl_link_set_type(rlink, "vlan") < 0) {
  83. wpa_printf(MSG_ERROR, "VLAN: failed to set link type");
  84. goto vlan_add_error;
  85. }
  86. rtnl_link_set_link(rlink, if_idx);
  87. rtnl_link_set_name(rlink, vlan_if_name);
  88. if (rtnl_link_vlan_set_id(rlink, vid) < 0) {
  89. wpa_printf(MSG_ERROR, "VLAN: failed to set link vlan id");
  90. goto vlan_add_error;
  91. }
  92. if (rtnl_link_add(handle, rlink, NLM_F_CREATE) < 0) {
  93. wpa_printf(MSG_ERROR, "VLAN: failed to create link %s for "
  94. "vlan %d on %s (%d)",
  95. vlan_if_name, vid, if_name, if_idx);
  96. goto vlan_add_error;
  97. }
  98. ret = 0;
  99. vlan_add_error:
  100. if (rlink)
  101. rtnl_link_put(rlink);
  102. if (cache)
  103. nl_cache_free(cache);
  104. if (handle)
  105. nl_socket_free(handle);
  106. return ret;
  107. }
  108. int vlan_rem(const char *if_name)
  109. {
  110. int ret = -1;
  111. struct nl_sock *handle = NULL;
  112. struct nl_cache *cache = NULL;
  113. struct rtnl_link *rlink = NULL;
  114. wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(if_name=%s)", if_name);
  115. handle = nl_socket_alloc();
  116. if (!handle) {
  117. wpa_printf(MSG_ERROR, "VLAN: failed to open netlink socket");
  118. goto vlan_rem_error;
  119. }
  120. if (nl_connect(handle, NETLINK_ROUTE) < 0) {
  121. wpa_printf(MSG_ERROR, "VLAN: failed to connect to netlink");
  122. goto vlan_rem_error;
  123. }
  124. if (rtnl_link_alloc_cache(handle, AF_UNSPEC, &cache) < 0) {
  125. cache = NULL;
  126. wpa_printf(MSG_ERROR, "VLAN: failed to alloc cache");
  127. goto vlan_rem_error;
  128. }
  129. if (!(rlink = rtnl_link_get_by_name(cache, if_name))) {
  130. /* link does not exist */
  131. wpa_printf(MSG_ERROR, "VLAN: interface %s does not exists",
  132. if_name);
  133. goto vlan_rem_error;
  134. }
  135. if (rtnl_link_delete(handle, rlink) < 0) {
  136. wpa_printf(MSG_ERROR, "VLAN: failed to remove link %s",
  137. if_name);
  138. goto vlan_rem_error;
  139. }
  140. ret = 0;
  141. vlan_rem_error:
  142. if (rlink)
  143. rtnl_link_put(rlink);
  144. if (cache)
  145. nl_cache_free(cache);
  146. if (handle)
  147. nl_socket_free(handle);
  148. return ret;
  149. }