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