Allow AP mode extended capabilities to be overridden

The new hostapd configuration parameters ext_capa_mask and ext_capa can
now be used to mask out or add extended capability bits. While this is
not without CONFIG_TESTING_OPTIONS, the main use case for this is for
testing purposes.

Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2021-03-22 11:29:31 +02:00
parent 7365eb43ea
commit 60974eb3f6
3 changed files with 35 additions and 1 deletions

View file

@ -2332,6 +2332,22 @@ fail:
#endif /* CONFIG_DPP2 */ #endif /* CONFIG_DPP2 */
static int get_hex_config(u8 *buf, size_t max_len, int line,
const char *field, const char *val)
{
size_t hlen = os_strlen(val), len = hlen / 2;
u8 tmp[EXT_CAPA_MAX_LEN];
os_memset(tmp, 0, EXT_CAPA_MAX_LEN);
if (hlen & 1 || len > EXT_CAPA_MAX_LEN || hexstr2bin(val, tmp, len)) {
wpa_printf(MSG_ERROR, "Line %d: Invalid %s", line, field);
return -1;
}
os_memcpy(buf, tmp, EXT_CAPA_MAX_LEN);
return 0;
}
static int hostapd_config_fill(struct hostapd_config *conf, static int hostapd_config_fill(struct hostapd_config *conf,
struct hostapd_bss_config *bss, struct hostapd_bss_config *bss,
const char *buf, char *pos, int line) const char *buf, char *pos, int line)
@ -4679,6 +4695,14 @@ static int hostapd_config_fill(struct hostapd_config *conf,
} else if (os_strcmp(buf, "pasn_comeback_after") == 0) { } else if (os_strcmp(buf, "pasn_comeback_after") == 0) {
bss->pasn_comeback_after = atoi(pos); bss->pasn_comeback_after = atoi(pos);
#endif /* CONFIG_PASN */ #endif /* CONFIG_PASN */
} else if (os_strcmp(buf, "ext_capa_mask") == 0) {
if (get_hex_config(bss->ext_capa_mask, EXT_CAPA_MAX_LEN,
line, "ext_capa_mask", pos))
return 1;
} else if (os_strcmp(buf, "ext_capa") == 0) {
if (get_hex_config(bss->ext_capa, EXT_CAPA_MAX_LEN,
line, "ext_capa", pos))
return 1;
} else { } else {
wpa_printf(MSG_ERROR, wpa_printf(MSG_ERROR,
"Line %d: unknown configuration item '%s'", "Line %d: unknown configuration item '%s'",

View file

@ -267,6 +267,8 @@ struct airtime_sta_weight {
u8 addr[ETH_ALEN]; u8 addr[ETH_ALEN];
}; };
#define EXT_CAPA_MAX_LEN 15
/** /**
* struct hostapd_bss_config - Per-BSS configuration * struct hostapd_bss_config - Per-BSS configuration
*/ */
@ -889,6 +891,9 @@ struct hostapd_bss_config {
#endif /* CONFIG_PASN */ #endif /* CONFIG_PASN */
unsigned int unsol_bcast_probe_resp_interval; unsigned int unsol_bcast_probe_resp_interval;
u8 ext_capa_mask[EXT_CAPA_MAX_LEN];
u8 ext_capa[EXT_CAPA_MAX_LEN];
}; };
/** /**

View file

@ -451,7 +451,7 @@ static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx)
u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
{ {
u8 *pos = eid; u8 *pos = eid;
u8 len = 12, i; u8 len = EXT_CAPA_MAX_LEN, i;
if (len < hapd->iface->extended_capa_len) if (len < hapd->iface->extended_capa_len)
len = hapd->iface->extended_capa_len; len = hapd->iface->extended_capa_len;
@ -465,6 +465,11 @@ u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid)
*pos &= ~hapd->iface->extended_capa_mask[i]; *pos &= ~hapd->iface->extended_capa_mask[i];
*pos |= hapd->iface->extended_capa[i]; *pos |= hapd->iface->extended_capa[i];
} }
if (i < EXT_CAPA_MAX_LEN) {
*pos &= ~hapd->conf->ext_capa_mask[i];
*pos |= hapd->conf->ext_capa[i];
}
} }
while (len > 0 && eid[1 + len] == 0) { while (len > 0 && eid[1 + len] == 0) {