Home | History | Annotate | Download | only in ap
      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 (at) 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 
     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 
     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 
     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 
    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 */
    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 
    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 */
    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 
    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 
    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 */
    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 
    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  */
    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  */
    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 
    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 
    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
    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 
    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 *
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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