vlan_init.c

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

Generated on Sat Nov 21 23:16:48 2009 for hostapd by  doxygen 1.6.1