X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=hostapd%2Fsta_info.c;h=6fc1e0435498c35b49543538ea5396cb28dbaa20;hb=eb76b7e3ffea75035836aa2313c3c69b60c2ac34;hp=e9c0cc6e133830cfb2ba566a789e98566dfbb5e1;hpb=71b6ae1425d5a347caede49a8fd8278b09d69880;p=wpasupplicant diff --git a/hostapd/sta_info.c b/hostapd/sta_info.c index e9c0cc6..6fc1e04 100644 --- a/hostapd/sta_info.c +++ b/hostapd/sta_info.c @@ -1,6 +1,6 @@ /* * hostapd / Station table - * Copyright (c) 2002-2007, Jouni Malinen + * Copyright (c) 2002-2008, Jouni Malinen * Copyright (c) 2007-2008, Intel Corporation * * This program is free software; you can redistribute it and/or modify @@ -34,6 +34,9 @@ static int ap_sta_in_other_bss(struct hostapd_data *hapd, struct sta_info *sta, u32 flags); static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx); +#ifdef CONFIG_IEEE80211W +static void ap_ping_timer(void *eloop_ctx, void *timeout_ctx); +#endif /* CONFIG_IEEE80211W */ int ap_for_each_sta(struct hostapd_data *hapd, int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, @@ -153,11 +156,11 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) #ifdef CONFIG_IEEE80211N if (sta->flags & WLAN_STA_HT) { - if ((sta->ht_capabilities.data.capabilities_info & - HT_CAP_INFO_GREEN_FIELD) == 0) + u16 ht_capab = le_to_host16( + sta->ht_capabilities.data.capabilities_info); + if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) hapd->iface->num_sta_ht_no_gf--; - if ((sta->ht_capabilities.data.capabilities_info & - HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) + if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) hapd->iface->num_sta_ht_20mhz--; } else hapd->iface->num_sta_no_ht--; @@ -179,6 +182,14 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) os_free(sta->last_assoc_req); os_free(sta->challenge); + +#ifdef CONFIG_IEEE80211W + os_free(sta->ping_trans_id); + eloop_cancel_timeout(ap_ping_timer, hapd, sta); +#endif /* CONFIG_IEEE80211W */ + + wpabuf_free(sta->wps_ie); + os_free(sta); } @@ -270,7 +281,6 @@ void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) os_memset(&hdr, 0, sizeof(hdr)); hdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, WLAN_FC_STYPE_DATA); - hdr.frame_control |= host_to_le16(BIT(1)); hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS); os_memcpy(hdr.IEEE80211_DA_FROMDS, sta->addr, ETH_ALEN); os_memcpy(hdr.IEEE80211_BSSID_FROMDS, hapd->own_addr, @@ -594,3 +604,87 @@ int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta, return hostapd_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id); } + + +#ifdef CONFIG_IEEE80211W + +/* MLME-PING.request */ +static void ieee802_11_send_ping_req(struct hostapd_data *hapd, const u8 *addr, + const u8 *trans_id) +{ + struct ieee80211_mgmt mgmt; + u8 *end; + + os_memset(&mgmt, 0, sizeof(mgmt)); + mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(mgmt.da, addr, ETH_ALEN); + os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); + os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); + mgmt.u.action.category = WLAN_ACTION_PING; + mgmt.u.action.u.ping_req.action = WLAN_PING_REQUEST; + os_memcpy(mgmt.u.action.u.ping_req.trans_id, trans_id, + WLAN_PING_TRANS_ID_LEN); + end = mgmt.u.action.u.ping_req.trans_id + WLAN_PING_TRANS_ID_LEN; + if (hostapd_send_mgmt_frame(hapd, &mgmt, IEEE80211_HDRLEN + + end - (u8 *) &mgmt, 0) < 0) + perror("ieee802_11_send_ping_req: send"); +} + + +static void ap_ping_timer(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + unsigned int timeout, sec, usec; + u8 *trans_id, *nbuf; + + if (sta->ping_count >= hapd->conf->assoc_ping_attempts) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "association ping timed out"); + sta->ping_timed_out = 1; + os_free(sta->ping_trans_id); + sta->ping_trans_id = NULL; + sta->ping_count = 0; + return; + } + + nbuf = os_realloc(sta->ping_trans_id, + (sta->ping_count + 1) * WLAN_PING_TRANS_ID_LEN); + if (nbuf == NULL) + return; + trans_id = nbuf + sta->ping_count * WLAN_PING_TRANS_ID_LEN; + sta->ping_trans_id = nbuf; + sta->ping_count++; + + os_get_random(trans_id, WLAN_PING_TRANS_ID_LEN); + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "association ping attempt %d", sta->ping_count); + + ieee802_11_send_ping_req(hapd, sta->addr, trans_id); + + timeout = hapd->conf->assoc_ping_timeout; + sec = ((timeout / 1000) * 1024) / 1000; + usec = (timeout % 1000) * 1024; + eloop_register_timeout(sec, usec, ap_ping_timer, hapd, sta); +} + + +void ap_sta_start_ping(struct hostapd_data *hapd, struct sta_info *sta) +{ + ap_ping_timer(hapd, sta); +} + + +void ap_sta_stop_ping(struct hostapd_data *hapd, struct sta_info *sta) +{ + eloop_cancel_timeout(ap_ping_timer, hapd, sta); + os_free(sta->ping_trans_id); + sta->ping_trans_id = NULL; + sta->ping_count = 0; +} + +#endif /* CONFIG_IEEE80211W */