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