00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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;
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
00098
00099
00100 #define _GET_VLAN_REALDEV_NAME_CMD 8
00101 #define _GET_VLAN_VID_CMD 9
00102
00103
00104
00105
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
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
00155
00156
00157
00158
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
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
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
00239
00240
00241
00242
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
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
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
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
00374
00375
00376
00377
00378
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
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
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
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
00737
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
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
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
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
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
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 }