File:  [ELWIX - Embedded LightWeight unIX -] / embedtools / src / dwds.c
Revision 1.1.2.13: download - view: text, annotated - select for diffs - revision graph
Tue Nov 2 02:25:46 2010 UTC (13 years, 8 months ago) by misho
Branches: tools1_0
finish dwds

    1: #include "global.h"
    2: #include "dwds.h"
    3: 
    4: 
    5: sl_config cfg;
    6: int Verbose, Kill, nif;
    7: char **ifs, szConfig[MAXPATHLEN] = DWDS_CONFIG;
    8: extern char compiled[], compiledby[], compilehost[];
    9: 
   10: 
   11: static void
   12: Usage()
   13: {
   14: 	printf(	"-= dWDS =- WiFi dynamic WDS service managment for VAP\n"
   15: 		"=== %s === %s@%s ===\n\n"
   16: 		"  Syntax: dwds [options] <interface|any> [interface [ath0, ...]]\n"
   17: 		"\n"
   18: 		"\t-v\t\tVerbose ...\n"
   19: 		"\t-f\t\tForeground, not demonize process ...\n"
   20: 		"\t-c <config>\tConfig file [default=/etc/dwds.conf]\n"
   21: 		"\n", compiled, compiledby, compilehost);
   22: }
   23: 
   24: static void
   25: sigHandler(int sig)
   26: {
   27: 	int stat;
   28: 	const u_char *v;
   29: 	char szStr[STRSIZ];
   30: 
   31: 	switch (sig) {
   32: 		case SIGHUP:
   33: 			UnloadConfig(&cfg);
   34: 			if (LoadConfig(szConfig, &cfg)) {
   35: 				printf("Error:: can`t load config %s ...\n", szConfig);
   36: 				Kill++;
   37: 			} else {
   38: 				closelog();
   39: 
   40: 				cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"), CFG(szStr), STRSIZ, DWDS_NAME);
   41: 				openlog(szStr, LOG_PID | LOG_CONS, LOG_DAEMON);
   42: 				v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("syslog_upto"));
   43: 				setlogmask(v ? strtol((char*) v, NULL, 0) : 0);
   44: 			}
   45: 			break;
   46: 		case SIGTERM:
   47: 			Kill++;
   48: 			break;
   49: 		case SIGCHLD:
   50: 			while (waitpid(-1, &stat, WNOHANG) > 0);
   51: 			break;
   52: 	}
   53: }
   54: 
   55: static int
   56: RtMsg(struct dwds_if **wds, struct rt_msghdr *msg, size_t len)
   57: {
   58: 	struct if_announcemsghdr *ifan;
   59: 	const u_char *v;
   60: 	struct ether_addr bssid;
   61: 	char szStr[STRSIZ] = { 0 }, szCmd[MAXPATHLEN] = { 0 }, szIdent[STRSIZ] = { 0 }, 
   62: 	     szName[IFNAMSIZ] = { 0 };
   63: 	int f, stat;
   64: 
   65: 	assert(wds);
   66: 	assert(msg);
   67: 
   68: 	if (msg->rtm_version != RTM_VERSION) {
   69: 		syslog(LOG_ERR, "Error:: routing message version %d not understood!\n", msg->rtm_version);
   70: 		return -1;
   71: 	}
   72: 
   73: 	switch (msg->rtm_type) {
   74: 		case RTM_IFANNOUNCE:
   75: 			ifan = (struct if_announcemsghdr*) msg;
   76: 			switch (ifan->ifan_what) {
   77: 				case IFAN_ARRIVAL:
   78: 					VERB(1) syslog(LOG_INFO, "RTM_IFANNOUNCE: if# %d, what: arrival\n", 
   79: 							ifan->ifan_index);
   80: 					break;
   81: 				case IFAN_DEPARTURE:
   82: 					VERB(1) syslog(LOG_INFO, "RTM_IFANNOUNCE: if# %d, what: departure\n", 
   83: 							ifan->ifan_index);
   84: 					wifi_destroyWDS(ifan->ifan_name, wds);
   85: 					break;
   86: 			}
   87: 			break;
   88: 		case RTM_IEEE80211:
   89: #define	V(type)	((struct type *)(&ifan[1]))
   90: 			ifan = (struct if_announcemsghdr*) msg;
   91: 			switch (ifan->ifan_what) {
   92: 				case RTM_IEEE80211_DISASSOC:
   93: 					v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("discover_on_join"));
   94: 					if (!v || !strtol((char*) v, NULL, 0))
   95: 						break;
   96: 					/* fall thru ... */
   97: 				case RTM_IEEE80211_LEAVE:
   98: 					if (!wifi_chkIface(ifan->ifan_name, ifs, nif))
   99: 						break;
  100: 					memcpy(&bssid, V(ieee80211_leave_event)->iev_addr, ETHER_ADDR_LEN);
  101: 					VERB(1) syslog(LOG_INFO, "BSSID:%s Station leave\n", ether_ntoa(&bssid));
  102: 					if (!wifi_leaveWDS(bssid, wds, szName, IFNAMSIZ)) {
  103: 						cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"), 
  104: 								CFG(szIdent), STRSIZ, DWDS_NAME);
  105: 						/* delete state file ... */
  106: 						v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("state_dir"));
  107: 						if (v) {
  108: 							memset(szCmd, 0, STRSIZ);
  109: 							snprintf(szCmd, MAXPATHLEN, "%s/%s-%s-%s", (char*) v, 
  110: 									szName, ether_ntoa(&bssid), szIdent);
  111: 							unlink(szCmd);
  112: 							VERB(2) syslog(LOG_DEBUG, "Debug:: delete session name %s\n", szCmd);
  113: 						}
  114: 
  115: 						/* Launch script ... */
  116: 						cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("disassoc_event"), 
  117: 								CFG(szStr), STRSIZ, NULL);
  118: 						if (*szStr) {
  119: 							cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"), 
  120: 									CFG(szIdent), STRSIZ, DWDS_NAME);
  121: 							memset(szCmd, 0, MAXPATHLEN);
  122: 							snprintf(szCmd, MAXPATHLEN, "%s %s %s %s", szStr, 
  123: 									szName, ether_ntoa(&bssid), szIdent);
  124: 							VERB(3) syslog(LOG_DEBUG, "Debug:: Command line: %s\n", szCmd);
  125: 
  126: 							if ((stat = system(szCmd)))
  127: 								syslog(LOG_ERR, "VAP down script %s exited "
  128: 										"with status %d\n", szStr, stat);
  129: 						}
  130: 					}
  131: 					break;
  132: 
  133: 				case RTM_IEEE80211_JOIN:
  134: 				case RTM_IEEE80211_REJOIN:
  135: 				case RTM_IEEE80211_ASSOC:
  136: 				case RTM_IEEE80211_REASSOC:
  137: 					v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("discover_on_join"));
  138: 					if (!v || !strtol((char*) v, NULL, 0))
  139: 						break;
  140: 					/* fall thru ... */
  141: 				case RTM_IEEE80211_WDS:
  142: 					memcpy(&bssid, V(ieee80211_leave_event)->iev_addr, ETHER_ADDR_LEN);
  143: 					VERB(1) syslog(LOG_INFO, "BSSID:%s WDS discovery\n", ether_ntoa(&bssid));
  144: 					if (!wifi_chkIface(ifan->ifan_name, ifs, nif))
  145: 						break;
  146: 					if (!wifi_createWDS(ifan->ifan_name, bssid, wds)) {
  147: 						cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"), 
  148: 								CFG(szIdent), STRSIZ, DWDS_NAME);
  149: 						/* create state file ... */
  150: 						v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("state_dir"));
  151: 						if (v) {
  152: 							memset(szCmd, 0, MAXPATHLEN);
  153: 							snprintf(szCmd, MAXPATHLEN, "%s/%s-%s-%s", (char*) v, 
  154: 									(*wds)->if_name, ether_ntoa(&bssid), szIdent);
  155: 							f = open(szCmd, O_WRONLY | O_CREAT, 0644);
  156: 							if (f != -1)
  157: 								close(f);
  158: 							VERB(2) syslog(LOG_DEBUG, "Debug:: create session name %s\n", szCmd);
  159: 						}
  160: 
  161: 						/* Launch script ... */
  162: 						cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("assoc_event"), 
  163: 								CFG(szStr), STRSIZ, NULL);
  164: 						if (*szStr) {
  165: 							memset(szCmd, 0, MAXPATHLEN);
  166: 							snprintf(szCmd, MAXPATHLEN, "%s %s %s %s", szStr, 
  167: 									(*wds)->if_name, ether_ntoa(&bssid), szIdent);
  168: 							VERB(3) syslog(LOG_DEBUG, "Debug:: Command line: %s\n", szCmd);
  169: 
  170: 							if ((stat = system(szCmd)))
  171: 								syslog(LOG_ERR, "VAP up script %s exited "
  172: 										"with status %d\n", szStr, stat);
  173: 						}
  174: 					}
  175: 					break;
  176: 			}
  177: #undef V
  178: 			break;
  179: 	}
  180: 
  181: 	return 0;
  182: }
  183: 
  184: // ---------------------------------------------------------------
  185: 
  186: int
  187: main(int argc, char **argv)
  188: {
  189: 	char ch, szStr[STRSIZ], fg = 0;
  190: 	const u_char *v, msg[2048];
  191: 	int s;
  192: 	struct sigaction sa;
  193: 	size_t len;
  194: 	struct dwds_if *wds = NULL;
  195: 
  196: 	while ((ch = getopt(argc, argv, "hvfc:")) != -1)
  197: 		switch (ch) {
  198: 			case 'v':
  199: 				Verbose++;
  200: 				break;
  201: 			case 'f':
  202: 				fg = 1;
  203: 				break;
  204: 			case 'c':
  205: 				strlcpy(szConfig, optarg, MAXPATHLEN);
  206: 				break;
  207: 			case 'h':
  208: 			default:
  209: 				Usage();
  210: 				return 1;
  211: 		}
  212: 	argc -= optind;
  213: 	argv += optind;
  214: 	if (!argc) {
  215: 		printf("Error:: not specified interface for use ...\n");
  216: 		Usage();
  217: 		return 1;
  218: 	} else {
  219: 		nif = argc;
  220: 		ifs = argv;
  221: 	}
  222: 	if (LoadConfig(szConfig, &cfg)) {
  223: 		printf("Error:: can`t load config %s ...\n", szConfig);
  224: 		return 1;
  225: 	}
  226: 
  227: 	if (!fg)
  228: 		switch (fork()) {
  229: 			case -1:
  230: 				printf("Error:: when fork() #%d - %s\n", errno, strerror(errno));
  231: 				UnloadConfig(&cfg);
  232: 				return 2;
  233: 			case 0 :
  234: 				VERB(1) printf("Going to shadow land ...\n");
  235: 
  236: 				setsid();
  237: 
  238: 				memset(&sa, 0, sizeof sa);
  239: 				sa.sa_handler = sigHandler;
  240: 				sigemptyset(&sa.sa_mask);
  241: 				sigaction(SIGHUP, &sa, NULL);
  242: 				sigaction(SIGTERM, &sa, NULL);
  243: 				sigaction(SIGCHLD, &sa, NULL);
  244: 				break;
  245: 			default:
  246: 				goto end;
  247: 		}
  248: 
  249: 	cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"), CFG(szStr), STRSIZ, DWDS_NAME);
  250: 	openlog(szStr, LOG_PID | LOG_CONS, LOG_DAEMON);
  251: 	v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("syslog_upto"));
  252: 	setlogmask(v ? strtol((char*) v, NULL, 0) : 0);
  253: 
  254: 	s = socket(PF_ROUTE, SOCK_RAW, 0);
  255: 	if (s == -1) {
  256: 		syslog(LOG_ERR, "Error:: socket() #%d - %s\n", errno, strerror(errno));
  257: 		goto end;
  258: 	}
  259: 
  260: 	if (!(wds = wifi_buildWDS(s, ifs, nif))) {
  261: 		syslog(LOG_ERR, "Error:: Go to dead ...\n");
  262: 		goto end;
  263: 	}
  264: 
  265: 	while (!Kill) {
  266: 		len = read(s, (void*) msg, sizeof msg);
  267: 		if (len == -1) {
  268: 			VERB(5) syslog(LOG_ERR, "Error:: read() #%d - %s\n", errno, strerror(errno));
  269: 			Kill++;
  270: 		} else
  271: 			RtMsg(&wds, (struct rt_msghdr*) msg, len);
  272: 	}
  273: 
  274: 	close(s);
  275: end:
  276: 	closelog();
  277: 	UnloadConfig(&cfg);
  278: 	return 0;
  279: }

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