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 "wpa_supplicant_i.h"
16#include "driver_i.h"
17#include "p2p_supplicant.h"
18
19extern struct wpa_driver_ops *wpa_drivers[];
20
21
22static void usage(void)
23{
24	int i;
25	printf("%s\n\n%s\n"
26	       "usage:\n"
27	       "  wpa_supplicant [-BddhKLqqstuvW] [-P<pid file>] "
28	       "[-g<global ctrl>] \\\n"
29	       "        [-G<group>] \\\n"
30	       "        -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
31	       "[-p<driver_param>] \\\n"
32	       "        [-b<br_ifname>] [-f<debug file>] [-e<entropy file>] "
33	       "\\\n"
34	       "        [-o<override driver>] [-O<override ctrl>] \\\n"
35	       "        [-N -i<ifname> -c<conf> [-C<ctrl>] "
36	       "[-D<driver>] \\\n"
37	       "        [-p<driver_param>] [-b<br_ifname>] [-I<config file>] "
38	       "...]\n"
39	       "\n"
40	       "drivers:\n",
41	       wpa_supplicant_version, wpa_supplicant_license);
42
43	for (i = 0; wpa_drivers[i]; i++) {
44		printf("  %s = %s\n",
45		       wpa_drivers[i]->name,
46		       wpa_drivers[i]->desc);
47	}
48
49#ifndef CONFIG_NO_STDOUT_DEBUG
50	printf("options:\n"
51	       "  -b = optional bridge interface name\n"
52	       "  -B = run daemon in the background\n"
53	       "  -c = Configuration file\n"
54	       "  -C = ctrl_interface parameter (only used if -c is not)\n"
55	       "  -i = interface name\n"
56	       "  -I = additional configuration file\n"
57	       "  -d = increase debugging verbosity (-dd even more)\n"
58	       "  -D = driver name (can be multiple drivers: nl80211,wext)\n"
59	       "  -e = entropy file\n");
60#ifdef CONFIG_DEBUG_FILE
61	printf("  -f = log output to debug file instead of stdout\n");
62#endif /* CONFIG_DEBUG_FILE */
63	printf("  -g = global ctrl_interface\n"
64	       "  -G = global ctrl_interface group\n"
65	       "  -K = include keys (passwords, etc.) in debug output\n");
66#ifdef CONFIG_DEBUG_SYSLOG
67	printf("  -s = log output to syslog instead of stdout\n");
68#endif /* CONFIG_DEBUG_SYSLOG */
69#ifdef CONFIG_DEBUG_LINUX_TRACING
70	printf("  -T = record to Linux tracing in addition to logging\n");
71	printf("       (records all messages regardless of debug verbosity)\n");
72#endif /* CONFIG_DEBUG_LINUX_TRACING */
73	printf("  -t = include timestamp in debug messages\n"
74	       "  -h = show this help text\n"
75	       "  -L = show license (BSD)\n"
76	       "  -o = override driver parameter for new interfaces\n"
77	       "  -O = override ctrl_interface parameter for new interfaces\n"
78	       "  -p = driver parameters\n"
79	       "  -P = PID file\n"
80	       "  -q = decrease debugging verbosity (-qq even less)\n");
81#ifdef CONFIG_DBUS
82	printf("  -u = enable DBus control interface\n");
83#endif /* CONFIG_DBUS */
84	printf("  -v = show version\n"
85	       "  -W = wait for a control interface monitor before starting\n"
86	       "  -N = start describing new interface\n");
87
88	printf("example:\n"
89	       "  wpa_supplicant -D%s -iwlan0 -c/etc/wpa_supplicant.conf\n",
90	       wpa_drivers[0] ? wpa_drivers[0]->name : "nl80211");
91#endif /* CONFIG_NO_STDOUT_DEBUG */
92}
93
94
95static void license(void)
96{
97#ifndef CONFIG_NO_STDOUT_DEBUG
98	printf("%s\n\n%s%s%s%s%s\n",
99	       wpa_supplicant_version,
100	       wpa_supplicant_full_license1,
101	       wpa_supplicant_full_license2,
102	       wpa_supplicant_full_license3,
103	       wpa_supplicant_full_license4,
104	       wpa_supplicant_full_license5);
105#endif /* CONFIG_NO_STDOUT_DEBUG */
106}
107
108
109static void wpa_supplicant_fd_workaround(int start)
110{
111#ifdef __linux__
112	static int fd[3] = { -1, -1, -1 };
113	int i;
114	/* When started from pcmcia-cs scripts, wpa_supplicant might start with
115	 * fd 0, 1, and 2 closed. This will cause some issues because many
116	 * places in wpa_supplicant are still printing out to stdout. As a
117	 * workaround, make sure that fd's 0, 1, and 2 are not used for other
118	 * sockets. */
119	if (start) {
120		for (i = 0; i < 3; i++) {
121			fd[i] = open("/dev/null", O_RDWR);
122			if (fd[i] > 2) {
123				close(fd[i]);
124				fd[i] = -1;
125				break;
126			}
127		}
128	} else {
129		for (i = 0; i < 3; i++) {
130			if (fd[i] >= 0) {
131				close(fd[i]);
132				fd[i] = -1;
133			}
134		}
135	}
136#endif /* __linux__ */
137}
138
139
140int main(int argc, char *argv[])
141{
142	int c, i;
143	struct wpa_interface *ifaces, *iface;
144	int iface_count, exitcode = -1;
145	struct wpa_params params;
146	struct wpa_global *global;
147
148	if (os_program_init())
149		return -1;
150
151	os_memset(&params, 0, sizeof(params));
152	params.wpa_debug_level = MSG_INFO;
153
154	iface = ifaces = os_zalloc(sizeof(struct wpa_interface));
155	if (ifaces == NULL)
156		return -1;
157	iface_count = 1;
158
159	wpa_supplicant_fd_workaround(1);
160
161	for (;;) {
162		c = getopt(argc, argv,
163			   "b:Bc:C:D:de:f:g:G:hi:I:KLNo:O:p:P:qsTtuvW");
164		if (c < 0)
165			break;
166		switch (c) {
167		case 'b':
168			iface->bridge_ifname = optarg;
169			break;
170		case 'B':
171			params.daemonize++;
172			break;
173		case 'c':
174			iface->confname = optarg;
175			break;
176		case 'C':
177			iface->ctrl_interface = optarg;
178			break;
179		case 'D':
180			iface->driver = optarg;
181			break;
182		case 'd':
183#ifdef CONFIG_NO_STDOUT_DEBUG
184			printf("Debugging disabled with "
185			       "CONFIG_NO_STDOUT_DEBUG=y build time "
186			       "option.\n");
187			goto out;
188#else /* CONFIG_NO_STDOUT_DEBUG */
189			params.wpa_debug_level--;
190			break;
191#endif /* CONFIG_NO_STDOUT_DEBUG */
192		case 'e':
193			params.entropy_file = optarg;
194			break;
195#ifdef CONFIG_DEBUG_FILE
196		case 'f':
197			params.wpa_debug_file_path = optarg;
198			break;
199#endif /* CONFIG_DEBUG_FILE */
200		case 'g':
201			params.ctrl_interface = optarg;
202			break;
203		case 'G':
204			params.ctrl_interface_group = optarg;
205			break;
206		case 'h':
207			usage();
208			exitcode = 0;
209			goto out;
210		case 'i':
211			iface->ifname = optarg;
212			break;
213		case 'I':
214			iface->confanother = optarg;
215			break;
216		case 'K':
217			params.wpa_debug_show_keys++;
218			break;
219		case 'L':
220			license();
221			exitcode = 0;
222			goto out;
223		case 'o':
224			params.override_driver = optarg;
225			break;
226		case 'O':
227			params.override_ctrl_interface = optarg;
228			break;
229		case 'p':
230			iface->driver_param = optarg;
231			break;
232		case 'P':
233			os_free(params.pid_file);
234			params.pid_file = os_rel2abs_path(optarg);
235			break;
236		case 'q':
237			params.wpa_debug_level++;
238			break;
239#ifdef CONFIG_DEBUG_SYSLOG
240		case 's':
241			params.wpa_debug_syslog++;
242			break;
243#endif /* CONFIG_DEBUG_SYSLOG */
244#ifdef CONFIG_DEBUG_LINUX_TRACING
245		case 'T':
246			params.wpa_debug_tracing++;
247			break;
248#endif /* CONFIG_DEBUG_LINUX_TRACING */
249		case 't':
250			params.wpa_debug_timestamp++;
251			break;
252#ifdef CONFIG_DBUS
253		case 'u':
254			params.dbus_ctrl_interface = 1;
255			break;
256#endif /* CONFIG_DBUS */
257		case 'v':
258			printf("%s\n", wpa_supplicant_version);
259			exitcode = 0;
260			goto out;
261		case 'W':
262			params.wait_for_monitor++;
263			break;
264		case 'N':
265			iface_count++;
266			iface = os_realloc_array(ifaces, iface_count,
267						 sizeof(struct wpa_interface));
268			if (iface == NULL)
269				goto out;
270			ifaces = iface;
271			iface = &ifaces[iface_count - 1];
272			os_memset(iface, 0, sizeof(*iface));
273			break;
274		default:
275			usage();
276			exitcode = 0;
277			goto out;
278		}
279	}
280
281	exitcode = 0;
282	global = wpa_supplicant_init(&params);
283	if (global == NULL) {
284		wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant");
285		exitcode = -1;
286		goto out;
287	} else {
288		wpa_printf(MSG_INFO, "Successfully initialized "
289			   "wpa_supplicant");
290	}
291
292	for (i = 0; exitcode == 0 && i < iface_count; i++) {
293		struct wpa_supplicant *wpa_s;
294
295		if ((ifaces[i].confname == NULL &&
296		     ifaces[i].ctrl_interface == NULL) ||
297		    ifaces[i].ifname == NULL) {
298			if (iface_count == 1 && (params.ctrl_interface ||
299						 params.dbus_ctrl_interface))
300				break;
301			usage();
302			exitcode = -1;
303			break;
304		}
305		wpa_s = wpa_supplicant_add_iface(global, &ifaces[i]);
306		if (wpa_s == NULL) {
307			exitcode = -1;
308			break;
309		}
310#ifdef CONFIG_P2P
311		if (wpa_s->global->p2p == NULL &&
312		    (wpa_s->drv_flags &
313		     WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) &&
314		    wpas_p2p_add_p2pdev_interface(wpa_s) < 0)
315			exitcode = -1;
316#endif /* CONFIG_P2P */
317	}
318
319	if (exitcode == 0)
320		exitcode = wpa_supplicant_run(global);
321
322	wpa_supplicant_deinit(global);
323
324out:
325	wpa_supplicant_fd_workaround(0);
326	os_free(ifaces);
327	os_free(params.pid_file);
328
329	os_program_deinit();
330
331	return exitcode;
332}
333