]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
DSCP: Add support to send DSCP Policy Query frame
authorVeerendranath Jakkam <vjakkam@codeaurora.org>
Mon, 6 Sep 2021 09:26:51 +0000 (14:56 +0530)
committerJouni Malinen <j@w1.fi>
Thu, 30 Sep 2021 13:56:56 +0000 (16:56 +0300)
Add support to send DSCP Policy Query frame using a new control
interface command DSCP_QUERY. This includes support for a wildcard DSCP
query and a DSCP query with a single Domain Name attribute.

Signed-off-by: Veerendranath Jakkam <vjakkam@codeaurora.org>
wpa_supplicant/README
wpa_supplicant/ctrl_iface.c
wpa_supplicant/robust_av.c
wpa_supplicant/wpa_supplicant_i.h

index 98cbf3e0a74ebded7bbbe071c9e98507ddf3c753..05f15ff46bdab45e29c879599e443ef188ac30cc 100644 (file)
@@ -1154,3 +1154,10 @@ associated AP.  wpa_supplicant sends DSCP policy response based on the
 control interface command received from the user is as below:
 
 DSCP_RESP <[reset]>/<[solicited] [policy_id=1 status=0...]> [more]
+
+DSCP Query:
+DSCP Policy Query enables a STA to query its associated AP for DSCP
+policies applicable to the STA. Currently, this includes support to send
+a wildcard DSCP query or a DSCP query with a single domain name
+attribute. The command format for the DSCP query command is as follows:
+DSCP_QUERY <wildcard>/<domain_name=<string>>
index 17f21e91a15ff40c370d80e03b4d42ba616ded17..8bdf5772fcbc922263cc3a1788a31d1959f14ce5 100644 (file)
@@ -11455,6 +11455,35 @@ fail:
 }
 
 
+static int wpas_ctrl_iface_send_dscp_query(struct wpa_supplicant *wpa_s,
+                                          const char *cmd)
+{
+       char *pos;
+
+       /*
+        * format:
+        * Wildcard DSCP query
+        * <wildcard>
+        *
+        * DSCP query with a domain name attribute:
+        * [domain_name=<string>]
+        */
+
+       if (os_strstr(cmd, "wildcard")) {
+               wpa_printf(MSG_DEBUG, "QM: Send wildcard DSCP policy query");
+               return wpas_send_dscp_query(wpa_s, NULL, 0);
+       }
+
+       pos = os_strstr(cmd, "domain_name=");
+       if (!pos || !os_strlen(pos + 12)) {
+               wpa_printf(MSG_ERROR, "QM: Domain name not preset");
+               return -1;
+       }
+
+       return wpas_send_dscp_query(wpa_s, pos + 12, os_strlen(pos + 12));
+}
+
+
 char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
                                         char *buf, size_t *resp_len)
 {
@@ -12386,6 +12415,9 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
        } else if (os_strncmp(buf, "DSCP_RESP ", 10) == 0) {
                if (wpas_ctrl_iface_send_dscp_resp(wpa_s, buf + 10))
                        reply_len = -1;
+       } else if (os_strncmp(buf, "DSCP_QUERY ", 11) == 0) {
+               if (wpas_ctrl_iface_send_dscp_query(wpa_s, buf + 11))
+                       reply_len = -1;
        } else {
                os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
                reply_len = 16;
index 4eabf2448b4bf6baf21ed678293404aae19febc6..770c8fcab1895c2595b3087deecc4d357d5b37e6 100644 (file)
@@ -1159,6 +1159,7 @@ void wpas_dscp_deinit(struct wpa_supplicant *wpa_s)
        wpa_printf(MSG_DEBUG, "QM: Clear all active DSCP policies");
        wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "clear_all");
        wpa_s->dscp_req_dialog_token = 0;
+       wpa_s->dscp_query_dialog_token = 0;
        wpa_s->connection_dscp = 0;
        if (wpa_s->wait_for_dscp_req) {
                wpa_s->wait_for_dscp_req = 0;
@@ -1410,3 +1411,77 @@ fail:
        wpabuf_free(buf);
        return ret;
 }
+
+
+int wpas_send_dscp_query(struct wpa_supplicant *wpa_s, const char *domain_name,
+                        size_t domain_name_length)
+{
+       struct wpabuf *buf = NULL;
+       int ret, dscp_query_size;
+
+       if (wpa_s->wpa_state != WPA_COMPLETED || !wpa_s->current_ssid)
+               return -1;
+
+       if (!wpa_s->connection_dscp) {
+               wpa_printf(MSG_ERROR,
+                          "QM: Failed to send DSCP query - DSCP capability not enabled for the current association");
+               return -1;
+       }
+
+       if (wpa_s->wait_for_dscp_req) {
+               wpa_printf(MSG_INFO, "QM: Wait until AP sends a DSCP request");
+               return -1;
+       }
+
+#define DOMAIN_NAME_OFFSET (4 /* OUI */ + 1 /* Attr Id */ + 1 /* Attr len */)
+
+       if (domain_name_length > 255 - DOMAIN_NAME_OFFSET) {
+               wpa_printf(MSG_ERROR, "QM: Too long domain name");
+               return -1;
+       }
+
+       dscp_query_size = 1 + /* Category */
+                         4 + /* OUI Type */
+                         1 + /* OUI subtype */
+                         1; /* Dialog Token */
+       if (domain_name && domain_name_length)
+               dscp_query_size += 1 + /* Element ID */
+                       1 + /* IE Length */
+                       DOMAIN_NAME_OFFSET + domain_name_length;
+
+       buf = wpabuf_alloc(dscp_query_size);
+       if (!buf) {
+               wpa_printf(MSG_ERROR, "QM: Failed to allocate DSCP query");
+               return -1;
+       }
+
+       wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC_PROTECTED);
+       wpabuf_put_be32(buf, QM_ACTION_VENDOR_TYPE);
+       wpabuf_put_u8(buf, QM_DSCP_POLICY_QUERY);
+       wpa_s->dscp_query_dialog_token++;
+       if (wpa_s->dscp_query_dialog_token == 0)
+               wpa_s->dscp_query_dialog_token++;
+       wpabuf_put_u8(buf, wpa_s->dscp_query_dialog_token);
+
+       if (domain_name && domain_name_length) {
+               /* Domain Name attribute */
+               wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
+               wpabuf_put_u8(buf, DOMAIN_NAME_OFFSET + domain_name_length);
+               wpabuf_put_be32(buf, QM_IE_VENDOR_TYPE);
+               wpabuf_put_u8(buf, QM_ATTR_DOMAIN_NAME);
+               wpabuf_put_u8(buf, domain_name_length);
+               wpabuf_put_data(buf, domain_name, domain_name_length);
+       }
+#undef DOMAIN_NAME_OFFSET
+
+       ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid,
+                                 wpa_s->own_addr, wpa_s->bssid,
+                                 wpabuf_head(buf), wpabuf_len(buf), 0);
+       if (ret < 0) {
+               wpa_dbg(wpa_s, MSG_ERROR, "QM: Failed to send DSCP query");
+               wpa_s->dscp_query_dialog_token--;
+       }
+
+       wpabuf_free(buf);
+       return ret;
+}
index 428dfe8e6a5ce7f2ea9c55a3e1ba12cd039f43bb..47d0cabbef3c3b40521386c6919af013f5ddfe51 100644 (file)
@@ -1514,6 +1514,7 @@ struct wpa_supplicant {
        struct dl_list active_scs_ids;
        bool ongoing_scs_req;
        u8 dscp_req_dialog_token;
+       u8 dscp_query_dialog_token;
        unsigned int enable_dscp_policy_capa:1;
        unsigned int connection_dscp:1;
        unsigned int wait_for_dscp_req:1;
@@ -1865,6 +1866,8 @@ int wpas_send_dscp_response(struct wpa_supplicant *wpa_s,
                            struct dscp_resp_data *resp_data);
 void wpas_handle_assoc_resp_qos_mgmt(struct wpa_supplicant *wpa_s,
                                     const u8 *ies, size_t ies_len);
+int wpas_send_dscp_query(struct wpa_supplicant *wpa_s, const char *domain_name,
+                        size_t domain_name_length);
 
 int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
                         const u8 *bssid, int akmp, int cipher,