Return an error when trying to connect hidden networks
[connman] / plugins / dhclient.c
index 3a06e3e..0bf9ad1 100644 (file)
@@ -2,7 +2,7 @@
  *
  *  Connection Manager
  *
- *  Copyright (C) 2007-2008  Intel Corporation. All rights reserved.
+ *  Copyright (C) 2007-2009  Intel Corporation. All rights reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2 as
 #include <config.h>
 #endif
 
+#include <unistd.h>
 #include <sys/wait.h>
 #include <glib/gstdio.h>
 
+#define CONNMAN_API_SUBJECT_TO_CHANGE
 #include <connman/plugin.h>
 #include <connman/driver.h>
 #include <connman/dbus.h>
 #include <connman/log.h>
 
+#include "inet.h"
+
 #define DHCLIENT_INTF "org.isc.dhclient"
 #define DHCLIENT_PATH "/org/isc/dhclient"
 
@@ -41,10 +45,8 @@ struct dhclient_task {
        int ifindex;
        gchar *ifname;
        struct connman_element *element;
-       struct connman_element *child;
 };
 
-static GStaticMutex task_mutex = G_STATIC_MUTEX_INIT;
 static GSList *task_list = NULL;
 
 static struct dhclient_task *find_task_by_pid(GPid pid)
@@ -112,9 +114,7 @@ static void task_died(GPid pid, gint status, gpointer data)
        g_spawn_close_pid(pid);
        task->pid = 0;
 
-       g_static_mutex_lock(&task_mutex);
        task_list = g_slist_remove(task_list, task);
-       g_static_mutex_unlock(&task_mutex);
 
        unlink_task(task);
 
@@ -137,14 +137,16 @@ static int dhclient_probe(struct connman_element *element)
 
        DBG("element %p name %s", element, element->name);
 
+       if (access(DHCLIENT, X_OK) < 0)
+               return -errno;
+
        task = g_try_new0(struct dhclient_task, 1);
        if (task == NULL)
                return -ENOMEM;
 
-       task->ifindex = element->netdev.index;
-       task->ifname = g_strdup(element->netdev.name);
+       task->ifindex = element->index;
+       task->ifname = inet_index2name(element->index);
        task->element = element;
-       task->child = NULL;
 
        if (task->ifname == NULL) {
                g_free(task);
@@ -186,9 +188,7 @@ static int dhclient_probe(struct connman_element *element)
                return -1;
        }
 
-       g_static_mutex_lock(&task_mutex);
        task_list = g_slist_append(task_list, task);
-       g_static_mutex_unlock(&task_mutex);
 
        g_child_watch_add(task->pid, task_died, task);
 
@@ -203,26 +203,25 @@ static void dhclient_remove(struct connman_element *element)
 
        DBG("element %p name %s", element, element->name);
 
-       g_static_mutex_lock(&task_mutex);
-       task = find_task_by_index(element->netdev.index);
-       g_static_mutex_unlock(&task_mutex);
+       task = find_task_by_index(element->index);
+       if (task != NULL)
+               task_list = g_slist_remove(task_list, task);
 
        if (task == NULL)
                return;
 
        DBG("release %s", task->ifname);
 
-       g_static_mutex_lock(&task_mutex);
-       task_list = g_slist_remove(task_list, task);
-       g_static_mutex_unlock(&task_mutex);
+       kill_task(task);
+}
 
-       if (task->child != NULL) {
-               connman_element_unregister(task->child);
-               connman_element_unref(task->child);
-               task->child = NULL;
-       }
+static void dhclient_change(struct connman_element *element)
+{
+       DBG("element %p name %s", element, element->name);
 
-       kill_task(task);
+       if (element->state == CONNMAN_ELEMENT_STATE_ERROR)
+               connman_element_set_error(element->parent,
+                                       CONNMAN_ELEMENT_ERROR_DHCP_FAILED);
 }
 
 static struct connman_driver dhclient_driver = {
@@ -230,6 +229,7 @@ static struct connman_driver dhclient_driver = {
        .type           = CONNMAN_ELEMENT_TYPE_DHCP,
        .probe          = dhclient_probe,
        .remove         = dhclient_remove,
+       .change         = dhclient_change,
 };
 
 static DBusHandlerResult dhclient_filter(DBusConnection *conn,
@@ -253,9 +253,7 @@ static DBusHandlerResult dhclient_filter(DBusConnection *conn,
 
        DBG("change %d to %s", pid, text);
 
-       g_static_mutex_lock(&task_mutex);
        task = find_task_by_pid(pid);
-       g_static_mutex_unlock(&task_mutex);
 
        if (task == NULL)
                return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
@@ -308,15 +306,19 @@ static DBusHandlerResult dhclient_filter(DBusConnection *conn,
        if (g_ascii_strcasecmp(text, "PREINIT") == 0) {
        } else if (g_ascii_strcasecmp(text, "BOUND") == 0 ||
                                g_ascii_strcasecmp(text, "REBOOT") == 0) {
-               task->child = connman_element_create();
-               task->child->type = CONNMAN_ELEMENT_TYPE_IPV4;
-               task->child->netdev.index = task->ifindex;
+               struct connman_element *element;
+               element = connman_element_create(NULL);
+               element->type = CONNMAN_ELEMENT_TYPE_IPV4;
+               element->index = task->ifindex;
                connman_element_update(task->element);
-               connman_element_register(task->child, task->element);
+               if (connman_element_register(element, task->element) < 0)
+                       connman_element_unref(element);
        } else if (g_ascii_strcasecmp(text, "RENEW") == 0 ||
                                g_ascii_strcasecmp(text, "REBIND") == 0) {
                connman_element_update(task->element);
-               connman_element_update(task->child);
+       } else if (g_ascii_strcasecmp(text, "FAIL") == 0) {
+               connman_element_set_error(task->element,
+                                               CONNMAN_ELEMENT_ERROR_FAILED);
        } else {
        }
 
@@ -325,24 +327,21 @@ static DBusHandlerResult dhclient_filter(DBusConnection *conn,
 
 static DBusConnection *connection;
 
+static const char *dhclient_rule = "path=" DHCLIENT_PATH
+                                               ",interface=" DHCLIENT_INTF;
+
 static int dhclient_init(void)
 {
-       gchar *filter;
        int err;
 
-       connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+       connection = connman_dbus_get_connection();
 
        busname = dbus_bus_get_unique_name(connection);
        busname = CONNMAN_SERVICE;
 
        dbus_connection_add_filter(connection, dhclient_filter, NULL, NULL);
 
-       filter = g_strdup_printf("interface=%s,path=%s",
-                                               DHCLIENT_INTF, DHCLIENT_PATH);
-
-       dbus_bus_add_match(connection, filter, NULL);
-
-       g_free(filter);
+       dbus_bus_add_match(connection, dhclient_rule, NULL);
 
        err = connman_driver_register(&dhclient_driver);
        if (err < 0) {
@@ -357,31 +356,25 @@ static void dhclient_exit(void)
 {
        GSList *list;
 
-       g_static_mutex_lock(&task_mutex);
-
        for (list = task_list; list; list = list->next) {
                struct dhclient_task *task = list->data;
 
-               if (task->child) {
-                       connman_element_unregister(task->child);
-                       connman_element_unref(task->child);
-                       task->child = NULL;
-               }
-
                DBG("killing process %d", task->pid);
 
                kill_task(task);
                unlink_task(task);
        }
 
-       g_static_mutex_unlock(&task_mutex);
-
        g_slist_free(task_list);
 
        connman_driver_unregister(&dhclient_driver);
 
+       dbus_bus_remove_match(connection, dhclient_rule, NULL);
+
+       dbus_connection_remove_filter(connection, dhclient_filter, NULL);
+
        dbus_connection_unref(connection);
 }
 
-CONNMAN_PLUGIN_DEFINE("dhclient", "ISC DHCP client plugin", VERSION,
-                                               dhclient_init, dhclient_exit)
+CONNMAN_PLUGIN_DEFINE(dhclient, "ISC DHCP client plugin", VERSION,
+               CONNMAN_PLUGIN_PRIORITY_DEFAULT, dhclient_init, dhclient_exit)