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>
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
11 #include "utils/includes.h"
13 #include "utils/common.h"
15 #include "ap_config.h"
16 #include "ap_drv_ops.h"
18 #include "vlan_init.h"
19 #include "vlan_util.h"
22 static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
27 for (i = 0; i < NUM_WEP_KEYS; i++) {
28 if (!hapd->conf->ssid.wep.key[i])
31 "VLAN: Refusing to set up VLAN iface %s with WEP",
36 if (!iface_exists(vlan->ifname))
37 ret = hostapd_vlan_if_add(hapd, vlan->ifname);
46 ifconfig_up(vlan->ifname); /* else wpa group will fail fatal */
49 ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
54 wpa_printf(MSG_ERROR, "WPA initialization for VLAN %d failed (%d)",
56 if (wpa_auth_release_group(hapd->wpa_auth, vlan->vlan_id))
57 wpa_printf(MSG_ERROR, "WPA deinit of %s failed", vlan->ifname);
59 /* group state machine setup failed */
60 if (hostapd_vlan_if_remove(hapd, vlan->ifname))
61 wpa_printf(MSG_ERROR, "Removal of %s failed", vlan->ifname);
67 int vlan_if_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
71 ret = wpa_auth_release_group(hapd->wpa_auth, vlan->vlan_id);
74 "WPA deinitialization for VLAN %d failed (%d)",
77 return hostapd_vlan_if_remove(hapd, vlan->ifname);
81 static int vlan_dynamic_add(struct hostapd_data *hapd,
82 struct hostapd_vlan *vlan)
85 if (vlan->vlan_id != VLAN_ID_WILDCARD) {
86 if (vlan_if_add(hapd, vlan, 1)) {
88 "VLAN: Could not add VLAN %s: %s",
89 vlan->ifname, strerror(errno));
92 #ifdef CONFIG_FULL_DYNAMIC_VLAN
93 vlan_newlink(vlan->ifname, hapd);
94 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
104 static void vlan_dynamic_remove(struct hostapd_data *hapd,
105 struct hostapd_vlan *vlan)
107 struct hostapd_vlan *next;
112 #ifdef CONFIG_FULL_DYNAMIC_VLAN
113 /* vlan_dellink() takes care of cleanup and interface removal */
114 if (vlan->vlan_id != VLAN_ID_WILDCARD)
115 vlan_dellink(vlan->ifname, hapd);
116 #else /* CONFIG_FULL_DYNAMIC_VLAN */
117 if (vlan->vlan_id != VLAN_ID_WILDCARD &&
118 vlan_if_remove(hapd, vlan)) {
119 wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
121 vlan->ifname, strerror(errno));
123 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
130 int vlan_init(struct hostapd_data *hapd)
132 #ifdef CONFIG_FULL_DYNAMIC_VLAN
133 hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
134 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
136 if ((hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED ||
137 hapd->conf->ssid.per_sta_vif) &&
139 /* dynamic vlans enabled but no (or empty) vlan_file given */
140 struct hostapd_vlan *vlan;
143 vlan = os_zalloc(sizeof(*vlan));
145 wpa_printf(MSG_ERROR, "Out of memory while assigning "
150 vlan->vlan_id = VLAN_ID_WILDCARD;
151 ret = os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
153 if (ret >= (int) sizeof(vlan->ifname)) {
154 wpa_printf(MSG_WARNING,
155 "VLAN: Interface name was truncated to %s",
157 } else if (ret < 0) {
161 vlan->next = hapd->conf->vlan;
162 hapd->conf->vlan = vlan;
165 if (vlan_dynamic_add(hapd, hapd->conf->vlan))
172 void vlan_deinit(struct hostapd_data *hapd)
174 vlan_dynamic_remove(hapd, hapd->conf->vlan);
176 #ifdef CONFIG_FULL_DYNAMIC_VLAN
177 full_dynamic_vlan_deinit(hapd->full_dynamic_vlan);
178 hapd->full_dynamic_vlan = NULL;
179 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
183 struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
184 struct hostapd_vlan *vlan,
186 struct vlan_description *vlan_desc)
188 struct hostapd_vlan *n;
189 char ifname[IFNAMSIZ + 1], *pos;
192 if (vlan == NULL || vlan->vlan_id != VLAN_ID_WILDCARD)
195 wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
196 __func__, vlan_id, vlan->ifname);
197 os_strlcpy(ifname, vlan->ifname, sizeof(ifname));
198 pos = os_strchr(ifname, '#');
203 n = os_zalloc(sizeof(*n));
207 n->vlan_id = vlan_id;
209 n->vlan_desc = *vlan_desc;
212 ret = os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s",
213 ifname, vlan_id, pos);
214 if (os_snprintf_error(sizeof(n->ifname), ret)) {
218 os_strlcpy(n->bridge, vlan->bridge, sizeof(n->bridge));
220 n->next = hapd->conf->vlan;
221 hapd->conf->vlan = n;
223 /* hapd->conf->vlan needs this new VLAN here for WPA setup */
224 if (vlan_if_add(hapd, n, 0)) {
225 hapd->conf->vlan = n->next;
234 int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
236 struct hostapd_vlan *vlan;
241 wpa_printf(MSG_DEBUG, "VLAN: %s(ifname=%s vlan_id=%d)",
242 __func__, hapd->conf->iface, vlan_id);
244 vlan = hapd->conf->vlan;
246 if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) {
247 vlan->dynamic_vlan--;
256 if (vlan->dynamic_vlan == 0) {
257 vlan_if_remove(hapd, vlan);
258 #ifdef CONFIG_FULL_DYNAMIC_VLAN
259 vlan_dellink(vlan->ifname, hapd);
260 #endif /* CONFIG_FULL_DYNAMIC_VLAN */