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 "vlan_init.h"
18 : #include "vlan_util.h"
19 :
20 :
21 : #ifdef CONFIG_FULL_DYNAMIC_VLAN
22 :
23 : #include <net/if.h>
24 : #include <sys/ioctl.h>
25 : #include <linux/sockios.h>
26 : #include <linux/if_vlan.h>
27 : #include <linux/if_bridge.h>
28 :
29 : #include "drivers/priv_netlink.h"
30 : #include "utils/eloop.h"
31 :
32 :
33 : struct full_dynamic_vlan {
34 : int s; /* socket on which to listen for new/removed interfaces. */
35 : };
36 :
37 :
38 328 : static int ifconfig_helper(const char *if_name, int up)
39 : {
40 : int fd;
41 : struct ifreq ifr;
42 :
43 328 : if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
44 0 : wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
45 0 : "failed: %s", __func__, strerror(errno));
46 0 : return -1;
47 : }
48 :
49 328 : os_memset(&ifr, 0, sizeof(ifr));
50 328 : os_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ);
51 :
52 328 : if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) {
53 25 : wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCGIFFLAGS) failed "
54 : "for interface %s: %s",
55 25 : __func__, if_name, strerror(errno));
56 25 : close(fd);
57 25 : return -1;
58 : }
59 :
60 303 : if (up)
61 290 : ifr.ifr_flags |= IFF_UP;
62 : else
63 13 : ifr.ifr_flags &= ~IFF_UP;
64 :
65 303 : if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) {
66 0 : wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCSIFFLAGS) failed "
67 : "for interface %s (up=%d): %s",
68 0 : __func__, if_name, up, strerror(errno));
69 0 : close(fd);
70 0 : return -1;
71 : }
72 :
73 303 : close(fd);
74 303 : return 0;
75 : }
76 :
77 :
78 313 : static int ifconfig_up(const char *if_name)
79 : {
80 313 : wpa_printf(MSG_DEBUG, "VLAN: Set interface %s up", if_name);
81 313 : return ifconfig_helper(if_name, 1);
82 : }
83 :
84 :
85 15 : static int ifconfig_down(const char *if_name)
86 : {
87 15 : wpa_printf(MSG_DEBUG, "VLAN: Set interface %s down", if_name);
88 15 : return ifconfig_helper(if_name, 0);
89 : }
90 :
91 :
92 : /*
93 : * These are only available in recent linux headers (without the leading
94 : * underscore).
95 : */
96 : #define _GET_VLAN_REALDEV_NAME_CMD 8
97 : #define _GET_VLAN_VID_CMD 9
98 :
99 : /* This value should be 256 ONLY. If it is something else, then hostapd
100 : * might crash!, as this value has been hard-coded in 2.4.x kernel
101 : * bridging code.
102 : */
103 : #define MAX_BR_PORTS 256
104 :
105 13 : static int br_delif(const char *br_name, const char *if_name)
106 : {
107 : int fd;
108 : struct ifreq ifr;
109 : unsigned long args[2];
110 : int if_index;
111 :
112 13 : wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name);
113 13 : if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
114 0 : wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
115 0 : "failed: %s", __func__, strerror(errno));
116 0 : return -1;
117 : }
118 :
119 13 : if_index = if_nametoindex(if_name);
120 :
121 13 : if (if_index == 0) {
122 13 : wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
123 : "interface index for '%s'",
124 : __func__, if_name);
125 13 : close(fd);
126 13 : return -1;
127 : }
128 :
129 0 : args[0] = BRCTL_DEL_IF;
130 0 : args[1] = if_index;
131 :
132 0 : os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
133 0 : ifr.ifr_data = (__caddr_t) args;
134 :
135 0 : if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) {
136 : /* No error if interface already removed. */
137 0 : wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
138 : "BRCTL_DEL_IF] failed for br_name=%s if_name=%s: "
139 0 : "%s", __func__, br_name, if_name, strerror(errno));
140 0 : close(fd);
141 0 : return -1;
142 : }
143 :
144 0 : close(fd);
145 0 : return 0;
146 : }
147 :
148 :
149 : /*
150 : Add interface 'if_name' to the bridge 'br_name'
151 :
152 : returns -1 on error
153 : returns 1 if the interface is already part of the bridge
154 : returns 0 otherwise
155 : */
156 141 : static int br_addif(const char *br_name, const char *if_name)
157 : {
158 : int fd;
159 : struct ifreq ifr;
160 : unsigned long args[2];
161 : int if_index;
162 :
163 141 : wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name);
164 141 : if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
165 0 : wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
166 0 : "failed: %s", __func__, strerror(errno));
167 0 : return -1;
168 : }
169 :
170 141 : if_index = if_nametoindex(if_name);
171 :
172 141 : if (if_index == 0) {
173 23 : wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
174 : "interface index for '%s'",
175 : __func__, if_name);
176 23 : close(fd);
177 23 : return -1;
178 : }
179 :
180 118 : args[0] = BRCTL_ADD_IF;
181 118 : args[1] = if_index;
182 :
183 118 : os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
184 118 : ifr.ifr_data = (__caddr_t) args;
185 :
186 118 : if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
187 105 : if (errno == EBUSY) {
188 : /* The interface is already added. */
189 105 : close(fd);
190 105 : return 1;
191 : }
192 :
193 0 : wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
194 : "BRCTL_ADD_IF] failed for br_name=%s if_name=%s: "
195 0 : "%s", __func__, br_name, if_name, strerror(errno));
196 0 : close(fd);
197 0 : return -1;
198 : }
199 :
200 13 : close(fd);
201 13 : return 0;
202 : }
203 :
204 :
205 13 : static int br_delbr(const char *br_name)
206 : {
207 : int fd;
208 : unsigned long arg[2];
209 :
210 13 : wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name);
211 13 : if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
212 0 : wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
213 0 : "failed: %s", __func__, strerror(errno));
214 0 : return -1;
215 : }
216 :
217 13 : arg[0] = BRCTL_DEL_BRIDGE;
218 13 : arg[1] = (unsigned long) br_name;
219 :
220 13 : if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) {
221 : /* No error if bridge already removed. */
222 0 : wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for "
223 0 : "%s: %s", __func__, br_name, strerror(errno));
224 0 : close(fd);
225 0 : return -1;
226 : }
227 :
228 13 : close(fd);
229 13 : return 0;
230 : }
231 :
232 :
233 : /*
234 : Add a bridge with the name 'br_name'.
235 :
236 : returns -1 on error
237 : returns 1 if the bridge already exists
238 : returns 0 otherwise
239 : */
240 123 : static int br_addbr(const char *br_name)
241 : {
242 : int fd;
243 : unsigned long arg[4];
244 : struct ifreq ifr;
245 :
246 123 : wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name);
247 123 : if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
248 0 : wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
249 0 : "failed: %s", __func__, strerror(errno));
250 0 : return -1;
251 : }
252 :
253 123 : arg[0] = BRCTL_ADD_BRIDGE;
254 123 : arg[1] = (unsigned long) br_name;
255 :
256 123 : if (ioctl(fd, SIOCGIFBR, arg) < 0) {
257 110 : if (errno == EEXIST) {
258 : /* The bridge is already added. */
259 110 : close(fd);
260 110 : return 1;
261 : } else {
262 0 : wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE "
263 : "failed for %s: %s",
264 0 : __func__, br_name, strerror(errno));
265 0 : close(fd);
266 0 : return -1;
267 : }
268 : }
269 :
270 : /* Decrease forwarding delay to avoid EAPOL timeouts. */
271 13 : os_memset(&ifr, 0, sizeof(ifr));
272 13 : os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ);
273 13 : arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
274 13 : arg[1] = 1;
275 13 : arg[2] = 0;
276 13 : arg[3] = 0;
277 13 : ifr.ifr_data = (char *) &arg;
278 13 : if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
279 0 : wpa_printf(MSG_ERROR, "VLAN: %s: "
280 : "BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for "
281 0 : "%s: %s", __func__, br_name, strerror(errno));
282 : /* Continue anyway */
283 : }
284 :
285 13 : close(fd);
286 13 : return 0;
287 : }
288 :
289 :
290 13 : static int br_getnumports(const char *br_name)
291 : {
292 : int fd;
293 : int i;
294 13 : int port_cnt = 0;
295 : unsigned long arg[4];
296 : int ifindices[MAX_BR_PORTS];
297 : struct ifreq ifr;
298 :
299 13 : if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
300 0 : wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
301 0 : "failed: %s", __func__, strerror(errno));
302 0 : return -1;
303 : }
304 :
305 13 : arg[0] = BRCTL_GET_PORT_LIST;
306 13 : arg[1] = (unsigned long) ifindices;
307 13 : arg[2] = MAX_BR_PORTS;
308 13 : arg[3] = 0;
309 :
310 13 : os_memset(ifindices, 0, sizeof(ifindices));
311 13 : os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
312 13 : ifr.ifr_data = (__caddr_t) arg;
313 :
314 13 : if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
315 0 : wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST "
316 : "failed for %s: %s",
317 0 : __func__, br_name, strerror(errno));
318 0 : close(fd);
319 0 : return -1;
320 : }
321 :
322 3328 : for (i = 1; i < MAX_BR_PORTS; i++) {
323 3315 : if (ifindices[i] > 0) {
324 0 : port_cnt++;
325 : }
326 : }
327 :
328 13 : close(fd);
329 13 : return port_cnt;
330 : }
331 :
332 :
333 : #ifndef CONFIG_VLAN_NETLINK
334 :
335 0 : int vlan_rem(const char *if_name)
336 : {
337 : int fd;
338 : struct vlan_ioctl_args if_request;
339 :
340 0 : wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name);
341 0 : if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
342 0 : wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
343 : if_name);
344 0 : return -1;
345 : }
346 :
347 0 : if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
348 0 : wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
349 0 : "failed: %s", __func__, strerror(errno));
350 0 : return -1;
351 : }
352 :
353 0 : os_memset(&if_request, 0, sizeof(if_request));
354 :
355 0 : os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
356 0 : if_request.cmd = DEL_VLAN_CMD;
357 :
358 0 : if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
359 0 : wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: "
360 0 : "%s", __func__, if_name, strerror(errno));
361 0 : close(fd);
362 0 : return -1;
363 : }
364 :
365 0 : close(fd);
366 0 : return 0;
367 : }
368 :
369 :
370 : /*
371 : Add a vlan interface with VLAN ID 'vid' and tagged interface
372 : 'if_name'.
373 :
374 : returns -1 on error
375 : returns 1 if the interface already exists
376 : returns 0 otherwise
377 : */
378 18 : int vlan_add(const char *if_name, int vid, const char *vlan_if_name)
379 : {
380 : int fd;
381 : struct vlan_ioctl_args if_request;
382 :
383 18 : wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)",
384 : if_name, vid);
385 18 : ifconfig_up(if_name);
386 :
387 18 : if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) {
388 0 : wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'",
389 : if_name);
390 0 : return -1;
391 : }
392 :
393 18 : if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
394 0 : wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
395 0 : "failed: %s", __func__, strerror(errno));
396 0 : return -1;
397 : }
398 :
399 18 : os_memset(&if_request, 0, sizeof(if_request));
400 :
401 : /* Determine if a suitable vlan device already exists. */
402 :
403 18 : os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d",
404 : vid);
405 :
406 18 : if_request.cmd = _GET_VLAN_VID_CMD;
407 :
408 18 : if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0) {
409 :
410 0 : if (if_request.u.VID == vid) {
411 0 : if_request.cmd = _GET_VLAN_REALDEV_NAME_CMD;
412 :
413 0 : if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 &&
414 0 : os_strncmp(if_request.u.device2, if_name,
415 : sizeof(if_request.u.device2)) == 0) {
416 0 : close(fd);
417 0 : wpa_printf(MSG_DEBUG, "VLAN: vlan_add: "
418 : "if_name %s exists already",
419 : if_request.device1);
420 0 : return 1;
421 : }
422 : }
423 : }
424 :
425 : /* A suitable vlan device does not already exist, add one. */
426 :
427 18 : os_memset(&if_request, 0, sizeof(if_request));
428 18 : os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1));
429 18 : if_request.u.VID = vid;
430 18 : if_request.cmd = ADD_VLAN_CMD;
431 :
432 18 : if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
433 18 : wpa_printf(MSG_ERROR, "VLAN: %s: ADD_VLAN_CMD failed for %s: "
434 : "%s",
435 18 : __func__, if_request.device1, strerror(errno));
436 18 : close(fd);
437 18 : return -1;
438 : }
439 :
440 0 : close(fd);
441 0 : return 0;
442 : }
443 :
444 :
445 1026 : static int vlan_set_name_type(unsigned int name_type)
446 : {
447 : int fd;
448 : struct vlan_ioctl_args if_request;
449 :
450 1026 : wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)",
451 : name_type);
452 1026 : if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
453 0 : wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
454 0 : "failed: %s", __func__, strerror(errno));
455 0 : return -1;
456 : }
457 :
458 1026 : os_memset(&if_request, 0, sizeof(if_request));
459 :
460 1026 : if_request.u.name_type = name_type;
461 1026 : if_request.cmd = SET_VLAN_NAME_TYPE_CMD;
462 1026 : if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) {
463 1026 : wpa_printf(MSG_ERROR, "VLAN: %s: SET_VLAN_NAME_TYPE_CMD "
464 : "name_type=%u failed: %s",
465 1026 : __func__, name_type, strerror(errno));
466 1026 : close(fd);
467 1026 : return -1;
468 : }
469 :
470 0 : close(fd);
471 0 : return 0;
472 : }
473 :
474 : #endif /* CONFIG_VLAN_NETLINK */
475 :
476 :
477 20473 : static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
478 : {
479 : char vlan_ifname[IFNAMSIZ];
480 : char br_name[IFNAMSIZ];
481 20473 : struct hostapd_vlan *vlan = hapd->conf->vlan;
482 20473 : char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
483 20473 : int vlan_naming = hapd->conf->ssid.vlan_naming;
484 :
485 20473 : wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
486 :
487 41448 : while (vlan) {
488 625 : if (os_strcmp(ifname, vlan->ifname) == 0) {
489 :
490 123 : if (hapd->conf->vlan_bridge[0]) {
491 0 : os_snprintf(br_name, sizeof(br_name), "%s%d",
492 0 : hapd->conf->vlan_bridge,
493 : vlan->vlan_id);
494 123 : } else if (tagged_interface) {
495 18 : os_snprintf(br_name, sizeof(br_name),
496 : "br%s.%d", tagged_interface,
497 : vlan->vlan_id);
498 : } else {
499 105 : os_snprintf(br_name, sizeof(br_name),
500 : "brvlan%d", vlan->vlan_id);
501 : }
502 :
503 123 : if (!br_addbr(br_name))
504 13 : vlan->clean |= DVLAN_CLEAN_BR;
505 :
506 123 : ifconfig_up(br_name);
507 :
508 123 : if (tagged_interface) {
509 18 : if (vlan_naming ==
510 : DYNAMIC_VLAN_NAMING_WITH_DEVICE)
511 0 : os_snprintf(vlan_ifname,
512 : sizeof(vlan_ifname),
513 : "%s.%d", tagged_interface,
514 : vlan->vlan_id);
515 : else
516 18 : os_snprintf(vlan_ifname,
517 : sizeof(vlan_ifname),
518 : "vlan%d", vlan->vlan_id);
519 :
520 18 : ifconfig_up(tagged_interface);
521 18 : if (!vlan_add(tagged_interface, vlan->vlan_id,
522 : vlan_ifname))
523 0 : vlan->clean |= DVLAN_CLEAN_VLAN;
524 :
525 18 : if (!br_addif(br_name, vlan_ifname))
526 0 : vlan->clean |= DVLAN_CLEAN_VLAN_PORT;
527 :
528 18 : ifconfig_up(vlan_ifname);
529 : }
530 :
531 123 : if (!br_addif(br_name, ifname))
532 13 : vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
533 :
534 123 : ifconfig_up(ifname);
535 :
536 123 : break;
537 : }
538 502 : vlan = vlan->next;
539 : }
540 20473 : }
541 :
542 :
543 258 : static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
544 : {
545 : char vlan_ifname[IFNAMSIZ];
546 : char br_name[IFNAMSIZ];
547 258 : struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
548 258 : char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
549 258 : int vlan_naming = hapd->conf->ssid.vlan_naming;
550 :
551 258 : wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
552 :
553 258 : first = prev = vlan;
554 :
555 522 : while (vlan) {
556 19 : if (os_strcmp(ifname, vlan->ifname) == 0) {
557 13 : if (hapd->conf->vlan_bridge[0]) {
558 0 : os_snprintf(br_name, sizeof(br_name), "%s%d",
559 0 : hapd->conf->vlan_bridge,
560 : vlan->vlan_id);
561 13 : } else if (tagged_interface) {
562 2 : os_snprintf(br_name, sizeof(br_name),
563 : "br%s.%d", tagged_interface,
564 : vlan->vlan_id);
565 : } else {
566 11 : os_snprintf(br_name, sizeof(br_name),
567 : "brvlan%d", vlan->vlan_id);
568 : }
569 :
570 13 : if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
571 13 : br_delif(br_name, vlan->ifname);
572 :
573 13 : if (tagged_interface) {
574 2 : if (vlan_naming ==
575 : DYNAMIC_VLAN_NAMING_WITH_DEVICE)
576 0 : os_snprintf(vlan_ifname,
577 : sizeof(vlan_ifname),
578 : "%s.%d", tagged_interface,
579 : vlan->vlan_id);
580 : else
581 2 : os_snprintf(vlan_ifname,
582 : sizeof(vlan_ifname),
583 : "vlan%d", vlan->vlan_id);
584 2 : if (vlan->clean & DVLAN_CLEAN_VLAN_PORT)
585 0 : br_delif(br_name, vlan_ifname);
586 2 : ifconfig_down(vlan_ifname);
587 :
588 2 : if (vlan->clean & DVLAN_CLEAN_VLAN)
589 0 : vlan_rem(vlan_ifname);
590 : }
591 :
592 26 : if ((vlan->clean & DVLAN_CLEAN_BR) &&
593 13 : br_getnumports(br_name) == 0) {
594 13 : ifconfig_down(br_name);
595 13 : br_delbr(br_name);
596 : }
597 :
598 13 : if (vlan == first) {
599 11 : hapd->conf->vlan = vlan->next;
600 : } else {
601 2 : prev->next = vlan->next;
602 : }
603 13 : os_free(vlan);
604 :
605 13 : break;
606 : }
607 6 : prev = vlan;
608 6 : vlan = vlan->next;
609 : }
610 258 : }
611 :
612 :
613 : static void
614 20719 : vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del,
615 : struct hostapd_data *hapd)
616 : {
617 : struct ifinfomsg *ifi;
618 : int attrlen, nlmsg_len, rta_len;
619 : struct rtattr *attr;
620 : char ifname[IFNAMSIZ + 1];
621 :
622 20719 : if (len < sizeof(*ifi))
623 0 : return;
624 :
625 20719 : ifi = NLMSG_DATA(h);
626 :
627 20719 : nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
628 :
629 20719 : attrlen = h->nlmsg_len - nlmsg_len;
630 20719 : if (attrlen < 0)
631 0 : return;
632 :
633 20719 : attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
634 :
635 20719 : os_memset(ifname, 0, sizeof(ifname));
636 20719 : rta_len = RTA_ALIGN(sizeof(struct rtattr));
637 242640 : while (RTA_OK(attr, attrlen)) {
638 201202 : if (attr->rta_type == IFLA_IFNAME) {
639 20719 : int n = attr->rta_len - rta_len;
640 20719 : if (n < 0)
641 0 : break;
642 :
643 20719 : if ((size_t) n >= sizeof(ifname))
644 0 : n = sizeof(ifname) - 1;
645 20719 : os_memcpy(ifname, ((char *) attr) + rta_len, n);
646 :
647 : }
648 :
649 201202 : attr = RTA_NEXT(attr, attrlen);
650 : }
651 :
652 20719 : if (!ifname[0])
653 0 : return;
654 :
655 103595 : wpa_printf(MSG_DEBUG,
656 : "VLAN: RTM_%sLINK: ifi_index=%d ifname=%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
657 : del ? "DEL" : "NEW",
658 20719 : ifi->ifi_index, ifname, ifi->ifi_family, ifi->ifi_flags,
659 20719 : (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
660 20719 : (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
661 20719 : (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
662 20719 : (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
663 :
664 20719 : if (del)
665 246 : vlan_dellink(ifname, hapd);
666 : else
667 20473 : vlan_newlink(ifname, hapd);
668 : }
669 :
670 :
671 20719 : static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
672 : {
673 : char buf[8192];
674 : int left;
675 : struct sockaddr_nl from;
676 : socklen_t fromlen;
677 : struct nlmsghdr *h;
678 20719 : struct hostapd_data *hapd = eloop_ctx;
679 :
680 20719 : fromlen = sizeof(from);
681 20719 : left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
682 : (struct sockaddr *) &from, &fromlen);
683 20719 : if (left < 0) {
684 0 : if (errno != EINTR && errno != EAGAIN)
685 0 : wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s",
686 0 : __func__, strerror(errno));
687 20719 : return;
688 : }
689 :
690 20719 : h = (struct nlmsghdr *) buf;
691 62157 : while (NLMSG_OK(h, left)) {
692 : int len, plen;
693 :
694 20719 : len = h->nlmsg_len;
695 20719 : plen = len - sizeof(*h);
696 20719 : if (len > left || plen < 0) {
697 0 : wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink "
698 : "message: len=%d left=%d plen=%d",
699 : len, left, plen);
700 0 : break;
701 : }
702 :
703 20719 : switch (h->nlmsg_type) {
704 : case RTM_NEWLINK:
705 20473 : vlan_read_ifnames(h, plen, 0, hapd);
706 20473 : break;
707 : case RTM_DELLINK:
708 246 : vlan_read_ifnames(h, plen, 1, hapd);
709 246 : break;
710 : }
711 :
712 20719 : h = NLMSG_NEXT(h, left);
713 : }
714 :
715 20719 : if (left > 0) {
716 0 : wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of "
717 : "netlink message", __func__, left);
718 : }
719 : }
720 :
721 :
722 : static struct full_dynamic_vlan *
723 1026 : full_dynamic_vlan_init(struct hostapd_data *hapd)
724 : {
725 : struct sockaddr_nl local;
726 : struct full_dynamic_vlan *priv;
727 :
728 1026 : priv = os_zalloc(sizeof(*priv));
729 1026 : if (priv == NULL)
730 0 : return NULL;
731 :
732 : #ifndef CONFIG_VLAN_NETLINK
733 1026 : vlan_set_name_type(hapd->conf->ssid.vlan_naming ==
734 : DYNAMIC_VLAN_NAMING_WITH_DEVICE ?
735 : VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD :
736 : VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
737 : #endif /* CONFIG_VLAN_NETLINK */
738 :
739 1026 : priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
740 1026 : if (priv->s < 0) {
741 0 : wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW,"
742 : "NETLINK_ROUTE) failed: %s",
743 0 : __func__, strerror(errno));
744 0 : os_free(priv);
745 0 : return NULL;
746 : }
747 :
748 1026 : os_memset(&local, 0, sizeof(local));
749 1026 : local.nl_family = AF_NETLINK;
750 1026 : local.nl_groups = RTMGRP_LINK;
751 1026 : if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) {
752 0 : wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s",
753 0 : __func__, strerror(errno));
754 0 : close(priv->s);
755 0 : os_free(priv);
756 0 : return NULL;
757 : }
758 :
759 1026 : if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL))
760 : {
761 0 : close(priv->s);
762 0 : os_free(priv);
763 0 : return NULL;
764 : }
765 :
766 1026 : return priv;
767 : }
768 :
769 :
770 1043 : static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv)
771 : {
772 1043 : if (priv == NULL)
773 1060 : return;
774 1026 : eloop_unregister_read_sock(priv->s);
775 1026 : close(priv->s);
776 1026 : os_free(priv);
777 : }
778 : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
779 :
780 :
781 13 : int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
782 : struct hostapd_ssid *mssid, const char *dyn_vlan)
783 : {
784 : int i;
785 :
786 13 : if (dyn_vlan == NULL)
787 0 : return 0;
788 :
789 : /* Static WEP keys are set here; IEEE 802.1X and WPA uses their own
790 : * functions for setting up dynamic broadcast keys. */
791 65 : for (i = 0; i < 4; i++) {
792 52 : if (mssid->wep.key[i] &&
793 0 : hostapd_drv_set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
794 0 : i == mssid->wep.idx, NULL, 0,
795 0 : mssid->wep.key[i], mssid->wep.len[i]))
796 : {
797 0 : wpa_printf(MSG_ERROR, "VLAN: Could not set WEP "
798 : "encryption for dynamic VLAN");
799 0 : return -1;
800 : }
801 : }
802 :
803 13 : return 0;
804 : }
805 :
806 :
807 1026 : static int vlan_dynamic_add(struct hostapd_data *hapd,
808 : struct hostapd_vlan *vlan)
809 : {
810 2060 : while (vlan) {
811 8 : if (vlan->vlan_id != VLAN_ID_WILDCARD) {
812 1 : if (hostapd_vlan_if_add(hapd, vlan->ifname)) {
813 0 : if (errno != EEXIST) {
814 0 : wpa_printf(MSG_ERROR, "VLAN: Could "
815 : "not add VLAN %s: %s",
816 0 : vlan->ifname,
817 0 : strerror(errno));
818 0 : return -1;
819 : }
820 : }
821 : #ifdef CONFIG_FULL_DYNAMIC_VLAN
822 1 : ifconfig_up(vlan->ifname);
823 : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
824 : }
825 :
826 8 : vlan = vlan->next;
827 : }
828 :
829 1026 : return 0;
830 : }
831 :
832 :
833 1043 : static void vlan_dynamic_remove(struct hostapd_data *hapd,
834 : struct hostapd_vlan *vlan)
835 : {
836 : struct hostapd_vlan *next;
837 :
838 2105 : while (vlan) {
839 19 : next = vlan->next;
840 :
841 31 : if (vlan->vlan_id != VLAN_ID_WILDCARD &&
842 12 : hostapd_vlan_if_remove(hapd, vlan->ifname)) {
843 0 : wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
844 : "iface: %s: %s",
845 0 : vlan->ifname, strerror(errno));
846 : }
847 : #ifdef CONFIG_FULL_DYNAMIC_VLAN
848 19 : if (vlan->clean)
849 12 : vlan_dellink(vlan->ifname, hapd);
850 : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
851 :
852 19 : vlan = next;
853 : }
854 1043 : }
855 :
856 :
857 1026 : int vlan_init(struct hostapd_data *hapd)
858 : {
859 : #ifdef CONFIG_FULL_DYNAMIC_VLAN
860 1026 : hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
861 : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
862 :
863 1033 : if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED &&
864 7 : !hapd->conf->vlan) {
865 : /* dynamic vlans enabled but no (or empty) vlan_file given */
866 : struct hostapd_vlan *vlan;
867 6 : vlan = os_zalloc(sizeof(*vlan));
868 6 : if (vlan == NULL) {
869 0 : wpa_printf(MSG_ERROR, "Out of memory while assigning "
870 : "VLAN interfaces");
871 0 : return -1;
872 : }
873 :
874 6 : vlan->vlan_id = VLAN_ID_WILDCARD;
875 6 : os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#",
876 6 : hapd->conf->iface);
877 6 : vlan->next = hapd->conf->vlan;
878 6 : hapd->conf->vlan = vlan;
879 : }
880 :
881 1026 : if (vlan_dynamic_add(hapd, hapd->conf->vlan))
882 0 : return -1;
883 :
884 1026 : return 0;
885 : }
886 :
887 :
888 1043 : void vlan_deinit(struct hostapd_data *hapd)
889 : {
890 1043 : vlan_dynamic_remove(hapd, hapd->conf->vlan);
891 :
892 : #ifdef CONFIG_FULL_DYNAMIC_VLAN
893 1043 : full_dynamic_vlan_deinit(hapd->full_dynamic_vlan);
894 1043 : hapd->full_dynamic_vlan = NULL;
895 : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
896 1043 : }
897 :
898 :
899 12 : struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
900 : struct hostapd_vlan *vlan,
901 : int vlan_id)
902 : {
903 12 : struct hostapd_vlan *n = NULL;
904 : char *ifname, *pos;
905 :
906 24 : if (vlan == NULL || vlan_id <= 0 || vlan_id > MAX_VLAN_ID ||
907 12 : vlan->vlan_id != VLAN_ID_WILDCARD)
908 0 : return NULL;
909 :
910 12 : wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
911 12 : __func__, vlan_id, vlan->ifname);
912 12 : ifname = os_strdup(vlan->ifname);
913 12 : if (ifname == NULL)
914 0 : return NULL;
915 12 : pos = os_strchr(ifname, '#');
916 12 : if (pos == NULL)
917 0 : goto free_ifname;
918 12 : *pos++ = '\0';
919 :
920 12 : n = os_zalloc(sizeof(*n));
921 12 : if (n == NULL)
922 0 : goto free_ifname;
923 :
924 12 : n->vlan_id = vlan_id;
925 12 : n->dynamic_vlan = 1;
926 :
927 12 : os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
928 : pos);
929 :
930 12 : if (hostapd_vlan_if_add(hapd, n->ifname)) {
931 0 : os_free(n);
932 0 : n = NULL;
933 0 : goto free_ifname;
934 : }
935 :
936 12 : n->next = hapd->conf->vlan;
937 12 : hapd->conf->vlan = n;
938 :
939 : #ifdef CONFIG_FULL_DYNAMIC_VLAN
940 12 : ifconfig_up(n->ifname);
941 : #endif /* CONFIG_FULL_DYNAMIC_VLAN */
942 :
943 : free_ifname:
944 12 : os_free(ifname);
945 12 : return n;
946 : }
947 :
948 :
949 1 : int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
950 : {
951 : struct hostapd_vlan *vlan;
952 :
953 1 : if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID)
954 0 : return 1;
955 :
956 1 : wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d)", __func__, vlan_id);
957 :
958 1 : vlan = hapd->conf->vlan;
959 3 : while (vlan) {
960 2 : if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) {
961 1 : vlan->dynamic_vlan--;
962 1 : break;
963 : }
964 1 : vlan = vlan->next;
965 : }
966 :
967 1 : if (vlan == NULL)
968 0 : return 1;
969 :
970 1 : if (vlan->dynamic_vlan == 0)
971 1 : hostapd_vlan_if_remove(hapd, vlan->ifname);
972 :
973 1 : return 0;
974 : }
|