Annotation of embedtools/src/dwds.c, revision 1.2.2.1
1.2.2.1 ! misho 1: /*************************************************************************
! 2: * (C) 2010 AITNET - Sofia/Bulgaria - <office@aitbg.com>
! 3: * by Michael Pounov <misho@aitbg.com>
! 4: *
! 5: * $Author: misho $
! 6: * $Id: athctl.c,v 1.2 2011/06/08 12:45:41 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, 2005, 2006, 2007, 2008, 2009, 2010, 2011
! 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: sl_config 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: const u_char *v;
74: char szStr[STRSIZ];
75:
76: switch (sig) {
77: case SIGHUP:
78: UnloadConfig(&cfg);
79: if (LoadConfig(szConfig, &cfg)) {
80: printf("Error:: can`t load config %s ...\n", szConfig);
81: Kill++;
82: } else {
83: closelog();
84:
85: cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"), CFG(szStr), STRSIZ, DWDS_NAME);
86: openlog(szStr, LOG_PID | LOG_CONS, LOG_DAEMON);
87: v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("syslog_upto"));
88: setlogmask(v ? strtol((char*) v, NULL, 0) : 0);
89: }
90: break;
91: case SIGTERM:
92: Kill++;
93: break;
94: case SIGCHLD:
95: while (waitpid(-1, &stat, WNOHANG) > 0);
96: break;
97: }
98: }
99:
100: static int
101: RtMsg(struct dwds_if **wds, struct rt_msghdr *msg, size_t len)
102: {
103: struct if_announcemsghdr *ifan;
104: const u_char *v;
105: struct ether_addr bssid;
106: char szStr[STRSIZ] = { 0 }, szCmd[MAXPATHLEN] = { 0 }, szIdent[STRSIZ] = { 0 },
107: szName[IFNAMSIZ] = { 0 };
108: int f, stat;
109:
110: assert(wds);
111: assert(msg);
112:
113: if (msg->rtm_version != RTM_VERSION) {
114: syslog(LOG_ERR, "Error:: routing message version %d not understood!\n", msg->rtm_version);
115: return -1;
116: }
117:
118: switch (msg->rtm_type) {
119: case RTM_IFANNOUNCE:
120: ifan = (struct if_announcemsghdr*) msg;
121: switch (ifan->ifan_what) {
122: case IFAN_ARRIVAL:
123: VERB(1) syslog(LOG_INFO, "RTM_IFANNOUNCE: if# %d, what: arrival\n",
124: ifan->ifan_index);
125: break;
126: case IFAN_DEPARTURE:
127: VERB(1) syslog(LOG_INFO, "RTM_IFANNOUNCE: if# %d, what: departure\n",
128: ifan->ifan_index);
129: wifi_destroyWDS(ifan->ifan_name, wds);
130: break;
131: }
132: break;
133: case RTM_IEEE80211:
134: #define V(type) ((struct type *)(&ifan[1]))
135: ifan = (struct if_announcemsghdr*) msg;
136: switch (ifan->ifan_what) {
137: case RTM_IEEE80211_DISASSOC:
138: v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("discover_on_join"));
139: if (!v || !strtol((char*) v, NULL, 0))
140: break;
141: /* fall thru ... */
142: case RTM_IEEE80211_LEAVE:
143: if (!wifi_chkIface(ifan->ifan_name, ifs, nif))
144: break;
145: memcpy(&bssid, V(ieee80211_leave_event)->iev_addr, ETHER_ADDR_LEN);
146: VERB(1) syslog(LOG_INFO, "BSSID:%s Station leave\n", ether_ntoa(&bssid));
147: if (!wifi_leaveWDS(bssid, wds, szName, IFNAMSIZ)) {
148: cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"),
149: CFG(szIdent), STRSIZ, DWDS_NAME);
150: /* delete state file ... */
151: v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("state_dir"));
152: if (v) {
153: memset(szCmd, 0, STRSIZ);
154: snprintf(szCmd, MAXPATHLEN, "%s/%s-%s-%s", (char*) v,
155: szName, ether_ntoa(&bssid), szIdent);
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, CFG("dwds"), CFG("disassoc_event"),
162: CFG(szStr), STRSIZ, NULL);
163: if (*szStr) {
164: cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"),
165: CFG(szIdent), STRSIZ, DWDS_NAME);
166: memset(szCmd, 0, MAXPATHLEN);
167: snprintf(szCmd, MAXPATHLEN, "%s %s %s %s", szStr,
168: szName, ether_ntoa(&bssid), szIdent);
169: VERB(3) syslog(LOG_DEBUG, "Debug:: Command line: %s\n", szCmd);
170:
171: if ((stat = system(szCmd)))
172: syslog(LOG_ERR, "VAP down script %s exited "
173: "with status %d\n", szStr, stat);
174: }
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, CFG("dwds"), CFG("discover_on_join"));
183: if (!v || !strtol((char*) 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, CFG("dwds"), CFG("name"),
193: CFG(szIdent), STRSIZ, DWDS_NAME);
194: /* create state file ... */
195: v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("state_dir"));
196: if (v) {
197: memset(szCmd, 0, MAXPATHLEN);
198: snprintf(szCmd, MAXPATHLEN, "%s/%s-%s-%s", (char*) v,
199: (*wds)->if_name, ether_ntoa(&bssid), szIdent);
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, CFG("dwds"), CFG("assoc_event"),
208: CFG(szStr), STRSIZ, NULL);
209: if (*szStr) {
210: memset(szCmd, 0, MAXPATHLEN);
211: snprintf(szCmd, MAXPATHLEN, "%s %s %s %s", szStr,
212: (*wds)->if_name, ether_ntoa(&bssid), szIdent);
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", szStr, stat);
218: }
219: }
220: break;
221: }
222: #undef V
223: break;
224: }
225:
226: return 0;
227: }
228:
229: // ---------------------------------------------------------------
230:
231: int
232: main(int argc, char **argv)
233: {
234: char ch, szStr[STRSIZ], fg = 0;
235: const u_char *v, msg[2048];
236: int s;
237: struct sigaction sa;
238: size_t len;
239: struct dwds_if *wds = NULL;
240:
241: while ((ch = getopt(argc, argv, "hvfc:")) != -1)
242: switch (ch) {
243: case 'v':
244: Verbose++;
245: break;
246: case 'f':
247: fg = 1;
248: break;
249: case 'c':
250: strlcpy(szConfig, optarg, MAXPATHLEN);
251: break;
252: case 'h':
253: default:
254: Usage();
255: return 1;
256: }
257: argc -= optind;
258: argv += optind;
259: if (!argc) {
260: printf("Error:: not specified interface for use ...\n");
261: Usage();
262: return 1;
263: } else {
264: nif = argc;
265: ifs = argv;
266: }
267: if (LoadConfig(szConfig, &cfg)) {
268: printf("Error:: can`t load config %s ...\n", szConfig);
269: return 1;
270: }
271:
272: if (!fg)
273: switch (fork()) {
274: case -1:
275: printf("Error:: when fork() #%d - %s\n", errno, strerror(errno));
276: UnloadConfig(&cfg);
277: return 2;
278: case 0 :
279: VERB(1) printf("Going to shadow land ...\n");
280:
281: setsid();
282:
283: memset(&sa, 0, sizeof sa);
284: sa.sa_handler = sigHandler;
285: sigemptyset(&sa.sa_mask);
286: sigaction(SIGHUP, &sa, NULL);
287: sigaction(SIGTERM, &sa, NULL);
288: sigaction(SIGCHLD, &sa, NULL);
289: break;
290: default:
291: goto end;
292: }
293:
294: cfg_LoadAttribute(&cfg, CFG("dwds"), CFG("name"), CFG(szStr), STRSIZ, DWDS_NAME);
295: openlog(szStr, LOG_PID | LOG_CONS, LOG_DAEMON);
296: v = cfg_GetAttribute(&cfg, CFG("dwds"), CFG("syslog_upto"));
297: setlogmask(v ? strtol((char*) v, NULL, 0) : 0);
298:
299: s = socket(PF_ROUTE, SOCK_RAW, 0);
300: if (s == -1) {
301: syslog(LOG_ERR, "Error:: socket() #%d - %s\n", errno, strerror(errno));
302: goto end;
303: }
304:
305: if (!(wds = wifi_buildWDS(s, ifs, nif))) {
306: syslog(LOG_ERR, "Error:: Go to dead ...\n");
307: goto end;
308: }
309:
310: while (!Kill) {
311: len = read(s, (void*) msg, sizeof msg);
312: if (len == -1) {
313: VERB(5) syslog(LOG_ERR, "Error:: read() #%d - %s\n", errno, strerror(errno));
314: Kill++;
315: } else
316: RtMsg(&wds, (struct rt_msghdr*) msg, len);
317: }
318:
319: close(s);
320: end:
321: closelog();
322: UnloadConfig(&cfg);
323: return 0;
324: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>