1 /*
2 * WPA Supplicant / main() function for UNIX like OSes and MinGW
3 * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
8
9 #include "includes.h"
10 #ifdef __linux__
11 #include <fcntl.h>
12 #endif /* __linux__ */
13
14 #include "common.h"
15 #include "fst/fst.h"
16 #include "wpa_supplicant_i.h"
17 #include "driver_i.h"
18 #include "p2p_supplicant.h"
19
20 struct wpa_global *global = NULL;
21
usage(void)22 static void usage(void)
23 {
24 int i;
25 printf("%s\n\n%s\n"
26 "usage:\n"
27 " wpa_supplicant [-BddhKLqq"
28 #ifdef CONFIG_DEBUG_SYSLOG
29 "s"
30 #endif /* CONFIG_DEBUG_SYSLOG */
31 "t"
32 #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
33 "u"
34 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
35 "vW] [-P<pid file>] "
36 "[-g<global ctrl>] \\\n"
37 " [-G<group>] \\\n"
38 " -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
39 "[-p<driver_param>] \\\n"
40 " [-b<br_ifname>] [-e<entropy file>]"
41 #ifdef CONFIG_DEBUG_FILE
42 " [-f<debug file>]"
43 #endif /* CONFIG_DEBUG_FILE */
44 " \\\n"
45 " [-o<override driver>] [-O<override ctrl>] \\\n"
46 " [-N -i<ifname> -c<conf> [-C<ctrl>] "
47 "[-D<driver>] \\\n"
48 #ifdef CONFIG_P2P
49 " [-m<P2P Device config file>] \\\n"
50 #endif /* CONFIG_P2P */
51 " [-p<driver_param>] [-b<br_ifname>] [-I<config file>] "
52 "...]\n"
53 "\n"
54 "drivers:\n",
55 wpa_supplicant_version, wpa_supplicant_license);
56
57 for (i = 0; wpa_drivers[i]; i++) {
58 printf(" %s = %s\n",
59 wpa_drivers[i]->name,
60 wpa_drivers[i]->desc);
61 }
62
63 #ifndef CONFIG_NO_STDOUT_DEBUG
64 printf("options:\n"
65 " -b = optional bridge interface name\n"
66 " -B = run daemon in the background\n"
67 " -c = Configuration file\n"
68 " -C = ctrl_interface parameter (only used if -c is not)\n"
69 " -d = increase debugging verbosity (-dd even more)\n"
70 " -D = driver name (can be multiple drivers: nl80211,wext)\n"
71 " -e = entropy file\n"
72 #ifdef CONFIG_DEBUG_FILE
73 " -f = log output to debug file instead of stdout\n"
74 #endif /* CONFIG_DEBUG_FILE */
75 " -g = global ctrl_interface\n"
76 " -G = global ctrl_interface group\n"
77 " -h = show this help text\n"
78 " -i = interface name\n"
79 " -I = additional configuration file\n"
80 " -K = include keys (passwords, etc.) in debug output\n"
81 " -L = show license (BSD)\n"
82 #ifdef CONFIG_P2P
83 " -m = Configuration file for the P2P Device interface\n"
84 #endif /* CONFIG_P2P */
85 #ifdef CONFIG_MATCH_IFACE
86 " -M = start describing new matching interface\n"
87 #endif /* CONFIG_MATCH_IFACE */
88 " -N = start describing new interface\n"
89 " -o = override driver parameter for new interfaces\n"
90 " -O = override ctrl_interface parameter for new interfaces\n"
91 " -p = driver parameters\n"
92 " -P = PID file\n"
93 " -q = decrease debugging verbosity (-qq even less)\n"
94 #ifdef CONFIG_DEBUG_SYSLOG
95 " -s = log output to syslog instead of stdout\n"
96 #endif /* CONFIG_DEBUG_SYSLOG */
97 " -t = include timestamp in debug messages\n"
98 #ifdef CONFIG_DEBUG_LINUX_TRACING
99 " -T = record to Linux tracing in addition to logging\n"
100 " (records all messages regardless of debug verbosity)\n"
101 #endif /* CONFIG_DEBUG_LINUX_TRACING */
102 #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
103 " -u = enable DBus control interface\n"
104 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
105 " -v = show version\n"
106 " -W = wait for a control interface monitor before starting\n");
107
108 printf("example:\n"
109 " wpa_supplicant -D%s -iwlan0 -c/etc/wpa_supplicant.conf\n",
110 wpa_drivers[0] ? wpa_drivers[0]->name : "nl80211");
111 #endif /* CONFIG_NO_STDOUT_DEBUG */
112 }
113
114
license(void)115 static void license(void)
116 {
117 #ifndef CONFIG_NO_STDOUT_DEBUG
118 printf("%s\n\n%s%s%s%s%s\n",
119 wpa_supplicant_version,
120 wpa_supplicant_full_license1,
121 wpa_supplicant_full_license2,
122 wpa_supplicant_full_license3,
123 wpa_supplicant_full_license4,
124 wpa_supplicant_full_license5);
125 #endif /* CONFIG_NO_STDOUT_DEBUG */
126 }
127
128
wpa_supplicant_fd_workaround(int start)129 static void wpa_supplicant_fd_workaround(int start)
130 {
131 #ifdef __linux__
132 static int fd[3] = { -1, -1, -1 };
133 int i;
134 /* When started from pcmcia-cs scripts, wpa_supplicant might start with
135 * fd 0, 1, and 2 closed. This will cause some issues because many
136 * places in wpa_supplicant are still printing out to stdout. As a
137 * workaround, make sure that fd's 0, 1, and 2 are not used for other
138 * sockets. */
139 if (start) {
140 for (i = 0; i < 3; i++) {
141 fd[i] = open("/dev/null", O_RDWR);
142 if (fd[i] > 2) {
143 close(fd[i]);
144 fd[i] = -1;
145 break;
146 }
147 }
148 } else {
149 for (i = 0; i < 3; i++) {
150 if (fd[i] >= 0) {
151 close(fd[i]);
152 fd[i] = -1;
153 }
154 }
155 }
156 #endif /* __linux__ */
157 }
158
159
160 #ifdef CONFIG_MATCH_IFACE
wpa_supplicant_init_match(struct wpa_global * global)161 static int wpa_supplicant_init_match(struct wpa_global *global)
162 {
163 /*
164 * The assumption is that the first driver is the primary driver and
165 * will handle the arrival / departure of interfaces.
166 */
167 if (wpa_drivers[0]->global_init && !global->drv_priv[0]) {
168 global->drv_priv[0] = wpa_drivers[0]->global_init(global);
169 if (!global->drv_priv[0]) {
170 wpa_printf(MSG_ERROR,
171 "Failed to initialize driver '%s'",
172 wpa_drivers[0]->name);
173 return -1;
174 }
175 }
176
177 return 0;
178 }
179 #endif /* CONFIG_MATCH_IFACE */
180
181 void set_running_wpa();
182
wpa_main(int argc,char * argv[])183 __attribute__ ((visibility ("default"))) int wpa_main(int argc, char *argv[])
184 {
185 int c, i;
186 struct wpa_interface *ifaces, *iface;
187 int iface_count, exitcode = -1;
188 struct wpa_params params;
189
190 for (i = 0; i < argc; i++) {
191 wpa_printf(MSG_DEBUG, "wpa_main argv[%d]: %s", i, argv[i]);
192 }
193
194 optind = 1;
195 set_running_wpa();
196
197 if (os_program_init())
198 return -1;
199
200 os_memset(¶ms, 0, sizeof(params));
201 params.wpa_debug_level = MSG_INFO;
202
203 iface = ifaces = os_zalloc(sizeof(struct wpa_interface));
204 if (ifaces == NULL)
205 return -1;
206 iface_count = 1;
207
208 wpa_supplicant_fd_workaround(1);
209
210 for (;;) {
211 c = getopt(argc, argv,
212 "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
213 if (c < 0)
214 break;
215 switch (c) {
216 case 'b':
217 iface->bridge_ifname = optarg;
218 break;
219 case 'B':
220 params.daemonize++;
221 break;
222 case 'c':
223 iface->confname = optarg;
224 break;
225 case 'C':
226 iface->ctrl_interface = optarg;
227 break;
228 case 'D':
229 iface->driver = optarg;
230 break;
231 case 'd':
232 #ifdef CONFIG_NO_STDOUT_DEBUG
233 printf("Debugging disabled with "
234 "CONFIG_NO_STDOUT_DEBUG=y build time "
235 "option.\n");
236 goto out;
237 #else /* CONFIG_NO_STDOUT_DEBUG */
238 params.wpa_debug_level--;
239 break;
240 #endif /* CONFIG_NO_STDOUT_DEBUG */
241 case 'e':
242 params.entropy_file = optarg;
243 break;
244 #ifdef CONFIG_DEBUG_FILE
245 case 'f':
246 params.wpa_debug_file_path = optarg;
247 break;
248 #endif /* CONFIG_DEBUG_FILE */
249 case 'g':
250 params.ctrl_interface = optarg;
251 break;
252 case 'G':
253 params.ctrl_interface_group = optarg;
254 break;
255 case 'h':
256 usage();
257 exitcode = 0;
258 goto out;
259 case 'i':
260 iface->ifname = optarg;
261 break;
262 case 'I':
263 iface->confanother = optarg;
264 break;
265 case 'K':
266 params.wpa_debug_show_keys++;
267 break;
268 case 'L':
269 license();
270 exitcode = 0;
271 goto out;
272 #ifdef CONFIG_P2P
273 case 'm':
274 params.conf_p2p_dev = optarg;
275 break;
276 #endif /* CONFIG_P2P */
277 case 'o':
278 params.override_driver = optarg;
279 break;
280 case 'O':
281 params.override_ctrl_interface = optarg;
282 break;
283 case 'p':
284 iface->driver_param = optarg;
285 break;
286 case 'P':
287 os_free(params.pid_file);
288 params.pid_file = os_rel2abs_path(optarg);
289 break;
290 case 'q':
291 params.wpa_debug_level++;
292 break;
293 #ifdef CONFIG_DEBUG_SYSLOG
294 case 's':
295 params.wpa_debug_syslog++;
296 break;
297 #endif /* CONFIG_DEBUG_SYSLOG */
298 #ifdef CONFIG_DEBUG_LINUX_TRACING
299 case 'T':
300 params.wpa_debug_tracing++;
301 break;
302 #endif /* CONFIG_DEBUG_LINUX_TRACING */
303 case 't':
304 params.wpa_debug_timestamp++;
305 break;
306 #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
307 case 'u':
308 params.dbus_ctrl_interface = 1;
309 break;
310 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
311 case 'v':
312 printf("%s\n", wpa_supplicant_version);
313 exitcode = 0;
314 goto out;
315 case 'W':
316 params.wait_for_monitor++;
317 break;
318 #ifdef CONFIG_MATCH_IFACE
319 case 'M':
320 params.match_iface_count++;
321 iface = os_realloc_array(params.match_ifaces,
322 params.match_iface_count,
323 sizeof(struct wpa_interface));
324 if (!iface)
325 goto out;
326 params.match_ifaces = iface;
327 iface = ¶ms.match_ifaces[params.match_iface_count -
328 1];
329 os_memset(iface, 0, sizeof(*iface));
330 break;
331 #endif /* CONFIG_MATCH_IFACE */
332 case 'N':
333 iface_count++;
334 iface = os_realloc_array(ifaces, iface_count,
335 sizeof(struct wpa_interface));
336 if (iface == NULL)
337 goto out;
338 ifaces = iface;
339 iface = &ifaces[iface_count - 1];
340 os_memset(iface, 0, sizeof(*iface));
341 break;
342 default:
343 usage();
344 exitcode = 0;
345 goto out;
346 }
347 }
348
349 exitcode = 0;
350 global = wpa_supplicant_init(¶ms);
351 if (global == NULL) {
352 wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant");
353 exitcode = -1;
354 goto out;
355 } else {
356 wpa_printf(MSG_INFO, "Successfully initialized "
357 "wpa_supplicant");
358 }
359
360 if (fst_global_init()) {
361 wpa_printf(MSG_ERROR, "Failed to initialize FST");
362 exitcode = -1;
363 goto out;
364 }
365
366 #if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
367 if (!fst_global_add_ctrl(fst_ctrl_cli))
368 wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
369 #endif
370
371 for (i = 0; exitcode == 0 && i < iface_count; i++) {
372 struct wpa_supplicant *wpa_s;
373
374 if ((ifaces[i].confname == NULL &&
375 ifaces[i].ctrl_interface == NULL) ||
376 ifaces[i].ifname == NULL) {
377 if (iface_count == 1 && (params.ctrl_interface ||
378 #ifdef CONFIG_MATCH_IFACE
379 params.match_iface_count ||
380 #endif /* CONFIG_MATCH_IFACE */
381 params.dbus_ctrl_interface))
382 break;
383 usage();
384 exitcode = -1;
385 break;
386 }
387 wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL);
388 if (wpa_s == NULL) {
389 exitcode = -1;
390 break;
391 }
392 }
393
394 #ifdef CONFIG_MATCH_IFACE
395 if (exitcode == 0)
396 exitcode = wpa_supplicant_init_match(global);
397 #endif /* CONFIG_MATCH_IFACE */
398
399 if (exitcode == 0)
400 exitcode = wpa_supplicant_run(global);
401
402 wpa_supplicant_deinit(global);
403
404 fst_global_deinit();
405
406 out:
407 wpa_supplicant_fd_workaround(0);
408 os_free(ifaces);
409 #ifdef CONFIG_MATCH_IFACE
410 os_free(params.match_ifaces);
411 #endif /* CONFIG_MATCH_IFACE */
412 os_free(params.pid_file);
413
414 os_program_deinit();
415
416 return exitcode;
417 }
getWpaGlobal()418 struct wpa_global* getWpaGlobal()
419 {
420 return global;
421 }
422