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