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 static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
    484 {
    485 	char vlan_ifname[IFNAMSIZ];
    486 	char br_name[IFNAMSIZ];
    487 	struct hostapd_vlan *vlan = hapd->conf->vlan;
    488 	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
    489 	int vlan_naming = hapd->conf->ssid.vlan_naming;
    490 
    491 	wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
    492 
    493 	while (vlan) {
    494 		if (os_strcmp(ifname, vlan->ifname) == 0) {
    495 
    496 			os_snprintf(br_name, sizeof(br_name), "brvlan%d",
    497 				    vlan->vlan_id);
    498 
    499 			if (!br_addbr(br_name))
    500 				vlan->clean |= DVLAN_CLEAN_BR;
    501 
    502 			ifconfig_up(br_name);
    503 
    504 			if (tagged_interface) {
    505 				if (vlan_naming ==
    506 				    DYNAMIC_VLAN_NAMING_WITH_DEVICE)
    507 					os_snprintf(vlan_ifname,
    508 						    sizeof(vlan_ifname),
    509 						    "%s.%d", tagged_interface,
    510 						    vlan->vlan_id);
    511 				else
    512 					os_snprintf(vlan_ifname,
    513 						    sizeof(vlan_ifname),
    514 						    "vlan%d", vlan->vlan_id);
    515 
    516 				ifconfig_up(tagged_interface);
    517 				if (!vlan_add(tagged_interface, vlan->vlan_id,
    518 					      vlan_ifname))
    519 					vlan->clean |= DVLAN_CLEAN_VLAN;
    520 
    521 				if (!br_addif(br_name, vlan_ifname))
    522 					vlan->clean |= DVLAN_CLEAN_VLAN_PORT;
    523 
    524 				ifconfig_up(vlan_ifname);
    525 			}
    526 
    527 			if (!br_addif(br_name, ifname))
    528 				vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
    529 
    530 			ifconfig_up(ifname);
    531 
    532 			break;
    533 		}
    534 		vlan = vlan->next;
    535 	}
    536 }
    537 
    538 
    539 static void vlan_dellink(char *ifname, struct hostapd_data *hapd)
    540 {
    541 	char vlan_ifname[IFNAMSIZ];
    542 	char br_name[IFNAMSIZ];
    543 	struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
    544 	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
    545 	int vlan_naming = hapd->conf->ssid.vlan_naming;
    546 
    547 	wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
    548 
    549 	first = prev = vlan;
    550 
    551 	while (vlan) {
    552 		if (os_strcmp(ifname, vlan->ifname) == 0) {
    553 			os_snprintf(br_name, sizeof(br_name), "brvlan%d",
    554 				    vlan->vlan_id);
    555 
    556 			if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
    557 				br_delif(br_name, vlan->ifname);
    558 
    559 			if (tagged_interface) {
    560 				if (vlan_naming ==
    561 				    DYNAMIC_VLAN_NAMING_WITH_DEVICE)
    562 					os_snprintf(vlan_ifname,
    563 						    sizeof(vlan_ifname),
    564 						    "%s.%d", tagged_interface,
    565 						    vlan->vlan_id);
    566 				else
    567 					os_snprintf(vlan_ifname,
    568 						    sizeof(vlan_ifname),
    569 						    "vlan%d", vlan->vlan_id);
    570 				if (vlan->clean & DVLAN_CLEAN_VLAN_PORT)
    571 					br_delif(br_name, vlan_ifname);
    572 				ifconfig_down(vlan_ifname);
    573 
    574 				if (vlan->clean & DVLAN_CLEAN_VLAN)
    575 					vlan_rem(vlan_ifname);
    576 			}
    577 
    578 			if ((vlan->clean & DVLAN_CLEAN_BR) &&
    579 			    br_getnumports(br_name) == 0) {
    580 				ifconfig_down(br_name);
    581 				br_delbr(br_name);
    582 			}
    583 
    584 			if (vlan == first) {
    585 				hapd->conf->vlan = vlan->next;
    586 			} else {
    587 				prev->next = vlan->next;
    588 			}
    589 			os_free(vlan);
    590 
    591 			break;
    592 		}
    593 		prev = vlan;
    594 		vlan = vlan->next;
    595 	}
    596 }
    597 
    598 
    599 static void
    600 vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del,
    601 		  struct hostapd_data *hapd)
    602 {
    603 	struct ifinfomsg *ifi;
    604 	int attrlen, nlmsg_len, rta_len;
    605 	struct rtattr *attr;
    606 
    607 	if (len < sizeof(*ifi))
    608 		return;
    609 
    610 	ifi = NLMSG_DATA(h);
    611 
    612 	nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
    613 
    614 	attrlen = h->nlmsg_len - nlmsg_len;
    615 	if (attrlen < 0)
    616 		return;
    617 
    618 	attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
    619 
    620 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
    621 	while (RTA_OK(attr, attrlen)) {
    622 		char ifname[IFNAMSIZ + 1];
    623 
    624 		if (attr->rta_type == IFLA_IFNAME) {
    625 			int n = attr->rta_len - rta_len;
    626 			if (n < 0)
    627 				break;
    628 
    629 			os_memset(ifname, 0, sizeof(ifname));
    630 
    631 			if ((size_t) n > sizeof(ifname))
    632 				n = sizeof(ifname);
    633 			os_memcpy(ifname, ((char *) attr) + rta_len, n);
    634 
    635 			if (del)
    636 				vlan_dellink(ifname, hapd);
    637 			else
    638 				vlan_newlink(ifname, hapd);
    639 		}
    640 
    641 		attr = RTA_NEXT(attr, attrlen);
    642 	}
    643 }
    644 
    645 
    646 static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
    647 {
    648 	char buf[8192];
    649 	int left;
    650 	struct sockaddr_nl from;
    651 	socklen_t fromlen;
    652 	struct nlmsghdr *h;
    653 	struct hostapd_data *hapd = eloop_ctx;
    654 
    655 	fromlen = sizeof(from);
    656 	left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
    657 			(struct sockaddr *) &from, &fromlen);
    658 	if (left < 0) {
    659 		if (errno != EINTR && errno != EAGAIN)
    660 			wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s",
    661 				   __func__, strerror(errno));
    662 		return;
    663 	}
    664 
    665 	h = (struct nlmsghdr *) buf;
    666 	while (left >= (int) sizeof(*h)) {
    667 		int len, plen;
    668 
    669 		len = h->nlmsg_len;
    670 		plen = len - sizeof(*h);
    671 		if (len > left || plen < 0) {
    672 			wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink "
    673 				   "message: len=%d left=%d plen=%d",
    674 				   len, left, plen);
    675 			break;
    676 		}
    677 
    678 		switch (h->nlmsg_type) {
    679 		case RTM_NEWLINK:
    680 			vlan_read_ifnames(h, plen, 0, hapd);
    681 			break;
    682 		case RTM_DELLINK:
    683 			vlan_read_ifnames(h, plen, 1, hapd);
    684 			break;
    685 		}
    686 
    687 		len = NLMSG_ALIGN(len);
    688 		left -= len;
    689 		h = (struct nlmsghdr *) ((char *) h + len);
    690 	}
    691 
    692 	if (left > 0) {
    693 		wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of "
    694 			   "netlink message", __func__, left);
    695 	}
    696 }
    697 
    698 
    699 static struct full_dynamic_vlan *
    700 full_dynamic_vlan_init(struct hostapd_data *hapd)
    701 {
    702 	struct sockaddr_nl local;
    703 	struct full_dynamic_vlan *priv;
    704 
    705 	priv = os_zalloc(sizeof(*priv));
    706 	if (priv == NULL)
    707 		return NULL;
    708 
    709 #ifndef CONFIG_VLAN_NETLINK
    710 	vlan_set_name_type(hapd->conf->ssid.vlan_naming ==
    711 			   DYNAMIC_VLAN_NAMING_WITH_DEVICE ?
    712 			   VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD :
    713 			   VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
    714 #endif /* CONFIG_VLAN_NETLINK */
    715 
    716 	priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    717 	if (priv->s < 0) {
    718 		wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW,"
    719 			   "NETLINK_ROUTE) failed: %s",
    720 			   __func__, strerror(errno));
    721 		os_free(priv);
    722 		return NULL;
    723 	}
    724 
    725 	os_memset(&local, 0, sizeof(local));
    726 	local.nl_family = AF_NETLINK;
    727 	local.nl_groups = RTMGRP_LINK;
    728 	if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) {
    729 		wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s",
    730 			   __func__, strerror(errno));
    731 		close(priv->s);
    732 		os_free(priv);
    733 		return NULL;
    734 	}
    735 
    736 	if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL))
    737 	{
    738 		close(priv->s);
    739 		os_free(priv);
    740 		return NULL;
    741 	}
    742 
    743 	return priv;
    744 }
    745 
    746 
    747 static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv)
    748 {
    749 	if (priv == NULL)
    750 		return;
    751 	eloop_unregister_read_sock(priv->s);
    752 	close(priv->s);
    753 	os_free(priv);
    754 }
    755 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
    756 
    757 
    758 int vlan_setup_encryption_dyn(struct hostapd_data *hapd,
    759 			      struct hostapd_ssid *mssid, const char *dyn_vlan)
    760 {
    761         int i;
    762 
    763         if (dyn_vlan == NULL)
    764 		return 0;
    765 
    766 	/* Static WEP keys are set here; IEEE 802.1X and WPA uses their own
    767 	 * functions for setting up dynamic broadcast keys. */
    768 	for (i = 0; i < 4; i++) {
    769 		if (mssid->wep.key[i] &&
    770 		    hostapd_drv_set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i,
    771 					i == mssid->wep.idx, NULL, 0,
    772 					mssid->wep.key[i], mssid->wep.len[i]))
    773 		{
    774 			wpa_printf(MSG_ERROR, "VLAN: Could not set WEP "
    775 				   "encryption for dynamic VLAN");
    776 			return -1;
    777 		}
    778 	}
    779 
    780 	return 0;
    781 }
    782 
    783 
    784 static int vlan_dynamic_add(struct hostapd_data *hapd,
    785 			    struct hostapd_vlan *vlan)
    786 {
    787 	while (vlan) {
    788 		if (vlan->vlan_id != VLAN_ID_WILDCARD) {
    789 			if (hostapd_vlan_if_add(hapd, vlan->ifname)) {
    790 				if (errno != EEXIST) {
    791 					wpa_printf(MSG_ERROR, "VLAN: Could "
    792 						   "not add VLAN %s: %s",
    793 						   vlan->ifname,
    794 						   strerror(errno));
    795 					return -1;
    796 				}
    797 			}
    798 #ifdef CONFIG_FULL_DYNAMIC_VLAN
    799 			ifconfig_up(vlan->ifname);
    800 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
    801 		}
    802 
    803 		vlan = vlan->next;
    804 	}
    805 
    806 	return 0;
    807 }
    808 
    809 
    810 static void vlan_dynamic_remove(struct hostapd_data *hapd,
    811 				struct hostapd_vlan *vlan)
    812 {
    813 	struct hostapd_vlan *next;
    814 
    815 	while (vlan) {
    816 		next = vlan->next;
    817 
    818 		if (vlan->vlan_id != VLAN_ID_WILDCARD &&
    819 		    hostapd_vlan_if_remove(hapd, vlan->ifname)) {
    820 			wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN "
    821 				   "iface: %s: %s",
    822 				   vlan->ifname, strerror(errno));
    823 		}
    824 #ifdef CONFIG_FULL_DYNAMIC_VLAN
    825 		if (vlan->clean)
    826 			vlan_dellink(vlan->ifname, hapd);
    827 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
    828 
    829 		vlan = next;
    830 	}
    831 }
    832 
    833 
    834 int vlan_init(struct hostapd_data *hapd)
    835 {
    836 #ifdef CONFIG_FULL_DYNAMIC_VLAN
    837 	hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd);
    838 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
    839 
    840 	if (vlan_dynamic_add(hapd, hapd->conf->vlan))
    841 		return -1;
    842 
    843         return 0;
    844 }
    845 
    846 
    847 void vlan_deinit(struct hostapd_data *hapd)
    848 {
    849 	vlan_dynamic_remove(hapd, hapd->conf->vlan);
    850 
    851 #ifdef CONFIG_FULL_DYNAMIC_VLAN
    852 	full_dynamic_vlan_deinit(hapd->full_dynamic_vlan);
    853 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
    854 }
    855 
    856 
    857 struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd,
    858 				       struct hostapd_vlan *vlan,
    859 				       int vlan_id)
    860 {
    861 	struct hostapd_vlan *n;
    862 	char *ifname, *pos;
    863 
    864 	if (vlan == NULL || vlan_id <= 0 || vlan_id > MAX_VLAN_ID ||
    865 	    vlan->vlan_id != VLAN_ID_WILDCARD)
    866 		return NULL;
    867 
    868 	wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)",
    869 		   __func__, vlan_id, vlan->ifname);
    870 	ifname = os_strdup(vlan->ifname);
    871 	if (ifname == NULL)
    872 		return NULL;
    873 	pos = os_strchr(ifname, '#');
    874 	if (pos == NULL) {
    875 		os_free(ifname);
    876 		return NULL;
    877 	}
    878 	*pos++ = '\0';
    879 
    880 	n = os_zalloc(sizeof(*n));
    881 	if (n == NULL) {
    882 		os_free(ifname);
    883 		return NULL;
    884 	}
    885 
    886 	n->vlan_id = vlan_id;
    887 	n->dynamic_vlan = 1;
    888 
    889 	os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id,
    890 		    pos);
    891 	os_free(ifname);
    892 
    893 	if (hostapd_vlan_if_add(hapd, n->ifname)) {
    894 		os_free(n);
    895 		return NULL;
    896 	}
    897 
    898 	n->next = hapd->conf->vlan;
    899 	hapd->conf->vlan = n;
    900 
    901 #ifdef CONFIG_FULL_DYNAMIC_VLAN
    902 	ifconfig_up(n->ifname);
    903 #endif /* CONFIG_FULL_DYNAMIC_VLAN */
    904 
    905 	return n;
    906 }
    907 
    908 
    909 int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id)
    910 {
    911 	struct hostapd_vlan *vlan;
    912 
    913 	if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID)
    914 		return 1;
    915 
    916 	wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d)", __func__, vlan_id);
    917 
    918 	vlan = hapd->conf->vlan;
    919 	while (vlan) {
    920 		if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) {
    921 			vlan->dynamic_vlan--;
    922 			break;
    923 		}
    924 		vlan = vlan->next;
    925 	}
    926 
    927 	if (vlan == NULL)
    928 		return 1;
    929 
    930 	if (vlan->dynamic_vlan == 0)
    931 		hostapd_vlan_if_remove(hapd, vlan->ifname);
    932 
    933 	return 0;
    934 }
    935