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