Support vendor element configuration for AP mode from wpa_supplicant

Support adding/deleting vendor elements dynamically for AP mode while it
is started by wpa_supplicant instead of hostapd which already supported
this. This adds ap_assocresp_elements global parameter and UPDATE_BEACON
control interface command to take the changed values into effect.

Usage in wpa_cli:
Add vendor IE for (Re)Association Response frames
> set ap_assocresp_elements=xxxx
Add vendor IE for Beacon/Probe Response frames
> set ap_vendor_elements=xxxx

Delete vendor IE from (Re)Association Response frames
> set ap_assocresp_elements
Delete vendor IE from Beacon/Probe Response frames
> set ap_vendor_elements

To make vendor IE changes take effect
> update_beacon

Signed-off-by: Chaoli Zhou <zchaoli@codeaurora.org>
This commit is contained in:
Chaoli Zhou 2021-07-28 18:51:08 +08:00 committed by Jouni Malinen
parent 7dc0e9cf47
commit 9651deba52
7 changed files with 98 additions and 3 deletions

View file

@ -763,6 +763,10 @@ no_wps:
bss->vendor_elements = bss->vendor_elements =
wpabuf_dup(wpa_s->conf->ap_vendor_elements); wpabuf_dup(wpa_s->conf->ap_vendor_elements);
} }
if (wpa_s->conf->ap_assocresp_elements) {
bss->assocresp_elements =
wpabuf_dup(wpa_s->conf->ap_assocresp_elements);
}
bss->ftm_responder = wpa_s->conf->ftm_responder; bss->ftm_responder = wpa_s->conf->ftm_responder;
bss->ftm_initiator = wpa_s->conf->ftm_initiator; bss->ftm_initiator = wpa_s->conf->ftm_initiator;
@ -1813,6 +1817,32 @@ int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd)
#endif /* CONFIG_MESH */ #endif /* CONFIG_MESH */
#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ #endif /* CONFIG_PMKSA_CACHE_EXTERNAL */
int wpas_ap_update_beacon(struct wpa_supplicant *wpa_s)
{
struct hostapd_data *hapd;
if (!wpa_s->ap_iface)
return -1;
hapd = wpa_s->ap_iface->bss[0];
wpabuf_free(hapd->conf->assocresp_elements);
hapd->conf->assocresp_elements = NULL;
if (wpa_s->conf->ap_assocresp_elements) {
hapd->conf->assocresp_elements =
wpabuf_dup(wpa_s->conf->ap_assocresp_elements);
}
wpabuf_free(hapd->conf->vendor_elements);
hapd->conf->vendor_elements = NULL;
if (wpa_s->conf->ap_vendor_elements) {
hapd->conf->vendor_elements =
wpabuf_dup(wpa_s->conf->ap_vendor_elements);
}
return ieee802_11_set_beacon(hapd);
}
#endif /* CONFIG_CTRL_IFACE */ #endif /* CONFIG_CTRL_IFACE */

View file

@ -88,6 +88,7 @@ void wpas_ap_pmksa_cache_flush(struct wpa_supplicant *wpa_s);
int wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr, int wpas_ap_pmksa_cache_list_mesh(struct wpa_supplicant *wpa_s, const u8 *addr,
char *buf, size_t len); char *buf, size_t len);
int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd); int wpas_ap_pmksa_cache_add_external(struct wpa_supplicant *wpa_s, char *cmd);
int wpas_ap_update_beacon(struct wpa_supplicant *wpa_s);
void wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s, void wpas_ap_event_dfs_radar_detected(struct wpa_supplicant *wpa_s,
struct dfs_event *radar); struct dfs_event *radar);

View file

@ -2951,6 +2951,7 @@ void wpa_config_free(struct wpa_config *config)
os_free(config->ext_password_backend); os_free(config->ext_password_backend);
os_free(config->sae_groups); os_free(config->sae_groups);
wpabuf_free(config->ap_vendor_elements); wpabuf_free(config->ap_vendor_elements);
wpabuf_free(config->ap_assocresp_elements);
os_free(config->osu_dir); os_free(config->osu_dir);
os_free(config->bgscan); os_free(config->bgscan);
os_free(config->wowlan_triggers); os_free(config->wowlan_triggers);
@ -4913,9 +4914,9 @@ static int wpa_config_process_ap_vendor_elements(
u8 *p; u8 *p;
if (!len) { if (!len) {
wpa_printf(MSG_ERROR, "Line %d: invalid ap_vendor_elements", wpabuf_free(config->ap_vendor_elements);
line); config->ap_vendor_elements = NULL;
return -1; return 0;
} }
tmp = wpabuf_alloc(len); tmp = wpabuf_alloc(len);
@ -4941,6 +4942,31 @@ static int wpa_config_process_ap_vendor_elements(
} }
static int wpa_config_process_ap_assocresp_elements(
const struct global_parse_data *data,
struct wpa_config *config, int line, const char *pos)
{
struct wpabuf *tmp;
if (!*pos) {
wpabuf_free(config->ap_assocresp_elements);
config->ap_assocresp_elements = NULL;
return 0;
}
tmp = wpabuf_parse_bin(pos);
if (!tmp) {
wpa_printf(MSG_ERROR, "Line %d: invalid ap_assocresp_elements",
line);
return -1;
}
wpabuf_free(config->ap_assocresp_elements);
config->ap_assocresp_elements = tmp;
return 0;
}
#ifdef CONFIG_CTRL_IFACE #ifdef CONFIG_CTRL_IFACE
static int wpa_config_process_no_ctrl_interface( static int wpa_config_process_no_ctrl_interface(
const struct global_parse_data *data, const struct global_parse_data *data,
@ -5155,6 +5181,7 @@ static const struct global_parse_data global_fields[] = {
{ INT_RANGE(sae_pmkid_in_assoc, 0, 1), 0 }, { INT_RANGE(sae_pmkid_in_assoc, 0, 1), 0 },
{ INT(dtim_period), 0 }, { INT(dtim_period), 0 },
{ INT(beacon_int), 0 }, { INT(beacon_int), 0 },
{ FUNC(ap_assocresp_elements), 0 },
{ FUNC(ap_vendor_elements), 0 }, { FUNC(ap_vendor_elements), 0 },
{ INT_RANGE(ignore_old_scan_res, 0, 1), 0 }, { INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
{ FUNC(freq_list), 0 }, { FUNC(freq_list), 0 },

View file

@ -1241,6 +1241,17 @@ struct wpa_config {
*/ */
struct wpabuf *ap_vendor_elements; struct wpabuf *ap_vendor_elements;
/**
* ap_assocresp_elements: Vendor specific elements for (Re)Association
* Response frames
*
* This parameter can be used to define additional vendor specific
* elements for (Re)Association Response frames in AP/P2P GO mode. The
* format for these element(s) is a hexdump of the raw information
* elements (id+len+payload for one or more elements).
*/
struct wpabuf *ap_assocresp_elements;
/** /**
* ignore_old_scan_res - Ignore scan results older than request * ignore_old_scan_res - Ignore scan results older than request
* *

View file

@ -1364,6 +1364,18 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config)
} }
} }
if (config->ap_assocresp_elements) {
int i, len = wpabuf_len(config->ap_assocresp_elements);
const u8 *p = wpabuf_head_u8(config->ap_assocresp_elements);
if (len > 0) {
fprintf(f, "ap_assocresp_elements=");
for (i = 0; i < len; i++)
fprintf(f, "%02x", *p++);
fprintf(f, "\n");
}
}
if (config->ignore_old_scan_res) if (config->ignore_old_scan_res)
fprintf(f, "ignore_old_scan_res=%d\n", fprintf(f, "ignore_old_scan_res=%d\n",
config->ignore_old_scan_res); config->ignore_old_scan_res);

View file

@ -12055,6 +12055,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strcmp(buf, "STOP_AP") == 0) { } else if (os_strcmp(buf, "STOP_AP") == 0) {
if (wpas_ap_stop_ap(wpa_s)) if (wpas_ap_stop_ap(wpa_s))
reply_len = -1; reply_len = -1;
} else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
if (wpas_ap_update_beacon(wpa_s))
reply_len = -1;
#endif /* CONFIG_AP */ #endif /* CONFIG_AP */
} else if (os_strcmp(buf, "SUSPEND") == 0) { } else if (os_strcmp(buf, "SUSPEND") == 0) {
wpas_notify_suspend(wpa_s->global); wpas_notify_suspend(wpa_s->global);

View file

@ -499,6 +499,7 @@ static char ** wpa_cli_complete_set(const char *str, int pos)
"p2p_search_delay", "mac_addr", "rand_addr_lifetime", "p2p_search_delay", "mac_addr", "rand_addr_lifetime",
"preassoc_mac_addr", "key_mgmt_offload", "passive_scan", "preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
"reassoc_same_bss_optim", "wps_priority", "reassoc_same_bss_optim", "wps_priority",
"ap_assocresp_elements",
#ifdef CONFIG_TESTING_OPTIONS #ifdef CONFIG_TESTING_OPTIONS
"ignore_auth_resp", "ignore_auth_resp",
#endif /* CONFIG_TESTING_OPTIONS */ #endif /* CONFIG_TESTING_OPTIONS */
@ -2037,6 +2038,13 @@ static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv); return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
} }
static int wpa_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
char *argv[])
{
return wpa_ctrl_command(ctrl, "UPDATE_BEACON");
}
#endif /* CONFIG_AP */ #endif /* CONFIG_AP */
@ -3563,6 +3571,9 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
"<cs_count> <freq> [sec_channel_offset=] [center_freq1=]" "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
" [center_freq2=] [bandwidth=] [blocktx] [ht|vht]" " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
" = CSA parameters" }, " = CSA parameters" },
{ "update_beacon", wpa_cli_cmd_update_beacon, NULL,
cli_cmd_flag_none,
"= update Beacon frame contents"},
#endif /* CONFIG_AP */ #endif /* CONFIG_AP */
{ "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none, { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
"= notification of suspend/hibernate" }, "= notification of suspend/hibernate" },