18dbcf02cSchristos /*
28dbcf02cSchristos * WPA Supplicant / main() function for UNIX like OSes and MinGW
336d97821Schristos * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
48dbcf02cSchristos *
562a52023Schristos * This software may be distributed under the terms of the BSD license.
662a52023Schristos * See README for more details.
78dbcf02cSchristos */
88dbcf02cSchristos
98dbcf02cSchristos #include "includes.h"
108dbcf02cSchristos #ifdef __linux__
118dbcf02cSchristos #include <fcntl.h>
128dbcf02cSchristos #endif /* __linux__ */
138dbcf02cSchristos
148dbcf02cSchristos #include "common.h"
158d355d6fSchristos #include "fst/fst.h"
168dbcf02cSchristos #include "wpa_supplicant_i.h"
178dbcf02cSchristos #include "driver_i.h"
1836d97821Schristos #include "p2p_supplicant.h"
198dbcf02cSchristos
208dbcf02cSchristos
usage(void)218dbcf02cSchristos static void usage(void)
228dbcf02cSchristos {
238dbcf02cSchristos int i;
248dbcf02cSchristos printf("%s\n\n%s\n"
258dbcf02cSchristos "usage:\n"
2636d97821Schristos " wpa_supplicant [-BddhKLqq"
2736d97821Schristos #ifdef CONFIG_DEBUG_SYSLOG
2836d97821Schristos "s"
2936d97821Schristos #endif /* CONFIG_DEBUG_SYSLOG */
3036d97821Schristos "t"
31*0dddab58Schristos #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
3236d97821Schristos "u"
33*0dddab58Schristos #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
3436d97821Schristos "vW] [-P<pid file>] "
358dbcf02cSchristos "[-g<global ctrl>] \\\n"
3636d97821Schristos " [-G<group>] \\\n"
378dbcf02cSchristos " -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
388dbcf02cSchristos "[-p<driver_param>] \\\n"
3936d97821Schristos " [-b<br_ifname>] [-e<entropy file>]"
4036d97821Schristos #ifdef CONFIG_DEBUG_FILE
4136d97821Schristos " [-f<debug file>]"
4236d97821Schristos #endif /* CONFIG_DEBUG_FILE */
4342669be3Schristos " \\\n"
448dbcf02cSchristos " [-o<override driver>] [-O<override ctrl>] \\\n"
458dbcf02cSchristos " [-N -i<ifname> -c<conf> [-C<ctrl>] "
468dbcf02cSchristos "[-D<driver>] \\\n"
4736d97821Schristos #ifdef CONFIG_P2P
4836d97821Schristos " [-m<P2P Device config file>] \\\n"
4936d97821Schristos #endif /* CONFIG_P2P */
5036d97821Schristos " [-p<driver_param>] [-b<br_ifname>] [-I<config file>] "
5136d97821Schristos "...]\n"
528dbcf02cSchristos "\n"
538dbcf02cSchristos "drivers:\n",
548dbcf02cSchristos wpa_supplicant_version, wpa_supplicant_license);
558dbcf02cSchristos
568dbcf02cSchristos for (i = 0; wpa_drivers[i]; i++) {
578dbcf02cSchristos printf(" %s = %s\n",
588dbcf02cSchristos wpa_drivers[i]->name,
598dbcf02cSchristos wpa_drivers[i]->desc);
608dbcf02cSchristos }
618dbcf02cSchristos
628dbcf02cSchristos #ifndef CONFIG_NO_STDOUT_DEBUG
638dbcf02cSchristos printf("options:\n"
648dbcf02cSchristos " -b = optional bridge interface name\n"
658dbcf02cSchristos " -B = run daemon in the background\n"
668dbcf02cSchristos " -c = Configuration file\n"
678dbcf02cSchristos " -C = ctrl_interface parameter (only used if -c is not)\n"
688dbcf02cSchristos " -d = increase debugging verbosity (-dd even more)\n"
6942669be3Schristos " -D = driver name (can be multiple drivers: nl80211,wext)\n"
7066edc40fSroy " -e = entropy file\n"
718dbcf02cSchristos #ifdef CONFIG_DEBUG_FILE
7266edc40fSroy " -f = log output to debug file instead of stdout\n"
738dbcf02cSchristos #endif /* CONFIG_DEBUG_FILE */
7466edc40fSroy " -g = global ctrl_interface\n"
7536d97821Schristos " -G = global ctrl_interface group\n"
768dbcf02cSchristos " -h = show this help text\n"
7766edc40fSroy " -i = interface name\n"
7866edc40fSroy " -I = additional configuration file\n"
7966edc40fSroy " -K = include keys (passwords, etc.) in debug output\n"
8062a52023Schristos " -L = show license (BSD)\n"
8166edc40fSroy #ifdef CONFIG_P2P
8266edc40fSroy " -m = Configuration file for the P2P Device interface\n"
8366edc40fSroy #endif /* CONFIG_P2P */
846855b8beSroy #ifdef CONFIG_MATCH_IFACE
856855b8beSroy " -M = start describing new matching interface\n"
866855b8beSroy #endif /* CONFIG_MATCH_IFACE */
8766edc40fSroy " -N = start describing new interface\n"
888dbcf02cSchristos " -o = override driver parameter for new interfaces\n"
898dbcf02cSchristos " -O = override ctrl_interface parameter for new interfaces\n"
908dbcf02cSchristos " -p = driver parameters\n"
918dbcf02cSchristos " -P = PID file\n"
9266edc40fSroy " -q = decrease debugging verbosity (-qq even less)\n"
9366edc40fSroy #ifdef CONFIG_DEBUG_SYSLOG
9466edc40fSroy " -s = log output to syslog instead of stdout\n"
9566edc40fSroy #endif /* CONFIG_DEBUG_SYSLOG */
968d355d6fSchristos " -t = include timestamp in debug messages\n"
9766edc40fSroy #ifdef CONFIG_DEBUG_LINUX_TRACING
9866edc40fSroy " -T = record to Linux tracing in addition to logging\n"
9966edc40fSroy " (records all messages regardless of debug verbosity)\n"
10066edc40fSroy #endif /* CONFIG_DEBUG_LINUX_TRACING */
101*0dddab58Schristos #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
10266edc40fSroy " -u = enable DBus control interface\n"
103*0dddab58Schristos #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
10466edc40fSroy " -v = show version\n"
1058d355d6fSchristos " -W = wait for a control interface monitor before starting\n");
1068dbcf02cSchristos
1078dbcf02cSchristos printf("example:\n"
1088dbcf02cSchristos " wpa_supplicant -D%s -iwlan0 -c/etc/wpa_supplicant.conf\n",
10936d97821Schristos wpa_drivers[0] ? wpa_drivers[0]->name : "nl80211");
1108dbcf02cSchristos #endif /* CONFIG_NO_STDOUT_DEBUG */
1118dbcf02cSchristos }
1128dbcf02cSchristos
1138dbcf02cSchristos
license(void)1148dbcf02cSchristos static void license(void)
1158dbcf02cSchristos {
1168dbcf02cSchristos #ifndef CONFIG_NO_STDOUT_DEBUG
1178dbcf02cSchristos printf("%s\n\n%s%s%s%s%s\n",
1188dbcf02cSchristos wpa_supplicant_version,
1198dbcf02cSchristos wpa_supplicant_full_license1,
1208dbcf02cSchristos wpa_supplicant_full_license2,
1218dbcf02cSchristos wpa_supplicant_full_license3,
1228dbcf02cSchristos wpa_supplicant_full_license4,
1238dbcf02cSchristos wpa_supplicant_full_license5);
1248dbcf02cSchristos #endif /* CONFIG_NO_STDOUT_DEBUG */
1258dbcf02cSchristos }
1268dbcf02cSchristos
1278dbcf02cSchristos
wpa_supplicant_fd_workaround(int start)12862a52023Schristos static void wpa_supplicant_fd_workaround(int start)
1298dbcf02cSchristos {
1308dbcf02cSchristos #ifdef __linux__
13162a52023Schristos static int fd[3] = { -1, -1, -1 };
13262a52023Schristos int i;
1338dbcf02cSchristos /* When started from pcmcia-cs scripts, wpa_supplicant might start with
1348dbcf02cSchristos * fd 0, 1, and 2 closed. This will cause some issues because many
1358dbcf02cSchristos * places in wpa_supplicant are still printing out to stdout. As a
1368dbcf02cSchristos * workaround, make sure that fd's 0, 1, and 2 are not used for other
1378dbcf02cSchristos * sockets. */
13862a52023Schristos if (start) {
1398dbcf02cSchristos for (i = 0; i < 3; i++) {
14062a52023Schristos fd[i] = open("/dev/null", O_RDWR);
14162a52023Schristos if (fd[i] > 2) {
14262a52023Schristos close(fd[i]);
14362a52023Schristos fd[i] = -1;
1448dbcf02cSchristos break;
1458dbcf02cSchristos }
1468dbcf02cSchristos }
14762a52023Schristos } else {
14862a52023Schristos for (i = 0; i < 3; i++) {
14962a52023Schristos if (fd[i] >= 0) {
15062a52023Schristos close(fd[i]);
15162a52023Schristos fd[i] = -1;
15262a52023Schristos }
15362a52023Schristos }
15462a52023Schristos }
1558dbcf02cSchristos #endif /* __linux__ */
1568dbcf02cSchristos }
1578dbcf02cSchristos
1588dbcf02cSchristos
1596855b8beSroy #ifdef CONFIG_MATCH_IFACE
wpa_supplicant_init_match(struct wpa_global * global)1606855b8beSroy static int wpa_supplicant_init_match(struct wpa_global *global)
1616855b8beSroy {
1626855b8beSroy /*
1636855b8beSroy * The assumption is that the first driver is the primary driver and
1646855b8beSroy * will handle the arrival / departure of interfaces.
1656855b8beSroy */
1666855b8beSroy if (wpa_drivers[0]->global_init && !global->drv_priv[0]) {
1676855b8beSroy global->drv_priv[0] = wpa_drivers[0]->global_init(global);
1686855b8beSroy if (!global->drv_priv[0]) {
1696855b8beSroy wpa_printf(MSG_ERROR,
1706855b8beSroy "Failed to initialize driver '%s'",
1716855b8beSroy wpa_drivers[0]->name);
1726855b8beSroy return -1;
1736855b8beSroy }
1746855b8beSroy }
1756855b8beSroy
1766855b8beSroy return 0;
1776855b8beSroy }
1786855b8beSroy #endif /* CONFIG_MATCH_IFACE */
1796855b8beSroy
1806855b8beSroy
main(int argc,char * argv[])1818dbcf02cSchristos int main(int argc, char *argv[])
1828dbcf02cSchristos {
1838dbcf02cSchristos int c, i;
1848dbcf02cSchristos struct wpa_interface *ifaces, *iface;
1858dbcf02cSchristos int iface_count, exitcode = -1;
1868dbcf02cSchristos struct wpa_params params;
1878dbcf02cSchristos struct wpa_global *global;
1888dbcf02cSchristos
1898dbcf02cSchristos if (os_program_init())
1908dbcf02cSchristos return -1;
1918dbcf02cSchristos
1928dbcf02cSchristos os_memset(¶ms, 0, sizeof(params));
1938dbcf02cSchristos params.wpa_debug_level = MSG_INFO;
1948dbcf02cSchristos
1958dbcf02cSchristos iface = ifaces = os_zalloc(sizeof(struct wpa_interface));
1968dbcf02cSchristos if (ifaces == NULL)
1978dbcf02cSchristos return -1;
1988dbcf02cSchristos iface_count = 1;
1998dbcf02cSchristos
20062a52023Schristos wpa_supplicant_fd_workaround(1);
2018dbcf02cSchristos
2028dbcf02cSchristos for (;;) {
20362a52023Schristos c = getopt(argc, argv,
2046855b8beSroy "b:Bc:C:D:de:f:g:G:hi:I:KLMm:No:O:p:P:qsTtuvW");
2058dbcf02cSchristos if (c < 0)
2068dbcf02cSchristos break;
2078dbcf02cSchristos switch (c) {
2088dbcf02cSchristos case 'b':
2098dbcf02cSchristos iface->bridge_ifname = optarg;
2108dbcf02cSchristos break;
2118dbcf02cSchristos case 'B':
2128dbcf02cSchristos params.daemonize++;
2138dbcf02cSchristos break;
2148dbcf02cSchristos case 'c':
2158dbcf02cSchristos iface->confname = optarg;
2168dbcf02cSchristos break;
2178dbcf02cSchristos case 'C':
2188dbcf02cSchristos iface->ctrl_interface = optarg;
2198dbcf02cSchristos break;
2208dbcf02cSchristos case 'D':
2218dbcf02cSchristos iface->driver = optarg;
2228dbcf02cSchristos break;
2238dbcf02cSchristos case 'd':
2248dbcf02cSchristos #ifdef CONFIG_NO_STDOUT_DEBUG
2258dbcf02cSchristos printf("Debugging disabled with "
2268dbcf02cSchristos "CONFIG_NO_STDOUT_DEBUG=y build time "
2278dbcf02cSchristos "option.\n");
2288dbcf02cSchristos goto out;
2298dbcf02cSchristos #else /* CONFIG_NO_STDOUT_DEBUG */
2308dbcf02cSchristos params.wpa_debug_level--;
2318dbcf02cSchristos break;
2328dbcf02cSchristos #endif /* CONFIG_NO_STDOUT_DEBUG */
23342669be3Schristos case 'e':
23442669be3Schristos params.entropy_file = optarg;
23542669be3Schristos break;
2368dbcf02cSchristos #ifdef CONFIG_DEBUG_FILE
2378dbcf02cSchristos case 'f':
2388dbcf02cSchristos params.wpa_debug_file_path = optarg;
2398dbcf02cSchristos break;
2408dbcf02cSchristos #endif /* CONFIG_DEBUG_FILE */
2418dbcf02cSchristos case 'g':
2428dbcf02cSchristos params.ctrl_interface = optarg;
2438dbcf02cSchristos break;
24436d97821Schristos case 'G':
24536d97821Schristos params.ctrl_interface_group = optarg;
24636d97821Schristos break;
2478dbcf02cSchristos case 'h':
2488dbcf02cSchristos usage();
2498dbcf02cSchristos exitcode = 0;
2508dbcf02cSchristos goto out;
2518dbcf02cSchristos case 'i':
2528dbcf02cSchristos iface->ifname = optarg;
2538dbcf02cSchristos break;
25436d97821Schristos case 'I':
25536d97821Schristos iface->confanother = optarg;
25636d97821Schristos break;
2578dbcf02cSchristos case 'K':
2588dbcf02cSchristos params.wpa_debug_show_keys++;
2598dbcf02cSchristos break;
2608dbcf02cSchristos case 'L':
2618dbcf02cSchristos license();
2628dbcf02cSchristos exitcode = 0;
2638dbcf02cSchristos goto out;
26436d97821Schristos #ifdef CONFIG_P2P
26536d97821Schristos case 'm':
2668d355d6fSchristos params.conf_p2p_dev = optarg;
26736d97821Schristos break;
26836d97821Schristos #endif /* CONFIG_P2P */
2698dbcf02cSchristos case 'o':
2708dbcf02cSchristos params.override_driver = optarg;
2718dbcf02cSchristos break;
2728dbcf02cSchristos case 'O':
2738dbcf02cSchristos params.override_ctrl_interface = optarg;
2748dbcf02cSchristos break;
2758dbcf02cSchristos case 'p':
2768dbcf02cSchristos iface->driver_param = optarg;
2778dbcf02cSchristos break;
2788dbcf02cSchristos case 'P':
2798dbcf02cSchristos os_free(params.pid_file);
2808dbcf02cSchristos params.pid_file = os_rel2abs_path(optarg);
2818dbcf02cSchristos break;
2828dbcf02cSchristos case 'q':
2838dbcf02cSchristos params.wpa_debug_level++;
2848dbcf02cSchristos break;
2858dbcf02cSchristos #ifdef CONFIG_DEBUG_SYSLOG
2868dbcf02cSchristos case 's':
2878dbcf02cSchristos params.wpa_debug_syslog++;
2888dbcf02cSchristos break;
2898dbcf02cSchristos #endif /* CONFIG_DEBUG_SYSLOG */
29062a52023Schristos #ifdef CONFIG_DEBUG_LINUX_TRACING
29162a52023Schristos case 'T':
29262a52023Schristos params.wpa_debug_tracing++;
29362a52023Schristos break;
29462a52023Schristos #endif /* CONFIG_DEBUG_LINUX_TRACING */
2958dbcf02cSchristos case 't':
2968dbcf02cSchristos params.wpa_debug_timestamp++;
2978dbcf02cSchristos break;
298*0dddab58Schristos #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
2998dbcf02cSchristos case 'u':
3008dbcf02cSchristos params.dbus_ctrl_interface = 1;
3018dbcf02cSchristos break;
302*0dddab58Schristos #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
3038dbcf02cSchristos case 'v':
3048dbcf02cSchristos printf("%s\n", wpa_supplicant_version);
3058dbcf02cSchristos exitcode = 0;
3068dbcf02cSchristos goto out;
3078dbcf02cSchristos case 'W':
3088dbcf02cSchristos params.wait_for_monitor++;
3098dbcf02cSchristos break;
3106855b8beSroy #ifdef CONFIG_MATCH_IFACE
3116855b8beSroy case 'M':
3126855b8beSroy params.match_iface_count++;
3136855b8beSroy iface = os_realloc_array(params.match_ifaces,
3146855b8beSroy params.match_iface_count,
3156855b8beSroy sizeof(struct wpa_interface));
3166855b8beSroy if (!iface)
3176855b8beSroy goto out;
3186855b8beSroy params.match_ifaces = iface;
3196855b8beSroy iface = ¶ms.match_ifaces[params.match_iface_count -
3206855b8beSroy 1];
3216855b8beSroy os_memset(iface, 0, sizeof(*iface));
3226855b8beSroy break;
3236855b8beSroy #endif /* CONFIG_MATCH_IFACE */
3248dbcf02cSchristos case 'N':
3258dbcf02cSchristos iface_count++;
32662a52023Schristos iface = os_realloc_array(ifaces, iface_count,
3278dbcf02cSchristos sizeof(struct wpa_interface));
3288dbcf02cSchristos if (iface == NULL)
3298dbcf02cSchristos goto out;
3308dbcf02cSchristos ifaces = iface;
3318dbcf02cSchristos iface = &ifaces[iface_count - 1];
3328dbcf02cSchristos os_memset(iface, 0, sizeof(*iface));
3338dbcf02cSchristos break;
3348dbcf02cSchristos default:
3358dbcf02cSchristos usage();
3368dbcf02cSchristos exitcode = 0;
3378dbcf02cSchristos goto out;
3388dbcf02cSchristos }
3398dbcf02cSchristos }
3408dbcf02cSchristos
3418dbcf02cSchristos exitcode = 0;
3428dbcf02cSchristos global = wpa_supplicant_init(¶ms);
3438dbcf02cSchristos if (global == NULL) {
3448dbcf02cSchristos wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant");
3458dbcf02cSchristos exitcode = -1;
3468dbcf02cSchristos goto out;
34762a52023Schristos } else {
34862a52023Schristos wpa_printf(MSG_INFO, "Successfully initialized "
34962a52023Schristos "wpa_supplicant");
3508dbcf02cSchristos }
3518dbcf02cSchristos
3528d355d6fSchristos if (fst_global_init()) {
3538d355d6fSchristos wpa_printf(MSG_ERROR, "Failed to initialize FST");
3548d355d6fSchristos exitcode = -1;
3558d355d6fSchristos goto out;
3568d355d6fSchristos }
3578d355d6fSchristos
3588d355d6fSchristos #if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE)
3598d355d6fSchristos if (!fst_global_add_ctrl(fst_ctrl_cli))
3608d355d6fSchristos wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl");
3618d355d6fSchristos #endif
3628d355d6fSchristos
3638dbcf02cSchristos for (i = 0; exitcode == 0 && i < iface_count; i++) {
36436d97821Schristos struct wpa_supplicant *wpa_s;
36536d97821Schristos
3668dbcf02cSchristos if ((ifaces[i].confname == NULL &&
3678dbcf02cSchristos ifaces[i].ctrl_interface == NULL) ||
3688dbcf02cSchristos ifaces[i].ifname == NULL) {
3698dbcf02cSchristos if (iface_count == 1 && (params.ctrl_interface ||
3706855b8beSroy #ifdef CONFIG_MATCH_IFACE
3716855b8beSroy params.match_iface_count ||
3726855b8beSroy #endif /* CONFIG_MATCH_IFACE */
3738dbcf02cSchristos params.dbus_ctrl_interface))
3748dbcf02cSchristos break;
3758dbcf02cSchristos usage();
3768dbcf02cSchristos exitcode = -1;
3778dbcf02cSchristos break;
3788dbcf02cSchristos }
3799a53cbbeSchristos wpa_s = wpa_supplicant_add_iface(global, &ifaces[i], NULL);
38036d97821Schristos if (wpa_s == NULL) {
3818dbcf02cSchristos exitcode = -1;
38236d97821Schristos break;
38336d97821Schristos }
3848dbcf02cSchristos }
3858dbcf02cSchristos
3866855b8beSroy #ifdef CONFIG_MATCH_IFACE
3876855b8beSroy if (exitcode == 0)
3886855b8beSroy exitcode = wpa_supplicant_init_match(global);
3896855b8beSroy #endif /* CONFIG_MATCH_IFACE */
3906855b8beSroy
3918dbcf02cSchristos if (exitcode == 0)
3928dbcf02cSchristos exitcode = wpa_supplicant_run(global);
3938dbcf02cSchristos
3948dbcf02cSchristos wpa_supplicant_deinit(global);
3958dbcf02cSchristos
3968d355d6fSchristos fst_global_deinit();
3978d355d6fSchristos
3988dbcf02cSchristos out:
39962a52023Schristos wpa_supplicant_fd_workaround(0);
4008dbcf02cSchristos os_free(ifaces);
4016855b8beSroy #ifdef CONFIG_MATCH_IFACE
4026855b8beSroy os_free(params.match_ifaces);
4036855b8beSroy #endif /* CONFIG_MATCH_IFACE */
4048dbcf02cSchristos os_free(params.pid_file);
4058dbcf02cSchristos
4068dbcf02cSchristos os_program_deinit();
4078dbcf02cSchristos
4088dbcf02cSchristos return exitcode;
4098dbcf02cSchristos }
410