mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-10-29 09:32:34 +00:00
540 lines
17 KiB
Diff
540 lines
17 KiB
Diff
--- a/src/ap/wpa_auth.h
|
|
+++ b/src/ap/wpa_auth.h
|
|
@@ -16,7 +16,11 @@
|
|
|
|
struct vlan_description;
|
|
struct mld_info;
|
|
-
|
|
+struct rate_description {
|
|
+ u32 rx;
|
|
+ u32 tx;
|
|
+};
|
|
+
|
|
#define MAX_OWN_IE_OVERRIDE 256
|
|
|
|
#ifdef _MSC_VER
|
|
@@ -88,6 +92,7 @@ struct ft_rrb_frame {
|
|
#define FT_RRB_IDENTITY 15
|
|
#define FT_RRB_RADIUS_CUI 16
|
|
#define FT_RRB_SESSION_TIMEOUT 17 /* le32 seconds */
|
|
+#define FT_RRB_RATE_LIMIT 18
|
|
|
|
struct ft_rrb_tlv {
|
|
le16 type;
|
|
@@ -368,6 +373,10 @@ struct wpa_auth_callbacks {
|
|
struct vlan_description *vlan);
|
|
int (*get_vlan)(void *ctx, const u8 *sta_addr,
|
|
struct vlan_description *vlan);
|
|
+ int (*set_rate_limit)(void *ctx, const u8 *sta_addr,
|
|
+ struct rate_description *rate);
|
|
+ int (*get_rate_limit)(void *ctx, const u8 *sta_addr,
|
|
+ struct rate_description *rate);
|
|
int (*set_identity)(void *ctx, const u8 *sta_addr,
|
|
const u8 *identity, size_t identity_len);
|
|
size_t (*get_identity)(void *ctx, const u8 *sta_addr, const u8 **buf);
|
|
@@ -536,7 +545,7 @@ int wpa_ft_fetch_pmk_r1(struct wpa_authe
|
|
struct vlan_description *vlan,
|
|
const u8 **identity, size_t *identity_len,
|
|
const u8 **radius_cui, size_t *radius_cui_len,
|
|
- int *session_timeout);
|
|
+ int *session_timeout, struct rate_description *rate);
|
|
|
|
#endif /* CONFIG_IEEE80211R_AP */
|
|
|
|
--- a/src/ap/wpa_auth_glue.c
|
|
+++ b/src/ap/wpa_auth_glue.c
|
|
@@ -1200,6 +1200,40 @@ static int hostapd_wpa_auth_get_vlan(voi
|
|
}
|
|
|
|
|
|
+static int hostapd_wpa_auth_set_rate_limit(void *ctx, const u8 *sta_addr,
|
|
+ struct rate_description *rate)
|
|
+{
|
|
+ struct hostapd_data *hapd = ctx;
|
|
+ struct sta_info *sta;
|
|
+
|
|
+ sta = ap_get_sta(hapd, sta_addr);
|
|
+ if (!sta || !sta->wpa_sm)
|
|
+ return -1;
|
|
+
|
|
+ memcpy(sta->bandwidth, rate, sizeof(*rate));
|
|
+ hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
|
|
+ HOSTAPD_LEVEL_INFO, "rate-limit %d %d", sta->bandwidth[0], sta->bandwidth[1]);
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+static int hostapd_wpa_auth_get_rate_limit(void *ctx, const u8 *sta_addr,
|
|
+ struct rate_description *rate)
|
|
+{
|
|
+ struct hostapd_data *hapd = ctx;
|
|
+ struct sta_info *sta;
|
|
+
|
|
+ sta = ap_get_sta(hapd, sta_addr);
|
|
+ if (!sta)
|
|
+ return -1;
|
|
+
|
|
+ memcpy(rate, sta->bandwidth, sizeof(*rate));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
static int
|
|
hostapd_wpa_auth_set_identity(void *ctx, const u8 *sta_addr,
|
|
const u8 *identity, size_t identity_len)
|
|
@@ -1640,6 +1674,8 @@ int hostapd_setup_wpa(struct hostapd_dat
|
|
.add_tspec = hostapd_wpa_auth_add_tspec,
|
|
.set_vlan = hostapd_wpa_auth_set_vlan,
|
|
.get_vlan = hostapd_wpa_auth_get_vlan,
|
|
+ .set_rate_limit = hostapd_wpa_auth_set_rate_limit,
|
|
+ .get_rate_limit = hostapd_wpa_auth_get_rate_limit,
|
|
.set_identity = hostapd_wpa_auth_set_identity,
|
|
.get_identity = hostapd_wpa_auth_get_identity,
|
|
.set_radius_cui = hostapd_wpa_auth_set_radius_cui,
|
|
--- a/src/ap/wpa_auth_ft.c
|
|
+++ b/src/ap/wpa_auth_ft.c
|
|
@@ -379,6 +379,14 @@ static size_t wpa_ft_vlan_len(const stru
|
|
return tlv_len;
|
|
}
|
|
|
|
+static size_t wpa_ft_rate_limit_len(const struct rate_description *rate)
|
|
+{
|
|
+ if (!rate || (!rate->rx && !rate->tx))
|
|
+ return 0;
|
|
+
|
|
+ return (sizeof(struct ft_rrb_tlv) + 8);
|
|
+}
|
|
+
|
|
|
|
static size_t wpa_ft_vlan_lin(const struct vlan_description *vlan,
|
|
u8 *start, u8 *endpos)
|
|
@@ -434,10 +442,48 @@ static size_t wpa_ft_vlan_lin(const stru
|
|
}
|
|
|
|
|
|
+static size_t wpa_ft_rate_limit_lin(const struct rate_description *rate,
|
|
+ u8 *start, u8 *endpos)
|
|
+{
|
|
+ size_t tlv_len;
|
|
+ int i, len;
|
|
+ struct ft_rrb_tlv *hdr;
|
|
+ u8 *pos = start;
|
|
+
|
|
+ if (!rate)
|
|
+ return 0;
|
|
+
|
|
+ tlv_len = 0;
|
|
+ if (rate->rx || rate->tx) {
|
|
+ tlv_len += sizeof(*hdr);
|
|
+ if (start + tlv_len > endpos)
|
|
+ return tlv_len;
|
|
+ hdr = (struct ft_rrb_tlv *) pos;
|
|
+ hdr->type = host_to_le16(FT_RRB_RATE_LIMIT);
|
|
+ hdr->len = host_to_le16(2 * sizeof(le32));
|
|
+ pos = start + tlv_len;
|
|
+
|
|
+ tlv_len += sizeof(u32);
|
|
+ if (start + tlv_len > endpos)
|
|
+ return tlv_len;
|
|
+ WPA_PUT_LE32(pos, rate->rx);
|
|
+ pos = start + tlv_len;
|
|
+ tlv_len += sizeof(u32);
|
|
+ if (start + tlv_len > endpos)
|
|
+ return tlv_len;
|
|
+ WPA_PUT_LE32(pos, rate->tx);
|
|
+ pos = start + tlv_len;
|
|
+ }
|
|
+
|
|
+ return tlv_len;
|
|
+}
|
|
+
|
|
+
|
|
static int wpa_ft_rrb_lin(const struct tlv_list *tlvs1,
|
|
const struct tlv_list *tlvs2,
|
|
const struct vlan_description *vlan,
|
|
- u8 **plain, size_t *plain_len)
|
|
+ u8 **plain, size_t *plain_len,
|
|
+ const struct rate_description *rate)
|
|
{
|
|
u8 *pos, *endpos;
|
|
size_t tlv_len;
|
|
@@ -445,6 +491,7 @@ static int wpa_ft_rrb_lin(const struct t
|
|
tlv_len = wpa_ft_tlv_len(tlvs1);
|
|
tlv_len += wpa_ft_tlv_len(tlvs2);
|
|
tlv_len += wpa_ft_vlan_len(vlan);
|
|
+ tlv_len += wpa_ft_rate_limit_len(rate);
|
|
|
|
*plain_len = tlv_len;
|
|
*plain = os_zalloc(tlv_len);
|
|
@@ -458,6 +505,7 @@ static int wpa_ft_rrb_lin(const struct t
|
|
pos += wpa_ft_tlv_lin(tlvs1, pos, endpos);
|
|
pos += wpa_ft_tlv_lin(tlvs2, pos, endpos);
|
|
pos += wpa_ft_vlan_lin(vlan, pos, endpos);
|
|
+ pos += wpa_ft_rate_limit_lin(rate, pos, endpos);
|
|
|
|
/* validity check */
|
|
if (pos != endpos) {
|
|
@@ -526,7 +574,8 @@ static int wpa_ft_rrb_build(const u8 *ke
|
|
const struct tlv_list *tlvs_auth,
|
|
const struct vlan_description *vlan,
|
|
const u8 *src_addr, u8 type,
|
|
- u8 **packet, size_t *packet_len)
|
|
+ u8 **packet, size_t *packet_len,
|
|
+ const struct rate_description *rate)
|
|
{
|
|
u8 *plain = NULL, *auth = NULL, *pos, *tmp;
|
|
size_t plain_len = 0, auth_len = 0;
|
|
@@ -534,10 +583,10 @@ static int wpa_ft_rrb_build(const u8 *ke
|
|
size_t pad_len = 0;
|
|
|
|
*packet = NULL;
|
|
- if (wpa_ft_rrb_lin(tlvs_enc0, tlvs_enc1, vlan, &plain, &plain_len) < 0)
|
|
+ if (wpa_ft_rrb_lin(tlvs_enc0, tlvs_enc1, vlan, &plain, &plain_len, rate) < 0)
|
|
goto out;
|
|
|
|
- if (wpa_ft_rrb_lin(tlvs_auth, NULL, NULL, &auth, &auth_len) < 0)
|
|
+ if (wpa_ft_rrb_lin(tlvs_auth, NULL, NULL, &auth, &auth_len, NULL) < 0)
|
|
goto out;
|
|
|
|
*packet_len = sizeof(u16) + auth_len + plain_len;
|
|
@@ -700,6 +749,24 @@ static int wpa_ft_get_vlan(struct wpa_au
|
|
}
|
|
|
|
|
|
+static int wpa_ft_get_rate_limit(struct wpa_authenticator *wpa_auth,
|
|
+ const u8 *sta_addr, struct rate_description *rate)
|
|
+{
|
|
+ if (!wpa_auth->cb->get_rate_limit)
|
|
+ return -1;
|
|
+ return wpa_auth->cb->get_rate_limit(wpa_auth->cb_ctx, sta_addr, rate);
|
|
+}
|
|
+
|
|
+
|
|
+static int wpa_ft_set_rate_limit(struct wpa_authenticator *wpa_auth,
|
|
+ const u8 *sta_addr, struct rate_description *rate)
|
|
+{
|
|
+ if (!wpa_auth->cb->set_rate_limit)
|
|
+ return -1;
|
|
+ return wpa_auth->cb->set_rate_limit(wpa_auth->cb_ctx, sta_addr, rate);
|
|
+}
|
|
+
|
|
+
|
|
static int
|
|
wpa_ft_set_identity(struct wpa_authenticator *wpa_auth, const u8 *sta_addr,
|
|
const u8 *identity, size_t identity_len)
|
|
@@ -1025,7 +1092,7 @@ wpa_ft_rrb_seq_req(struct wpa_authentica
|
|
|
|
if (wpa_ft_rrb_build(key, key_len, NULL, NULL, seq_req_auth, NULL,
|
|
wpa_auth->addr, FT_PACKET_R0KH_R1KH_SEQ_REQ,
|
|
- &packet, &packet_len) < 0) {
|
|
+ &packet, &packet_len, NULL) < 0) {
|
|
item = NULL; /* some other seq resp might still accept this */
|
|
goto err;
|
|
}
|
|
@@ -1208,6 +1275,7 @@ struct wpa_ft_pmk_r0_sa {
|
|
u8 spa[ETH_ALEN];
|
|
int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
|
|
struct vlan_description *vlan;
|
|
+ struct rate_description *rate;
|
|
os_time_t expiration; /* 0 for no expiration */
|
|
u8 *identity;
|
|
size_t identity_len;
|
|
@@ -1226,6 +1294,7 @@ struct wpa_ft_pmk_r1_sa {
|
|
u8 spa[ETH_ALEN];
|
|
int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */
|
|
struct vlan_description *vlan;
|
|
+ struct rate_description *rate;
|
|
u8 *identity;
|
|
size_t identity_len;
|
|
u8 *radius_cui;
|
|
@@ -1254,6 +1323,7 @@ static void wpa_ft_free_pmk_r0(struct wp
|
|
|
|
os_memset(r0->pmk_r0, 0, PMK_LEN_MAX);
|
|
os_free(r0->vlan);
|
|
+ os_free(r0->rate);
|
|
os_free(r0->identity);
|
|
os_free(r0->radius_cui);
|
|
os_free(r0);
|
|
@@ -1307,6 +1377,7 @@ static void wpa_ft_free_pmk_r1(struct wp
|
|
eloop_cancel_timeout(wpa_ft_expire_pmk_r1, r1, NULL);
|
|
|
|
os_memset(r1->pmk_r1, 0, PMK_LEN_MAX);
|
|
+ os_free(r1->rate);
|
|
os_free(r1->vlan);
|
|
os_free(r1->identity);
|
|
os_free(r1->radius_cui);
|
|
@@ -1360,7 +1431,8 @@ static int wpa_ft_store_pmk_r0(struct wp
|
|
const struct vlan_description *vlan,
|
|
int expires_in, int session_timeout,
|
|
const u8 *identity, size_t identity_len,
|
|
- const u8 *radius_cui, size_t radius_cui_len)
|
|
+ const u8 *radius_cui, size_t radius_cui_len,
|
|
+ struct rate_description *rate)
|
|
{
|
|
struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
|
|
struct wpa_ft_pmk_r0_sa *r0;
|
|
@@ -1388,6 +1460,14 @@ static int wpa_ft_store_pmk_r0(struct wp
|
|
}
|
|
*r0->vlan = *vlan;
|
|
}
|
|
+ if (rate) {
|
|
+ r0->rate = os_zalloc(sizeof(*rate));
|
|
+ if (!r0->rate) {
|
|
+ bin_clear_free(r0, sizeof(*r0));
|
|
+ return -1;
|
|
+ }
|
|
+ *r0->rate = *rate;
|
|
+ }
|
|
if (identity) {
|
|
r0->identity = os_malloc(identity_len);
|
|
if (r0->identity) {
|
|
@@ -1447,7 +1527,8 @@ static int wpa_ft_store_pmk_r1(struct wp
|
|
const struct vlan_description *vlan,
|
|
int expires_in, int session_timeout,
|
|
const u8 *identity, size_t identity_len,
|
|
- const u8 *radius_cui, size_t radius_cui_len)
|
|
+ const u8 *radius_cui, size_t radius_cui_len,
|
|
+ struct rate_description *rate)
|
|
{
|
|
struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
|
|
int max_expires_in = wpa_auth->conf.r1_max_key_lifetime;
|
|
@@ -1477,6 +1558,14 @@ static int wpa_ft_store_pmk_r1(struct wp
|
|
}
|
|
*r1->vlan = *vlan;
|
|
}
|
|
+ if (rate) {
|
|
+ r1->rate = os_zalloc(sizeof(*rate));
|
|
+ if (!r1->rate) {
|
|
+ bin_clear_free(r1, sizeof(*r1));
|
|
+ return -1;
|
|
+ }
|
|
+ *r1->rate = *rate;
|
|
+ }
|
|
if (identity) {
|
|
r1->identity = os_malloc(identity_len);
|
|
if (r1->identity) {
|
|
@@ -1513,7 +1602,7 @@ int wpa_ft_fetch_pmk_r1(struct wpa_authe
|
|
struct vlan_description *vlan,
|
|
const u8 **identity, size_t *identity_len,
|
|
const u8 **radius_cui, size_t *radius_cui_len,
|
|
- int *session_timeout)
|
|
+ int *session_timeout, struct rate_description *rate)
|
|
{
|
|
struct wpa_ft_pmk_cache *cache = wpa_auth->ft_pmk_cache;
|
|
struct wpa_ft_pmk_r1_sa *r1;
|
|
@@ -1533,6 +1622,12 @@ int wpa_ft_fetch_pmk_r1(struct wpa_authe
|
|
*vlan = *r1->vlan;
|
|
if (vlan && !r1->vlan)
|
|
os_memset(vlan, 0, sizeof(*vlan));
|
|
+ if (rate) {
|
|
+ if (r1->rate)
|
|
+ *rate = *r1->rate;
|
|
+ else
|
|
+ memset(rate, 0, sizeof(*rate));
|
|
+ }
|
|
if (identity && identity_len) {
|
|
*identity = r1->identity;
|
|
*identity_len = r1->identity_len;
|
|
@@ -2059,7 +2154,7 @@ static int wpa_ft_pull_pmk_r1(struct wpa
|
|
|
|
if (wpa_ft_rrb_build(key, key_len, req_enc, NULL, req_auth, NULL,
|
|
sm->wpa_auth->addr, FT_PACKET_R0KH_R1KH_PULL,
|
|
- &packet, &packet_len) < 0)
|
|
+ &packet, &packet_len, NULL) < 0)
|
|
return -1;
|
|
|
|
ft_pending_req_ies = wpabuf_alloc_copy(ies, ies_len);
|
|
@@ -2088,6 +2183,7 @@ int wpa_ft_store_pmk_fils(struct wpa_sta
|
|
{
|
|
int expires_in = sm->wpa_auth->conf.r0_key_lifetime;
|
|
struct vlan_description vlan;
|
|
+ struct rate_description rate;
|
|
const u8 *identity, *radius_cui;
|
|
size_t identity_len, radius_cui_len;
|
|
int session_timeout;
|
|
@@ -2099,6 +2195,7 @@ int wpa_ft_store_pmk_fils(struct wpa_sta
|
|
MAC2STR(sm->addr));
|
|
return -1;
|
|
}
|
|
+ wpa_ft_get_rate_limit(sm->wpa_auth, sm->addr, &rate);
|
|
|
|
identity_len = wpa_ft_get_identity(sm->wpa_auth, sm->addr, &identity);
|
|
radius_cui_len = wpa_ft_get_radius_cui(sm->wpa_auth, sm->addr,
|
|
@@ -2108,7 +2205,7 @@ int wpa_ft_store_pmk_fils(struct wpa_sta
|
|
return wpa_ft_store_pmk_r0(sm->wpa_auth, sm->addr, pmk_r0, pmk_r0_len,
|
|
pmk_r0_name, sm->pairwise, &vlan, expires_in,
|
|
session_timeout, identity, identity_len,
|
|
- radius_cui, radius_cui_len);
|
|
+ radius_cui, radius_cui_len, &rate);
|
|
}
|
|
|
|
|
|
@@ -2172,6 +2269,7 @@ void wpa_auth_ft_store_keys(struct wpa_s
|
|
int psk_local = sm->wpa_auth->conf.ft_psk_generate_local;
|
|
int expires_in = sm->wpa_auth->conf.r0_key_lifetime;
|
|
struct vlan_description vlan;
|
|
+ struct rate_description rate;
|
|
const u8 *identity, *radius_cui;
|
|
size_t identity_len, radius_cui_len;
|
|
int session_timeout;
|
|
@@ -2185,6 +2283,8 @@ void wpa_auth_ft_store_keys(struct wpa_s
|
|
return;
|
|
}
|
|
|
|
+ wpa_ft_get_rate_limit(sm->wpa_auth, sm->addr, &rate);
|
|
+
|
|
identity_len = wpa_ft_get_identity(sm->wpa_auth, sm->addr, &identity);
|
|
radius_cui_len = wpa_ft_get_radius_cui(sm->wpa_auth, sm->addr,
|
|
&radius_cui);
|
|
@@ -2195,11 +2295,12 @@ void wpa_auth_ft_store_keys(struct wpa_s
|
|
pmk_r0_name,
|
|
sm->pairwise, &vlan, expires_in,
|
|
session_timeout, identity, identity_len,
|
|
- radius_cui, radius_cui_len);
|
|
+ radius_cui, radius_cui_len, &rate);
|
|
wpa_ft_store_pmk_r1(sm->wpa_auth, sm->addr, pmk_r1, key_len,
|
|
sm->pmk_r1_name, sm->pairwise, &vlan,
|
|
expires_in, session_timeout, identity,
|
|
- identity_len, radius_cui, radius_cui_len);
|
|
+ identity_len, radius_cui, radius_cui_len,
|
|
+ &rate);
|
|
}
|
|
|
|
|
|
@@ -3100,7 +3201,8 @@ static int wpa_ft_local_derive_pmk_r1(st
|
|
const u8 **radius_cui,
|
|
size_t *radius_cui_len,
|
|
int *out_session_timeout,
|
|
- size_t *pmk_r1_len)
|
|
+ size_t *pmk_r1_len,
|
|
+ struct rate_description *rate)
|
|
{
|
|
struct wpa_auth_config *conf = &wpa_auth->conf;
|
|
const struct wpa_ft_pmk_r0_sa *r0;
|
|
@@ -3136,7 +3238,8 @@ static int wpa_ft_local_derive_pmk_r1(st
|
|
out_pmk_r1_name,
|
|
sm->pairwise, r0->vlan, expires_in, session_timeout,
|
|
r0->identity, r0->identity_len,
|
|
- r0->radius_cui, r0->radius_cui_len);
|
|
+ r0->radius_cui, r0->radius_cui_len,
|
|
+ r0->rate);
|
|
|
|
*out_pairwise = sm->pairwise;
|
|
if (vlan) {
|
|
@@ -3146,6 +3249,13 @@ static int wpa_ft_local_derive_pmk_r1(st
|
|
os_memset(vlan, 0, sizeof(*vlan));
|
|
}
|
|
|
|
+ if (rate) {
|
|
+ if (r0->rate)
|
|
+ *rate = *r0->rate;
|
|
+ else
|
|
+ os_memset(rate, 0, sizeof(*rate));
|
|
+ }
|
|
+
|
|
if (identity && identity_len) {
|
|
*identity = r0->identity;
|
|
*identity_len = r0->identity_len;
|
|
@@ -3178,6 +3288,7 @@ static int wpa_ft_process_auth_req(struc
|
|
u8 *pos, *end;
|
|
int pairwise, session_timeout = 0;
|
|
struct vlan_description vlan;
|
|
+ struct rate_description rate = {};
|
|
const u8 *identity, *radius_cui;
|
|
size_t identity_len = 0, radius_cui_len = 0;
|
|
size_t pmk_r1_len, kdk_len, len;
|
|
@@ -3274,7 +3385,7 @@ static int wpa_ft_process_auth_req(struc
|
|
pmk_r1, &pmk_r1_len, &pairwise, &vlan,
|
|
&identity, &identity_len, &radius_cui,
|
|
&radius_cui_len,
|
|
- &session_timeout) == 0) {
|
|
+ &session_timeout, &rate) == 0) {
|
|
wpa_printf(MSG_DEBUG,
|
|
"FT: Found PMKR1Name (using SHA%zu) from local cache",
|
|
pmk_r1_len * 8);
|
|
@@ -3290,7 +3401,7 @@ static int wpa_ft_process_auth_req(struc
|
|
pmk_r1_name, pmk_r1, &pairwise,
|
|
&vlan, &identity, &identity_len,
|
|
&radius_cui, &radius_cui_len,
|
|
- &session_timeout, &pmk_r1_len) == 0) {
|
|
+ &session_timeout, &pmk_r1_len, &rate) == 0) {
|
|
wpa_printf(MSG_DEBUG,
|
|
"FT: Generated PMK-R1 based on local PMK-R0");
|
|
goto pmk_r1_derived;
|
|
@@ -3392,6 +3503,7 @@ pmk_r1_derived:
|
|
wpa_printf(MSG_DEBUG, "FT: Failed to configure VLAN");
|
|
goto out;
|
|
}
|
|
+ wpa_ft_set_rate_limit(sm->wpa_auth, sm->addr, &rate);
|
|
if (wpa_ft_set_identity(sm->wpa_auth, sm->addr,
|
|
identity, identity_len) < 0 ||
|
|
wpa_ft_set_radius_cui(sm->wpa_auth, sm->addr,
|
|
@@ -3973,7 +4085,7 @@ static int wpa_ft_rrb_build_r0(const u8
|
|
|
|
ret = wpa_ft_rrb_build(key, key_len, tlvs, sess_tlv, tlv_auth,
|
|
pmk_r0->vlan, src_addr, type,
|
|
- packet, packet_len);
|
|
+ packet, packet_len, pmk_r0->rate);
|
|
|
|
forced_memzero(pmk_r1, sizeof(pmk_r1));
|
|
|
|
@@ -4113,7 +4225,7 @@ static int wpa_ft_rrb_rx_pull(struct wpa
|
|
ret = wpa_ft_rrb_build(key, key_len, resp, NULL, resp_auth,
|
|
NULL, wpa_auth->addr,
|
|
FT_PACKET_R0KH_R1KH_RESP,
|
|
- &packet, &packet_len);
|
|
+ &packet, &packet_len, NULL);
|
|
} else {
|
|
ret = wpa_ft_rrb_build_r0(key, key_len, resp, r0, f_r1kh_id,
|
|
f_s1kh_id, resp_auth, wpa_auth->addr,
|
|
@@ -4165,11 +4277,15 @@ static int wpa_ft_rrb_rx_r1(struct wpa_a
|
|
size_t f_expires_in_len;
|
|
size_t f_identity_len, f_radius_cui_len;
|
|
size_t f_session_timeout_len;
|
|
+ size_t f_rate_len;
|
|
+ const u8 *f_rate;
|
|
int pairwise;
|
|
int ret = -1;
|
|
int expires_in;
|
|
int session_timeout;
|
|
struct vlan_description vlan;
|
|
+ struct rate_description rate;
|
|
+ int has_rate = 0;
|
|
size_t pmk_r1_len;
|
|
|
|
RRB_GET_AUTH(FT_RRB_R0KH_ID, r0kh_id, msgtype, -1);
|
|
@@ -4279,6 +4395,13 @@ static int wpa_ft_rrb_rx_r1(struct wpa_a
|
|
wpa_printf(MSG_DEBUG, "FT: vlan %d%s",
|
|
le_to_host16(vlan.untagged), vlan.tagged[0] ? "+" : "");
|
|
|
|
+ RRB_GET_OPTIONAL(FT_RRB_RATE_LIMIT, rate, msgtype, 2 * sizeof(le32));
|
|
+ if (f_rate) {
|
|
+ memcpy(&rate, f_rate, sizeof(rate));
|
|
+ rate.rx = le_to_host32(rate.rx);
|
|
+ rate.tx = le_to_host32(rate.tx);
|
|
+ has_rate = 1;
|
|
+ };
|
|
RRB_GET_OPTIONAL(FT_RRB_IDENTITY, identity, msgtype, -1);
|
|
if (f_identity)
|
|
wpa_hexdump_ascii(MSG_DEBUG, "FT: Identity", f_identity,
|
|
@@ -4301,7 +4424,7 @@ static int wpa_ft_rrb_rx_r1(struct wpa_a
|
|
f_pmk_r1_name,
|
|
pairwise, &vlan, expires_in, session_timeout,
|
|
f_identity, f_identity_len, f_radius_cui,
|
|
- f_radius_cui_len) < 0)
|
|
+ f_radius_cui_len, has_rate ? &rate : 0) < 0)
|
|
goto out;
|
|
|
|
ret = 0;
|
|
@@ -4614,7 +4737,7 @@ static int wpa_ft_rrb_rx_seq_req(struct
|
|
|
|
if (wpa_ft_rrb_build(key, key_len, NULL, NULL, seq_resp_auth, NULL,
|
|
wpa_auth->addr, FT_PACKET_R0KH_R1KH_SEQ_RESP,
|
|
- &packet, &packet_len) < 0)
|
|
+ &packet, &packet_len, NULL) < 0)
|
|
goto out;
|
|
|
|
wpa_ft_rrb_oui_send(wpa_auth, src_addr,
|