+ if (g_strcmp0(key, "SSID") == 0) {
+ DBusMessageIter array;
+ unsigned char *ssid;
+ int ssid_len;
+
+ dbus_message_iter_recurse(iter, &array);
+ dbus_message_iter_get_fixed_array(&array, &ssid, &ssid_len);
+
+ if (ssid_len > 0 && ssid_len < 33) {
+ memcpy(interface->group_info.ssid, ssid, ssid_len);
+ interface->group_info.ssid_len = ssid_len;
+ } else {
+ memset(interface->group_info.ssid, 0, 32);
+ interface->group_info.ssid_len = 0;
+ }
+ } else if (g_strcmp0(key, "DisconnectReason") == 0) {
+ int disconnect_reason = 0;
+ dbus_message_iter_get_basic(iter, &disconnect_reason);
+ interface->group_info.disconnect_reason = disconnect_reason;
+ }
+}
+
+static void signal_mesh_group_started(const char *path, DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ supplicant_dbus_property_foreach(iter, mesh_group_info, interface);
+
+ callback_mesh_group_started(interface);
+}
+
+static void signal_mesh_group_removed(const char *path, DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ supplicant_dbus_property_foreach(iter, mesh_group_info, interface);
+
+ callback_mesh_group_removed(interface);
+}
+
+static void callback_mesh_peer_connected(GSupplicantMeshPeer *mesh_peer)
+{
+ if (!callbacks_pointer)
+ return;
+
+ if (!callbacks_pointer->mesh_peer_connected)
+ return;
+
+ callbacks_pointer->mesh_peer_connected(mesh_peer);
+}
+
+static void callback_mesh_peer_disconnected(GSupplicantMeshPeer *mesh_peer)
+{
+ if (!callbacks_pointer)
+ return;
+
+ if (!callbacks_pointer->mesh_peer_disconnected)
+ return;
+
+ callbacks_pointer->mesh_peer_disconnected(mesh_peer);
+}
+
+static void mesh_peer_info(const char *key, DBusMessageIter *iter,
+ void *user_data)
+{
+ GSupplicantMeshPeer *mesh_peer = user_data;
+ if (!key)
+ return;
+
+ if (g_strcmp0(key, "PeerAddress") == 0) {
+ DBusMessageIter array;
+ unsigned char *addr;
+ int addr_len;
+
+ dbus_message_iter_recurse(iter, &array);
+ dbus_message_iter_get_fixed_array(&array, &addr, &addr_len);
+
+ if (addr_len == 6) {
+ mesh_peer->peer_address = g_malloc0(19);
+ snprintf(mesh_peer->peer_address, 19,
+ "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1],
+ addr[2], addr[3], addr[4], addr[5]);
+ }
+ } else if (g_strcmp0(key, "DisconnectReason") == 0) {
+ int disconnect_reason = 0;
+ dbus_message_iter_get_basic(iter, &disconnect_reason);
+ mesh_peer->disconnect_reason = disconnect_reason;
+ }
+}
+
+static void signal_mesh_peer_connected(const char *path, DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+ GSupplicantMeshPeer *mesh_peer;
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ mesh_peer = dbus_malloc0(sizeof(GSupplicantMeshPeer));
+ mesh_peer->interface = interface;
+
+ supplicant_dbus_property_foreach(iter, mesh_peer_info, mesh_peer);
+
+ callback_mesh_peer_connected(mesh_peer);
+ g_free(mesh_peer->peer_address);
+ g_free(mesh_peer);
+}
+
+static void signal_mesh_peer_disconnected(const char *path,
+ DBusMessageIter *iter)
+{
+ GSupplicantInterface *interface;
+ GSupplicantMeshPeer *mesh_peer;
+
+ interface = g_hash_table_lookup(interface_table, path);
+ if (!interface)
+ return;
+
+ mesh_peer = dbus_malloc0(sizeof(GSupplicantMeshPeer));
+ mesh_peer->interface = interface;
+
+ supplicant_dbus_property_foreach(iter, mesh_peer_info, mesh_peer);
+
+ callback_mesh_peer_disconnected(mesh_peer);
+ g_free(mesh_peer->peer_address);
+ g_free(mesh_peer);
+}
+#endif
+
+static struct {
+ const char *interface;
+ const char *member;
+ void (*function) (const char *path, DBusMessageIter *iter);
+} signal_map[] = {
+ { DBUS_INTERFACE_DBUS, "NameOwnerChanged", signal_name_owner_changed },
+
+ { SUPPLICANT_INTERFACE, "PropertiesChanged", signal_properties_changed },
+ { SUPPLICANT_INTERFACE, "InterfaceAdded", signal_interface_added },
+ { SUPPLICANT_INTERFACE, "InterfaceCreated", signal_interface_added },
+ { SUPPLICANT_INTERFACE, "InterfaceRemoved", signal_interface_removed },
+
+ { SUPPLICANT_INTERFACE ".Interface", "PropertiesChanged", signal_interface_changed },
+ { SUPPLICANT_INTERFACE ".Interface", "ScanDone", signal_scan_done },
+ { SUPPLICANT_INTERFACE ".Interface", "BSSAdded", signal_bss_added },
+ { SUPPLICANT_INTERFACE ".Interface", "BSSRemoved", signal_bss_removed },
+ { SUPPLICANT_INTERFACE ".Interface", "NetworkAdded", signal_network_added },
+ { SUPPLICANT_INTERFACE ".Interface", "NetworkRemoved", signal_network_removed },
+ { SUPPLICANT_INTERFACE ".Interface", "StaAuthorized", signal_sta_authorized },
+ { SUPPLICANT_INTERFACE ".Interface", "StaDeauthorized", signal_sta_deauthorized },
+
+ { SUPPLICANT_INTERFACE ".BSS", "PropertiesChanged", signal_bss_changed },
+
+ { SUPPLICANT_INTERFACE ".Interface.WPS", "Credentials", signal_wps_credentials },
+ { SUPPLICANT_INTERFACE ".Interface.WPS", "Event", signal_wps_event },
+#if defined TIZEN_EXT
+ { "org.tizen.system.deviced.PowerOff", "ChangeState", signal_power_off },
+#endif
+
+ { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceFound", signal_peer_found },
+ { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "DeviceLost", signal_peer_lost },
+
+ { SUPPLICANT_INTERFACE ".Peer", "PropertiesChanged", signal_peer_changed },
+
+ { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationSuccess", signal_group_success },
+ { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationFailure", signal_group_failure },
+ { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupStarted", signal_group_started },
+ { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GroupFinished", signal_group_finished },
+ { SUPPLICANT_INTERFACE ".Interface.P2PDevice", "GONegotiationRequest", signal_group_request },
+
+ { SUPPLICANT_INTERFACE ".Group", "PeerJoined", signal_group_peer_joined },
+ { SUPPLICANT_INTERFACE ".Group", "PeerDisconnected", signal_group_peer_disconnected },
+#if defined TIZEN_EXT_WIFI_MESH
+ { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshGroupStarted",
+ signal_mesh_group_started },
+ { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshGroupRemoved",
+ signal_mesh_group_removed },
+ { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshPeerConnected",
+ signal_mesh_peer_connected },
+ { SUPPLICANT_INTERFACE ".Interface.Mesh", "MeshPeerDisconnected",
+ signal_mesh_peer_disconnected },
+#endif
+
+#if defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET
+ { SUPPLICANT_INTERFACE ".Interface", "EAP", signal_eap },
+#endif /* defined TIZEN_EXT && defined TIZEN_EXT_EAP_ON_ETHERNET */
+
+ { }
+};
+
+static DBusHandlerResult g_supplicant_filter(DBusConnection *conn,
+ DBusMessage *message, void *data)
+{
+ DBusMessageIter iter;
+ const char *path;
+ int i;
+
+ path = dbus_message_get_path(message);
+ if (!path)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (!dbus_message_iter_init(message, &iter))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ for (i = 0; signal_map[i].interface; i++) {
+ if (!dbus_message_has_interface(message, signal_map[i].interface))
+ continue;
+
+ if (!dbus_message_has_member(message, signal_map[i].member))
+ continue;
+
+ signal_map[i].function(path, &iter);
+ break;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+void g_supplicant_interface_cancel(GSupplicantInterface *interface)
+{
+ SUPPLICANT_DBG("Cancelling any pending DBus calls");
+ supplicant_dbus_method_call_cancel_all(interface);
+ supplicant_dbus_property_call_cancel_all(interface);
+}
+
+struct supplicant_regdom {
+ GSupplicantCountryCallback callback;
+ const char *alpha2;