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