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:
parent
c903257fb1
commit
d144b7f34c
4 changed files with 117 additions and 0 deletions
|
@ -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:
|
control interface command received from the user is as below:
|
||||||
|
|
||||||
DSCP_RESP <[reset]>/<[solicited] [policy_id=1 status=0...]> [more]
|
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>>
|
||||||
|
|
|
@ -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 * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
|
||||||
char *buf, size_t *resp_len)
|
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) {
|
} else if (os_strncmp(buf, "DSCP_RESP ", 10) == 0) {
|
||||||
if (wpas_ctrl_iface_send_dscp_resp(wpa_s, buf + 10))
|
if (wpas_ctrl_iface_send_dscp_resp(wpa_s, buf + 10))
|
||||||
reply_len = -1;
|
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 {
|
} else {
|
||||||
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
|
||||||
reply_len = 16;
|
reply_len = 16;
|
||||||
|
|
|
@ -1159,6 +1159,7 @@ void wpas_dscp_deinit(struct wpa_supplicant *wpa_s)
|
||||||
wpa_printf(MSG_DEBUG, "QM: Clear all active DSCP policies");
|
wpa_printf(MSG_DEBUG, "QM: Clear all active DSCP policies");
|
||||||
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "clear_all");
|
wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DSCP_POLICY "clear_all");
|
||||||
wpa_s->dscp_req_dialog_token = 0;
|
wpa_s->dscp_req_dialog_token = 0;
|
||||||
|
wpa_s->dscp_query_dialog_token = 0;
|
||||||
wpa_s->connection_dscp = 0;
|
wpa_s->connection_dscp = 0;
|
||||||
if (wpa_s->wait_for_dscp_req) {
|
if (wpa_s->wait_for_dscp_req) {
|
||||||
wpa_s->wait_for_dscp_req = 0;
|
wpa_s->wait_for_dscp_req = 0;
|
||||||
|
@ -1410,3 +1411,77 @@ fail:
|
||||||
wpabuf_free(buf);
|
wpabuf_free(buf);
|
||||||
return ret;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -1514,6 +1514,7 @@ struct wpa_supplicant {
|
||||||
struct dl_list active_scs_ids;
|
struct dl_list active_scs_ids;
|
||||||
bool ongoing_scs_req;
|
bool ongoing_scs_req;
|
||||||
u8 dscp_req_dialog_token;
|
u8 dscp_req_dialog_token;
|
||||||
|
u8 dscp_query_dialog_token;
|
||||||
unsigned int enable_dscp_policy_capa:1;
|
unsigned int enable_dscp_policy_capa:1;
|
||||||
unsigned int connection_dscp:1;
|
unsigned int connection_dscp:1;
|
||||||
unsigned int wait_for_dscp_req: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);
|
struct dscp_resp_data *resp_data);
|
||||||
void wpas_handle_assoc_resp_qos_mgmt(struct wpa_supplicant *wpa_s,
|
void wpas_handle_assoc_resp_qos_mgmt(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *ies, size_t ies_len);
|
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,
|
int wpas_pasn_auth_start(struct wpa_supplicant *wpa_s,
|
||||||
const u8 *bssid, int akmp, int cipher,
|
const u8 *bssid, int akmp, int cipher,
|
||||||
|
|
Loading…
Reference in a new issue