void hostapd_2040_coex_action(struct hostapd_data *hapd, const struct ieee80211_mgmt *mgmt, size_t len) { struct hostapd_iface *iface = hapd->iface; struct ieee80211_2040_bss_coex_ie *bc_ie; struct ieee80211_2040_intol_chan_report *ic_report; int is_ht40_allowed = 1; int i; const u8 *start = (const u8 *) mgmt; const u8 *data = start + IEEE80211_HDRLEN + 2; hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "hostapd_public_action - action=%d", mgmt->u.action.u.public_action.action); if (!(iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) return; if (len < IEEE80211_HDRLEN + 2 + sizeof(*bc_ie)) return; bc_ie = (struct ieee80211_2040_bss_coex_ie *) data; if (bc_ie->element_id != WLAN_EID_20_40_BSS_COEXISTENCE || bc_ie->length < 1) { wpa_printf(MSG_DEBUG, "Unexpected IE (%u,%u) in coex report", bc_ie->element_id, bc_ie->length); return; } if (len < IEEE80211_HDRLEN + 2 + 2 + bc_ie->length) return; data += 2 + bc_ie->length; wpa_printf(MSG_DEBUG, "20/40 BSS Coexistence Information field: 0x%x", bc_ie->coex_param); if (bc_ie->coex_param & WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ) { hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "20 MHz BSS width request bit is set in BSS coexistence information field"); is_ht40_allowed = 0; } if (bc_ie->coex_param & WLAN_20_40_BSS_COEX_40MHZ_INTOL) { hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "40 MHz intolerant bit is set in BSS coexistence information field"); is_ht40_allowed = 0; } if (start + len - data >= 3 && data[0] == WLAN_EID_20_40_BSS_INTOLERANT && data[1] >= 1) { u8 ielen = data[1]; if (ielen > start + len - data - 2) return; ic_report = (struct ieee80211_2040_intol_chan_report *) data; wpa_printf(MSG_DEBUG, "20/40 BSS Intolerant Channel Report: Operating Class %u", ic_report->op_class); /* Go through the channel report to find any BSS there in the * affected channel range */ for (i = 0; i < ielen - 1; i++) { u8 chan = ic_report->variable[i]; if (is_40_allowed(iface, chan)) continue; hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, "20_40_INTOLERANT channel %d reported", chan); is_ht40_allowed = 0; } } wpa_printf(MSG_DEBUG, "is_ht40_allowed=%d num_sta_ht40_intolerant=%d", is_ht40_allowed, iface->num_sta_ht40_intolerant); if (!is_ht40_allowed && (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) { if (iface->conf->secondary_channel) { hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "Switching to 20 MHz operation"); iface->conf->secondary_channel = 0; ieee802_11_set_beacons(iface); } if (!iface->num_sta_ht40_intolerant && iface->conf->obss_interval) { unsigned int delay_time; delay_time = OVERLAPPING_BSS_TRANS_DELAY_FACTOR * iface->conf->obss_interval; eloop_cancel_timeout(ap_ht2040_timeout, hapd->iface, NULL); eloop_register_timeout(delay_time, 0, ap_ht2040_timeout, hapd->iface, NULL); wpa_printf(MSG_DEBUG, "Reschedule HT 20/40 timeout to occur in %u seconds", delay_time); } } }
int main(int argc, char *argv[]) { struct hapd_interfaces interfaces; int ret = 1; size_t i, j; int c, debug = 0, daemonize = 0; char *pid_file = NULL; const char *log_file = NULL; const char *entropy_file = NULL; char **bss_config = NULL, **tmp_bss; size_t num_bss_configs = 0; #ifdef CONFIG_DEBUG_LINUX_TRACING int enable_trace_dbg = 0; #endif /* CONFIG_DEBUG_LINUX_TRACING */ if (os_program_init()) return -1; wpa_printf(MSG_INFO, "Pavan edit: os program initialized"); os_memset(&interfaces, 0, sizeof(interfaces)); interfaces.reload_config = hostapd_reload_config; interfaces.config_read_cb = hostapd_config_read; interfaces.for_each_interface = hostapd_for_each_interface; interfaces.ctrl_iface_init = hostapd_ctrl_iface_init; interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit; interfaces.driver_init = hostapd_driver_init; interfaces.global_iface_path = NULL; interfaces.global_iface_name = NULL; interfaces.global_ctrl_sock = -1; interfaces.global_ctrl_dst = NULL; for (;;) { c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:vg:G:"); if (c < 0) break; switch (c) { case 'h': usage(); break; case 'd': debug++; if (wpa_debug_level > 0) wpa_debug_level--; break; case 'B': daemonize++; break; case 'e': entropy_file = optarg; break; case 'f': log_file = optarg; break; case 'K': wpa_debug_show_keys++; break; case 'P': os_free(pid_file); pid_file = os_rel2abs_path(optarg); break; case 't': wpa_debug_timestamp++; break; #ifdef CONFIG_DEBUG_LINUX_TRACING case 'T': enable_trace_dbg = 1; break; #endif /* CONFIG_DEBUG_LINUX_TRACING */ case 'v': show_version(); exit(1); break; case 'g': if (hostapd_get_global_ctrl_iface(&interfaces, optarg)) return -1; break; case 'G': if (hostapd_get_ctrl_iface_group(&interfaces, optarg)) return -1; break; case 'b': tmp_bss = os_realloc_array(bss_config, num_bss_configs + 1, sizeof(char *)); if (tmp_bss == NULL) goto out; bss_config = tmp_bss; bss_config[num_bss_configs++] = optarg; break; #ifdef CONFIG_WPS case 'u': return gen_uuid(optarg); #endif /* CONFIG_WPS */ default: usage(); break; } } if (optind == argc && interfaces.global_iface_path == NULL && num_bss_configs == 0) usage(); wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb); if (log_file) wpa_debug_open_file(log_file); else wpa_debug_setup_stdout(); #ifdef CONFIG_DEBUG_LINUX_TRACING if (enable_trace_dbg) { int tret = wpa_debug_open_linux_tracing(); if (tret) { wpa_printf(MSG_ERROR, "Failed to enable trace logging"); return -1; } } #endif /* CONFIG_DEBUG_LINUX_TRACING */ interfaces.count = argc - optind; if (interfaces.count || num_bss_configs) { interfaces.iface = os_calloc(interfaces.count + num_bss_configs, sizeof(struct hostapd_iface *)); if (interfaces.iface == NULL) { wpa_printf(MSG_ERROR, "malloc failed"); return -1; } } if (hostapd_global_init(&interfaces, entropy_file)) { wpa_printf(MSG_ERROR, "Failed to initialize global context"); return -1; } eloop_register_timeout(HOSTAPD_CLEANUP_INTERVAL, 0, hostapd_periodic, &interfaces, NULL); /*Timeout event is triggered after 5 seconds of start of hostapd. The parameters are pulled after the event is triggered in the handler*/ eloop_register_timeout(2, 0, get_params_handler, &interfaces, NULL); if (fst_global_init()) { wpa_printf(MSG_ERROR, "Failed to initialize global FST context"); goto out; } #if defined(CONFIG_FST) && defined(CONFIG_CTRL_IFACE) if (!fst_global_add_ctrl(fst_ctrl_cli)) wpa_printf(MSG_WARNING, "Failed to add CLI FST ctrl"); #endif /* CONFIG_FST && CONFIG_CTRL_IFACE */ /* Allocate and parse configuration for full interface files */ wpa_printf(MSG_INFO, "Pavan edit: interfaces.count = %d",interfaces.count); for (i = 0; i < interfaces.count; i++) { interfaces.iface[i] = hostapd_interface_init(&interfaces, argv[optind + i], debug); if (!interfaces.iface[i]) { wpa_printf(MSG_ERROR, "Failed to initialize interface"); goto out; } } wpa_printf(MSG_INFO, "Pavan edit: num_bss_configs = %d", num_bss_configs); /* Allocate and parse configuration for per-BSS files */ for (i = 0; i < num_bss_configs; i++) { struct hostapd_iface *iface; char *fname; wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]); fname = os_strchr(bss_config[i], ':'); if (fname == NULL) { wpa_printf(MSG_ERROR, "Invalid BSS config identifier '%s'", bss_config[i]); goto out; } *fname++ = '\0'; iface = hostapd_interface_init_bss(&interfaces, bss_config[i], fname, debug); if (iface == NULL) goto out; for (j = 0; j < interfaces.count; j++) { if (interfaces.iface[j] == iface) break; } if (j == interfaces.count) { struct hostapd_iface **tmp; tmp = os_realloc_array(interfaces.iface, interfaces.count + 1, sizeof(struct hostapd_iface *)); if (tmp == NULL) { hostapd_interface_deinit_free(iface); goto out; } interfaces.iface = tmp; interfaces.iface[interfaces.count++] = iface; } } /* * Enable configured interfaces. Depending on channel configuration, * this may complete full initialization before returning or use a * callback mechanism to complete setup in case of operations like HT * co-ex scans, ACS, or DFS are needed to determine channel parameters. * In such case, the interface will be enabled from eloop context within * hostapd_global_run(). */ interfaces.terminate_on_error = interfaces.count; for (i = 0; i < interfaces.count; i++) { wpa_printf(MSG_INFO, "Pavan edit: initializing driver and setting up interface"); if (hostapd_driver_init(interfaces.iface[i]) || hostapd_setup_interface(interfaces.iface[i])) { wpa_printf(MSG_INFO, "Pavan edit: goto out called, hostapd_global_ctrl_iface_deinit called"); goto out; } } hostapd_global_ctrl_iface_init(&interfaces); if (hostapd_global_run(&interfaces, daemonize, pid_file)) { wpa_printf(MSG_ERROR, "Failed to start eloop"); goto out; } ret = 0; out: hostapd_global_ctrl_iface_deinit(&interfaces); /* Deinitialize all interfaces */ for (i = 0; i < interfaces.count; i++) { if (!interfaces.iface[i]) continue; interfaces.iface[i]->driver_ap_teardown = !!(interfaces.iface[i]->drv_flags & WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); hostapd_interface_deinit_free(interfaces.iface[i]); } os_free(interfaces.iface); eloop_cancel_timeout(hostapd_periodic, &interfaces, NULL); hostapd_global_deinit(pid_file); os_free(pid_file); if (log_file) wpa_debug_close_file(); wpa_debug_close_linux_tracing(); os_free(bss_config); fst_global_deinit(); os_program_deinit(); return ret; }
/** * wpa_supplicant_cancel_scan - Cancel a scheduled scan request * @wpa_s: Pointer to wpa_supplicant data * * This function is used to cancel a scan request scheduled with * wpa_supplicant_req_scan(). */ void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) { wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request"); eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); wpas_p2p_continue_after_scan(wpa_s); }
void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, const u8 *sa, const u8 *data, size_t slen, u8 dialog_token) { const u8 *pos = data; u8 subtype; struct wpa_bss_anqp *anqp = NULL; int ret; if (slen < 2) return; if (bss) anqp = bss->anqp; subtype = *pos++; slen--; pos++; /* Reserved */ slen--; switch (subtype) { case HS20_STYPE_CAPABILITY_LIST: wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR " HS Capability List", MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "HS Capability List", pos, slen); if (anqp) { wpabuf_free(anqp->hs20_capability_list); anqp->hs20_capability_list = wpabuf_alloc_copy(pos, slen); } break; case HS20_STYPE_OPERATOR_FRIENDLY_NAME: wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR " Operator Friendly Name", MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "oper friendly name", pos, slen); if (anqp) { wpabuf_free(anqp->hs20_operator_friendly_name); anqp->hs20_operator_friendly_name = wpabuf_alloc_copy(pos, slen); } break; case HS20_STYPE_WAN_METRICS: wpa_hexdump(MSG_DEBUG, "WAN Metrics", pos, slen); if (slen < 13) { wpa_dbg(wpa_s, MSG_DEBUG, "HS 2.0: Too short WAN " "Metrics value from " MACSTR, MAC2STR(sa)); break; } wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR " WAN Metrics %02x:%u:%u:%u:%u:%u", MAC2STR(sa), pos[0], WPA_GET_LE32(pos + 1), WPA_GET_LE32(pos + 5), pos[9], pos[10], WPA_GET_LE16(pos + 11)); if (anqp) { wpabuf_free(anqp->hs20_wan_metrics); anqp->hs20_wan_metrics = wpabuf_alloc_copy(pos, slen); } break; case HS20_STYPE_CONNECTION_CAPABILITY: wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR " Connection Capability", MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "conn capability", pos, slen); if (anqp) { wpabuf_free(anqp->hs20_connection_capability); anqp->hs20_connection_capability = wpabuf_alloc_copy(pos, slen); } break; case HS20_STYPE_OPERATING_CLASS: wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR " Operating Class", MAC2STR(sa)); wpa_hexdump_ascii(MSG_DEBUG, "Operating Class", pos, slen); if (anqp) { wpabuf_free(anqp->hs20_operating_class); anqp->hs20_operating_class = wpabuf_alloc_copy(pos, slen); } break; case HS20_STYPE_OSU_PROVIDERS_LIST: wpa_msg(wpa_s, MSG_INFO, RX_HS20_ANQP MACSTR " OSU Providers list", MAC2STR(sa)); wpa_s->num_prov_found++; if (anqp) { wpabuf_free(anqp->hs20_osu_providers_list); anqp->hs20_osu_providers_list = wpabuf_alloc_copy(pos, slen); } break; case HS20_STYPE_ICON_BINARY_FILE: ret = hs20_process_icon_binary_file(wpa_s, sa, pos, slen, dialog_token); if (wpa_s->fetch_osu_icon_in_progress) { hs20_osu_icon_fetch_result(wpa_s, ret); eloop_cancel_timeout(hs20_continue_icon_fetch, wpa_s, NULL); eloop_register_timeout(0, 0, hs20_continue_icon_fetch, wpa_s, NULL); } break; default: wpa_printf(MSG_DEBUG, "HS20: Unsupported subtype %u", subtype); break; } }
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) { int set_beacon = 0; accounting_sta_stop(hapd, sta); /* just in case */ ap_sta_set_authorized(hapd, sta, 0); if (sta->flags & WLAN_STA_WDS) hostapd_set_wds_sta(hapd, sta->addr, sta->aid, 0); if (!(sta->flags & WLAN_STA_PREAUTH)) hostapd_drv_sta_remove(hapd, sta->addr); ap_sta_hash_del(hapd, sta); ap_sta_list_del(hapd, sta); if (sta->aid > 0) hapd->sta_aid[(sta->aid - 1) / 32] &= ~BIT((sta->aid - 1) % 32); hapd->num_sta--; if (sta->nonerp_set) { sta->nonerp_set = 0; hapd->iface->num_sta_non_erp--; if (hapd->iface->num_sta_non_erp == 0) set_beacon++; } if (sta->no_short_slot_time_set) { sta->no_short_slot_time_set = 0; hapd->iface->num_sta_no_short_slot_time--; if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->iface->num_sta_no_short_slot_time == 0) set_beacon++; } if (sta->no_short_preamble_set) { sta->no_short_preamble_set = 0; hapd->iface->num_sta_no_short_preamble--; if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->iface->num_sta_no_short_preamble == 0) set_beacon++; } if (sta->no_ht_gf_set) { sta->no_ht_gf_set = 0; hapd->iface->num_sta_ht_no_gf--; } if (sta->no_ht_set) { sta->no_ht_set = 0; hapd->iface->num_sta_no_ht--; } if (sta->ht_20mhz_set) { sta->ht_20mhz_set = 0; hapd->iface->num_sta_ht_20mhz--; } #ifdef CONFIG_P2P if (sta->no_p2p_set) { sta->no_p2p_set = 0; hapd->num_sta_no_p2p--; if (hapd->num_sta_no_p2p == 0) hostapd_p2p_non_p2p_sta_disconnected(hapd); } #endif /* CONFIG_P2P */ #if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N) if (hostapd_ht_operation_update(hapd->iface) > 0) set_beacon++; #endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ if (set_beacon) ieee802_11_set_beacons(hapd->iface); eloop_cancel_timeout(ap_handle_timer, hapd, sta); eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); ieee802_1x_free_station(sta); wpa_auth_sta_deinit(sta->wpa_sm); rsn_preauth_free_station(hapd, sta); #ifndef CONFIG_NO_RADIUS radius_client_flush_auth(hapd->radius, sta->addr); #endif /* CONFIG_NO_RADIUS */ os_free(sta->last_assoc_req); os_free(sta->challenge); #ifdef CONFIG_IEEE80211W os_free(sta->sa_query_trans_id); eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P p2p_group_notif_disassoc(hapd->p2p_group, sta->addr); #endif /* CONFIG_P2P */ wpabuf_free(sta->wps_ie); wpabuf_free(sta->p2p_ie); os_free(sta->ht_capabilities); os_free(sta); }
/** * offchannel_deinit - Deinit off-channel operations * @wpa_s: Pointer to wpa_supplicant data * * This function is used to free up any allocated resources for off-channel * operations. */ void offchannel_deinit(struct wpa_supplicant *wpa_s) { offchannel_clear_pending_action_tx(wpa_s); eloop_cancel_timeout(wpas_send_action_cb, wpa_s, NULL); }
/** * wpa_supplicant_cancel_scan - Cancel a scheduled scan request * @wpa_s: Pointer to wpa_supplicant data * * This function is used to cancel a scan request scheduled with * wpa_supplicant_req_scan(). */ void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) { wpa_msg(wpa_s, MSG_DEBUG, "Cancelling scan request"); eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); }
static int bgscan_learn_notify_scan(void *priv, struct wpa_scan_results *scan_res) { struct bgscan_learn_data *data = priv; size_t i, j; #define MAX_BSS 50 u8 bssid[MAX_BSS * ETH_ALEN]; size_t num_bssid = 0; wpa_printf(MSG_DEBUG, "bgscan learn: scan result notification"); eloop_cancel_timeout(bgscan_learn_timeout, data, NULL); eloop_register_timeout(data->scan_interval, 0, bgscan_learn_timeout, data, NULL); for (i = 0; i < scan_res->num; i++) { struct wpa_scan_res *res = scan_res->res[i]; if (!bgscan_learn_bss_match(data, res)) continue; if (num_bssid < MAX_BSS) { os_memcpy(bssid + num_bssid * ETH_ALEN, res->bssid, ETH_ALEN); num_bssid++; } } wpa_printf(MSG_DEBUG, "bgscan learn: %u matching BSSes in scan " "results", (unsigned int) num_bssid); for (i = 0; i < scan_res->num; i++) { struct wpa_scan_res *res = scan_res->res[i]; struct bgscan_learn_bss *bss; if (!bgscan_learn_bss_match(data, res)) continue; bss = bgscan_learn_get_bss(data, res->bssid); if (bss && bss->freq != res->freq) { wpa_printf(MSG_DEBUG, "bgscan learn: Update BSS " MACSTR " freq %d -> %d", MAC2STR(res->bssid), bss->freq, res->freq); bss->freq = res->freq; } else if (!bss) { wpa_printf(MSG_DEBUG, "bgscan learn: Add BSS " MACSTR " freq=%d", MAC2STR(res->bssid), res->freq); bss = os_zalloc(sizeof(*bss)); if (!bss) continue; os_memcpy(bss->bssid, res->bssid, ETH_ALEN); bss->freq = res->freq; dl_list_add(&data->bss, &bss->list); } for (j = 0; j < num_bssid; j++) { u8 *addr = bssid + j * ETH_ALEN; bgscan_learn_add_neighbor(bss, addr); } } /* * A more advanced bgscan could process scan results internally, select * the BSS and request roam if needed. This sample uses the existing * BSS/ESS selection routine. Change this to return 1 if selection is * done inside the bgscan module. */ return 0; }
static void connection_setup_remove_timeout(struct ctrl_iface_dbus_priv *iface, DBusTimeout *timeout) { eloop_cancel_timeout(process_timeout, iface, timeout); dbus_timeout_set_data(timeout, NULL, NULL); }
/* httpread_read_handler -- called when socket ready to read * * Note: any extra data we read past end of transmitted file is ignored; * if we were to support keeping connections open for multiple files then * this would have to be addressed. */ static void httpread_read_handler(int sd, void *eloop_ctx, void *sock_ctx) { struct httpread *h = sock_ctx; int nread; char *rbp; /* pointer into read buffer */ char *hbp; /* pointer into header buffer */ char *bbp; /* pointer into body buffer */ char readbuf[HTTPREAD_READBUF_SIZE]; /* temp use to read into */ if (httpread_debug >= 20) wpa_printf(MSG_DEBUG, "ENTER httpread_read_handler(%p)", h); /* read some at a time, then search for the interal * boundaries between header and data and etc. */ nread = read(h->sd, readbuf, sizeof(readbuf)); if (nread < 0) goto bad; if (nread == 0) { /* end of transmission... this may be normal * or may be an error... in some cases we can't * tell which so we must assume it is normal then. */ if (!h->got_hdr) { /* Must at least have completed header */ wpa_printf(MSG_DEBUG, "httpread premature eof(%p)", h); goto bad; } if (h->chunked || h->got_content_length) { /* Premature EOF; e.g. dropped connection */ wpa_printf(MSG_DEBUG, "httpread premature eof(%p) %d/%d", h, h->body_nbytes, h->content_length); goto bad; } /* No explicit length, hopefully we have all the data * although dropped connections can cause false * end */ if (httpread_debug >= 10) wpa_printf(MSG_DEBUG, "httpread ok eof(%p)", h); h->got_body = 1; goto got_file; } rbp = readbuf; /* Header consists of text lines (terminated by both CR and LF) * and an empty line (CR LF only). */ if (!h->got_hdr) { hbp = h->hdr + h->hdr_nbytes; /* add to headers until: * -- we run out of data in read buffer * -- or, we run out of header buffer room * -- or, we get double CRLF in headers */ for (;;) { if (nread == 0) goto get_more; if (h->hdr_nbytes == HTTPREAD_HEADER_MAX_SIZE) { goto bad; } *hbp++ = *rbp++; nread--; h->hdr_nbytes++; if (h->hdr_nbytes >= 4 && hbp[-1] == '\n' && hbp[-2] == '\r' && hbp[-3] == '\n' && hbp[-4] == '\r' ) { h->got_hdr = 1; *hbp = 0; /* null terminate */ break; } } /* here we've just finished reading the header */ if (httpread_hdr_analyze(h)) { wpa_printf(MSG_DEBUG, "httpread bad hdr(%p)", h); goto bad; } if (h->max_bytes == 0) { if (httpread_debug >= 10) wpa_printf(MSG_DEBUG, "httpread no body hdr end(%p)", h); goto got_file; } if (h->got_content_length && h->content_length == 0) { if (httpread_debug >= 10) wpa_printf(MSG_DEBUG, "httpread zero content length(%p)", h); goto got_file; } } /* Certain types of requests never have data and so * must be specially recognized. */ if (!os_strncasecmp(h->hdr, "SUBSCRIBE", 9) || !os_strncasecmp(h->hdr, "UNSUBSCRIBE", 11) || !os_strncasecmp(h->hdr, "HEAD", 4) || !os_strncasecmp(h->hdr, "GET", 3)) { if (!h->got_body) { if (httpread_debug >= 10) wpa_printf(MSG_DEBUG, "httpread NO BODY for sp. type"); } h->got_body = 1; goto got_file; } /* Data can be just plain binary data, or if "chunked" * consists of chunks each with a header, ending with * an ending header. */ if (!h->got_body) { /* Here to get (more of) body */ /* ensure we have enough room for worst case for body * plus a null termination character */ if (h->body_alloc_nbytes < (h->body_nbytes + nread + 1)) { char *new_body; int new_alloc_nbytes; if (h->body_nbytes >= h->max_bytes) goto bad; new_alloc_nbytes = h->body_alloc_nbytes + HTTPREAD_BODYBUF_DELTA; /* For content-length case, the first time * through we allocate the whole amount * we need. */ if (h->got_content_length && new_alloc_nbytes < (h->content_length + 1)) new_alloc_nbytes = h->content_length + 1; if ((new_body = os_realloc(h->body, new_alloc_nbytes)) == NULL) goto bad; h->body = new_body; h->body_alloc_nbytes = new_alloc_nbytes; } /* add bytes */ bbp = h->body + h->body_nbytes; for (;;) { int ncopy; /* See if we need to stop */ if (h->chunked && h->in_chunk_data == 0) { /* in chunk header */ char *cbp = h->body + h->chunk_start; if (bbp-cbp >= 2 && bbp[-2] == '\r' && bbp[-1] == '\n') { /* end of chunk hdr line */ /* hdr line consists solely * of a hex numeral and CFLF */ if (!isxdigit(*cbp)) goto bad; h->chunk_size = strtoul(cbp, NULL, 16); /* throw away chunk header * so we have only real data */ h->body_nbytes = h->chunk_start; bbp = cbp; if (h->chunk_size == 0) { /* end of chunking */ /* trailer follows */ h->in_trailer = 1; if (httpread_debug >= 20) wpa_printf( MSG_DEBUG, "httpread end chunks(%p)", h); break; } h->in_chunk_data = 1; /* leave chunk_start alone */ } } else if (h->chunked) { /* in chunk data */ if ((h->body_nbytes - h->chunk_start) == (h->chunk_size + 2)) { /* end of chunk reached, * new chunk starts */ /* check chunk ended w/ CRLF * which we'll throw away */ if (bbp[-1] == '\n' && bbp[-2] == '\r') { } else goto bad; h->body_nbytes -= 2; bbp -= 2; h->chunk_start = h->body_nbytes; h->in_chunk_data = 0; h->chunk_size = 0; /* just in case */ } } else if (h->got_content_length && h->body_nbytes >= h->content_length) { h->got_body = 1; if (httpread_debug >= 10) wpa_printf( MSG_DEBUG, "httpread got content(%p)", h); goto got_file; } if (nread <= 0) break; /* Now transfer. Optimize using memcpy where we can. */ if (h->chunked && h->in_chunk_data) { /* copy up to remainder of chunk data * plus the required CR+LF at end */ ncopy = (h->chunk_start + h->chunk_size + 2) - h->body_nbytes; } else if (h->chunked) { /*in chunk header -- don't optimize */ *bbp++ = *rbp++; nread--; h->body_nbytes++; continue; } else if (h->got_content_length) { ncopy = h->content_length - h->body_nbytes; } else { ncopy = nread; } /* Note: should never be 0 */ if (ncopy > nread) ncopy = nread; os_memcpy(bbp, rbp, ncopy); bbp += ncopy; h->body_nbytes += ncopy; rbp += ncopy; nread -= ncopy; } /* body copy loop */ } /* !got_body */ if (h->chunked && h->in_trailer) { /* If "chunked" then there is always a trailer, * consisting of zero or more non-empty lines * ending with CR LF and then an empty line w/ CR LF. * We do NOT support trailers except to skip them -- * this is supported (generally) by the http spec. */ bbp = h->body + h->body_nbytes; for (;;) { int c; if (nread <= 0) break; c = *rbp++; nread--; switch (h->trailer_state) { case trailer_line_begin: if (c == '\r') h->trailer_state = trailer_empty_cr; else h->trailer_state = trailer_nonempty; break; case trailer_empty_cr: /* end empty line */ if (c == '\n') { h->trailer_state = trailer_line_begin; h->in_trailer = 0; if (httpread_debug >= 10) wpa_printf( MSG_DEBUG, "httpread got content(%p)", h); h->got_body = 1; goto got_file; } h->trailer_state = trailer_nonempty; break; case trailer_nonempty: if (c == '\r') h->trailer_state = trailer_nonempty_cr; break; case trailer_nonempty_cr: if (c == '\n') h->trailer_state = trailer_line_begin; else h->trailer_state = trailer_nonempty; break; } } } goto get_more; bad: /* Error */ wpa_printf(MSG_DEBUG, "httpread read/parse failure (%p)", h); (*h->cb)(h, h->cookie, HTTPREAD_EVENT_ERROR); return; get_more: return; got_file: if (httpread_debug >= 10) wpa_printf(MSG_DEBUG, "httpread got file %d bytes type %d", h->body_nbytes, h->hdr_type); /* Null terminate for convenience of some applications */ if (h->body) h->body[h->body_nbytes] = 0; /* null terminate */ h->got_file = 1; /* Assume that we do NOT support keeping connection alive, * and just in case somehow we don't get destroyed right away, * unregister now. */ if (h->sd_registered) eloop_unregister_sock(h->sd, EVENT_TYPE_READ); h->sd_registered = 0; /* The application can destroy us whenever they feel like... * cancel timeout. */ if (h->to_registered) eloop_cancel_timeout(httpread_timeout_handler, NULL, h); h->to_registered = 0; (*h->cb)(h, h->cookie, HTTPREAD_EVENT_FILE_READY); }
void hostapd_deinit_ht(struct hostapd_iface *iface) { eloop_cancel_timeout(hostapd_restore_40mhz, iface, NULL); }
static int radius_change_server(struct radius_client_data *radius, struct hostapd_radius_server *nserv, struct hostapd_radius_server *oserv, int sock, int sock6, int auth) { struct sockaddr_in serv; #ifdef CONFIG_IPV6 struct sockaddr_in6 serv6; #endif /* CONFIG_IPV6 */ struct sockaddr *addr; socklen_t addrlen; char abuf[50]; int sel_sock; struct radius_msg_list *entry; hostapd_logger(radius->ctx, NULL, HOSTAPD_MODULE_RADIUS, HOSTAPD_LEVEL_INFO, "%s server %s:%d", auth ? "Authentication" : "Accounting", hostapd_ip_txt(&nserv->addr, abuf, sizeof(abuf)), nserv->port); if (!oserv || nserv->shared_secret_len != oserv->shared_secret_len || os_memcmp(nserv->shared_secret, oserv->shared_secret, nserv->shared_secret_len) != 0) { /* Pending RADIUS packets used different shared secret, so * they need to be modified. Update accounting message * authenticators here. Authentication messages are removed * since they would require more changes and the new RADIUS * server may not be prepared to receive them anyway due to * missing state information. Client will likely retry * authentication, so this should not be an issue. */ if (auth) radius_client_flush(radius, 1); else { radius_client_update_acct_msgs( radius, nserv->shared_secret, nserv->shared_secret_len); } } /* Reset retry counters for the new server */ for (entry = radius->msgs; entry; entry = entry->next) { if ((auth && entry->msg_type != RADIUS_AUTH) || (!auth && entry->msg_type != RADIUS_ACCT)) continue; entry->next_try = entry->first_try + RADIUS_CLIENT_FIRST_WAIT; entry->attempts = 0; entry->next_wait = RADIUS_CLIENT_FIRST_WAIT * 2; } if (radius->msgs) { eloop_cancel_timeout(radius_client_timer, radius, NULL); eloop_register_timeout(RADIUS_CLIENT_FIRST_WAIT, 0, radius_client_timer, radius, NULL); } switch (nserv->addr.af) { case AF_INET: os_memset(&serv, 0, sizeof(serv)); serv.sin_family = AF_INET; serv.sin_addr.s_addr = nserv->addr.u.v4.s_addr; serv.sin_port = htons(nserv->port); addr = (struct sockaddr *) &serv; addrlen = sizeof(serv); sel_sock = sock; break; #ifdef CONFIG_IPV6 case AF_INET6: os_memset(&serv6, 0, sizeof(serv6)); serv6.sin6_family = AF_INET6; os_memcpy(&serv6.sin6_addr, &nserv->addr.u.v6, sizeof(struct in6_addr)); serv6.sin6_port = htons(nserv->port); addr = (struct sockaddr *) &serv6; addrlen = sizeof(serv6); sel_sock = sock6; break; #endif /* CONFIG_IPV6 */ default: return -1; } if (connect(sel_sock, addr, addrlen) < 0) { perror("connect[radius]"); return -1; } if (auth) radius->auth_sock = sel_sock; else radius->acct_sock = sel_sock; return 0; }
void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable) { const u8 *ie; struct wpa_bss *bss = wpa_s->current_bss; struct wpa_ssid *ssid = wpa_s->current_ssid; struct hostapd_hw_modes *hw_mode = NULL; int i; eloop_cancel_timeout(sme_obss_scan_timeout, wpa_s, NULL); wpa_s->sme.sched_obss_scan = 0; if (!enable) return; /* * Schedule OBSS scan if driver is using station SME in wpa_supplicant * or it expects OBSS scan to be performed by wpa_supplicant. */ if (!((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) || (wpa_s->drv_flags & WPA_DRIVER_FLAGS_OBSS_SCAN)) || ssid == NULL || ssid->mode != IEEE80211_MODE_INFRA) return; if (!wpa_s->hw.modes) return; /* only HT caps in 11g mode are relevant */ for (i = 0; i < wpa_s->hw.num_modes; i++) { hw_mode = &wpa_s->hw.modes[i]; if (hw_mode->mode == HOSTAPD_MODE_IEEE80211G) break; } /* Driver does not support HT40 for 11g or doesn't have 11g. */ if (i == wpa_s->hw.num_modes || !hw_mode || !(hw_mode->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) return; if (bss == NULL || bss->freq < 2400 || bss->freq > 2500) return; /* Not associated on 2.4 GHz band */ /* Check whether AP supports HT40 */ ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_HT_CAP); if (!ie || ie[1] < 2 || !(WPA_GET_LE16(ie + 2) & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) return; /* AP does not support HT40 */ ie = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS); if (!ie || ie[1] < 14) return; /* AP does not request OBSS scans */ wpa_s->sme.obss_scan_int = WPA_GET_LE16(ie + 6); if (wpa_s->sme.obss_scan_int < 10) { wpa_printf(MSG_DEBUG, "SME: Invalid OBSS Scan Interval %u " "replaced with the minimum 10 sec", wpa_s->sme.obss_scan_int); wpa_s->sme.obss_scan_int = 10; } wpa_printf(MSG_DEBUG, "SME: OBSS Scan Interval %u sec", wpa_s->sme.obss_scan_int); eloop_register_timeout(wpa_s->sme.obss_scan_int, 0, sme_obss_scan_timeout, wpa_s, NULL); }
void offchannel_deinit(struct wpa_supplicant *wpa_s) { wpabuf_free(wpa_s->pending_action_tx); wpa_s->pending_action_tx = NULL; eloop_cancel_timeout(wpas_send_action_cb, wpa_s, NULL); }
static void eap_wsc_process(struct eap_sm *sm, void *priv, struct wpabuf *respData) { struct eap_wsc_data *data = priv; const u8 *start, *pos, *end; size_t len; u8 op_code, flags; u16 message_length = 0; enum wps_process_res res; struct wpabuf tmpbuf; eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); if (data->ext_reg_timeout) { eap_wsc_state(data, FAIL); return; } pos = eap_hdr_validate(EAP_VENDOR_WFA, EAP_VENDOR_TYPE_WSC, respData, &len); if (pos == NULL || len < 2) return; /* Should not happen; message already verified */ start = pos; end = start + len; op_code = *pos++; flags = *pos++; if (flags & WSC_FLAGS_LF) { if (end - pos < 2) { wpa_printf(MSG_DEBUG, "EAP-WSC: Message underflow"); return; } message_length = WPA_GET_BE16(pos); pos += 2; if (message_length < end - pos) { wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid Message " "Length"); return; } } wpa_printf(MSG_DEBUG, "EAP-WSC: Received packet: Op-Code %d " "Flags 0x%x Message Length %d", op_code, flags, message_length); if (data->state == WAIT_FRAG_ACK) { if (op_code != WSC_FRAG_ACK) { wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d " "in WAIT_FRAG_ACK state", op_code); eap_wsc_state(data, FAIL); return; } wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment acknowledged"); eap_wsc_state(data, MESG); return; } if (op_code != WSC_ACK && op_code != WSC_NACK && op_code != WSC_MSG && op_code != WSC_Done) { wpa_printf(MSG_DEBUG, "EAP-WSC: Unexpected Op-Code %d", op_code); eap_wsc_state(data, FAIL); return; } if (data->in_buf && eap_wsc_process_cont(data, pos, end - pos, op_code) < 0) { eap_wsc_state(data, FAIL); return; } if (flags & WSC_FLAGS_MF) { if (eap_wsc_process_fragment(data, flags, op_code, message_length, pos, end - pos) < 0) eap_wsc_state(data, FAIL); else eap_wsc_state(data, FRAG_ACK); return; } if (data->in_buf == NULL) { /* Wrap unfragmented messages as wpabuf without extra copy */ wpabuf_set(&tmpbuf, pos, end - pos); data->in_buf = &tmpbuf; } res = wps_process_msg(data->wps, op_code, data->in_buf); switch (res) { case WPS_DONE: wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing completed " "successfully - report EAP failure"); eap_wsc_state(data, FAIL); break; case WPS_CONTINUE: eap_wsc_state(data, MESG); break; case WPS_FAILURE: wpa_printf(MSG_DEBUG, "EAP-WSC: WPS processing failed"); eap_wsc_state(data, FAIL); break; case WPS_PENDING: eap_wsc_state(data, MESG); sm->method_pending = METHOD_PENDING_WAIT; eloop_cancel_timeout(eap_wsc_ext_reg_timeout, sm, data); eloop_register_timeout(5, 0, eap_wsc_ext_reg_timeout, sm, data); break; } if (data->in_buf != &tmpbuf) wpabuf_free(data->in_buf); data->in_buf = NULL; }
void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { struct wpa_ssid *ssid = wpa_s->current_ssid; if (ssid == NULL) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event " "when network is not selected"); return; } if (wpa_s->wpa_state != WPA_AUTHENTICATING) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication event " "when not in authenticating state"); return; } if (os_memcmp(wpa_s->pending_bssid, data->auth.peer, ETH_ALEN) != 0) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Ignore authentication with " "unexpected peer " MACSTR, MAC2STR(data->auth.peer)); return; } wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication response: peer=" MACSTR " auth_type=%d status_code=%d", MAC2STR(data->auth.peer), data->auth.auth_type, data->auth.status_code); wpa_hexdump(MSG_MSGDUMP, "SME: Authentication response IEs", data->auth.ies, data->auth.ies_len); eloop_cancel_timeout(sme_auth_timer, wpa_s, NULL); if (data->auth.status_code != WLAN_STATUS_SUCCESS) { wpa_dbg(wpa_s, MSG_DEBUG, "SME: Authentication failed (status " "code %d)", data->auth.status_code); if (data->auth.status_code != WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG || wpa_s->sme.auth_alg == data->auth.auth_type || wpa_s->current_ssid->auth_alg == WPA_AUTH_ALG_LEAP) { wpas_connection_failed(wpa_s, wpa_s->pending_bssid); return; } switch (data->auth.auth_type) { case WLAN_AUTH_OPEN: wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_SHARED; wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying SHARED auth"); wpa_supplicant_associate(wpa_s, wpa_s->current_bss, wpa_s->current_ssid); return; case WLAN_AUTH_SHARED_KEY: wpa_s->current_ssid->auth_alg = WPA_AUTH_ALG_LEAP; wpa_dbg(wpa_s, MSG_DEBUG, "SME: Trying LEAP auth"); wpa_supplicant_associate(wpa_s, wpa_s->current_bss, wpa_s->current_ssid); return; default: return; } } #ifdef CONFIG_IEEE80211R if (data->auth.auth_type == WLAN_AUTH_FT) { union wpa_event_data edata; os_memset(&edata, 0, sizeof(edata)); edata.ft_ies.ies = data->auth.ies; edata.ft_ies.ies_len = data->auth.ies_len; os_memcpy(edata.ft_ies.target_ap, data->auth.peer, ETH_ALEN); wpa_supplicant_event(wpa_s, EVENT_FT_RESPONSE, &edata); } #endif /* CONFIG_IEEE80211R */ sme_associate(wpa_s, ssid->mode, data->auth.peer, data->auth.auth_type); }
/** * offchannel_send_action - Request off-channel Action frame TX * @wpa_s: Pointer to wpa_supplicant data * @freq: The frequency in MHz indicating the channel on which the frame is to * transmitted or 0 for the current channel (only if associated) * @dst: Action frame destination MAC address * @src: Action frame source MAC address * @bssid: Action frame BSSID * @buf: Frame to transmit starting from the Category field * @len: Length of @buf in bytes * @wait_time: Wait time for response in milliseconds * @tx_cb: Callback function for indicating TX status or %NULL for now callback * @no_cck: Whether CCK rates are to be disallowed for TX rate selection * Returns: 0 on success or -1 on failure * * This function is used to request an Action frame to be transmitted on the * current operating channel or on another channel (off-channel). The actual * frame transmission will be delayed until the driver is ready on the specified * channel. The @wait_time parameter can be used to request the driver to remain * awake on the channel to wait for a response. */ int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq, const u8 *dst, const u8 *src, const u8 *bssid, const u8 *buf, size_t len, unsigned int wait_time, void (*tx_cb)(struct wpa_supplicant *wpa_s, unsigned int freq, const u8 *dst, const u8 *src, const u8 *bssid, const u8 *data, size_t data_len, enum offchannel_send_action_result result), int no_cck) { wpa_printf(MSG_DEBUG, "Off-channel: Send action frame: freq=%d dst=" MACSTR " src=" MACSTR " bssid=" MACSTR " len=%d", freq, MAC2STR(dst), MAC2STR(src), MAC2STR(bssid), (int) len); wpa_s->pending_action_tx_status_cb = tx_cb; if (wpa_s->pending_action_tx) { wpa_printf(MSG_DEBUG, "Off-channel: Dropped pending Action " "frame TX to " MACSTR, MAC2STR(wpa_s->pending_action_dst)); wpabuf_free(wpa_s->pending_action_tx); } wpa_s->pending_action_tx_done = 0; wpa_s->pending_action_tx = wpabuf_alloc(len); if (wpa_s->pending_action_tx == NULL) { wpa_printf(MSG_DEBUG, "Off-channel: Failed to allocate Action " "frame TX buffer (len=%llu)", (unsigned long long) len); return -1; } wpabuf_put_data(wpa_s->pending_action_tx, buf, len); os_memcpy(wpa_s->pending_action_src, src, ETH_ALEN); os_memcpy(wpa_s->pending_action_dst, dst, ETH_ALEN); os_memcpy(wpa_s->pending_action_bssid, bssid, ETH_ALEN); wpa_s->pending_action_freq = freq; wpa_s->pending_action_no_cck = no_cck; if (freq != 0 && wpa_s->drv_flags & WPA_DRIVER_FLAGS_OFFCHANNEL_TX) { struct wpa_supplicant *iface; int ret; iface = wpas_get_tx_interface(wpa_s, src); wpa_s->action_tx_wait_time = wait_time; ret = wpa_drv_send_action( iface, wpa_s->pending_action_freq, wait_time, wpa_s->pending_action_dst, wpa_s->pending_action_src, wpa_s->pending_action_bssid, wpabuf_head(wpa_s->pending_action_tx), wpabuf_len(wpa_s->pending_action_tx), wpa_s->pending_action_no_cck); if (ret == 0) wpa_s->pending_action_tx_done = 1; return ret; } if (freq) { struct wpa_supplicant *tx_iface; tx_iface = wpas_get_tx_interface(wpa_s, src); if (tx_iface->assoc_freq == freq) { wpa_printf(MSG_DEBUG, "Off-channel: Already on " "requested channel (TX interface operating " "channel)"); freq = 0; } } if (wpa_s->off_channel_freq == freq || freq == 0) { wpa_printf(MSG_DEBUG, "Off-channel: Already on requested " "channel; send Action frame immediately"); /* TODO: Would there ever be need to extend the current * duration on the channel? */ wpa_s->pending_action_without_roc = 1; eloop_cancel_timeout(wpas_send_action_cb, wpa_s, NULL); eloop_register_timeout(0, 0, wpas_send_action_cb, wpa_s, NULL); return 0; } wpa_s->pending_action_without_roc = 0; if (wpa_s->roc_waiting_drv_freq == freq) { wpa_printf(MSG_DEBUG, "Off-channel: Already waiting for " "driver to get to frequency %u MHz; continue " "waiting to send the Action frame", freq); return 0; } wpa_printf(MSG_DEBUG, "Off-channel: Schedule Action frame to be " "transmitted once the driver gets to the requested " "channel"); if (wait_time > wpa_s->max_remain_on_chan) wait_time = wpa_s->max_remain_on_chan; else if (wait_time == 0) wait_time = 20; #ifdef CONFIG_TESTING_OPTIONS if (wpa_s->extra_roc_dur) { wpa_printf(MSG_DEBUG, "TESTING: Increase ROC duration %u -> %u", wait_time, wait_time + wpa_s->extra_roc_dur); wait_time += wpa_s->extra_roc_dur; } #endif /* CONFIG_TESTING_OPTIONS */ if (wpa_drv_remain_on_channel(wpa_s, freq, wait_time) < 0) { wpa_printf(MSG_DEBUG, "Off-channel: Failed to request driver " "to remain on channel (%u MHz) for Action " "Frame TX", freq); return -1; } wpa_s->off_channel_freq = 0; wpa_s->roc_waiting_drv_freq = freq; return 0; }
void ap_list_deinit(struct hostapd_iface *iface) { eloop_cancel_timeout(ap_list_timer, iface, NULL); hostapd_free_aps(iface); }
void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd) { eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); }
void hostapd_stop_setup_timers(struct hostapd_iface *iface) { eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL); }
void hs20_icon_fetch_failed(struct wpa_supplicant *wpa_s) { hs20_osu_icon_fetch_result(wpa_s, -1); eloop_cancel_timeout(hs20_continue_icon_fetch, wpa_s, NULL); eloop_register_timeout(0, 0, hs20_continue_icon_fetch, wpa_s, NULL); }
int main(int argc, char *argv[]) { struct wpa_supplicant wpa_s; int c, ret = 1, wait_for_monitor = 0, save_config = 0; char *as_addr = "127.0.0.1"; int as_port = 1812; char *as_secret = "radius"; char *cli_addr = NULL; char *conf = NULL; int timeout = 30; char *pos; struct extra_radius_attr *p = NULL, *p1; if (os_program_init()) return -1; hostapd_logger_register_cb(hostapd_logger_cb); os_memset(&eapol_test, 0, sizeof(eapol_test)); eapol_test.connect_info = "CONNECT 11Mbps 802.11b"; os_memcpy(eapol_test.own_addr, "\x02\x00\x00\x00\x00\x01", ETH_ALEN); wpa_debug_level = 0; wpa_debug_show_keys = 1; for (;;) { c = getopt(argc, argv, "a:A:c:C:M:nN:p:r:s:St:W"); if (c < 0) break; switch (c) { case 'a': as_addr = optarg; break; case 'A': cli_addr = optarg; break; case 'c': conf = optarg; break; case 'C': eapol_test.connect_info = optarg; break; case 'M': if (hwaddr_aton(optarg, eapol_test.own_addr)) { usage(); return -1; } break; case 'n': eapol_test.no_mppe_keys++; break; case 'p': as_port = atoi(optarg); break; case 'r': eapol_test.eapol_test_num_reauths = atoi(optarg); break; case 's': as_secret = optarg; break; case 'S': save_config++; break; case 't': timeout = atoi(optarg); break; case 'W': wait_for_monitor++; break; case 'N': p1 = os_zalloc(sizeof(p1)); if (p1 == NULL) break; if (!p) eapol_test.extra_attrs = p1; else p->next = p1; p = p1; p->type = atoi(optarg); pos = os_strchr(optarg, ':'); if (pos == NULL) { p->syntax = 'n'; p->data = NULL; break; } pos++; if (pos[0] == '\0' || pos[1] != ':') { printf("Incorrect format of attribute " "specification\n"); break; } p->syntax = pos[0]; p->data = pos + 2; break; default: usage(); return -1; } } if (argc > optind && os_strcmp(argv[optind], "scard") == 0) { return scard_test(); } if (argc > optind && os_strcmp(argv[optind], "sim") == 0) { return scard_get_triplets(argc - optind - 1, &argv[optind + 1]); } if (conf == NULL) { usage(); printf("Configuration file is required.\n"); return -1; } if (eap_register_methods()) { wpa_printf(MSG_ERROR, "Failed to register EAP methods"); return -1; } if (eloop_init()) { wpa_printf(MSG_ERROR, "Failed to initialize event loop"); return -1; } os_memset(&wpa_s, 0, sizeof(wpa_s)); eapol_test.wpa_s = &wpa_s; wpa_s.conf = wpa_config_read(conf); if (wpa_s.conf == NULL) { printf("Failed to parse configuration file '%s'.\n", conf); return -1; } if (wpa_s.conf->ssid == NULL) { printf("No networks defined.\n"); return -1; } wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret, cli_addr); wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s); if (wpa_s.ctrl_iface == NULL) { printf("Failed to initialize control interface '%s'.\n" "You may have another eapol_test process already " "running or the file was\n" "left by an unclean termination of eapol_test in " "which case you will need\n" "to manually remove this file before starting " "eapol_test again.\n", wpa_s.conf->ctrl_interface); return -1; } if (wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid)) return -1; if (test_eapol(&eapol_test, &wpa_s, wpa_s.conf->ssid)) return -1; if (wait_for_monitor) wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface); eloop_register_timeout(timeout, 0, eapol_test_timeout, &eapol_test, NULL); eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s, NULL); eloop_register_signal_terminate(eapol_test_terminate, &wpa_s); eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s); eloop_run(); eloop_cancel_timeout(eapol_test_timeout, &eapol_test, NULL); eloop_cancel_timeout(eapol_sm_reauth, &eapol_test, NULL); if (eapol_test_compare_pmk(&eapol_test) == 0 || eapol_test.no_mppe_keys) ret = 0; if (eapol_test.auth_timed_out) ret = -2; if (eapol_test.radius_access_reject_received) ret = -3; if (save_config) wpa_config_write(conf, wpa_s.conf); test_eapol_clean(&eapol_test, &wpa_s); eap_peer_unregister_methods(); eloop_destroy(); printf("MPPE keys OK: %d mismatch: %d\n", eapol_test.num_mppe_ok, eapol_test.num_mppe_mismatch); if (eapol_test.num_mppe_mismatch) ret = -4; if (ret) printf("FAILURE\n"); else printf("SUCCESS\n"); os_program_deinit(); return ret; }
void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) { int set_beacon = 0; accounting_sta_stop(hapd, sta); /* just in case */ ap_sta_set_authorized(hapd, sta, 0); if (sta->flags & WLAN_STA_WDS) hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0); if (!hapd->iface->driver_ap_teardown && !(sta->flags & WLAN_STA_PREAUTH)) hostapd_drv_sta_remove(hapd, sta->addr); ap_sta_hash_del(hapd, sta); ap_sta_list_del(hapd, sta); if (sta->aid > 0) hapd->sta_aid[(sta->aid - 1) / 32] &= ~BIT((sta->aid - 1) % 32); hapd->num_sta--; if (sta->nonerp_set) { sta->nonerp_set = 0; hapd->iface->num_sta_non_erp--; if (hapd->iface->num_sta_non_erp == 0) set_beacon++; } if (sta->no_short_slot_time_set) { sta->no_short_slot_time_set = 0; hapd->iface->num_sta_no_short_slot_time--; if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->iface->num_sta_no_short_slot_time == 0) set_beacon++; } if (sta->no_short_preamble_set) { sta->no_short_preamble_set = 0; hapd->iface->num_sta_no_short_preamble--; if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->iface->num_sta_no_short_preamble == 0) set_beacon++; } if (sta->no_ht_gf_set) { sta->no_ht_gf_set = 0; hapd->iface->num_sta_ht_no_gf--; } if (sta->no_ht_set) { sta->no_ht_set = 0; hapd->iface->num_sta_no_ht--; } if (sta->ht_20mhz_set) { sta->ht_20mhz_set = 0; hapd->iface->num_sta_ht_20mhz--; } #ifdef CONFIG_IEEE80211N ht40_intolerant_remove(hapd->iface, sta); #endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_P2P if (sta->no_p2p_set) { sta->no_p2p_set = 0; hapd->num_sta_no_p2p--; if (hapd->num_sta_no_p2p == 0) hostapd_p2p_non_p2p_sta_disconnected(hapd); } #endif /* CONFIG_P2P */ #if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N) if (hostapd_ht_operation_update(hapd->iface) > 0) set_beacon++; #endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ if (set_beacon) ieee802_11_set_beacons(hapd->iface); wpa_printf(MSG_DEBUG, "%s: cancel ap_handle_timer for " MACSTR, __func__, MAC2STR(sta->addr)); eloop_cancel_timeout(ap_handle_timer, hapd, sta); eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta); eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); ieee802_1x_free_station(sta); wpa_auth_sta_deinit(sta->wpa_sm); rsn_preauth_free_station(hapd, sta); #ifndef CONFIG_NO_RADIUS if (hapd->radius) radius_client_flush_auth(hapd->radius, sta->addr); #endif /* CONFIG_NO_RADIUS */ os_free(sta->challenge); #ifdef CONFIG_IEEE80211W os_free(sta->sa_query_trans_id); eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); #endif /* CONFIG_IEEE80211W */ #ifdef CONFIG_P2P p2p_group_notif_disassoc(hapd->p2p_group, sta->addr); #endif /* CONFIG_P2P */ #ifdef CONFIG_INTERWORKING if (sta->gas_dialog) { int i; for (i = 0; i < GAS_DIALOG_MAX; i++) gas_serv_dialog_clear(&sta->gas_dialog[i]); os_free(sta->gas_dialog); } #endif /* CONFIG_INTERWORKING */ wpabuf_free(sta->wps_ie); wpabuf_free(sta->p2p_ie); wpabuf_free(sta->hs20_ie); os_free(sta->ht_capabilities); os_free(sta->vht_capabilities); hostapd_free_psk_list(sta->psk); os_free(sta->identity); os_free(sta->radius_cui); os_free(sta->remediation_url); wpabuf_free(sta->hs20_deauth_req); os_free(sta->hs20_session_info_url); #ifdef CONFIG_SAE sae_clear_data(sta->sae); os_free(sta->sae); #endif /* CONFIG_SAE */ os_free(sta); }
static int radius_server_request(struct radius_server_data *data, struct radius_msg *msg, struct sockaddr *from, socklen_t fromlen, struct radius_client *client, const char *from_addr, int from_port, struct radius_session *force_sess) { u8 *eap = NULL; size_t eap_len; int res, state_included = 0; u8 statebuf[4]; unsigned int state; struct radius_session *sess; struct radius_msg *reply; int is_complete = 0; if (force_sess) sess = force_sess; else { res = radius_msg_get_attr(msg, RADIUS_ATTR_STATE, statebuf, sizeof(statebuf)); state_included = res >= 0; if (res == sizeof(statebuf)) { state = WPA_GET_BE32(statebuf); sess = radius_server_get_session(client, state); } else { sess = NULL; } } if (sess) { RADIUS_DEBUG("Request for session 0x%x", sess->sess_id); } else if (state_included) { RADIUS_DEBUG("State attribute included but no session found"); radius_server_reject(data, client, msg, from, fromlen, from_addr, from_port); return -1; } else { sess = radius_server_get_new_session(data, client, msg); if (sess == NULL) { RADIUS_DEBUG("Could not create a new session"); radius_server_reject(data, client, msg, from, fromlen, from_addr, from_port); return -1; } } if (sess->last_from_port == from_port && sess->last_identifier == msg->hdr->identifier && os_memcmp(sess->last_authenticator, msg->hdr->authenticator, 16) == 0) { RADIUS_DEBUG("Duplicate message from %s", from_addr); data->counters.dup_access_requests++; client->counters.dup_access_requests++; if (sess->last_reply) { res = sendto(data->auth_sock, sess->last_reply->buf, sess->last_reply->buf_used, 0, (struct sockaddr *) from, fromlen); if (res < 0) { perror("sendto[RADIUS SRV]"); } return 0; } RADIUS_DEBUG("No previous reply available for duplicate " "message"); return -1; } eap = radius_msg_get_eap(msg, &eap_len); if (eap == NULL) { RADIUS_DEBUG("No EAP-Message in RADIUS packet from %s", from_addr); data->counters.packets_dropped++; client->counters.packets_dropped++; return -1; } RADIUS_DUMP("Received EAP data", eap, eap_len); /* FIX: if Code is Request, Success, or Failure, send Access-Reject; * RFC3579 Sect. 2.6.2. * Include EAP-Response/Nak with no preferred method if * code == request. * If code is not 1-4, discard the packet silently. * Or is this already done by the EAP state machine? */ wpabuf_free(sess->eap_if->eapRespData); sess->eap_if->eapRespData = wpabuf_alloc_ext_data(eap, eap_len); if (sess->eap_if->eapRespData == NULL) os_free(eap); eap = NULL; sess->eap_if->eapResp = TRUE; eap_server_sm_step(sess->eap); if ((sess->eap_if->eapReq || sess->eap_if->eapSuccess || sess->eap_if->eapFail) && sess->eap_if->eapReqData) { RADIUS_DUMP("EAP data from the state machine", wpabuf_head(sess->eap_if->eapReqData), wpabuf_len(sess->eap_if->eapReqData)); } else if (sess->eap_if->eapFail) { RADIUS_DEBUG("No EAP data from the state machine, but eapFail " "set"); } else if (eap_sm_method_pending(sess->eap)) { if (sess->last_msg) { radius_msg_free(sess->last_msg); os_free(sess->last_msg); } sess->last_msg = msg; sess->last_from_port = from_port; os_free(sess->last_from_addr); sess->last_from_addr = os_strdup(from_addr); sess->last_fromlen = fromlen; os_memcpy(&sess->last_from, from, fromlen); return -2; } else { RADIUS_DEBUG("No EAP data from the state machine - ignore this" " Access-Request silently (assuming it was a " "duplicate)"); data->counters.packets_dropped++; client->counters.packets_dropped++; return -1; } if (sess->eap_if->eapSuccess || sess->eap_if->eapFail) is_complete = 1; reply = radius_server_encapsulate_eap(data, client, sess, msg); if (reply) { RADIUS_DEBUG("Reply to %s:%d", from_addr, from_port); if (wpa_debug_level <= MSG_MSGDUMP) { radius_msg_dump(reply); } switch (reply->hdr->code) { case RADIUS_CODE_ACCESS_ACCEPT: data->counters.access_accepts++; client->counters.access_accepts++; break; case RADIUS_CODE_ACCESS_REJECT: data->counters.access_rejects++; client->counters.access_rejects++; break; case RADIUS_CODE_ACCESS_CHALLENGE: data->counters.access_challenges++; client->counters.access_challenges++; break; } res = sendto(data->auth_sock, reply->buf, reply->buf_used, 0, (struct sockaddr *) from, fromlen); if (res < 0) { perror("sendto[RADIUS SRV]"); } if (sess->last_reply) { radius_msg_free(sess->last_reply); os_free(sess->last_reply); } sess->last_reply = reply; sess->last_from_port = from_port; sess->last_identifier = msg->hdr->identifier; os_memcpy(sess->last_authenticator, msg->hdr->authenticator, 16); } else { data->counters.packets_dropped++; client->counters.packets_dropped++; } if (is_complete) { RADIUS_DEBUG("Removing completed session 0x%x after timeout", sess->sess_id); eloop_cancel_timeout(radius_server_session_remove_timeout, data, sess); eloop_register_timeout(10, 0, radius_server_session_remove_timeout, data, sess); } return 0; }
void ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta) { eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); }
static void remove_timeout(DBusTimeout *timeout, void *data) { struct wpas_dbus_priv *priv = data; eloop_cancel_timeout(process_timeout, priv, timeout); dbus_timeout_set_data(timeout, NULL, NULL); }
/* event_send_stop_all -- cleanup */ void event_send_stop_all(struct upnp_wps_device_sm *sm) { if (sm->event_send_all_queued) eloop_cancel_timeout(event_send_all_later_handler, NULL, sm); sm->event_send_all_queued = 0; }
int hs20_web_browser(const char *url) { struct http_server *http; struct in_addr addr; struct browser_data data; pid_t pid; wpa_printf(MSG_INFO, "Launching Android browser to %s", url); os_memset(&data, 0, sizeof(data)); if (eloop_init() < 0) { wpa_printf(MSG_ERROR, "eloop_init failed"); return -1; } addr.s_addr = htonl((127 << 24) | 1); http = http_server_init(&addr, 12345, http_req, &data); if (http == NULL) { wpa_printf(MSG_ERROR, "http_server_init failed"); eloop_destroy(); return -1; } pid = fork(); if (pid < 0) { wpa_printf(MSG_ERROR, "fork: %s", strerror(errno)); http_server_deinit(http); eloop_destroy(); return -1; } if (pid == 0) { /* run the external command in the child process */ char *argv[7]; argv[0] = "browser-android"; argv[1] = "start"; argv[2] = "-a"; argv[3] = "android.intent.action.VIEW"; argv[4] = "-d"; argv[5] = (void *) url; argv[6] = NULL; execv("/system/bin/am", argv); wpa_printf(MSG_ERROR, "execv: %s", strerror(errno)); exit(0); return -1; } eloop_register_timeout(30, 0, browser_timeout, &data, NULL); eloop_run(); eloop_cancel_timeout(browser_timeout, &data, NULL); http_server_deinit(http); eloop_destroy(); wpa_printf(MSG_INFO, "Closing Android browser"); if (system("/system/bin/input keyevent KEYCODE_HOME") != 0) { wpa_printf(MSG_INFO, "Failed to inject keyevent"); } return data.success; }
static void wpa_supplicant_event_michael_mic_failure(struct wpa_supplicant *wpa_s, union wpa_event_data *data) { int pairwise; struct os_time t; wpa_msg(wpa_s, MSG_WARNING, "Michael MIC failure detected"); pairwise = (data && data->michael_mic_failure.unicast); os_get_time(&t); if ((wpa_s->last_michael_mic_error && t.sec - wpa_s->last_michael_mic_error <= 60) || wpa_s->pending_mic_error_report) { if (wpa_s->pending_mic_error_report) { /* * Send the pending MIC error report immediately since * we are going to start countermeasures and AP better * do the same. */ wpa_sm_key_request(wpa_s->wpa, 1, wpa_s->pending_mic_error_pairwise); } /* Send the new MIC error report immediately since we are going * to start countermeasures and AP better do the same. */ wpa_sm_key_request(wpa_s->wpa, 1, pairwise); /* initialize countermeasures */ wpa_s->countermeasures = 1; wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures started"); /* * Need to wait for completion of request frame. We do not get * any callback for the message completion, so just wait a * short while and hope for the best. */ os_sleep(0, 10000); wpa_drv_set_countermeasures(wpa_s, 1); wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_MICHAEL_MIC_FAILURE); eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL); eloop_register_timeout(60, 0, wpa_supplicant_stop_countermeasures, wpa_s, NULL); /* TODO: mark the AP rejected for 60 second. STA is * allowed to associate with another AP.. */ } else { #ifdef CONFIG_DELAYED_MIC_ERROR_REPORT if (wpa_s->mic_errors_seen) { /* * Reduce the effectiveness of Michael MIC error * reports as a means for attacking against TKIP if * more than one MIC failure is noticed with the same * PTK. We delay the transmission of the reports by a * random time between 0 and 60 seconds in order to * force the attacker wait 60 seconds before getting * the information on whether a frame resulted in a MIC * failure. */ u8 rval[4]; int sec; if (os_get_random(rval, sizeof(rval)) < 0) sec = os_random() % 60; else sec = WPA_GET_BE32(rval) % 60; wpa_printf(MSG_DEBUG, "WPA: Delay MIC error report %d " "seconds", sec); wpa_s->pending_mic_error_report = 1; wpa_s->pending_mic_error_pairwise = pairwise; eloop_cancel_timeout( wpa_supplicant_delayed_mic_error_report, wpa_s, NULL); eloop_register_timeout( sec, os_random() % 1000000, wpa_supplicant_delayed_mic_error_report, wpa_s, NULL); } else { wpa_sm_key_request(wpa_s->wpa, 1, pairwise); } #else /* CONFIG_DELAYED_MIC_ERROR_REPORT */ wpa_sm_key_request(wpa_s->wpa, 1, pairwise); #endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */ } wpa_s->last_michael_mic_error = t.sec; wpa_s->mic_errors_seen++; }
int hs20_web_browser(const char *url) { struct http_server *http; struct in_addr addr; struct browser_data data; pid_t pid; wpa_printf(MSG_INFO, "Launching wpadebug browser to %s", url); os_memset(&data, 0, sizeof(data)); if (eloop_init() < 0) { wpa_printf(MSG_ERROR, "eloop_init failed"); return -1; } addr.s_addr = htonl((127 << 24) | 1); http = http_server_init(&addr, 12345, http_req, &data); if (http == NULL) { wpa_printf(MSG_ERROR, "http_server_init failed"); eloop_destroy(); return -1; } pid = fork(); if (pid < 0) { wpa_printf(MSG_ERROR, "fork: %s", strerror(errno)); http_server_deinit(http); eloop_destroy(); return -1; } if (pid == 0) { /* run the external command in the child process */ char *argv[14]; argv[0] = "browser-wpadebug"; argv[1] = "start"; argv[2] = "-a"; argv[3] = "android.action.MAIN"; argv[4] = "-c"; argv[5] = "android.intent.category.LAUNCHER"; argv[6] = "-n"; argv[7] = "w1.fi.wpadebug/.WpaWebViewActivity"; argv[8] = "-e"; argv[9] = "w1.fi.wpadebug.URL"; argv[10] = (void *) url; argv[11] = "--user"; argv[12] = "-3"; /* USER_CURRENT_OR_SELF */ argv[13] = NULL; execv("/system/bin/am", argv); wpa_printf(MSG_ERROR, "execv: %s", strerror(errno)); exit(0); return -1; } eloop_register_timeout(300, 0, browser_timeout, &data, NULL); eloop_run(); eloop_cancel_timeout(browser_timeout, &data, NULL); http_server_deinit(http); eloop_destroy(); wpa_printf(MSG_INFO, "Closing Android browser"); if (os_exec("/system/bin/am", "start -a android.action.MAIN " "-c android.intent.category.LAUNCHER " "-n w1.fi.wpadebug/.WpaWebViewActivity " "-e w1.fi.wpadebug.URL FINISH", 1) != 0) { wpa_printf(MSG_INFO, "Failed to close wpadebug browser"); } return data.success; }