*
* 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/inet.h>
#include <connman/dbus.h>
#include <connman/log.h>
GPid pid;
int ifindex;
gchar *ifname;
- struct connman_element *parent;
- struct connman_element *child;
+ struct connman_element *element;
};
-static GStaticMutex task_mutex = G_STATIC_MUTEX_INIT;
static GSList *task_list = NULL;
static struct dhclient_task *find_task_by_pid(GPid pid)
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);
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->parent = element;
- task->child = NULL;
+ task->ifindex = element->index;
+ task->ifname = connman_inet_ifname(element->index);
+ task->element = element;
if (task->ifname == NULL) {
g_free(task);
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);
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);
+}
- 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 = {
.type = CONNMAN_ELEMENT_TYPE_DHCP,
.probe = dhclient_probe,
.remove = dhclient_remove,
+ .change = dhclient_change,
};
-static void copy_ipv4(struct connman_element *src, struct connman_element *dst)
-{
- g_free(dst->ipv4.address);
- g_free(dst->ipv4.netmask);
- g_free(dst->ipv4.gateway);
- g_free(dst->ipv4.network);
- g_free(dst->ipv4.broadcast);
- g_free(dst->ipv4.nameserver);
-
- dst->ipv4.address = g_strdup(src->ipv4.address);
- dst->ipv4.netmask = g_strdup(src->ipv4.netmask);
- dst->ipv4.gateway = g_strdup(src->ipv4.gateway);
- dst->ipv4.network = g_strdup(src->ipv4.network);
- dst->ipv4.broadcast = g_strdup(src->ipv4.broadcast);
- dst->ipv4.nameserver = g_strdup(src->ipv4.nameserver);
-}
-
static DBusHandlerResult dhclient_filter(DBusConnection *conn,
DBusMessage *msg, void *data)
{
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;
DBG("%s = %s", key, value);
- if (g_ascii_strcasecmp(key, "new_ip_address") == 0)
- task->parent->ipv4.address = g_strdup(value);
+ if (g_ascii_strcasecmp(key, "new_ip_address") == 0) {
+ g_free(task->element->ipv4.address);
+ task->element->ipv4.address = g_strdup(value);
+ }
- if (g_ascii_strcasecmp(key, "new_subnet_mask") == 0)
- task->parent->ipv4.netmask = g_strdup(value);
+ if (g_ascii_strcasecmp(key, "new_subnet_mask") == 0) {
+ g_free(task->element->ipv4.netmask);
+ task->element->ipv4.netmask = g_strdup(value);
+ }
- if (g_ascii_strcasecmp(key, "new_routers") == 0)
- task->parent->ipv4.gateway = g_strdup(value);
+ if (g_ascii_strcasecmp(key, "new_routers") == 0) {
+ g_free(task->element->ipv4.gateway);
+ task->element->ipv4.gateway = g_strdup(value);
+ }
- if (g_ascii_strcasecmp(key, "new_network_number") == 0)
- task->parent->ipv4.network = g_strdup(value);
+ if (g_ascii_strcasecmp(key, "new_network_number") == 0) {
+ g_free(task->element->ipv4.network);
+ task->element->ipv4.network = g_strdup(value);
+ }
- if (g_ascii_strcasecmp(key, "new_broadcast_address") == 0)
- task->parent->ipv4.broadcast = g_strdup(value);
+ if (g_ascii_strcasecmp(key, "new_broadcast_address") == 0) {
+ g_free(task->element->ipv4.broadcast);
+ task->element->ipv4.broadcast = g_strdup(value);
+ }
- if (g_ascii_strcasecmp(key, "new_domain_name_servers") == 0)
- task->parent->ipv4.nameserver = g_strdup(value);
+ if (g_ascii_strcasecmp(key, "new_domain_name_servers") == 0) {
+ g_free(task->element->ipv4.nameserver);
+ task->element->ipv4.nameserver = g_strdup(value);
+ }
dbus_message_iter_next(&dict);
}
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;
- copy_ipv4(task->parent, task->child);
- connman_element_register(task->child, task->parent);
+ struct connman_element *element;
+ element = connman_element_create(NULL);
+ element->type = CONNMAN_ELEMENT_TYPE_IPV4;
+ element->index = task->ifindex;
+ connman_element_update(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) {
- copy_ipv4(task->parent, task->child);
- connman_element_update(task->child);
+ connman_element_update(task->element);
+ } else if (g_ascii_strcasecmp(text, "FAIL") == 0) {
+ connman_element_set_error(task->element,
+ CONNMAN_ELEMENT_ERROR_FAILED);
} else {
}
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) {
{
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)