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