14126Szf162725 /* 25895Syz147064 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 34126Szf162725 * Use is subject to license terms. 44126Szf162725 */ 54126Szf162725 64126Szf162725 /* 74126Szf162725 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> 84126Szf162725 * Sun elects to license this software under the BSD license. 94126Szf162725 * See README for more details. 104126Szf162725 */ 114126Szf162725 124126Szf162725 #include <stdio.h> 134126Szf162725 #include <stdlib.h> 144126Szf162725 #include <stdarg.h> 154126Szf162725 #include <unistd.h> 164126Szf162725 #include <string.h> 174126Szf162725 #include <syslog.h> 184126Szf162725 #include <sys/stat.h> 194126Szf162725 #include <errno.h> 204126Szf162725 #include <signal.h> 214126Szf162725 #include <fcntl.h> 224126Szf162725 #include <door.h> 236411Szf162725 #include <libscf.h> 244126Szf162725 #include <libdladm.h> 254126Szf162725 #include <libdllink.h> 264126Szf162725 #include <sys/ethernet.h> 274126Szf162725 284126Szf162725 #include "wpa_impl.h" 294126Szf162725 #include "wpa_enc.h" 304126Szf162725 #include "driver.h" 314126Szf162725 #include "eloop.h" 324126Szf162725 #include "l2_packet.h" 334126Szf162725 344126Szf162725 extern struct wpa_driver_ops wpa_driver_wifi_ops; 354126Szf162725 int wpa_debug_level = MSG_ERROR; 364126Szf162725 374126Szf162725 /* 384126Szf162725 * wpa_printf - conditional printf 394126Szf162725 * @level: priority level (MSG_*) of the message 404126Szf162725 * @fmt: printf format string, followed by optional arguments 414126Szf162725 * 424126Szf162725 * This function is used to print conditional debugging and error messages. The 434126Szf162725 * output may be directed to stdout, stderr, and/or syslog based on 444126Szf162725 * configuration. 454126Szf162725 */ 464126Szf162725 void 474126Szf162725 wpa_printf(int level, char *fmt, ...) 484126Szf162725 { 494126Szf162725 va_list ap; 504126Szf162725 char buffer[MAX_LOGBUF]; 514126Szf162725 524126Szf162725 if (level < wpa_debug_level) 534126Szf162725 return; 544126Szf162725 554126Szf162725 va_start(ap, fmt); 564126Szf162725 574126Szf162725 /* LINTED E_SEC_PRINTF_VAR_FMT */ 584126Szf162725 (void) vsnprintf(buffer, sizeof (buffer), fmt, ap); 594126Szf162725 604126Szf162725 va_end(ap); 614126Szf162725 624126Szf162725 syslog(LOG_NOTICE | LOG_DAEMON, "%s", buffer); 634126Szf162725 } 644126Szf162725 654126Szf162725 /* 664126Szf162725 * wpa_hexdump - conditional hex dump 674126Szf162725 * @level: priority level (MSG_*) of the message 684126Szf162725 * @title: title of for the message 694126Szf162725 * @buf: data buffer to be dumped 704126Szf162725 * @len: length of the @buf 714126Szf162725 * 724126Szf162725 * This function is used to print conditional debugging and error messages. The 734126Szf162725 * output may be directed to stdout, stderr, and/or syslog based on 744126Szf162725 * configuration. The contents of @buf is printed out has hex dump. 754126Szf162725 */ 764126Szf162725 void 774126Szf162725 wpa_hexdump(int level, const char *title, const uint8_t *buf, size_t len) 784126Szf162725 { 794126Szf162725 size_t i; 804126Szf162725 char buffer[MAX_LOGBUF], tmp[4]; 814126Szf162725 int n; 824126Szf162725 834126Szf162725 if (level < wpa_debug_level) 844126Szf162725 return; 854126Szf162725 864126Szf162725 (void) snprintf(buffer, sizeof (buffer), "%s - hexdump(len=%d):", 874126Szf162725 title, len); 884126Szf162725 n = strlen(buffer); 894126Szf162725 904126Szf162725 for (i = 0; i < len; i++) { 914126Szf162725 (void) sprintf(tmp, " %02x", buf[i]); 924126Szf162725 934126Szf162725 n += strlen(tmp); 944126Szf162725 if (n >= MAX_LOGBUF) break; 954126Szf162725 964126Szf162725 (void) strlcat(buffer, tmp, sizeof (buffer)); 974126Szf162725 } 984126Szf162725 994126Szf162725 syslog(LOG_NOTICE | LOG_DAEMON, "%s", buffer); 1004126Szf162725 } 1014126Szf162725 1024126Szf162725 static const char * 1034126Szf162725 wpa_ssid_txt(char *ssid, size_t ssid_len) 1044126Szf162725 { 1054126Szf162725 static char ssid_txt[MAX_ESSID_LENGTH + 1]; 1064126Szf162725 char *pos; 1074126Szf162725 1084126Szf162725 if (ssid_len > MAX_ESSID_LENGTH) 1094126Szf162725 ssid_len = MAX_ESSID_LENGTH; 1104126Szf162725 (void) memcpy(ssid_txt, ssid, ssid_len); 1114126Szf162725 ssid_txt[ssid_len] = '\0'; 1124126Szf162725 for (pos = ssid_txt; *pos != '\0'; pos ++) { 1134126Szf162725 if ((uint8_t)*pos < 32 || (uint8_t)*pos >= 127) 1144126Szf162725 *pos = '_'; 1154126Szf162725 } 1164126Szf162725 return (ssid_txt); 1174126Szf162725 } 1184126Szf162725 1194126Szf162725 /* ARGSUSED */ 1204126Szf162725 void 1214126Szf162725 wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) 1224126Szf162725 { 1234126Szf162725 struct wpa_supplicant *wpa_s = eloop_ctx; 1244126Szf162725 struct wpa_ssid *ssid; 1254126Szf162725 1264126Szf162725 if (wpa_s->conf == NULL) 1274126Szf162725 return; 1284126Szf162725 1294126Szf162725 if (wpa_s->wpa_state == WPA_DISCONNECTED) 1304126Szf162725 wpa_s->wpa_state = WPA_SCANNING; 1314126Szf162725 1324126Szf162725 ssid = wpa_s->conf->ssid; 1334126Szf162725 wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)", 1344126Szf162725 ssid ? "specific": "broadcast"); 1354126Szf162725 1364126Szf162725 if (ssid) { 1374126Szf162725 wpa_printf(MSG_DEBUG, "Scan SSID: %s", ssid->ssid); 1384126Szf162725 } 1394126Szf162725 140*8453SAnurag.Maskey@Sun.COM if (wpa_s->driver->scan(wpa_s->handle, wpa_s->linkid)) { 1414126Szf162725 wpa_printf(MSG_WARNING, "Failed to initiate AP scan."); 1424126Szf162725 } 1434126Szf162725 } 1444126Szf162725 1454126Szf162725 void 1464126Szf162725 wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) 1474126Szf162725 { 1484126Szf162725 wpa_printf(MSG_DEBUG, "Setting scan request: %d sec %d usec", 1494126Szf162725 sec, usec); 1504126Szf162725 (void) eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 1514126Szf162725 (void) eloop_register_timeout(sec, usec, wpa_supplicant_scan, 1524126Szf162725 wpa_s, NULL); 1534126Szf162725 } 1544126Szf162725 1554126Szf162725 void 1564126Szf162725 wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) 1574126Szf162725 { 1584126Szf162725 wpa_printf(MSG_DEBUG, "Cancelling scan request"); 1594126Szf162725 eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 1604126Szf162725 } 1614126Szf162725 1624126Szf162725 /* ARGSUSED */ 1634126Szf162725 static void 1644126Szf162725 wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx) 1654126Szf162725 { 1664126Szf162725 struct wpa_supplicant *wpa_s = eloop_ctx; 1674126Szf162725 1684126Szf162725 wpa_printf(MSG_INFO, "Authentication with " MACSTR " timed out.", 1694126Szf162725 MAC2STR(wpa_s->bssid)); 1704126Szf162725 1714126Szf162725 wpa_s->reassociate = 1; 1724126Szf162725 wpa_supplicant_req_scan(wpa_s, 0, 0); 1734126Szf162725 } 1744126Szf162725 1754126Szf162725 void 1764126Szf162725 wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, 1774126Szf162725 int sec, int usec) 1784126Szf162725 { 1794126Szf162725 wpa_printf(MSG_DEBUG, "Setting authentication timeout: %d sec " 1804126Szf162725 "%d usec", sec, usec); 1814126Szf162725 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); 1824126Szf162725 (void) eloop_register_timeout(sec, usec, wpa_supplicant_timeout, 1834126Szf162725 wpa_s, NULL); 1844126Szf162725 } 1854126Szf162725 1864126Szf162725 void 1874126Szf162725 wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s) 1884126Szf162725 { 1894126Szf162725 wpa_printf(MSG_DEBUG, "Cancelling authentication timeout"); 1904126Szf162725 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); 1914126Szf162725 } 1924126Szf162725 1934126Szf162725 static void 1944126Szf162725 wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) 1954126Szf162725 { 1964126Szf162725 l2_packet_deinit(wpa_s->l2); 1974126Szf162725 wpa_s->l2 = NULL; 1984126Szf162725 1994126Szf162725 if (wpa_s->conf != NULL) { 2004126Szf162725 wpa_config_free(wpa_s->conf); 2014126Szf162725 wpa_s->conf = NULL; 2024126Szf162725 } 2034126Szf162725 204*8453SAnurag.Maskey@Sun.COM dladm_close(wpa_s->handle); 2054126Szf162725 free(wpa_s->ap_wpa_ie); 2064126Szf162725 pmksa_candidate_free(wpa_s); 2074126Szf162725 pmksa_cache_free(wpa_s); 2084126Szf162725 } 2094126Szf162725 2104126Szf162725 static void 2114126Szf162725 wpa_clear_keys(struct wpa_supplicant *wpa_s, uint8_t *addr) 2124126Szf162725 { 213*8453SAnurag.Maskey@Sun.COM wpa_s->driver->set_key(wpa_s->handle, wpa_s->linkid, WPA_ALG_NONE, 2144126Szf162725 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 0, 0, NULL, 0, NULL, 0); 215*8453SAnurag.Maskey@Sun.COM wpa_s->driver->set_key(wpa_s->handle, wpa_s->linkid, WPA_ALG_NONE, 2164126Szf162725 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 1, 0, NULL, 0, NULL, 0); 217*8453SAnurag.Maskey@Sun.COM wpa_s->driver->set_key(wpa_s->handle, wpa_s->linkid, WPA_ALG_NONE, 2184126Szf162725 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 2, 0, NULL, 0, NULL, 0); 219*8453SAnurag.Maskey@Sun.COM wpa_s->driver->set_key(wpa_s->handle, wpa_s->linkid, WPA_ALG_NONE, 2204126Szf162725 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 3, 0, NULL, 0, NULL, 0); 2214126Szf162725 if (addr) { 222*8453SAnurag.Maskey@Sun.COM wpa_s->driver->set_key(wpa_s->handle, wpa_s->linkid, 223*8453SAnurag.Maskey@Sun.COM WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL, 0); 2244126Szf162725 } 2254126Szf162725 } 2264126Szf162725 2274126Szf162725 static void 2284126Szf162725 wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) 2294126Szf162725 { 2304126Szf162725 wpa_s->wpa_state = WPA_DISCONNECTED; 2314126Szf162725 (void) memset(wpa_s->bssid, 0, IEEE80211_ADDR_LEN); 2324126Szf162725 } 2334126Szf162725 2344126Szf162725 static int 2354126Szf162725 wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, 2364126Szf162725 dladm_wlan_ess_t *bss, struct wpa_ssid *ssid, 2374126Szf162725 uint8_t *wpa_ie, int *wpa_ie_len) 2384126Szf162725 { 2394126Szf162725 struct wpa_ie_data ie; 2404126Szf162725 int sel, proto; 2414126Szf162725 uint8_t *ap_ie; 2424126Szf162725 size_t ap_ie_len; 2434126Szf162725 2444126Szf162725 /* RSN or WPA */ 2454126Szf162725 if (bss->we_wpa_ie_len && bss->we_wpa_ie[0] == RSN_INFO_ELEM && 2464126Szf162725 (ssid->proto & WPA_PROTO_RSN)) { 2474126Szf162725 wpa_printf(MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0"); 2484126Szf162725 proto = WPA_PROTO_RSN; 2494126Szf162725 } else { 2504126Szf162725 wpa_printf(MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0"); 2514126Szf162725 proto = WPA_PROTO_WPA; 2524126Szf162725 } 2534126Szf162725 2544126Szf162725 ap_ie = bss->we_wpa_ie; 2554126Szf162725 ap_ie_len = bss->we_wpa_ie_len; 2564126Szf162725 2574126Szf162725 if (wpa_parse_wpa_ie(wpa_s, ap_ie, ap_ie_len, &ie)) { 2584126Szf162725 wpa_printf(MSG_WARNING, "WPA: Failed to parse WPA IE for " 2594126Szf162725 "the selected BSS."); 2604126Szf162725 return (-1); 2614126Szf162725 } 2624126Szf162725 2634126Szf162725 wpa_s->proto = proto; 2644126Szf162725 free(wpa_s->ap_wpa_ie); 2654126Szf162725 wpa_s->ap_wpa_ie = malloc(ap_ie_len); 2664126Szf162725 (void) memcpy(wpa_s->ap_wpa_ie, ap_ie, ap_ie_len); 2674126Szf162725 wpa_s->ap_wpa_ie_len = ap_ie_len; 2684126Szf162725 2694126Szf162725 sel = ie.group_cipher & ssid->group_cipher; 2704126Szf162725 if (sel & WPA_CIPHER_CCMP) { 2714126Szf162725 wpa_s->group_cipher = WPA_CIPHER_CCMP; 2724126Szf162725 } else if (sel & WPA_CIPHER_TKIP) { 2734126Szf162725 wpa_s->group_cipher = WPA_CIPHER_TKIP; 2744126Szf162725 } else if (sel & WPA_CIPHER_WEP104) { 2754126Szf162725 wpa_s->group_cipher = WPA_CIPHER_WEP104; 2764126Szf162725 } else if (sel & WPA_CIPHER_WEP40) { 2774126Szf162725 wpa_s->group_cipher = WPA_CIPHER_WEP40; 2784126Szf162725 } else { 2794126Szf162725 wpa_printf(MSG_WARNING, "WPA: Failed to select group cipher."); 2804126Szf162725 return (-1); 2814126Szf162725 } 2824126Szf162725 2834126Szf162725 sel = ie.pairwise_cipher & ssid->pairwise_cipher; 2844126Szf162725 if (sel & WPA_CIPHER_CCMP) { 2854126Szf162725 wpa_s->pairwise_cipher = WPA_CIPHER_CCMP; 2864126Szf162725 } else if (sel & WPA_CIPHER_TKIP) { 2874126Szf162725 wpa_s->pairwise_cipher = WPA_CIPHER_TKIP; 2884126Szf162725 } else if (sel & WPA_CIPHER_NONE) { 2894126Szf162725 wpa_s->pairwise_cipher = WPA_CIPHER_NONE; 2904126Szf162725 } else { 2914126Szf162725 wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise " 2924126Szf162725 "cipher."); 2934126Szf162725 return (-1); 2944126Szf162725 } 2954126Szf162725 2964126Szf162725 sel = ie.key_mgmt & ssid->key_mgmt; 2974126Szf162725 if (sel & WPA_KEY_MGMT_IEEE8021X) { 2984126Szf162725 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 2994126Szf162725 } else if (sel & WPA_KEY_MGMT_PSK) { 3004126Szf162725 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK; 3014126Szf162725 } else { 3024126Szf162725 wpa_printf(MSG_WARNING, "WPA: Failed to select authenticated " 3034126Szf162725 "key management type."); 3044126Szf162725 return (-1); 3054126Szf162725 } 3064126Szf162725 3074126Szf162725 *wpa_ie_len = wpa_gen_wpa_ie(wpa_s, wpa_ie); 3084126Szf162725 if (*wpa_ie_len < 0) { 3094126Szf162725 wpa_printf(MSG_WARNING, "WPA: Failed to generate WPA IE."); 3104126Szf162725 return (-1); 3114126Szf162725 } 3124126Szf162725 wpa_hexdump(MSG_DEBUG, "WPA: Own WPA IE", wpa_ie, *wpa_ie_len); 3134126Szf162725 3144126Szf162725 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) 3154126Szf162725 (void) memcpy(wpa_s->pmk, ssid->psk, PMK_LEN); 3164126Szf162725 else if (wpa_s->cur_pmksa) 3174126Szf162725 (void) memcpy(wpa_s->pmk, wpa_s->cur_pmksa->pmk, PMK_LEN); 3184126Szf162725 else { 3194126Szf162725 (void) memset(wpa_s->pmk, 0, PMK_LEN); 3204126Szf162725 } 3214126Szf162725 3224126Szf162725 return (0); 3234126Szf162725 } 3244126Szf162725 3254126Szf162725 static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, 3264126Szf162725 dladm_wlan_ess_t *bss, struct wpa_ssid *ssid) 3274126Szf162725 { 3284126Szf162725 uint8_t wpa_ie[IEEE80211_MAX_OPT_IE]; 3294126Szf162725 int wpa_ie_len; 3304126Szf162725 3314126Szf162725 wpa_s->reassociate = 0; 3324126Szf162725 wpa_printf(MSG_DEBUG, "Trying to associate with " MACSTR 3334126Szf162725 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->we_bssid.wb_bytes), 3344126Szf162725 wpa_ssid_txt((char *)ssid->ssid, ssid->ssid_len), bss->we_freq); 3354126Szf162725 wpa_supplicant_cancel_scan(wpa_s); 3364126Szf162725 3374126Szf162725 if (bss->we_wpa_ie_len && 3384126Szf162725 (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK))) { 3394126Szf162725 wpa_s->cur_pmksa = pmksa_cache_get(wpa_s, 3404126Szf162725 bss->we_bssid.wb_bytes, NULL); 3414126Szf162725 if (wpa_s->cur_pmksa) { 3424126Szf162725 wpa_hexdump(MSG_DEBUG, "RSN: PMKID", 3434126Szf162725 wpa_s->cur_pmksa->pmkid, PMKID_LEN); 3444126Szf162725 } 3454126Szf162725 if (wpa_supplicant_set_suites(wpa_s, bss, ssid, 3464126Szf162725 wpa_ie, &wpa_ie_len)) { 3474126Szf162725 wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key " 3484126Szf162725 "management and encryption suites"); 3494126Szf162725 return; 3504126Szf162725 } 3514126Szf162725 } else { 3524126Szf162725 wpa_ie_len = 0; 3534126Szf162725 } 3544126Szf162725 3554126Szf162725 wpa_clear_keys(wpa_s, bss->we_bssid.wb_bytes); 3564126Szf162725 wpa_s->wpa_state = WPA_ASSOCIATING; 357*8453SAnurag.Maskey@Sun.COM wpa_s->driver->associate(wpa_s->handle, wpa_s->linkid, 3584126Szf162725 (const char *)bss->we_bssid.wb_bytes, wpa_ie, wpa_ie_len); 3594126Szf162725 3604126Szf162725 /* Timeout for IEEE 802.11 authentication and association */ 3614126Szf162725 wpa_supplicant_req_auth_timeout(wpa_s, 15, 0); 3624126Szf162725 } 3634126Szf162725 3644126Szf162725 void 3654126Szf162725 wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, int reason_code) 3664126Szf162725 { 3674126Szf162725 uint8_t *addr = NULL; 3684126Szf162725 wpa_s->wpa_state = WPA_DISCONNECTED; 3694126Szf162725 if (memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", 3704126Szf162725 IEEE80211_ADDR_LEN) != 0) { 371*8453SAnurag.Maskey@Sun.COM wpa_s->driver->disassociate(wpa_s->handle, wpa_s->linkid, 372*8453SAnurag.Maskey@Sun.COM reason_code); 3734126Szf162725 addr = wpa_s->bssid; 3744126Szf162725 } 3754126Szf162725 wpa_clear_keys(wpa_s, addr); 3764126Szf162725 } 3774126Szf162725 3784126Szf162725 static dladm_wlan_ess_t * 3794126Szf162725 wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, 3804126Szf162725 dladm_wlan_ess_t *results, int num, struct wpa_ssid **selected_ssid) 3814126Szf162725 { 3824126Szf162725 struct wpa_ssid *ssid; 3834126Szf162725 dladm_wlan_ess_t *bss, *selected = NULL; 3844126Szf162725 int i; 3854126Szf162725 3864126Szf162725 struct wpa_ie_data ie; 3874126Szf162725 3884126Szf162725 wpa_printf(MSG_DEBUG, "Selecting BSS from scan results (%d)", num); 3894126Szf162725 3904126Szf162725 bss = NULL; 3914126Szf162725 ssid = NULL; 3924126Szf162725 3934126Szf162725 /* try to find matched AP */ 3944126Szf162725 for (i = 0; i < num && !selected; i++) { 3954126Szf162725 bss = &results[i]; 3964126Szf162725 wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' " 3974126Szf162725 "wpa_ie_len=%d", 3984126Szf162725 i, MAC2STR(bss->we_bssid.wb_bytes), 3994126Szf162725 wpa_ssid_txt(bss->we_ssid.we_bytes, bss->we_ssid_len), 4004126Szf162725 bss->we_wpa_ie_len); 4014126Szf162725 if (bss->we_wpa_ie_len == 0) { 4024126Szf162725 wpa_printf(MSG_DEBUG, " skip - no WPA/RSN IE"); 4034126Szf162725 } 4044126Szf162725 4054126Szf162725 ssid = group; 4064126Szf162725 if (bss->we_ssid_len != ssid->ssid_len || 4074126Szf162725 memcmp(bss->we_ssid.we_bytes, ssid->ssid, 4084126Szf162725 bss->we_ssid_len) != 0) { 4094126Szf162725 wpa_printf(MSG_DEBUG, " skip - SSID mismatch"); 4104126Szf162725 continue; 4114126Szf162725 } 4124126Szf162725 if (!((ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_WPA)) && 4134126Szf162725 wpa_parse_wpa_ie(wpa_s, bss->we_wpa_ie, 4144126Szf162725 bss->we_wpa_ie_len, &ie) == 0)) { 4154126Szf162725 wpa_printf(MSG_DEBUG, " skip - " 4164126Szf162725 "could not parse WPA/RSN IE"); 4174126Szf162725 continue; 4184126Szf162725 } 4194126Szf162725 if (!(ie.proto & ssid->proto)) { 4204126Szf162725 wpa_printf(MSG_DEBUG, " skip - proto mismatch"); 4214126Szf162725 continue; 4224126Szf162725 } 4234126Szf162725 if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { 4244126Szf162725 wpa_printf(MSG_DEBUG, " skip - PTK cipher mismatch"); 4254126Szf162725 continue; 4264126Szf162725 } 4274126Szf162725 if (!(ie.group_cipher & ssid->group_cipher)) { 4284126Szf162725 wpa_printf(MSG_DEBUG, " skip - GTK cipher mismatch"); 4294126Szf162725 continue; 4304126Szf162725 } 4314126Szf162725 if (!(ie.key_mgmt & ssid->key_mgmt)) { 4324126Szf162725 wpa_printf(MSG_DEBUG, " skip - key mgmt mismatch"); 4334126Szf162725 continue; 4344126Szf162725 } 4354126Szf162725 4364126Szf162725 selected = bss; 4374126Szf162725 *selected_ssid = ssid; 4384126Szf162725 wpa_printf(MSG_DEBUG, " selected"); 4394126Szf162725 } 4404126Szf162725 4414126Szf162725 return (selected); 4424126Szf162725 } 4434126Szf162725 4444126Szf162725 4454126Szf162725 static void 4464126Szf162725 wpa_supplicant_scan_results(struct wpa_supplicant *wpa_s) 4474126Szf162725 { 4484126Szf162725 dladm_wlan_ess_t results[MAX_SCANRESULTS]; 4494126Szf162725 int num; 4504126Szf162725 dladm_wlan_ess_t *selected = NULL; 4514126Szf162725 struct wpa_ssid *ssid; 4524126Szf162725 4534126Szf162725 (void) memset(results, 0, sizeof (dladm_wlan_ess_t) * MAX_SCANRESULTS); 454*8453SAnurag.Maskey@Sun.COM num = wpa_s->driver->get_scan_results(wpa_s->handle, wpa_s->linkid, 455*8453SAnurag.Maskey@Sun.COM results, MAX_SCANRESULTS); 4564126Szf162725 wpa_printf(MSG_DEBUG, "Scan results: %d", num); 4574126Szf162725 if (num < 0) 4584126Szf162725 return; 4594126Szf162725 if (num > MAX_SCANRESULTS) { 4604126Szf162725 wpa_printf(MSG_INFO, "Not enough room for all APs (%d < %d)", 4614126Szf162725 num, MAX_SCANRESULTS); 4624126Szf162725 num = MAX_SCANRESULTS; 4634126Szf162725 } 4644126Szf162725 4654126Szf162725 selected = wpa_supplicant_select_bss(wpa_s, 4664126Szf162725 wpa_s->conf->ssid, results, num, &ssid); 4674126Szf162725 4684126Szf162725 if (selected) { 4694126Szf162725 if (wpa_s->reassociate || 4704126Szf162725 memcmp(selected->we_bssid.wb_bytes, wpa_s->bssid, 4714126Szf162725 IEEE80211_ADDR_LEN) != 0) { 4724126Szf162725 wpa_supplicant_associate(wpa_s, selected, ssid); 4734126Szf162725 } else { 4744126Szf162725 wpa_printf(MSG_DEBUG, "Already associated with the " 4754126Szf162725 "selected AP."); 4764126Szf162725 } 4774126Szf162725 } else { 4784126Szf162725 wpa_printf(MSG_DEBUG, "No suitable AP found."); 4794126Szf162725 wpa_supplicant_req_scan(wpa_s, 5, 0); /* wait 5 seconds */ 4804126Szf162725 } 4814126Szf162725 } 4824126Szf162725 4834126Szf162725 /* 4844126Szf162725 * wpa_event_handler - report a driver event for wpa_supplicant 4854126Szf162725 * @wpa_s: pointer to wpa_supplicant data; this is the @ctx variable registered 4864126Szf162725 * with wpa_driver_events_init() 4874126Szf162725 * @event: event type (defined above) 4884126Szf162725 * 4894126Szf162725 * Driver wrapper code should call this function whenever an event is received 4904126Szf162725 * from the driver. 4914126Szf162725 */ 4924126Szf162725 void 4934126Szf162725 wpa_event_handler(void *cookie, wpa_event_type event) 4944126Szf162725 { 4954126Szf162725 struct wpa_supplicant *wpa_s = cookie; 4964126Szf162725 4974126Szf162725 switch (event) { 4984126Szf162725 case EVENT_ASSOC: 4998230SQuaker.Fang@Sun.COM wpa_printf(MSG_DEBUG, "\nAssociation event\n"); 5008230SQuaker.Fang@Sun.COM /* async event */ 5018230SQuaker.Fang@Sun.COM if (wpa_s->wpa_state < WPA_ASSOCIATED) { 5028230SQuaker.Fang@Sun.COM wpa_s->wpa_state = WPA_ASSOCIATED; 5038230SQuaker.Fang@Sun.COM if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { 5048230SQuaker.Fang@Sun.COM wpa_supplicant_cancel_auth_timeout(wpa_s); 5058230SQuaker.Fang@Sun.COM } else { 5068230SQuaker.Fang@Sun.COM /* Timeout for receiving first EAPOL packet */ 5078230SQuaker.Fang@Sun.COM wpa_supplicant_req_auth_timeout(wpa_s, 10, 0); 5088230SQuaker.Fang@Sun.COM } 5094126Szf162725 } 5104126Szf162725 break; 5114126Szf162725 case EVENT_DISASSOC: 5124126Szf162725 if (wpa_s->wpa_state >= WPA_ASSOCIATED) 5134126Szf162725 wpa_supplicant_req_scan(wpa_s, 0, 100000); 5144126Szf162725 wpa_supplicant_mark_disassoc(wpa_s); 5154126Szf162725 wpa_printf(MSG_DEBUG, "Disconnect event - remove keys"); 5164126Szf162725 if (wpa_s->key_mgmt != WPA_KEY_MGMT_NONE) 5174126Szf162725 wpa_clear_keys(wpa_s, wpa_s->bssid); 5184126Szf162725 break; 5194126Szf162725 case EVENT_SCAN_RESULTS: 5204126Szf162725 wpa_supplicant_scan_results(wpa_s); 5218230SQuaker.Fang@Sun.COM /* reset vars */ 5228230SQuaker.Fang@Sun.COM (void) memset(wpa_s->rx_replay_counter, 0, 5238230SQuaker.Fang@Sun.COM WPA_REPLAY_COUNTER_LEN); 5248230SQuaker.Fang@Sun.COM wpa_s->rx_replay_counter_set = 0; 5258230SQuaker.Fang@Sun.COM wpa_s->renew_snonce = 1; 5268230SQuaker.Fang@Sun.COM wpa_s->eapol_received = 0; 5274126Szf162725 break; 5284126Szf162725 default: 5294126Szf162725 wpa_printf(MSG_INFO, "Unknown event %d", event); 5304126Szf162725 break; 5314126Szf162725 } 5324126Szf162725 } 5334126Szf162725 5344126Szf162725 /* ARGSUSED */ 5354126Szf162725 static void 5364126Szf162725 wpa_supplicant_terminate(int sig, void *eloop_ctx, void *signal_ctx) 5374126Szf162725 { 5384126Szf162725 wpa_printf(MSG_INFO, "Signal %d received - terminating", sig); 5394126Szf162725 eloop_terminate(); 5404126Szf162725 } 5414126Szf162725 5424126Szf162725 static int 5435895Syz147064 wpa_supplicant_driver_init(const char *link, struct wpa_supplicant *wpa_s) 5444126Szf162725 { 5455895Syz147064 wpa_s->l2 = l2_packet_init(link, ETHERTYPE_EAPOL, 5464126Szf162725 wpa_supplicant_rx_eapol, wpa_s); 5474126Szf162725 if (wpa_s->l2 == NULL) 5484126Szf162725 return (-1); 5494126Szf162725 5504126Szf162725 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) { 5514126Szf162725 (void) fprintf(stderr, "Failed to get own L2 address\n"); 5524126Szf162725 return (-1); 5534126Szf162725 } 5544126Szf162725 555*8453SAnurag.Maskey@Sun.COM if (wpa_s->driver->set_wpa(wpa_s->handle, wpa_s->linkid, 1) < 0) { 5564126Szf162725 wpa_printf(MSG_ERROR, "Failed to enable WPA in the driver."); 5574126Szf162725 return (-1); 5584126Szf162725 } 5594126Szf162725 5604126Szf162725 wpa_clear_keys(wpa_s, NULL); 5614126Szf162725 wpa_supplicant_req_scan(wpa_s, 0, 100000); 5624126Szf162725 5634126Szf162725 return (0); 5644126Szf162725 } 5654126Szf162725 5664126Szf162725 static int door_id = -1; 5674126Szf162725 5684126Szf162725 /* ARGSUSED */ 5694126Szf162725 static void 5704126Szf162725 event_handler(void *cookie, char *argp, size_t asize, 5714126Szf162725 door_desc_t *dp, uint_t n_desc) 5724126Szf162725 { 5734126Szf162725 wpa_event_type event; 5744126Szf162725 5757249Sff224033 /* LINTED E_BAD_PTR_CAST_ALIGN */ 5764126Szf162725 event = ((wl_events_t *)argp)->event; 5774126Szf162725 wpa_event_handler(cookie, event); 5784126Szf162725 5794126Szf162725 (void) door_return(NULL, 0, NULL, 0); 5804126Szf162725 } 5814126Szf162725 5824126Szf162725 /* 5834126Szf162725 * Create the driver to wpad door 5844126Szf162725 */ 5854126Szf162725 int 5864126Szf162725 wpa_supplicant_door_setup(void *cookie, char *doorname) 5874126Szf162725 { 5884126Szf162725 struct stat stbuf; 5894126Szf162725 int error = 0; 5904126Szf162725 5914126Szf162725 wpa_printf(MSG_DEBUG, "wpa_supplicant_door_setup(%s)", doorname); 5924126Szf162725 /* 5934126Szf162725 * Create the door 5944126Szf162725 */ 5954126Szf162725 door_id = door_create(event_handler, cookie, 5964126Szf162725 DOOR_UNREF | DOOR_REFUSE_DESC | DOOR_NO_CANCEL); 5974126Szf162725 5984126Szf162725 if (door_id < 0) { 5994126Szf162725 error = -1; 6004126Szf162725 goto out; 6014126Szf162725 } 6024126Szf162725 6034126Szf162725 if (stat(doorname, &stbuf) < 0) { 6044126Szf162725 int newfd; 6054126Szf162725 if ((newfd = creat(doorname, 0666)) < 0) { 6064126Szf162725 (void) door_revoke(door_id); 6074126Szf162725 door_id = -1; 6084126Szf162725 error = -1; 6094126Szf162725 6104126Szf162725 goto out; 6114126Szf162725 } 6124126Szf162725 (void) close(newfd); 6134126Szf162725 } 6144126Szf162725 6154126Szf162725 if (fattach(door_id, doorname) < 0) { 6164126Szf162725 if ((errno != EBUSY) || (fdetach(doorname) < 0) || 6174126Szf162725 (fattach(door_id, doorname) < 0)) { 6184126Szf162725 (void) door_revoke(door_id); 6194126Szf162725 door_id = -1; 6204126Szf162725 error = -1; 6214126Szf162725 6224126Szf162725 goto out; 6234126Szf162725 } 6244126Szf162725 } 6254126Szf162725 6264126Szf162725 out: 6274126Szf162725 return (error); 6284126Szf162725 } 6294126Szf162725 6304126Szf162725 void 6314126Szf162725 wpa_supplicant_door_destroy(char *doorname) 6324126Szf162725 { 6334126Szf162725 wpa_printf(MSG_DEBUG, "wpa_supplicant_door_destroy(%s)\n", doorname); 6344126Szf162725 6355895Syz147064 if (door_id == -1) 6365895Syz147064 return; 6375895Syz147064 6384126Szf162725 if (door_revoke(door_id) == -1) { 6394126Szf162725 wpa_printf(MSG_ERROR, "failed to door_revoke(%d) %s, exiting.", 6404126Szf162725 door_id, strerror(errno)); 6414126Szf162725 } 6424126Szf162725 6434126Szf162725 if (fdetach(doorname) == -1) { 6444126Szf162725 wpa_printf(MSG_ERROR, "failed to fdetach %s: %s, exiting.", 6454126Szf162725 doorname, strerror(errno)); 6464126Szf162725 } 6474126Szf162725 6484126Szf162725 (void) close(door_id); 6494126Szf162725 } 6504126Szf162725 6514126Szf162725 static int 6524126Szf162725 wpa_config_parse_ssid(struct wpa_ssid *ssid, int line, const char *value) 6534126Szf162725 { 6544126Szf162725 free(ssid->ssid); 6554126Szf162725 6564126Szf162725 ssid->ssid = (uint8_t *)strdup(value); 6574126Szf162725 ssid->ssid_len = strlen(value); 6584126Szf162725 6594126Szf162725 if (ssid->ssid == NULL) { 6604126Szf162725 wpa_printf(MSG_ERROR, "Invalid SSID '%s'.", line, value); 6614126Szf162725 return (-1); 6624126Szf162725 } 6634126Szf162725 if (ssid->ssid_len > MAX_ESSID_LENGTH) { 6644126Szf162725 free(ssid->ssid); 6654126Szf162725 wpa_printf(MSG_ERROR, "Too long SSID '%s'.", line, value); 6664126Szf162725 return (-1); 6674126Szf162725 } 6684126Szf162725 wpa_printf(MSG_MSGDUMP, "SSID: %s", ssid->ssid); 6694126Szf162725 return (0); 6704126Szf162725 } 6714126Szf162725 6724126Szf162725 static struct wpa_ssid * 6734126Szf162725 wpa_config_read_network(struct wpa_supplicant *wpa_s) 6744126Szf162725 { 6754126Szf162725 struct wpa_ssid *ssid; 6764126Szf162725 char buf[MAX_ESSID_LENGTH + 1]; 6774126Szf162725 dladm_secobj_class_t cl; 6784126Szf162725 uint8_t psk[MAX_PSK_LENGTH + 1]; 6794126Szf162725 uint_t key_len; 6804126Szf162725 6814126Szf162725 wpa_printf(MSG_MSGDUMP, "Start of a new network configration"); 6824126Szf162725 6834126Szf162725 ssid = (struct wpa_ssid *)malloc(sizeof (*ssid)); 6844126Szf162725 if (ssid == NULL) 6854126Szf162725 return (NULL); 6864126Szf162725 (void) memset(ssid, 0, sizeof (*ssid)); 6874126Szf162725 6884126Szf162725 /* 6894126Szf162725 * Set default supported values 6904126Szf162725 */ 6914126Szf162725 ssid->proto = WPA_PROTO_WPA | WPA_PROTO_RSN; 6924126Szf162725 ssid->pairwise_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP; 6934126Szf162725 ssid->group_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | 6944126Szf162725 WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40; 6954126Szf162725 ssid->key_mgmt = WPA_KEY_MGMT_PSK; /* | WPA_KEY_MGMT_IEEE8021X; */ 6964126Szf162725 6974126Szf162725 (void) memset(buf, 0, MAX_ESSID_LENGTH + 1); 698*8453SAnurag.Maskey@Sun.COM wpa_s->driver->get_ssid(wpa_s->handle, wpa_s->linkid, (char *)buf); 6994126Szf162725 7004126Szf162725 (void) wpa_config_parse_ssid(ssid, 0, buf); 7014126Szf162725 7024126Szf162725 key_len = sizeof (psk); 703*8453SAnurag.Maskey@Sun.COM (void) dladm_get_secobj(wpa_s->handle, (const char *)wpa_s->kname, &cl, 704*8453SAnurag.Maskey@Sun.COM psk, &key_len, DLADM_OPT_ACTIVE); 7054126Szf162725 psk[key_len] = '\0'; 7064126Szf162725 ssid->passphrase = strdup((const char *)psk); 7074126Szf162725 7084126Szf162725 if (ssid->passphrase) { 7094126Szf162725 pbkdf2_sha1(ssid->passphrase, (char *)ssid->ssid, 7104126Szf162725 ssid->ssid_len, 4096, ssid->psk, PMK_LEN); 7114126Szf162725 wpa_hexdump(MSG_MSGDUMP, "PSK (from passphrase)", 7124126Szf162725 ssid->psk, PMK_LEN); 7134126Szf162725 ssid->psk_set = 1; 7144126Szf162725 } 7154126Szf162725 7164126Szf162725 if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) { 7174126Szf162725 wpa_printf(MSG_ERROR, "WPA-PSK accepted for key " 7184126Szf162725 "management, but no PSK configured."); 7194126Szf162725 free(ssid); 7204126Szf162725 ssid = NULL; 7214126Szf162725 } 7224126Szf162725 7234126Szf162725 return (ssid); 7244126Szf162725 } 7254126Szf162725 7264126Szf162725 struct wpa_config * 7274126Szf162725 wpa_config_read(void *arg) 7284126Szf162725 { 7294126Szf162725 struct wpa_ssid *ssid; 7304126Szf162725 struct wpa_config *config; 7314126Szf162725 struct wpa_supplicant *wpa_s = arg; 7324126Szf162725 7334126Szf162725 config = malloc(sizeof (*config)); 7344126Szf162725 if (config == NULL) 7354126Szf162725 return (NULL); 7364126Szf162725 (void) memset(config, 0, sizeof (*config)); 7374126Szf162725 config->eapol_version = 1; /* fixed value */ 7384126Szf162725 7394126Szf162725 wpa_printf(MSG_DEBUG, "Reading configuration parameters from driver\n"); 7404126Szf162725 7414126Szf162725 ssid = wpa_config_read_network(wpa_s); 7424126Szf162725 if (ssid == NULL) { 7434126Szf162725 wpa_config_free(config); 7444126Szf162725 config = NULL; 7454126Szf162725 } else { 7464126Szf162725 config->ssid = ssid; 7474126Szf162725 } 7484126Szf162725 7494126Szf162725 return (config); 7504126Szf162725 } 7514126Szf162725 7524126Szf162725 void 7534126Szf162725 wpa_config_free(struct wpa_config *config) 7544126Szf162725 { 7554126Szf162725 struct wpa_ssid *ssid = config->ssid; 7564126Szf162725 7575895Syz147064 if (ssid != NULL) { 7585895Syz147064 free(ssid->ssid); 7595895Syz147064 free(ssid->passphrase); 7605895Syz147064 free(ssid); 7615895Syz147064 } 7624126Szf162725 free(config); 7634126Szf162725 } 7644126Szf162725 7654126Szf162725 static int 7664126Szf162725 daemon(boolean_t nochdir, boolean_t noclose) 7674126Szf162725 { 7684126Szf162725 int retv; 7694126Szf162725 7704126Szf162725 if ((retv = fork()) == -1) 7714126Szf162725 return (-1); 7724126Szf162725 if (retv != 0) 7734126Szf162725 _exit(EXIT_SUCCESS); 7744126Szf162725 if (setsid() == -1) 7754126Szf162725 return (-1); 7764126Szf162725 7774126Szf162725 if (!nochdir && chdir("/") == -1) 7784126Szf162725 return (-1); 7794126Szf162725 7804126Szf162725 if (!noclose) { 7814126Szf162725 (void) close(0); 7824126Szf162725 (void) close(1); 7834126Szf162725 (void) close(2); 7844126Szf162725 if ((retv = open("/dev/null", O_RDWR)) != -1) { 7854126Szf162725 (void) dup2(retv, 1); 7864126Szf162725 (void) dup2(retv, 2); 7874126Szf162725 } 7884126Szf162725 } 7894126Szf162725 7904126Szf162725 return (0); 7914126Szf162725 } 7924126Szf162725 7936411Szf162725 /* 7946411Szf162725 * make sure wpad is running under SMF context. 7956411Szf162725 */ 7966411Szf162725 static boolean_t 7976411Szf162725 is_smf_context(void) 7984126Szf162725 { 7996411Szf162725 char *fmri; 8006411Szf162725 8016411Szf162725 return (((fmri = getenv("SMF_FMRI")) != NULL) && 8026411Szf162725 (strstr(fmri, SERVICE_NAME) != NULL)); 8034126Szf162725 } 8044126Szf162725 8054126Szf162725 int 8064126Szf162725 main(int argc, char *argv[]) 8074126Szf162725 { 8084126Szf162725 struct wpa_supplicant wpa_s; 8094126Szf162725 char *link = NULL; 8104126Szf162725 char *key = NULL; 8115895Syz147064 dlpi_handle_t dh = NULL; 8125895Syz147064 datalink_id_t linkid; 8135895Syz147064 dladm_phys_attr_t dpa; 8144126Szf162725 int c; 8154126Szf162725 int exitcode; 8166411Szf162725 char door_file[MAXPATHLEN]; 817*8453SAnurag.Maskey@Sun.COM dladm_handle_t handle; 8186411Szf162725 8196411Szf162725 if (!is_smf_context()) { 8206411Szf162725 (void) fprintf(stderr, 8216411Szf162725 "wpad is an smf(5) managed service and cannot be run from " 8226411Szf162725 "the command line; please use dladm(1M).\n"); 8236411Szf162725 return (SMF_EXIT_ERR_NOSMF); 8246411Szf162725 } 8254126Szf162725 8264126Szf162725 for (;;) { 8276411Szf162725 c = getopt(argc, argv, "i:k:"); 8284126Szf162725 if (c < 0) 8294126Szf162725 break; 8304126Szf162725 switch (c) { 8314126Szf162725 case 'i': 8324126Szf162725 link = optarg; 8334126Szf162725 break; 8344126Szf162725 case 'k': 8354126Szf162725 key = optarg; 8364126Szf162725 break; 8374126Szf162725 default: 8386411Szf162725 return (SMF_EXIT_ERR_CONFIG); 8394126Szf162725 } 8404126Szf162725 } 8414126Szf162725 8424126Szf162725 /* 8434126Szf162725 * key name is required to retrieve PSK value through libwdladm APIs. 8444126Szf162725 * key is saved by dladm command by keyname 8454126Szf162725 * see dladm. 8464126Szf162725 */ 8474126Szf162725 if ((link == NULL) || (key == NULL)) { 8484126Szf162725 wpa_printf(MSG_ERROR, "\nLink & key is required."); 8494126Szf162725 return (-1); 8504126Szf162725 } 8514126Szf162725 8525895Syz147064 if ((strlen(key) >= sizeof (wpa_s.kname))) { 8535895Syz147064 wpa_printf(MSG_ERROR, "Too long key name '%s'.", key); 8545895Syz147064 return (-1); 8555895Syz147064 } 8565895Syz147064 8575895Syz147064 if (daemon(0, 0)) 8585895Syz147064 return (-1); 8595895Syz147064 8605895Syz147064 /* 8615895Syz147064 * Hold this link open to prevent a link renaming operation. 8625895Syz147064 */ 8635895Syz147064 if (dlpi_open(link, &dh, 0) != DLPI_SUCCESS) { 8645895Syz147064 wpa_printf(MSG_ERROR, "Failed to open link '%s'.", link); 8654126Szf162725 return (-1); 8664126Szf162725 } 8674126Szf162725 868*8453SAnurag.Maskey@Sun.COM /* This handle is stored in wpa_s when that struct is filled. */ 869*8453SAnurag.Maskey@Sun.COM if (dladm_open(&handle) != DLADM_STATUS_OK) { 870*8453SAnurag.Maskey@Sun.COM wpa_printf(MSG_ERROR, "Failed to open dladm handle"); 871*8453SAnurag.Maskey@Sun.COM dlpi_close(dh); 872*8453SAnurag.Maskey@Sun.COM return (-1); 873*8453SAnurag.Maskey@Sun.COM } 874*8453SAnurag.Maskey@Sun.COM 875*8453SAnurag.Maskey@Sun.COM if (dladm_name2info(handle, link, &linkid, NULL, NULL, NULL) != 8765895Syz147064 DLADM_STATUS_OK) { 8775895Syz147064 wpa_printf(MSG_ERROR, "Invalid link name '%s'.", link); 878*8453SAnurag.Maskey@Sun.COM dladm_close(handle); 8795895Syz147064 dlpi_close(dh); 8805895Syz147064 return (-1); 8815895Syz147064 } 8824126Szf162725 8834126Szf162725 /* 8845895Syz147064 * Get the device name of the link, which will be used as the door 8855895Syz147064 * file name used to communicate with the driver. Note that different 8865895Syz147064 * links use different doors. 8874126Szf162725 */ 888*8453SAnurag.Maskey@Sun.COM if (dladm_phys_info(handle, linkid, &dpa, DLADM_OPT_ACTIVE) != 8895895Syz147064 DLADM_STATUS_OK) { 8905895Syz147064 wpa_printf(MSG_ERROR, 8915895Syz147064 "Failed to get device name of link '%s'.", link); 892*8453SAnurag.Maskey@Sun.COM dladm_close(handle); 8935895Syz147064 dlpi_close(dh); 8945895Syz147064 return (-1); 8955895Syz147064 } 8966411Szf162725 (void) snprintf(door_file, MAXPATHLEN, "%s_%s", WPA_DOOR, dpa.dp_dev); 8975895Syz147064 8985895Syz147064 (void) memset(&wpa_s, 0, sizeof (wpa_s)); 8995895Syz147064 wpa_s.driver = &wpa_driver_wifi_ops; 900*8453SAnurag.Maskey@Sun.COM wpa_s.handle = handle; 9015895Syz147064 wpa_s.linkid = linkid; 9025895Syz147064 (void) strlcpy(wpa_s.kname, key, sizeof (wpa_s.kname)); 9035895Syz147064 eloop_init(&wpa_s); 9044126Szf162725 9054126Szf162725 /* 9064126Szf162725 * Setup default WPA/WPA2 configuration 9074126Szf162725 * get ESSID and PSK value 9084126Szf162725 */ 9094126Szf162725 wpa_s.conf = wpa_config_read(&wpa_s); 9104126Szf162725 if (wpa_s.conf == NULL || wpa_s.conf->ssid == NULL) { 9114126Szf162725 wpa_printf(MSG_ERROR, "\nNo networks (SSID) configured.\n"); 9125895Syz147064 exitcode = -1; 9135895Syz147064 goto cleanup; 9144126Szf162725 } 9154126Szf162725 9164126Szf162725 exitcode = 0; 9174126Szf162725 9185895Syz147064 /* 9195895Syz147064 * Setup door file to communicate with driver 9205895Syz147064 */ 9214126Szf162725 if (wpa_supplicant_door_setup(&wpa_s, door_file) != 0) { 9224126Szf162725 wpa_printf(MSG_ERROR, "Failed to setup door(%s)", door_file); 9234126Szf162725 exitcode = -1; 9244126Szf162725 goto cleanup; 9254126Szf162725 } 9264126Szf162725 9274126Szf162725 wpa_s.renew_snonce = 1; 9285895Syz147064 if (wpa_supplicant_driver_init(link, &wpa_s) < 0) { 9294126Szf162725 exitcode = -1; 9304126Szf162725 goto cleanup; 9314126Szf162725 } 9324126Szf162725 9335895Syz147064 /* 9345895Syz147064 * This link is hold again in wpa_supplicant_driver_init(), so that 9355895Syz147064 * we release the first reference. 9365895Syz147064 */ 9375895Syz147064 dlpi_close(dh); 9385895Syz147064 dh = NULL; 9395895Syz147064 9404126Szf162725 wpa_printf(MSG_DEBUG, "=> eloop_run"); 9414126Szf162725 9424126Szf162725 (void) eloop_register_signal(SIGINT, wpa_supplicant_terminate, NULL); 9434126Szf162725 (void) eloop_register_signal(SIGTERM, wpa_supplicant_terminate, NULL); 9444126Szf162725 (void) eloop_register_signal(SIGKILL, wpa_supplicant_terminate, NULL); 9454126Szf162725 9464126Szf162725 eloop_run(); 9474126Szf162725 9484126Szf162725 wpa_printf(MSG_DEBUG, "<= eloop_run()"); 9494126Szf162725 wpa_supplicant_disassociate(&wpa_s, REASON_DEAUTH_LEAVING); 9504126Szf162725 951*8453SAnurag.Maskey@Sun.COM if (wpa_s.driver->set_wpa(wpa_s.handle, wpa_s.linkid, 0) < 0) { 9524126Szf162725 wpa_printf(MSG_ERROR, "Failed to disable WPA in the driver.\n"); 9534126Szf162725 } 9544126Szf162725 9555895Syz147064 cleanup: 9564126Szf162725 wpa_supplicant_door_destroy(door_file); 957*8453SAnurag.Maskey@Sun.COM /* The libdladm handle is closed in the following method */ 9584126Szf162725 wpa_supplicant_cleanup(&wpa_s); 9594126Szf162725 eloop_destroy(); 9604126Szf162725 9615895Syz147064 if (dh != NULL) 9625895Syz147064 dlpi_close(dh); 9635895Syz147064 9644126Szf162725 return (exitcode); 9654126Szf162725 } 966