X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=plugins%2Fdhclient.c;h=cb0e8753d4c85c00ac1aa6fd4aa91d34ce8b137a;hb=44ed8df3ee8197d0cb06a4250cf51484b88e5b5b;hp=612d02af30df07c38e35e93aa0c346da7a8fa183;hpb=249a12194decb4b7a06d717bcd5284d1467e759b;p=connman diff --git a/plugins/dhclient.c b/plugins/dhclient.c index 612d02a..cb0e875 100644 --- a/plugins/dhclient.c +++ b/plugins/dhclient.c @@ -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 @@ -23,23 +23,17 @@ #include #endif -#include -#include #include -#include -#include -#include #include -#include -#include -#include -#include - -#include -#include +#include +#define CONNMAN_API_SUBJECT_TO_CHANGE #include -#include +#include +#include +#include + +#include "inet.h" #define DHCLIENT_INTF "org.isc.dhclient" #define DHCLIENT_PATH "/org/isc/dhclient" @@ -49,17 +43,17 @@ static const char *busname; struct dhclient_task { GPid pid; int ifindex; - char *ifname; - struct connman_iface *iface; + gchar *ifname; + struct connman_element *element; }; -static GSList *tasks = NULL; +static GSList *task_list = NULL; static struct dhclient_task *find_task_by_pid(GPid pid) { GSList *list; - for (list = tasks; list; list = list->next) { + for (list = task_list; list; list = list->next) { struct dhclient_task *task = list->data; if (task->pid == pid) @@ -73,7 +67,7 @@ static struct dhclient_task *find_task_by_index(int index) { GSList *list; - for (list = tasks; list; list = list->next) { + for (list = task_list; list; list = list->next) { struct dhclient_task *task = list->data; if (task->ifindex == index) @@ -85,37 +79,46 @@ static struct dhclient_task *find_task_by_index(int index) static void kill_task(struct dhclient_task *task) { + DBG("task %p name %s pid %d", task, task->ifname, task->pid); + if (task->pid > 0) kill(task->pid, SIGTERM); } +static void unlink_task(struct dhclient_task *task) +{ + gchar *pathname; + + DBG("task %p name %s pid %d", task, task->ifname, task->pid); + + pathname = g_strdup_printf("%s/dhclient.%s.pid", + STATEDIR, task->ifname); + g_unlink(pathname); + g_free(pathname); + + pathname = g_strdup_printf("%s/dhclient.%s.leases", + STATEDIR, task->ifname); + g_unlink(pathname); + g_free(pathname); +} + static void task_died(GPid pid, gint status, gpointer data) { struct dhclient_task *task = data; - char pathname[PATH_MAX]; if (WIFEXITED(status)) - printf("[DHCP] exit status %d for %s\n", - WEXITSTATUS(status), task->ifname); + DBG("exit status %d for %s", WEXITSTATUS(status), task->ifname); else - printf("[DHCP] signal %d killed %s\n", - WTERMSIG(status), task->ifname); + DBG("signal %d killed %s", WTERMSIG(status), task->ifname); g_spawn_close_pid(pid); task->pid = 0; - tasks = g_slist_remove(tasks, task); - - snprintf(pathname, sizeof(pathname) - 1, - "%s/dhclient.%s.pid", STATEDIR, task->ifname); - unlink(pathname); - - snprintf(pathname, sizeof(pathname) - 1, - "%s/dhclient.%s.leases", STATEDIR, task->ifname); - unlink(pathname); + task_list = g_slist_remove(task_list, task); - free(task->ifname); + unlink_task(task); + g_free(task->ifname); g_free(task); } @@ -123,45 +126,34 @@ static void task_setup(gpointer data) { struct dhclient_task *task = data; - printf("[DHCP] setup %s\n", task->ifname); + DBG("task %p name %s", task, task->ifname); } -static int dhclient_request(struct connman_iface *iface) +static int dhclient_probe(struct connman_element *element) { - struct ifreq ifr; struct dhclient_task *task; char *argv[16], *envp[1], address[128], pidfile[PATH_MAX]; char leases[PATH_MAX], config[PATH_MAX], script[PATH_MAX]; - int sk, err; - - sk = socket(PF_INET, SOCK_DGRAM, 0); - if (sk < 0) - return -EIO; - - memset(&ifr, 0, sizeof(ifr)); - ifr.ifr_ifindex = iface->index; - - err = ioctl(sk, SIOCGIFNAME, &ifr); - close(sk); + DBG("element %p name %s", element, element->name); - if (err < 0) - return -EIO; + if (access(DHCLIENT, X_OK) < 0) + return -errno; task = g_try_new0(struct dhclient_task, 1); if (task == NULL) return -ENOMEM; - task->ifindex = iface->index; - task->ifname = strdup(ifr.ifr_name); - task->iface = iface; + task->ifindex = element->index; + task->ifname = inet_index2name(element->index); + task->element = element; if (task->ifname == NULL) { g_free(task); return -ENOMEM; } - printf("[DHCP] request %s\n", task->ifname); + DBG("request %s", task->ifname); snprintf(address, sizeof(address) - 1, "BUSNAME=%s", busname); snprintf(pidfile, sizeof(pidfile) - 1, @@ -192,40 +184,42 @@ static int dhclient_request(struct connman_iface *iface) if (g_spawn_async(NULL, argv, envp, G_SPAWN_DO_NOT_REAP_CHILD, task_setup, task, &task->pid, NULL) == FALSE) { - printf("Failed to spawn dhclient\n"); + connman_error("Failed to spawn dhclient"); return -1; } - tasks = g_slist_append(tasks, task); + task_list = g_slist_append(task_list, task); g_child_watch_add(task->pid, task_died, task); - printf("[DHCP] executed %s with pid %d\n", DHCLIENT, task->pid); + DBG("executed %s with pid %d", DHCLIENT, task->pid); return 0; } -static int dhclient_release(struct connman_iface *iface) +static void dhclient_remove(struct connman_element *element) { struct dhclient_task *task; - task = find_task_by_index(iface->index); - if (task == NULL) - return -ENODEV; + DBG("element %p name %s", element, element->name); - printf("[DHCP] release %s\n", task->ifname); + task = find_task_by_index(element->index); + if (task != NULL) + task_list = g_slist_remove(task_list, task); - tasks = g_slist_remove(tasks, task); + if (task == NULL) + return; - kill_task(task); + DBG("release %s", task->ifname); - return 0; + kill_task(task); } -static struct connman_dhcp_driver dhclient_driver = { +static struct connman_driver dhclient_driver = { .name = "dhclient", - .request = dhclient_request, - .release = dhclient_release, + .type = CONNMAN_ELEMENT_TYPE_DHCP, + .probe = dhclient_probe, + .remove = dhclient_remove, }; static DBusHandlerResult dhclient_filter(DBusConnection *conn, @@ -234,14 +228,11 @@ static DBusHandlerResult dhclient_filter(DBusConnection *conn, DBusMessageIter iter, dict; dbus_uint32_t pid; struct dhclient_task *task; - struct connman_ipv4 ipv4; const char *text, *key, *value; if (dbus_message_is_method_call(msg, DHCLIENT_INTF, "notify") == FALSE) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; - memset(&ipv4, 0, sizeof(ipv4)); - dbus_message_iter_init(msg, &iter); dbus_message_iter_get_basic(&iter, &pid); @@ -250,9 +241,10 @@ static DBusHandlerResult dhclient_filter(DBusConnection *conn, dbus_message_iter_get_basic(&iter, &text); dbus_message_iter_next(&iter); - printf("[DHCP] change %d to %s\n", pid, text); + DBG("change %d to %s", pid, text); task = find_task_by_pid(pid); + if (task == NULL) return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; @@ -266,89 +258,110 @@ static DBusHandlerResult dhclient_filter(DBusConnection *conn, dbus_message_iter_next(&entry); dbus_message_iter_get_basic(&entry, &value); - printf("[DHCP] %s = %s\n", key, value); + DBG("%s = %s", key, value); - if (strcmp(key, "new_ip_address") == 0) - inet_aton(value, &ipv4.address); + if (g_ascii_strcasecmp(key, "new_ip_address") == 0) { + g_free(task->element->ipv4.address); + task->element->ipv4.address = g_strdup(value); + } - if (strcmp(key, "new_subnet_mask") == 0) - inet_aton(value, &ipv4.netmask); + if (g_ascii_strcasecmp(key, "new_subnet_mask") == 0) { + g_free(task->element->ipv4.netmask); + task->element->ipv4.netmask = g_strdup(value); + } - if (strcmp(key, "new_routers") == 0) - inet_aton(value, &ipv4.gateway); + if (g_ascii_strcasecmp(key, "new_routers") == 0) { + g_free(task->element->ipv4.gateway); + task->element->ipv4.gateway = g_strdup(value); + } - if (strcmp(key, "new_network_number") == 0) - inet_aton(value, &ipv4.network); + if (g_ascii_strcasecmp(key, "new_network_number") == 0) { + g_free(task->element->ipv4.network); + task->element->ipv4.network = g_strdup(value); + } - if (strcmp(key, "new_broadcast_address") == 0) - inet_aton(value, &ipv4.broadcast); + if (g_ascii_strcasecmp(key, "new_broadcast_address") == 0) { + g_free(task->element->ipv4.broadcast); + task->element->ipv4.broadcast = g_strdup(value); + } - if (strcmp(key, "new_domain_name_servers") == 0) - inet_aton(value, &ipv4.nameserver); + 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 (strcmp(text, "PREINIT") == 0) - connman_dhcp_update(task->iface, - CONNMAN_DHCP_STATE_INIT, &ipv4); - else if (strcmp(text, "BOUND") == 0 || strcmp(text, "REBOOT") == 0) - connman_dhcp_update(task->iface, - CONNMAN_DHCP_STATE_BOUND, &ipv4); - else if (strcmp(text, "RENEW") == 0 || strcmp(text, "REBIND") == 0) - connman_dhcp_update(task->iface, - CONNMAN_DHCP_STATE_RENEW, &ipv4); - else - connman_dhcp_update(task->iface, - CONNMAN_DHCP_STATE_FAILED, NULL); + if (g_ascii_strcasecmp(text, "PREINIT") == 0) { + } else if (g_ascii_strcasecmp(text, "BOUND") == 0 || + g_ascii_strcasecmp(text, "REBOOT") == 0) { + 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) { + connman_element_update(task->element); + } else { + } return DBUS_HANDLER_RESULT_HANDLED; } static DBusConnection *connection; -static int plugin_init(void) +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 = "org.freedesktop.connman"; + 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); + dbus_bus_add_match(connection, dhclient_rule, NULL); - g_free(filter); - - connman_dhcp_register(&dhclient_driver); + err = connman_driver_register(&dhclient_driver); + if (err < 0) { + dbus_connection_unref(connection); + return err; + } return 0; } -static void plugin_exit(void) +static void dhclient_exit(void) { GSList *list; - for (list = tasks; list; list = list->next) { + for (list = task_list; list; list = list->next) { struct dhclient_task *task = list->data; - printf("[DHCP] killing process %d\n", task->pid); + DBG("killing process %d", task->pid); kill_task(task); + unlink_task(task); } - g_slist_free(tasks); + g_slist_free(task_list); + + connman_driver_unregister(&dhclient_driver); + + dbus_bus_remove_match(connection, dhclient_rule, NULL); - connman_dhcp_unregister(&dhclient_driver); + dbus_connection_remove_filter(connection, dhclient_filter, NULL); dbus_connection_unref(connection); } -CONNMAN_PLUGIN_DEFINE("dhclient", "ISC DHCP client plugin", VERSION, - plugin_init, plugin_exit) +CONNMAN_PLUGIN_DEFINE(dhclient, "ISC DHCP client plugin", VERSION, + dhclient_init, dhclient_exit)