]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Support vendor element configuration for AP mode from wpa_supplicant
authorChaoli Zhou <zchaoli@codeaurora.org>
Wed, 28 Jul 2021 10:51:08 +0000 (18:51 +0800)
committerJouni Malinen <j@w1.fi>
Thu, 30 Sep 2021 15:16:11 +0000 (18:16 +0300)
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>
wpa_supplicant/ap.c
wpa_supplicant/ap.h
wpa_supplicant/config.c
wpa_supplicant/config.h
wpa_supplicant/config_file.c
wpa_supplicant/ctrl_iface.c
wpa_supplicant/wpa_cli.c

index 415f08789fd3225cd1eeabc48b249d3fc55cecfe..13015ac6f872c78a1c2f750326ac1a90d29498f6 100644 (file)
@@ -763,6 +763,10 @@ no_wps:
                bss->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_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_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 */
 
 
index 6c6e94cdf6a28d60da3a7912ce898de9bf2f5b1e..7bc1b781e3ac4f24e7f2af0703e56d3d403d7dc4 100644 (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,
                                  char *buf, size_t len);
 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,
                                      struct dfs_event *radar);
index e8e9fd4326189229b29446a229902af2bc18dc78..6c4d67d40c37a7d4e5c026c66aa679850f488c85 100644 (file)
@@ -2951,6 +2951,7 @@ void wpa_config_free(struct wpa_config *config)
        os_free(config->ext_password_backend);
        os_free(config->sae_groups);
        wpabuf_free(config->ap_vendor_elements);
+       wpabuf_free(config->ap_assocresp_elements);
        os_free(config->osu_dir);
        os_free(config->bgscan);
        os_free(config->wowlan_triggers);
@@ -4913,9 +4914,9 @@ static int wpa_config_process_ap_vendor_elements(
        u8 *p;
 
        if (!len) {
-               wpa_printf(MSG_ERROR, "Line %d: invalid ap_vendor_elements",
-                          line);
-               return -1;
+               wpabuf_free(config->ap_vendor_elements);
+               config->ap_vendor_elements = NULL;
+               return 0;
        }
 
        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
 static int wpa_config_process_no_ctrl_interface(
        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(dtim_period), 0 },
        { INT(beacon_int), 0 },
+       { FUNC(ap_assocresp_elements), 0 },
        { FUNC(ap_vendor_elements), 0 },
        { INT_RANGE(ignore_old_scan_res, 0, 1), 0 },
        { FUNC(freq_list), 0 },
index 68679c6e380a7c8b31e5a856c231a5e96209ac52..0320d9eebb57e1f41cb7a03cf257b740c709922d 100644 (file)
@@ -1241,6 +1241,17 @@ struct wpa_config {
         */
        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
         *
index a535e3f08aadaab21a0570932d9d71c56d6b0435..1ad02b988a5ca04b8bd3756933ff7621a2ac0090 100644 (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)
                fprintf(f, "ignore_old_scan_res=%d\n",
                        config->ignore_old_scan_res);
index 8bdf5772fcbc922263cc3a1788a31d1959f14ce5..96667e4d8e1fbdb4683dbf283e071b7727ec7284 100644 (file)
@@ -12055,6 +12055,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strcmp(buf, "STOP_AP") == 0) {
                if (wpas_ap_stop_ap(wpa_s))
                        reply_len = -1;
+       } else if (os_strcmp(buf, "UPDATE_BEACON") == 0) {
+               if (wpas_ap_update_beacon(wpa_s))
+                       reply_len = -1;
 #endif /* CONFIG_AP */
        } else if (os_strcmp(buf, "SUSPEND") == 0) {
                wpas_notify_suspend(wpa_s->global);
index fea7b85e081d31b7775708c495acbf1da2dcf896..32d006f52071fadd8b1d5c65ddfe2284871d249c 100644 (file)
@@ -499,6 +499,7 @@ static char ** wpa_cli_complete_set(const char *str, int pos)
                "p2p_search_delay", "mac_addr", "rand_addr_lifetime",
                "preassoc_mac_addr", "key_mgmt_offload", "passive_scan",
                "reassoc_same_bss_optim", "wps_priority",
+               "ap_assocresp_elements",
 #ifdef CONFIG_TESTING_OPTIONS
                "ignore_auth_resp",
 #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);
 }
 
+
+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 */
 
 
@@ -3563,6 +3571,9 @@ static const struct wpa_cli_cmd wpa_cli_commands[] = {
          "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
          " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
          " = CSA parameters" },
+       { "update_beacon", wpa_cli_cmd_update_beacon, NULL,
+         cli_cmd_flag_none,
+         "= update Beacon frame contents"},
 #endif /* CONFIG_AP */
        { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
          "= notification of suspend/hibernate" },