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>