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@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 34struct 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 42struct 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 */ 53static 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 */ 90static 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 123static 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 163static 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 170static 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 190static 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*/ 241static 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 290static 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*/ 325static 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 375static 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 420int 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*/ 463int 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 530static 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 562static 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 633static 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 712static void 713vlan_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 775static 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 826static struct full_dynamic_vlan * 827full_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 874static 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 885int 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 911static 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 937static 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 961int 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 992void 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 1003struct 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 1047free_ifname: 1048 os_free(ifname); 1049 return n; 1050} 1051 1052 1053int 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