dbus: add BSS Age property to indicate last-seen time
[mech_eap.git] / wpa_supplicant / dbus / dbus_new.c
index a1e2c09..ab20961 100644 (file)
@@ -24,6 +24,7 @@
 #include "dbus_common_i.h"
 #include "dbus_new_handlers_p2p.h"
 #include "p2p/p2p.h"
+#include "../p2p_supplicant.h"
 
 #ifdef CONFIG_AP /* until needed by something else */
 
@@ -709,9 +710,9 @@ void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
        DBusMessage *msg;
        DBusMessageIter iter, dict_iter;
        struct wpas_dbus_priv *iface;
-       char *auth_type[6]; /* we have six possible authorization types */
+       char *auth_type[5]; /* we have five possible authentication types */
        int at_num = 0;
-       char *encr_type[4]; /* we have four possible encryption types */
+       char *encr_type[3]; /* we have three possible encryption types */
        int et_num = 0;
 
        iface = wpa_s->global->dbus;
@@ -734,20 +735,15 @@ void wpas_dbus_signal_wps_cred(struct wpa_supplicant *wpa_s,
                auth_type[at_num++] = "open";
        if (cred->auth_type & WPS_AUTH_WPAPSK)
                auth_type[at_num++] = "wpa-psk";
-       if (cred->auth_type & WPS_AUTH_SHARED)
-               auth_type[at_num++] = "shared";
        if (cred->auth_type & WPS_AUTH_WPA)
                auth_type[at_num++] = "wpa-eap";
        if (cred->auth_type & WPS_AUTH_WPA2)
                auth_type[at_num++] = "wpa2-eap";
        if (cred->auth_type & WPS_AUTH_WPA2PSK)
-               auth_type[at_num++] =
-               "wpa2-psk";
+               auth_type[at_num++] = "wpa2-psk";
 
        if (cred->encr_type & WPS_ENCR_NONE)
                encr_type[et_num++] = "none";
-       if (cred->encr_type & WPS_ENCR_WEP)
-               encr_type[et_num++] = "wep";
        if (cred->encr_type & WPS_ENCR_TKIP)
                encr_type[et_num++] = "tkip";
        if (cred->encr_type & WPS_ENCR_AES)
@@ -950,37 +946,49 @@ void wpas_dbus_signal_sta_deauthorized(struct wpa_supplicant *wpa_s,
 void wpas_dbus_signal_p2p_group_removed(struct wpa_supplicant *wpa_s,
                                        const char *role)
 {
-
+       int error = 1;
        DBusMessage *msg;
-       DBusMessageIter iter;
+       DBusMessageIter iter, dict_iter;
        struct wpas_dbus_priv *iface = wpa_s->global->dbus;
-       char *ifname = wpa_s->ifname;
 
        /* Do nothing if the control interface is not turned on */
        if (iface == NULL)
                return;
 
-       msg = dbus_message_new_signal(wpa_s->dbus_new_path,
+       if (!wpa_s->dbus_groupobj_path)
+               return;
+
+       msg = dbus_message_new_signal(wpa_s->parent->dbus_new_path,
                                      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
                                      "GroupFinished");
        if (msg == NULL)
                return;
 
        dbus_message_iter_init_append(msg, &iter);
+       if (!wpa_dbus_dict_open_write(&iter, &dict_iter))
+               goto nomem;
 
-       if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ifname)) {
-               wpa_printf(MSG_ERROR, "dbus: Failed to construct GroupFinished"
-                                     "signal -not enough memory for ifname ");
-               goto err;
-       }
+       if (!wpa_dbus_dict_append_object_path(&dict_iter,
+                                             "interface_object",
+                                             wpa_s->dbus_new_path))
+               goto nomem;
 
-       if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &role))
-               wpa_printf(MSG_ERROR, "dbus: Failed to construct GroupFinished"
-                                     "signal -not enough memory for role ");
-       else
-               dbus_connection_send(iface->con, msg, NULL);
+       if (!wpa_dbus_dict_append_string(&dict_iter, "role", role))
+               goto nomem;
+
+       if (!wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
+                                             wpa_s->dbus_groupobj_path) ||
+           !wpa_dbus_dict_close_write(&iter, &dict_iter))
+               goto nomem;
+
+       error = 0;
+       dbus_connection_send(iface->con, msg, NULL);
+
+nomem:
+       if (error > 0)
+               wpa_printf(MSG_ERROR,
+                          "dbus: Failed to construct GroupFinished");
 
-err:
        dbus_message_unref(msg);
 }
 
@@ -1156,6 +1164,69 @@ static int wpas_dbus_get_group_obj_path(struct wpa_supplicant *wpa_s,
 }
 
 
+struct group_changed_data {
+       struct wpa_supplicant *wpa_s;
+       struct p2p_peer_info *info;
+};
+
+
+static int match_group_where_peer_is_client(struct p2p_group *group,
+                                           void *user_data)
+{
+       struct group_changed_data *data = user_data;
+       const struct p2p_group_config *cfg;
+       struct wpa_supplicant *wpa_s_go;
+
+       if (!p2p_group_is_client_connected(group, data->info->p2p_device_addr))
+               return 1;
+
+       cfg = p2p_group_get_config(group);
+
+       wpa_s_go = wpas_get_p2p_go_iface(data->wpa_s, cfg->ssid,
+                                        cfg->ssid_len);
+       if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
+               wpas_dbus_signal_peer_groups_changed(
+                       data->wpa_s->parent, data->info->p2p_device_addr);
+               return 0;
+       }
+
+       return 1;
+}
+
+
+static void signal_peer_groups_changed(struct p2p_peer_info *info,
+                                      void *user_data)
+{
+       struct group_changed_data *data = user_data;
+       struct wpa_supplicant *wpa_s_go;
+
+       wpa_s_go = wpas_get_p2p_client_iface(data->wpa_s,
+                                            info->p2p_device_addr);
+       if (wpa_s_go != NULL && wpa_s_go == data->wpa_s) {
+               wpas_dbus_signal_peer_groups_changed(data->wpa_s->parent,
+                                                    info->p2p_device_addr);
+               return;
+       }
+
+       data->info = info;
+       p2p_loop_on_all_groups(data->wpa_s->global->p2p,
+                              match_group_where_peer_is_client, data);
+       data->info = NULL;
+}
+
+
+static void peer_groups_changed(struct wpa_supplicant *wpa_s)
+{
+       struct group_changed_data data;
+
+       os_memset(&data, 0, sizeof(data));
+       data.wpa_s = wpa_s;
+
+       p2p_loop_on_known_peers(wpa_s->global->p2p,
+                               signal_peer_groups_changed, &data);
+}
+
+
 /**
  * wpas_dbus_signal_p2p_group_started - Signals P2P group has
  * started. Emitted when a group is successfully started
@@ -1174,7 +1245,6 @@ void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
        DBusMessage *msg;
        DBusMessageIter iter, dict_iter;
        struct wpas_dbus_priv *iface;
-       char group_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
 
        iface = wpa_s->parent->global->dbus;
 
@@ -1182,14 +1252,13 @@ void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
        if (iface == NULL)
                return;
 
-       if (wpas_dbus_get_group_obj_path(wpa_s, ssid, group_obj_path) < 0)
+       if (wpa_s->dbus_groupobj_path == NULL)
                return;
 
        /* New interface has been created for this group */
        msg = dbus_message_new_signal(wpa_s->parent->dbus_new_path,
                                      WPAS_DBUS_NEW_IFACE_P2PDEVICE,
                                      "GroupStarted");
-
        if (msg == NULL)
                return;
 
@@ -1212,12 +1281,15 @@ void wpas_dbus_signal_p2p_group_started(struct wpa_supplicant *wpa_s,
                goto nomem;
 
        if (!wpa_dbus_dict_append_object_path(&dict_iter, "group_object",
-                                            group_obj_path) ||
+                                             wpa_s->dbus_groupobj_path) ||
           !wpa_dbus_dict_close_write(&iter, &dict_iter))
                goto nomem;
 
        dbus_connection_send(iface->con, msg, NULL);
 
+       if (client)
+               peer_groups_changed(wpa_s);
+
 nomem:
        dbus_message_unref(msg);
 }
@@ -1225,7 +1297,7 @@ nomem:
 
 /**
  *
- * Method to emit GONeogtiation Success or Failure signals based
+ * Method to emit GONegotiation Success or Failure signals based
  * on status.
  * @status: Status of the GO neg request. 0 for success, other for errors.
  */
@@ -1405,15 +1477,15 @@ nomem:
  * constructed using p2p i/f addr used for connecting.
  *
  * @wpa_s: %wpa_supplicant network interface data
- * @member_addr: addr (p2p i/f) of the peer joining the group
+ * @peer_addr: P2P Device Address of the peer joining the group
  */
 void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
-                                     const u8 *member)
+                                     const u8 *peer_addr)
 {
        struct wpas_dbus_priv *iface;
        DBusMessage *msg;
        DBusMessageIter iter;
-       char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+       char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
 
        iface = wpa_s->global->dbus;
 
@@ -1424,10 +1496,10 @@ void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
        if (!wpa_s->dbus_groupobj_path)
                return;
 
-       os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-                       "%s/"  WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/"
+       os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                       "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
                        COMPACT_MACSTR,
-                       wpa_s->dbus_groupobj_path, MAC2STR(member));
+                       wpa_s->parent->dbus_new_path, MAC2STR(peer_addr));
 
        msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
                                      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
@@ -1436,14 +1508,16 @@ void wpas_dbus_signal_p2p_peer_joined(struct wpa_supplicant *wpa_s,
                return;
 
        dbus_message_iter_init_append(msg, &iter);
-       path = groupmember_obj_path;
+       path = peer_obj_path;
        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
                                            &path))
                goto err;
 
        dbus_connection_send(iface->con, msg, NULL);
-
        dbus_message_unref(msg);
+
+       wpas_dbus_signal_peer_groups_changed(wpa_s->parent, peer_addr);
+
        return;
 
 err:
@@ -1456,18 +1530,18 @@ err:
  *
  * Method to emit a signal for a peer disconnecting the group.
  * The signal will carry path to the group member object
- * constructed using p2p i/f addr used for connecting.
+ * constructed using the P2P Device Address of the peer.
  *
  * @wpa_s: %wpa_supplicant network interface data
- * @member_addr: addr (p2p i/f) of the peer joining the group
+ * @peer_addr: P2P Device Address of the peer joining the group
  */
 void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
-                                     const u8 *member)
+                                           const u8 *peer_addr)
 {
        struct wpas_dbus_priv *iface;
        DBusMessage *msg;
        DBusMessageIter iter;
-       char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
+       char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX], *path;
 
        iface = wpa_s->global->dbus;
 
@@ -1478,10 +1552,10 @@ void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
        if (!wpa_s->dbus_groupobj_path)
                return;
 
-       os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-                       "%s/"  WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/"
+       os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                       "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/"
                        COMPACT_MACSTR,
-                       wpa_s->dbus_groupobj_path, MAC2STR(member));
+                       wpa_s->dbus_groupobj_path, MAC2STR(peer_addr));
 
        msg = dbus_message_new_signal(wpa_s->dbus_groupobj_path,
                                      WPAS_DBUS_NEW_IFACE_P2P_GROUP,
@@ -1490,14 +1564,16 @@ void wpas_dbus_signal_p2p_peer_disconnected(struct wpa_supplicant *wpa_s,
                return;
 
        dbus_message_iter_init_append(msg, &iter);
-       path = groupmember_obj_path;
+       path = peer_obj_path;
        if (!dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH,
                                            &path))
                goto err;
 
        dbus_connection_send(iface->con, msg, NULL);
-
        dbus_message_unref(msg);
+
+       wpas_dbus_signal_peer_groups_changed(wpa_s->parent, peer_addr);
+
        return;
 
 err:
@@ -1884,6 +1960,9 @@ void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
        case WPAS_DBUS_BSS_PROP_IES:
                prop = "IEs";
                break;
+       case WPAS_DBUS_BSS_PROP_AGE:
+               prop = "Age";
+               break;
        default:
                wpa_printf(MSG_ERROR, "dbus: %s: Unknown Property value %d",
                           __func__, property);
@@ -2308,6 +2387,10 @@ static const struct wpa_dbus_property_desc wpas_dbus_bss_properties[] = {
          wpas_dbus_getter_bss_ies,
          NULL
        },
+       { "Age", WPAS_DBUS_NEW_IFACE_BSS, "u",
+         wpas_dbus_getter_bss_age,
+         NULL
+       },
        { NULL, NULL, NULL, NULL, NULL }
 };
 
@@ -2649,6 +2732,7 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = {
          (WPADBusMethodHandler)wpas_dbus_handler_p2p_service_sd_req,
          {
                  { "args", "a{sv}", ARG_IN },
+                 { "ref", "t", ARG_OUT },
                  END_ARGS
          }
        },
@@ -2988,7 +3072,6 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
        { "DeviceFound", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
                  { "path", "o", ARG_OUT },
-                 { "properties", "a{sv}", ARG_OUT },
                  END_ARGS
          }
        },
@@ -3051,12 +3134,13 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
        },
        { "GONegotiationSuccess", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
+                 { "properties", "a{sv}", ARG_OUT },
                  END_ARGS
          }
        },
        { "GONegotiationFailure", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
-                 { "status", "i", ARG_OUT },
+                 { "properties", "a{sv}", ARG_OUT },
                  END_ARGS
          }
        },
@@ -3075,8 +3159,7 @@ static const struct wpa_dbus_signal_desc wpas_dbus_interface_signals[] = {
        },
        { "GroupFinished", WPAS_DBUS_NEW_IFACE_P2PDEVICE,
          {
-                 { "ifname", "s", ARG_OUT },
-                 { "role", "s", ARG_OUT },
+                 { "properties", "a{sv}", ARG_OUT },
                  END_ARGS
          }
        },
@@ -3273,11 +3356,25 @@ static const struct wpa_dbus_property_desc wpas_dbus_p2p_peer_properties[] = {
          wpas_dbus_getter_p2p_peer_ies,
          NULL
        },
+       { "DeviceAddress", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ay",
+         wpas_dbus_getter_p2p_peer_device_address,
+         NULL
+       },
+       { "Groups", WPAS_DBUS_NEW_IFACE_P2P_PEER, "ao",
+         wpas_dbus_getter_p2p_peer_groups,
+         NULL
+       },
        { NULL, NULL, NULL, NULL, NULL }
 };
 
 static const struct wpa_dbus_signal_desc wpas_dbus_p2p_peer_signals[] = {
-
+       /* Deprecated: use org.freedesktop.DBus.Properties.PropertiesChanged */
+       { "PropertiesChanged", WPAS_DBUS_NEW_IFACE_P2P_PEER,
+         {
+                 { "properties", "a{sv}", ARG_OUT },
+                 END_ARGS
+         }
+       },
        { NULL, NULL, { END_ARGS } }
 };
 
@@ -3461,6 +3558,20 @@ int wpas_dbus_unregister_peer(struct wpa_supplicant *wpa_s,
 }
 
 
+void wpas_dbus_signal_peer_groups_changed(struct wpa_supplicant *wpa_s,
+                                         const u8 *dev_addr)
+{
+       char peer_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
+
+       os_snprintf(peer_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
+                   "%s/" WPAS_DBUS_NEW_P2P_PEERS_PART "/" COMPACT_MACSTR,
+                   wpa_s->dbus_new_path, MAC2STR(dev_addr));
+
+       wpa_dbus_mark_property_changed(wpa_s->global->dbus, peer_obj_path,
+                                      WPAS_DBUS_NEW_IFACE_P2P_PEER, "Groups");
+}
+
+
 static const struct wpa_dbus_property_desc wpas_dbus_p2p_group_properties[] = {
        { "Members", WPAS_DBUS_NEW_IFACE_P2P_GROUP, "ao",
          wpas_dbus_getter_p2p_group_members,
@@ -3606,6 +3717,8 @@ void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
                return;
        }
 
+       peer_groups_changed(wpa_s);
+
        wpa_printf(MSG_DEBUG, "dbus: Unregister group object '%s'",
                   wpa_s->dbus_groupobj_path);
 
@@ -3617,109 +3730,6 @@ void wpas_dbus_unregister_p2p_group(struct wpa_supplicant *wpa_s,
 }
 
 static const struct wpa_dbus_property_desc
-wpas_dbus_p2p_groupmember_properties[] = {
-       { NULL, NULL, NULL, NULL, NULL }
-};
-
-/**
- * wpas_dbus_register_p2p_groupmember - Register a p2p groupmember
- * object with dbus
- * @wpa_s: wpa_supplicant interface structure
- * @p2p_if_addr: i/f addr of the device joining this group
- *
- * Registers p2p groupmember representing object with dbus
- */
-void wpas_dbus_register_p2p_groupmember(struct wpa_supplicant *wpa_s,
-                                       const u8 *p2p_if_addr)
-{
-       struct wpas_dbus_priv *ctrl_iface;
-       struct wpa_dbus_object_desc *obj_desc = NULL;
-       struct groupmember_handler_args *arg;
-       char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
-
-       /* Do nothing if the control interface is not turned on */
-       if (wpa_s == NULL || wpa_s->global == NULL)
-               return;
-
-       ctrl_iface = wpa_s->global->dbus;
-       if (ctrl_iface == NULL)
-               return;
-
-       if (!wpa_s->dbus_groupobj_path)
-               return;
-
-       os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-               "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
-               wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
-
-       obj_desc = os_zalloc(sizeof(struct wpa_dbus_object_desc));
-       if (!obj_desc) {
-               wpa_printf(MSG_ERROR, "Not enough memory "
-                          "to create object description");
-               goto err;
-       }
-
-       /* allocate memory for handlers arguments */
-       arg = os_zalloc(sizeof(struct groupmember_handler_args));
-       if (!arg) {
-               wpa_printf(MSG_ERROR, "Not enough memory "
-                          "to create arguments for method");
-               goto err;
-       }
-
-       arg->wpa_s = wpa_s;
-       os_memcpy(arg->member_addr, p2p_if_addr, ETH_ALEN);
-
-       wpas_dbus_register(obj_desc, arg, wpa_dbus_free, NULL,
-                          wpas_dbus_p2p_groupmember_properties, NULL);
-
-       if (wpa_dbus_register_object_per_iface(ctrl_iface, groupmember_obj_path,
-                                              wpa_s->ifname, obj_desc))
-               goto err;
-
-       wpa_printf(MSG_INFO,
-                  "dbus: Registered group member object '%s' successfully",
-                  groupmember_obj_path);
-       return;
-
-err:
-       free_dbus_object_desc(obj_desc);
-}
-
-/**
- * wpas_dbus_unregister_p2p_groupmember - Unregister a p2p groupmember
- * object with dbus
- * @wpa_s: wpa_supplicant interface structure
- * @p2p_if_addr: i/f addr of the device joining this group
- *
- * Unregisters p2p groupmember representing object with dbus
- */
-void wpas_dbus_unregister_p2p_groupmember(struct wpa_supplicant *wpa_s,
-                                         const u8 *p2p_if_addr)
-{
-       struct wpas_dbus_priv *ctrl_iface;
-       char groupmember_obj_path[WPAS_DBUS_OBJECT_PATH_MAX];
-
-       /* Do nothing if the control interface is not turned on */
-       if (wpa_s == NULL || wpa_s->global == NULL)
-               return;
-
-       ctrl_iface = wpa_s->global->dbus;
-       if (ctrl_iface == NULL)
-               return;
-
-       if (!wpa_s->dbus_groupobj_path)
-               return;
-
-       os_snprintf(groupmember_obj_path, WPAS_DBUS_OBJECT_PATH_MAX,
-               "%s/" WPAS_DBUS_NEW_P2P_GROUPMEMBERS_PART "/" COMPACT_MACSTR,
-               wpa_s->dbus_groupobj_path, MAC2STR(p2p_if_addr));
-
-       wpa_dbus_unregister_object_per_iface(ctrl_iface, groupmember_obj_path);
-}
-
-
-static const struct wpa_dbus_property_desc
        wpas_dbus_persistent_group_properties[] = {
        { "Properties", WPAS_DBUS_NEW_IFACE_PERSISTENT_GROUP, "a{sv}",
          wpas_dbus_getter_persistent_group_properties,