$search
00001 /* 00002 * hostapd / VLAN initialization 00003 * Copyright 2003, Instant802 Networks, Inc. 00004 * Copyright 2005-2006, Devicescape Software, Inc. 00005 * Copyright (c) 2009, Jouni Malinen <j@w1.fi> 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License version 2 as 00009 * published by the Free Software Foundation. 00010 * 00011 * Alternatively, this software may be distributed under the terms of BSD 00012 * license. 00013 * 00014 * See README and COPYING for more details. 00015 */ 00016 00017 #include "utils/includes.h" 00018 00019 #include "utils/common.h" 00020 #include "hostapd.h" 00021 #include "ap_config.h" 00022 #include "vlan_init.h" 00023 00024 00025 #ifdef CONFIG_FULL_DYNAMIC_VLAN 00026 00027 #include <net/if.h> 00028 #include <sys/ioctl.h> 00029 #include <linux/sockios.h> 00030 #include <linux/if_vlan.h> 00031 #include <linux/if_bridge.h> 00032 00033 #include "drivers/priv_netlink.h" 00034 #include "utils/eloop.h" 00035 00036 00037 struct full_dynamic_vlan { 00038 int s; /* socket on which to listen for new/removed interfaces. */ 00039 }; 00040 00041 00042 static int ifconfig_helper(const char *if_name, int up) 00043 { 00044 int fd; 00045 struct ifreq ifr; 00046 00047 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 00048 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " 00049 "failed: %s", __func__, strerror(errno)); 00050 return -1; 00051 } 00052 00053 os_memset(&ifr, 0, sizeof(ifr)); 00054 os_strlcpy(ifr.ifr_name, if_name, IFNAMSIZ); 00055 00056 if (ioctl(fd, SIOCGIFFLAGS, &ifr) != 0) { 00057 wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCGIFFLAGS) failed " 00058 "for interface %s: %s", 00059 __func__, if_name, strerror(errno)); 00060 close(fd); 00061 return -1; 00062 } 00063 00064 if (up) 00065 ifr.ifr_flags |= IFF_UP; 00066 else 00067 ifr.ifr_flags &= ~IFF_UP; 00068 00069 if (ioctl(fd, SIOCSIFFLAGS, &ifr) != 0) { 00070 wpa_printf(MSG_ERROR, "VLAN: %s: ioctl(SIOCSIFFLAGS) failed " 00071 "for interface %s (up=%d): %s", 00072 __func__, if_name, up, strerror(errno)); 00073 close(fd); 00074 return -1; 00075 } 00076 00077 close(fd); 00078 return 0; 00079 } 00080 00081 00082 static int ifconfig_up(const char *if_name) 00083 { 00084 wpa_printf(MSG_DEBUG, "VLAN: Set interface %s up", if_name); 00085 return ifconfig_helper(if_name, 1); 00086 } 00087 00088 00089 static int ifconfig_down(const char *if_name) 00090 { 00091 wpa_printf(MSG_DEBUG, "VLAN: Set interface %s down", if_name); 00092 return ifconfig_helper(if_name, 0); 00093 } 00094 00095 00096 /* 00097 * These are only available in recent linux headers (without the leading 00098 * underscore). 00099 */ 00100 #define _GET_VLAN_REALDEV_NAME_CMD 8 00101 #define _GET_VLAN_VID_CMD 9 00102 00103 /* This value should be 256 ONLY. If it is something else, then hostapd 00104 * might crash!, as this value has been hard-coded in 2.4.x kernel 00105 * bridging code. 00106 */ 00107 #define MAX_BR_PORTS 256 00108 00109 static int br_delif(const char *br_name, const char *if_name) 00110 { 00111 int fd; 00112 struct ifreq ifr; 00113 unsigned long args[2]; 00114 int if_index; 00115 00116 wpa_printf(MSG_DEBUG, "VLAN: br_delif(%s, %s)", br_name, if_name); 00117 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 00118 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " 00119 "failed: %s", __func__, strerror(errno)); 00120 return -1; 00121 } 00122 00123 if_index = if_nametoindex(if_name); 00124 00125 if (if_index == 0) { 00126 wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining " 00127 "interface index for '%s'", 00128 __func__, if_name); 00129 close(fd); 00130 return -1; 00131 } 00132 00133 args[0] = BRCTL_DEL_IF; 00134 args[1] = if_index; 00135 00136 os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); 00137 ifr.ifr_data = (__caddr_t) args; 00138 00139 if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0 && errno != EINVAL) { 00140 /* No error if interface already removed. */ 00141 wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE," 00142 "BRCTL_DEL_IF] failed for br_name=%s if_name=%s: " 00143 "%s", __func__, br_name, if_name, strerror(errno)); 00144 close(fd); 00145 return -1; 00146 } 00147 00148 close(fd); 00149 return 0; 00150 } 00151 00152 00153 /* 00154 Add interface 'if_name' to the bridge 'br_name' 00155 00156 returns -1 on error 00157 returns 1 if the interface is already part of the bridge 00158 returns 0 otherwise 00159 */ 00160 static int br_addif(const char *br_name, const char *if_name) 00161 { 00162 int fd; 00163 struct ifreq ifr; 00164 unsigned long args[2]; 00165 int if_index; 00166 00167 wpa_printf(MSG_DEBUG, "VLAN: br_addif(%s, %s)", br_name, if_name); 00168 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 00169 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " 00170 "failed: %s", __func__, strerror(errno)); 00171 return -1; 00172 } 00173 00174 if_index = if_nametoindex(if_name); 00175 00176 if (if_index == 0) { 00177 wpa_printf(MSG_ERROR, "VLAN: %s: Failure determining " 00178 "interface index for '%s'", 00179 __func__, if_name); 00180 close(fd); 00181 return -1; 00182 } 00183 00184 args[0] = BRCTL_ADD_IF; 00185 args[1] = if_index; 00186 00187 os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); 00188 ifr.ifr_data = (__caddr_t) args; 00189 00190 if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { 00191 if (errno == EBUSY) { 00192 /* The interface is already added. */ 00193 close(fd); 00194 return 1; 00195 } 00196 00197 wpa_printf(MSG_ERROR, "VLAN: %s: ioctl[SIOCDEVPRIVATE," 00198 "BRCTL_ADD_IF] failed for br_name=%s if_name=%s: " 00199 "%s", __func__, br_name, if_name, strerror(errno)); 00200 close(fd); 00201 return -1; 00202 } 00203 00204 close(fd); 00205 return 0; 00206 } 00207 00208 00209 static int br_delbr(const char *br_name) 00210 { 00211 int fd; 00212 unsigned long arg[2]; 00213 00214 wpa_printf(MSG_DEBUG, "VLAN: br_delbr(%s)", br_name); 00215 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 00216 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " 00217 "failed: %s", __func__, strerror(errno)); 00218 return -1; 00219 } 00220 00221 arg[0] = BRCTL_DEL_BRIDGE; 00222 arg[1] = (unsigned long) br_name; 00223 00224 if (ioctl(fd, SIOCGIFBR, arg) < 0 && errno != ENXIO) { 00225 /* No error if bridge already removed. */ 00226 wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_DEL_BRIDGE failed for " 00227 "%s: %s", __func__, br_name, strerror(errno)); 00228 close(fd); 00229 return -1; 00230 } 00231 00232 close(fd); 00233 return 0; 00234 } 00235 00236 00237 /* 00238 Add a bridge with the name 'br_name'. 00239 00240 returns -1 on error 00241 returns 1 if the bridge already exists 00242 returns 0 otherwise 00243 */ 00244 static int br_addbr(const char *br_name) 00245 { 00246 int fd; 00247 unsigned long arg[4]; 00248 struct ifreq ifr; 00249 00250 wpa_printf(MSG_DEBUG, "VLAN: br_addbr(%s)", br_name); 00251 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 00252 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " 00253 "failed: %s", __func__, strerror(errno)); 00254 return -1; 00255 } 00256 00257 arg[0] = BRCTL_ADD_BRIDGE; 00258 arg[1] = (unsigned long) br_name; 00259 00260 if (ioctl(fd, SIOCGIFBR, arg) < 0) { 00261 if (errno == EEXIST) { 00262 /* The bridge is already added. */ 00263 close(fd); 00264 return 1; 00265 } else { 00266 wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_ADD_BRIDGE " 00267 "failed for %s: %s", 00268 __func__, br_name, strerror(errno)); 00269 close(fd); 00270 return -1; 00271 } 00272 } 00273 00274 /* Decrease forwarding delay to avoid EAPOL timeouts. */ 00275 os_memset(&ifr, 0, sizeof(ifr)); 00276 os_strlcpy(ifr.ifr_name, br_name, IFNAMSIZ); 00277 arg[0] = BRCTL_SET_BRIDGE_FORWARD_DELAY; 00278 arg[1] = 1; 00279 arg[2] = 0; 00280 arg[3] = 0; 00281 ifr.ifr_data = (char *) &arg; 00282 if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { 00283 wpa_printf(MSG_ERROR, "VLAN: %s: " 00284 "BRCTL_SET_BRIDGE_FORWARD_DELAY (1 sec) failed for " 00285 "%s: %s", __func__, br_name, strerror(errno)); 00286 /* Continue anyway */ 00287 } 00288 00289 close(fd); 00290 return 0; 00291 } 00292 00293 00294 static int br_getnumports(const char *br_name) 00295 { 00296 int fd; 00297 int i; 00298 int port_cnt = 0; 00299 unsigned long arg[4]; 00300 int ifindices[MAX_BR_PORTS]; 00301 struct ifreq ifr; 00302 00303 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 00304 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " 00305 "failed: %s", __func__, strerror(errno)); 00306 return -1; 00307 } 00308 00309 arg[0] = BRCTL_GET_PORT_LIST; 00310 arg[1] = (unsigned long) ifindices; 00311 arg[2] = MAX_BR_PORTS; 00312 arg[3] = 0; 00313 00314 os_memset(ifindices, 0, sizeof(ifindices)); 00315 os_strlcpy(ifr.ifr_name, br_name, sizeof(ifr.ifr_name)); 00316 ifr.ifr_data = (__caddr_t) arg; 00317 00318 if (ioctl(fd, SIOCDEVPRIVATE, &ifr) < 0) { 00319 wpa_printf(MSG_ERROR, "VLAN: %s: BRCTL_GET_PORT_LIST " 00320 "failed for %s: %s", 00321 __func__, br_name, strerror(errno)); 00322 close(fd); 00323 return -1; 00324 } 00325 00326 for (i = 1; i < MAX_BR_PORTS; i++) { 00327 if (ifindices[i] > 0) { 00328 port_cnt++; 00329 } 00330 } 00331 00332 close(fd); 00333 return port_cnt; 00334 } 00335 00336 00337 static int vlan_rem(const char *if_name) 00338 { 00339 int fd; 00340 struct vlan_ioctl_args if_request; 00341 00342 wpa_printf(MSG_DEBUG, "VLAN: vlan_rem(%s)", if_name); 00343 if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) { 00344 wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", 00345 if_name); 00346 return -1; 00347 } 00348 00349 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 00350 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " 00351 "failed: %s", __func__, strerror(errno)); 00352 return -1; 00353 } 00354 00355 os_memset(&if_request, 0, sizeof(if_request)); 00356 00357 os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1)); 00358 if_request.cmd = DEL_VLAN_CMD; 00359 00360 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 00361 wpa_printf(MSG_ERROR, "VLAN: %s: DEL_VLAN_CMD failed for %s: " 00362 "%s", __func__, if_name, strerror(errno)); 00363 close(fd); 00364 return -1; 00365 } 00366 00367 close(fd); 00368 return 0; 00369 } 00370 00371 00372 /* 00373 Add a vlan interface with VLAN ID 'vid' and tagged interface 00374 'if_name'. 00375 00376 returns -1 on error 00377 returns 1 if the interface already exists 00378 returns 0 otherwise 00379 */ 00380 static int vlan_add(const char *if_name, int vid) 00381 { 00382 int fd; 00383 struct vlan_ioctl_args if_request; 00384 00385 wpa_printf(MSG_DEBUG, "VLAN: vlan_add(if_name=%s, vid=%d)", 00386 if_name, vid); 00387 ifconfig_up(if_name); 00388 00389 if ((os_strlen(if_name) + 1) > sizeof(if_request.device1)) { 00390 wpa_printf(MSG_ERROR, "VLAN: Interface name too long: '%s'", 00391 if_name); 00392 return -1; 00393 } 00394 00395 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 00396 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " 00397 "failed: %s", __func__, strerror(errno)); 00398 return -1; 00399 } 00400 00401 os_memset(&if_request, 0, sizeof(if_request)); 00402 00403 /* Determine if a suitable vlan device already exists. */ 00404 00405 os_snprintf(if_request.device1, sizeof(if_request.device1), "vlan%d", 00406 vid); 00407 00408 if_request.cmd = _GET_VLAN_VID_CMD; 00409 00410 if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0) { 00411 00412 if (if_request.u.VID == vid) { 00413 if_request.cmd = _GET_VLAN_REALDEV_NAME_CMD; 00414 00415 if (ioctl(fd, SIOCSIFVLAN, &if_request) == 0 && 00416 os_strncmp(if_request.u.device2, if_name, 00417 sizeof(if_request.u.device2)) == 0) { 00418 close(fd); 00419 wpa_printf(MSG_DEBUG, "VLAN: vlan_add: " 00420 "if_name %s exists already", 00421 if_request.device1); 00422 return 1; 00423 } 00424 } 00425 } 00426 00427 /* A suitable vlan device does not already exist, add one. */ 00428 00429 os_memset(&if_request, 0, sizeof(if_request)); 00430 os_strlcpy(if_request.device1, if_name, sizeof(if_request.device1)); 00431 if_request.u.VID = vid; 00432 if_request.cmd = ADD_VLAN_CMD; 00433 00434 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 00435 wpa_printf(MSG_ERROR, "VLAN: %s: ADD_VLAN_CMD failed for %s: " 00436 "%s", 00437 __func__, if_request.device1, strerror(errno)); 00438 close(fd); 00439 return -1; 00440 } 00441 00442 close(fd); 00443 return 0; 00444 } 00445 00446 00447 static int vlan_set_name_type(unsigned int name_type) 00448 { 00449 int fd; 00450 struct vlan_ioctl_args if_request; 00451 00452 wpa_printf(MSG_DEBUG, "VLAN: vlan_set_name_type(name_type=%u)", 00453 name_type); 00454 if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 00455 wpa_printf(MSG_ERROR, "VLAN: %s: socket(AF_INET,SOCK_STREAM) " 00456 "failed: %s", __func__, strerror(errno)); 00457 return -1; 00458 } 00459 00460 os_memset(&if_request, 0, sizeof(if_request)); 00461 00462 if_request.u.name_type = name_type; 00463 if_request.cmd = SET_VLAN_NAME_TYPE_CMD; 00464 if (ioctl(fd, SIOCSIFVLAN, &if_request) < 0) { 00465 wpa_printf(MSG_ERROR, "VLAN: %s: SET_VLAN_NAME_TYPE_CMD " 00466 "name_type=%u failed: %s", 00467 __func__, name_type, strerror(errno)); 00468 close(fd); 00469 return -1; 00470 } 00471 00472 close(fd); 00473 return 0; 00474 } 00475 00476 00477 static void vlan_newlink(char *ifname, struct hostapd_data *hapd) 00478 { 00479 char vlan_ifname[IFNAMSIZ]; 00480 char br_name[IFNAMSIZ]; 00481 struct hostapd_vlan *vlan = hapd->conf->vlan; 00482 char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; 00483 00484 wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname); 00485 00486 while (vlan) { 00487 if (os_strcmp(ifname, vlan->ifname) == 0) { 00488 00489 os_snprintf(br_name, sizeof(br_name), "brvlan%d", 00490 vlan->vlan_id); 00491 00492 if (!br_addbr(br_name)) 00493 vlan->clean |= DVLAN_CLEAN_BR; 00494 00495 ifconfig_up(br_name); 00496 00497 if (tagged_interface) { 00498 00499 if (!vlan_add(tagged_interface, vlan->vlan_id)) 00500 vlan->clean |= DVLAN_CLEAN_VLAN; 00501 00502 os_snprintf(vlan_ifname, sizeof(vlan_ifname), 00503 "vlan%d", vlan->vlan_id); 00504 00505 if (!br_addif(br_name, vlan_ifname)) 00506 vlan->clean |= DVLAN_CLEAN_VLAN_PORT; 00507 00508 ifconfig_up(vlan_ifname); 00509 } 00510 00511 if (!br_addif(br_name, ifname)) 00512 vlan->clean |= DVLAN_CLEAN_WLAN_PORT; 00513 00514 ifconfig_up(ifname); 00515 00516 break; 00517 } 00518 vlan = vlan->next; 00519 } 00520 } 00521 00522 00523 static void vlan_dellink(char *ifname, struct hostapd_data *hapd) 00524 { 00525 char vlan_ifname[IFNAMSIZ]; 00526 char br_name[IFNAMSIZ]; 00527 struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan; 00528 char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; 00529 00530 wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname); 00531 00532 first = prev = vlan; 00533 00534 while (vlan) { 00535 if (os_strcmp(ifname, vlan->ifname) == 0) { 00536 os_snprintf(br_name, sizeof(br_name), "brvlan%d", 00537 vlan->vlan_id); 00538 00539 if (vlan->clean & DVLAN_CLEAN_WLAN_PORT) 00540 br_delif(br_name, vlan->ifname); 00541 00542 if (tagged_interface) { 00543 os_snprintf(vlan_ifname, sizeof(vlan_ifname), 00544 "vlan%d", vlan->vlan_id); 00545 if (vlan->clean & DVLAN_CLEAN_VLAN_PORT) 00546 br_delif(br_name, vlan_ifname); 00547 ifconfig_down(vlan_ifname); 00548 00549 if (vlan->clean & DVLAN_CLEAN_VLAN) 00550 vlan_rem(vlan_ifname); 00551 } 00552 00553 if ((vlan->clean & DVLAN_CLEAN_BR) && 00554 br_getnumports(br_name) == 0) { 00555 ifconfig_down(br_name); 00556 br_delbr(br_name); 00557 } 00558 00559 if (vlan == first) { 00560 hapd->conf->vlan = vlan->next; 00561 } else { 00562 prev->next = vlan->next; 00563 } 00564 os_free(vlan); 00565 00566 break; 00567 } 00568 prev = vlan; 00569 vlan = vlan->next; 00570 } 00571 } 00572 00573 00574 static void 00575 vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del, 00576 struct hostapd_data *hapd) 00577 { 00578 struct ifinfomsg *ifi; 00579 int attrlen, nlmsg_len, rta_len; 00580 struct rtattr *attr; 00581 00582 if (len < sizeof(*ifi)) 00583 return; 00584 00585 ifi = NLMSG_DATA(h); 00586 00587 nlmsg_len = NLMSG_ALIGN(sizeof(struct ifinfomsg)); 00588 00589 attrlen = h->nlmsg_len - nlmsg_len; 00590 if (attrlen < 0) 00591 return; 00592 00593 attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); 00594 00595 rta_len = RTA_ALIGN(sizeof(struct rtattr)); 00596 while (RTA_OK(attr, attrlen)) { 00597 char ifname[IFNAMSIZ + 1]; 00598 00599 if (attr->rta_type == IFLA_IFNAME) { 00600 int n = attr->rta_len - rta_len; 00601 if (n < 0) 00602 break; 00603 00604 os_memset(ifname, 0, sizeof(ifname)); 00605 00606 if ((size_t) n > sizeof(ifname)) 00607 n = sizeof(ifname); 00608 os_memcpy(ifname, ((char *) attr) + rta_len, n); 00609 00610 if (del) 00611 vlan_dellink(ifname, hapd); 00612 else 00613 vlan_newlink(ifname, hapd); 00614 } 00615 00616 attr = RTA_NEXT(attr, attrlen); 00617 } 00618 } 00619 00620 00621 static void vlan_event_receive(int sock, void *eloop_ctx, void *sock_ctx) 00622 { 00623 char buf[8192]; 00624 int left; 00625 struct sockaddr_nl from; 00626 socklen_t fromlen; 00627 struct nlmsghdr *h; 00628 struct hostapd_data *hapd = eloop_ctx; 00629 00630 fromlen = sizeof(from); 00631 left = recvfrom(sock, buf, sizeof(buf), MSG_DONTWAIT, 00632 (struct sockaddr *) &from, &fromlen); 00633 if (left < 0) { 00634 if (errno != EINTR && errno != EAGAIN) 00635 wpa_printf(MSG_ERROR, "VLAN: %s: recvfrom failed: %s", 00636 __func__, strerror(errno)); 00637 return; 00638 } 00639 00640 h = (struct nlmsghdr *) buf; 00641 while (left >= (int) sizeof(*h)) { 00642 int len, plen; 00643 00644 len = h->nlmsg_len; 00645 plen = len - sizeof(*h); 00646 if (len > left || plen < 0) { 00647 wpa_printf(MSG_DEBUG, "VLAN: Malformed netlink " 00648 "message: len=%d left=%d plen=%d", 00649 len, left, plen); 00650 break; 00651 } 00652 00653 switch (h->nlmsg_type) { 00654 case RTM_NEWLINK: 00655 vlan_read_ifnames(h, plen, 0, hapd); 00656 break; 00657 case RTM_DELLINK: 00658 vlan_read_ifnames(h, plen, 1, hapd); 00659 break; 00660 } 00661 00662 len = NLMSG_ALIGN(len); 00663 left -= len; 00664 h = (struct nlmsghdr *) ((char *) h + len); 00665 } 00666 00667 if (left > 0) { 00668 wpa_printf(MSG_DEBUG, "VLAN: %s: %d extra bytes in the end of " 00669 "netlink message", __func__, left); 00670 } 00671 } 00672 00673 00674 static struct full_dynamic_vlan * 00675 full_dynamic_vlan_init(struct hostapd_data *hapd) 00676 { 00677 struct sockaddr_nl local; 00678 struct full_dynamic_vlan *priv; 00679 00680 priv = os_zalloc(sizeof(*priv)); 00681 if (priv == NULL) 00682 return NULL; 00683 00684 vlan_set_name_type(VLAN_NAME_TYPE_PLUS_VID_NO_PAD); 00685 00686 priv->s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 00687 if (priv->s < 0) { 00688 wpa_printf(MSG_ERROR, "VLAN: %s: socket(PF_NETLINK,SOCK_RAW," 00689 "NETLINK_ROUTE) failed: %s", 00690 __func__, strerror(errno)); 00691 os_free(priv); 00692 return NULL; 00693 } 00694 00695 os_memset(&local, 0, sizeof(local)); 00696 local.nl_family = AF_NETLINK; 00697 local.nl_groups = RTMGRP_LINK; 00698 if (bind(priv->s, (struct sockaddr *) &local, sizeof(local)) < 0) { 00699 wpa_printf(MSG_ERROR, "VLAN: %s: bind(netlink) failed: %s", 00700 __func__, strerror(errno)); 00701 close(priv->s); 00702 os_free(priv); 00703 return NULL; 00704 } 00705 00706 if (eloop_register_read_sock(priv->s, vlan_event_receive, hapd, NULL)) 00707 { 00708 close(priv->s); 00709 os_free(priv); 00710 return NULL; 00711 } 00712 00713 return priv; 00714 } 00715 00716 00717 static void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv) 00718 { 00719 if (priv == NULL) 00720 return; 00721 eloop_unregister_read_sock(priv->s); 00722 close(priv->s); 00723 os_free(priv); 00724 } 00725 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 00726 00727 00728 int vlan_setup_encryption_dyn(struct hostapd_data *hapd, 00729 struct hostapd_ssid *mssid, const char *dyn_vlan) 00730 { 00731 int i; 00732 00733 if (dyn_vlan == NULL) 00734 return 0; 00735 00736 /* Static WEP keys are set here; IEEE 802.1X and WPA uses their own 00737 * functions for setting up dynamic broadcast keys. */ 00738 for (i = 0; i < 4; i++) { 00739 if (mssid->wep.key[i] && 00740 hapd->drv.set_key(dyn_vlan, hapd, WPA_ALG_WEP, NULL, i, 00741 i == mssid->wep.idx, NULL, 0, 00742 mssid->wep.key[i], mssid->wep.len[i])) { 00743 wpa_printf(MSG_ERROR, "VLAN: Could not set WEP " 00744 "encryption for dynamic VLAN"); 00745 return -1; 00746 } 00747 } 00748 00749 return 0; 00750 } 00751 00752 00753 static int vlan_dynamic_add(struct hostapd_data *hapd, 00754 struct hostapd_vlan *vlan) 00755 { 00756 while (vlan) { 00757 if (vlan->vlan_id != VLAN_ID_WILDCARD) { 00758 if (hapd->drv.vlan_if_add(hapd, vlan->ifname)) { 00759 if (errno != EEXIST) { 00760 wpa_printf(MSG_ERROR, "VLAN: Could " 00761 "not add VLAN %s: %s", 00762 vlan->ifname, 00763 strerror(errno)); 00764 return -1; 00765 } 00766 } 00767 #ifdef CONFIG_FULL_DYNAMIC_VLAN 00768 ifconfig_up(vlan->ifname); 00769 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 00770 } 00771 00772 vlan = vlan->next; 00773 } 00774 00775 return 0; 00776 } 00777 00778 00779 static void vlan_dynamic_remove(struct hostapd_data *hapd, 00780 struct hostapd_vlan *vlan) 00781 { 00782 struct hostapd_vlan *next; 00783 00784 while (vlan) { 00785 next = vlan->next; 00786 00787 if (vlan->vlan_id != VLAN_ID_WILDCARD && 00788 hapd->drv.vlan_if_remove(hapd, vlan->ifname)) { 00789 wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN " 00790 "iface: %s: %s", 00791 vlan->ifname, strerror(errno)); 00792 } 00793 #ifdef CONFIG_FULL_DYNAMIC_VLAN 00794 if (vlan->clean) 00795 vlan_dellink(vlan->ifname, hapd); 00796 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 00797 00798 vlan = next; 00799 } 00800 } 00801 00802 00803 int vlan_init(struct hostapd_data *hapd) 00804 { 00805 #ifdef CONFIG_FULL_DYNAMIC_VLAN 00806 hapd->full_dynamic_vlan = full_dynamic_vlan_init(hapd); 00807 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 00808 00809 if (vlan_dynamic_add(hapd, hapd->conf->vlan)) 00810 return -1; 00811 00812 return 0; 00813 } 00814 00815 00816 void vlan_deinit(struct hostapd_data *hapd) 00817 { 00818 vlan_dynamic_remove(hapd, hapd->conf->vlan); 00819 00820 #ifdef CONFIG_FULL_DYNAMIC_VLAN 00821 full_dynamic_vlan_deinit(hapd->full_dynamic_vlan); 00822 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 00823 } 00824 00825 00826 struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, 00827 struct hostapd_vlan *vlan, 00828 int vlan_id) 00829 { 00830 struct hostapd_vlan *n; 00831 char *ifname, *pos; 00832 00833 if (vlan == NULL || vlan_id <= 0 || vlan_id > MAX_VLAN_ID || 00834 vlan->vlan_id != VLAN_ID_WILDCARD) 00835 return NULL; 00836 00837 wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d ifname=%s)", 00838 __func__, vlan_id, vlan->ifname); 00839 ifname = os_strdup(vlan->ifname); 00840 if (ifname == NULL) 00841 return NULL; 00842 pos = os_strchr(ifname, '#'); 00843 if (pos == NULL) { 00844 os_free(ifname); 00845 return NULL; 00846 } 00847 *pos++ = '\0'; 00848 00849 n = os_zalloc(sizeof(*n)); 00850 if (n == NULL) { 00851 os_free(ifname); 00852 return NULL; 00853 } 00854 00855 n->vlan_id = vlan_id; 00856 n->dynamic_vlan = 1; 00857 00858 os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, vlan_id, 00859 pos); 00860 os_free(ifname); 00861 00862 if (hapd->drv.vlan_if_add(hapd, n->ifname)) { 00863 os_free(n); 00864 return NULL; 00865 } 00866 00867 n->next = hapd->conf->vlan; 00868 hapd->conf->vlan = n; 00869 00870 #ifdef CONFIG_FULL_DYNAMIC_VLAN 00871 ifconfig_up(n->ifname); 00872 #endif /* CONFIG_FULL_DYNAMIC_VLAN */ 00873 00874 return n; 00875 } 00876 00877 00878 int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id) 00879 { 00880 struct hostapd_vlan *vlan; 00881 00882 if (vlan_id <= 0 || vlan_id > MAX_VLAN_ID) 00883 return 1; 00884 00885 wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%d)", __func__, vlan_id); 00886 00887 vlan = hapd->conf->vlan; 00888 while (vlan) { 00889 if (vlan->vlan_id == vlan_id && vlan->dynamic_vlan > 0) { 00890 vlan->dynamic_vlan--; 00891 break; 00892 } 00893 vlan = vlan->next; 00894 } 00895 00896 if (vlan == NULL) 00897 return 1; 00898 00899 if (vlan->dynamic_vlan == 0) 00900 hapd->drv.vlan_if_remove(hapd, vlan->ifname); 00901 00902 return 0; 00903 }