From dc405c55dc7e4a4cc2533e8103adac7340d6d8de Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 24 Mar 2008 13:33:56 +0100 Subject: [PATCH] Update DHCP plugin to use D-Bus low-level calls --- configure.in | 1 + plugins/Makefile.am | 5 +-- plugins/dhclient.c | 82 +++++++++++++++++++++++++++++++++++------------ scripts/dhclient-script.c | 23 ++++++++++--- 4 files changed, 83 insertions(+), 28 deletions(-) diff --git a/configure.in b/configure.in index 9918d72..6830105 100644 --- a/configure.in +++ b/configure.in @@ -41,6 +41,7 @@ AC_ARG_ENABLE(pie, AC_HELP_STRING([--enable-pie], fi ]) +AC_PATH_PROG(DHCLIENT, [dhclient]) AC_PATH_PROG(WPASUPPLICANT, [wpa_supplicant]) PKG_CHECK_MODULES(GMODULE, gmodule-2.0, dummy=yes, diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 87464b0..3ecb1ae 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -10,6 +10,8 @@ libconnman_80211_la_SOURCES = 80211.c supplicant.h supplicant.c libconnman_dhclient_la_SOURCES = dhclient.c libconnman_dhclient_la_LIBADD = @GDBUS_LIBS@ +libconnman_dhclient_la_CFLAGS = @GDBUS_CFLAGS@ -DDHCLIENT=\"@DHCLIENT@\" \ + -DSTATEDIR=\""$(statedir)"\" -DSCRIPTDIR=\""$(scriptdir)"\" libconnman_resolvconf_la_SOURCES = resolvconf.c @@ -23,8 +25,7 @@ else scriptdir = $(libdir)/connman/scripts endif -AM_CFLAGS = @GDBUS_CFLAGS@ \ - -DSTATEDIR=\""$(statedir)"\" -DSCRIPTDIR=\""$(scriptdir)"\" +AM_CFLAGS = @GDBUS_CFLAGS@ INCLUDES = -I$(top_builddir)/include diff --git a/plugins/dhclient.c b/plugins/dhclient.c index 211b84e..8847a1d 100644 --- a/plugins/dhclient.c +++ b/plugins/dhclient.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -40,6 +41,9 @@ #include #include +#define DHCLIENT_INTF "org.isc.dhclient" +#define DHCLIENT_PATH "/org/isc/dhclient" + static const char *busname; struct dhclient_task { @@ -83,7 +87,8 @@ static void kill_task(struct dhclient_task *task) { char pathname[PATH_MAX]; - kill(task->pid, SIGTERM); + if (task->pid > 0) + kill(task->pid, SIGTERM); snprintf(pathname, sizeof(pathname) - 1, "%s/dhclient.%s.pid", STATEDIR, task->ifname); @@ -98,11 +103,37 @@ static void kill_task(struct dhclient_task *task) g_free(task); } +static void task_died(GPid pid, gint status, gpointer data) +{ + struct dhclient_task *task = data; + + if (WIFEXITED(status)) + printf("[DHCP] exit status %d for %s\n", + WEXITSTATUS(status), task->ifname); + else + printf("[DHCP] signal %d killed %s\n", + WTERMSIG(status), task->ifname); + + g_spawn_close_pid(pid); + task->pid = 0; + + tasks = g_slist_remove(tasks, task); + + kill_task(task); +} + +static void task_setup(gpointer data) +{ + struct dhclient_task *task = data; + + printf("[DHCP] setup %s\n", task->ifname); +} + static int dhclient_request(struct connman_iface *iface) { struct ifreq ifr; struct dhclient_task *task; - char *argv[16], address[128], pidfile[PATH_MAX]; + char *argv[16], *envp[1], address[128], pidfile[PATH_MAX]; char leases[PATH_MAX], config[PATH_MAX], script[PATH_MAX]; int sk, err; @@ -143,7 +174,7 @@ static int dhclient_request(struct connman_iface *iface) snprintf(config, sizeof(config) - 1, "%s/dhclient.conf", SCRIPTDIR); snprintf(script, sizeof(script) - 1, "%s/dhclient-script", SCRIPTDIR); - argv[0] = "/sbin/dhclient"; + argv[0] = DHCLIENT; argv[1] = "-d"; argv[2] = "-q"; argv[3] = "-n"; @@ -160,15 +191,19 @@ static int dhclient_request(struct connman_iface *iface) argv[14] = task->ifname; argv[15] = NULL; - if (g_spawn_async(NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, - NULL, NULL, &task->pid, NULL) == FALSE) { + envp[0] = NULL; + + 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"); return -1; } tasks = g_slist_append(tasks, task); - printf("[DHCP] executed with pid %d\n", task->pid); + g_child_watch_add(task->pid, task_died, task); + + printf("[DHCP] executed %s with pid %d\n", DHCLIENT, task->pid); return 0; } @@ -196,8 +231,8 @@ static struct connman_dhcp_driver dhclient_driver = { .release = dhclient_release, }; -static DBusMessage *notify_method(DBusConnection *conn, - DBusMessage *msg, void *data) +static DBusHandlerResult dhclient_filter(DBusConnection *conn, + DBusMessage *msg, void *data) { DBusMessageIter iter, dict; dbus_uint32_t pid; @@ -205,6 +240,9 @@ static DBusMessage *notify_method(DBusConnection *conn, 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); @@ -219,7 +257,7 @@ static DBusMessage *notify_method(DBusConnection *conn, task = find_task_by_pid(pid); if (task == NULL) - return NULL; + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; dbus_message_iter_recurse(&iter, &dict); @@ -267,27 +305,29 @@ static DBusMessage *notify_method(DBusConnection *conn, connman_dhcp_update(task->iface, CONNMAN_DHCP_STATE_FAILED, NULL); - return NULL; + return DBUS_HANDLER_RESULT_HANDLED; } -static GDBusMethodTable dhclient_methods[] = { - { "notify", "usa{ss}", "", notify_method, G_DBUS_METHOD_FLAG_NOREPLY }, - { }, -}; - static DBusConnection *connection; static int plugin_init(void) { - connection = g_dbus_setup_bus(DBUS_BUS_SYSTEM, NULL, NULL); + gchar *filter; + + connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); busname = dbus_bus_get_unique_name(connection); - g_dbus_register_object(connection, "/org/isc/dhclient", NULL, NULL); + busname = "org.freedesktop.connman"; + + 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_dbus_register_interface(connection, "/org/isc/dhclient", - "org.isc.dhclient", - dhclient_methods, NULL, NULL); + g_free(filter); connman_dhcp_register(&dhclient_driver); @@ -310,7 +350,7 @@ static void plugin_exit(void) connman_dhcp_unregister(&dhclient_driver); - g_dbus_cleanup_connection(connection); + dbus_connection_unref(connection); } CONNMAN_PLUGIN_DEFINE("dhclient", "ISC DHCP client plugin", VERSION, diff --git a/scripts/dhclient-script.c b/scripts/dhclient-script.c index 39b235c..f4a8431 100644 --- a/scripts/dhclient-script.c +++ b/scripts/dhclient-script.c @@ -56,6 +56,7 @@ static void append(DBusMessageIter *dict, const char *pattern) int main(int argc, char *argv[]) { DBusConnection *conn; + DBusError error; DBusMessage *msg; DBusMessageIter iter, dict; dbus_uint32_t pid; @@ -67,17 +68,28 @@ int main(int argc, char *argv[]) reason = getenv("reason"); interface = getenv("interface"); - conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL); - if (conn == NULL) - exit(1); + dbus_error_init(&error); + + conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error); + if (conn == NULL) { + if (dbus_error_is_set(&error) == TRUE) { + fprintf(stderr, "%s\n", error.message); + dbus_error_free(&error); + } else + fprintf(stderr, "Failed to get on system bus\n"); + return 0; + } msg = dbus_message_new_method_call(busname, "/org/isc/dhclient", "org.isc.dhclient", "notify"); if (msg == NULL) { dbus_connection_unref(conn); - exit(1); + fprintf(stderr, "Failed to allocate method call\n"); + return 0; } + dbus_message_set_no_reply(msg, TRUE); + dbus_message_append_args(msg, DBUS_TYPE_UINT32, &pid, DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID); @@ -100,7 +112,8 @@ int main(int argc, char *argv[]) dbus_message_iter_close_container(&iter, &dict); - dbus_connection_send(conn, msg, NULL); + if (dbus_connection_send(conn, msg, NULL) == FALSE) + fprintf(stderr, "Failed to send message\n"); dbus_message_unref(msg); -- 2.7.4