Line data Source code
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 :
11 : #include "utils/includes.h"
12 :
13 : #include "utils/common.h"
14 : #include "hostapd.h"
15 : #include "ap_config.h"
16 : #include "ap_drv_ops.h"
17 : #include "wpa_auth.h"
18 : #include "vlan_init.h"
19 : #include "vlan_util.h"
20 :
21 :
22 51 : static int vlan_if_add(struct hostapd_data *hapd, struct hostapd_vlan *vlan,
23 : int existsok)
24 : {
25 : int ret, i;
26 :
27 510 : for (i = 0; i < NUM_WEP_KEYS; i++) {
28 204 : if (!hapd->conf->ssid.wep.key[i])
29 204 : continue;
30 0 : wpa_printf(MSG_ERROR,
31 : "VLAN: Refusing to set up VLAN iface %s with WEP",
32 0 : vlan->ifname);
33 0 : return -1;
34 : }
35 :
36 51 : if (!iface_exists(vlan->ifname))
37 51 : ret = hostapd_vlan_if_add(hapd, vlan->ifname);
38 0 : else if (!existsok)
39 0 : return -1;
40 : else
41 0 : ret = 0;
42 :
43 51 : if (ret)
44 0 : return ret;
45 :
46 51 : ifconfig_up(vlan->ifname); /* else wpa group will fail fatal */
47 :
48 51 : if (hapd->wpa_auth)
49 43 : ret = wpa_auth_ensure_group(hapd->wpa_auth, vlan->vlan_id);
50 :
51 51 : if (ret == 0)
52 51 : return ret;
53 :
54 0 : wpa_printf(MSG_ERROR, "WPA initialization for VLAN %d failed (%d)",
55 : vlan->vlan_id, ret);
56 0 : if (wpa_auth_release_group(hapd->wpa_auth, vlan->vlan_id))
57 0 : wpa_printf(MSG_ERROR, "WPA deinit of %s failed", vlan->ifname);
58 :
59 : /* group state machine setup failed */
60 0 : if (hostapd_vlan_if_remove(hapd, vlan->ifname))
61 0 : wpa_printf(MSG_ERROR, "Removal of %s failed", vlan->ifname);
62 :
63 0 : return ret;
64 : }
65 :
66 :
67 51 : int vlan_if_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan)
68 : {
69 : int ret;
70 :
71 51 : ret = wpa_auth_release_group(hapd->wpa_auth, vlan->vlan_id);
72 51 : if (ret)
73 0 : wpa_printf(MSG_ERROR,
74 : "WPA deinitialization for VLAN %d failed (%d)",
75 : vlan->vlan_id, ret);
76 :
77 51 : return hostapd_vlan_if_remove(hapd, vlan->ifname);
78 : }
79 :
80 :
81 2024 : static int vlan_dynamic_add(struct hostapd_data *hapd,
82 : struct hostapd_vlan *vlan)
83 : {
84 4084 : while (vlan) {
85 36 : if (vlan->vlan_id != VLAN_ID_WILDCARD) {
86 6 : if (vlan_if_add(hapd, vlan, 1)) {
87 0 : wpa_printf(MSG_ERROR,
88 : "VLAN: Could not add VLAN %s: %s",
89 0 : vlan->ifname, strerror(errno));
90 0 : return -1;
91 : }
92 : #ifdef CONFIG_FULL_DYNAMIC_VLAN
93 6 : vlan_newlink(vlan->ifname, hapd);
94 : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
95 : }
96 :
97 36 : vlan = vlan->next;
98 : }
99 :
100 2024 : return 0;
101 : }
102 :
103 :
104 2046 : static void vlan_dynamic_remove(struct hostapd_data *hapd,
105 : struct hostapd_vlan *vlan)
106 : {
107 : struct hostapd_vlan *next;
108 :
109 4128 : while (vlan) {
110 36 : next = vlan->next;
111 :
112 : #ifdef CONFIG_FULL_DYNAMIC_VLAN
113 : /* vlan_dellink() takes care of cleanup and interface removal */
114 36 : if (vlan->vlan_id != VLAN_ID_WILDCARD)
115 6 : 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 "
120 : "iface: %s: %s",
121 : vlan->ifname, strerror(errno));
122 : }
123 : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
124 :
125 36 : vlan = next;
126 : }
127 2046 : }
128 :
129 :
130 2024 : int vlan_init(struct hostapd_data *hapd)
131 : {
132 : #ifdef CONFIG_FULL_DYNAMIC_VLAN
133 2024 : hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
134 : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
135 :
136 4021 : if ((hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED ||
137 2027 : hapd->conf->ssid.per_sta_vif) &&
138 30 : !hapd->conf->vlan) {
139 : /* dynamic vlans enabled but no (or empty) vlan_file given */
140 : struct hostapd_vlan *vlan;
141 24 : vlan = os_zalloc(sizeof(*vlan));
142 24 : if (vlan == NULL) {
143 0 : wpa_printf(MSG_ERROR, "Out of memory while assigning "
144 : "VLAN interfaces");
145 0 : return -1;
146 : }
147 :
148 24 : vlan->vlan_id = VLAN_ID_WILDCARD;
149 24 : os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
150 24 : hapd->conf->iface);
151 24 : vlan->next = hapd->conf->vlan;
152 24 : hapd->conf->vlan = vlan;
153 : }
154 :
155 2024 : if (vlan_dynamic_add(hapd, hapd->conf->vlan))
156 0 : return -1;
157 :
158 2024 : return 0;
159 : }
160 :
161 :
162 2046 : void vlan_deinit(struct hostapd_data *hapd)
163 : {
164 2046 : vlan_dynamic_remove(hapd, hapd->conf->vlan);
165 :
166 : #ifdef CONFIG_FULL_DYNAMIC_VLAN
167 2046 : full_dynamic_vlan_deinit(hapd->full_dynamic_vlan);
168 2046 : hapd->full_dynamic_vlan = NULL;
169 : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
170 2046 : }
171 :
172 :
173 45 : struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
174 : struct hostapd_vlan *vlan,
175 : int vlan_id,
176 : struct vlan_description *vlan_desc)
177 : {
178 : struct hostapd_vlan *n;
179 : char ifname[IFNAMSIZ + 1], *pos;
180 :
181 45 : if (vlan == NULL || vlan->vlan_id != VLAN_ID_WILDCARD)
182 0 : return NULL;
183 :
184 45 : wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
185 45 : __func__, vlan_id, vlan->ifname);
186 45 : os_strlcpy(ifname, vlan->ifname, sizeof(ifname));
187 45 : pos = os_strchr(ifname, '#');
188 45 : if (pos == NULL)
189 0 : return NULL;
190 45 : *pos++ = '\0';
191 :
192 45 : n = os_zalloc(sizeof(*n));
193 45 : if (n == NULL)
194 0 : return NULL;
195 :
196 45 : n->vlan_id = vlan_id;
197 45 : if (vlan_desc)
198 41 : n->vlan_desc = *vlan_desc;
199 45 : n->dynamic_vlan = 1;
200 :
201 45 : os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
202 : pos);
203 :
204 45 : n->next = hapd->conf->vlan;
205 45 : hapd->conf->vlan = n;
206 :
207 : /* hapd->conf->vlan needs this new VLAN here for WPA setup */
208 45 : if (vlan_if_add(hapd, n, 0)) {
209 0 : hapd->conf->vlan = n->next;
210 0 : os_free(n);
211 0 : n = NULL;
212 : }
213 :
214 45 : return n;
215 : }
216 :
217 :
218 96 : int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
219 : {
220 : struct hostapd_vlan *vlan;
221 :
222 96 : if (vlan_id <= 0)
223 0 : return 1;
224 :
225 96 : wpa_printf(MSG_DEBUG, "VLAN: %s(ifname=%s vlan_id=%d)",
226 96 : __func__, hapd->conf->iface, vlan_id);
227 :
228 96 : vlan = hapd->conf->vlan;
229 244 : while (vlan) {
230 139 : if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) {
231 87 : vlan->dynamic_vlan--;
232 87 : break;
233 : }
234 52 : vlan = vlan->next;
235 : }
236 :
237 96 : if (vlan == NULL)
238 9 : return 1;
239 :
240 87 : if (vlan->dynamic_vlan == 0) {
241 45 : vlan_if_remove(hapd, vlan);
242 : #ifdef CONFIG_FULL_DYNAMIC_VLAN
243 45 : vlan_dellink(vlan->ifname, hapd);
244 : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
245 : }
246 :
247 87 : return 0;
248 : }
|