Below is the patch for connman bug filed on bugs.meego.com
http://bugs.meego.com/show_bug.cgi?id=6897

Description:
When connected to an AP, doing a `kill -9 <connmand_pid>` and restarting 
connmand will fail to auto connect to the WiFi service. The 
/var/lib/connman/default.profile shows a 'connect-failed' message for the 
auto-connect AP.

Analysis:
connmand communicates to wpa_supplicant for WiFi using dbus messages. 
wpa_supplicant is responsible to communicate with the underlying wlan driver 
and add/remove/scan network based on the dbus request from connmand. When 
connmand connects to an AP, wpa_supplicant will ask the wlan driver to 
associate to that AP and a network object is created by wpa_supplicant. When 
connmand is killed, this network is still active and the wlan is also 
associated to the AP.

Now when connmand is restarted, it will get the interface, add network and ask 
wpa_supplicant to select this network. wpa_supplicant will in turn ask the wlan 
driver to associate to this network. The driver in turn will now dis-associate 
from the old network and send a 'Disassociation notification'. On receiving 
this disassociation event, wpa_supplicant will send a deauthenticate request to 
the driver and set the state to disconnected. As a result connmand gets a 
state_changed signal with state disconnected and hence we get a connect-failure 
message.

Solution:
The new dbus interface for wpa_supplicant (fi.w1.wpa_supplicant1) provides a 
properties Get method for the network objects. This dbus requests returns the 
list of current network objects for the specified interface. When connmand get 
a reply for getInterface, fetching this network list and removing all the old 
network objects for the respective interface will fix this issue.

In order to use the new dbus interface for wpa_supplicant 
(fi.w1.wpa_supplicant1), also adding functions to GetInterface and 
RemoveNetwork on this interface.

Patch:

----------

 plugins/supplicant.c |  170 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 170 insertions(+), 0 deletions(-)

diff --git a/plugins/supplicant.c b/plugins/supplicant.c
index 469e109..d65d84b 100644
--- a/plugins/supplicant.c
+++ b/plugins/supplicant.c
@@ -56,6 +56,10 @@
 #define SUPPLICANT_INTF  "fi.epitest.hostap.WPASupplicant"
 #define SUPPLICANT_PATH  "/fi/epitest/hostap/WPASupplicant"
 
+#define SUPPLICANT_NEW_NAME  "fi.w1.wpa_supplicant1"
+#define SUPPLICANT_NEW_INTF  "fi.w1.wpa_supplicant1"
+#define SUPPLICANT_NEW_PATH  "/fi/w1/wpa_supplicant1"
+
 /* Taken from "WPA Supplicant - Common definitions" */
 enum supplicant_state {
        /**
@@ -703,6 +707,171 @@ static int add_interface(struct supplicant_task *task)
        return -EINPROGRESS;
 }
 
+static int get_interface_path (char *ifname, char **result)
+{
+       DBusMessage *message, *reply;
+       DBusError error;
+       char *path;
+
+       message = dbus_message_new_method_call(SUPPLICANT_NEW_NAME, 
SUPPLICANT_NEW_PATH,
+                                       SUPPLICANT_NEW_INTF, "GetInterface");
+
+       if (message == NULL)
+               return -ENOMEM;
+
+       dbus_message_set_auto_start(message, FALSE);
+
+       dbus_message_append_args(message, DBUS_TYPE_STRING, &ifname,
+                                       DBUS_TYPE_INVALID);
+
+       dbus_error_init(&error);
+
+       reply = dbus_connection_send_with_reply_and_block(connection,
+                                       message, -1, &error);
+
+       if (reply == NULL) {
+               if (dbus_error_is_set(&error) == TRUE) {
+                       connman_error("%s", error.message);
+                       dbus_error_free(&error);
+               } else
+                       connman_error("Failed to get interface");
+
+               dbus_message_unref(message);
+               return -EIO;
+       }
+
+       dbus_message_unref(message);
+
+       dbus_error_init(&error);
+
+       if (dbus_message_get_args(reply, &error, DBUS_TYPE_OBJECT_PATH, &path,
+                                               DBUS_TYPE_INVALID) == FALSE) {
+               if (dbus_error_is_set(&error) == TRUE) {
+                       connman_error("%s", error.message);
+                       dbus_error_free(&error);
+               } else
+                       connman_error("Wrong arguments for get interface");
+
+               dbus_message_unref(reply);
+               return -EIO;
+       }
+       
+       *result =  g_strdup(path);
+       dbus_message_unref(reply);
+
+       return 0;
+}
+
+static int delete_network (char *task_path, char *network_path)
+{
+       DBusMessage *message, *reply;
+       DBusError error;
+
+       if (task_path == NULL || network_path == NULL)
+               return -EINVAL;
+
+       message = dbus_message_new_method_call(SUPPLICANT_NEW_NAME, task_path,
+                                       SUPPLICANT_NEW_INTF ".Interface", 
"RemoveNetwork");
+       if (message == NULL)
+               return -ENOMEM;
+
+       dbus_message_set_auto_start(message, FALSE);
+
+       dbus_message_append_args(message, DBUS_TYPE_OBJECT_PATH, &network_path,
+                                       DBUS_TYPE_INVALID);
+
+       dbus_error_init(&error);
+
+       reply = dbus_connection_send_with_reply_and_block(connection,
+                                       message, -1, &error);
+
+       if (reply == NULL) {
+               if (dbus_error_is_set(&error) == TRUE) {
+                       connman_error("%s", error.message);
+                       dbus_error_free(&error);
+               } else
+                       connman_error("Failed to remove network");
+               dbus_message_unref(message);
+               return -EIO;
+       }
+
+       dbus_message_unref(message);
+       dbus_message_unref(reply);
+
+       return 0;
+}
+
+static int get_networks (char *ifname)
+{
+       DBusMessage *message, *reply;
+       DBusError error;
+       char *task_path = NULL;
+       char *interface_name, *method_name;
+
+       if (get_interface_path(ifname, &task_path) != 0)
+               return -1;
+
+       message = dbus_message_new_method_call(SUPPLICANT_NEW_NAME, task_path,
+                                       DBUS_INTERFACE_PROPERTIES, "Get");
+
+       if (message == NULL)
+               return -ENOMEM;
+
+       dbus_message_set_auto_start(message, FALSE);
+
+       interface_name = SUPPLICANT_NEW_INTF ".Interface";
+       method_name = "Networks";
+       dbus_message_append_args(message, DBUS_TYPE_STRING, &interface_name,
+                                       DBUS_TYPE_STRING, &method_name, 
DBUS_TYPE_INVALID);
+
+       dbus_error_init(&error);
+       reply = dbus_connection_send_with_reply_and_block(connection,
+                                       message, -1, &error);
+
+       if (reply == NULL) {
+               if (dbus_error_is_set(&error) == TRUE) {
+                       connman_error("%s", error.message);
+                       dbus_error_free(&error);
+               } else
+                       connman_error("Failed to get networks list");
+               dbus_message_unref(message);
+               return -EIO;
+       }
+
+       if (reply) {
+               DBusMessageIter iter;
+
+               if (dbus_message_iter_init(reply, &iter) == FALSE)
+                       return -EIO;
+
+               if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) 
{
+                       DBusMessageIter variant;
+
+                       dbus_message_iter_recurse(&iter, &variant);
+
+                       if (dbus_message_iter_get_arg_type(&variant) == 
DBUS_TYPE_ARRAY) {
+                               DBusMessageIter array;
+
+                               dbus_message_iter_recurse(&variant, &array);
+
+                               while (dbus_message_iter_get_arg_type(&array) 
!= DBUS_TYPE_INVALID) {
+                                       char *path;
+
+                                       dbus_message_iter_get_basic(&array, 
&path);
+                                       delete_network(task_path, path);
+
+                                       dbus_message_iter_next(&array);
+                               }
+                       }
+               }
+       }
+
+       dbus_message_unref(message);
+       dbus_message_unref(reply);
+
+       return 0;
+}
+
 static void get_interface_reply(DBusPendingCall *call, void *user_data)
 {
        struct supplicant_task *task = user_data;
@@ -737,6 +906,7 @@ static void get_interface_reply(DBusPendingCall *call, void 
*user_data)
        task->created = FALSE;
 
        connman_device_set_powered(task->device, TRUE);
+       get_networks(task->ifname);
 
 done:
        dbus_message_unref(reply);

----------

Please do not print this email unless it is absolutely necessary. 

The information contained in this electronic message and any attachments to 
this message are intended for the exclusive use of the addressee(s) and may 
contain proprietary, confidential or privileged information. If you are not the 
intended recipient, you should not disseminate, distribute or copy this e-mail. 
Please notify the sender immediately and destroy all copies of this message and 
any attachments. 

WARNING: Computer viruses can be transmitted via email. The recipient should 
check this email and any attachments for the presence of viruses. The company 
accepts no liability for any damage caused by any virus transmitted by this 
email. 

www.wipro.com
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to