void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, int authorized) { const u8 *dev_addr = NULL; char buf[100]; #ifdef CONFIG_P2P u8 addr[ETH_ALEN]; u8 ip_addr_buf[4]; #endif /* CONFIG_P2P */ if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED)) return; if (authorized) sta->flags |= WLAN_STA_AUTHORIZED; else sta->flags &= ~WLAN_STA_AUTHORIZED; #ifdef CONFIG_P2P if (hapd->p2p_group == NULL) { if (sta->p2p_ie != NULL && p2p_parse_dev_addr_in_p2p_ie(sta->p2p_ie, addr) == 0) dev_addr = addr; } else dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr); #endif /* CONFIG_P2P */ if (dev_addr) os_snprintf(buf, sizeof(buf), MACSTR " p2p_dev_addr=" MACSTR, MAC2STR(sta->addr), MAC2STR(dev_addr)); else os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr)); if (hapd->sta_authorized_cb) hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx, sta->addr, authorized, dev_addr); if (authorized) { char ip_addr[100]; ip_addr[0] = '\0'; #ifdef CONFIG_P2P if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) { os_snprintf(ip_addr, sizeof(ip_addr), " ip_addr=%u.%u.%u.%u", ip_addr_buf[0], ip_addr_buf[1], ip_addr_buf[2], ip_addr_buf[3]); } #endif /* CONFIG_P2P */ wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s", buf, ip_addr); if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx) wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, AP_STA_CONNECTED "%s%s", buf, ip_addr); } else { wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx) wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); } }
/** * pmksa_candidate_add - Add a new PMKSA candidate * @sm: Pointer to WPA state machine data from wpa_sm_init() * @bssid: BSSID (authenticator address) of the candidate * @prio: Priority (the smaller number, the higher priority) * @preauth: Whether the candidate AP advertises support for pre-authentication * * This function is used to add PMKSA candidates for RSN pre-authentication. It * is called from scan result processing and from driver events for PMKSA * candidates, i.e., EVENT_PMKID_CANDIDATE events to wpa_supplicant_event(). */ void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, int prio, int preauth) { struct rsn_pmksa_candidate *cand, *prev, *pos; if (sm->cur_ssid && sm->cur_ssid->proactive_key_caching) pmksa_cache_get_opportunistic(sm, sm->cur_ssid, bssid); if (!preauth) { wpa_printf(MSG_DEBUG, "RSN: Ignored PMKID candidate without " "preauth flag"); return; } /* If BSSID already on candidate list, update the priority of the old * entry. Do not override priority based on normal scan results. */ prev = NULL; cand = sm->pmksa_candidates; while (cand) { if (memcmp(cand->bssid, bssid, ETH_ALEN) == 0) { if (prev) prev->next = cand->next; else sm->pmksa_candidates = cand->next; break; } prev = cand; cand = cand->next; } if (cand) { if (prio < PMKID_CANDIDATE_PRIO_SCAN) cand->priority = prio; } else { cand = malloc(sizeof(*cand)); if (cand == NULL) return; memset(cand, 0, sizeof(*cand)); memcpy(cand->bssid, bssid, ETH_ALEN); cand->priority = prio; } /* Add candidate to the list; order by increasing priority value. i.e., * highest priority (smallest value) first. */ prev = NULL; pos = sm->pmksa_candidates; while (pos) { if (cand->priority <= pos->priority) break; prev = pos; pos = pos->next; } cand->next = pos; if (prev) prev->next = cand; else sm->pmksa_candidates = cand; wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: added PMKSA cache " "candidate " MACSTR " prio %d", MAC2STR(bssid), prio); rsn_preauth_candidate_process(sm); }
/** * ap_handle_timer - Per STA timer handler * @eloop_ctx: struct hostapd_data * * @timeout_ctx: struct sta_info * * * This function is called to check station activity and to remove inactive * stations. */ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) { struct hostapd_data *hapd = eloop_ctx; struct sta_info *sta = timeout_ctx; unsigned long next_time = 0; int reason; wpa_printf(MSG_DEBUG, "%s: " MACSTR " flags=0x%x timeout_next=%d", __func__, MAC2STR(sta->addr), sta->flags, sta->timeout_next); if (sta->timeout_next == STA_REMOVE) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deauthenticated due to " "local deauth request"); ap_free_sta(hapd, sta); return; } if ((sta->flags & WLAN_STA_ASSOC) && (sta->timeout_next == STA_NULLFUNC || sta->timeout_next == STA_DISASSOC)) { int inactive_sec; /* * Add random value to timeout so that we don't end up bouncing * all stations at the same time if we have lots of associated * stations that are idle (but keep re-associating). */ int fuzz = os_random() % 20; inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr); if (inactive_sec == -1) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Check inactivity: Could not " "get station info from kernel driver for " MACSTR, MAC2STR(sta->addr)); /* * The driver may not support this functionality. * Anyway, try again after the next inactivity timeout, * but do not disconnect the station now. */ next_time = hapd->conf->ap_max_inactivity + fuzz; } else if (inactive_sec < hapd->conf->ap_max_inactivity && sta->flags & WLAN_STA_ASSOC) { /* station activity detected; reset timeout state */ wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " has been active %is ago", MAC2STR(sta->addr), inactive_sec); sta->timeout_next = STA_NULLFUNC; next_time = hapd->conf->ap_max_inactivity + fuzz - inactive_sec; } else { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " has been " "inactive too long: %d sec, max allowed: %d", MAC2STR(sta->addr), inactive_sec, hapd->conf->ap_max_inactivity); if (hapd->conf->skip_inactivity_poll) sta->timeout_next = STA_DISASSOC; } } if ((sta->flags & WLAN_STA_ASSOC) && sta->timeout_next == STA_DISASSOC && !(sta->flags & WLAN_STA_PENDING_POLL) && !hapd->conf->skip_inactivity_poll) { wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " has ACKed data poll", MAC2STR(sta->addr)); /* data nullfunc frame poll did not produce TX errors; assume * station ACKed it */ sta->timeout_next = STA_NULLFUNC; next_time = hapd->conf->ap_max_inactivity; } if (next_time) { wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " "for " MACSTR " (%lu seconds)", __func__, MAC2STR(sta->addr), next_time); eloop_register_timeout(next_time, 0, ap_handle_timer, hapd, sta); return; } if (sta->timeout_next == STA_NULLFUNC && (sta->flags & WLAN_STA_ASSOC)) { wpa_printf(MSG_DEBUG, " Polling STA"); sta->flags |= WLAN_STA_PENDING_POLL; hostapd_drv_poll_client(hapd, hapd->own_addr, sta->addr, sta->flags & WLAN_STA_WMM); } else if (sta->timeout_next != STA_REMOVE) { int deauth = sta->timeout_next == STA_DEAUTH; wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Timeout, sending %s info to STA " MACSTR, deauth ? "deauthentication" : "disassociation", MAC2STR(sta->addr)); if (deauth) { hostapd_drv_sta_deauth( hapd, sta->addr, WLAN_REASON_PREV_AUTH_NOT_VALID); } else { reason = (sta->timeout_next == STA_DISASSOC) ? WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY : WLAN_REASON_PREV_AUTH_NOT_VALID; hostapd_drv_sta_disassoc(hapd, sta->addr, reason); } } switch (sta->timeout_next) { case STA_NULLFUNC: sta->timeout_next = STA_DISASSOC; wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " "for " MACSTR " (%d seconds - AP_DISASSOC_DELAY)", __func__, MAC2STR(sta->addr), AP_DISASSOC_DELAY); eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer, hapd, sta); break; case STA_DISASSOC: case STA_DISASSOC_FROM_CLI: ap_sta_set_authorized(hapd, sta, 0); sta->flags &= ~WLAN_STA_ASSOC; ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); if (!sta->acct_terminate_cause) sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; accounting_sta_stop(hapd, sta); ieee802_1x_free_station(sta); hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "disassociated due to " "inactivity"); reason = (sta->timeout_next == STA_DISASSOC) ? WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY : WLAN_REASON_PREV_AUTH_NOT_VALID; sta->timeout_next = STA_DEAUTH; wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " "for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)", __func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY); eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, hapd, sta); mlme_disassociate_indication(hapd, sta, reason); break; case STA_DEAUTH: case STA_REMOVE: hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "deauthenticated due to " "inactivity (timer DEAUTH/REMOVE)"); if (!sta->acct_terminate_cause) sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; mlme_deauthenticate_indication( hapd, sta, WLAN_REASON_PREV_AUTH_NOT_VALID); ap_free_sta(hapd, sta); break; } }
/** * rsn_preauth_init - Start new RSN pre-authentication * @sm: Pointer to WPA state machine data from wpa_sm_init() * @dst: Authenticator address (BSSID) with which to preauthenticate * @config: Current network configuration * Returns: 0 on success, -1 on another pre-authentication is in progress, * -2 on layer 2 packet initialization failure, -3 on EAPOL state machine * initialization failure, -4 on memory allocation failure * * This function request an RSN pre-authentication with a given destination * address. This is usually called for PMKSA candidates found from scan results * or from driver reports. In addition, ctrl_iface PREAUTH command can trigger * pre-authentication. */ int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, struct wpa_ssid *config) { struct eapol_config eapol_conf; struct eapol_ctx *ctx; if (sm->preauth_eapol) return -1; wpa_msg(sm->ctx->ctx, MSG_DEBUG, "RSN: starting pre-authentication " "with " MACSTR, MAC2STR(dst)); sm->l2_preauth = l2_packet_init(sm->ifname, sm->own_addr, ETH_P_RSN_PREAUTH, rsn_preauth_receive, sm, 0); if (sm->l2_preauth == NULL) { wpa_printf(MSG_WARNING, "RSN: Failed to initialize L2 packet " "processing for pre-authentication"); return -2; } ctx = malloc(sizeof(*ctx)); if (ctx == NULL) { wpa_printf(MSG_WARNING, "Failed to allocate EAPOL context."); return -4; } memset(ctx, 0, sizeof(*ctx)); ctx->ctx = sm->ctx->ctx; ctx->msg_ctx = sm->ctx->ctx; ctx->preauth = 1; ctx->cb = rsn_preauth_eapol_cb; ctx->cb_ctx = sm; ctx->scard_ctx = sm->scard_ctx; ctx->eapol_send = rsn_preauth_eapol_send; ctx->eapol_send_ctx = sm; ctx->set_config_blob = sm->ctx->set_config_blob; ctx->get_config_blob = sm->ctx->get_config_blob; sm->preauth_eapol = eapol_sm_init(ctx); if (sm->preauth_eapol == NULL) { free(ctx); wpa_printf(MSG_WARNING, "RSN: Failed to initialize EAPOL " "state machines for pre-authentication"); return -3; } memset(&eapol_conf, 0, sizeof(eapol_conf)); eapol_conf.accept_802_1x_keys = 0; eapol_conf.required_keys = 0; eapol_conf.fast_reauth = sm->fast_reauth; if (config) eapol_conf.workaround = config->eap_workaround; eapol_sm_notify_config(sm->preauth_eapol, config, &eapol_conf); /* * Use a shorter startPeriod with preauthentication since the first * preauth EAPOL-Start frame may end up being dropped due to race * condition in the AP between the data receive and key configuration * after the 4-Way Handshake. */ eapol_sm_configure(sm->preauth_eapol, -1, -1, 5, 6); memcpy(sm->preauth_bssid, dst, ETH_ALEN); eapol_sm_notify_portValid(sm->preauth_eapol, TRUE); /* 802.1X::portControl = Auto */ eapol_sm_notify_portEnabled(sm->preauth_eapol, TRUE); eloop_register_timeout(sm->dot11RSNAConfigSATimeout, 0, rsn_preauth_timeout, sm, NULL); return 0; }
void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, const u8 *bssid, u16 auth_type) { struct wpa_driver_associate_params params; struct ieee802_11_elems elems; #ifdef CONFIG_HT_OVERRIDES struct ieee80211_ht_capabilities htcaps; struct ieee80211_ht_capabilities htcaps_mask; #endif /* CONFIG_HT_OVERRIDES */ #ifdef CONFIG_VHT_OVERRIDES struct ieee80211_vht_capabilities vhtcaps; struct ieee80211_vht_capabilities vhtcaps_mask; #endif /* CONFIG_VHT_OVERRIDES */ os_memset(¶ms, 0, sizeof(params)); params.bssid = bssid; params.ssid = wpa_s->sme.ssid; params.ssid_len = wpa_s->sme.ssid_len; params.freq = wpa_s->sme.freq; params.bg_scan_period = wpa_s->current_ssid ? wpa_s->current_ssid->bg_scan_period : -1; params.wpa_ie = wpa_s->sme.assoc_req_ie_len ? wpa_s->sme.assoc_req_ie : NULL; params.wpa_ie_len = wpa_s->sme.assoc_req_ie_len; params.pairwise_suite = wpa_cipher_to_suite_driver(wpa_s->pairwise_cipher); params.group_suite = wpa_cipher_to_suite_driver(wpa_s->group_cipher); #ifdef CONFIG_HT_OVERRIDES os_memset(&htcaps, 0, sizeof(htcaps)); os_memset(&htcaps_mask, 0, sizeof(htcaps_mask)); params.htcaps = (u8 *) &htcaps; params.htcaps_mask = (u8 *) &htcaps_mask; wpa_supplicant_apply_ht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); #endif /* CONFIG_HT_OVERRIDES */ #ifdef CONFIG_VHT_OVERRIDES os_memset(&vhtcaps, 0, sizeof(vhtcaps)); os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask)); params.vhtcaps = &vhtcaps; params.vhtcaps_mask = &vhtcaps_mask; wpa_supplicant_apply_vht_overrides(wpa_s, wpa_s->current_ssid, ¶ms); #endif /* CONFIG_VHT_OVERRIDES */ #ifdef CONFIG_IEEE80211R if (auth_type == WLAN_AUTH_FT && wpa_s->sme.ft_ies) { params.wpa_ie = wpa_s->sme.ft_ies; params.wpa_ie_len = wpa_s->sme.ft_ies_len; } #endif /* CONFIG_IEEE80211R */ params.mode = mode; params.mgmt_frame_protection = wpa_s->sme.mfp; if (wpa_s->sme.prev_bssid_set) params.prev_bssid = wpa_s->sme.prev_bssid; wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), params.ssid ? wpa_ssid_txt(params.ssid, params.ssid_len) : "", params.freq); wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); if (params.wpa_ie == NULL || ieee802_11_parse_elems(params.wpa_ie, params.wpa_ie_len, &elems, 0) < 0) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Could not parse own IEs?!"); os_memset(&elems, 0, sizeof(elems)); } if (elems.rsn_ie) { params.wpa_proto = WPA_PROTO_RSN; wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.rsn_ie - 2, elems.rsn_ie_len + 2); } else if (elems.wpa_ie) { params.wpa_proto = WPA_PROTO_WPA; wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, elems.wpa_ie - 2, elems.wpa_ie_len + 2); } else wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); if (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group) params.p2p = 1; if (wpa_s->parent->set_sta_uapsd) params.uapsd = wpa_s->parent->sta_uapsd; else params.uapsd = -1; if (wpa_drv_associate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Association request to the " "driver failed"); wpas_connection_failed(wpa_s, wpa_s->pending_bssid); wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); return; } eloop_register_timeout(SME_ASSOC_TIMEOUT, 0, sme_assoc_timer, wpa_s, NULL); }
static void sme_send_authentication(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, struct wpa_ssid *ssid, int start) { struct wpa_driver_auth_params params; struct wpa_ssid *old_ssid; #ifdef CONFIG_IEEE80211R const u8 *ie; #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211R const u8 *md = NULL; #endif /* CONFIG_IEEE80211R */ int i, bssid_changed; struct wpabuf *resp = NULL; u8 ext_capab[10]; int ext_capab_len; if (bss == NULL) { wpa_msg(wpa_s, MSG_ERROR, "SME: No scan result available for " "the network"); return; } wpa_s->current_bss = bss; os_memset(¶ms, 0, sizeof(params)); wpa_s->reassociate = 0; params.freq = bss->freq; params.bssid = bss->bssid; params.ssid = bss->ssid; params.ssid_len = bss->ssid_len; params.p2p = ssid->p2p_group; if (wpa_s->sme.ssid_len != params.ssid_len || os_memcmp(wpa_s->sme.ssid, params.ssid, params.ssid_len) != 0) wpa_s->sme.prev_bssid_set = 0; wpa_s->sme.freq = params.freq; os_memcpy(wpa_s->sme.ssid, params.ssid, params.ssid_len); wpa_s->sme.ssid_len = params.ssid_len; params.auth_alg = WPA_AUTH_ALG_OPEN; #ifdef IEEE8021X_EAPOL if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { if (ssid->leap) { if (ssid->non_leap == 0) params.auth_alg = WPA_AUTH_ALG_LEAP; else params.auth_alg |= WPA_AUTH_ALG_LEAP; } } #endif /* IEEE8021X_EAPOL */ wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", params.auth_alg); if (ssid->auth_alg) { params.auth_alg = ssid->auth_alg; wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " "0x%x", params.auth_alg); } #ifdef CONFIG_SAE if (wpa_key_mgmt_sae(ssid->key_mgmt)) { const u8 *rsn; struct wpa_ie_data ied; rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ied) == 0) { if (wpa_key_mgmt_sae(ied.key_mgmt)) { wpa_dbg(wpa_s, MSG_DEBUG, "Using SAE auth_alg"); params.auth_alg = WPA_AUTH_ALG_SAE; } } } #endif /* CONFIG_SAE */ for (i = 0; i < NUM_WEP_KEYS; i++) { if (ssid->wep_key_len[i]) params.wep_key[i] = ssid->wep_key[i]; params.wep_key_len[i] = ssid->wep_key_len[i]; } params.wep_tx_keyidx = ssid->wep_tx_keyidx; bssid_changed = !is_zero_ether_addr(wpa_s->bssid); os_memset(wpa_s->bssid, 0, ETH_ALEN); os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); if (bssid_changed) wpas_notify_bssid_changed(wpa_s); if ((wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || wpa_bss_get_ie(bss, WLAN_EID_RSN)) && wpa_key_mgmt_wpa(ssid->key_mgmt)) { int try_opportunistic; try_opportunistic = (ssid->proactive_key_caching < 0 ? wpa_s->conf->okc : ssid->proactive_key_caching) && (ssid->proto & WPA_PROTO_RSN); if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, wpa_s->current_ssid, try_opportunistic) == 0) eapol_sm_notify_pmkid_attempt(wpa_s->eapol, 1); wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, bss, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites"); return; } } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) { /* * Both WPA and non-WPA IEEE 802.1X enabled in configuration - * use non-WPA since the scan results did not indicate that the * AP is using WPA or WPA2. */ wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { wpa_s->sme.assoc_req_ie_len = sizeof(wpa_s->sme.assoc_req_ie); if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, wpa_s->sme.assoc_req_ie, &wpa_s->sme.assoc_req_ie_len)) { wpa_msg(wpa_s, MSG_WARNING, "SME: Failed to set WPA " "key management and encryption suites (no " "scan results)"); return; } #ifdef CONFIG_WPS } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { struct wpabuf *wps_ie; wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_s->sme.assoc_req_ie)) { wpa_s->sme.assoc_req_ie_len = wpabuf_len(wps_ie); os_memcpy(wpa_s->sme.assoc_req_ie, wpabuf_head(wps_ie), wpa_s->sme.assoc_req_ie_len); } else wpa_s->sme.assoc_req_ie_len = 0; wpabuf_free(wps_ie); wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); #endif /* CONFIG_WPS */ } else { wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); wpa_s->sme.assoc_req_ie_len = 0; } #ifdef CONFIG_IEEE80211R ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) md = ie + 2; wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); if (md) { /* Prepare for the next transition */ wpa_ft_prepare_auth_request(wpa_s->wpa, ie); } if (md && wpa_key_mgmt_ft(ssid->key_mgmt)) { if (wpa_s->sme.assoc_req_ie_len + 5 < sizeof(wpa_s->sme.assoc_req_ie)) { struct rsn_mdie *mdie; u8 *pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; *pos++ = WLAN_EID_MOBILITY_DOMAIN; *pos++ = sizeof(*mdie); mdie = (struct rsn_mdie *) pos; os_memcpy(mdie->mobility_domain, md, MOBILITY_DOMAIN_ID_LEN); mdie->ft_capab = md[MOBILITY_DOMAIN_ID_LEN]; wpa_s->sme.assoc_req_ie_len += 5; } if (wpa_s->sme.ft_used && os_memcmp(md, wpa_s->sme.mobility_domain, 2) == 0 && wpa_sm_has_ptk(wpa_s->wpa)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying to use FT " "over-the-air"); params.auth_alg = WPA_AUTH_ALG_FT; params.ie = wpa_s->sme.ft_ies; params.ie_len = wpa_s->sme.ft_ies_len; } } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211W wpa_s->sme.mfp = ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT ? wpa_s->conf->pmf : ssid->ieee80211w; if (wpa_s->sme.mfp != NO_MGMT_FRAME_PROTECTION) { const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); struct wpa_ie_data _ie; if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &_ie) == 0 && _ie.capabilities & (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Selected AP supports " "MFP: require MFP"); wpa_s->sme.mfp = MGMT_FRAME_PROTECTION_REQUIRED; } } #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P if (wpa_s->global->p2p) { u8 *pos; size_t len; int res; pos = wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len; len = sizeof(wpa_s->sme.assoc_req_ie) - wpa_s->sme.assoc_req_ie_len; res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, ssid->p2p_group); if (res >= 0) wpa_s->sme.assoc_req_ie_len += res; } #endif /* CONFIG_P2P */ #ifdef CONFIG_HS20 if (is_hs20_network(wpa_s, ssid, bss)) { struct wpabuf *hs20; hs20 = wpabuf_alloc(20); if (hs20) { wpas_hs20_add_indication(hs20); os_memcpy(wpa_s->sme.assoc_req_ie + wpa_s->sme.assoc_req_ie_len, wpabuf_head(hs20), wpabuf_len(hs20)); wpa_s->sme.assoc_req_ie_len += wpabuf_len(hs20); wpabuf_free(hs20); } } #endif /* CONFIG_HS20 */ ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab); if (ext_capab_len > 0) { u8 *pos = wpa_s->sme.assoc_req_ie; if (wpa_s->sme.assoc_req_ie_len > 0 && pos[0] == WLAN_EID_RSN) pos += 2 + pos[1]; os_memmove(pos + ext_capab_len, pos, wpa_s->sme.assoc_req_ie_len - (pos - wpa_s->sme.assoc_req_ie)); wpa_s->sme.assoc_req_ie_len += ext_capab_len; os_memcpy(pos, ext_capab, ext_capab_len); } #ifdef CONFIG_SAE if (params.auth_alg == WPA_AUTH_ALG_SAE) { if (start) resp = sme_auth_build_sae_commit(wpa_s, ssid, bss->bssid); else resp = sme_auth_build_sae_confirm(wpa_s); if (resp == NULL) return; params.sae_data = wpabuf_head(resp); params.sae_data_len = wpabuf_len(resp); wpa_s->sme.sae.state = start ? SAE_COMMITTED : SAE_CONFIRMED; } #endif /* CONFIG_SAE */ wpa_supplicant_cancel_sched_scan(wpa_s); wpa_supplicant_cancel_scan(wpa_s); wpa_msg(wpa_s, MSG_INFO, "SME: Trying to authenticate with " MACSTR " (SSID='%s' freq=%d MHz)", MAC2STR(params.bssid), wpa_ssid_txt(params.ssid, params.ssid_len), params.freq); wpa_clear_keys(wpa_s, bss->bssid); wpa_supplicant_set_state(wpa_s, WPA_AUTHENTICATING); old_ssid = wpa_s->current_ssid; wpa_s->current_ssid = ssid; wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); wpa_supplicant_initiate_eapol(wpa_s); if (old_ssid != wpa_s->current_ssid) wpas_notify_network_changed(wpa_s); wpa_s->sme.auth_alg = params.auth_alg; if (wpa_drv_authenticate(wpa_s, ¶ms) < 0) { wpa_msg(wpa_s, MSG_INFO, "SME: Authentication request to the " "driver failed"); wpas_connection_failed(wpa_s, bss->bssid); wpa_supplicant_mark_disassoc(wpa_s); wpabuf_free(resp); return; } eloop_register_timeout(SME_AUTH_TIMEOUT, 0, sme_auth_timer, wpa_s, NULL); /* * Association will be started based on the authentication event from * the driver. */ wpabuf_free(resp); }
static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx) { const struct wps_credential *cred = ctx; FILE *oconf, *nconf; size_t len, i; char *tmp_fname; char buf[1024]; int multi_bss; int wpa; if (hapd->wps == NULL) return 0; wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute", cred->cred_attr, cred->cred_attr_len); wpa_printf(MSG_DEBUG, "WPS: Received new AP Settings"); wpa_hexdump_ascii(MSG_DEBUG, "WPS: SSID", cred->ssid, cred->ssid_len); wpa_printf(MSG_DEBUG, "WPS: Authentication Type 0x%x", cred->auth_type); wpa_printf(MSG_DEBUG, "WPS: Encryption Type 0x%x", cred->encr_type); wpa_printf(MSG_DEBUG, "WPS: Network Key Index %d", cred->key_idx); wpa_hexdump_key(MSG_DEBUG, "WPS: Network Key", cred->key, cred->key_len); wpa_printf(MSG_DEBUG, "WPS: MAC Address " MACSTR, MAC2STR(cred->mac_addr)); if ((hapd->conf->wps_cred_processing == 1 || hapd->conf->wps_cred_processing == 2) && cred->cred_attr) { size_t blen = cred->cred_attr_len * 2 + 1; char *_buf = os_malloc(blen); if (_buf) { wpa_snprintf_hex(_buf, blen, cred->cred_attr, cred->cred_attr_len); wpa_msg(hapd->msg_ctx, MSG_INFO, "%s%s", WPS_EVENT_NEW_AP_SETTINGS, _buf); os_free(_buf); } } else wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_NEW_AP_SETTINGS); if (hapd->conf->wps_cred_processing == 1) return 0; os_memcpy(hapd->wps->ssid, cred->ssid, cred->ssid_len); hapd->wps->ssid_len = cred->ssid_len; hapd->wps->encr_types = cred->encr_type; hapd->wps->auth_types = cred->auth_type; if (cred->key_len == 0) { os_free(hapd->wps->network_key); hapd->wps->network_key = NULL; hapd->wps->network_key_len = 0; } else { if (hapd->wps->network_key == NULL || hapd->wps->network_key_len < cred->key_len) { hapd->wps->network_key_len = 0; os_free(hapd->wps->network_key); hapd->wps->network_key = os_malloc(cred->key_len); if (hapd->wps->network_key == NULL) return -1; } hapd->wps->network_key_len = cred->key_len; os_memcpy(hapd->wps->network_key, cred->key, cred->key_len); } hapd->wps->wps_state = WPS_STATE_CONFIGURED; len = os_strlen(hapd->iface->config_fname) + 5; tmp_fname = os_malloc(len); if (tmp_fname == NULL) return -1; os_snprintf(tmp_fname, len, "%s-new", hapd->iface->config_fname); oconf = fopen(hapd->iface->config_fname, "r"); if (oconf == NULL) { wpa_printf(MSG_WARNING, "WPS: Could not open current " "configuration file"); os_free(tmp_fname); return -1; } nconf = fopen(tmp_fname, "w"); if (nconf == NULL) { wpa_printf(MSG_WARNING, "WPS: Could not write updated " "configuration file"); os_free(tmp_fname); fclose(oconf); return -1; } fprintf(nconf, "# WPS configuration - START\n"); fprintf(nconf, "wps_state=2\n"); fprintf(nconf, "ssid="); for (i = 0; i < cred->ssid_len; i++) fputc(cred->ssid[i], nconf); fprintf(nconf, "\n"); if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) && (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))) wpa = 3; else if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) wpa = 2; else if (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)) wpa = 1; else wpa = 0; if (wpa) { char *prefix; fprintf(nconf, "wpa=%d\n", wpa); fprintf(nconf, "wpa_key_mgmt="); prefix = ""; if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA)) { fprintf(nconf, "WPA-EAP"); prefix = " "; } if (cred->auth_type & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK)) fprintf(nconf, "%sWPA-PSK", prefix); fprintf(nconf, "\n"); fprintf(nconf, "wpa_pairwise="); prefix = ""; if (cred->encr_type & WPS_ENCR_AES) { fprintf(nconf, "CCMP"); prefix = " "; } if (cred->encr_type & WPS_ENCR_TKIP) { fprintf(nconf, "%sTKIP", prefix); } fprintf(nconf, "\n"); if (cred->key_len >= 8 && cred->key_len < 64) { fprintf(nconf, "wpa_passphrase="); for (i = 0; i < cred->key_len; i++) fputc(cred->key[i], nconf); fprintf(nconf, "\n"); } else if (cred->key_len == 64) { fprintf(nconf, "wpa_psk="); for (i = 0; i < cred->key_len; i++) fputc(cred->key[i], nconf); fprintf(nconf, "\n"); } else { wpa_printf(MSG_WARNING, "WPS: Invalid key length %lu " "for WPA/WPA2", (unsigned long) cred->key_len); } fprintf(nconf, "auth_algs=1\n"); } else { if ((cred->auth_type & WPS_AUTH_OPEN) && (cred->auth_type & WPS_AUTH_SHARED)) fprintf(nconf, "auth_algs=3\n"); else if (cred->auth_type & WPS_AUTH_SHARED) fprintf(nconf, "auth_algs=2\n"); else fprintf(nconf, "auth_algs=1\n"); if (cred->encr_type & WPS_ENCR_WEP && cred->key_idx <= 4) { int key_idx = cred->key_idx; if (key_idx) key_idx--; fprintf(nconf, "wep_default_key=%d\n", key_idx); fprintf(nconf, "wep_key%d=", key_idx); if (cred->key_len == 10 || cred->key_len == 26) { /* WEP key as a hex string */ for (i = 0; i < cred->key_len; i++) fputc(cred->key[i], nconf); } else { /* Raw WEP key; convert to hex */ for (i = 0; i < cred->key_len; i++) fprintf(nconf, "%02x", cred->key[i]); } fprintf(nconf, "\n"); } } fprintf(nconf, "# WPS configuration - END\n"); multi_bss = 0; while (fgets(buf, sizeof(buf), oconf)) { if (os_strncmp(buf, "bss=", 4) == 0) multi_bss = 1; if (!multi_bss && (str_starts(buf, "ssid=") || str_starts(buf, "auth_algs=") || str_starts(buf, "wep_default_key=") || str_starts(buf, "wep_key") || str_starts(buf, "wps_state=") || str_starts(buf, "wpa=") || str_starts(buf, "wpa_psk=") || str_starts(buf, "wpa_pairwise=") || str_starts(buf, "rsn_pairwise=") || str_starts(buf, "wpa_key_mgmt=") || str_starts(buf, "wpa_passphrase="))) { fprintf(nconf, "#WPS# %s", buf); } else fprintf(nconf, "%s", buf); } fclose(nconf); fclose(oconf); if (rename(tmp_fname, hapd->iface->config_fname) < 0) { wpa_printf(MSG_WARNING, "WPS: Failed to rename the updated " "configuration file: %s", strerror(errno)); os_free(tmp_fname); return -1; } os_free(tmp_fname); /* Schedule configuration reload after short period of time to allow * EAP-WSC to be finished. */ eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface, NULL); wpa_printf(MSG_DEBUG, "WPS: AP configuration updated"); return 0; }
/*----------------------------------------------------------------------------- Routine Name: wpa_driver_tista_driver_cmd Routine Description: executes driver-specific commands Arguments: priv - pointer to private data structure cmd - command buf - return buffer buf_len - buffer length Return Value: actual buffer length - success, -1 - failure -----------------------------------------------------------------------------*/ static int wpa_driver_tista_driver_cmd( void *priv, char *cmd, char *buf, size_t buf_len ) { struct wpa_driver_ti_data *drv = (struct wpa_driver_ti_data *)priv; int ret = -1, prev_events, flags; wpa_printf(MSG_DEBUG, "%s %s", __func__, cmd); if( os_strcasecmp(cmd, "start") == 0 ) { wpa_printf(MSG_DEBUG,"Start command"); ret = wpa_driver_tista_driver_start(priv); if( ret == 0 ) { drv->driver_is_loaded = TRUE; wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STARTED"); } return( TI2WPA_STATUS(ret) ); } TI_CHECK_DRIVER( drv->driver_is_loaded, -1 ); if( os_strcasecmp(cmd, "stop") == 0 ) { wpa_printf(MSG_DEBUG,"Stop command"); if ((wpa_driver_wext_get_ifflags(drv->wext, &flags) == 0) && (flags & IFF_UP)) { wpa_printf(MSG_ERROR, "TI: %s when iface is UP", cmd); wpa_driver_wext_set_ifflags(drv->wext, flags & ~IFF_UP); } ret = wpa_driver_tista_driver_stop(priv); if( ret == 0 ) { scan_exit(drv); /* Clear scan cache */ drv->driver_is_loaded = FALSE; wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "STOPPED"); } } if( os_strcasecmp(cmd, "reload") == 0 ) { wpa_printf(MSG_DEBUG,"Reload command"); ret = 0; wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED"); } else if( os_strcasecmp(cmd, "macaddr") == 0 ) { wpa_driver_tista_get_mac_addr(priv); wpa_printf(MSG_DEBUG, "Macaddr command"); ret = sprintf(buf, "Macaddr = " MACSTR "\n", MAC2STR(drv->own_addr)); wpa_printf(MSG_DEBUG, "buf %s", buf); } else if( os_strcasecmp(cmd, "scan-passive") == 0 ) { wpa_printf(MSG_DEBUG,"Scan Passive command"); drv->scan_type = SCAN_TYPE_NORMAL_PASSIVE; ret = 0; } else if( os_strcasecmp(cmd, "scan-active") == 0 ) { wpa_printf(MSG_DEBUG,"Scan Active command"); drv->scan_type = SCAN_TYPE_NORMAL_ACTIVE; ret = 0; } else if( os_strcasecmp(cmd, "scan-mode") == 0 ) { wpa_printf(MSG_DEBUG,"Scan Mode command"); ret = snprintf(buf, buf_len, "ScanMode = %u\n", drv->scan_type); if (ret < (int)buf_len) { return( ret ); } } else if( os_strcasecmp(cmd, "linkspeed") == 0 ) { struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx); wpa_printf(MSG_DEBUG,"Link Speed command"); drv->link_speed = wpa_driver_tista_get_rate(priv); ret = sprintf(buf,"LinkSpeed %u\n", drv->link_speed); wpa_printf(MSG_DEBUG, "buf %s", buf); } else if( os_strncasecmp(cmd, "scan-channels", 13) == 0 ) { int noOfChan; noOfChan = atoi(cmd + 13); wpa_printf(MSG_DEBUG,"Scan Channels command = %d", noOfChan); if( (noOfChan > 0) && (noOfChan <= MAX_NUMBER_OF_CHANNELS_PER_SCAN) ) drv->scan_channels = noOfChan; ret = sprintf(buf,"Scan-Channels = %d\n", drv->scan_channels); wpa_printf(MSG_DEBUG, "buf %s", buf); } else if( os_strcasecmp(cmd, "rssi-approx") == 0 ) { scan_result_t *cur_res; struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx); scan_ssid_t *p_ssid; int rssi, len; wpa_printf(MSG_DEBUG,"rssi-approx command"); if( !wpa_s ) return( ret ); cur_res = scan_get_by_bssid(drv, wpa_s->bssid); if( cur_res ) { p_ssid = scan_get_ssid(cur_res); len = (int)(p_ssid->ssid_len); rssi = cur_res->level; if( (len > 0) && (len <= MAX_SSID_LEN) && (len < (int)buf_len)) { os_memcpy((void *)buf, (void *)(p_ssid->ssid), len); ret = len; ret += snprintf(&buf[ret], buf_len-len, " rssi %d\n", rssi); } } } else if( os_strcasecmp(cmd, "rssi") == 0 ) { u8 ssid[MAX_SSID_LEN]; scan_result_t *cur_res; struct wpa_supplicant *wpa_s = (struct wpa_supplicant *)(drv->ctx); int rssi_data, rssi_beacon, len; wpa_printf(MSG_DEBUG,"rssi command"); ret = wpa_driver_tista_get_rssi(priv, &rssi_data, &rssi_beacon); if( ret == 0 ) { len = wpa_driver_tista_get_ssid(priv, (u8 *)ssid); wpa_printf(MSG_DEBUG,"rssi_data %d rssi_beacon %d", rssi_data, rssi_beacon); if( (len > 0) && (len <= MAX_SSID_LEN) ) { os_memcpy((void *)buf, (void *)ssid, len); ret = len; ret += sprintf(&buf[ret], " rssi %d\n", rssi_beacon); wpa_printf(MSG_DEBUG, "buf %s", buf); /* Update cached value */ if( !wpa_s ) return( ret ); cur_res = scan_get_by_bssid(drv, wpa_s->bssid); if( cur_res ) cur_res->level = rssi_beacon; } else { wpa_printf(MSG_DEBUG, "Fail to get ssid when reporting rssi"); ret = -1; } } } else if( os_strncasecmp(cmd, "powermode", 9) == 0 ) { u32 mode; TPowerMgr_PowerMode tMode; mode = (u32)atoi(cmd + 9); wpa_printf(MSG_DEBUG,"Power Mode command = %u", mode); if( mode < POWER_MODE_MAX ) { tMode.PowerMode = (PowerMgr_PowerMode_e)mode; tMode.PowerMngPriority = POWER_MANAGER_USER_PRIORITY; ret = wpa_driver_tista_config_power_management( priv, &tMode, 1 ); } } else if (os_strncasecmp(cmd, "getpower", 8) == 0 ) { u32 mode; TPowerMgr_PowerMode tMode; os_memset(&tMode, 0, sizeof(TPowerMgr_PowerMode)); ret = wpa_driver_tista_config_power_management( priv, &tMode, 0 ); if( ret == 0 ) { ret = sprintf(buf, "powermode = %u\n", tMode.PowerMode); wpa_printf(MSG_DEBUG, "buf %s", buf); } } else if( os_strncasecmp(cmd, "btcoexmode", 10) == 0 ) { u32 mode; mode = (u32)atoi(cmd + 10); wpa_printf(MSG_DEBUG,"BtCoex Mode command = %u", mode); ret = wpa_driver_tista_enable_bt_coe( priv, mode ); if( ret == 0 ) { drv->btcoex_mode = mode; } } else if( os_strcasecmp(cmd, "btcoexstat") == 0 ) { u32 status = drv->btcoex_mode; wpa_printf(MSG_DEBUG,"BtCoex Status"); ret = wpa_driver_tista_get_bt_coe_status( priv, &status ); if( ret == 0 ) { ret = sprintf(buf, "btcoexstatus = 0x%x\n", status); wpa_printf(MSG_DEBUG, "buf %s", buf); } } else if( os_strcasecmp(cmd, "rxfilter-start") == 0 ) { wpa_printf(MSG_DEBUG,"Rx Data Filter Start command"); ret = wpa_driver_tista_driver_enable_rx_data_filter( priv ); } else if( os_strcasecmp(cmd, "rxfilter-stop") == 0 ) { wpa_printf(MSG_DEBUG,"Rx Data Filter Stop command"); ret = wpa_driver_tista_driver_disable_rx_data_filter( priv ); } else if( os_strcasecmp(cmd, "rxfilter-statistics") == 0 ) { TCuCommon_RxDataFilteringStatistics stats; int len, i; os_memset(&stats, 0, sizeof(TCuCommon_RxDataFilteringStatistics)); wpa_printf(MSG_DEBUG,"Rx Data Filter Statistics command"); ret = wpa_driver_tista_driver_rx_data_filter_statistics( priv, &stats ); if( ret == 0 ) { ret = snprintf(buf, buf_len, "RxFilterStat: %u", (u32)stats.unmatchedPacketsCount); for(i=0;( i < MAX_DATA_FILTERS );i++) { ret += snprintf(&buf[ret], buf_len-ret, " %u", (u32)stats.matchedPacketsCount[i]); } ret += snprintf(&buf[ret], buf_len-ret, "\n"); if (ret >= (int)buf_len) { ret = -1; } } } else if( os_strncasecmp(cmd, "rxfilter-add", 12) == 0 ) { TRxDataFilterRequest dfreq; char *cp = cmd + 12; char *endp; int type; if (*cp != '\0') { type = (int)strtol(cp, &endp, 0); if (endp != cp) { wpa_printf(MSG_DEBUG,"Rx Data Filter Add [%d] command", type); ret = prepare_filter_struct( priv, type, &dfreq ); if( ret == 0 ) { ret = wpa_driver_tista_driver_rx_data_filter( priv, &dfreq, 1 ); } } } } else if( os_strncasecmp(cmd, "rxfilter-remove",15) == 0 ) { TRxDataFilterRequest dfreq; char *cp = cmd + 15; char *endp; int type; if (*cp != '\0') { type = (int)strtol(cp, &endp, 0); if (endp != cp) { wpa_printf(MSG_DEBUG,"Rx Data Filter remove [%d] command", type); ret = prepare_filter_struct( priv, type, &dfreq ); if( ret == 0 ) { ret = wpa_driver_tista_driver_rx_data_filter( priv, &dfreq, 0 ); } } } } else if( os_strncasecmp(cmd, "setip",5) == 0 ) { u32 staIp; staIp = (u32)atoi(cmd + 5); wpa_printf(MSG_DEBUG,"setip command = %u", staIp); ret = wpa_driver_tista_set_driver_ip( priv, staIp ); } else { wpa_printf(MSG_DEBUG,"Unsupported command"); } return ret; }