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