void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa, const u8 *da, u16 reason_code) { struct wpa_ssid *ssid; struct os_reltime now; if (wpa_s->wpa_state != WPA_COMPLETED) return; ssid = wpa_s->current_ssid; if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION) return; if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) return; if (reason_code != WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA && reason_code != WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA) return; if (wpa_s->sme.sa_query_count > 0) return; os_get_reltime(&now); if (wpa_s->sme.last_unprot_disconnect.sec && !os_reltime_expired(&now, &wpa_s->sme.last_unprot_disconnect, 10)) return; /* limit SA Query procedure frequency */ wpa_s->sme.last_unprot_disconnect = now; wpa_dbg(wpa_s, MSG_DEBUG, "SME: Unprotected disconnect dropped - " "possible AP/STA state mismatch - trigger SA Query"); sme_start_sa_query(wpa_s); }
void sta_track_add(struct hostapd_iface *iface, const u8 *addr) { struct hostapd_sta_info *info; info = sta_track_get(iface, addr); if (info) { /* Move the most recent entry to the end of the list */ dl_list_del(&info->list); dl_list_add_tail(&iface->sta_seen, &info->list); os_get_reltime(&info->last_seen); return; } /* Add a new entry */ info = os_zalloc(sizeof(*info)); os_memcpy(info->addr, addr, ETH_ALEN); os_get_reltime(&info->last_seen); if (iface->num_sta_seen >= iface->conf->track_sta_max_num) { /* Expire oldest entry to make room for a new one */ sta_track_expire(iface, 1); } wpa_printf(MSG_MSGDUMP, "%s: Add STA tracking entry for " MACSTR, iface->bss[0]->conf->iface, MAC2STR(addr)); dl_list_add_tail(&iface->sta_seen, &info->list); iface->num_sta_seen++; }
void eloop_run(void) { int num_poll_fds; int timeout_ms = 0; int res; struct os_reltime tv, now; bzero(&now, sizeof(struct os_reltime)); while (!eloop.terminate && (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || eloop.writers.count > 0 || eloop.exceptions.count > 0)) { struct eloop_timeout *timeout; timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, list); if (timeout) { os_get_reltime(&now); if (os_reltime_before(&now, &timeout->time)) os_reltime_sub(&timeout->time, &now, &tv); else tv.sec = tv.usec = 0; timeout_ms = tv.sec * 1000 + tv.usec / 1000; } num_poll_fds = eloop_sock_table_set_fds(&eloop.readers, &eloop.writers, &eloop.exceptions, eloop.pollfds, eloop.pollfds_map, eloop.max_pollfd_map); res = poll(eloop.pollfds, num_poll_fds, timeout ? timeout_ms : -1); if (res < 0 && errno != EINTR && errno != 0) { fprintf(stderr, "eloop: poll: %s", strerror(errno)); goto out; } timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, list); if (timeout) { os_get_reltime(&now); if (!os_reltime_before(&now, &timeout->time)) { void *eloop_data = timeout->eloop_data; void *user_data = timeout->user_data; eloop_timeout_handler handler = timeout->handler; eloop_remove_timeout(timeout); handler(eloop_data, user_data); } } if (res <= 0) continue; eloop_sock_table_dispatch(&eloop.readers, &eloop.writers, &eloop.exceptions, eloop.pollfds_map, eloop.max_pollfd_map); } out: return; }
static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit) { struct wpa_supplicant *wpa_s = work->wpa_s; struct wpa_driver_scan_params *params = work->ctx; int ret; if (deinit) { wpa_scan_free_params(params); return; } wpa_supplicant_notify_scanning(wpa_s, 1); if (wpa_s->clear_driver_scan_cache) params->only_new_results = 1; ret = wpa_drv_scan(wpa_s, params); wpa_scan_free_params(params); work->ctx = NULL; if (ret) { wpa_supplicant_notify_scanning(wpa_s, 0); wpas_notify_scan_done(wpa_s, 0); radio_work_done(work); return; } os_get_reltime(&wpa_s->scan_trigger_time); wpa_s->scan_runs++; wpa_s->normal_scans++; wpa_s->own_scan_requested = 1; wpa_s->clear_driver_scan_cache = 0; wpa_s->scan_work = work; }
void hs20_next_osu_icon(struct wpa_supplicant *wpa_s) { size_t i, j; wpa_printf(MSG_DEBUG, "HS 2.0: Ready to fetch next icon"); for (i = 0; i < wpa_s->osu_prov_count; i++) { struct osu_provider *osu = &wpa_s->osu_prov[i]; for (j = 0; j < osu->icon_count; j++) { struct osu_icon *icon = &osu->icon[j]; if (icon->id || icon->failed) continue; wpa_printf(MSG_DEBUG, "HS 2.0: Try to fetch icon '%s' " "from " MACSTR, icon->filename, MAC2STR(osu->bssid)); os_get_reltime(&wpa_s->osu_icon_fetch_start); if (hs20_anqp_send_req(wpa_s, osu->bssid, BIT(HS20_STYPE_ICON_REQUEST), (u8 *) icon->filename, os_strlen(icon->filename), 0) < 0) { icon->failed = 1; continue; } return; } } wpa_printf(MSG_DEBUG, "HS 2.0: No more icons to fetch"); hs20_osu_fetch_done(wpa_s); }
static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query, struct wpabuf *req, unsigned int wait_time) { int res, prot = pmf_in_use(gas->wpa_s, query->addr); const u8 *bssid; const u8 wildcard_bssid[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u " "freq=%d prot=%d", MAC2STR(query->addr), (unsigned int) wpabuf_len(req), query->freq, prot); if (prot) { u8 *categ = wpabuf_mhead_u8(req); *categ = WLAN_ACTION_PROTECTED_DUAL; } os_get_reltime(&query->last_oper); if (gas->wpa_s->max_remain_on_chan && wait_time > gas->wpa_s->max_remain_on_chan) wait_time = gas->wpa_s->max_remain_on_chan; if (!gas->wpa_s->conf->gas_address3 || (gas->wpa_s->current_ssid && gas->wpa_s->wpa_state >= WPA_ASSOCIATED && os_memcmp(query->addr, gas->wpa_s->bssid, ETH_ALEN) == 0)) bssid = query->addr; else bssid = wildcard_bssid; res = offchannel_send_action(gas->wpa_s, query->freq, query->addr, gas->wpa_s->own_addr, bssid, wpabuf_head(req), wpabuf_len(req), wait_time, gas_query_tx_status, 0); if (res == 0) query->offchannel_tx_started = 1; return res; }
void sta_track_expire(struct hostapd_iface *iface, int force) { struct os_reltime now; struct hostapd_sta_info *info; if (!iface->num_sta_seen) return; os_get_reltime(&now); while ((info = dl_list_first(&iface->sta_seen, struct hostapd_sta_info, list))) { if (!force && !os_reltime_expired(&now, &info->last_seen, iface->conf->track_sta_max_age)) break; force = 0; wpa_printf(MSG_MSGDUMP, "%s: Expire STA tracking entry for " MACSTR, iface->bss[0]->conf->iface, MAC2STR(info->addr)); dl_list_del(&info->list); iface->num_sta_seen--; os_free(info); } }
/** * wpa_bss_update_end - End a BSS table update from scan results * @wpa_s: Pointer to wpa_supplicant data * @info: Information about scan parameters * @new_scan: Whether this update round was based on a new scan * * This function is called at the end of each BSS table update round for new * scan results. The start of the update was indicated with a call to * wpa_bss_update_start(). */ void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info, int new_scan) { struct wpa_bss *bss, *n; os_get_reltime(&wpa_s->last_scan); if (!new_scan) return; /* do not expire entries without new scan */ dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) { if (wpa_bss_in_use(wpa_s, bss)) continue; if (!wpa_bss_included_in_scan(bss, info)) continue; /* expire only BSSes that were scanned */ if (bss->last_update_idx < wpa_s->bss_update_idx) bss->scan_miss_count++; if (bss->scan_miss_count >= wpa_s->conf->bss_expiration_scan_count) { wpa_bss_remove(wpa_s, bss, "no match in scan"); } } wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%u/%u", wpa_s->last_scan_res_used, wpa_s->last_scan_res_size); }
static void hs20_osu_icon_fetch_result(struct wpa_supplicant *wpa_s, int res) { size_t i, j; struct os_reltime now, tmp; int dur; os_get_reltime(&now); os_reltime_sub(&now, &wpa_s->osu_icon_fetch_start, &tmp); dur = tmp.sec * 1000 + tmp.usec / 1000; wpa_printf(MSG_DEBUG, "HS 2.0: Icon fetch dur=%d ms res=%d", dur, res); for (i = 0; i < wpa_s->osu_prov_count; i++) { struct osu_provider *osu = &wpa_s->osu_prov[i]; for (j = 0; j < osu->icon_count; j++) { struct osu_icon *icon = &osu->icon[j]; if (icon->id || icon->failed) continue; if (res < 0) icon->failed = 1; else icon->id = wpa_s->osu_icon_id; return; } } }
int eloop_cancel_timeout_one(eloop_timeout_handler handler, void *eloop_data, void *user_data, struct os_reltime *remaining) { struct eloop_timeout *timeout, *prev; int removed = 0; struct os_reltime now; os_get_reltime(&now); remaining->sec = remaining->usec = 0; dl_list_for_each_safe(timeout, prev, &eloop.timeout, struct eloop_timeout, list) { if (timeout->handler == handler && (timeout->eloop_data == eloop_data) && (timeout->user_data == user_data)) { removed = 1; if (os_reltime_before(&now, &timeout->time)) os_reltime_sub(&timeout->time, &now, remaining); eloop_remove_timeout(timeout); break; } } return removed; }
int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr) { struct ibss_rsn_peer *peer; int res; if (!ibss_rsn) return -1; /* if the peer already exists, exit immediately */ peer = ibss_rsn_get_peer(ibss_rsn, addr); if (peer) return 0; peer = ibss_rsn_peer_init(ibss_rsn, addr); if (peer == NULL) return -1; /* Open Authentication: send first Authentication frame */ res = ibss_rsn_send_auth(ibss_rsn, addr, 1); if (res) { /* * The driver may not support Authentication frame exchange in * IBSS. Ignore authentication and go through EAPOL exchange. */ peer->authentication_status |= IBSS_RSN_AUTH_BY_US; return ibss_rsn_auth_init(ibss_rsn, peer); } else { os_get_reltime(&peer->own_auth_tx); eloop_register_timeout(1, 0, ibss_rsn_auth_timeout, peer, NULL); } return 0; }
/** * pmksa_cache_auth_list - Dump text list of entries in PMKSA cache * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() * @buf: Buffer for the list * @len: Length of the buffer * Returns: Number of bytes written to buffer * * This function is used to generate a text format representation of the * current PMKSA cache contents for the ctrl_iface PMKSA command. */ int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) { int i, ret; char *pos = buf; struct rsn_pmksa_cache_entry *entry; struct os_reltime now; os_get_reltime(&now); ret = os_snprintf(pos, buf + len - pos, "Index / SPA / PMKID / expiration (in seconds) / opportunistic\n"); if (os_snprintf_error(buf + len - pos, ret)) return pos - buf; pos += ret; i = 0; entry = pmksa->pmksa; while (entry) { ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ", i, MAC2STR(entry->spa)); if (os_snprintf_error(buf + len - pos, ret)) return pos - buf; pos += ret; pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid, PMKID_LEN); ret = os_snprintf(pos, buf + len - pos, " %d %d\n", (int) (entry->expiration - now.sec), entry->opportunistic); if (os_snprintf_error(buf + len - pos, ret)) return pos - buf; pos += ret; entry = entry->next; } return pos - buf; }
static void sme_sa_query_timer(void *eloop_ctx, void *timeout_ctx) { struct wpa_supplicant *wpa_s = eloop_ctx; unsigned int timeout, sec, usec; u8 *trans_id, *nbuf; if (wpa_s->sme.sa_query_count > 0 && sme_check_sa_query_timeout(wpa_s)) return; nbuf = os_realloc_array(wpa_s->sme.sa_query_trans_id, wpa_s->sme.sa_query_count + 1, WLAN_SA_QUERY_TR_ID_LEN); if (nbuf == NULL) return; if (wpa_s->sme.sa_query_count == 0) { /* Starting a new SA Query procedure */ os_get_reltime(&wpa_s->sme.sa_query_start); } trans_id = nbuf + wpa_s->sme.sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; wpa_s->sme.sa_query_trans_id = nbuf; wpa_s->sme.sa_query_count++; os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN); timeout = sa_query_retry_timeout; sec = ((timeout / 1000) * 1024) / 1000; usec = (timeout % 1000) * 1024; eloop_register_timeout(sec, usec, sme_sa_query_timer, wpa_s, NULL); wpa_dbg(wpa_s, MSG_DEBUG, "SME: Association SA Query attempt %d", wpa_s->sme.sa_query_count); sme_send_sa_query_req(wpa_s, trans_id); }
void eloop_destroy(void) { struct eloop_timeout *timeout, *prev; struct os_reltime now; os_get_reltime(&now); dl_list_for_each_safe(timeout, prev, &eloop.timeout, struct eloop_timeout, list) { int sec, usec; sec = timeout->time.sec - now.sec; usec = timeout->time.usec - now.usec; if (timeout->time.usec < now.usec) { sec--; usec += 1000000; } wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d " "eloop_data=%p user_data=%p handler=%p", sec, usec, timeout->eloop_data, timeout->user_data, timeout->handler); wpa_trace_dump_funcname("eloop unregistered timeout handler", timeout->handler); wpa_trace_dump("eloop timeout", timeout); eloop_remove_timeout(timeout); } eloop_sock_table_destroy(&eloop.readers); eloop_sock_table_destroy(&eloop.writers); eloop_sock_table_destroy(&eloop.exceptions); os_free(eloop.signals); #ifdef CONFIG_ELOOP_POLL os_free(eloop.pollfds); os_free(eloop.pollfds_map); #endif /* CONFIG_ELOOP_POLL */ }
int hostapd_start_dfs_cac(struct hostapd_iface *iface, int mode, int freq, int channel, int ht_enabled, int vht_enabled, int sec_channel_offset, int vht_oper_chwidth, int center_segment0, int center_segment1) { struct hostapd_data *hapd = iface->bss[0]; struct hostapd_freq_params data; int res; if (!hapd->driver || !hapd->driver->start_dfs_cac) return 0; if (!iface->conf->ieee80211h) { wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality " "is not enabled"); return -1; } if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled, vht_enabled, sec_channel_offset, vht_oper_chwidth, center_segment0, center_segment1, iface->current_mode->vht_capab)) { wpa_printf(MSG_ERROR, "Can't set freq params"); return -1; } res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data); if (!res) { iface->cac_started = 1; os_get_reltime(&iface->dfs_cac_start); } return res; }
/** * accounting_sta_start - Start STA accounting * @hapd: hostapd BSS data * @sta: The station */ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta) { struct radius_msg *msg; int interval; if (sta->acct_session_started) return; hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO, "starting accounting session %08X-%08X", sta->acct_session_id_hi, sta->acct_session_id_lo); os_get_reltime(&sta->acct_session_start); sta->last_rx_bytes = sta->last_tx_bytes = 0; sta->acct_input_gigawords = sta->acct_output_gigawords = 0; hostapd_drv_sta_clear_stats(hapd, sta->addr); if (!hapd->conf->radius->acct_server) return; if (sta->acct_interim_interval) interval = sta->acct_interim_interval; else interval = ACCT_DEFAULT_UPDATE_INTERVAL; eloop_register_timeout(interval, 0, accounting_interim_update, hapd, sta); msg = accounting_msg(hapd, sta, RADIUS_ACCT_STATUS_TYPE_START); if (msg && radius_client_send(hapd->radius, msg, RADIUS_ACCT, sta->addr) < 0) radius_msg_free(msg); sta->acct_session_started = 1; }
static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) { int sec; struct rsn_pmksa_cache_entry *entry; struct os_reltime now; eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); eloop_cancel_timeout(pmksa_cache_reauth, pmksa, NULL); if (pmksa->pmksa == NULL) return; os_get_reltime(&now); sec = pmksa->pmksa->expiration - now.sec; if (sec < 0) sec = 0; eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL); entry = pmksa->sm->cur_pmksa ? pmksa->sm->cur_pmksa : pmksa_cache_get(pmksa, pmksa->sm->bssid, NULL, NULL); if (entry) { sec = pmksa->pmksa->reauth_time - now.sec; if (sec < 0) sec = 0; eloop_register_timeout(sec, 0, pmksa_cache_reauth, pmksa, NULL); } }
static int gas_query_tx(struct gas_query *gas, struct gas_query_pending *query, struct wpabuf *req) { unsigned int wait_time; int res, prot = pmf_in_use(gas->wpa_s, query->addr); wpa_printf(MSG_DEBUG, "GAS: Send action frame to " MACSTR " len=%u " "freq=%d prot=%d", MAC2STR(query->addr), (unsigned int) wpabuf_len(req), query->freq, prot); if (prot) { u8 *categ = wpabuf_mhead_u8(req); *categ = WLAN_ACTION_PROTECTED_DUAL; } os_get_reltime(&query->last_oper); wait_time = 1000; if (gas->wpa_s->max_remain_on_chan && wait_time > gas->wpa_s->max_remain_on_chan) wait_time = gas->wpa_s->max_remain_on_chan; res = offchannel_send_action(gas->wpa_s, query->freq, query->addr, gas->wpa_s->own_addr, query->addr, wpabuf_head(req), wpabuf_len(req), wait_time, gas_query_tx_status, 0); if (res == 0) query->offchannel_tx_started = 1; return res; }
int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs, eloop_timeout_handler handler, void *eloop_data, void *user_data) { struct os_reltime now, requested, remaining; struct eloop_timeout *tmp; dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { if (tmp->handler == handler && tmp->eloop_data == eloop_data && tmp->user_data == user_data) { requested.sec = req_secs; requested.usec = req_usecs; os_get_reltime(&now); os_reltime_sub(&tmp->time, &now, &remaining); if (os_reltime_before(&remaining, &requested)) { eloop_cancel_timeout(handler, eloop_data, user_data); eloop_register_timeout(requested.sec, requested.usec, handler, eloop_data, user_data); return 1; } return 0; } } return -1; }
static void radius_client_update_timeout(struct radius_client_data *radius) { struct os_reltime now; os_time_t first; struct radius_msg_list *entry; eloop_cancel_timeout(radius_client_timer, radius, NULL); if (radius->msgs == NULL) { return; } first = 0; for (entry = radius->msgs; entry; entry = entry->next) { if (first == 0 || entry->next_try < first) first = entry->next_try; } os_get_reltime(&now); if (first < now.sec) first = now.sec; eloop_register_timeout(first - now.sec, 0, radius_client_timer, radius, NULL); hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_DEBUG, "Next RADIUS client retransmit in" " %ld seconds", (long int) (first - now.sec)); }
static void bgscan_learn_notify_signal_change(void *priv, int above, int current_signal, int current_noise, int current_txrate) { struct bgscan_learn_data *data = priv; int scan = 0; struct os_reltime now; if (data->short_interval == data->long_interval || data->signal_threshold == 0) return; wpa_printf(MSG_DEBUG, "bgscan learn: signal level changed " "(above=%d current_signal=%d current_noise=%d " "current_txrate=%d)", above, current_signal, current_noise, current_txrate); if (data->scan_interval == data->long_interval && !above) { wpa_printf(MSG_DEBUG, "bgscan learn: Start using short bgscan " "interval"); data->scan_interval = data->short_interval; os_get_reltime(&now); if (now.sec > data->last_bgscan.sec + 1) scan = 1; } else if (data->scan_interval == data->short_interval && above) { wpa_printf(MSG_DEBUG, "bgscan learn: Start using long bgscan " "interval"); data->scan_interval = data->long_interval; eloop_cancel_timeout(bgscan_learn_timeout, data, NULL); eloop_register_timeout(data->scan_interval, 0, bgscan_learn_timeout, data, NULL); } else if (!above) { /* * Signal dropped further 4 dB. Request a new scan if we have * not yet scanned in a while. */ os_get_reltime(&now); if (now.sec > data->last_bgscan.sec + 10) scan = 1; } if (scan) { wpa_printf(MSG_DEBUG, "bgscan learn: Trigger immediate scan"); eloop_cancel_timeout(bgscan_learn_timeout, data, NULL); eloop_register_timeout(0, 0, bgscan_learn_timeout, data, NULL); } }
static void ibss_rsn_handle_auth_1_of_2(struct ibss_rsn *ibss_rsn, struct ibss_rsn_peer *peer, const u8* addr) { wpa_printf(MSG_DEBUG, "RSN: IBSS RX Auth frame (SEQ 1) from " MACSTR, MAC2STR(addr)); if (peer && peer->authentication_status & (IBSS_RSN_SET_PTK_SUPP | IBSS_RSN_SET_PTK_AUTH)) { /* Clear the TK for this pair to allow recovery from the case * where the peer STA has restarted and lost its key while we * still have a pairwise key configured. */ wpa_printf(MSG_DEBUG, "RSN: Clear pairwise key for peer " MACSTR, MAC2STR(addr)); wpa_drv_set_key(ibss_rsn->wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL, 0); } if (peer && peer->authentication_status & IBSS_RSN_AUTH_EAPOL_BY_PEER) { if (peer->own_auth_tx.sec) { struct os_reltime now, diff; os_get_reltime(&now); os_reltime_sub(&now, &peer->own_auth_tx, &diff); if (diff.sec == 0 && diff.usec < 500000) { wpa_printf(MSG_DEBUG, "RSN: Skip IBSS reinit since only %u usec from own Auth frame TX", (int) diff.usec); goto skip_reinit; } } /* * A peer sent us an Authentication frame even though it already * started an EAPOL session. We should reinit state machines * here, but it's much more complicated than just deleting and * recreating the state machine */ wpa_printf(MSG_DEBUG, "RSN: IBSS Reinitializing station " MACSTR, MAC2STR(addr)); ibss_rsn_stop(ibss_rsn, addr); peer = NULL; } if (!peer) { peer = ibss_rsn_peer_init(ibss_rsn, addr); if (!peer) return; wpa_printf(MSG_DEBUG, "RSN: IBSS Auth started by peer " MACSTR, MAC2STR(addr)); } skip_reinit: /* reply with an Authentication frame now, before sending an EAPOL */ ibss_rsn_send_auth(ibss_rsn, addr, 2); /* no need to start another AUTH challenge in the other way.. */ ibss_rsn_peer_authenticated(ibss_rsn, peer, IBSS_RSN_AUTH_EAPOL_BY_US); }
/** * hostapd_acl_expire - ACL cache expiration callback * @hapd: struct hostapd_data * */ void hostapd_acl_expire(struct hostapd_data *hapd) { struct os_reltime now; os_get_reltime(&now); hostapd_acl_expire_cache(hapd, &now); hostapd_acl_expire_queries(hapd, &now); }
static int ms_from_time(struct os_reltime *last) { struct os_reltime now, res; os_get_reltime(&now); os_reltime_sub(&now, last, &res); return res.sec * 1000 + res.usec / 1000; }
/** * pmksa_cache_auth_add - Add a PMKSA cache entry * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() * @pmk: The new pairwise master key * @pmk_len: PMK length in bytes, usually PMK_LEN (32) * @pmkid: Calculated PMKID * @kck: Key confirmation key or %NULL if not yet derived * @kck_len: KCK length in bytes * @aa: Authenticator address * @spa: Supplicant address * @session_timeout: Session timeout * @eapol: Pointer to EAPOL state machine data * @akmp: WPA_KEY_MGMT_* used in key derivation * Returns: Pointer to the added PMKSA cache entry or %NULL on error * * This function create a PMKSA entry for a new PMK and adds it to the PMKSA * cache. If an old entry is already in the cache for the same Supplicant, * this entry will be replaced with the new entry. PMKID will be calculated * based on the PMK. */ struct rsn_pmksa_cache_entry * pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, const u8 *pmkid, const u8 *kck, size_t kck_len, const u8 *aa, const u8 *spa, int session_timeout, struct eapol_state_machine *eapol, int akmp) { struct rsn_pmksa_cache_entry *entry, *pos; struct os_reltime now; if (pmk_len > PMK_LEN_MAX) return NULL; if (wpa_key_mgmt_suite_b(akmp) && !kck) return NULL; entry = os_zalloc(sizeof(*entry)); if (entry == NULL) return NULL; os_memcpy(entry->pmk, pmk, pmk_len); entry->pmk_len = pmk_len; if (pmkid) os_memcpy(entry->pmkid, pmkid, PMKID_LEN); else if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid); else if (wpa_key_mgmt_suite_b(akmp)) rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid); else rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, wpa_key_mgmt_sha256(akmp)); os_get_reltime(&now); entry->expiration = now.sec; if (session_timeout > 0) entry->expiration += session_timeout; else entry->expiration += dot11RSNAConfigPMKLifetime; entry->akmp = akmp; os_memcpy(entry->spa, spa, ETH_ALEN); pmksa_cache_from_eapol_data(entry, eapol); /* Replace an old entry for the same STA (if found) with the new entry */ pos = pmksa_cache_auth_get(pmksa, spa, NULL); if (pos) pmksa_cache_free_entry(pmksa, pos); if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) { /* Remove the oldest entry to make room for the new entry */ wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache " "entry (for " MACSTR ") to make room for new one", MAC2STR(pmksa->pmksa->spa)); pmksa_cache_free_entry(pmksa, pmksa->pmksa); } pmksa_cache_link_entry(pmksa, entry); return entry; }
static void *bgscan_learn_init(struct wpa_supplicant *wpa_s, const char *params, const struct wpa_ssid *ssid) { struct bgscan_learn_data *data; data = os_zalloc(sizeof(*data)); if (data == NULL) { return NULL; } dl_list_init(&data->bss); data->wpa_s = wpa_s; data->ssid = ssid; if (bgscan_learn_get_params(data, params) < 0) { os_free(data->fname); os_free(data); return NULL; } if (data->short_interval <= 0) { data->short_interval = 30; } if (data->long_interval <= 0) { data->long_interval = 30; } if (bgscan_learn_load(data) < 0) { os_free(data->fname); os_free(data); return NULL; } wpa_printf(MSG_DEBUG, "bgscan learn: Signal strength threshold %d " "Short bgscan interval %d Long bgscan interval %d", data->signal_threshold, data->short_interval, data->long_interval); if (data->signal_threshold && wpa_drv_signal_monitor(wpa_s, data->signal_threshold, 4) < 0) { wpa_printf(MSG_ERROR, "bgscan learn: Failed to enable " "signal strength monitoring"); } data->supp_freqs = bgscan_learn_get_supp_freqs(wpa_s); data->scan_interval = data->short_interval; if (data->signal_threshold) { /* Poll for signal info to set initial scan interval */ struct wpa_signal_info siginfo; if (wpa_drv_signal_poll(wpa_s, &siginfo) == 0 && siginfo.current_signal >= data->signal_threshold) { data->scan_interval = data->long_interval; } } eloop_register_timeout(data->scan_interval, 0, bgscan_learn_timeout, data, NULL); /* * This function is called immediately after an association, so it is * reasonable to assume that a scan was completed recently. This makes * us skip an immediate new scan in cases where the current signal * level is below the bgscan threshold. */ os_get_reltime(&data->last_bgscan); return data; }
static void ap_list_timer(void *eloop_ctx, void *timeout_ctx) { struct hostapd_iface *iface = eloop_ctx; struct os_reltime now; struct ap_info *ap; int set_beacon = 0; eloop_register_timeout(10, 0, ap_list_timer, iface, NULL); if (!iface->ap_list) { return; } os_get_reltime(&now); while (iface->ap_list) { ap = iface->ap_list->prev; if (!os_reltime_expired(&now, &ap->last_beacon, iface->conf->ap_table_expiration_time)) { break; } ap_free_ap(iface, ap); } if (iface->olbc || iface->olbc_ht) { int olbc = 0; int olbc_ht = 0; ap = iface->ap_list; while (ap && (olbc == 0 || olbc_ht == 0)) { if (ap_list_beacon_olbc(iface, ap)) { olbc = 1; } if (!ap->ht_support) { olbc_ht = 1; } ap = ap->next; } if (!olbc && iface->olbc) { wpa_printf(MSG_DEBUG, "OLBC not detected anymore"); iface->olbc = 0; set_beacon++; } #ifdef CONFIG_IEEE80211N if (!olbc_ht && iface->olbc_ht) { wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore"); iface->olbc_ht = 0; hostapd_ht_operation_update(iface); set_beacon++; } #endif /* CONFIG_IEEE80211N */ } if (set_beacon) { ieee802_11_update_beacons(iface); } }
/** * hostapd_acl_expire - ACL cache expiration callback * @eloop_ctx: struct hostapd_data * * @timeout_ctx: Not used */ static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx) { struct hostapd_data *hapd = eloop_ctx; struct os_reltime now; os_get_reltime(&now); hostapd_acl_expire_cache(hapd, &now); hostapd_acl_expire_queries(hapd, &now); eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL); }
void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code, u16 reauth_delay, const char *url) { if (!wpa_sm_pmf_enabled(wpa_s->wpa)) { wpa_printf(MSG_DEBUG, "HS 2.0: Ignore deauthentication imminent notice since PMF was not enabled"); return; } wpa_msg(wpa_s, MSG_INFO, HS20_DEAUTH_IMMINENT_NOTICE "%u %u %s", code, reauth_delay, url); if (code == HS20_DEAUTH_REASON_CODE_BSS) { wpa_printf(MSG_DEBUG, "HS 2.0: Add BSS to blacklist"); wpa_blacklist_add(wpa_s, wpa_s->bssid); /* TODO: For now, disable full ESS since some drivers may not * support disabling per BSS. */ if (wpa_s->current_ssid) { struct os_reltime now; os_get_reltime(&now); if (now.sec + reauth_delay <= wpa_s->current_ssid->disabled_until.sec) return; wpa_printf(MSG_DEBUG, "HS 2.0: Disable network for %u seconds (BSS)", reauth_delay); wpa_s->current_ssid->disabled_until.sec = now.sec + reauth_delay; } } if (code == HS20_DEAUTH_REASON_CODE_ESS && wpa_s->current_ssid) { struct os_reltime now; os_get_reltime(&now); if (now.sec + reauth_delay <= wpa_s->current_ssid->disabled_until.sec) return; wpa_printf(MSG_DEBUG, "HS 2.0: Disable network for %u seconds", reauth_delay); wpa_s->current_ssid->disabled_until.sec = now.sec + reauth_delay; } }
/** * hostapd_acl_expire - ACL cache expiration callback * @eloop_ctx: struct hostapd_data * * @timeout_ctx: Not used */ static void hostapd_acl_expire(void *eloop_ctx, void *timeout_ctx) { struct hostapd_data *hapd = eloop_ctx; struct os_reltime now; wpa_printf(MSG_INFO, "WGTT: %s %s():%d\n", __FILE__, __FUNCTION__, __LINE__); os_get_reltime(&now); hostapd_acl_expire_cache(hapd, &now); hostapd_acl_expire_queries(hapd, &now); eloop_register_timeout(10, 0, hostapd_acl_expire, hapd, NULL); }