dbus: Add support for vendor specific elements
authorAvichal Agarwal <avichal.a@samsung.com>
Fri, 4 Dec 2015 05:27:27 +0000 (10:57 +0530)
committerJouni Malinen <j@w1.fi>
Sun, 6 Dec 2015 10:50:13 +0000 (12:50 +0200)
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>
doc/dbus.doxygen
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dbus/dbus_new.c
wpa_supplicant/dbus/dbus_new_handlers.c
wpa_supplicant/dbus/dbus_new_handlers.h
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index cf60755..1989eea 100644 (file)
@@ -456,6 +456,58 @@ fi.w1.wpa_supplicant1.CreateInterface.
        </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>
       </li>
index 7b45a3a..1f4630f 100644 (file)
@@ -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;
 }
 
 
index 440b8cf..91a1511 100644 (file)
@@ -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,
index fbfcdc9..6b77008 100644 (file)
@@ -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");
+}
index 86c8359..31b92d1 100644 (file)
@@ -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);
 
index 7e5c07a..580fbe8 100644 (file)
@@ -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;
+}
index a8b273b..05a1bc6 100644 (file)
@@ -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;