HS 2.0R2 AP: Add support for Session Info URL RADIUS AVP
If the authentication server includes the WFA HS 2.0 Session Info URL AVP in Access-Accept, schedule ESS Disassociation Imminent frame to be transmitted specified warning time prior to session timeout. Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
8e1146d9da
commit
97596f8ed4
4 changed files with 86 additions and 2 deletions
|
@ -1286,12 +1286,55 @@ static void ieee802_1x_hs20_deauth_req(struct hostapd_data *hapd,
|
||||||
ap_sta_session_timeout(hapd, sta, hapd->conf->hs20_deauth_req_timeout);
|
ap_sta_session_timeout(hapd, sta, hapd->conf->hs20_deauth_req_timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ieee802_1x_hs20_session_info(struct hostapd_data *hapd,
|
||||||
|
struct sta_info *sta, u8 *pos,
|
||||||
|
size_t len, int session_timeout)
|
||||||
|
{
|
||||||
|
unsigned int swt;
|
||||||
|
int warning_time, beacon_int;
|
||||||
|
|
||||||
|
if (len < 1)
|
||||||
|
return; /* Malformed information */
|
||||||
|
os_free(sta->hs20_session_info_url);
|
||||||
|
sta->hs20_session_info_url = os_malloc(len);
|
||||||
|
if (sta->hs20_session_info_url == NULL)
|
||||||
|
return;
|
||||||
|
swt = pos[0];
|
||||||
|
os_memcpy(sta->hs20_session_info_url, pos + 1, len - 1);
|
||||||
|
sta->hs20_session_info_url[len - 1] = '\0';
|
||||||
|
wpa_printf(MSG_DEBUG, "HS 2.0: Session Information URL='%s' SWT=%u "
|
||||||
|
"(session_timeout=%d)",
|
||||||
|
sta->hs20_session_info_url, swt, session_timeout);
|
||||||
|
if (session_timeout < 0) {
|
||||||
|
wpa_printf(MSG_DEBUG, "HS 2.0: No Session-Timeout set - ignore session info URL");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (swt == 255)
|
||||||
|
swt = 1; /* Use one minute as the AP selected value */
|
||||||
|
|
||||||
|
if ((unsigned int) session_timeout < swt * 60)
|
||||||
|
warning_time = 0;
|
||||||
|
else
|
||||||
|
warning_time = session_timeout - swt * 60;
|
||||||
|
|
||||||
|
beacon_int = hapd->iconf->beacon_int;
|
||||||
|
if (beacon_int < 1)
|
||||||
|
beacon_int = 100; /* best guess */
|
||||||
|
sta->hs20_disassoc_timer = swt * 60 * 1000 / beacon_int * 125 / 128;
|
||||||
|
if (sta->hs20_disassoc_timer > 65535)
|
||||||
|
sta->hs20_disassoc_timer = 65535;
|
||||||
|
|
||||||
|
ap_sta_session_warning_timeout(hapd, sta, warning_time);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_HS20 */
|
#endif /* CONFIG_HS20 */
|
||||||
|
|
||||||
|
|
||||||
static void ieee802_1x_check_hs20(struct hostapd_data *hapd,
|
static void ieee802_1x_check_hs20(struct hostapd_data *hapd,
|
||||||
struct sta_info *sta,
|
struct sta_info *sta,
|
||||||
struct radius_msg *msg)
|
struct radius_msg *msg,
|
||||||
|
int session_timeout)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_HS20
|
#ifdef CONFIG_HS20
|
||||||
u8 *buf, *pos, *end, type, sublen;
|
u8 *buf, *pos, *end, type, sublen;
|
||||||
|
@ -1328,6 +1371,10 @@ static void ieee802_1x_check_hs20(struct hostapd_data *hapd,
|
||||||
case RADIUS_VENDOR_ATTR_WFA_HS20_DEAUTH_REQ:
|
case RADIUS_VENDOR_ATTR_WFA_HS20_DEAUTH_REQ:
|
||||||
ieee802_1x_hs20_deauth_req(hapd, sta, pos, sublen);
|
ieee802_1x_hs20_deauth_req(hapd, sta, pos, sublen);
|
||||||
break;
|
break;
|
||||||
|
case RADIUS_VENDOR_ATTR_WFA_HS20_SESSION_INFO_URL:
|
||||||
|
ieee802_1x_hs20_session_info(hapd, sta, pos, sublen,
|
||||||
|
session_timeout);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_HS20 */
|
#endif /* CONFIG_HS20 */
|
||||||
|
@ -1492,7 +1539,9 @@ ieee802_1x_receive_auth(struct radius_msg *msg, struct radius_msg *req,
|
||||||
ieee802_1x_store_radius_class(hapd, sta, msg);
|
ieee802_1x_store_radius_class(hapd, sta, msg);
|
||||||
ieee802_1x_update_sta_identity(hapd, sta, msg);
|
ieee802_1x_update_sta_identity(hapd, sta, msg);
|
||||||
ieee802_1x_update_sta_cui(hapd, sta, msg);
|
ieee802_1x_update_sta_cui(hapd, sta, msg);
|
||||||
ieee802_1x_check_hs20(hapd, sta, msg);
|
ieee802_1x_check_hs20(hapd, sta, msg,
|
||||||
|
session_timeout_set ?
|
||||||
|
(int) session_timeout : -1);
|
||||||
if (sm->eap_if->eapKeyAvailable && !sta->remediation &&
|
if (sm->eap_if->eapKeyAvailable && !sta->remediation &&
|
||||||
!sta->hs20_deauth_requested &&
|
!sta->hs20_deauth_requested &&
|
||||||
wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt,
|
wpa_auth_pmksa_add(sta->wpa_sm, sm->eapol_key_crypt,
|
||||||
|
|
|
@ -30,11 +30,13 @@
|
||||||
#include "p2p_hostapd.h"
|
#include "p2p_hostapd.h"
|
||||||
#include "ap_drv_ops.h"
|
#include "ap_drv_ops.h"
|
||||||
#include "gas_serv.h"
|
#include "gas_serv.h"
|
||||||
|
#include "wnm_ap.h"
|
||||||
#include "sta_info.h"
|
#include "sta_info.h"
|
||||||
|
|
||||||
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
|
static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd,
|
||||||
struct sta_info *sta);
|
struct sta_info *sta);
|
||||||
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
|
static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx);
|
||||||
|
static void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx);
|
||||||
static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx);
|
static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||||
static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx);
|
static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx);
|
||||||
#ifdef CONFIG_IEEE80211W
|
#ifdef CONFIG_IEEE80211W
|
||||||
|
@ -224,6 +226,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
__func__, MAC2STR(sta->addr));
|
__func__, MAC2STR(sta->addr));
|
||||||
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
|
||||||
eloop_cancel_timeout(ap_handle_session_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_deauth_cb_timeout, hapd, sta);
|
||||||
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
|
eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta);
|
||||||
|
|
||||||
|
@ -267,6 +270,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
os_free(sta->radius_cui);
|
os_free(sta->radius_cui);
|
||||||
os_free(sta->remediation_url);
|
os_free(sta->remediation_url);
|
||||||
wpabuf_free(sta->hs20_deauth_req);
|
wpabuf_free(sta->hs20_deauth_req);
|
||||||
|
os_free(sta->hs20_session_info_url);
|
||||||
|
|
||||||
#ifdef CONFIG_SAE
|
#ifdef CONFIG_SAE
|
||||||
sae_clear_data(sta->sae);
|
sae_clear_data(sta->sae);
|
||||||
|
@ -522,6 +526,32 @@ void ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_WNM
|
||||||
|
struct hostapd_data *hapd = eloop_ctx;
|
||||||
|
struct sta_info *sta = timeout_ctx;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WNM: Session warning time reached for " MACSTR,
|
||||||
|
MAC2STR(sta->addr));
|
||||||
|
if (sta->hs20_session_info_url == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
wnm_send_ess_disassoc_imminent(hapd, sta, sta->hs20_session_info_url,
|
||||||
|
sta->hs20_disassoc_timer);
|
||||||
|
#endif /* CONFIG_WNM */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ap_sta_session_warning_timeout(struct hostapd_data *hapd,
|
||||||
|
struct sta_info *sta, int warning_time)
|
||||||
|
{
|
||||||
|
eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta);
|
||||||
|
eloop_register_timeout(warning_time, 0, ap_handle_session_warning_timer,
|
||||||
|
hapd, sta);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
|
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr)
|
||||||
{
|
{
|
||||||
struct sta_info *sta;
|
struct sta_info *sta;
|
||||||
|
|
|
@ -130,6 +130,8 @@ struct sta_info {
|
||||||
u8 remediation_method;
|
u8 remediation_method;
|
||||||
char *remediation_url; /* HS 2.0 Subscription Remediation Server URL */
|
char *remediation_url; /* HS 2.0 Subscription Remediation Server URL */
|
||||||
struct wpabuf *hs20_deauth_req;
|
struct wpabuf *hs20_deauth_req;
|
||||||
|
char *hs20_session_info_url;
|
||||||
|
int hs20_disassoc_timer;
|
||||||
|
|
||||||
struct os_reltime connected_time;
|
struct os_reltime connected_time;
|
||||||
|
|
||||||
|
@ -173,6 +175,8 @@ void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
u32 session_timeout);
|
u32 session_timeout);
|
||||||
void ap_sta_no_session_timeout(struct hostapd_data *hapd,
|
void ap_sta_no_session_timeout(struct hostapd_data *hapd,
|
||||||
struct sta_info *sta);
|
struct sta_info *sta);
|
||||||
|
void ap_sta_session_warning_timeout(struct hostapd_data *hapd,
|
||||||
|
struct sta_info *sta, int warning_time);
|
||||||
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr);
|
struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr);
|
||||||
void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
|
void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta,
|
||||||
u16 reason);
|
u16 reason);
|
||||||
|
|
|
@ -172,6 +172,7 @@ enum {
|
||||||
RADIUS_VENDOR_ATTR_WFA_HS20_AP_VERSION = 2,
|
RADIUS_VENDOR_ATTR_WFA_HS20_AP_VERSION = 2,
|
||||||
RADIUS_VENDOR_ATTR_WFA_HS20_STA_VERSION = 3,
|
RADIUS_VENDOR_ATTR_WFA_HS20_STA_VERSION = 3,
|
||||||
RADIUS_VENDOR_ATTR_WFA_HS20_DEAUTH_REQ = 4,
|
RADIUS_VENDOR_ATTR_WFA_HS20_DEAUTH_REQ = 4,
|
||||||
|
RADIUS_VENDOR_ATTR_WFA_HS20_SESSION_INFO_URL = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
Loading…
Reference in a new issue