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