Home | History | Annotate | Download | only in ap
      1 /*
      2  * hostapd / VLAN initialization - full dynamic VLAN
      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 #include <net/if.h>
     13 /* Avoid conflicts due to NetBSD net/if.h if_type define with driver.h */
     14 #undef if_type
     15 #include <sys/ioctl.h>
     16 
     17 #include "utils/common.h"
     18 #include "drivers/priv_netlink.h"
     19 #include "common/linux_bridge.h"
     20 #include "common/linux_vlan.h"
     21 #include "utils/eloop.h"
     22 #include "hostapd.h"
     23 #include "ap_config.h"
     24 #include "ap_drv_ops.h"
     25 #include "wpa_auth.h"
     26 #include "vlan_init.h"
     27 #include "vlan_util.h"
     28 
     29 
     30 struct full_dynamic_vlan {
     31 	int s; /* socket on which to listen for new/removed interfaces. */
     32 };
     33 
     34 #define DVLAN_CLEAN_BR         0x1
     35 #define DVLAN_CLEAN_VLAN       0x2
     36 #define DVLAN_CLEAN_VLAN_PORT  0x4
     37 
     38 struct dynamic_iface {
     39 	char ifname[IFNAMSIZ + 1];
     40 	int usage;
     41 	int clean;
     42 	struct dynamic_iface *next;
     43 };
     44 
     45 
     46 /* Increment ref counter for ifname and add clean flag.
     47  * If not in list, add it only if some flags are given.
     48  */
     49 static void dyn_iface_get(struct hostapd_data *hapd, const char *ifname,
     50 			  int clean)
     51 {
     52 	struct dynamic_iface *next, **dynamic_ifaces;
     53 	struct hapd_interfaces *interfaces;
     54 
     55 	interfaces = hapd->iface->interfaces;
     56 	dynamic_ifaces = &interfaces->vlan_priv;
     57 
     58 	for (next = *dynamic_ifaces; next; next = next->next) {
     59 		if (os_strcmp(ifname, next->ifname) == 0)
     60 			break;
     61 	}
     62 
     63 	if (next) {
     64 		next->usage++;
     65 		next->clean |= clean;
     66 		return;
     67 	}
     68 
     69 	if (!clean)
     70 		return;
     71 
     72 	next = os_zalloc(sizeof(*next));
     73 	if (!next)
     74 		return;
     75 	os_strlcpy(next->ifname, ifname, sizeof(next->ifname));
     76 	next->usage = 1;
     77 	next->clean = clean;
     78 	next->next = *dynamic_ifaces;
     79 	*dynamic_ifaces = next;
     80 }
     81 
     82 
     83 /* Decrement reference counter for given ifname.
     84  * Return clean flag iff reference counter was decreased to zero, else zero
     85  */
     86 static int dyn_iface_put(struct hostapd_data *hapd, const char *ifname)
     87 {
     88 	struct dynamic_iface *next, *prev = NULL, **dynamic_ifaces;
     89 	struct hapd_interfaces *interfaces;
     90 	int clean;
     91 
     92 	interfaces = hapd->iface->interfaces;
     93 	dynamic_ifaces = &interfaces->vlan_priv;
     94 
     95 	for (next = *dynamic_ifaces; next; next = next->next) {
     96 		if (os_strcmp(ifname, next->ifname) == 0)
     97 			break;
     98 		prev = next;
     99 	}
    100 
    101 	if (!next)
    102 		return 0;
    103 
    104 	next->usage--;
    105 	if (next->usage)
    106 		return 0;
    107 
    108 	if (prev)
    109 		prev->next = next->next;
    110 	else
    111 		*dynamic_ifaces = next->next;
    112 	clean = next->clean;
    113 	os_free(next);
    114 
    115 	return clean;
    116 }
    117 
    118 
    119 static int ifconfig_down(const char *if_name)
    120 {
    121 	wpa_printf(MSG_DEBUG, "VLAN: Set interface %s down", if_name);
    122 	return ifconfig_helper(if_name, 0);
    123 }
    124 
    125 
    126 /* This value should be 256 ONLY. If it is something else, then hostapd
    127  * might crash!, as this value has been hard-coded in 2.4.x kernel
    128  * bridging code.
    129  */
    130 #define MAX_BR_PORTS      		256
    131 
    132 static int br_delif(const char *br_name, const char *if_name)
    133 {
    134 	int fd;
    135 	struct ifreq ifr;
    136 	unsigned long args[2];
    137 	int if_index;
    138 
    139 	wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name);
    140 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    141 		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
    142 			   "failed: %s", __func__, strerror(errno));
    143 		return -1;
    144 	}
    145 
    146 	if_index = if_nametoindex(if_name);
    147 
    148 	if (if_index == 0) {
    149 		wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
    150 			   "interface index for '%s'",
    151 			   __func__, if_name);
    152 		close(fd);
    153 		return -1;
    154 	}
    155 
    156 	args[0] = BRCTL_DEL_IF;
    157 	args[1] = if_index;
    158 
    159 	os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
    160 	ifr.ifr_data = (void *) args;
    161 
    162 	if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) {
    163 		/* No error if interface already removed. */
    164 		wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
    165 			   "BRCTL_DEL_IF] failed for br_name=%s if_name=%s: "
    166 			   "%s", __func__, br_name, if_name, strerror(errno));
    167 		close(fd);
    168 		return -1;
    169 	}
    170 
    171 	close(fd);
    172 	return 0;
    173 }
    174 
    175 
    176 /*
    177 	Add interface 'if_name' to the bridge 'br_name'
    178 
    179 	returns -1 on error
    180 	returns 1 if the interface is already part of the bridge
    181 	returns 0 otherwise
    182 */
    183 static int br_addif(const char *br_name, const char *if_name)
    184 {
    185 	int fd;
    186 	struct ifreq ifr;
    187 	unsigned long args[2];
    188 	int if_index;
    189 
    190 	wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name);
    191 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    192 		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
    193 			   "failed: %s", __func__, strerror(errno));
    194 		return -1;
    195 	}
    196 
    197 	if_index = if_nametoindex(if_name);
    198 
    199 	if (if_index == 0) {
    200 		wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining "
    201 			   "interface index for '%s'",
    202 			   __func__, if_name);
    203 		close(fd);
    204 		return -1;
    205 	}
    206 
    207 	args[0] = BRCTL_ADD_IF;
    208 	args[1] = if_index;
    209 
    210 	os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
    211 	ifr.ifr_data = (void *) args;
    212 
    213 	if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
    214 		if (errno == EBUSY) {
    215 			/* The interface is already added. */
    216 			close(fd);
    217 			return 1;
    218 		}
    219 
    220 		wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE,"
    221 			   "BRCTL_ADD_IF] failed for br_name=%s if_name=%s: "
    222 			   "%s", __func__, br_name, if_name, strerror(errno));
    223 		close(fd);
    224 		return -1;
    225 	}
    226 
    227 	close(fd);
    228 	return 0;
    229 }
    230 
    231 
    232 static int br_delbr(const char *br_name)
    233 {
    234 	int fd;
    235 	unsigned long arg[2];
    236 
    237 	wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name);
    238 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    239 		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
    240 			   "failed: %s", __func__, strerror(errno));
    241 		return -1;
    242 	}
    243 
    244 	arg[0] = BRCTL_DEL_BRIDGE;
    245 	arg[1] = (unsigned long) br_name;
    246 
    247 	if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) {
    248 		/* No error if bridge already removed. */
    249 		wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for "
    250 			   "%s: %s", __func__, br_name, strerror(errno));
    251 		close(fd);
    252 		return -1;
    253 	}
    254 
    255 	close(fd);
    256 	return 0;
    257 }
    258 
    259 
    260 /*
    261 	Add a bridge with the name 'br_name'.
    262 
    263 	returns -1 on error
    264 	returns 1 if the bridge already exists
    265 	returns 0 otherwise
    266 */
    267 static int br_addbr(const char *br_name)
    268 {
    269 	int fd;
    270 	unsigned long arg[4];
    271 	struct ifreq ifr;
    272 
    273 	wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name);
    274 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    275 		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
    276 			   "failed: %s", __func__, strerror(errno));
    277 		return -1;
    278 	}
    279 
    280 	arg[0] = BRCTL_ADD_BRIDGE;
    281 	arg[1] = (unsigned long) br_name;
    282 
    283 	if (ioctl(fd, SIOCGIFBR, arg) < 0) {
    284  		if (errno == EEXIST) {
    285 			/* The bridge is already added. */
    286 			close(fd);
    287 			return 1;
    288 		} else {
    289 			wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE "
    290 				   "failed for %s: %s",
    291 				   __func__, br_name, strerror(errno));
    292 			close(fd);
    293 			return -1;
    294 		}
    295 	}
    296 
    297 	/* Decrease forwarding delay to avoid EAPOL timeouts. */
    298 	os_memset(&ifr, 0, sizeof(ifr));
    299 	os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ);
    300 	arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY;
    301 	arg[1] = 1;
    302 	arg[2] = 0;
    303 	arg[3] = 0;
    304 	ifr.ifr_data = (char *) &arg;
    305 	if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
    306 		wpa_printf(MSG_ERROR, "VLAN: %s: "
    307 			   "BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for "
    308 			   "%s: %s", __func__, br_name, strerror(errno));
    309 		/* Continue anyway */
    310 	}
    311 
    312 	close(fd);
    313 	return 0;
    314 }
    315 
    316 
    317 static int br_getnumports(const char *br_name)
    318 {
    319 	int fd;
    320 	int i;
    321 	int port_cnt = 0;
    322 	unsigned long arg[4];
    323 	int ifindices[MAX_BR_PORTS];
    324 	struct ifreq ifr;
    325 
    326 	if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    327 		wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) "
    328 			   "failed: %s", __func__, strerror(errno));
    329 		return -1;
    330 	}
    331 
    332 	arg[0] = BRCTL_GET_PORT_LIST;
    333 	arg[1] = (unsigned long) ifindices;
    334 	arg[2] = MAX_BR_PORTS;
    335 	arg[3] = 0;
    336 
    337 	os_memset(ifindices, 0, sizeof(ifindices));
    338 	os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name));
    339 	ifr.ifr_data = (void *) arg;
    340 
    341 	if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) {
    342 		wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST "
    343 			   "failed for %s: %s",
    344 			   __func__, br_name, strerror(errno));
    345 		close(fd);
    346 		return -1;
    347 	}
    348 
    349 	for (i = 1; i < MAX_BR_PORTS; i++) {
    350 		if (ifindices[i] > 0) {
    351 			port_cnt++;
    352 		}
    353 	}
    354 
    355 	close(fd);
    356 	return port_cnt;
    357 }
    358 
    359 
    360 static void vlan_newlink_tagged(int vlan_naming, const char *tagged_interface,
    361 				const char *br_name, int vid,
    362 				struct hostapd_data *hapd)
    363 {
    364 	char vlan_ifname[IFNAMSIZ];
    365 	int clean;
    366 
    367 	if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE)
    368 		os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d",
    369 			    tagged_interface, vid);
    370 	else
    371 		os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vid);
    372 
    373 	clean = 0;
    374 	ifconfig_up(tagged_interface);
    375 	if (!vlan_add(tagged_interface, vid, vlan_ifname))
    376 		clean |= DVLAN_CLEAN_VLAN;
    377 
    378 	if (!br_addif(br_name, vlan_ifname))
    379 		clean |= DVLAN_CLEAN_VLAN_PORT;
    380 
    381 	dyn_iface_get(hapd, vlan_ifname, clean);
    382 
    383 	ifconfig_up(vlan_ifname);
    384 }
    385 
    386 
    387 static void vlan_bridge_name(char *br_name, struct hostapd_data *hapd, int vid)
    388 {
    389 	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
    390 
    391 	if (hapd->conf->vlan_bridge[0]) {
    392 		os_snprintf(br_name, IFNAMSIZ, "%s%d",
    393 			    hapd->conf->vlan_bridge, vid);
    394 	} else if (tagged_interface) {
    395 		os_snprintf(br_name, IFNAMSIZ, "br%s.%d",
    396 			    tagged_interface, vid);
    397 	} else {
    398 		os_snprintf(br_name, IFNAMSIZ, "brvlan%d", vid);
    399 	}
    400 }
    401 
    402 
    403 static void vlan_get_bridge(const char *br_name, struct hostapd_data *hapd,
    404 			    int vid)
    405 {
    406 	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
    407 	int vlan_naming = hapd->conf->ssid.vlan_naming;
    408 
    409 	dyn_iface_get(hapd, br_name, br_addbr(br_name) ? 0 : DVLAN_CLEAN_BR);
    410 
    411 	ifconfig_up(br_name);
    412 
    413 	if (tagged_interface)
    414 		vlan_newlink_tagged(vlan_naming, tagged_interface, br_name,
    415 				    vid, hapd);
    416 }
    417 
    418 
    419 void vlan_newlink(const char *ifname, struct hostapd_data *hapd)
    420 {
    421 	char br_name[IFNAMSIZ];
    422 	struct hostapd_vlan *vlan;
    423 	int untagged, *tagged, i, notempty;
    424 
    425 	wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
    426 
    427 	for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
    428 		if (vlan->configured ||
    429 		    os_strcmp(ifname, vlan->ifname) != 0)
    430 			continue;
    431 		break;
    432 	}
    433 	if (!vlan)
    434 		return;
    435 
    436 	vlan->configured = 1;
    437 
    438 	notempty = vlan->vlan_desc.notempty;
    439 	untagged = vlan->vlan_desc.untagged;
    440 	tagged = vlan->vlan_desc.tagged;
    441 
    442 	if (!notempty) {
    443 		/* Non-VLAN STA */
    444 		if (hapd->conf->bridge[0] &&
    445 		    !br_addif(hapd->conf->bridge, ifname))
    446 			vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
    447 	} else if (untagged > 0 && untagged <= MAX_VLAN_ID) {
    448 		vlan_bridge_name(br_name, hapd, untagged);
    449 
    450 		vlan_get_bridge(br_name, hapd, untagged);
    451 
    452 		if (!br_addif(br_name, ifname))
    453 			vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
    454 	}
    455 
    456 	for (i = 0; i < MAX_NUM_TAGGED_VLAN && tagged[i]; i++) {
    457 		if (tagged[i] == untagged ||
    458 		    tagged[i] <= 0 || tagged[i] > MAX_VLAN_ID ||
    459 		    (i > 0 && tagged[i] == tagged[i - 1]))
    460 			continue;
    461 		vlan_bridge_name(br_name, hapd, tagged[i]);
    462 		vlan_get_bridge(br_name, hapd, tagged[i]);
    463 		vlan_newlink_tagged(DYNAMIC_VLAN_NAMING_WITH_DEVICE,
    464 				    ifname, br_name, tagged[i], hapd);
    465 	}
    466 
    467 	ifconfig_up(ifname);
    468 }
    469 
    470 
    471 static void vlan_dellink_tagged(int vlan_naming, const char *tagged_interface,
    472 				const char *br_name, int vid,
    473 				struct hostapd_data *hapd)
    474 {
    475 	char vlan_ifname[IFNAMSIZ];
    476 	int clean;
    477 
    478 	if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE)
    479 		os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d",
    480 			    tagged_interface, vid);
    481 	else
    482 		os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vid);
    483 
    484 	clean = dyn_iface_put(hapd, vlan_ifname);
    485 
    486 	if (clean & DVLAN_CLEAN_VLAN_PORT)
    487 		br_delif(br_name, vlan_ifname);
    488 
    489 	if (clean & DVLAN_CLEAN_VLAN) {
    490 		ifconfig_down(vlan_ifname);
    491 		vlan_rem(vlan_ifname);
    492 	}
    493 }
    494 
    495 
    496 static void vlan_put_bridge(const char *br_name, struct hostapd_data *hapd,
    497 			    int vid)
    498 {
    499 	int clean;
    500 	char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
    501 	int vlan_naming = hapd->conf->ssid.vlan_naming;
    502 
    503 	if (tagged_interface)
    504 		vlan_dellink_tagged(vlan_naming, tagged_interface, br_name,
    505 				    vid, hapd);
    506 
    507 	clean = dyn_iface_put(hapd, br_name);
    508 	if ((clean & DVLAN_CLEAN_BR) && br_getnumports(br_name) == 0) {
    509 		ifconfig_down(br_name);
    510 		br_delbr(br_name);
    511 	}
    512 }
    513 
    514 
    515 void vlan_dellink(const char *ifname, struct hostapd_data *hapd)
    516 {
    517 	struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan;
    518 
    519 	wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname);
    520 
    521 	first = prev = vlan;
    522 
    523 	while (vlan) {
    524 		if (os_strcmp(ifname, vlan->ifname) != 0) {
    525 			prev = vlan;
    526 			vlan = vlan->next;
    527 			continue;
    528 		}
    529 		break;
    530 	}
    531 	if (!vlan)
    532 		return;
    533 
    534 	if (vlan->configured) {
    535 		int notempty = vlan->vlan_desc.notempty;
    536 		int untagged = vlan->vlan_desc.untagged;
    537 		int *tagged = vlan->vlan_desc.tagged;
    538 		char br_name[IFNAMSIZ];
    539 		int i;
    540 
    541 		for (i = 0; i < MAX_NUM_TAGGED_VLAN && tagged[i]; i++) {
    542 			if (tagged[i] == untagged ||
    543 			    tagged[i] <= 0 || tagged[i] > MAX_VLAN_ID ||
    544 			    (i > 0 && tagged[i] == tagged[i - 1]))
    545 				continue;
    546 			vlan_bridge_name(br_name, hapd, tagged[i]);
    547 			vlan_dellink_tagged(DYNAMIC_VLAN_NAMING_WITH_DEVICE,
    548 					    ifname, br_name, tagged[i], hapd);
    549 			vlan_put_bridge(br_name, hapd, tagged[i]);
    550 		}
    551 
    552 		if (!notempty) {
    553 			/* Non-VLAN STA */
    554 			if (hapd->conf->bridge[0] &&
    555 			    (vlan->clean & DVLAN_CLEAN_WLAN_PORT))
    556 				br_delif(hapd->conf->bridge, ifname);
    557 		} else if (untagged > 0 && untagged <= MAX_VLAN_ID) {
    558 			vlan_bridge_name(br_name, hapd, untagged);
    559 
    560 			if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
    561 				br_delif(br_name, vlan->ifname);
    562 
    563 			vlan_put_bridge(br_name, hapd, untagged);
    564 		}
    565 	}
    566 
    567 	/*
    568 	 * Ensure this VLAN interface is actually removed even if
    569 	 * NEWLINK message is only received later.
    570 	 */
    571 	if (if_nametoindex(vlan->ifname) && vlan_if_remove(hapd, vlan))
    572 		wpa_printf(MSG_ERROR,
    573 			   "VLAN: Could not remove VLAN iface: %s: %s",
    574 			   vlan->ifname, strerror(errno));
    575 
    576 	if (vlan == first)
    577 		hapd->conf->vlan = vlan->next;
    578 	else
    579 		prev->next = vlan->next;
    580 
    581 	os_free(vlan);
    582 }
    583 
    584 
    585 static void
    586 vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del,
    587 		  struct hostapd_data *hapd)
    588 {
    589 	struct ifinfomsg *ifi;
    590 	int attrlen, nlmsg_len, rta_len;
    591 	struct rtattr *attr;
    592 	char ifname[IFNAMSIZ + 1];
    593 
    594 	if (len < sizeof(*ifi))
    595 		return;
    596 
    597 	ifi = NLMSG_DATA(h);
    598 
    599 	nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg));
    600 
    601 	attrlen = h->nlmsg_len - nlmsg_len;
    602 	if (attrlen < 0)
    603 		return;
    604 
    605 	attr = (struct rtattr *) (((char *) ifi) + nlmsg_len);
    606 
    607 	os_memset(ifname, 0, sizeof(ifname));
    608 	rta_len = RTA_ALIGN(sizeof(struct rtattr));
    609 	while (RTA_OK(attr, attrlen)) {
    610 		if (attr->rta_type == IFLA_IFNAME) {
    611 			int n = attr->rta_len - rta_len;
    612 			if (n < 0)
    613 				break;
    614 
    615 			if ((size_t) n >= sizeof(ifname))
    616 				n = sizeof(ifname) - 1;
    617 			os_memcpy(ifname, ((char *) attr) + rta_len, n);
    618 
    619 		}
    620 
    621 		attr = RTA_NEXT(attr, attrlen);
    622 	}
    623 
    624 	if (!ifname[0])
    625 		return;
    626 	if (del && if_nametoindex(ifname)) {
    627 		 /* interface still exists, race condition ->
    628 		  * iface has just been recreated */
    629 		return;
    630 	}
    631 
    632 	wpa_printf(MSG_DEBUG,
    633 		   "VLAN: RTM_%sLINK: ifi_index=%d ifname=%s ifi_family=%d ifi_flags=0x%x (%s%s%s%s)",
    634 		   del ? "DEL" : "NEW",
    635 		   ifi->ifi_index, ifname, ifi->ifi_family, ifi->ifi_flags,
    636 		   (ifi->ifi_flags & IFF_UP) ? "[UP]" : "",
    637 		   (ifi->ifi_flags & IFF_RUNNING) ? "[RUNNING]" : "",
    638 		   (ifi->ifi_flags & IFF_LOWER_UP) ? "[LOWER_UP]" : "",
    639 		   (ifi->ifi_flags & IFF_DORMANT) ? "[DORMANT]" : "");
    640 
    641 	if (del)
    642 		vlan_dellink(ifname, hapd);
    643 	else
    644 		vlan_newlink(ifname, hapd);
    645 }
    646 
    647 
    648 static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx)
    649 {
    650 	char buf[8192];
    651 	int left;
    652 	struct sockaddr_nl from;
    653 	socklen_t fromlen;
    654 	struct nlmsghdr *h;
    655 	struct hostapd_data *hapd = eloop_ctx;
    656 
    657 	fromlen = sizeof(from);
    658 	left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT,
    659 			(struct sockaddr *) &from, &fromlen);
    660 	if (left < 0) {
    661 		if (errno != EINTR && errno != EAGAIN)
    662 			wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s",
    663 				   __func__, strerror(errno));
    664 		return;
    665 	}
    666 
    667 	h = (struct nlmsghdr *) buf;
    668 	while (NLMSG_OK(h, left)) {
    669 		int len, plen;
    670 
    671 		len = h->nlmsg_len;
    672 		plen = len - sizeof(*h);
    673 		if (len > left || plen < 0) {
    674 			wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink "
    675 				   "message: len=%d left=%d plen=%d",
    676 				   len, left, plen);
    677 			break;
    678 		}
    679 
    680 		switch (h->nlmsg_type) {
    681 		case RTM_NEWLINK:
    682 			vlan_read_ifnames(h, plen, 0, hapd);
    683 			break;
    684 		case RTM_DELLINK:
    685 			vlan_read_ifnames(h, plen, 1, hapd);
    686 			break;
    687 		}
    688 
    689 		h = NLMSG_NEXT(h, left);
    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 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 	vlan_set_name_type(hapd->conf->ssid.vlan_naming ==
    710 			   DYNAMIC_VLAN_NAMING_WITH_DEVICE ?
    711 			   VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD :
    712 			   VLAN_NAME_TYPE_PLUS_VID_NO_PAD);
    713 
    714 	priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    715 	if (priv->s < 0) {
    716 		wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW,"
    717 			   "NETLINK_ROUTE) failed: %s",
    718 			   __func__, strerror(errno));
    719 		os_free(priv);
    720 		return NULL;
    721 	}
    722 
    723 	os_memset(&local, 0, sizeof(local));
    724 	local.nl_family = AF_NETLINK;
    725 	local.nl_groups = RTMGRP_LINK;
    726 	if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) {
    727 		wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s",
    728 			   __func__, strerror(errno));
    729 		close(priv->s);
    730 		os_free(priv);
    731 		return NULL;
    732 	}
    733 
    734 	if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL))
    735 	{
    736 		close(priv->s);
    737 		os_free(priv);
    738 		return NULL;
    739 	}
    740 
    741 	return priv;
    742 }
    743 
    744 
    745 void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv)
    746 {
    747 	if (priv == NULL)
    748 		return;
    749 	eloop_unregister_read_sock(priv->s);
    750 	close(priv->s);
    751 	os_free(priv);
    752 }
    753