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 "crypto/crypto.h"
16  #include "fst/fst.h"
17  #include "wpa_supplicant_i.h"
18  #include "driver_i.h"
19  #include "p2p_supplicant.h"
20  
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  
main(int argc,char * argv[])182  int main(int argc, char *argv[])
183  {
184  	int c, i;
185  	struct wpa_interface *ifaces, *iface;
186  	int iface_count, exitcode = -1;
187  	struct wpa_params params;
188  	struct wpa_global *global;
189  
190  	if (os_program_init())
191  		return -1;
192  
193  	os_memset(&params, 0, sizeof(params));
194  	params.wpa_debug_level = MSG_INFO;
195  
196  	iface = ifaces = os_zalloc(sizeof(struct wpa_interface));
197  	if (ifaces == NULL)
198  		return -1;
199  	iface_count = 1;
200  
201  	wpa_supplicant_fd_workaround(1);
202  
203  	for (;;) {
204  		c = getopt(argc, argv,
205  			   "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
206  		if (c < 0)
207  			break;
208  		switch (c) {
209  		case 'b':
210  			iface->bridge_ifname = optarg;
211  			break;
212  		case 'B':
213  			params.daemonize++;
214  			break;
215  		case 'c':
216  			iface->confname = optarg;
217  			break;
218  		case 'C':
219  			iface->ctrl_interface = optarg;
220  			break;
221  		case 'D':
222  			iface->driver = optarg;
223  			break;
224  		case 'd':
225  #ifdef CONFIG_NO_STDOUT_DEBUG
226  			printf("Debugging disabled with "
227  			       "CONFIG_NO_STDOUT_DEBUG=y build time "
228  			       "option.\n");
229  			goto out;
230  #else /* CONFIG_NO_STDOUT_DEBUG */
231  			params.wpa_debug_level--;
232  			break;
233  #endif /* CONFIG_NO_STDOUT_DEBUG */
234  		case 'e':
235  			params.entropy_file = optarg;
236  			break;
237  #ifdef CONFIG_DEBUG_FILE
238  		case 'f':
239  			params.wpa_debug_file_path = optarg;
240  			break;
241  #endif /* CONFIG_DEBUG_FILE */
242  		case 'g':
243  			params.ctrl_interface = optarg;
244  			break;
245  		case 'G':
246  			params.ctrl_interface_group = optarg;
247  			break;
248  		case 'h':
249  			usage();
250  			exitcode = 0;
251  			goto out;
252  		case 'i':
253  			iface->ifname = optarg;
254  			break;
255  		case 'I':
256  			iface->confanother = optarg;
257  			break;
258  		case 'K':
259  			params.wpa_debug_show_keys++;
260  			break;
261  		case 'L':
262  			license();
263  			exitcode = 0;
264  			goto out;
265  #ifdef CONFIG_P2P
266  		case 'm':
267  			params.conf_p2p_dev = optarg;
268  			break;
269  #endif /* CONFIG_P2P */
270  		case 'o':
271  			params.override_driver = optarg;
272  			break;
273  		case 'O':
274  			params.override_ctrl_interface = optarg;
275  			break;
276  		case 'p':
277  			iface->driver_param = optarg;
278  			break;
279  		case 'P':
280  			os_free(params.pid_file);
281  			params.pid_file = os_rel2abs_path(optarg);
282  			break;
283  		case 'q':
284  			params.wpa_debug_level++;
285  			break;
286  #ifdef CONFIG_DEBUG_SYSLOG
287  		case 's':
288  			params.wpa_debug_syslog++;
289  			break;
290  #endif /* CONFIG_DEBUG_SYSLOG */
291  #ifdef CONFIG_DEBUG_LINUX_TRACING
292  		case 'T':
293  			params.wpa_debug_tracing++;
294  			break;
295  #endif /* CONFIG_DEBUG_LINUX_TRACING */
296  		case 't':
297  			params.wpa_debug_timestamp++;
298  			break;
299  #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
300  		case 'u':
301  			params.dbus_ctrl_interface = 1;
302  			break;
303  #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
304  		case 'v':
305  			printf("%s\n", wpa_supplicant_version);
306  			exitcode = 0;
307  			goto out;
308  		case 'W':
309  			params.wait_for_monitor++;
310  			break;
311  #ifdef CONFIG_MATCH_IFACE
312  		case 'M':
313  			params.match_iface_count++;
314  			iface = os_realloc_array(params.match_ifaces,
315  						 params.match_iface_count,
316  						 sizeof(struct wpa_interface));
317  			if (!iface)
318  				goto out;
319  			params.match_ifaces = iface;
320  			iface = &params.match_ifaces[params.match_iface_count -
321  						     1];
322  			os_memset(iface, 0, sizeof(*iface));
323  			break;
324  #endif /* CONFIG_MATCH_IFACE */
325  		case 'N':
326  			iface_count++;
327  			iface = os_realloc_array(ifaces, iface_count,
328  						 sizeof(struct wpa_interface));
329  			if (iface == NULL)
330  				goto out;
331  			ifaces = iface;
332  			iface = &ifaces[iface_count - 1];
333  			os_memset(iface, 0, sizeof(*iface));
334  			break;
335  		default:
336  			usage();
337  			exitcode = 0;
338  			goto out;
339  		}
340  	}
341  
342  	exitcode = 0;
343  	global = wpa_supplicant_init(&params);
344  	if (global == NULL) {
345  		wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant");
346  		exitcode = -1;
347  		goto out;
348  	} else {
349  		wpa_printf(MSG_INFO, "Successfully initialized "
350  			   "wpa_supplicant");
351  	}
352  
353  	if (fst_global_init()) {
354  		wpa_printf(MSG_ERROR, "Failed to initialize FST");
355  		exitcode = -1;
356  		goto out;
357  	}
358  
359  #if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
360  	if (!fst_global_add_ctrl(fst_ctrl_cli))
361  		wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
362  #endif
363  
364  	for (i = 0; exitcode == 0 && i < iface_count; i++) {
365  		struct wpa_supplicant *wpa_s;
366  
367  		if ((ifaces[i].confname == NULL &&
368  		     ifaces[i].ctrl_interface == NULL) ||
369  		    ifaces[i].ifname == NULL) {
370  			if (iface_count == 1 && (params.ctrl_interface ||
371  #ifdef CONFIG_MATCH_IFACE
372  						 params.match_iface_count ||
373  #endif /* CONFIG_MATCH_IFACE */
374  						 params.dbus_ctrl_interface))
375  				break;
376  			usage();
377  			exitcode = -1;
378  			break;
379  		}
380  		wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL);
381  		if (wpa_s == NULL) {
382  			exitcode = -1;
383  			break;
384  		}
385  	}
386  
387  #ifdef CONFIG_MATCH_IFACE
388  	if (exitcode == 0)
389  		exitcode = wpa_supplicant_init_match(global);
390  #endif /* CONFIG_MATCH_IFACE */
391  
392  	if (exitcode == 0)
393  		exitcode = wpa_supplicant_run(global);
394  
395  	wpa_supplicant_deinit(global);
396  
397  	fst_global_deinit();
398  
399  out:
400  	wpa_supplicant_fd_workaround(0);
401  	os_free(ifaces);
402  #ifdef CONFIG_MATCH_IFACE
403  	os_free(params.match_ifaces);
404  #endif /* CONFIG_MATCH_IFACE */
405  	os_free(params.pid_file);
406  
407  	crypto_unload();
408  	os_program_deinit();
409  
410  	return exitcode;
411  }
412