static int wpa_driver_bsd_set_ssid(void *priv, const char *ssid, size_t ssid_len) { struct wpa_driver_bsd_data *drv = priv; return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len); }
static int wpa_driver_bsd_set_bssid(void *priv, const char *bssid) { struct wpa_driver_bsd_data *drv = priv; return set80211var(drv, IEEE80211_IOC_BSSID, bssid, IEEE80211_ADDR_LEN); }
static int bsd_set_ssid(const char *ifname, void *priv, const u8 *buf, int len) { struct bsd_driver_data *drv = priv; wpa_printf(MSG_DEBUG, "%s: ssid=\"%.*s\"", __func__, len, buf); return set80211var(drv, IEEE80211_IOC_SSID, buf, len); }
static int wpa_driver_bsd_set_wpa_ie(struct bsd_driver_data *drv, const u8 *wpa_ie, size_t wpa_ie_len) { #ifdef IEEE80211_IOC_APPIE return bsd_set_opt_ie(drv, wpa_ie, wpa_ie_len); #else /* IEEE80211_IOC_APPIE */ return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len); #endif /* IEEE80211_IOC_APPIE */ }
static int bsd_set_ssid(void *priv, u8 *buf, int len) { struct bsd_driver_data *drv = priv; hostapd *hapd = drv->hapd; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: ssid=\"%.*s\"\n", __func__, len, buf); return set80211var(priv, IEEE80211_IOC_SSID, buf, len); }
static int bsd_send_mlme_param(void *priv, const u8 op, const u16 reason, const u8 *addr) { struct ieee80211req_mlme mlme; os_memset(&mlme, 0, sizeof(mlme)); mlme.im_op = op; mlme.im_reason = reason; os_memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); return set80211var(priv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); }
static int wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params) { struct wpa_driver_bsd_data *drv = priv; struct ieee80211req_mlme mlme; int privacy; wpa_printf(MSG_DEBUG, "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u" , __func__ , params->ssid_len, params->ssid , params->wpa_ie_len , params->pairwise_suite , params->group_suite , params->key_mgmt_suite ); /* XXX error handling is wrong but unclear what to do... */ if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0) return -1; #ifndef NEW_FREEBSD_MLME_ASSOC if (wpa_driver_bsd_set_ssid(drv, params->ssid, params->ssid_len) < 0) return -1; #endif privacy = !(params->pairwise_suite == CIPHER_NONE && params->group_suite == CIPHER_NONE && params->key_mgmt_suite == KEY_MGMT_NONE && params->wpa_ie_len == 0); wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy); if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0) return -1; if (params->wpa_ie_len && set80211param(drv, IEEE80211_IOC_WPA, params->wpa_ie[0] == RSN_INFO_ELEM ? 2 : 1) < 0) return -1; memset(&mlme, 0, sizeof(mlme)); mlme.im_op = IEEE80211_MLME_ASSOC; #ifdef NEW_FREEBSD_MLME_ASSOC if (params->ssid != NULL) memcpy(mlme.im_ssid, params->ssid, params->ssid_len); mlme.im_ssid_len = params->ssid_len; #endif if (params->bssid != NULL) memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN); if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0) return -1; return 0; }
static int wpa_driver_bsd_scan(void *priv, const u8 *ssid, size_t ssid_len) { struct wpa_driver_bsd_data *drv = priv; struct ieee80211_scan_req sr; int flags; /* XXX not true but easiest to perpetuate the myth */ /* NB: interface must be marked UP to do a scan */ if (getifflags(drv, &flags) != 0) { wpa_printf(MSG_DEBUG, "%s did not mark interface UP", __func__); return -1; } if ((flags & IFF_UP) == 0 && setifflags(drv, flags | IFF_UP) != 0) { wpa_printf(MSG_DEBUG, "%s unable to mark interface UP", __func__); return -1; } memset(&sr, 0, sizeof(sr)); sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE | IEEE80211_IOC_SCAN_NOJOIN ; sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER; if (ssid_len != 0) { /* XXX ssid_len must be <= IEEE80211_NWID_LEN */ memcpy(sr.sr_ssid[sr.sr_nssid].ssid, ssid, ssid_len); sr.sr_ssid[sr.sr_nssid].len = ssid_len; sr.sr_nssid++; } if (drv->lastssid_len != 0 && (drv->lastssid_len != ssid_len || memcmp(drv->lastssid, ssid, ssid_len) != 0)) { /* * If we are scanning because we received a deauth * and the scan cache is warm then we'll find the * ap there and short circuit a full-blown scan. */ memcpy(sr.sr_ssid[sr.sr_nssid].ssid, drv->lastssid, drv->lastssid_len); sr.sr_ssid[sr.sr_nssid].len = drv->lastssid_len; sr.sr_nssid++; /* NB: clear so we don't retry w/o associating first */ drv->lastssid_len = 0; } if (sr.sr_nssid != 0) /* NB: check scan cache first */ sr.sr_flags |= IEEE80211_IOC_SCAN_CHECK; /* NB: net80211 delivers a scan complete event so no need to poll */ return set80211var(drv, IEEE80211_IOC_SCAN_REQ, &sr, sizeof(sr)); }
static int wpa_driver_bsd_disassociate(void *priv, const u8 *addr, int reason_code) { struct wpa_driver_bsd_data *drv = priv; struct ieee80211req_mlme mlme; wpa_printf(MSG_DEBUG, "%s", __func__); memset(&mlme, 0, sizeof(mlme)); mlme.im_op = IEEE80211_MLME_DISASSOC; mlme.im_reason = reason_code; memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); }
static int bsd_sta_clear_stats(void *priv, const u8 *addr) { struct ieee80211req_sta_stats stats; wpa_printf(MSG_DEBUG, "%s: addr=%s", __func__, ether_sprintf(addr)); /* zero station statistics */ memset(&stats, 0, sizeof(stats)); memcpy(stats.is_u.macaddr, addr, IEEE80211_ADDR_LEN); return set80211var(priv, IEEE80211_IOC_STA_STATS, &stats, sizeof(stats)); }
static int bsd_set_key(void *priv, const char *alg, unsigned char *addr, int key_idx, u8 *key, size_t key_len) { struct bsd_driver_data *drv = priv; hostapd *hapd = drv->hapd; struct ieee80211req_key wk; u_int8_t cipher; if (strcmp(alg, "none") == 0) return bsd_del_key(priv, addr, key_idx); HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: alg=%s addr=%s key_idx=%d\n", __func__, alg, ether_sprintf(addr), key_idx); if (strcmp(alg, "WEP") == 0) cipher = IEEE80211_CIPHER_WEP; else if (strcmp(alg, "TKIP") == 0) cipher = IEEE80211_CIPHER_TKIP; else if (strcmp(alg, "CCMP") == 0) cipher = IEEE80211_CIPHER_AES_CCM; else { printf("%s: unknown/unsupported algorithm %s\n", __func__, alg); return -1; } if (key_len > sizeof(wk.ik_keydata)) { printf("%s: key length %d too big\n", __func__, key_len); return -3; } memset(&wk, 0, sizeof(wk)); wk.ik_type = cipher; wk.ik_flags = IEEE80211_KEY_RECV | IEEE80211_KEY_XMIT; if (addr == NULL) { memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); wk.ik_keyix = key_idx; wk.ik_flags |= IEEE80211_KEY_DEFAULT; } else { memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); wk.ik_keyix = IEEE80211_KEYIX_NONE; } wk.ik_keylen = key_len; memcpy(wk.ik_keydata, key, key_len); return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); }
static int bsd_sta_disassoc(void *priv, const u8 *addr, int reason_code) { struct bsd_driver_data *drv = priv; struct ieee80211req_mlme mlme; wpa_printf(MSG_DEBUG, "%s: addr=%s reason_code=%d", __func__, ether_sprintf(addr), reason_code); mlme.im_op = IEEE80211_MLME_DISASSOC; mlme.im_reason = reason_code; memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); }
static int bsd_sta_disassoc(void *priv, u8 *addr, int reason_code) { struct bsd_driver_data *drv = priv; hostapd *hapd = drv->hapd; struct ieee80211req_mlme mlme; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: addr=%s reason_code=%d\n", __func__, ether_sprintf(addr), reason_code); mlme.im_reason = reason_code; memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); return set80211var(priv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); }
static int bsd_set_sta_authorized(void *priv, const u8 *addr, int authorized) { struct bsd_driver_data *drv = priv; struct ieee80211req_mlme mlme; wpa_printf(MSG_DEBUG, "%s: addr=%s authorized=%d", __func__, ether_sprintf(addr), authorized); if (authorized) mlme.im_op = IEEE80211_MLME_AUTHORIZE; else mlme.im_op = IEEE80211_MLME_UNAUTHORIZE; mlme.im_reason = 0; memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); }
static int bsd_del_key(void *priv, const u8 *addr, int key_idx) { struct ieee80211req_del_key wk; os_memset(&wk, 0, sizeof(wk)); if (addr == NULL) { wpa_printf(MSG_DEBUG, "%s: key_idx=%d", __func__, key_idx); wk.idk_keyix = key_idx; } else { wpa_printf(MSG_DEBUG, "%s: addr=" MACSTR, __func__, MAC2STR(addr)); os_memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */ } return set80211var(priv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); }
static int bsd_del_key(void *priv, unsigned char *addr, int key_idx) { struct bsd_driver_data *drv = priv; hostapd *hapd = drv->hapd; struct ieee80211req_del_key wk; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "%s: addr=%s key_idx=%d\n", __func__, ether_sprintf(addr), key_idx); memset(&wk, 0, sizeof(wk)); wk.idk_keyix = key_idx; if (addr != NULL) memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); return set80211var(priv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); }
static int bsd_set_ssid(void *priv, const u8 *ssid, int ssid_len) { struct bsd_driver_data *drv = priv; #ifdef SIOCS80211NWID struct ieee80211_nwid nwid; struct ifreq ifr; os_memcpy(nwid.i_nwid, ssid, ssid_len); nwid.i_len = ssid_len; os_memset(&ifr, 0, sizeof(ifr)); os_strlcpy(ifr.ifr_name, drv->ifname, sizeof(ifr.ifr_name)); ifr.ifr_data = (void *)&nwid; return ioctl(drv->sock, SIOCS80211NWID, &ifr); #else return set80211var(drv, IEEE80211_IOC_SSID, ssid, ssid_len); #endif }
static int bsd_set_sta_authorized(void *priv, u8 *addr, int authorized) { struct bsd_driver_data *drv = priv; hostapd *hapd = drv->hapd; struct ieee80211req_mlme mlme; HOSTAPD_DEBUG(HOSTAPD_DEBUG_VERBOSE, "%s: addr=%s authorized=%d\n", __func__, ether_sprintf(addr), authorized); if (authorized) mlme.im_op = IEEE80211_MLME_AUTHORIZE; else mlme.im_op = IEEE80211_MLME_UNAUTHORIZE; mlme.im_reason = 0; memcpy(mlme.im_macaddr, addr, IEEE80211_ADDR_LEN); return set80211var(priv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); }
static int bsd_del_key(void *priv, const u8 *addr, int key_idx) { struct bsd_driver_data *drv = priv; struct ieee80211req_del_key wk; wpa_printf(MSG_DEBUG, "%s: addr=%s key_idx=%d", __func__, ether_sprintf(addr), key_idx); memset(&wk, 0, sizeof(wk)); if (addr != NULL) { memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); wk.idk_keyix = (u_int8_t) IEEE80211_KEYIX_NONE; /* XXX */ } else { wk.idk_keyix = key_idx; } return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); }
static int bsd_set_radius_acl_auth(void *priv, const u8 *mac, int accepted, u32 session_timeout) { struct bsd_driver_data *drv = priv; struct hostapd_data *hapd = drv->hapd; struct ieee80211req_mlme mlme; switch (accepted) { case HOSTAPD_ACL_ACCEPT_TIMEOUT: wpa_printf(MSG_DEBUG, "[%s] STA " MACSTR " has been accepted by RADIUS ACL with timeout " "of %d.\n", hapd->conf->iface, MAC2STR(mac), session_timeout); mlme.im_reason = IEEE80211_STATUS_SUCCESS; break; case HOSTAPD_ACL_ACCEPT: wpa_printf(MSG_DEBUG, "[%s] STA " MACSTR " has been accepted by RADIUS ACL.\n", hapd->conf->iface, MAC2STR(mac)); mlme.im_reason = IEEE80211_STATUS_SUCCESS; break; case HOSTAPD_ACL_REJECT: wpa_printf(MSG_DEBUG, "[%s] STA " MACSTR " has been rejected by RADIUS ACL.\n", hapd->conf->iface, MAC2STR(mac)); mlme.im_reason = IEEE80211_STATUS_UNSPECIFIED; break; default: wpa_printf(MSG_ERROR, "[%s] STA " MACSTR " has unknown status (%d) by RADIUS ACL. " "Nothing to do...\n", hapd->conf->iface, MAC2STR(mac), accepted); return 0; } memset(&mlme, 0, sizeof(mlme)); mlme.im_op = IEEE80211_MLME_AUTH; memcpy(mlme.im_macaddr, mac, IEEE80211_ADDR_LEN); return set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)); }
static int wpa_driver_bsd_del_key(struct wpa_driver_bsd_data *drv, int key_idx, const unsigned char *addr) { struct ieee80211req_del_key wk; memset(&wk, 0, sizeof(wk)); if (addr != NULL && bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) != 0) { struct ether_addr ea; memcpy(&ea, addr, IEEE80211_ADDR_LEN); wpa_printf(MSG_DEBUG, "%s: addr=%s keyidx=%d", __func__, ether_ntoa(&ea), key_idx); memcpy(wk.idk_macaddr, addr, IEEE80211_ADDR_LEN); wk.idk_keyix = (uint8_t) IEEE80211_KEYIX_NONE; } else { wpa_printf(MSG_DEBUG, "%s: keyidx=%d", __func__, key_idx); wk.idk_keyix = key_idx; } return set80211var(drv, IEEE80211_IOC_DELKEY, &wk, sizeof(wk)); }
static int wpa_driver_bsd_set_key(void *priv, wpa_alg alg, const unsigned char *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len) { struct wpa_driver_bsd_data *drv = priv; struct ieee80211req_key wk; struct ether_addr ea; char *alg_name; u_int8_t cipher; if (alg == WPA_ALG_NONE) return wpa_driver_bsd_del_key(drv, key_idx, addr); switch (alg) { case WPA_ALG_WEP: alg_name = "WEP"; cipher = IEEE80211_CIPHER_WEP; break; case WPA_ALG_TKIP: alg_name = "TKIP"; cipher = IEEE80211_CIPHER_TKIP; break; case WPA_ALG_CCMP: alg_name = "CCMP"; cipher = IEEE80211_CIPHER_AES_CCM; break; default: wpa_printf(MSG_DEBUG, "%s: unknown/unsupported algorithm %d", __func__, alg); return -1; } memcpy(&ea, addr, IEEE80211_ADDR_LEN); wpa_printf(MSG_DEBUG, "%s: alg=%s addr=%s key_idx=%d set_tx=%d seq_len=%zu key_len=%zu", __func__, alg_name, ether_ntoa(&ea), key_idx, set_tx, seq_len, key_len); if (seq_len > sizeof(u_int64_t)) { wpa_printf(MSG_DEBUG, "%s: seq_len %zu too big", __func__, seq_len); return -2; } if (key_len > sizeof(wk.ik_keydata)) { wpa_printf(MSG_DEBUG, "%s: key length %zu too big", __func__, key_len); return -3; } memset(&wk, 0, sizeof(wk)); wk.ik_type = cipher; wk.ik_flags = IEEE80211_KEY_RECV; if (set_tx) wk.ik_flags |= IEEE80211_KEY_XMIT; memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); /* * Deduce whether group/global or unicast key by checking * the address (yech). Note also that we can only mark global * keys default; doing this for a unicast key is an error. */ if (bcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) { wk.ik_flags |= IEEE80211_KEY_GROUP; wk.ik_keyix = key_idx; } else { wk.ik_keyix = (key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx); } if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) wk.ik_flags |= IEEE80211_KEY_DEFAULT; wk.ik_keylen = key_len; memcpy(&wk.ik_keyrsc, seq, seq_len); wk.ik_keyrsc = le64toh(wk.ik_keyrsc); memcpy(wk.ik_keydata, key, key_len); return set80211var(drv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); }
static int bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg, const unsigned char *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len) { struct ieee80211req_key wk; wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d " "seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx, set_tx, seq_len, key_len); if (alg == WPA_ALG_NONE) { #ifndef HOSTAPD if (addr == NULL || is_broadcast_ether_addr(addr)) return bsd_del_key(priv, NULL, key_idx); else #endif /* HOSTAPD */ return bsd_del_key(priv, addr, key_idx); } os_memset(&wk, 0, sizeof(wk)); switch (alg) { case WPA_ALG_WEP: wk.ik_type = IEEE80211_CIPHER_WEP; break; case WPA_ALG_TKIP: wk.ik_type = IEEE80211_CIPHER_TKIP; break; case WPA_ALG_CCMP: wk.ik_type = IEEE80211_CIPHER_AES_CCM; break; default: wpa_printf(MSG_ERROR, "%s: unknown alg=%d", __func__, alg); return -1; } wk.ik_flags = IEEE80211_KEY_RECV; if (set_tx) wk.ik_flags |= IEEE80211_KEY_XMIT; if (addr == NULL) { os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); wk.ik_keyix = key_idx; } else { os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); /* * Deduce whether group/global or unicast key by checking * the address (yech). Note also that we can only mark global * keys default; doing this for a unicast key is an error. */ if (is_broadcast_ether_addr(addr)) { wk.ik_flags |= IEEE80211_KEY_GROUP; wk.ik_keyix = key_idx; } else { wk.ik_keyix = key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx; } } if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) wk.ik_flags |= IEEE80211_KEY_DEFAULT; wk.ik_keylen = key_len; if (seq) { #ifdef WORDS_BIGENDIAN /* * wk.ik_keyrsc is in host byte order (big endian), need to * swap it to match with the byte order used in WPA. */ int i; u8 *keyrsc = (u8 *) &wk.ik_keyrsc; for (i = 0; i < seq_len; i++) keyrsc[WPA_KEY_RSC_LEN - i - 1] = seq[i]; #else /* WORDS_BIGENDIAN */ os_memcpy(&wk.ik_keyrsc, seq, seq_len); #endif /* WORDS_BIGENDIAN */ } os_memcpy(wk.ik_keydata, key, key_len); return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); }
static int bsd_set_key(const char *ifname, void *priv, enum wpa_alg alg, const unsigned char *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len) { struct ieee80211req_key wk; wpa_printf(MSG_DEBUG, "%s: alg=%d addr=%p key_idx=%d set_tx=%d " "seq_len=%zu key_len=%zu", __func__, alg, addr, key_idx, set_tx, seq_len, key_len); if (alg == WPA_ALG_NONE) { return bsd_del_key(priv, addr, key_idx); } os_memset(&wk, 0, sizeof(wk)); switch (alg) { case WPA_ALG_WEP: wk.ik_type = IEEE80211_CIPHER_WEP; break; case WPA_ALG_TKIP: wk.ik_type = IEEE80211_CIPHER_TKIP; break; case WPA_ALG_CCMP: wk.ik_type = IEEE80211_CIPHER_AES_CCM; break; default: wpa_printf(MSG_ERROR, "%s: unknown alg=%d", __func__, alg); return -1; } wk.ik_flags = IEEE80211_KEY_RECV; if (set_tx) wk.ik_flags |= IEEE80211_KEY_XMIT; if (addr == NULL) { os_memset(wk.ik_macaddr, 0xff, IEEE80211_ADDR_LEN); wk.ik_keyix = key_idx; } else { os_memcpy(wk.ik_macaddr, addr, IEEE80211_ADDR_LEN); /* * Deduce whether group/global or unicast key by checking * the address (yech). Note also that we can only mark global * keys default; doing this for a unicast key is an error. */ if (os_memcmp(addr, "\xff\xff\xff\xff\xff\xff", IEEE80211_ADDR_LEN) == 0) { wk.ik_flags |= IEEE80211_KEY_GROUP; wk.ik_keyix = key_idx; } else { wk.ik_keyix = key_idx == 0 ? IEEE80211_KEYIX_NONE : key_idx; } } if (wk.ik_keyix != IEEE80211_KEYIX_NONE && set_tx) wk.ik_flags |= IEEE80211_KEY_DEFAULT; wk.ik_keylen = key_len; os_memcpy(&wk.ik_keyrsc, seq, seq_len); os_memcpy(wk.ik_keydata, key, key_len); return set80211var(priv, IEEE80211_IOC_WPAKEY, &wk, sizeof(wk)); }
static int wpa_driver_bsd_scan(void *priv, struct wpa_driver_scan_params *params) { struct bsd_driver_data *drv = priv; #ifdef IEEE80211_IOC_SCAN_MAX_SSID struct ieee80211_scan_req sr; int i; #endif /* IEEE80211_IOC_SCAN_MAX_SSID */ if (bsd_set_mediaopt(drv, IFM_OMASK, 0 /* STA */) < 0) { wpa_printf(MSG_ERROR, "%s: failed to set operation mode", __func__); return -1; } if (set80211param(drv, IEEE80211_IOC_ROAMING, IEEE80211_ROAMING_MANUAL) < 0) { wpa_printf(MSG_ERROR, "%s: failed to set " "wpa_supplicant-based roaming: %s", __func__, strerror(errno)); return -1; } if (wpa_driver_bsd_set_wpa(drv, 1) < 0) { wpa_printf(MSG_ERROR, "%s: failed to set wpa: %s", __func__, strerror(errno)); return -1; } /* NB: interface must be marked UP to do a scan */ if (bsd_ctrl_iface(drv, 1) < 0) return -1; #ifdef IEEE80211_IOC_SCAN_MAX_SSID os_memset(&sr, 0, sizeof(sr)); sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE | IEEE80211_IOC_SCAN_ONCE | IEEE80211_IOC_SCAN_NOJOIN; sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER; if (params->num_ssids > 0) { sr.sr_nssid = params->num_ssids; #if 0 /* Boundary check is done by upper layer */ if (sr.sr_nssid > IEEE80211_IOC_SCAN_MAX_SSID) sr.sr_nssid = IEEE80211_IOC_SCAN_MAX_SSID; #endif /* NB: check scan cache first */ sr.sr_flags |= IEEE80211_IOC_SCAN_CHECK; } for (i = 0; i < sr.sr_nssid; i++) { sr.sr_ssid[i].len = params->ssids[i].ssid_len; os_memcpy(sr.sr_ssid[i].ssid, params->ssids[i].ssid, sr.sr_ssid[i].len); } /* NB: net80211 delivers a scan complete event so no need to poll */ return set80211var(drv, IEEE80211_IOC_SCAN_REQ, &sr, sizeof(sr)); #else /* IEEE80211_IOC_SCAN_MAX_SSID */ /* set desired ssid before scan */ if (bsd_set_ssid(drv, params->ssids[0].ssid, params->ssids[0].ssid_len) < 0) return -1; /* NB: net80211 delivers a scan complete event so no need to poll */ return set80211param(drv, IEEE80211_IOC_SCAN_REQ, 0); #endif /* IEEE80211_IOC_SCAN_MAX_SSID */ }
static int wpa_driver_bsd_associate(void *priv, struct wpa_driver_associate_params *params) { struct bsd_driver_data *drv = priv; struct ieee80211req_mlme mlme; u32 mode; int privacy; int ret = 0; wpa_printf(MSG_DEBUG, "%s: ssid '%.*s' wpa ie len %u pairwise %u group %u key mgmt %u" , __func__ , (unsigned int) params->ssid_len, params->ssid , (unsigned int) params->wpa_ie_len , params->pairwise_suite , params->group_suite , params->key_mgmt_suite ); switch (params->mode) { case IEEE80211_MODE_INFRA: mode = 0 /* STA */; break; case IEEE80211_MODE_IBSS: mode = IFM_IEEE80211_IBSS; break; case IEEE80211_MODE_AP: mode = IFM_IEEE80211_HOSTAP; break; default: wpa_printf(MSG_ERROR, "%s: unknown operation mode", __func__); return -1; } if (bsd_set_mediaopt(drv, IFM_OMASK, mode) < 0) { wpa_printf(MSG_ERROR, "%s: failed to set operation mode", __func__); return -1; } if (params->mode == IEEE80211_MODE_AP) { drv->sock_xmit = l2_packet_init(drv->ifname, NULL, ETH_P_EAPOL, handle_read, drv, 0); if (drv->sock_xmit == NULL) return -1; drv->is_ap = 1; return 0; } if (wpa_driver_bsd_set_drop_unencrypted(drv, params->drop_unencrypted) < 0) ret = -1; if (wpa_driver_bsd_set_auth_alg(drv, params->auth_alg) < 0) ret = -1; /* XXX error handling is wrong but unclear what to do... */ if (wpa_driver_bsd_set_wpa_ie(drv, params->wpa_ie, params->wpa_ie_len) < 0) return -1; privacy = !(params->pairwise_suite == CIPHER_NONE && params->group_suite == CIPHER_NONE && params->key_mgmt_suite == KEY_MGMT_NONE && params->wpa_ie_len == 0); wpa_printf(MSG_DEBUG, "%s: set PRIVACY %u", __func__, privacy); if (set80211param(drv, IEEE80211_IOC_PRIVACY, privacy) < 0) return -1; if (params->wpa_ie_len && set80211param(drv, IEEE80211_IOC_WPA, params->wpa_ie[0] == WLAN_EID_RSN ? 2 : 1) < 0) return -1; os_memset(&mlme, 0, sizeof(mlme)); mlme.im_op = IEEE80211_MLME_ASSOC; if (params->ssid != NULL) os_memcpy(mlme.im_ssid, params->ssid, params->ssid_len); mlme.im_ssid_len = params->ssid_len; if (params->bssid != NULL) os_memcpy(mlme.im_macaddr, params->bssid, IEEE80211_ADDR_LEN); if (set80211var(drv, IEEE80211_IOC_MLME, &mlme, sizeof(mlme)) < 0) return -1; return ret; }
static int wpa_driver_bsd_set_wpa_ie(struct wpa_driver_bsd_data *drv, const char *wpa_ie, size_t wpa_ie_len) { return set80211var(drv, IEEE80211_IOC_OPTIE, wpa_ie, wpa_ie_len); }