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