Example #1
0
int
main(int argc, char *argv[])
{
	struct wpa_supplicant wpa_s;
	char *link = NULL;
	char *key = NULL;
	dlpi_handle_t dh = NULL;
	datalink_id_t linkid;
	dladm_phys_attr_t dpa;
	int c;
	int exitcode;
	char door_file[WPA_STRSIZE];

	for (;;) {
		c = getopt(argc, argv, "Dk:hi:v");
		if (c < 0)
			break;
		switch (c) {
		case 'D':
			wpa_debug_level = MSG_DEBUG;
			break;
		case 'h':
			usage();
			return (-1);
		case 'i':
			link = optarg;
			break;
		case 'k':
			key = optarg;
			break;
		case 'v':
			(void) printf("%s\n", wpa_supplicant_version);
			return (-1);
		default:
			usage();
			return (-1);
		}
	}

	/*
	 * key name is required to retrieve PSK value through libwdladm APIs.
	 * key is saved by dladm command by keyname
	 * see dladm.
	 */
	if ((link == NULL) || (key == NULL)) {
		wpa_printf(MSG_ERROR, "\nLink & key is required.");
		return (-1);
	}

	if ((strlen(key) >= sizeof (wpa_s.kname)))  {
		wpa_printf(MSG_ERROR, "Too long key name '%s'.", key);
		return (-1);
	}

	if (daemon(0, 0))
		return (-1);

	/*
	 * Hold this link open to prevent a link renaming operation.
	 */
	if (dlpi_open(link, &dh, 0) != DLPI_SUCCESS) {
		wpa_printf(MSG_ERROR, "Failed to open link '%s'.", link);
		return (-1);
	}

	if (dladm_name2info(link, &linkid, NULL, NULL, NULL) !=
	    DLADM_STATUS_OK) {
		wpa_printf(MSG_ERROR, "Invalid link name '%s'.", link);
		dlpi_close(dh);
		return (-1);
	}

	/*
	 * Get the device name of the link, which will be used as the door
	 * file name used to communicate with the driver. Note that different
	 * links use different doors.
	 */
	if (dladm_phys_info(linkid, &dpa, DLADM_OPT_ACTIVE) !=
	    DLADM_STATUS_OK) {
		wpa_printf(MSG_ERROR,
		    "Failed to get device name of link '%s'.", link);
		dlpi_close(dh);
		return (-1);
	}
	(void) snprintf(door_file, WPA_STRSIZE, "%s_%s", WPA_DOOR, dpa.dp_dev);

	(void) memset(&wpa_s, 0, sizeof (wpa_s));
	wpa_s.driver = &wpa_driver_wifi_ops;
	wpa_s.linkid = linkid;
	(void) strlcpy(wpa_s.kname, key, sizeof (wpa_s.kname));
	eloop_init(&wpa_s);

	/*
	 * Setup default WPA/WPA2 configuration
	 * get ESSID and PSK value
	 */
	wpa_s.conf = wpa_config_read(&wpa_s);
	if (wpa_s.conf == NULL || wpa_s.conf->ssid == NULL) {
		wpa_printf(MSG_ERROR, "\nNo networks (SSID) configured.\n");
		exitcode = -1;
		goto cleanup;
	}

	exitcode = 0;

	/*
	 * Setup door file to communicate with driver
	 */
	if (wpa_supplicant_door_setup(&wpa_s, door_file) != 0) {
		wpa_printf(MSG_ERROR, "Failed to setup door(%s)", door_file);
		exitcode = -1;
		goto cleanup;
	}

	wpa_s.renew_snonce = 1;
	if (wpa_supplicant_driver_init(link, &wpa_s) < 0) {
		exitcode = -1;
		goto cleanup;
	}

	/*
	 * This link is hold again in wpa_supplicant_driver_init(), so that
	 * we release the first reference.
	 */
	dlpi_close(dh);
	dh = NULL;

	wpa_printf(MSG_DEBUG, "=> eloop_run");

	(void) eloop_register_signal(SIGINT, wpa_supplicant_terminate, NULL);
	(void) eloop_register_signal(SIGTERM, wpa_supplicant_terminate, NULL);
	(void) eloop_register_signal(SIGKILL, wpa_supplicant_terminate, NULL);

	eloop_run();

	wpa_printf(MSG_DEBUG, "<= eloop_run()");
	wpa_supplicant_disassociate(&wpa_s, REASON_DEAUTH_LEAVING);

	if (wpa_s.driver->set_wpa(wpa_s.linkid, 0) < 0) {
		wpa_printf(MSG_ERROR, "Failed to disable WPA in the driver.\n");
	}

cleanup:
	wpa_supplicant_door_destroy(door_file);
	wpa_supplicant_cleanup(&wpa_s);
	eloop_destroy();

	if (dh != NULL)
		dlpi_close(dh);

	return (exitcode);
}
Example #2
0
/*
 * This function attempts to open a device under the following namespaces:
 *	/dev/ipnet	- if DLPI_DEVIPNET is specified
 *      /dev/net	- if a data-link with the specified name exists
 *	/dev		- if DLPI_DEVONLY is specified, or if there is no
 *			  data-link with the specified name (could be /dev/ip)
 *
 * In particular, if DLPI_DEVIPNET is not specified, this function is used to
 * open a data-link node, or "/dev/ip" node. It is usually be called firstly
 * with style1 being B_TRUE, and if that fails and the return value is not
 * DLPI_ENOTSTYLE2, the function will again be called with style1 being
 * B_FALSE (style-1 open attempt first, then style-2 open attempt).
 *
 * If DLPI_DEVONLY is specified, both attempt will try to open the /dev node
 * directly.
 *
 * Otherwise, for style-1 attempt, the function will try to open the style-1
 * /dev/net node, and perhaps fallback to open the style-1 /dev node if the
 * give name is not a data-link name (e.g., it is /dev/ip). Note that the
 * fallback and the subsequent style-2 attempt will not happen if:
 * 1. style-1 opening of the /dev/net node succeeds;
 * 2. style-1 opening of the /dev/net node fails with errno other than ENOENT,
 *    which means that the specific /dev/net node exist, but the attempt fails
 *    for some other reason;
 * 3. style-1 openning of the /dev/net fails with ENOENT, but the name is
 *    a known device name or its VLAN PPA hack name. (for example, assuming
 *    device bge0 is renamed to net0, opening /dev/net/bge1000 would return
 *    ENOENT, but we should not fallback to open /dev/bge1000 in this case,
 *    as VLAN 1 over the bge0 device should be named as net1000.
 *
 * DLPI_ENOTSTYLE2 will be returned in case 2 and 3 to indicate not to proceed
 * the second style-2 open attempt.
 */
static int
i_dlpi_open(const char *provider, int *fd, uint_t flags, boolean_t style1)
{
	char		path[MAXPATHLEN];
	int		oflags;

	errno = ENOENT;
	oflags = O_RDWR;
	if (flags & DLPI_EXCL)
		oflags |= O_EXCL;

	if (flags & DLPI_DEVIPNET) {
		(void) snprintf(path, sizeof (path), "/dev/ipnet/%s", provider);
		if ((*fd = open(path, oflags)) != -1)
			return (DLPI_SUCCESS);
		else
			return (errno == ENOENT ? DLPI_ENOLINK : DL_SYSERR);
	} else if (style1 && !(flags & DLPI_DEVONLY)) {
		char		driver[DLPI_LINKNAME_MAX];
		char		device[DLPI_LINKNAME_MAX];
		datalink_id_t	linkid;
		uint_t		ppa;
		dladm_handle_t	handle;

		/*
		 * This is not a valid style-1 name. It could be "ip" module
		 * for example. Fallback to open the /dev node.
		 */
		if (dlpi_parselink(provider, driver, &ppa) != DLPI_SUCCESS)
			goto fallback;

		(void) snprintf(path, sizeof (path), "/dev/net/%s", provider);
		if ((*fd = open(path, oflags)) != -1)
			return (DLPI_SUCCESS);

		/*
		 * We don't fallback to open the /dev node when it returns
		 * error codes other than ENOENT. In that case, DLPI_ENOTSTYLE2
		 * is returned to indicate not to continue the style-2 open.
		 */
		if (errno != ENOENT)
			return (DLPI_ENOTSTYLE2);

		/*
		 * We didn't find the /dev/net node. Then we check whether
		 * the given name is a device name or its VLAN PPA hack name
		 * of a known link. If the answer is yes, and this link
		 * supports vanity naming, then the link (or the VLAN) should
		 * also have its /dev/net node but perhaps with another vanity
		 * name (for example, when bge0 is renamed to net0). In this
		 * case, although attempt to open the /dev/net/<devname> fails,
		 * we should not fallback to open the /dev/<devname> node.
		 */
		(void) snprintf(device, DLPI_LINKNAME_MAX, "%s%d", driver,
		    ppa >= 1000 ? ppa % 1000 : ppa);

		/* open libdladm handle rather than taking it as input */
		if (dladm_open(&handle) != DLADM_STATUS_OK)
			goto fallback;

		if (dladm_dev2linkid(handle, device, &linkid) ==
		    DLADM_STATUS_OK) {
			dladm_phys_attr_t dpa;

			if ((dladm_phys_info(handle, linkid, &dpa,
			    DLADM_OPT_ACTIVE)) == DLADM_STATUS_OK &&
			    !dpa.dp_novanity) {
				dladm_close(handle);
				return (DLPI_ENOTSTYLE2);
			}
		}
		dladm_close(handle);
	}

fallback:
	(void) snprintf(path, sizeof (path), "/dev/%s", provider);
	if ((*fd = open(path, oflags)) != -1)
		return (DLPI_SUCCESS);

	return (errno == ENOENT ? DLPI_ENOLINK : DL_SYSERR);
}