dbus: Add support for vendor specific elements
The new methods are 1. VendorElemAdd "i" "ay" i=integer ay=array of bytes 2. VendorElemGet "i" i=integer (output array of bytes) 3. VendorElemRem "i" "ay" i=integer ay=array of bytes These provide functionality similar to the control interface commands VENDOR_ELEM_ADD, VENDOR_ELEM_GET, and VENDOR_ELEM_REMOVE. Signed-off-by: Avichal Agarwal <avichal.a@samsung.com> Signed-off-by: Purushottam Kushwaha <p.kushwaha@samsung.com> Signed-off-by: Kyeong-Chae Lim <kcya.lim@samsung.com> Signed-off-by: Mayank Haarit <mayank.h@samsung.com> Signed-off-by: Dilshad Ahmad <dilshad.a@samsung.com> [VendorElemGet to return array of bytes instead of string; cleanup] Signed-off-by: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
b4e1e99577
commit
af041f997d
7 changed files with 325 additions and 86 deletions
|
@ -455,6 +455,58 @@ fi.w1.wpa_supplicant1.CreateInterface.
|
|||
<dd>Initiating the TDLS operation failed for an unknown reason.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>
|
||||
<h3>VendorElemAdd ( i: frame_id, ay: ielems ) --> nothing</h3>
|
||||
<p>Add Vendor Elements to corresponding frame ID.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt>i : frame_id</dt>
|
||||
<dd>Frame ID for which Vendor specific IE is to be added.</dd>
|
||||
<dt>ay : ielems</dt>
|
||||
<dd>Information Element(s).</dd>
|
||||
</dl>
|
||||
<h4>Possible errors</h4>
|
||||
<dl>
|
||||
<dt>fi.w1.wpa_supplicant1.InvalidArgs</dt>
|
||||
<dd>The "ielems" argument is not a properly formatted or size mismatch.</dd>
|
||||
<dt>fi.w1.wpa_supplicant1.NoMemory</dt>
|
||||
<dd>Needed memory was not possible to get allocated.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>
|
||||
<h3>VendorElemGet ( i: frame_id ) --> ay: ielems</h3>
|
||||
<p>Get Vendor Elements of corresponding frame ID.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt>i : frame_id</dt>
|
||||
<dd>Frame ID for which Vendor specific IE is being queried.</dd>
|
||||
<dt>ay : ielems</dt>
|
||||
<dd>Information Element(s).</dd>
|
||||
</dl>
|
||||
<h4>Possible errors</h4>
|
||||
<dl>
|
||||
<dt>fi.w1.wpa_supplicant1.InvalidArgs</dt>
|
||||
<dd>The "frame_id" argument is not valid.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>
|
||||
<h3>VendorElemRem ( i: frame_id, ay: ielems ) --> nothing</h3>
|
||||
<p>Remove Vendor Elements of corresponding frame ID.</p>
|
||||
<h4>Arguments</h4>
|
||||
<dl>
|
||||
<dt>i : frame_id</dt>
|
||||
<dd>Frame ID for which Vendor specific IE is to be removed.</dd>
|
||||
<dt>ay : ielems</dt>
|
||||
<dd>Information Element(s) OR * to remove all.</dd>
|
||||
</dl>
|
||||
<h4>Possible errors</h4>
|
||||
<dl>
|
||||
<dt>fi.w1.wpa_supplicant1.InvalidArgs</dt>
|
||||
<dd>The "ielems" argument is not a properly formatted or size mismatch.</dd>
|
||||
<dt>fi.w1.wpa_supplicant1.NoMemory</dt>
|
||||
<dd>Needed memory was not possible to get allocated.</dd>
|
||||
</dl>
|
||||
</li>
|
||||
<li>
|
||||
<h3>SaveConfig ( ) --> nothing</h3>
|
||||
<p>Save configuration to the configuration file.</p>
|
||||
|
|
|
@ -7844,61 +7844,6 @@ static int wpas_ctrl_event_test(struct wpa_supplicant *wpa_s, const char *cmd)
|
|||
#endif /* CONFIG_TESTING_OPTIONS */
|
||||
|
||||
|
||||
static void wpas_ctrl_vendor_elem_update(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
unsigned int i;
|
||||
char buf[30];
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Update vendor elements");
|
||||
|
||||
for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
|
||||
if (wpa_s->vendor_elem[i]) {
|
||||
int res;
|
||||
|
||||
res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
|
||||
if (!os_snprintf_error(sizeof(buf), res)) {
|
||||
wpa_hexdump_buf(MSG_DEBUG, buf,
|
||||
wpa_s->vendor_elem[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (wpa_s->parent == wpa_s &&
|
||||
wpa_s->global->p2p &&
|
||||
!wpa_s->global->p2p_disabled)
|
||||
p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
|
||||
#endif /* CONFIG_P2P */
|
||||
}
|
||||
|
||||
|
||||
static struct wpa_supplicant *
|
||||
wpas_ctrl_vendor_elem_iface(struct wpa_supplicant *wpa_s,
|
||||
enum wpa_vendor_elem_frame frame)
|
||||
{
|
||||
switch (frame) {
|
||||
#ifdef CONFIG_P2P
|
||||
case VENDOR_ELEM_PROBE_REQ_P2P:
|
||||
case VENDOR_ELEM_PROBE_RESP_P2P:
|
||||
case VENDOR_ELEM_PROBE_RESP_P2P_GO:
|
||||
case VENDOR_ELEM_BEACON_P2P_GO:
|
||||
case VENDOR_ELEM_P2P_PD_REQ:
|
||||
case VENDOR_ELEM_P2P_PD_RESP:
|
||||
case VENDOR_ELEM_P2P_GO_NEG_REQ:
|
||||
case VENDOR_ELEM_P2P_GO_NEG_RESP:
|
||||
case VENDOR_ELEM_P2P_GO_NEG_CONF:
|
||||
case VENDOR_ELEM_P2P_INV_REQ:
|
||||
case VENDOR_ELEM_P2P_INV_RESP:
|
||||
case VENDOR_ELEM_P2P_ASSOC_REQ:
|
||||
case VENDOR_ELEM_P2P_ASSOC_RESP:
|
||||
return wpa_s->parent;
|
||||
#endif /* CONFIG_P2P */
|
||||
default:
|
||||
return wpa_s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
|
||||
{
|
||||
char *pos = cmd;
|
||||
|
@ -7910,7 +7855,7 @@ static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
|
|||
frame = atoi(pos);
|
||||
if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
|
||||
return -1;
|
||||
wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
|
||||
wpa_s = wpas_vendor_elem(wpa_s, frame);
|
||||
|
||||
pos = os_strchr(pos, ' ');
|
||||
if (pos == NULL)
|
||||
|
@ -7941,7 +7886,7 @@ static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
|
|||
|
||||
if (wpa_s->vendor_elem[frame] == NULL) {
|
||||
wpa_s->vendor_elem[frame] = buf;
|
||||
wpas_ctrl_vendor_elem_update(wpa_s);
|
||||
wpas_vendor_elem_update(wpa_s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -7952,7 +7897,7 @@ static int wpas_ctrl_vendor_elem_add(struct wpa_supplicant *wpa_s, char *cmd)
|
|||
|
||||
wpabuf_put_buf(wpa_s->vendor_elem[frame], buf);
|
||||
wpabuf_free(buf);
|
||||
wpas_ctrl_vendor_elem_update(wpa_s);
|
||||
wpas_vendor_elem_update(wpa_s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -7965,7 +7910,7 @@ static int wpas_ctrl_vendor_elem_get(struct wpa_supplicant *wpa_s, char *cmd,
|
|||
|
||||
if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
|
||||
return -1;
|
||||
wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
|
||||
wpa_s = wpas_vendor_elem(wpa_s, frame);
|
||||
|
||||
if (wpa_s->vendor_elem[frame] == NULL)
|
||||
return 0;
|
||||
|
@ -7983,12 +7928,12 @@ static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
|
|||
size_t len;
|
||||
u8 *buf;
|
||||
struct ieee802_11_elems elems;
|
||||
u8 *ie, *end;
|
||||
int res;
|
||||
|
||||
frame = atoi(pos);
|
||||
if (frame < 0 || frame >= NUM_VENDOR_ELEM_FRAMES)
|
||||
return -1;
|
||||
wpa_s = wpas_ctrl_vendor_elem_iface(wpa_s, frame);
|
||||
wpa_s = wpas_vendor_elem(wpa_s, frame);
|
||||
|
||||
pos = os_strchr(pos, ' ');
|
||||
if (pos == NULL)
|
||||
|
@ -7998,7 +7943,7 @@ static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
|
|||
if (*pos == '*') {
|
||||
wpabuf_free(wpa_s->vendor_elem[frame]);
|
||||
wpa_s->vendor_elem[frame] = NULL;
|
||||
wpas_ctrl_vendor_elem_update(wpa_s);
|
||||
wpas_vendor_elem_update(wpa_s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -8026,31 +7971,9 @@ static int wpas_ctrl_vendor_elem_remove(struct wpa_supplicant *wpa_s, char *cmd)
|
|||
return -1;
|
||||
}
|
||||
|
||||
ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
|
||||
end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
|
||||
|
||||
for (; ie + 1 < end; ie += 2 + ie[1]) {
|
||||
if (ie + len > end)
|
||||
break;
|
||||
if (os_memcmp(ie, buf, len) != 0)
|
||||
continue;
|
||||
|
||||
if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
|
||||
wpabuf_free(wpa_s->vendor_elem[frame]);
|
||||
wpa_s->vendor_elem[frame] = NULL;
|
||||
} else {
|
||||
os_memmove(ie, ie + len,
|
||||
end - (ie + len));
|
||||
wpa_s->vendor_elem[frame]->used -= len;
|
||||
}
|
||||
os_free(buf);
|
||||
wpas_ctrl_vendor_elem_update(wpa_s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = wpas_vendor_elem_remove(wpa_s, frame, buf, len);
|
||||
os_free(buf);
|
||||
|
||||
return -1;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3070,6 +3070,30 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
|
|||
}
|
||||
},
|
||||
#endif /* CONFIG_TDLS */
|
||||
{ "VendorElemAdd", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||
(WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_add,
|
||||
{
|
||||
{ "frame_id", "i", ARG_IN },
|
||||
{ "ielems", "ay", ARG_IN },
|
||||
END_ARGS
|
||||
}
|
||||
},
|
||||
{ "VendorElemGet", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||
(WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_get,
|
||||
{
|
||||
{ "frame_id", "i", ARG_IN },
|
||||
{ "ielems", "ay", ARG_OUT },
|
||||
END_ARGS
|
||||
}
|
||||
},
|
||||
{ "VendorElemRem", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||
(WPADBusMethodHandler) wpas_dbus_handler_vendor_elem_remove,
|
||||
{
|
||||
{ "frame_id", "i", ARG_IN },
|
||||
{ "ielems", "ay", ARG_IN },
|
||||
END_ARGS
|
||||
}
|
||||
},
|
||||
#ifndef CONFIG_NO_CONFIG_WRITE
|
||||
{ "SaveConfig", WPAS_DBUS_NEW_IFACE_INTERFACE,
|
||||
(WPADBusMethodHandler) wpas_dbus_handler_save_config,
|
||||
|
|
|
@ -4363,3 +4363,147 @@ out:
|
|||
}
|
||||
|
||||
#endif /* CONFIG_AP */
|
||||
|
||||
|
||||
DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
u8 *ielems;
|
||||
int len;
|
||||
struct ieee802_11_elems elems;
|
||||
dbus_int32_t frame_id;
|
||||
DBusMessageIter iter, array;
|
||||
|
||||
dbus_message_iter_init(message, &iter);
|
||||
dbus_message_iter_get_basic(&iter, &frame_id);
|
||||
if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid ID");
|
||||
}
|
||||
|
||||
dbus_message_iter_next(&iter);
|
||||
dbus_message_iter_recurse(&iter, &array);
|
||||
dbus_message_iter_get_fixed_array(&array, &ielems, &len);
|
||||
if (!ielems || len == 0) {
|
||||
return dbus_message_new_error(
|
||||
message, DBUS_ERROR_INVALID_ARGS, "Invalid value");
|
||||
}
|
||||
|
||||
if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Parse error");
|
||||
}
|
||||
|
||||
wpa_s = wpas_vendor_elem(wpa_s, frame_id);
|
||||
if (!wpa_s->vendor_elem[frame_id]) {
|
||||
wpa_s->vendor_elem[frame_id] = wpabuf_alloc_copy(ielems, len);
|
||||
wpas_vendor_elem_update(wpa_s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (wpabuf_resize(&wpa_s->vendor_elem[frame_id], len) < 0) {
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Resize error");
|
||||
}
|
||||
|
||||
wpabuf_put_data(wpa_s->vendor_elem[frame_id], ielems, len);
|
||||
wpas_vendor_elem_update(wpa_s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
DBusMessage *reply;
|
||||
DBusMessageIter iter, array_iter;
|
||||
dbus_int32_t frame_id;
|
||||
const u8 *elem;
|
||||
size_t elem_len;
|
||||
|
||||
dbus_message_iter_init(message, &iter);
|
||||
dbus_message_iter_get_basic(&iter, &frame_id);
|
||||
|
||||
if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid ID");
|
||||
}
|
||||
|
||||
wpa_s = wpas_vendor_elem(wpa_s, frame_id);
|
||||
if (!wpa_s->vendor_elem[frame_id]) {
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"ID value does not exist");
|
||||
}
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
return wpas_dbus_error_no_memory(message);
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
|
||||
elem = wpabuf_head_u8(wpa_s->vendor_elem[frame_id]);
|
||||
elem_len = wpabuf_len(wpa_s->vendor_elem[frame_id]);
|
||||
|
||||
if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
|
||||
DBUS_TYPE_BYTE_AS_STRING,
|
||||
&array_iter) ||
|
||||
!dbus_message_iter_append_fixed_array(&array_iter, DBUS_TYPE_BYTE,
|
||||
&elem, elem_len) ||
|
||||
!dbus_message_iter_close_container(&iter, &array_iter)) {
|
||||
dbus_message_unref(reply);
|
||||
reply = wpas_dbus_error_no_memory(message);
|
||||
}
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
DBusMessage * wpas_dbus_handler_vendor_elem_remove(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
u8 *ielems;
|
||||
int len;
|
||||
struct ieee802_11_elems elems;
|
||||
DBusMessageIter iter, array;
|
||||
dbus_int32_t frame_id;
|
||||
|
||||
dbus_message_iter_init(message, &iter);
|
||||
dbus_message_iter_get_basic(&iter, &frame_id);
|
||||
if (frame_id < 0 || frame_id >= NUM_VENDOR_ELEM_FRAMES) {
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid ID");
|
||||
}
|
||||
|
||||
dbus_message_iter_next(&iter);
|
||||
dbus_message_iter_recurse(&iter, &array);
|
||||
dbus_message_iter_get_fixed_array(&array, &ielems, &len);
|
||||
if (!ielems || len == 0) {
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Invalid value");
|
||||
}
|
||||
|
||||
wpa_s = wpas_vendor_elem(wpa_s, frame_id);
|
||||
|
||||
if (len == 1 && *ielems == '*') {
|
||||
wpabuf_free(wpa_s->vendor_elem[frame_id]);
|
||||
wpa_s->vendor_elem[frame_id] = NULL;
|
||||
wpas_vendor_elem_update(wpa_s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!wpa_s->vendor_elem[frame_id]) {
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"ID value does not exist");
|
||||
}
|
||||
|
||||
if (ieee802_11_parse_elems(ielems, len, &elems, 0) == ParseFailed) {
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Parse error");
|
||||
}
|
||||
|
||||
if (wpas_vendor_elem_remove(wpa_s, frame_id, ielems, len) == 0)
|
||||
return NULL;
|
||||
|
||||
return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
|
||||
"Not found");
|
||||
}
|
||||
|
|
|
@ -194,6 +194,13 @@ DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message,
|
|||
DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_vendor_elem_add(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
DBusMessage * wpas_dbus_handler_vendor_elem_get(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
DBusMessage * wpas_dbus_handler_vendor_elem_remove(
|
||||
DBusMessage *message, struct wpa_supplicant *wpa_s);
|
||||
|
||||
DBusMessage * wpas_dbus_handler_save_config(DBusMessage *message,
|
||||
struct wpa_supplicant *wpa_s);
|
||||
|
||||
|
|
|
@ -6143,3 +6143,86 @@ void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s,
|
|||
}
|
||||
wpabuf_free(buf);
|
||||
}
|
||||
|
||||
|
||||
struct wpa_supplicant *
|
||||
wpas_vendor_elem(struct wpa_supplicant *wpa_s, enum wpa_vendor_elem_frame frame)
|
||||
{
|
||||
switch (frame) {
|
||||
#ifdef CONFIG_P2P
|
||||
case VENDOR_ELEM_PROBE_REQ_P2P:
|
||||
case VENDOR_ELEM_PROBE_RESP_P2P:
|
||||
case VENDOR_ELEM_PROBE_RESP_P2P_GO:
|
||||
case VENDOR_ELEM_BEACON_P2P_GO:
|
||||
case VENDOR_ELEM_P2P_PD_REQ:
|
||||
case VENDOR_ELEM_P2P_PD_RESP:
|
||||
case VENDOR_ELEM_P2P_GO_NEG_REQ:
|
||||
case VENDOR_ELEM_P2P_GO_NEG_RESP:
|
||||
case VENDOR_ELEM_P2P_GO_NEG_CONF:
|
||||
case VENDOR_ELEM_P2P_INV_REQ:
|
||||
case VENDOR_ELEM_P2P_INV_RESP:
|
||||
case VENDOR_ELEM_P2P_ASSOC_REQ:
|
||||
case VENDOR_ELEM_P2P_ASSOC_RESP:
|
||||
return wpa_s->parent;
|
||||
#endif /* CONFIG_P2P */
|
||||
default:
|
||||
return wpa_s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s)
|
||||
{
|
||||
unsigned int i;
|
||||
char buf[30];
|
||||
|
||||
wpa_printf(MSG_DEBUG, "Update vendor elements");
|
||||
|
||||
for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) {
|
||||
if (wpa_s->vendor_elem[i]) {
|
||||
int res;
|
||||
|
||||
res = os_snprintf(buf, sizeof(buf), "frame[%u]", i);
|
||||
if (!os_snprintf_error(sizeof(buf), res)) {
|
||||
wpa_hexdump_buf(MSG_DEBUG, buf,
|
||||
wpa_s->vendor_elem[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_P2P
|
||||
if (wpa_s->parent == wpa_s &&
|
||||
wpa_s->global->p2p &&
|
||||
!wpa_s->global->p2p_disabled)
|
||||
p2p_set_vendor_elems(wpa_s->global->p2p, wpa_s->vendor_elem);
|
||||
#endif /* CONFIG_P2P */
|
||||
}
|
||||
|
||||
|
||||
int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
|
||||
const u8 *elem, size_t len)
|
||||
{
|
||||
u8 *ie, *end;
|
||||
|
||||
ie = wpabuf_mhead_u8(wpa_s->vendor_elem[frame]);
|
||||
end = ie + wpabuf_len(wpa_s->vendor_elem[frame]);
|
||||
|
||||
for (; ie + 1 < end; ie += 2 + ie[1]) {
|
||||
if (ie + len > end)
|
||||
break;
|
||||
if (os_memcmp(ie, elem, len) != 0)
|
||||
continue;
|
||||
|
||||
if (wpabuf_len(wpa_s->vendor_elem[frame]) == len) {
|
||||
wpabuf_free(wpa_s->vendor_elem[frame]);
|
||||
wpa_s->vendor_elem[frame] = NULL;
|
||||
} else {
|
||||
os_memmove(ie, ie + len, end - (ie + len));
|
||||
wpa_s->vendor_elem[frame]->used -= len;
|
||||
}
|
||||
wpas_vendor_elem_update(wpa_s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -1179,6 +1179,12 @@ int get_shared_radio_freqs(struct wpa_supplicant *wpa_s,
|
|||
|
||||
void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx);
|
||||
|
||||
void wpas_vendor_elem_update(struct wpa_supplicant *wpa_s);
|
||||
struct wpa_supplicant * wpas_vendor_elem(struct wpa_supplicant *wpa_s,
|
||||
enum wpa_vendor_elem_frame frame);
|
||||
int wpas_vendor_elem_remove(struct wpa_supplicant *wpa_s, int frame,
|
||||
const u8 *elem, size_t len);
|
||||
|
||||
#ifdef CONFIG_FST
|
||||
|
||||
struct fst_wpa_obj;
|
||||
|
|
Loading…
Reference in a new issue