File:  [ELWIX - Embedded LightWeight unIX -] / embedtools / src / dwds.c
Revision 1.4: download - view: text, annotated - select for diffs - revision graph
Wed Feb 5 15:44:06 2014 UTC (10 years, 4 months ago) by misho
Branches: MAIN
CVS tags: tools3_0, tools2_9, tools2_8, tools2_7, tools2_6, tools2_5, tools2_4, tools2_3, tools2_2, tools2_1, TOOLS2_9, TOOLS2_8, TOOLS2_7, TOOLS2_6, TOOLS2_5, TOOLS2_4, TOOLS2_3, TOOLS2_2, TOOLS2_1, TOOLS2_0, HEAD
version 2.0

    1: /*************************************************************************
    2:  * (C) 2010 AITNET - Sofia/Bulgaria - <office@aitbg.com>
    3:  *  by Michael Pounov <misho@aitbg.com>
    4:  *
    5:  * $Author: misho $
    6:  * $Id: dwds.c,v 1.4 2014/02/05 15:44:06 misho Exp $
    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: 
   15: Copyright 2004 - 2014
   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: */
   46: #include "global.h"
   47: #include "dwds.h"
   48: 
   49: 
   50: cfg_root_t cfg;
   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;
   73: 	ait_val_t name;
   74: 	const char *v;
   75: 
   76: 	switch (sig) {
   77: 		case SIGHUP:
   78: 			cfgUnloadConfig(&cfg);
   79: 			if (cfgLoadConfig(szConfig, &cfg)) {
   80: 				printf("Error:: can`t load config %s ...\n", szConfig);
   81: 				Kill++;
   82: 			} else {
   83: 				closelog();
   84: 
   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);
   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;
  105: 	const char *v;
  106: 	struct ether_addr bssid;
  107: 	ait_val_t Str, Ident;
  108: 	char szCmd[MAXPATHLEN] = { 0 }, szName[IFNAMSIZ] = { 0 };
  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:
  139: 					v = cfg_getAttribute(&cfg, "dwds", "discover_on_join");
  140: 					if (!v || !strtol(v, NULL, 0))
  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)) {
  149: 						cfg_loadAttribute(&cfg, "dwds", "name", &Ident, DWDS_NAME);
  150: 						/* delete state file ... */
  151: 						v = cfg_getAttribute(&cfg, "dwds", "state_dir");
  152: 						if (v) {
  153: 							memset(szCmd, 0, STRSIZ);
  154: 							snprintf(szCmd, MAXPATHLEN, "%s/%s-%s-%s", v, szName, 
  155: 									ether_ntoa(&bssid), AIT_GET_STR(&Ident));
  156: 							unlink(szCmd);
  157: 							VERB(2) syslog(LOG_DEBUG, "Debug:: delete session name %s\n", szCmd);
  158: 						}
  159: 
  160: 						/* Launch script ... */
  161: 						cfg_loadAttribute(&cfg, "dwds", "disassoc_event", &Str, NULL);
  162: 						if (!AIT_ISEMPTY(&Str)) {
  163: 							memset(szCmd, 0, MAXPATHLEN);
  164: 							snprintf(szCmd, MAXPATHLEN, "%s %s %s %s", AIT_GET_STR(&Str), 
  165: 									szName, ether_ntoa(&bssid), AIT_GET_STR(&Ident));
  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 "
  170: 										"with status %d\n", 
  171: 										AIT_GET_STR(&Str), stat);
  172: 							AIT_FREE_VAL(&Str);
  173: 						}
  174: 						AIT_FREE_VAL(&Ident);
  175: 					}
  176: 					break;
  177: 
  178: 				case RTM_IEEE80211_JOIN:
  179: 				case RTM_IEEE80211_REJOIN:
  180: 				case RTM_IEEE80211_ASSOC:
  181: 				case RTM_IEEE80211_REASSOC:
  182: 					v = cfg_getAttribute(&cfg, "dwds", "discover_on_join");
  183: 					if (!v || !strtol(v, NULL, 0))
  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)) {
  192: 						cfg_loadAttribute(&cfg, "dwds", "name", &Ident, DWDS_NAME);
  193: 						/* create state file ... */
  194: 						v = cfg_getAttribute(&cfg, "dwds", "state_dir");
  195: 						if (v) {
  196: 							memset(szCmd, 0, MAXPATHLEN);
  197: 							snprintf(szCmd, MAXPATHLEN, "%s/%s-%s-%s", (char*) v, 
  198: 									(*wds)->if_name, ether_ntoa(&bssid), 
  199: 									AIT_GET_STR(&Ident));
  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 ... */
  207: 						cfg_loadAttribute(&cfg, "dwds", "assoc_event", &Str, NULL);
  208: 						if (!AIT_ISEMPTY(&Str)) {
  209: 							memset(szCmd, 0, MAXPATHLEN);
  210: 							snprintf(szCmd, MAXPATHLEN, "%s %s %s %s", AIT_GET_STR(&Str), 
  211: 									(*wds)->if_name, ether_ntoa(&bssid), 
  212: 									AIT_GET_STR(&Ident));
  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 "
  217: 										"with status %d\n", 
  218: 										AIT_GET_STR(&Str), stat);
  219: 							AIT_FREE_VAL(&Str);
  220: 						}
  221: 						AIT_FREE_VAL(&Ident);
  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: {
  236: 	char ch, fg = 0;
  237: 	ait_val_t Ident;
  238: 	const char *v, msg[2048];
  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: 	}
  270: 	if (cfgLoadConfig(szConfig, &cfg)) {
  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));
  279: 				cfgUnloadConfig(&cfg);
  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: 
  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);
  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();
  326: 	cfgUnloadConfig(&cfg);
  327: 	return 0;
  328: }

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