vlan_init.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * hostapd / VLAN initialization
  3. * Copyright 2003, Instant802 Networks, Inc.
  4. * Copyright 2005-2006, Devicescape Software, Inc.
  5. * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
  6. *
  7. * This software may be distributed under the terms of the BSD license.
  8. * See README for more details.
  9. */
  10. #include "utils/includes.h"
  11. #include "utils/common.h"
  12. #include "hostapd.h"
  13. #include "ap_config.h"
  14. #include "ap_drv_ops.h"
  15. #include "wpa_auth.h"
  16. #include "vlan_init.h"
  17. #include "vlan_util.h"
  18. static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
  19. int existsok)
  20. {
  21. int ret, i;
  22. for (i = 0; i < NUM_WEP_KEYS; i++) {
  23. if (!hapd->conf->ssid.wep.key[i])
  24. continue;
  25. wpa_printf(MSG_ERROR,
  26. "VLAN: Refusing to set up VLAN iface %s with WEP",
  27. vlan->ifname);
  28. return -1;
  29. }
  30. if (!iface_exists(vlan->ifname))
  31. ret = hostapd_vlan_if_add(hapd, vlan->ifname);
  32. else if (!existsok)
  33. return -1;
  34. else
  35. ret = 0;
  36. if (ret)
  37. return ret;
  38. ifconfig_up(vlan->ifname); /* else wpa group will fail fatal */
  39. if (hapd->wpa_auth)
  40. ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
  41. if (ret == 0)
  42. return ret;
  43. wpa_printf(MSG_ERROR, "WPA initialization for VLAN %d failed (%d)",
  44. vlan->vlan_id, ret);
  45. if (wpa_auth_release_group(hapd->wpa_auth, vlan->vlan_id))
  46. wpa_printf(MSG_ERROR, "WPA deinit of %s failed", vlan->ifname);
  47. /* group state machine setup failed */
  48. if (hostapd_vlan_if_remove(hapd, vlan->ifname))
  49. wpa_printf(MSG_ERROR, "Removal of %s failed", vlan->ifname);
  50. return ret;
  51. }
  52. int vlan_if_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
  53. {
  54. int ret;
  55. ret = wpa_auth_release_group(hapd->wpa_auth, vlan->vlan_id);
  56. if (ret)
  57. wpa_printf(MSG_ERROR,
  58. "WPA deinitialization for VLAN %d failed (%d)",
  59. vlan->vlan_id, ret);
  60. return hostapd_vlan_if_remove(hapd, vlan->ifname);
  61. }
  62. static int vlan_dynamic_add(struct hostapd_data *hapd,
  63. struct hostapd_vlan *vlan)
  64. {
  65. while (vlan) {
  66. if (vlan->vlan_id != VLAN_ID_WILDCARD) {
  67. if (vlan_if_add(hapd, vlan, 1)) {
  68. wpa_printf(MSG_ERROR,
  69. "VLAN: Could not add VLAN %s: %s",
  70. vlan->ifname, strerror(errno));
  71. return -1;
  72. }
  73. #ifdef CONFIG_FULL_DYNAMIC_VLAN
  74. vlan_newlink(vlan->ifname, hapd);
  75. #endif /* CONFIG_FULL_DYNAMIC_VLAN */
  76. }
  77. vlan = vlan->next;
  78. }
  79. return 0;
  80. }
  81. static void vlan_dynamic_remove(struct hostapd_data *hapd,
  82. struct hostapd_vlan *vlan)
  83. {
  84. struct hostapd_vlan *next;
  85. while (vlan) {
  86. next = vlan->next;
  87. #ifdef CONFIG_FULL_DYNAMIC_VLAN
  88. /* vlan_dellink() takes care of cleanup and interface removal */
  89. if (vlan->vlan_id != VLAN_ID_WILDCARD)
  90. vlan_dellink(vlan->ifname, hapd);
  91. #else /* CONFIG_FULL_DYNAMIC_VLAN */
  92. if (vlan->vlan_id != VLAN_ID_WILDCARD &&
  93. vlan_if_remove(hapd, vlan)) {
  94. wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
  95. "iface: %s: %s",
  96. vlan->ifname, strerror(errno));
  97. }
  98. #endif /* CONFIG_FULL_DYNAMIC_VLAN */
  99. vlan = next;
  100. }
  101. }
  102. int vlan_init(struct hostapd_data *hapd)
  103. {
  104. #ifdef CONFIG_FULL_DYNAMIC_VLAN
  105. hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
  106. #endif /* CONFIG_FULL_DYNAMIC_VLAN */
  107. if ((hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED ||
  108. hapd->conf->ssid.per_sta_vif) &&
  109. !hapd->conf->vlan) {
  110. /* dynamic vlans enabled but no (or empty) vlan_file given */
  111. struct hostapd_vlan *vlan;
  112. vlan = os_zalloc(sizeof(*vlan));
  113. if (vlan == NULL) {
  114. wpa_printf(MSG_ERROR, "Out of memory while assigning "
  115. "VLAN interfaces");
  116. return -1;
  117. }
  118. vlan->vlan_id = VLAN_ID_WILDCARD;
  119. os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
  120. hapd->conf->iface);
  121. vlan->next = hapd->conf->vlan;
  122. hapd->conf->vlan = vlan;
  123. }
  124. if (vlan_dynamic_add(hapd, hapd->conf->vlan))
  125. return -1;
  126. return 0;
  127. }
  128. void vlan_deinit(struct hostapd_data *hapd)
  129. {
  130. vlan_dynamic_remove(hapd, hapd->conf->vlan);
  131. #ifdef CONFIG_FULL_DYNAMIC_VLAN
  132. full_dynamic_vlan_deinit(hapd->full_dynamic_vlan);
  133. hapd->full_dynamic_vlan = NULL;
  134. #endif /* CONFIG_FULL_DYNAMIC_VLAN */
  135. }
  136. struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
  137. struct hostapd_vlan *vlan,
  138. int vlan_id,
  139. struct vlan_description *vlan_desc)
  140. {
  141. struct hostapd_vlan *n;
  142. char ifname[IFNAMSIZ + 1], *pos;
  143. if (vlan == NULL || vlan->vlan_id != VLAN_ID_WILDCARD)
  144. return NULL;
  145. wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
  146. __func__, vlan_id, vlan->ifname);
  147. os_strlcpy(ifname, vlan->ifname, sizeof(ifname));
  148. pos = os_strchr(ifname, '#');
  149. if (pos == NULL)
  150. return NULL;
  151. *pos++ = '\0';
  152. n = os_zalloc(sizeof(*n));
  153. if (n == NULL)
  154. return NULL;
  155. n->vlan_id = vlan_id;
  156. if (vlan_desc)
  157. n->vlan_desc = *vlan_desc;
  158. n->dynamic_vlan = 1;
  159. os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
  160. pos);
  161. n->next = hapd->conf->vlan;
  162. hapd->conf->vlan = n;
  163. /* hapd->conf->vlan needs this new VLAN here for WPA setup */
  164. if (vlan_if_add(hapd, n, 0)) {
  165. hapd->conf->vlan = n->next;
  166. os_free(n);
  167. n = NULL;
  168. }
  169. return n;
  170. }
  171. int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
  172. {
  173. struct hostapd_vlan *vlan;
  174. if (vlan_id <= 0)
  175. return 1;
  176. wpa_printf(MSG_DEBUG, "VLAN: %s(ifname=%s vlan_id=%d)",
  177. __func__, hapd->conf->iface, vlan_id);
  178. vlan = hapd->conf->vlan;
  179. while (vlan) {
  180. if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) {
  181. vlan->dynamic_vlan--;
  182. break;
  183. }
  184. vlan = vlan->next;
  185. }
  186. if (vlan == NULL)
  187. return 1;
  188. if (vlan->dynamic_vlan == 0) {
  189. vlan_if_remove(hapd, vlan);
  190. #ifdef CONFIG_FULL_DYNAMIC_VLAN
  191. vlan_dellink(vlan->ifname, hapd);
  192. #endif /* CONFIG_FULL_DYNAMIC_VLAN */
  193. }
  194. return 0;
  195. }