Annotation of embedtools/src/dwds.c, revision 1.4

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.4     ! misho       6:  * $Id: dwds.c,v 1.3.4.1 2014/01/30 01:03:23 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.4     ! 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: 
1.3       misho      50: cfg_root_t cfg;
1.2       misho      51: int Verbose, Kill, nif;
                     52: char **ifs, szConfig[MAXPATHLEN] = DWDS_CONFIG;
                     53: extern char compiled[], compiledby[], compilehost[];
                     54: 
                     55: 
                     56: static void
                     57: Usage()
                     58: {
                     59:        printf( "-= dWDS =- WiFi dynamic WDS service managment for VAP\n"
                     60:                "=== %s === %s@%s ===\n\n"
                     61:                "  Syntax: dwds [options] <interface|any> [interface [ath0, ...]]\n"
                     62:                "\n"
                     63:                "\t-v\t\tVerbose ...\n"
                     64:                "\t-f\t\tForeground, not demonize process ...\n"
                     65:                "\t-c <config>\tConfig file [default=/etc/dwds.conf]\n"
                     66:                "\n", compiled, compiledby, compilehost);
                     67: }
                     68: 
                     69: static void
                     70: sigHandler(int sig)
                     71: {
                     72:        int stat;
1.3       misho      73:        ait_val_t name;
                     74:        const char *v;
1.2       misho      75: 
                     76:        switch (sig) {
                     77:                case SIGHUP:
1.3       misho      78:                        cfgUnloadConfig(&cfg);
                     79:                        if (cfgLoadConfig(szConfig, &cfg)) {
1.2       misho      80:                                printf("Error:: can`t load config %s ...\n", szConfig);
                     81:                                Kill++;
                     82:                        } else {
                     83:                                closelog();
                     84: 
1.3       misho      85:                                cfg_loadAttribute(&cfg, "dwds", "name", &name, DWDS_NAME);
                     86:                                openlog(AIT_GET_STR(&name), LOG_PID | LOG_CONS, LOG_DAEMON);
                     87:                                AIT_FREE_VAL(&name);
                     88:                                v = cfg_getAttribute(&cfg, "dwds", "syslog_upto");
                     89:                                setlogmask(v ? strtol(v, NULL, 0) : 0);
1.2       misho      90:                        }
                     91:                        break;
                     92:                case SIGTERM:
                     93:                        Kill++;
                     94:                        break;
                     95:                case SIGCHLD:
                     96:                        while (waitpid(-1, &stat, WNOHANG) > 0);
                     97:                        break;
                     98:        }
                     99: }
                    100: 
                    101: static int
                    102: RtMsg(struct dwds_if **wds, struct rt_msghdr *msg, size_t len)
                    103: {
                    104:        struct if_announcemsghdr *ifan;
1.3       misho     105:        const char *v;
1.2       misho     106:        struct ether_addr bssid;
1.3       misho     107:        ait_val_t Str, Ident;
                    108:        char szCmd[MAXPATHLEN] = { 0 }, szName[IFNAMSIZ] = { 0 };
1.2       misho     109:        int f, stat;
                    110: 
                    111:        assert(wds);
                    112:        assert(msg);
                    113: 
                    114:        if (msg->rtm_version != RTM_VERSION) {
                    115:                syslog(LOG_ERR, "Error:: routing message version %d not understood!\n", msg->rtm_version);
                    116:                return -1;
                    117:        }
                    118: 
                    119:        switch (msg->rtm_type) {
                    120:                case RTM_IFANNOUNCE:
                    121:                        ifan = (struct if_announcemsghdr*) msg;
                    122:                        switch (ifan->ifan_what) {
                    123:                                case IFAN_ARRIVAL:
                    124:                                        VERB(1) syslog(LOG_INFO, "RTM_IFANNOUNCE: if# %d, what: arrival\n", 
                    125:                                                        ifan->ifan_index);
                    126:                                        break;
                    127:                                case IFAN_DEPARTURE:
                    128:                                        VERB(1) syslog(LOG_INFO, "RTM_IFANNOUNCE: if# %d, what: departure\n", 
                    129:                                                        ifan->ifan_index);
                    130:                                        wifi_destroyWDS(ifan->ifan_name, wds);
                    131:                                        break;
                    132:                        }
                    133:                        break;
                    134:                case RTM_IEEE80211:
                    135: #define        V(type) ((struct type *)(&ifan[1]))
                    136:                        ifan = (struct if_announcemsghdr*) msg;
                    137:                        switch (ifan->ifan_what) {
                    138:                                case RTM_IEEE80211_DISASSOC:
1.3       misho     139:                                        v = cfg_getAttribute(&cfg, "dwds", "discover_on_join");
                    140:                                        if (!v || !strtol(v, NULL, 0))
1.2       misho     141:                                                break;
                    142:                                        /* fall thru ... */
                    143:                                case RTM_IEEE80211_LEAVE:
                    144:                                        if (!wifi_chkIface(ifan->ifan_name, ifs, nif))
                    145:                                                break;
                    146:                                        memcpy(&bssid, V(ieee80211_leave_event)->iev_addr, ETHER_ADDR_LEN);
                    147:                                        VERB(1) syslog(LOG_INFO, "BSSID:%s Station leave\n", ether_ntoa(&bssid));
                    148:                                        if (!wifi_leaveWDS(bssid, wds, szName, IFNAMSIZ)) {
1.3       misho     149:                                                cfg_loadAttribute(&cfg, "dwds", "name", &Ident, DWDS_NAME);
1.2       misho     150:                                                /* delete state file ... */
1.3       misho     151:                                                v = cfg_getAttribute(&cfg, "dwds", "state_dir");
1.2       misho     152:                                                if (v) {
                    153:                                                        memset(szCmd, 0, STRSIZ);
1.3       misho     154:                                                        snprintf(szCmd, MAXPATHLEN, "%s/%s-%s-%s", v, szName, 
                    155:                                                                        ether_ntoa(&bssid), AIT_GET_STR(&Ident));
1.2       misho     156:                                                        unlink(szCmd);
                    157:                                                        VERB(2) syslog(LOG_DEBUG, "Debug:: delete session name %s\n", szCmd);
                    158:                                                }
                    159: 
                    160:                                                /* Launch script ... */
1.3       misho     161:                                                cfg_loadAttribute(&cfg, "dwds", "disassoc_event", &Str, NULL);
                    162:                                                if (!AIT_ISEMPTY(&Str)) {
1.2       misho     163:                                                        memset(szCmd, 0, MAXPATHLEN);
1.3       misho     164:                                                        snprintf(szCmd, MAXPATHLEN, "%s %s %s %s", AIT_GET_STR(&Str), 
                    165:                                                                        szName, ether_ntoa(&bssid), AIT_GET_STR(&Ident));
1.2       misho     166:                                                        VERB(3) syslog(LOG_DEBUG, "Debug:: Command line: %s\n", szCmd);
                    167: 
                    168:                                                        if ((stat = system(szCmd)))
                    169:                                                                syslog(LOG_ERR, "VAP down script %s exited "
1.3       misho     170:                                                                                "with status %d\n", 
                    171:                                                                                AIT_GET_STR(&Str), stat);
                    172:                                                        AIT_FREE_VAL(&Str);
1.2       misho     173:                                                }
1.3       misho     174:                                                AIT_FREE_VAL(&Ident);
1.2       misho     175:                                        }
                    176:                                        break;
                    177: 
                    178:                                case RTM_IEEE80211_JOIN:
                    179:                                case RTM_IEEE80211_REJOIN:
                    180:                                case RTM_IEEE80211_ASSOC:
                    181:                                case RTM_IEEE80211_REASSOC:
1.3       misho     182:                                        v = cfg_getAttribute(&cfg, "dwds", "discover_on_join");
                    183:                                        if (!v || !strtol(v, NULL, 0))
1.2       misho     184:                                                break;
                    185:                                        /* fall thru ... */
                    186:                                case RTM_IEEE80211_WDS:
                    187:                                        memcpy(&bssid, V(ieee80211_leave_event)->iev_addr, ETHER_ADDR_LEN);
                    188:                                        VERB(1) syslog(LOG_INFO, "BSSID:%s WDS discovery\n", ether_ntoa(&bssid));
                    189:                                        if (!wifi_chkIface(ifan->ifan_name, ifs, nif))
                    190:                                                break;
                    191:                                        if (!wifi_createWDS(ifan->ifan_name, bssid, wds)) {
1.3       misho     192:                                                cfg_loadAttribute(&cfg, "dwds", "name", &Ident, DWDS_NAME);
1.2       misho     193:                                                /* create state file ... */
1.3       misho     194:                                                v = cfg_getAttribute(&cfg, "dwds", "state_dir");
1.2       misho     195:                                                if (v) {
                    196:                                                        memset(szCmd, 0, MAXPATHLEN);
                    197:                                                        snprintf(szCmd, MAXPATHLEN, "%s/%s-%s-%s", (char*) v, 
1.3       misho     198:                                                                        (*wds)->if_name, ether_ntoa(&bssid), 
                    199:                                                                        AIT_GET_STR(&Ident));
1.2       misho     200:                                                        f = open(szCmd, O_WRONLY | O_CREAT, 0644);
                    201:                                                        if (f != -1)
                    202:                                                                close(f);
                    203:                                                        VERB(2) syslog(LOG_DEBUG, "Debug:: create session name %s\n", szCmd);
                    204:                                                }
                    205: 
                    206:                                                /* Launch script ... */
1.3       misho     207:                                                cfg_loadAttribute(&cfg, "dwds", "assoc_event", &Str, NULL);
                    208:                                                if (!AIT_ISEMPTY(&Str)) {
1.2       misho     209:                                                        memset(szCmd, 0, MAXPATHLEN);
1.3       misho     210:                                                        snprintf(szCmd, MAXPATHLEN, "%s %s %s %s", AIT_GET_STR(&Str), 
                    211:                                                                        (*wds)->if_name, ether_ntoa(&bssid), 
                    212:                                                                        AIT_GET_STR(&Ident));
1.2       misho     213:                                                        VERB(3) syslog(LOG_DEBUG, "Debug:: Command line: %s\n", szCmd);
                    214: 
                    215:                                                        if ((stat = system(szCmd)))
                    216:                                                                syslog(LOG_ERR, "VAP up script %s exited "
1.3       misho     217:                                                                                "with status %d\n", 
                    218:                                                                                AIT_GET_STR(&Str), stat);
                    219:                                                        AIT_FREE_VAL(&Str);
1.2       misho     220:                                                }
1.3       misho     221:                                                AIT_FREE_VAL(&Ident);
1.2       misho     222:                                        }
                    223:                                        break;
                    224:                        }
                    225: #undef V
                    226:                        break;
                    227:        }
                    228: 
                    229:        return 0;
                    230: }
                    231: 
                    232: 
                    233: int
                    234: main(int argc, char **argv)
                    235: {
1.3       misho     236:        char ch, fg = 0;
                    237:        ait_val_t Ident;
                    238:        const char *v, msg[2048];
1.2       misho     239:        int s;
                    240:        struct sigaction sa;
                    241:        size_t len;
                    242:        struct dwds_if *wds = NULL;
                    243: 
                    244:        while ((ch = getopt(argc, argv, "hvfc:")) != -1)
                    245:                switch (ch) {
                    246:                        case 'v':
                    247:                                Verbose++;
                    248:                                break;
                    249:                        case 'f':
                    250:                                fg = 1;
                    251:                                break;
                    252:                        case 'c':
                    253:                                strlcpy(szConfig, optarg, MAXPATHLEN);
                    254:                                break;
                    255:                        case 'h':
                    256:                        default:
                    257:                                Usage();
                    258:                                return 1;
                    259:                }
                    260:        argc -= optind;
                    261:        argv += optind;
                    262:        if (!argc) {
                    263:                printf("Error:: not specified interface for use ...\n");
                    264:                Usage();
                    265:                return 1;
                    266:        } else {
                    267:                nif = argc;
                    268:                ifs = argv;
                    269:        }
1.3       misho     270:        if (cfgLoadConfig(szConfig, &cfg)) {
1.2       misho     271:                printf("Error:: can`t load config %s ...\n", szConfig);
                    272:                return 1;
                    273:        }
                    274: 
                    275:        if (!fg)
                    276:                switch (fork()) {
                    277:                        case -1:
                    278:                                printf("Error:: when fork() #%d - %s\n", errno, strerror(errno));
1.3       misho     279:                                cfgUnloadConfig(&cfg);
1.2       misho     280:                                return 2;
                    281:                        case 0 :
                    282:                                VERB(1) printf("Going to shadow land ...\n");
                    283: 
                    284:                                setsid();
                    285: 
                    286:                                memset(&sa, 0, sizeof sa);
                    287:                                sa.sa_handler = sigHandler;
                    288:                                sigemptyset(&sa.sa_mask);
                    289:                                sigaction(SIGHUP, &sa, NULL);
                    290:                                sigaction(SIGTERM, &sa, NULL);
                    291:                                sigaction(SIGCHLD, &sa, NULL);
                    292:                                break;
                    293:                        default:
                    294:                                goto end;
                    295:                }
                    296: 
1.3       misho     297:        cfg_loadAttribute(&cfg, "dwds", "name", &Ident, DWDS_NAME);
                    298:        openlog(AIT_GET_STR(&Ident), LOG_PID | LOG_CONS, LOG_DAEMON);
                    299:        AIT_FREE_VAL(&Ident);
                    300:        v = cfg_getAttribute(&cfg, "dwds", "syslog_upto");
                    301:        setlogmask(v ? strtol(v, NULL, 0) : 0);
1.2       misho     302: 
                    303:        s = socket(PF_ROUTE, SOCK_RAW, 0);
                    304:        if (s == -1) {
                    305:                syslog(LOG_ERR, "Error:: socket() #%d - %s\n", errno, strerror(errno));
                    306:                goto end;
                    307:        }
                    308: 
                    309:        if (!(wds = wifi_buildWDS(s, ifs, nif))) {
                    310:                syslog(LOG_ERR, "Error:: Go to dead ...\n");
                    311:                goto end;
                    312:        }
                    313: 
                    314:        while (!Kill) {
                    315:                len = read(s, (void*) msg, sizeof msg);
                    316:                if (len == -1) {
                    317:                        VERB(5) syslog(LOG_ERR, "Error:: read() #%d - %s\n", errno, strerror(errno));
                    318:                        Kill++;
                    319:                } else
                    320:                        RtMsg(&wds, (struct rt_msghdr*) msg, len);
                    321:        }
                    322: 
                    323:        close(s);
                    324: end:
                    325:        closelog();
1.3       misho     326:        cfgUnloadConfig(&cfg);
1.2       misho     327:        return 0;
                    328: }

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