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