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 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 /** 478 * Increase the usage counter for given parent/ifname combination. 479 * If create is set, then this iface is added to the global list. 480 * Returns 481 * -1 on error 482 * 0 if iface is not in list 483 * 1 if iface is in list (was there or has been added) 484 */ 485 static int hapd_get_dynamic_iface(const char *parent, const char *ifname, 486 int create, struct hostapd_data *hapd) 487 { 488 size_t i; 489 struct hostapd_dynamic_iface *j = NULL, **tmp; 490 struct hapd_interfaces *hapd_global = hapd->iface->interfaces; 491 492 if (!parent) 493 parent = ""; 494 495 for (i = 0; i < hapd_global->count_dynamic; i++) { 496 j = hapd_global->dynamic_iface[i]; 497 if (os_strncmp(j->iface, ifname, sizeof(j->iface)) == 0 && 498 os_strncmp(j->parent, parent, sizeof(j->parent)) == 0) 499 break; 500 } 501 if (i < hapd_global->count_dynamic) { 502 j->usage++; 503 return 1; 504 } 505 506 /* new entry required */ 507 if (!create) 508 return 0; 509 510 j = os_zalloc(sizeof(*j)); 511 if (!j) 512 return -1; 513 os_strlcpy(j->iface, ifname, sizeof(j->iface)); 514 os_strlcpy(j->parent, parent, sizeof(j->parent)); 515 516 tmp = os_realloc_array(hapd_global->dynamic_iface, i + 1, 517 sizeof(*hapd_global->dynamic_iface)); 518 if (!tmp) { 519 wpa_printf(MSG_ERROR, "VLAN: Failed to allocate memory in %s", 520 __func__); 521 return -1; 522 } 523 hapd_global->count_dynamic++; 524 hapd_global->dynamic_iface = tmp; 525 hapd_global->dynamic_iface[i] = j; 526 527 return 1; 528 } 529 530 531 /** 532 * Decrease the usage counter for given ifname. 533 * Returns 534 * -1 on error or if iface was not found 535 * 0 if iface was found and is still present 536 * 1 if iface was removed from global list 537 */ 538 static int hapd_put_dynamic_iface(const char *parent, const char *ifname, 539 struct hostapd_data *hapd) 540 { 541 size_t i; 542 struct hostapd_dynamic_iface *j = NULL, **tmp; 543 struct hapd_interfaces *hapd_glob = hapd->iface->interfaces; 544 545 if (!parent) 546 parent = ""; 547 548 for (i = 0; i < hapd_glob->count_dynamic; i++) { 549 j = hapd_glob->dynamic_iface[i]; 550 if (os_strncmp(j->iface, ifname, sizeof(j->iface)) == 0 && 551 os_strncmp(j->parent, parent, sizeof(j->parent)) == 0) 552 break; 553 } 554 555 if (i == hapd_glob->count_dynamic) { 556 /* 557 * Interface not in global list. This can happen if alloc in 558 * _get_ failed. 559 */ 560 return -1; 561 } 562 563 if (j->usage > 0) { 564 j->usage--; 565 return 0; 566 } 567 568 os_free(j); 569 for (; i < hapd_glob->count_dynamic - 1; i++) 570 hapd_glob->dynamic_iface[i] = hapd_glob->dynamic_iface[i + 1]; 571 hapd_glob->dynamic_iface[hapd_glob->count_dynamic - 1] = NULL; 572 hapd_glob->count_dynamic--; 573 574 if (hapd_glob->count_dynamic == 0) { 575 os_free(hapd_glob->dynamic_iface); 576 hapd_glob->dynamic_iface = NULL; 577 return 1; 578 } 579 580 tmp = os_realloc_array(hapd_glob->dynamic_iface, 581 hapd_glob->count_dynamic, 582 sizeof(*hapd_glob->dynamic_iface)); 583 if (!tmp) { 584 wpa_printf(MSG_ERROR, "VLAN: Failed to release memory in %s", 585 __func__); 586 return -1; 587 } 588 hapd_glob->dynamic_iface = tmp; 589 590 return 1; 591 } 592 593 594 static void vlan_newlink(char *ifname, struct hostapd_data *hapd) 595 { 596 char vlan_ifname[IFNAMSIZ]; 597 char br_name[IFNAMSIZ]; 598 struct hostapd_vlan *vlan = hapd->conf->vlan; 599 char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; 600 int vlan_naming = hapd->conf->ssid.vlan_naming; 601 int ret; 602 603 wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname); 604 605 while (vlan) { 606 if (os_strcmp(ifname, vlan->ifname) == 0) { 607 608 if (hapd->conf->vlan_bridge[0]) { 609 os_snprintf(br_name, sizeof(br_name), "%s%d", 610 hapd->conf->vlan_bridge, 611 vlan->vlan_id); 612 } else if (tagged_interface) { 613 os_snprintf(br_name, sizeof(br_name), 614 "br%s.%d", tagged_interface, 615 vlan->vlan_id); 616 } else { 617 os_snprintf(br_name, sizeof(br_name), 618 "brvlan%d", vlan->vlan_id); 619 } 620 621 ret = br_addbr(br_name); 622 if (hapd_get_dynamic_iface(NULL, br_name, ret == 0, 623 hapd)) 624 vlan->clean |= DVLAN_CLEAN_BR; 625 626 ifconfig_up(br_name); 627 628 if (tagged_interface) { 629 if (vlan_naming == 630 DYNAMIC_VLAN_NAMING_WITH_DEVICE) 631 os_snprintf(vlan_ifname, 632 sizeof(vlan_ifname), 633 "%s.%d", tagged_interface, 634 vlan->vlan_id); 635 else 636 os_snprintf(vlan_ifname, 637 sizeof(vlan_ifname), 638 "vlan%d", vlan->vlan_id); 639 640 ifconfig_up(tagged_interface); 641 ret = vlan_add(tagged_interface, vlan->vlan_id, 642 vlan_ifname); 643 if (hapd_get_dynamic_iface(NULL, vlan_ifname, 644 ret == 0, hapd)) 645 vlan->clean |= DVLAN_CLEAN_VLAN; 646 647 ret = br_addif(br_name, vlan_ifname); 648 if (hapd_get_dynamic_iface(br_name, 649 vlan_ifname, 650 ret == 0, hapd)) 651 vlan->clean |= DVLAN_CLEAN_VLAN_PORT; 652 653 ifconfig_up(vlan_ifname); 654 } 655 656 ret = br_addif(br_name, ifname); 657 if (hapd_get_dynamic_iface(br_name, ifname, ret == 0, 658 hapd)) 659 vlan->clean |= DVLAN_CLEAN_WLAN_PORT; 660 661 ifconfig_up(ifname); 662 663 break; 664 } 665 vlan = vlan->next; 666 } 667 } 668 669 670 static void vlan_dellink(char *ifname, struct hostapd_data *hapd) 671 { 672 char vlan_ifname[IFNAMSIZ]; 673 char br_name[IFNAMSIZ]; 674 struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan; 675 char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; 676 int vlan_naming = hapd->conf->ssid.vlan_naming; 677 678 wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname); 679 680 first = prev = vlan; 681 682 while (vlan) { 683 if (os_strcmp(ifname, vlan->ifname) == 0) { 684 if (hapd->conf->vlan_bridge[0]) { 685 os_snprintf(br_name, sizeof(br_name), "%s%d", 686 hapd->conf->vlan_bridge, 687 vlan->vlan_id); 688 } else if (tagged_interface) { 689 os_snprintf(br_name, sizeof(br_name), 690 "br%s.%d", tagged_interface, 691 vlan->vlan_id); 692 } else { 693 os_snprintf(br_name, sizeof(br_name), 694 "brvlan%d", vlan->vlan_id); 695 } 696 697 if ((vlan->clean & DVLAN_CLEAN_WLAN_PORT) && 698 hapd_put_dynamic_iface(br_name, vlan->ifname, hapd)) 699 br_delif(br_name, vlan->ifname); 700 701 if (tagged_interface) { 702 if (vlan_naming == 703 DYNAMIC_VLAN_NAMING_WITH_DEVICE) 704 os_snprintf(vlan_ifname, 705 sizeof(vlan_ifname), 706 "%s.%d", tagged_interface, 707 vlan->vlan_id); 708 else 709 os_snprintf(vlan_ifname, 710 sizeof(vlan_ifname), 711 "vlan%d", vlan->vlan_id); 712 if ((vlan->clean & DVLAN_CLEAN_VLAN_PORT) && 713 hapd_put_dynamic_iface(br_name, vlan_ifname, 714 hapd)) 715 br_delif(br_name, vlan_ifname); 716 ifconfig_down(vlan_ifname); 717 718 if ((vlan->clean & DVLAN_CLEAN_VLAN) && 719 hapd_put_dynamic_iface(NULL, vlan_ifname, 720 hapd)) 721 vlan_rem(vlan_ifname); 722 } 723 724 if ((vlan->clean & DVLAN_CLEAN_BR) && 725 hapd_put_dynamic_iface(NULL, br_name, hapd) && 726 br_getnumports(br_name) == 0) { 727 ifconfig_down(br_name); 728 br_delbr(br_name); 729 } 730 731 if (vlan == first) { 732 hapd->conf->vlan = vlan->next; 733 } else { 734 prev->next = vlan->next; 735 } 736 os_free(vlan); 737 738 break; 739 } 740 prev = vlan; 741 vlan = vlan->next; 742 } 743 } 744 745 746 static void 747 vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del, 748 struct hostapd_data *hapd) 749 { 750 struct ifinfomsg *ifi; 751 int attrlen, nlmsg_len, rta_len; 752 struct rtattr *attr; 753 754 if (len < sizeof(*ifi)) 755 return; 756 757 ifi = NLMSG_DATA(h); 758 759 nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); 760 761 attrlen = h->nlmsg_len - nlmsg_len; 762 if (attrlen < 0) 763 return; 764 765 attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); 766 767 rta_len = RTA_ALIGN(sizeof(struct rtattr)); 768 while (RTA_OK(attr, attrlen)) { 769 char ifname[IFNAMSIZ + 1]; 770 771 if (attr->rta_type == IFLA_IFNAME) { 772 int n = attr->rta_len - rta_len; 773 if (n < 0) 774 break; 775 776 os_memset(ifname, 0, sizeof(ifname)); 777 778 if ((size_t) n > sizeof(ifname)) 779 n = sizeof(ifname); 780 os_memcpy(ifname, ((char *) attr) + rta_len, n); 781 782 if (del) 783 vlan_dellink(ifname, hapd); 784 else 785 vlan_newlink(ifname, hapd); 786 } 787 788 attr = RTA_NEXT(attr, attrlen); 789 } 790 } 791 792 793 static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx) 794 { 795 char buf[8192]; 796 int left; 797 struct sockaddr_nl from; 798 socklen_t fromlen; 799 struct nlmsghdr *h; 800 struct hostapd_data *hapd = eloop_ctx; 801 802 fromlen = sizeof(from); 803 left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, 804 (struct sockaddr *) &from, &fromlen); 805 if (left < 0) { 806 if (errno != EINTR && errno != EAGAIN) 807 wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s", 808 __func__, strerror(errno)); 809 return; 810 } 811 812 h = (struct nlmsghdr *) buf; 813 while (left >= (int) sizeof(*h)) { 814 int len, plen; 815 816 len = h->nlmsg_len; 817 plen = len - sizeof(*h); 818 if (len > left || plen < 0) { 819 wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink " 820 "message: len=%d left=%d plen=%d", 821 len, left, plen); 822 break; 823 } 824 825 switch (h->nlmsg_type) { 826 case RTM_NEWLINK: 827 vlan_read_ifnames(h, plen, 0, hapd); 828 break; 829 case RTM_DELLINK: 830 vlan_read_ifnames(h, plen, 1, hapd); 831 break; 832 } 833 834 len = NLMSG_ALIGN(len); 835 left -= len; 836 h = (struct nlmsghdr *) ((char *) h + len); 837 } 838 839 if (left > 0) { 840 wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of " 841 "netlink message", __func__, left); 842 } 843 } 844 845 846 static struct full_dynamic_vlan * 847 full_dynamic_vlan_init(struct hostapd_data *hapd) 848 { 849 struct sockaddr_nl local; 850 struct full_dynamic_vlan *priv; 851 852 priv = os_zalloc(sizeof(*priv)); 853 if (priv == NULL) 854 return NULL; 855 856 #ifndef CONFIG_VLAN_NETLINK 857 vlan_set_name_type(hapd->conf->ssid.vlan_naming == 858 DYNAMIC_VLAN_NAMING_WITH_DEVICE ? 859 VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD : 860 VLAN_NAME_TYPE_PLUS_VID_NO_PAD); 861 #endif /* CONFIG_VLAN_NETLINK */ 862 863 priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 864 if (priv->s < 0) { 865 wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW," 866 "NETLINK_ROUTE) failed: %s", 867 __func__, strerror(errno)); 868 os_free(priv); 869 return NULL; 870 } 871 872 os_memset(&local, 0, sizeof(local)); 873 local.nl_family = AF_NETLINK; 874 local.nl_groups = RTMGRP_LINK; 875 if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) { 876 wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s", 877 __func__, strerror(errno)); 878 close(priv->s); 879 os_free(priv); 880 return NULL; 881 } 882 883 if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL)) 884 { 885 close(priv->s); 886 os_free(priv); 887 return NULL; 888 } 889 890 return priv; 891 } 892 893 894 static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv) 895 { 896 if (priv == NULL) 897 return; 898 eloop_unregister_read_sock(priv->s); 899 close(priv->s); 900 os_free(priv); 901 } 902 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 903 904 905 int vlan_setup_encryption_dyn(struct hostapd_data *hapd, 906 struct hostapd_ssid *mssid, const char *dyn_vlan) 907 { 908 int i; 909 910 if (dyn_vlan == NULL) 911 return 0; 912 913 /* Static WEP keys are set here; IEEE 802.1X and WPA uses their own 914 * functions for setting up dynamic broadcast keys. */ 915 for (i = 0; i < 4; i++) { 916 if (mssid->wep.key[i] && 917 hostapd_drv_set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i, 918 i == mssid->wep.idx, NULL, 0, 919 mssid->wep.key[i], mssid->wep.len[i])) 920 { 921 wpa_printf(MSG_ERROR, "VLAN: Could not set WEP " 922 "encryption for dynamic VLAN"); 923 return -1; 924 } 925 } 926 927 return 0; 928 } 929 930 931 static int vlan_dynamic_add(struct hostapd_data *hapd, 932 struct hostapd_vlan *vlan) 933 { 934 while (vlan) { 935 if (vlan->vlan_id != VLAN_ID_WILDCARD) { 936 if (hostapd_vlan_if_add(hapd, vlan->ifname)) { 937 if (errno != EEXIST) { 938 wpa_printf(MSG_ERROR, "VLAN: Could " 939 "not add VLAN %s: %s", 940 vlan->ifname, 941 strerror(errno)); 942 return -1; 943 } 944 } 945 #ifdef CONFIG_FULL_DYNAMIC_VLAN 946 ifconfig_up(vlan->ifname); 947 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 948 } 949 950 vlan = vlan->next; 951 } 952 953 return 0; 954 } 955 956 957 static void vlan_dynamic_remove(struct hostapd_data *hapd, 958 struct hostapd_vlan *vlan) 959 { 960 struct hostapd_vlan *next; 961 962 while (vlan) { 963 next = vlan->next; 964 965 if (vlan->vlan_id != VLAN_ID_WILDCARD && 966 hostapd_vlan_if_remove(hapd, vlan->ifname)) { 967 wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN " 968 "iface: %s: %s", 969 vlan->ifname, strerror(errno)); 970 } 971 #ifdef CONFIG_FULL_DYNAMIC_VLAN 972 if (vlan->clean) 973 vlan_dellink(vlan->ifname, hapd); 974 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 975 976 vlan = next; 977 } 978 } 979 980 981 int vlan_init(struct hostapd_data *hapd) 982 { 983 #ifdef CONFIG_FULL_DYNAMIC_VLAN 984 hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd); 985 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 986 987 if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED && 988 !hapd->conf->vlan) { 989 /* dynamic vlans enabled but no (or empty) vlan_file given */ 990 struct hostapd_vlan *vlan; 991 vlan = os_zalloc(sizeof(*vlan)); 992 if (vlan == NULL) { 993 wpa_printf(MSG_ERROR, "Out of memory while assigning " 994 "VLAN interfaces"); 995 return -1; 996 } 997 998 vlan->vlan_id = VLAN_ID_WILDCARD; 999 os_snprintf(vlan->ifname, sizeof(vlan->ifname), "%s.#", 1000 hapd->conf->iface); 1001 vlan->next = hapd->conf->vlan; 1002 hapd->conf->vlan = vlan; 1003 } 1004 1005 if (vlan_dynamic_add(hapd, hapd->conf->vlan)) 1006 return -1; 1007 1008 return 0; 1009 } 1010 1011 1012 void vlan_deinit(struct hostapd_data *hapd) 1013 { 1014 vlan_dynamic_remove(hapd, hapd->conf->vlan); 1015 1016 #ifdef CONFIG_FULL_DYNAMIC_VLAN 1017 full_dynamic_vlan_deinit(hapd->full_dynamic_vlan); 1018 hapd->full_dynamic_vlan = NULL; 1019 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 1020 } 1021 1022 1023 struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, 1024 struct hostapd_vlan *vlan, 1025 int vlan_id) 1026 { 1027 struct hostapd_vlan *n; 1028 char *ifname, *pos; 1029 1030 if (vlan == NULL || vlan_id <= 0 || vlan_id > MAX_VLAN_ID || 1031 vlan->vlan_id != VLAN_ID_WILDCARD) 1032 return NULL; 1033 1034 wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)", 1035 __func__, vlan_id, vlan->ifname); 1036 ifname = os_strdup(vlan->ifname); 1037 if (ifname == NULL) 1038 return NULL; 1039 pos = os_strchr(ifname, '#'); 1040 if (pos == NULL) { 1041 os_free(ifname); 1042 return NULL; 1043 } 1044 *pos++ = '\0'; 1045 1046 n = os_zalloc(sizeof(*n)); 1047 if (n == NULL) { 1048 os_free(ifname); 1049 return NULL; 1050 } 1051 1052 n->vlan_id = vlan_id; 1053 n->dynamic_vlan = 1; 1054 1055 os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id, 1056 pos); 1057 os_free(ifname); 1058 1059 if (hostapd_vlan_if_add(hapd, n->ifname)) { 1060 os_free(n); 1061 return NULL; 1062 } 1063 1064 n->next = hapd->conf->vlan; 1065 hapd->conf->vlan = n; 1066 1067 #ifdef CONFIG_FULL_DYNAMIC_VLAN 1068 ifconfig_up(n->ifname); 1069 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 1070 1071 return n; 1072 } 1073 1074 1075 int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id) 1076 { 1077 struct hostapd_vlan *vlan; 1078 1079 if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID) 1080 return 1; 1081 1082 wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d)", __func__, vlan_id); 1083 1084 vlan = hapd->conf->vlan; 1085 while (vlan) { 1086 if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) { 1087 vlan->dynamic_vlan--; 1088 break; 1089 } 1090 vlan = vlan->next; 1091 } 1092 1093 if (vlan == NULL) 1094 return 1; 1095 1096 if (vlan->dynamic_vlan == 0) 1097 hostapd_vlan_if_remove(hapd, vlan->ifname); 1098 1099 return 0; 1100 } 1101