Annotation of embedtools/src/vap.c, revision 1.3.4.1

1.3       misho       1: /*************************************************************************
                      2:  * (C) 2010 AITNET - Sofia/Bulgaria - <office@aitbg.com>
                      3:  *  by Michael Pounov <misho@aitbg.com>
                      4:  *
                      5:  * $Author: misho $
1.3.4.1 ! misho       6:  * $Id: vap.c,v 1.3 2012/07/22 22:46:48 misho Exp $
1.3       misho       7:  *
                      8:  *************************************************************************
                      9: The ELWIX and AITNET software is distributed under the following
                     10: terms:
                     11: 
                     12: All of the documentation and software included in the ELWIX and AITNET
                     13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
                     14: 
1.3.4.1 ! misho      15: Copyright 2004 - 2014
1.3       misho      16:        by Michael Pounov <misho@elwix.org>.  All rights reserved.
                     17: 
                     18: Redistribution and use in source and binary forms, with or without
                     19: modification, are permitted provided that the following conditions
                     20: are met:
                     21: 1. Redistributions of source code must retain the above copyright
                     22:    notice, this list of conditions and the following disclaimer.
                     23: 2. Redistributions in binary form must reproduce the above copyright
                     24:    notice, this list of conditions and the following disclaimer in the
                     25:    documentation and/or other materials provided with the distribution.
                     26: 3. All advertising materials mentioning features or use of this software
                     27:    must display the following acknowledgement:
                     28: This product includes software developed by Michael Pounov <misho@elwix.org>
                     29: ELWIX - Embedded LightWeight unIX and its contributors.
                     30: 4. Neither the name of AITNET nor the names of its contributors
                     31:    may be used to endorse or promote products derived from this software
                     32:    without specific prior written permission.
                     33: 
                     34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
                     35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     44: SUCH DAMAGE.
                     45: */
1.2       misho      46: #include "global.h"
                     47: #include "dwds.h"
                     48: 
                     49: 
                     50: static inline int
                     51: wifi_getParent(const char *csVAP, char *psParent, size_t plen)
                     52: {
                     53:        char szOID[STRSIZ] = { 0 };
                     54: 
                     55:        FTRACE(5);
                     56: 
                     57:        assert(csVAP);
                     58:        assert(psParent);
                     59: 
                     60:        memset(psParent, 0, plen);
                     61:        snprintf(szOID, STRSIZ, "net.wlan.%s.%%parent", csVAP + 4);
                     62:        if (sysctlbyname(szOID, psParent, &plen, NULL, 0) == -1) {
                     63: //             syslog(LOG_ERR, "Error:: can`t get parent #%d - %s\n", errno, strerror(errno));
                     64:                return -1;
                     65:        } else
                     66:                psParent[plen] = 0;
                     67: 
                     68:        return 0;
                     69: }
                     70: 
                     71: inline int
                     72: wifi_chkIface(const char *csVAP, char **ppsIF, int nIF)
                     73: {
                     74:        char szParent[IFNAMSIZ];
                     75:        register int i;
                     76: 
                     77:        FTRACE(5);
                     78: 
                     79:        assert(csVAP);
                     80: 
                     81:        if (wifi_getParent(csVAP, szParent, IFNAMSIZ) == -1)
                     82:                return 0;
                     83: 
                     84:        for (i = 0; i < nIF; i++)
                     85:                if (!strcasecmp(ppsIF[i], "any") || !strcmp(ppsIF[i], szParent))
                     86:                        return 1; /* OK, vap is child */
                     87: 
                     88:        VERB(2) syslog(LOG_ERR, "Error:: Interface %s parent %s not being monitored", csVAP, szParent);
                     89:        return 0;
                     90: }
                     91: 
                     92: static inline int
                     93: wifi_isWDS(int fd, const char *csVAP)
                     94: {
                     95:        struct ifmediareq ifmr;
                     96: 
                     97:        FTRACE(5);
                     98: 
                     99:        assert(csVAP);
                    100: 
                    101:        memset(&ifmr, 0, sizeof ifmr);
                    102:        strlcpy(ifmr.ifm_name, csVAP, sizeof ifmr.ifm_name);
                    103:        if (ioctl(fd, SIOCGIFMEDIA, &ifmr) == -1) {
                    104:                syslog(LOG_ERR, "Error:: can`t get media for %s #%d - %s\n", csVAP, 
                    105:                                errno, strerror(errno));
                    106:                return -1;
                    107:        }
                    108: 
                    109:        return (ifmr.ifm_current & IFM_IEEE80211_WDS) != 0;
                    110: }
                    111: 
                    112: static inline int
                    113: wifi_getBSSID(int fd, const char *csVAP, uint8_t *psBSSID, int len)
                    114: {
                    115:        struct ieee80211req ireq;
                    116: 
                    117:        FTRACE(5);
                    118: 
                    119:        assert(csVAP);
                    120:        assert(psBSSID);
                    121: 
                    122:        memset(&ireq, 0, sizeof ireq);
                    123:        strlcpy(ireq.i_name, csVAP, sizeof ireq.i_name);
                    124:        ireq.i_type = IEEE80211_IOC_BSSID;
                    125:        ireq.i_data = psBSSID;
                    126:        ireq.i_len = len;
                    127:        if (ioctl(fd, SIOCG80211, &ireq) == -1) {
                    128:                syslog(LOG_ERR, "Error:: can`t get BSSID for %s #%d - %s\n", csVAP, 
                    129:                                errno, strerror(errno));
                    130:                return -1;
                    131:        }
                    132: 
                    133:        return 0;
                    134: }
                    135: 
                    136: struct dwds_if *
                    137: wifi_buildWDS(int fd, char **ppsIF, int nIF)
                    138: {
                    139:        struct dwds_if *p, *wds = NULL;
                    140:        char szVAP[IFNAMSIZ];
                    141:        struct ether_addr bssid;
                    142:        register int i;
                    143: 
                    144:        FTRACE(5);
                    145: 
                    146:        for (i = 0; i < 128; i++) {
                    147:                memset(szVAP, 0, IFNAMSIZ);
                    148:                snprintf(szVAP, IFNAMSIZ, "wlan%d", i);
                    149:                if (wifi_chkIface(szVAP, ppsIF, nIF) && !wifi_isWDS(fd, szVAP)) {
                    150:                        p = malloc(sizeof(struct dwds_if));
                    151:                        if (!p) {
                    152:                                syslog(LOG_ERR, "Error:: can`t allocate memory #%d - %s\n", 
                    153:                                                errno, strerror(errno));
                    154:                                i = -1;
                    155:                                break;
                    156:                        }
                    157:                        strlcpy(p->if_name, szVAP, IFNAMSIZ);
                    158:                        if (wifi_getBSSID(fd, szVAP, p->if_bssid, IEEE80211_ADDR_LEN) == -1) {
                    159:                                syslog(LOG_ERR, "Error:: can`t get BSSID #%d - %s\n", 
                    160:                                                errno, strerror(errno));
                    161:                                i = -1;
                    162:                                break;
                    163:                        }
                    164:                        p->if_next = wds;
                    165:                        wds = p;
                    166: 
                    167:                        memcpy(&bssid, p->if_bssid, ETHER_ADDR_LEN);
                    168:                        syslog(LOG_INFO, "BSSID:%s discover WDS vap %s\n", ether_ntoa(&bssid), szVAP);
                    169:                }
                    170:        }
                    171: 
                    172:        if (i == -1)
                    173:                while ((p = wds)) {
                    174:                        wds = wds->if_next;
                    175:                        free(p);
                    176:                }
                    177: 
                    178:        return wds;
                    179: }
                    180: 
                    181: inline int
                    182: wifi_destroyWDS(const char *csIface, struct dwds_if **wds)
                    183: {
                    184:        struct dwds_if *p, **pp;
                    185: 
                    186:        FTRACE(5);
                    187: 
                    188:        assert(csIface);
                    189:        assert(wds);
                    190: 
                    191:        for (pp = wds; (p = *pp); pp = &p->if_next)
                    192:                if (!strncmp(p->if_name, csIface, IFNAMSIZ))
                    193:                        break;
                    194:        if (p) {
                    195:                *pp = p->if_next;
                    196:                free(p);
                    197:                return 0;
                    198:        }
                    199: 
                    200:        return 1;
                    201: }
                    202: 
                    203: static int
                    204: wifi_vapDestroy(const char *csVAP)
                    205: {
                    206:        struct ieee80211req ifr;
                    207:        int s;
                    208: 
                    209:        FTRACE(5);
                    210: 
                    211:        assert(csVAP);
                    212: 
                    213:        s = socket(PF_INET, SOCK_DGRAM, 0);
                    214:        if (s == -1) {
                    215:                syslog(LOG_ERR, "Error:: destroy socket(vap) %m\n");
                    216:                return -1;
                    217:        }
                    218: 
                    219:        memset(&ifr, 0, sizeof ifr);
                    220:        strlcpy(ifr.i_name, csVAP, IFNAMSIZ);
                    221:        if (ioctl(s, SIOCIFDESTROY, &ifr) == -1) {
                    222:                syslog(LOG_ERR, "Error:: destroy ioctl(vap) %m\n");
                    223:                close(s);
                    224:                return -1;
                    225:        } else
                    226:                close(s);
                    227: 
                    228:        return 0;
                    229: }
                    230: 
                    231: inline int
                    232: wifi_leaveWDS(struct ether_addr bssid, struct dwds_if **wds, char *psVAP, int vapLen)
                    233: {
                    234:        struct dwds_if *p, **pp;
                    235: 
                    236:        FTRACE(5);
                    237: 
                    238:        assert(wds);
                    239:        assert(psVAP);
                    240: 
                    241:        for (pp = wds; (p = *pp); pp = &p->if_next)
                    242:                if (!memcmp(p->if_bssid, &bssid, IEEE80211_ADDR_LEN))
                    243:                        break;
                    244:        if (p) {
                    245:                *pp = p->if_next;
                    246:                strlcpy(psVAP, p->if_name, vapLen);
                    247:                if (wifi_vapDestroy(p->if_name) != -1)
                    248:                       VERB(1) syslog(LOG_INFO, "BSSID:%s WDS VAP %s destroyed\n", 
                    249:                                       ether_ntoa(&bssid), p->if_name); 
                    250:                free(p);
                    251:                return 0;
                    252:        }
                    253: 
                    254:        return 1;
                    255: }
                    256: 
                    257: static int
                    258: wifi_vapCreate(const char *csIface, struct dwds_if *p)
                    259: {
                    260:        struct ieee80211_clone_params cp;
                    261:        struct ifreq ifr;
                    262:        struct ether_addr bssid;
                    263:        int s;
                    264: 
                    265:        FTRACE(5);
                    266: 
                    267:        assert(csIface);
                    268:        assert(p);
                    269: 
                    270:        s = socket(PF_INET, SOCK_DGRAM, 0);
                    271:        if (s == -1) {
                    272:                syslog(LOG_ERR, "Error:: create socket(vap) %m\n");
                    273:                return -1;
                    274:        }
                    275: 
                    276:        memset(&cp, 0, sizeof cp);
                    277:        strlcpy(cp.icp_parent, csIface, IFNAMSIZ);
                    278:        cp.icp_opmode = IEEE80211_M_WDS;
                    279:        memcpy(cp.icp_bssid, p->if_bssid, IEEE80211_ADDR_LEN);
                    280: 
                    281:        memset(&ifr, 0, sizeof ifr);
                    282:        strlcpy(ifr.ifr_name, "wlan", IFNAMSIZ);
                    283:        ifr.ifr_data = (void *) &cp;
                    284: 
                    285:        if (ioctl(s, SIOCIFCREATE2, &ifr) == -1) {
                    286:                memcpy(&bssid, cp.icp_bssid, IEEE80211_ADDR_LEN);
                    287:                syslog(LOG_ERR, "Error:: create ioctl(vap) mode %u flags 0x%x parent %s bssid %s %m\n", 
                    288:                                cp.icp_opmode, cp.icp_flags, cp.icp_parent, ether_ntoa(&bssid));
                    289:                close(s);
                    290:                return -1;
                    291:        } else {
                    292:                strlcpy(p->if_name, ifr.ifr_name, IFNAMSIZ);
                    293:                close(s);
                    294:        }
                    295: 
                    296:        return 0;
                    297: }
                    298: 
                    299: inline int
                    300: wifi_createWDS(const char *csIface, struct ether_addr bssid, struct dwds_if **wds)
                    301: {
                    302:        struct dwds_if *p;
                    303:        char szParent[IFNAMSIZ];
                    304: 
                    305:        FTRACE(5);
                    306: 
                    307:        assert(csIface);
                    308:        assert(wds);
                    309: 
                    310:        for (p = *wds; p; p = p->if_next)
                    311:                if (!memcmp(p->if_bssid, &bssid, IEEE80211_ADDR_LEN)) {
                    312:                        VERB(1) syslog(LOG_INFO, "BSSID:%s WDS VAP already created (%s)\n",
                    313:                            ether_ntoa(&bssid), csIface);
                    314:                        return 1;
                    315:                }
                    316:        if (wifi_getParent(csIface, szParent, IFNAMSIZ) == -1) {
                    317:                syslog(LOG_ERR, "Error:: %s no pointer to parent interface\n", csIface);
                    318:                return -1;
                    319:        }
                    320: 
                    321:        p = malloc(sizeof(struct dwds_if));
                    322:        if (!p) {
                    323:                syslog(LOG_ERR, "Error:: malloc failed: %m\n");
                    324:                return -1;
                    325:        } else
                    326:                memcpy(p->if_bssid, &bssid, IEEE80211_ADDR_LEN);
                    327:        if (wifi_vapCreate(szParent, p) == -1) {
                    328:                free(p);
                    329:                return -1;
                    330:        } else {
                    331:                p->if_next = *wds;
                    332:                *wds = p;
                    333:                VERB(1) syslog(LOG_INFO, "BSSID:%s create WDS VAP %s\n", ether_ntoa(&bssid), p->if_name);
                    334:        }
                    335: 
                    336:        return 0;
                    337: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>