static int wpa_driver_hostap_scan(void *priv, const u8 *ssid, size_t ssid_len) { struct wpa_driver_hostap_data *drv = priv; struct prism2_hostapd_param param; int ret; if (ssid == NULL) { /* Use standard Linux Wireless Extensions ioctl if possible * because some drivers using hostap code in wpa_supplicant * might not support Host AP specific scan request (with SSID * info). */ return wpa_driver_wext_scan(drv->wext, ssid, ssid_len); } if (ssid_len > 32) ssid_len = 32; memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_SCAN_REQ; param.u.scan_req.ssid_len = ssid_len; memcpy(param.u.scan_req.ssid, ssid, ssid_len); ret = hostapd_ioctl(drv, ¶m, sizeof(param), 1); /* Not all drivers generate "scan completed" wireless event, so try to * read results after a timeout. */ eloop_register_timeout(3, 0, wpa_driver_wext_scan_timeout, drv->wext, drv->ctx); return ret; }
static int hostap_get_seqnum(const char *ifname, void *priv, const u8 *addr, int idx, u8 *seq) { struct hostap_driver_data *drv = priv; struct prism2_hostapd_param *param; u8 *buf; size_t blen; int ret = 0; blen = sizeof(*param) + 32; buf = os_zalloc(blen); if (buf == NULL) return -1; param = (struct prism2_hostapd_param *) buf; param->cmd = PRISM2_GET_ENCRYPTION; if (addr == NULL) os_memset(param->sta_addr, 0xff, ETH_ALEN); else os_memcpy(param->sta_addr, addr, ETH_ALEN); param->u.crypt.idx = idx; if (hostapd_ioctl(drv, param, blen)) { printf("Failed to get encryption.\n"); ret = -1; } else { os_memcpy(seq, param->u.crypt.seq, 8); } os_free(buf); return ret; }
static int hostap_sta_add(void *priv, struct hostapd_sta_add_params *params) { struct hostap_driver_data *drv = priv; struct prism2_hostapd_param param; int tx_supp_rates = 0; size_t i; #define WLAN_RATE_1M BIT(0) #define WLAN_RATE_2M BIT(1) #define WLAN_RATE_5M5 BIT(2) #define WLAN_RATE_11M BIT(3) for (i = 0; i < params->supp_rates_len; i++) { if ((params->supp_rates[i] & 0x7f) == 2) tx_supp_rates |= WLAN_RATE_1M; if ((params->supp_rates[i] & 0x7f) == 4) tx_supp_rates |= WLAN_RATE_2M; if ((params->supp_rates[i] & 0x7f) == 11) tx_supp_rates |= WLAN_RATE_5M5; if ((params->supp_rates[i] & 0x7f) == 22) tx_supp_rates |= WLAN_RATE_11M; } memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_ADD_STA; memcpy(param.sta_addr, params->addr, ETH_ALEN); param.u.add_sta.aid = params->aid; param.u.add_sta.capability = params->capability; param.u.add_sta.tx_supp_rates = tx_supp_rates; return hostapd_ioctl(drv, ¶m, sizeof(param)); }
int hostapd_set_encryption(hostapd *hapd, const char *alg, u8 *addr, int idx, u8 *key, size_t key_len) { struct prism2_hostapd_param *param; u8 *buf; size_t blen; int ret = 0; blen = sizeof(*param) + key_len; buf = malloc(blen); if (buf == NULL) return -1; memset(buf, 0, blen); param = (struct prism2_hostapd_param *) buf; param->cmd = PRISM2_SET_ENCRYPTION; if (addr == NULL) memset(param->sta_addr, 0xff, ETH_ALEN); else memcpy(param->sta_addr, addr, ETH_ALEN); strncpy(param->u.crypt.alg, alg, HOSTAP_CRYPT_ALG_NAME_LEN); param->u.crypt.flags = HOSTAP_CRYPT_FLAG_SET_TX_KEY; param->u.crypt.idx = idx; param->u.crypt.key_len = key_len; memcpy((u8 *) (param + 1), key, key_len); if (hostapd_ioctl(hapd, param, blen)) { printf("Failed to set encryption.\n"); ret = -1; } free(buf); return ret; }
static int hostap_sta_add(const char *ifname, void *priv, const u8 *addr, u16 aid, u16 capability, u8 *supp_rates, size_t supp_rates_len, int flags, u16 listen_interval) { struct hostap_driver_data *drv = priv; struct prism2_hostapd_param param; int tx_supp_rates = 0; size_t i; #define WLAN_RATE_1M BIT(0) #define WLAN_RATE_2M BIT(1) #define WLAN_RATE_5M5 BIT(2) #define WLAN_RATE_11M BIT(3) for (i = 0; i < supp_rates_len; i++) { if ((supp_rates[i] & 0x7f) == 2) tx_supp_rates |= WLAN_RATE_1M; if ((supp_rates[i] & 0x7f) == 4) tx_supp_rates |= WLAN_RATE_2M; if ((supp_rates[i] & 0x7f) == 11) tx_supp_rates |= WLAN_RATE_5M5; if ((supp_rates[i] & 0x7f) == 22) tx_supp_rates |= WLAN_RATE_11M; } memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_ADD_STA; memcpy(param.sta_addr, addr, ETH_ALEN); param.u.add_sta.aid = aid; param.u.add_sta.capability = capability; param.u.add_sta.tx_supp_rates = tx_supp_rates; return hostapd_ioctl(drv, ¶m, sizeof(param)); }
static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv) { struct prism2_hostapd_param *param; int res; size_t blen, elem_len; elem_len = drv->generic_ie_len + drv->wps_ie_len; blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + elem_len; if (blen < sizeof(*param)) blen = sizeof(*param); param = os_zalloc(blen); if (param == NULL) return -1; param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT; param->u.generic_elem.len = elem_len; if (drv->generic_ie) { os_memcpy(param->u.generic_elem.data, drv->generic_ie, drv->generic_ie_len); } if (drv->wps_ie) { os_memcpy(¶m->u.generic_elem.data[drv->generic_ie_len], drv->wps_ie, drv->wps_ie_len); } wpa_hexdump(MSG_DEBUG, "hostap: Set generic IE", param->u.generic_elem.data, elem_len); res = hostapd_ioctl(drv, param, blen); os_free(param); return res; }
int hostapd_flush(hostapd *hapd) { struct prism2_hostapd_param param; memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_FLUSH; return hostapd_ioctl(hapd, ¶m, sizeof(param)); }
static int hostap_flush(void *priv) { struct hostap_driver_data *drv = priv; struct prism2_hostapd_param param; memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_FLUSH; return hostapd_ioctl(drv, ¶m, sizeof(param)); }
static int wpa_driver_hostap_set_key(const char *ifname, void *priv, enum wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len) { struct hostap_driver_data *drv = priv; struct prism2_hostapd_param *param; u8 *buf; size_t blen; int ret = 0; blen = sizeof(*param) + key_len; buf = os_zalloc(blen); if (buf == NULL) return -1; param = (struct prism2_hostapd_param *) buf; param->cmd = PRISM2_SET_ENCRYPTION; if (addr == NULL) memset(param->sta_addr, 0xff, ETH_ALEN); else memcpy(param->sta_addr, addr, ETH_ALEN); switch (alg) { case WPA_ALG_NONE: os_strlcpy((char *) param->u.crypt.alg, "NONE", HOSTAP_CRYPT_ALG_NAME_LEN); break; case WPA_ALG_WEP: os_strlcpy((char *) param->u.crypt.alg, "WEP", HOSTAP_CRYPT_ALG_NAME_LEN); break; case WPA_ALG_TKIP: os_strlcpy((char *) param->u.crypt.alg, "TKIP", HOSTAP_CRYPT_ALG_NAME_LEN); break; case WPA_ALG_CCMP: os_strlcpy((char *) param->u.crypt.alg, "CCMP", HOSTAP_CRYPT_ALG_NAME_LEN); break; default: os_free(buf); return -1; } param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; param->u.crypt.idx = key_idx; param->u.crypt.key_len = key_len; memcpy((u8 *) (param + 1), key, key_len); if (hostapd_ioctl(drv, param, blen)) { printf("Failed to set encryption.\n"); ret = -1; } free(buf); return ret; }
int wpa_driver_hostap_set_key(const char *ifname, wpa_alg alg, unsigned char *addr, int key_idx, int set_tx, u8 *seq, size_t seq_len, u8 *key, size_t key_len) { struct prism2_hostapd_param *param; u8 *buf; size_t blen; int ret = 0; char *alg_name; switch (alg) { case WPA_ALG_NONE: alg_name = "none"; break; case WPA_ALG_WEP: alg_name = "WEP"; break; case WPA_ALG_TKIP: alg_name = "TKIP"; break; case WPA_ALG_CCMP: alg_name = "CCMP"; break; default: return -1; } if (seq_len > 8) return -2; blen = sizeof(*param) + key_len; buf = malloc(blen); if (buf == NULL) return -1; memset(buf, 0, blen); param = (struct prism2_hostapd_param *) buf; param->cmd = PRISM2_SET_ENCRYPTION; memset(param->sta_addr, 0xff, ETH_ALEN); strncpy(param->u.crypt.alg, alg_name, HOSTAP_CRYPT_ALG_NAME_LEN); param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; param->u.crypt.idx = key_idx; memcpy(param->u.crypt.seq, seq, seq_len); param->u.crypt.key_len = key_len; memcpy((u8 *) (param + 1), key, key_len); if (hostapd_ioctl(ifname, param, blen, 1)) { ret = -1; } free(buf); return ret; }
static void handle_assoc_resp(hostapd *hapd, struct ieee80211_mgmt *mgmt, size_t len) { u16 status_code, aid; struct prism2_hostapd_param param; if (hapd->assoc_ap_state != ASSOCIATE) { printf("Unexpected association response received from " MACSTR "\n", MAC2STR(mgmt->sa)); return; } if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_resp)) { printf("handle_assoc_resp - too short payload (len=%d)\n", len); return; } if (memcmp(mgmt->sa, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0 || memcmp(mgmt->bssid, hapd->conf->assoc_ap_addr, ETH_ALEN) != 0) { printf("Received association response from unexpected address " "(SA=" MACSTR " BSSID=" MACSTR "\n", MAC2STR(mgmt->sa), MAC2STR(mgmt->bssid)); return; } status_code = le_to_host16(mgmt->u.assoc_resp.status_code); aid = le_to_host16(mgmt->u.assoc_resp.aid); aid &= ~(BIT(14) | BIT(15)); if (status_code != 0) { printf("Association (as station) with AP " MACSTR " failed " "(status_code=%d)\n", MAC2STR(hapd->conf->assoc_ap_addr), status_code); /* Try to authenticate again */ hapd->assoc_ap_state = AUTHENTICATE; eloop_register_timeout(5, 0, ieee802_11_sta_authenticate, hapd, NULL); } printf("Associated (as station) with AP " MACSTR " (aid=%d)\n", MAC2STR(hapd->conf->assoc_ap_addr), aid); hapd->assoc_ap_aid = aid; hapd->assoc_ap_state = ASSOCIATED; memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR; memcpy(param.sta_addr, hapd->conf->assoc_ap_addr, ETH_ALEN); if (hostapd_ioctl(hapd, ¶m, sizeof(param))) { printf("Could not set associated AP address to kernel " "driver.\n"); } }
void remove_sta(hostapd *hapd, struct sta_info *sta) { struct prism2_hostapd_param param; ieee802_1x_set_port_enabled(hapd, sta, 0); memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_REMOVE_STA; memcpy(param.sta_addr, sta->addr, ETH_ALEN); if (hostapd_ioctl(hapd, ¶m, sizeof(param))) { printf("Could not remove station from kernel driver.\n"); } }
static int hostap_set_assoc_ap(void *priv, const u8 *addr) { struct hostap_driver_data *drv = priv; struct prism2_hostapd_param param; memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR; memcpy(param.sta_addr, addr, ETH_ALEN); if (hostapd_ioctl(drv, ¶m, sizeof(param))) return -1; return 0; }
static int hostap_sta_set_flags(void *priv, const u8 *addr, int total_flags, int flags_or, int flags_and) { struct hostap_driver_data *drv = priv; struct prism2_hostapd_param param; memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA; memcpy(param.sta_addr, addr, ETH_ALEN); param.u.set_flags_sta.flags_or = flags_or; param.u.set_flags_sta.flags_and = flags_and; return hostapd_ioctl(drv, ¶m, sizeof(param)); }
static int hostap_get_inact_sec(void *priv, const u8 *addr) { struct hostap_driver_data *drv = priv; struct prism2_hostapd_param param; memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_GET_INFO_STA; memcpy(param.sta_addr, addr, ETH_ALEN); if (hostapd_ioctl(drv, ¶m, sizeof(param))) { return -1; } return param.u.get_info_sta.inactive_sec; }
static int hostap_sta_clear_stats(void *priv, const u8 *addr) { struct hostap_driver_data *drv = priv; struct prism2_hostapd_param param; memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_STA_CLEAR_STATS; memcpy(param.sta_addr, addr, ETH_ALEN); if (hostapd_ioctl(drv, ¶m, sizeof(param))) { return -1; } return 0; }
static int hostap_sta_remove(void *priv, const u8 *addr) { struct hostap_driver_data *drv = priv; struct prism2_hostapd_param param; hostap_sta_set_flags(drv, addr, 0, 0, ~WPA_STA_AUTHORIZED); memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_REMOVE_STA; memcpy(param.sta_addr, addr, ETH_ALEN); if (hostapd_ioctl(drv, ¶m, sizeof(param))) { printf("Could not remove station from kernel driver.\n"); return -1; } return 0; }
static int hostap_sta_set_flags(void *priv, const u8 *addr, int total_flags, int flags_or, int flags_and) { struct hostap_driver_data *drv = priv; struct prism2_hostapd_param param; if (flags_or & WPA_STA_AUTHORIZED) flags_or = BIT(5); /* WLAN_STA_AUTHORIZED */ if (!(flags_and & WPA_STA_AUTHORIZED)) flags_and = ~BIT(5); else flags_and = ~0; memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA; memcpy(param.sta_addr, addr, ETH_ALEN); param.u.set_flags_sta.flags_or = flags_or; param.u.set_flags_sta.flags_and = flags_and; return hostapd_ioctl(drv, ¶m, sizeof(param)); }
static int wpa_driver_hostap_set_wpa_ie(struct wpa_driver_hostap_data *drv, const u8 *wpa_ie, size_t wpa_ie_len) { struct prism2_hostapd_param *param; int res; size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len; if (blen < sizeof(*param)) blen = sizeof(*param); param = os_zalloc(blen); if (param == NULL) return -1; param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT; param->u.generic_elem.len = wpa_ie_len; os_memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len); res = hostapd_ioctl(drv, param, blen, 1); os_free(param); return res; }
static int wpa_driver_hostap_mlme(struct wpa_driver_hostap_data *drv, const u8 *addr, int cmd, int reason_code) { struct prism2_hostapd_param param; int ret; /* There does not seem to be a better way of deauthenticating or * disassociating with Prism2/2.5/3 than sending the management frame * and then resetting the Port0 to make sure both the AP and the STA * end up in disconnected state. */ memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_MLME; memcpy(param.sta_addr, addr, ETH_ALEN); param.u.mlme.cmd = cmd; param.u.mlme.reason_code = reason_code; ret = hostapd_ioctl(drv, ¶m, sizeof(param), 1); if (ret == 0) { usleep(100000); ret = wpa_driver_hostap_reset(drv, 2); } return ret; }
static int wpa_driver_hostap_set_wpa_ie(const char *ifname, const char *wpa_ie, size_t wpa_ie_len) { struct prism2_hostapd_param *param; int res; size_t blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + wpa_ie_len; if (blen < sizeof(*param)) blen = sizeof(*param); param = (struct prism2_hostapd_param *) malloc(blen); if (param == NULL) return -1; memset(param, 0, blen); param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT; param->u.generic_elem.len = wpa_ie_len; memcpy(param->u.generic_elem.data, wpa_ie, wpa_ie_len); res = hostapd_ioctl(ifname, param, blen, 1); free(param); return res; }
static int hostap_set_encryption(const char *ifname, void *priv, const char *alg, const u8 *addr, int idx, const u8 *key, size_t key_len, int txkey) { struct hostap_driver_data *drv = priv; struct prism2_hostapd_param *param; u8 *buf; size_t blen; int ret = 0; blen = sizeof(*param) + key_len; buf = os_zalloc(blen); if (buf == NULL) return -1; param = (struct prism2_hostapd_param *) buf; param->cmd = PRISM2_SET_ENCRYPTION; if (addr == NULL) memset(param->sta_addr, 0xff, ETH_ALEN); else memcpy(param->sta_addr, addr, ETH_ALEN); os_strlcpy((char *) param->u.crypt.alg, alg, HOSTAP_CRYPT_ALG_NAME_LEN); param->u.crypt.flags = txkey ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; param->u.crypt.idx = idx; param->u.crypt.key_len = key_len; memcpy((u8 *) (param + 1), key, key_len); if (hostapd_ioctl(drv, param, blen)) { printf("Failed to set encryption.\n"); ret = -1; } free(buf); return ret; }
static void handle_assoc_cb(hostapd *hapd, struct ieee80211_mgmt *mgmt, size_t len, int reassoc, int ok) { u16 status; struct prism2_hostapd_param param; struct sta_info *sta; int new_assoc = 1; if (!ok) { hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "did not acknowledge association response"); return; } if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) : sizeof(mgmt->u.assoc_req))) { printf("handle_assoc_cb(reassoc=%d) - too short payload " "(len=%d)\n", reassoc, len); return; } if (reassoc) status = le_to_host16(mgmt->u.reassoc_resp.status_code); else status = le_to_host16(mgmt->u.assoc_resp.status_code); sta = ap_get_sta(hapd, mgmt->da); if (!sta) { printf("handle_assoc_cb: STA " MACSTR " not found\n", MAC2STR(mgmt->da)); return; } if (status != WLAN_STATUS_SUCCESS) goto fail; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "associated (aid %d)", sta->aid); if (sta->flags & WLAN_STA_ASSOC) new_assoc = 0; sta->flags |= WLAN_STA_ASSOC; memset(¶m, 0, sizeof(param)); param.cmd = PRISM2_HOSTAPD_ADD_STA; memcpy(param.sta_addr, sta->addr, ETH_ALEN); param.u.add_sta.aid = sta->aid; param.u.add_sta.capability = sta->capability; param.u.add_sta.tx_supp_rates = sta->tx_supp_rates; if (hostapd_ioctl(hapd, ¶m, sizeof(param))) { printf("Could not add station to kernel driver.\n"); } if (new_assoc) hostapd_new_assoc_sta(hapd, sta); if (sta->eapol_sm) sta->eapol_sm->portEnabled = TRUE; fail: /* Copy of the association request is not needed anymore */ if (sta->last_assoc_req) { free(sta->last_assoc_req); sta->last_assoc_req = NULL; } }
static int wpa_driver_hostap_set_key(void *priv, wpa_alg alg, const u8 *addr, int key_idx, int set_tx, const u8 *seq, size_t seq_len, const u8 *key, size_t key_len) { struct wpa_driver_hostap_data *drv = priv; struct prism2_hostapd_param *param; u8 *buf; size_t blen; int ret = 0; char *alg_name; switch (alg) { case WPA_ALG_NONE: alg_name = "none"; break; case WPA_ALG_WEP: alg_name = "WEP"; break; case WPA_ALG_TKIP: alg_name = "TKIP"; break; case WPA_ALG_CCMP: alg_name = "CCMP"; break; default: return -1; } wpa_printf(MSG_DEBUG, "%s: alg=%s key_idx=%d set_tx=%d seq_len=%lu " "key_len=%lu", __FUNCTION__, alg_name, key_idx, set_tx, (unsigned long) seq_len, (unsigned long) key_len); if (seq_len > 8) return -2; blen = sizeof(*param) + key_len; buf = malloc(blen); if (buf == NULL) return -1; memset(buf, 0, blen); param = (struct prism2_hostapd_param *) buf; param->cmd = PRISM2_SET_ENCRYPTION; /* TODO: In theory, STA in client mode can use five keys; four default * keys for receiving (with keyidx 0..3) and one individual key for * both transmitting and receiving (keyidx 0) _unicast_ packets. Now, * keyidx 0 is reserved for this unicast use and default keys can only * use keyidx 1..3 (i.e., default key with keyidx 0 is not supported). * This should be fine for more or less all cases, but for completeness * sake, the driver could be enhanced to support the missing key. */ #if 0 if (addr == NULL) memset(param->sta_addr, 0xff, ETH_ALEN); else memcpy(param->sta_addr, addr, ETH_ALEN); #else memset(param->sta_addr, 0xff, ETH_ALEN); #endif strncpy((char *) param->u.crypt.alg, alg_name, HOSTAP_CRYPT_ALG_NAME_LEN); param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; param->u.crypt.idx = key_idx; memcpy(param->u.crypt.seq, seq, seq_len); param->u.crypt.key_len = key_len; memcpy((u8 *) (param + 1), key, key_len); if (hostapd_ioctl(drv, param, blen, 1)) { wpa_printf(MSG_WARNING, "Failed to set encryption."); show_set_key_error(param); ret = -1; } free(buf); return ret; }