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); }
/* * 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); }