1*4126Szf162725 /* 2*4126Szf162725 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3*4126Szf162725 * Use is subject to license terms. 4*4126Szf162725 */ 5*4126Szf162725 6*4126Szf162725 /* 7*4126Szf162725 * Copyright (c) 2003-2004, Jouni Malinen <jkmaline@cc.hut.fi> 8*4126Szf162725 * Sun elects to license this software under the BSD license. 9*4126Szf162725 * See README for more details. 10*4126Szf162725 */ 11*4126Szf162725 12*4126Szf162725 #pragma ident "%Z%%M% %I% %E% SMI" 13*4126Szf162725 14*4126Szf162725 #include <stdio.h> 15*4126Szf162725 #include <stdlib.h> 16*4126Szf162725 #include <stdarg.h> 17*4126Szf162725 #include <unistd.h> 18*4126Szf162725 #include <string.h> 19*4126Szf162725 #include <syslog.h> 20*4126Szf162725 #include <sys/stat.h> 21*4126Szf162725 #include <errno.h> 22*4126Szf162725 #include <signal.h> 23*4126Szf162725 #include <fcntl.h> 24*4126Szf162725 #include <door.h> 25*4126Szf162725 #include <libdladm.h> 26*4126Szf162725 #include <libdllink.h> 27*4126Szf162725 #include <sys/ethernet.h> 28*4126Szf162725 29*4126Szf162725 #include "wpa_impl.h" 30*4126Szf162725 #include "wpa_enc.h" 31*4126Szf162725 #include "driver.h" 32*4126Szf162725 #include "eloop.h" 33*4126Szf162725 #include "l2_packet.h" 34*4126Szf162725 35*4126Szf162725 static const char *wpa_supplicant_version = 36*4126Szf162725 "wpa_supplicant v1.0"; 37*4126Szf162725 38*4126Szf162725 extern struct wpa_driver_ops wpa_driver_wifi_ops; 39*4126Szf162725 int wpa_debug_level = MSG_ERROR; 40*4126Szf162725 41*4126Szf162725 /* 42*4126Szf162725 * wpa_printf - conditional printf 43*4126Szf162725 * @level: priority level (MSG_*) of the message 44*4126Szf162725 * @fmt: printf format string, followed by optional arguments 45*4126Szf162725 * 46*4126Szf162725 * This function is used to print conditional debugging and error messages. The 47*4126Szf162725 * output may be directed to stdout, stderr, and/or syslog based on 48*4126Szf162725 * configuration. 49*4126Szf162725 */ 50*4126Szf162725 void 51*4126Szf162725 wpa_printf(int level, char *fmt, ...) 52*4126Szf162725 { 53*4126Szf162725 va_list ap; 54*4126Szf162725 char buffer[MAX_LOGBUF]; 55*4126Szf162725 56*4126Szf162725 if (level < wpa_debug_level) 57*4126Szf162725 return; 58*4126Szf162725 59*4126Szf162725 va_start(ap, fmt); 60*4126Szf162725 61*4126Szf162725 /* LINTED E_SEC_PRINTF_VAR_FMT */ 62*4126Szf162725 (void) vsnprintf(buffer, sizeof (buffer), fmt, ap); 63*4126Szf162725 64*4126Szf162725 va_end(ap); 65*4126Szf162725 66*4126Szf162725 syslog(LOG_NOTICE | LOG_DAEMON, "%s", buffer); 67*4126Szf162725 } 68*4126Szf162725 69*4126Szf162725 /* 70*4126Szf162725 * wpa_hexdump - conditional hex dump 71*4126Szf162725 * @level: priority level (MSG_*) of the message 72*4126Szf162725 * @title: title of for the message 73*4126Szf162725 * @buf: data buffer to be dumped 74*4126Szf162725 * @len: length of the @buf 75*4126Szf162725 * 76*4126Szf162725 * This function is used to print conditional debugging and error messages. The 77*4126Szf162725 * output may be directed to stdout, stderr, and/or syslog based on 78*4126Szf162725 * configuration. The contents of @buf is printed out has hex dump. 79*4126Szf162725 */ 80*4126Szf162725 void 81*4126Szf162725 wpa_hexdump(int level, const char *title, const uint8_t *buf, size_t len) 82*4126Szf162725 { 83*4126Szf162725 size_t i; 84*4126Szf162725 char buffer[MAX_LOGBUF], tmp[4]; 85*4126Szf162725 int n; 86*4126Szf162725 87*4126Szf162725 if (level < wpa_debug_level) 88*4126Szf162725 return; 89*4126Szf162725 90*4126Szf162725 (void) snprintf(buffer, sizeof (buffer), "%s - hexdump(len=%d):", 91*4126Szf162725 title, len); 92*4126Szf162725 n = strlen(buffer); 93*4126Szf162725 94*4126Szf162725 for (i = 0; i < len; i++) { 95*4126Szf162725 (void) sprintf(tmp, " %02x", buf[i]); 96*4126Szf162725 97*4126Szf162725 n += strlen(tmp); 98*4126Szf162725 if (n >= MAX_LOGBUF) break; 99*4126Szf162725 100*4126Szf162725 (void) strlcat(buffer, tmp, sizeof (buffer)); 101*4126Szf162725 } 102*4126Szf162725 103*4126Szf162725 syslog(LOG_NOTICE | LOG_DAEMON, "%s", buffer); 104*4126Szf162725 } 105*4126Szf162725 106*4126Szf162725 static const char * 107*4126Szf162725 wpa_ssid_txt(char *ssid, size_t ssid_len) 108*4126Szf162725 { 109*4126Szf162725 static char ssid_txt[MAX_ESSID_LENGTH + 1]; 110*4126Szf162725 char *pos; 111*4126Szf162725 112*4126Szf162725 if (ssid_len > MAX_ESSID_LENGTH) 113*4126Szf162725 ssid_len = MAX_ESSID_LENGTH; 114*4126Szf162725 (void) memcpy(ssid_txt, ssid, ssid_len); 115*4126Szf162725 ssid_txt[ssid_len] = '\0'; 116*4126Szf162725 for (pos = ssid_txt; *pos != '\0'; pos ++) { 117*4126Szf162725 if ((uint8_t)*pos < 32 || (uint8_t)*pos >= 127) 118*4126Szf162725 *pos = '_'; 119*4126Szf162725 } 120*4126Szf162725 return (ssid_txt); 121*4126Szf162725 } 122*4126Szf162725 123*4126Szf162725 /* ARGSUSED */ 124*4126Szf162725 void 125*4126Szf162725 wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) 126*4126Szf162725 { 127*4126Szf162725 struct wpa_supplicant *wpa_s = eloop_ctx; 128*4126Szf162725 struct wpa_ssid *ssid; 129*4126Szf162725 130*4126Szf162725 if (wpa_s->conf == NULL) 131*4126Szf162725 return; 132*4126Szf162725 133*4126Szf162725 if (wpa_s->wpa_state == WPA_DISCONNECTED) 134*4126Szf162725 wpa_s->wpa_state = WPA_SCANNING; 135*4126Szf162725 136*4126Szf162725 ssid = wpa_s->conf->ssid; 137*4126Szf162725 wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)", 138*4126Szf162725 ssid ? "specific": "broadcast"); 139*4126Szf162725 140*4126Szf162725 if (ssid) { 141*4126Szf162725 wpa_printf(MSG_DEBUG, "Scan SSID: %s", ssid->ssid); 142*4126Szf162725 } 143*4126Szf162725 144*4126Szf162725 if (wpa_s->driver->scan(wpa_s->ifname)) { 145*4126Szf162725 wpa_printf(MSG_WARNING, "Failed to initiate AP scan."); 146*4126Szf162725 } 147*4126Szf162725 } 148*4126Szf162725 149*4126Szf162725 void 150*4126Szf162725 wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) 151*4126Szf162725 { 152*4126Szf162725 wpa_printf(MSG_DEBUG, "Setting scan request: %d sec %d usec", 153*4126Szf162725 sec, usec); 154*4126Szf162725 (void) eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 155*4126Szf162725 (void) eloop_register_timeout(sec, usec, wpa_supplicant_scan, 156*4126Szf162725 wpa_s, NULL); 157*4126Szf162725 } 158*4126Szf162725 159*4126Szf162725 void 160*4126Szf162725 wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) 161*4126Szf162725 { 162*4126Szf162725 wpa_printf(MSG_DEBUG, "Cancelling scan request"); 163*4126Szf162725 eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); 164*4126Szf162725 } 165*4126Szf162725 166*4126Szf162725 /* ARGSUSED */ 167*4126Szf162725 static void 168*4126Szf162725 wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx) 169*4126Szf162725 { 170*4126Szf162725 struct wpa_supplicant *wpa_s = eloop_ctx; 171*4126Szf162725 172*4126Szf162725 wpa_printf(MSG_INFO, "Authentication with " MACSTR " timed out.", 173*4126Szf162725 MAC2STR(wpa_s->bssid)); 174*4126Szf162725 175*4126Szf162725 wpa_s->reassociate = 1; 176*4126Szf162725 wpa_supplicant_req_scan(wpa_s, 0, 0); 177*4126Szf162725 } 178*4126Szf162725 179*4126Szf162725 void 180*4126Szf162725 wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, 181*4126Szf162725 int sec, int usec) 182*4126Szf162725 { 183*4126Szf162725 wpa_printf(MSG_DEBUG, "Setting authentication timeout: %d sec " 184*4126Szf162725 "%d usec", sec, usec); 185*4126Szf162725 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); 186*4126Szf162725 (void) eloop_register_timeout(sec, usec, wpa_supplicant_timeout, 187*4126Szf162725 wpa_s, NULL); 188*4126Szf162725 } 189*4126Szf162725 190*4126Szf162725 void 191*4126Szf162725 wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s) 192*4126Szf162725 { 193*4126Szf162725 wpa_printf(MSG_DEBUG, "Cancelling authentication timeout"); 194*4126Szf162725 eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); 195*4126Szf162725 } 196*4126Szf162725 197*4126Szf162725 static void 198*4126Szf162725 wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) 199*4126Szf162725 { 200*4126Szf162725 l2_packet_deinit(wpa_s->l2); 201*4126Szf162725 wpa_s->l2 = NULL; 202*4126Szf162725 203*4126Szf162725 if (wpa_s->conf != NULL) { 204*4126Szf162725 wpa_config_free(wpa_s->conf); 205*4126Szf162725 wpa_s->conf = NULL; 206*4126Szf162725 } 207*4126Szf162725 208*4126Szf162725 free(wpa_s->ap_wpa_ie); 209*4126Szf162725 pmksa_candidate_free(wpa_s); 210*4126Szf162725 pmksa_cache_free(wpa_s); 211*4126Szf162725 } 212*4126Szf162725 213*4126Szf162725 static void 214*4126Szf162725 wpa_clear_keys(struct wpa_supplicant *wpa_s, uint8_t *addr) 215*4126Szf162725 { 216*4126Szf162725 wpa_s->driver->set_key(wpa_s->ifname, WPA_ALG_NONE, 217*4126Szf162725 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 0, 0, NULL, 0, NULL, 0); 218*4126Szf162725 wpa_s->driver->set_key(wpa_s->ifname, WPA_ALG_NONE, 219*4126Szf162725 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 1, 0, NULL, 0, NULL, 0); 220*4126Szf162725 wpa_s->driver->set_key(wpa_s->ifname, WPA_ALG_NONE, 221*4126Szf162725 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 2, 0, NULL, 0, NULL, 0); 222*4126Szf162725 wpa_s->driver->set_key(wpa_s->ifname, WPA_ALG_NONE, 223*4126Szf162725 (uint8_t *)"\xff\xff\xff\xff\xff\xff", 3, 0, NULL, 0, NULL, 0); 224*4126Szf162725 if (addr) { 225*4126Szf162725 wpa_s->driver->set_key(wpa_s->ifname, WPA_ALG_NONE, addr, 226*4126Szf162725 0, 0, NULL, 0, NULL, 0); 227*4126Szf162725 } 228*4126Szf162725 } 229*4126Szf162725 230*4126Szf162725 static void 231*4126Szf162725 wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) 232*4126Szf162725 { 233*4126Szf162725 wpa_s->wpa_state = WPA_DISCONNECTED; 234*4126Szf162725 (void) memset(wpa_s->bssid, 0, IEEE80211_ADDR_LEN); 235*4126Szf162725 } 236*4126Szf162725 237*4126Szf162725 static int 238*4126Szf162725 wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, 239*4126Szf162725 dladm_wlan_ess_t *bss, struct wpa_ssid *ssid, 240*4126Szf162725 uint8_t *wpa_ie, int *wpa_ie_len) 241*4126Szf162725 { 242*4126Szf162725 struct wpa_ie_data ie; 243*4126Szf162725 int sel, proto; 244*4126Szf162725 uint8_t *ap_ie; 245*4126Szf162725 size_t ap_ie_len; 246*4126Szf162725 247*4126Szf162725 /* RSN or WPA */ 248*4126Szf162725 if (bss->we_wpa_ie_len && bss->we_wpa_ie[0] == RSN_INFO_ELEM && 249*4126Szf162725 (ssid->proto & WPA_PROTO_RSN)) { 250*4126Szf162725 wpa_printf(MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0"); 251*4126Szf162725 proto = WPA_PROTO_RSN; 252*4126Szf162725 } else { 253*4126Szf162725 wpa_printf(MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0"); 254*4126Szf162725 proto = WPA_PROTO_WPA; 255*4126Szf162725 } 256*4126Szf162725 257*4126Szf162725 ap_ie = bss->we_wpa_ie; 258*4126Szf162725 ap_ie_len = bss->we_wpa_ie_len; 259*4126Szf162725 260*4126Szf162725 if (wpa_parse_wpa_ie(wpa_s, ap_ie, ap_ie_len, &ie)) { 261*4126Szf162725 wpa_printf(MSG_WARNING, "WPA: Failed to parse WPA IE for " 262*4126Szf162725 "the selected BSS."); 263*4126Szf162725 return (-1); 264*4126Szf162725 } 265*4126Szf162725 266*4126Szf162725 wpa_s->proto = proto; 267*4126Szf162725 free(wpa_s->ap_wpa_ie); 268*4126Szf162725 wpa_s->ap_wpa_ie = malloc(ap_ie_len); 269*4126Szf162725 (void) memcpy(wpa_s->ap_wpa_ie, ap_ie, ap_ie_len); 270*4126Szf162725 wpa_s->ap_wpa_ie_len = ap_ie_len; 271*4126Szf162725 272*4126Szf162725 sel = ie.group_cipher & ssid->group_cipher; 273*4126Szf162725 if (sel & WPA_CIPHER_CCMP) { 274*4126Szf162725 wpa_s->group_cipher = WPA_CIPHER_CCMP; 275*4126Szf162725 } else if (sel & WPA_CIPHER_TKIP) { 276*4126Szf162725 wpa_s->group_cipher = WPA_CIPHER_TKIP; 277*4126Szf162725 } else if (sel & WPA_CIPHER_WEP104) { 278*4126Szf162725 wpa_s->group_cipher = WPA_CIPHER_WEP104; 279*4126Szf162725 } else if (sel & WPA_CIPHER_WEP40) { 280*4126Szf162725 wpa_s->group_cipher = WPA_CIPHER_WEP40; 281*4126Szf162725 } else { 282*4126Szf162725 wpa_printf(MSG_WARNING, "WPA: Failed to select group cipher."); 283*4126Szf162725 return (-1); 284*4126Szf162725 } 285*4126Szf162725 286*4126Szf162725 sel = ie.pairwise_cipher & ssid->pairwise_cipher; 287*4126Szf162725 if (sel & WPA_CIPHER_CCMP) { 288*4126Szf162725 wpa_s->pairwise_cipher = WPA_CIPHER_CCMP; 289*4126Szf162725 } else if (sel & WPA_CIPHER_TKIP) { 290*4126Szf162725 wpa_s->pairwise_cipher = WPA_CIPHER_TKIP; 291*4126Szf162725 } else if (sel & WPA_CIPHER_NONE) { 292*4126Szf162725 wpa_s->pairwise_cipher = WPA_CIPHER_NONE; 293*4126Szf162725 } else { 294*4126Szf162725 wpa_printf(MSG_WARNING, "WPA: Failed to select pairwise " 295*4126Szf162725 "cipher."); 296*4126Szf162725 return (-1); 297*4126Szf162725 } 298*4126Szf162725 299*4126Szf162725 sel = ie.key_mgmt & ssid->key_mgmt; 300*4126Szf162725 if (sel & WPA_KEY_MGMT_IEEE8021X) { 301*4126Szf162725 wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X; 302*4126Szf162725 } else if (sel & WPA_KEY_MGMT_PSK) { 303*4126Szf162725 wpa_s->key_mgmt = WPA_KEY_MGMT_PSK; 304*4126Szf162725 } else { 305*4126Szf162725 wpa_printf(MSG_WARNING, "WPA: Failed to select authenticated " 306*4126Szf162725 "key management type."); 307*4126Szf162725 return (-1); 308*4126Szf162725 } 309*4126Szf162725 310*4126Szf162725 *wpa_ie_len = wpa_gen_wpa_ie(wpa_s, wpa_ie); 311*4126Szf162725 if (*wpa_ie_len < 0) { 312*4126Szf162725 wpa_printf(MSG_WARNING, "WPA: Failed to generate WPA IE."); 313*4126Szf162725 return (-1); 314*4126Szf162725 } 315*4126Szf162725 wpa_hexdump(MSG_DEBUG, "WPA: Own WPA IE", wpa_ie, *wpa_ie_len); 316*4126Szf162725 317*4126Szf162725 if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) 318*4126Szf162725 (void) memcpy(wpa_s->pmk, ssid->psk, PMK_LEN); 319*4126Szf162725 else if (wpa_s->cur_pmksa) 320*4126Szf162725 (void) memcpy(wpa_s->pmk, wpa_s->cur_pmksa->pmk, PMK_LEN); 321*4126Szf162725 else { 322*4126Szf162725 (void) memset(wpa_s->pmk, 0, PMK_LEN); 323*4126Szf162725 } 324*4126Szf162725 325*4126Szf162725 return (0); 326*4126Szf162725 } 327*4126Szf162725 328*4126Szf162725 static void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, 329*4126Szf162725 dladm_wlan_ess_t *bss, struct wpa_ssid *ssid) 330*4126Szf162725 { 331*4126Szf162725 uint8_t wpa_ie[IEEE80211_MAX_OPT_IE]; 332*4126Szf162725 int wpa_ie_len; 333*4126Szf162725 334*4126Szf162725 wpa_s->reassociate = 0; 335*4126Szf162725 wpa_printf(MSG_DEBUG, "Trying to associate with " MACSTR 336*4126Szf162725 " (SSID='%s' freq=%d MHz)", MAC2STR(bss->we_bssid.wb_bytes), 337*4126Szf162725 wpa_ssid_txt((char *)ssid->ssid, ssid->ssid_len), bss->we_freq); 338*4126Szf162725 wpa_supplicant_cancel_scan(wpa_s); 339*4126Szf162725 340*4126Szf162725 if (bss->we_wpa_ie_len && 341*4126Szf162725 (ssid->key_mgmt & (WPA_KEY_MGMT_IEEE8021X | WPA_KEY_MGMT_PSK))) { 342*4126Szf162725 wpa_s->cur_pmksa = pmksa_cache_get(wpa_s, 343*4126Szf162725 bss->we_bssid.wb_bytes, NULL); 344*4126Szf162725 if (wpa_s->cur_pmksa) { 345*4126Szf162725 wpa_hexdump(MSG_DEBUG, "RSN: PMKID", 346*4126Szf162725 wpa_s->cur_pmksa->pmkid, PMKID_LEN); 347*4126Szf162725 } 348*4126Szf162725 if (wpa_supplicant_set_suites(wpa_s, bss, ssid, 349*4126Szf162725 wpa_ie, &wpa_ie_len)) { 350*4126Szf162725 wpa_printf(MSG_WARNING, "WPA: Failed to set WPA key " 351*4126Szf162725 "management and encryption suites"); 352*4126Szf162725 return; 353*4126Szf162725 } 354*4126Szf162725 } else { 355*4126Szf162725 wpa_ie_len = 0; 356*4126Szf162725 } 357*4126Szf162725 358*4126Szf162725 wpa_clear_keys(wpa_s, bss->we_bssid.wb_bytes); 359*4126Szf162725 wpa_s->wpa_state = WPA_ASSOCIATING; 360*4126Szf162725 wpa_s->driver->associate(wpa_s->ifname, 361*4126Szf162725 (const char *)bss->we_bssid.wb_bytes, wpa_ie, wpa_ie_len); 362*4126Szf162725 363*4126Szf162725 /* Timeout for IEEE 802.11 authentication and association */ 364*4126Szf162725 wpa_supplicant_req_auth_timeout(wpa_s, 15, 0); 365*4126Szf162725 } 366*4126Szf162725 367*4126Szf162725 void 368*4126Szf162725 wpa_supplicant_disassociate(struct wpa_supplicant *wpa_s, int reason_code) 369*4126Szf162725 { 370*4126Szf162725 uint8_t *addr = NULL; 371*4126Szf162725 wpa_s->wpa_state = WPA_DISCONNECTED; 372*4126Szf162725 if (memcmp(wpa_s->bssid, "\x00\x00\x00\x00\x00\x00", 373*4126Szf162725 IEEE80211_ADDR_LEN) != 0) { 374*4126Szf162725 wpa_s->driver->disassociate(wpa_s->ifname, reason_code); 375*4126Szf162725 addr = wpa_s->bssid; 376*4126Szf162725 } 377*4126Szf162725 wpa_clear_keys(wpa_s, addr); 378*4126Szf162725 } 379*4126Szf162725 380*4126Szf162725 static dladm_wlan_ess_t * 381*4126Szf162725 wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, struct wpa_ssid *group, 382*4126Szf162725 dladm_wlan_ess_t *results, int num, struct wpa_ssid **selected_ssid) 383*4126Szf162725 { 384*4126Szf162725 struct wpa_ssid *ssid; 385*4126Szf162725 dladm_wlan_ess_t *bss, *selected = NULL; 386*4126Szf162725 int i; 387*4126Szf162725 388*4126Szf162725 struct wpa_ie_data ie; 389*4126Szf162725 390*4126Szf162725 wpa_printf(MSG_DEBUG, "Selecting BSS from scan results (%d)", num); 391*4126Szf162725 392*4126Szf162725 bss = NULL; 393*4126Szf162725 ssid = NULL; 394*4126Szf162725 395*4126Szf162725 /* try to find matched AP */ 396*4126Szf162725 for (i = 0; i < num && !selected; i++) { 397*4126Szf162725 bss = &results[i]; 398*4126Szf162725 wpa_printf(MSG_DEBUG, "%d: " MACSTR " ssid='%s' " 399*4126Szf162725 "wpa_ie_len=%d", 400*4126Szf162725 i, MAC2STR(bss->we_bssid.wb_bytes), 401*4126Szf162725 wpa_ssid_txt(bss->we_ssid.we_bytes, bss->we_ssid_len), 402*4126Szf162725 bss->we_wpa_ie_len); 403*4126Szf162725 if (bss->we_wpa_ie_len == 0) { 404*4126Szf162725 wpa_printf(MSG_DEBUG, " skip - no WPA/RSN IE"); 405*4126Szf162725 } 406*4126Szf162725 407*4126Szf162725 ssid = group; 408*4126Szf162725 if (bss->we_ssid_len != ssid->ssid_len || 409*4126Szf162725 memcmp(bss->we_ssid.we_bytes, ssid->ssid, 410*4126Szf162725 bss->we_ssid_len) != 0) { 411*4126Szf162725 wpa_printf(MSG_DEBUG, " skip - SSID mismatch"); 412*4126Szf162725 continue; 413*4126Szf162725 } 414*4126Szf162725 if (!((ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_WPA)) && 415*4126Szf162725 wpa_parse_wpa_ie(wpa_s, bss->we_wpa_ie, 416*4126Szf162725 bss->we_wpa_ie_len, &ie) == 0)) { 417*4126Szf162725 wpa_printf(MSG_DEBUG, " skip - " 418*4126Szf162725 "could not parse WPA/RSN IE"); 419*4126Szf162725 continue; 420*4126Szf162725 } 421*4126Szf162725 if (!(ie.proto & ssid->proto)) { 422*4126Szf162725 wpa_printf(MSG_DEBUG, " skip - proto mismatch"); 423*4126Szf162725 continue; 424*4126Szf162725 } 425*4126Szf162725 if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { 426*4126Szf162725 wpa_printf(MSG_DEBUG, " skip - PTK cipher mismatch"); 427*4126Szf162725 continue; 428*4126Szf162725 } 429*4126Szf162725 if (!(ie.group_cipher & ssid->group_cipher)) { 430*4126Szf162725 wpa_printf(MSG_DEBUG, " skip - GTK cipher mismatch"); 431*4126Szf162725 continue; 432*4126Szf162725 } 433*4126Szf162725 if (!(ie.key_mgmt & ssid->key_mgmt)) { 434*4126Szf162725 wpa_printf(MSG_DEBUG, " skip - key mgmt mismatch"); 435*4126Szf162725 continue; 436*4126Szf162725 } 437*4126Szf162725 438*4126Szf162725 selected = bss; 439*4126Szf162725 *selected_ssid = ssid; 440*4126Szf162725 wpa_printf(MSG_DEBUG, " selected"); 441*4126Szf162725 } 442*4126Szf162725 443*4126Szf162725 return (selected); 444*4126Szf162725 } 445*4126Szf162725 446*4126Szf162725 447*4126Szf162725 static void 448*4126Szf162725 wpa_supplicant_scan_results(struct wpa_supplicant *wpa_s) 449*4126Szf162725 { 450*4126Szf162725 dladm_wlan_ess_t results[MAX_SCANRESULTS]; 451*4126Szf162725 int num; 452*4126Szf162725 dladm_wlan_ess_t *selected = NULL; 453*4126Szf162725 struct wpa_ssid *ssid; 454*4126Szf162725 455*4126Szf162725 (void) memset(results, 0, sizeof (dladm_wlan_ess_t) * MAX_SCANRESULTS); 456*4126Szf162725 num = wpa_s->driver->get_scan_results(wpa_s->ifname, results, 457*4126Szf162725 MAX_SCANRESULTS); 458*4126Szf162725 wpa_printf(MSG_DEBUG, "Scan results: %d", num); 459*4126Szf162725 if (num < 0) 460*4126Szf162725 return; 461*4126Szf162725 if (num > MAX_SCANRESULTS) { 462*4126Szf162725 wpa_printf(MSG_INFO, "Not enough room for all APs (%d < %d)", 463*4126Szf162725 num, MAX_SCANRESULTS); 464*4126Szf162725 num = MAX_SCANRESULTS; 465*4126Szf162725 } 466*4126Szf162725 467*4126Szf162725 selected = wpa_supplicant_select_bss(wpa_s, 468*4126Szf162725 wpa_s->conf->ssid, results, num, &ssid); 469*4126Szf162725 470*4126Szf162725 if (selected) { 471*4126Szf162725 if (wpa_s->reassociate || 472*4126Szf162725 memcmp(selected->we_bssid.wb_bytes, wpa_s->bssid, 473*4126Szf162725 IEEE80211_ADDR_LEN) != 0) { 474*4126Szf162725 wpa_supplicant_associate(wpa_s, selected, ssid); 475*4126Szf162725 } else { 476*4126Szf162725 wpa_printf(MSG_DEBUG, "Already associated with the " 477*4126Szf162725 "selected AP."); 478*4126Szf162725 } 479*4126Szf162725 } else { 480*4126Szf162725 wpa_printf(MSG_DEBUG, "No suitable AP found."); 481*4126Szf162725 wpa_supplicant_req_scan(wpa_s, 5, 0); /* wait 5 seconds */ 482*4126Szf162725 } 483*4126Szf162725 } 484*4126Szf162725 485*4126Szf162725 /* 486*4126Szf162725 * wpa_event_handler - report a driver event for wpa_supplicant 487*4126Szf162725 * @wpa_s: pointer to wpa_supplicant data; this is the @ctx variable registered 488*4126Szf162725 * with wpa_driver_events_init() 489*4126Szf162725 * @event: event type (defined above) 490*4126Szf162725 * 491*4126Szf162725 * Driver wrapper code should call this function whenever an event is received 492*4126Szf162725 * from the driver. 493*4126Szf162725 */ 494*4126Szf162725 void 495*4126Szf162725 wpa_event_handler(void *cookie, wpa_event_type event) 496*4126Szf162725 { 497*4126Szf162725 struct wpa_supplicant *wpa_s = cookie; 498*4126Szf162725 uint8_t bssid[IEEE80211_ADDR_LEN]; 499*4126Szf162725 500*4126Szf162725 switch (event) { 501*4126Szf162725 case EVENT_ASSOC: 502*4126Szf162725 wpa_s->wpa_state = WPA_ASSOCIATED; 503*4126Szf162725 wpa_printf(MSG_DEBUG, "\nAssociation event - clear replay " 504*4126Szf162725 "counter\n"); 505*4126Szf162725 (void) memset(wpa_s->rx_replay_counter, 0, 506*4126Szf162725 WPA_REPLAY_COUNTER_LEN); 507*4126Szf162725 wpa_s->rx_replay_counter_set = 0; 508*4126Szf162725 wpa_s->renew_snonce = 1; 509*4126Szf162725 if (wpa_s->driver->get_bssid(wpa_s->ifname, 510*4126Szf162725 (char *)bssid) >= 0 && 511*4126Szf162725 memcmp(bssid, wpa_s->bssid, IEEE80211_ADDR_LEN) != 0) { 512*4126Szf162725 wpa_printf(MSG_DEBUG, "Associated to a new BSS: " 513*4126Szf162725 "BSSID=" MACSTR, MAC2STR(bssid)); 514*4126Szf162725 (void) memcpy(wpa_s->bssid, bssid, IEEE80211_ADDR_LEN); 515*4126Szf162725 if (wpa_s->key_mgmt != WPA_KEY_MGMT_NONE) 516*4126Szf162725 wpa_clear_keys(wpa_s, bssid); 517*4126Szf162725 } 518*4126Szf162725 519*4126Szf162725 wpa_s->eapol_received = 0; 520*4126Szf162725 if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { 521*4126Szf162725 wpa_supplicant_cancel_auth_timeout(wpa_s); 522*4126Szf162725 } else { 523*4126Szf162725 /* Timeout for receiving the first EAPOL packet */ 524*4126Szf162725 wpa_supplicant_req_auth_timeout(wpa_s, 10, 0); 525*4126Szf162725 } 526*4126Szf162725 break; 527*4126Szf162725 case EVENT_DISASSOC: 528*4126Szf162725 if (wpa_s->wpa_state >= WPA_ASSOCIATED) 529*4126Szf162725 wpa_supplicant_req_scan(wpa_s, 0, 100000); 530*4126Szf162725 wpa_supplicant_mark_disassoc(wpa_s); 531*4126Szf162725 wpa_printf(MSG_DEBUG, "Disconnect event - remove keys"); 532*4126Szf162725 if (wpa_s->key_mgmt != WPA_KEY_MGMT_NONE) 533*4126Szf162725 wpa_clear_keys(wpa_s, wpa_s->bssid); 534*4126Szf162725 break; 535*4126Szf162725 case EVENT_SCAN_RESULTS: 536*4126Szf162725 wpa_supplicant_scan_results(wpa_s); 537*4126Szf162725 break; 538*4126Szf162725 default: 539*4126Szf162725 wpa_printf(MSG_INFO, "Unknown event %d", event); 540*4126Szf162725 break; 541*4126Szf162725 } 542*4126Szf162725 } 543*4126Szf162725 544*4126Szf162725 /* ARGSUSED */ 545*4126Szf162725 static void 546*4126Szf162725 wpa_supplicant_terminate(int sig, void *eloop_ctx, void *signal_ctx) 547*4126Szf162725 { 548*4126Szf162725 wpa_printf(MSG_INFO, "Signal %d received - terminating", sig); 549*4126Szf162725 eloop_terminate(); 550*4126Szf162725 } 551*4126Szf162725 552*4126Szf162725 static int 553*4126Szf162725 wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s) 554*4126Szf162725 { 555*4126Szf162725 wpa_s->l2 = l2_packet_init(wpa_s->ifname, ETHERTYPE_EAPOL, 556*4126Szf162725 wpa_supplicant_rx_eapol, wpa_s); 557*4126Szf162725 if (wpa_s->l2 == NULL) 558*4126Szf162725 return (-1); 559*4126Szf162725 560*4126Szf162725 if (l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) { 561*4126Szf162725 (void) fprintf(stderr, "Failed to get own L2 address\n"); 562*4126Szf162725 return (-1); 563*4126Szf162725 } 564*4126Szf162725 565*4126Szf162725 if (wpa_s->driver->set_wpa(wpa_s->ifname, 1) < 0) { 566*4126Szf162725 wpa_printf(MSG_ERROR, "Failed to enable WPA in the driver."); 567*4126Szf162725 return (-1); 568*4126Szf162725 } 569*4126Szf162725 570*4126Szf162725 wpa_clear_keys(wpa_s, NULL); 571*4126Szf162725 wpa_supplicant_req_scan(wpa_s, 0, 100000); 572*4126Szf162725 573*4126Szf162725 return (0); 574*4126Szf162725 } 575*4126Szf162725 576*4126Szf162725 static int door_id = -1; 577*4126Szf162725 578*4126Szf162725 /* ARGSUSED */ 579*4126Szf162725 static void 580*4126Szf162725 event_handler(void *cookie, char *argp, size_t asize, 581*4126Szf162725 door_desc_t *dp, uint_t n_desc) 582*4126Szf162725 { 583*4126Szf162725 wpa_event_type event; 584*4126Szf162725 585*4126Szf162725 event = ((wl_events_t *)argp)->event; 586*4126Szf162725 wpa_event_handler(cookie, event); 587*4126Szf162725 588*4126Szf162725 (void) door_return(NULL, 0, NULL, 0); 589*4126Szf162725 } 590*4126Szf162725 591*4126Szf162725 /* 592*4126Szf162725 * Create the driver to wpad door 593*4126Szf162725 */ 594*4126Szf162725 int 595*4126Szf162725 wpa_supplicant_door_setup(void *cookie, char *doorname) 596*4126Szf162725 { 597*4126Szf162725 struct stat stbuf; 598*4126Szf162725 int error = 0; 599*4126Szf162725 600*4126Szf162725 wpa_printf(MSG_DEBUG, "wpa_supplicant_door_setup(%s)", doorname); 601*4126Szf162725 /* 602*4126Szf162725 * Create the door 603*4126Szf162725 */ 604*4126Szf162725 door_id = door_create(event_handler, cookie, 605*4126Szf162725 DOOR_UNREF | DOOR_REFUSE_DESC | DOOR_NO_CANCEL); 606*4126Szf162725 607*4126Szf162725 if (door_id < 0) { 608*4126Szf162725 error = -1; 609*4126Szf162725 goto out; 610*4126Szf162725 } 611*4126Szf162725 612*4126Szf162725 if (stat(doorname, &stbuf) < 0) { 613*4126Szf162725 int newfd; 614*4126Szf162725 if ((newfd = creat(doorname, 0666)) < 0) { 615*4126Szf162725 (void) door_revoke(door_id); 616*4126Szf162725 door_id = -1; 617*4126Szf162725 error = -1; 618*4126Szf162725 619*4126Szf162725 goto out; 620*4126Szf162725 } 621*4126Szf162725 (void) close(newfd); 622*4126Szf162725 } 623*4126Szf162725 624*4126Szf162725 if (fattach(door_id, doorname) < 0) { 625*4126Szf162725 if ((errno != EBUSY) || (fdetach(doorname) < 0) || 626*4126Szf162725 (fattach(door_id, doorname) < 0)) { 627*4126Szf162725 (void) door_revoke(door_id); 628*4126Szf162725 door_id = -1; 629*4126Szf162725 error = -1; 630*4126Szf162725 631*4126Szf162725 goto out; 632*4126Szf162725 } 633*4126Szf162725 } 634*4126Szf162725 635*4126Szf162725 out: 636*4126Szf162725 return (error); 637*4126Szf162725 } 638*4126Szf162725 639*4126Szf162725 void 640*4126Szf162725 wpa_supplicant_door_destroy(char *doorname) 641*4126Szf162725 { 642*4126Szf162725 wpa_printf(MSG_DEBUG, "wpa_supplicant_door_destroy(%s)\n", doorname); 643*4126Szf162725 644*4126Szf162725 if (door_revoke(door_id) == -1) { 645*4126Szf162725 wpa_printf(MSG_ERROR, "failed to door_revoke(%d) %s, exiting.", 646*4126Szf162725 door_id, strerror(errno)); 647*4126Szf162725 } 648*4126Szf162725 649*4126Szf162725 if (fdetach(doorname) == -1) { 650*4126Szf162725 wpa_printf(MSG_ERROR, "failed to fdetach %s: %s, exiting.", 651*4126Szf162725 doorname, strerror(errno)); 652*4126Szf162725 } 653*4126Szf162725 654*4126Szf162725 (void) close(door_id); 655*4126Szf162725 } 656*4126Szf162725 657*4126Szf162725 static int 658*4126Szf162725 wpa_config_parse_ssid(struct wpa_ssid *ssid, int line, const char *value) 659*4126Szf162725 { 660*4126Szf162725 free(ssid->ssid); 661*4126Szf162725 662*4126Szf162725 ssid->ssid = (uint8_t *)strdup(value); 663*4126Szf162725 ssid->ssid_len = strlen(value); 664*4126Szf162725 665*4126Szf162725 if (ssid->ssid == NULL) { 666*4126Szf162725 wpa_printf(MSG_ERROR, "Invalid SSID '%s'.", line, value); 667*4126Szf162725 return (-1); 668*4126Szf162725 } 669*4126Szf162725 if (ssid->ssid_len > MAX_ESSID_LENGTH) { 670*4126Szf162725 free(ssid->ssid); 671*4126Szf162725 wpa_printf(MSG_ERROR, "Too long SSID '%s'.", line, value); 672*4126Szf162725 return (-1); 673*4126Szf162725 } 674*4126Szf162725 wpa_printf(MSG_MSGDUMP, "SSID: %s", ssid->ssid); 675*4126Szf162725 return (0); 676*4126Szf162725 } 677*4126Szf162725 678*4126Szf162725 static struct wpa_ssid * 679*4126Szf162725 wpa_config_read_network(struct wpa_supplicant *wpa_s) 680*4126Szf162725 { 681*4126Szf162725 struct wpa_ssid *ssid; 682*4126Szf162725 char buf[MAX_ESSID_LENGTH + 1]; 683*4126Szf162725 dladm_secobj_class_t cl; 684*4126Szf162725 uint8_t psk[MAX_PSK_LENGTH + 1]; 685*4126Szf162725 uint_t key_len; 686*4126Szf162725 687*4126Szf162725 wpa_printf(MSG_MSGDUMP, "Start of a new network configration"); 688*4126Szf162725 689*4126Szf162725 ssid = (struct wpa_ssid *)malloc(sizeof (*ssid)); 690*4126Szf162725 if (ssid == NULL) 691*4126Szf162725 return (NULL); 692*4126Szf162725 (void) memset(ssid, 0, sizeof (*ssid)); 693*4126Szf162725 694*4126Szf162725 /* 695*4126Szf162725 * Set default supported values 696*4126Szf162725 */ 697*4126Szf162725 ssid->proto = WPA_PROTO_WPA | WPA_PROTO_RSN; 698*4126Szf162725 ssid->pairwise_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP; 699*4126Szf162725 ssid->group_cipher = WPA_CIPHER_CCMP | WPA_CIPHER_TKIP | 700*4126Szf162725 WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40; 701*4126Szf162725 ssid->key_mgmt = WPA_KEY_MGMT_PSK; /* | WPA_KEY_MGMT_IEEE8021X; */ 702*4126Szf162725 703*4126Szf162725 (void) memset(buf, 0, MAX_ESSID_LENGTH + 1); 704*4126Szf162725 wpa_s->driver->get_ssid(wpa_s->ifname, (char *)buf); 705*4126Szf162725 706*4126Szf162725 (void) wpa_config_parse_ssid(ssid, 0, buf); 707*4126Szf162725 708*4126Szf162725 key_len = sizeof (psk); 709*4126Szf162725 (void) dladm_get_secobj((const char *)wpa_s->kname, &cl, psk, &key_len, 710*4126Szf162725 DLADM_OPT_TEMP); 711*4126Szf162725 psk[key_len] = '\0'; 712*4126Szf162725 ssid->passphrase = strdup((const char *)psk); 713*4126Szf162725 714*4126Szf162725 if (ssid->passphrase) { 715*4126Szf162725 pbkdf2_sha1(ssid->passphrase, (char *)ssid->ssid, 716*4126Szf162725 ssid->ssid_len, 4096, ssid->psk, PMK_LEN); 717*4126Szf162725 wpa_hexdump(MSG_MSGDUMP, "PSK (from passphrase)", 718*4126Szf162725 ssid->psk, PMK_LEN); 719*4126Szf162725 ssid->psk_set = 1; 720*4126Szf162725 } 721*4126Szf162725 722*4126Szf162725 if ((ssid->key_mgmt & WPA_KEY_MGMT_PSK) && !ssid->psk_set) { 723*4126Szf162725 wpa_printf(MSG_ERROR, "WPA-PSK accepted for key " 724*4126Szf162725 "management, but no PSK configured."); 725*4126Szf162725 free(ssid); 726*4126Szf162725 ssid = NULL; 727*4126Szf162725 } 728*4126Szf162725 729*4126Szf162725 return (ssid); 730*4126Szf162725 } 731*4126Szf162725 732*4126Szf162725 struct wpa_config * 733*4126Szf162725 wpa_config_read(void *arg) 734*4126Szf162725 { 735*4126Szf162725 struct wpa_ssid *ssid; 736*4126Szf162725 struct wpa_config *config; 737*4126Szf162725 struct wpa_supplicant *wpa_s = arg; 738*4126Szf162725 739*4126Szf162725 config = malloc(sizeof (*config)); 740*4126Szf162725 if (config == NULL) 741*4126Szf162725 return (NULL); 742*4126Szf162725 (void) memset(config, 0, sizeof (*config)); 743*4126Szf162725 config->eapol_version = 1; /* fixed value */ 744*4126Szf162725 745*4126Szf162725 wpa_printf(MSG_DEBUG, "Reading configuration parameters from driver\n"); 746*4126Szf162725 747*4126Szf162725 ssid = wpa_config_read_network(wpa_s); 748*4126Szf162725 if (ssid == NULL) { 749*4126Szf162725 wpa_config_free(config); 750*4126Szf162725 config = NULL; 751*4126Szf162725 } else { 752*4126Szf162725 config->ssid = ssid; 753*4126Szf162725 } 754*4126Szf162725 755*4126Szf162725 return (config); 756*4126Szf162725 } 757*4126Szf162725 758*4126Szf162725 void 759*4126Szf162725 wpa_config_free(struct wpa_config *config) 760*4126Szf162725 { 761*4126Szf162725 struct wpa_ssid *ssid = config->ssid; 762*4126Szf162725 763*4126Szf162725 free(ssid->ssid); 764*4126Szf162725 free(ssid->passphrase); 765*4126Szf162725 free(ssid); 766*4126Szf162725 free(config); 767*4126Szf162725 } 768*4126Szf162725 769*4126Szf162725 static int 770*4126Szf162725 daemon(boolean_t nochdir, boolean_t noclose) 771*4126Szf162725 { 772*4126Szf162725 int retv; 773*4126Szf162725 774*4126Szf162725 if ((retv = fork()) == -1) 775*4126Szf162725 return (-1); 776*4126Szf162725 if (retv != 0) 777*4126Szf162725 _exit(EXIT_SUCCESS); 778*4126Szf162725 if (setsid() == -1) 779*4126Szf162725 return (-1); 780*4126Szf162725 781*4126Szf162725 if (!nochdir && chdir("/") == -1) 782*4126Szf162725 return (-1); 783*4126Szf162725 784*4126Szf162725 if (!noclose) { 785*4126Szf162725 (void) close(0); 786*4126Szf162725 (void) close(1); 787*4126Szf162725 (void) close(2); 788*4126Szf162725 if ((retv = open("/dev/null", O_RDWR)) != -1) { 789*4126Szf162725 (void) dup2(retv, 1); 790*4126Szf162725 (void) dup2(retv, 2); 791*4126Szf162725 } 792*4126Szf162725 } 793*4126Szf162725 794*4126Szf162725 return (0); 795*4126Szf162725 } 796*4126Szf162725 797*4126Szf162725 static void 798*4126Szf162725 usage(void) 799*4126Szf162725 { 800*4126Szf162725 (void) printf("%s\n\n" 801*4126Szf162725 "usage:\n" 802*4126Szf162725 " wpa_supplicant [-hv] -i<ifname> -k<keyname>" 803*4126Szf162725 "\n" 804*4126Szf162725 "options:\n" 805*4126Szf162725 " -h = show this help text\n" 806*4126Szf162725 " -v = show version\n", 807*4126Szf162725 wpa_supplicant_version); 808*4126Szf162725 } 809*4126Szf162725 810*4126Szf162725 int 811*4126Szf162725 main(int argc, char *argv[]) 812*4126Szf162725 { 813*4126Szf162725 struct wpa_supplicant wpa_s; 814*4126Szf162725 char *link = NULL; 815*4126Szf162725 char *key = NULL; 816*4126Szf162725 int c; 817*4126Szf162725 int exitcode; 818*4126Szf162725 char door_file[WPA_STRSIZE]; 819*4126Szf162725 820*4126Szf162725 (void) memset(&wpa_s, 0, sizeof (wpa_s)); 821*4126Szf162725 822*4126Szf162725 for (;;) { 823*4126Szf162725 c = getopt(argc, argv, "Dk:hi:v"); 824*4126Szf162725 if (c < 0) 825*4126Szf162725 break; 826*4126Szf162725 switch (c) { 827*4126Szf162725 case 'D': 828*4126Szf162725 wpa_debug_level = MSG_DEBUG; 829*4126Szf162725 break; 830*4126Szf162725 case 'h': 831*4126Szf162725 usage(); 832*4126Szf162725 return (-1); 833*4126Szf162725 case 'i': 834*4126Szf162725 link = optarg; 835*4126Szf162725 break; 836*4126Szf162725 case 'k': 837*4126Szf162725 key = optarg; 838*4126Szf162725 break; 839*4126Szf162725 case 'v': 840*4126Szf162725 (void) printf("%s\n", wpa_supplicant_version); 841*4126Szf162725 return (-1); 842*4126Szf162725 default: 843*4126Szf162725 usage(); 844*4126Szf162725 return (-1); 845*4126Szf162725 } 846*4126Szf162725 } 847*4126Szf162725 848*4126Szf162725 wpa_s.driver = &wpa_driver_wifi_ops; 849*4126Szf162725 eloop_init(&wpa_s); 850*4126Szf162725 /* 851*4126Szf162725 * key name is required to retrieve PSK value through libwdladm APIs. 852*4126Szf162725 * key is saved by dladm command by keyname 853*4126Szf162725 * see dladm. 854*4126Szf162725 */ 855*4126Szf162725 if ((link == NULL) || (key == NULL)) { 856*4126Szf162725 wpa_printf(MSG_ERROR, "\nLink & key is required."); 857*4126Szf162725 return (-1); 858*4126Szf162725 } 859*4126Szf162725 860*4126Szf162725 if ((strlen(link) >= sizeof (wpa_s.ifname)) || 861*4126Szf162725 (strlen(key) >= sizeof (wpa_s.kname))) { 862*4126Szf162725 wpa_printf(MSG_ERROR, "Too long link/key name '%s', '%s'.", 863*4126Szf162725 link, key); 864*4126Szf162725 return (-1); 865*4126Szf162725 } 866*4126Szf162725 867*4126Szf162725 (void) strlcpy(wpa_s.ifname, link, sizeof (wpa_s.ifname)); 868*4126Szf162725 (void) strlcpy(wpa_s.kname, key, sizeof (wpa_s.kname)); 869*4126Szf162725 870*4126Szf162725 /* 871*4126Szf162725 * Setup door file to communicate with driver 872*4126Szf162725 * Since this is multiple instance service, different instance 873*4126Szf162725 * has different doors. 874*4126Szf162725 */ 875*4126Szf162725 (void) snprintf(door_file, WPA_STRSIZE, "%s_%s", WPA_DOOR, link); 876*4126Szf162725 877*4126Szf162725 /* 878*4126Szf162725 * Setup default WPA/WPA2 configuration 879*4126Szf162725 * get ESSID and PSK value 880*4126Szf162725 */ 881*4126Szf162725 wpa_s.conf = wpa_config_read(&wpa_s); 882*4126Szf162725 if (wpa_s.conf == NULL || wpa_s.conf->ssid == NULL) { 883*4126Szf162725 wpa_printf(MSG_ERROR, "\nNo networks (SSID) configured.\n"); 884*4126Szf162725 return (-1); 885*4126Szf162725 } 886*4126Szf162725 887*4126Szf162725 exitcode = 0; 888*4126Szf162725 889*4126Szf162725 if (daemon(0, 0)) { 890*4126Szf162725 exitcode = -1; 891*4126Szf162725 goto cleanup; 892*4126Szf162725 } 893*4126Szf162725 894*4126Szf162725 if (wpa_supplicant_door_setup(&wpa_s, door_file) != 0) { 895*4126Szf162725 wpa_printf(MSG_ERROR, "Failed to setup door(%s)", door_file); 896*4126Szf162725 exitcode = -1; 897*4126Szf162725 goto cleanup; 898*4126Szf162725 } 899*4126Szf162725 900*4126Szf162725 wpa_s.renew_snonce = 1; 901*4126Szf162725 if (wpa_supplicant_driver_init(&wpa_s) < 0) { 902*4126Szf162725 exitcode = -1; 903*4126Szf162725 goto cleanup; 904*4126Szf162725 } 905*4126Szf162725 906*4126Szf162725 wpa_printf(MSG_DEBUG, "=> eloop_run"); 907*4126Szf162725 908*4126Szf162725 (void) eloop_register_signal(SIGINT, wpa_supplicant_terminate, NULL); 909*4126Szf162725 (void) eloop_register_signal(SIGTERM, wpa_supplicant_terminate, NULL); 910*4126Szf162725 (void) eloop_register_signal(SIGKILL, wpa_supplicant_terminate, NULL); 911*4126Szf162725 912*4126Szf162725 eloop_run(); 913*4126Szf162725 914*4126Szf162725 wpa_printf(MSG_DEBUG, "<= eloop_run()"); 915*4126Szf162725 wpa_supplicant_disassociate(&wpa_s, REASON_DEAUTH_LEAVING); 916*4126Szf162725 917*4126Szf162725 cleanup: 918*4126Szf162725 if (wpa_s.driver->set_wpa(wpa_s.ifname, 0) < 0) { 919*4126Szf162725 wpa_printf(MSG_ERROR, "Failed to disable WPA in the driver.\n"); 920*4126Szf162725 } 921*4126Szf162725 922*4126Szf162725 wpa_supplicant_door_destroy(door_file); 923*4126Szf162725 wpa_supplicant_cleanup(&wpa_s); 924*4126Szf162725 eloop_destroy(); 925*4126Szf162725 926*4126Szf162725 return (exitcode); 927*4126Szf162725 } 928