DSCP: Add support to send DSCP Policy Query frame

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>
This commit is contained in:
Veerendranath Jakkam 2021-09-06 14:56:51 +05:30 committed by Jouni Malinen
parent c903257fb1
commit d144b7f34c
4 changed files with 117 additions and 0 deletions

View 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>>

View 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;

View 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;
}

View 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,