5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #define INTERFACE "isc.dhclient"
35 #define PATH "/dhclient"
39 static GMainLoop *main_loop;
41 static guint child_watch = 0;
44 static void sig_term(int sig)
46 g_main_loop_quit(main_loop);
49 static void free_pointer(gpointer data, gpointer user_data)
54 static void dhclient_died(GPid pid, gint status, gpointer user_data)
56 if (WIFEXITED(status))
57 printf("exit status %d\n", WEXITSTATUS(status));
59 printf("signal %d\n", WTERMSIG(status));
61 g_spawn_close_pid(pid);
66 static void dhclient_setup(gpointer user_data)
68 printf("dhclient process setup\n");
71 static void add_argument(GPtrArray *array, const char *name,
72 const char *format, ...)
78 g_ptr_array_add(array, str);
83 str = g_strdup_vprintf(format, ap);
84 g_ptr_array_add(array, str);
90 static void start_dhclient(DBusConnection *conn, const char *ifname)
92 GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD;
98 busname = dbus_bus_get_unique_name(conn);
99 busname = "org.moblin.connman";
101 argv = g_ptr_array_new();
102 add_argument(argv, DHCLIENT, NULL);
103 add_argument(argv, "-d", NULL);
104 add_argument(argv, "-q", NULL);
105 add_argument(argv, "-e", "BUSNAME=%s", busname);
106 add_argument(argv, "-e", "BUSINTF=%s", INTERFACE);
107 add_argument(argv, "-e", "BUSPATH=%s", PATH);
108 add_argument(argv, "-pf", "%s/dhclient.%s.pid", STATEDIR, ifname);
109 add_argument(argv, "-lf", "%s/dhclient.%s.leases", STATEDIR, ifname);
110 add_argument(argv, "-cf", "%s/dhclient.conf", SCRIPTDIR);
111 add_argument(argv, "-sf", "%s/dhclient-script", SCRIPTDIR);
112 add_argument(argv, ifname, NULL);
113 add_argument(argv, "-n", NULL);
114 g_ptr_array_add(argv, NULL);
116 envp = g_ptr_array_new();
117 g_ptr_array_add(envp, NULL);
119 result = g_spawn_async_with_pipes(NULL, (char **) argv->pdata,
120 (char **) envp->pdata,
121 flags, dhclient_setup, NULL,
122 &pid, NULL, NULL, NULL, NULL);
124 child_watch = g_child_watch_add(pid, dhclient_died, NULL);
126 g_ptr_array_foreach(envp, free_pointer, NULL);
127 g_ptr_array_free(envp, TRUE);
129 g_ptr_array_foreach(argv, free_pointer, NULL);
130 g_ptr_array_free(argv, TRUE);
133 static void parse_notification(DBusMessage *msg)
135 DBusMessageIter iter, dict;
138 const char *text, *key, *value;
140 dbus_message_iter_init(msg, &iter);
142 dbus_message_iter_get_basic(&iter, &pid);
143 dbus_message_iter_next(&iter);
145 dbus_message_iter_get_basic(&iter, &text);
146 dbus_message_iter_next(&iter);
148 printf("change %d to %s\n", pid, text);
150 dbus_message_iter_recurse(&iter, &dict);
152 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
153 DBusMessageIter entry;
155 dbus_message_iter_recurse(&dict, &entry);
156 dbus_message_iter_get_basic(&entry, &key);
157 dbus_message_iter_next(&entry);
158 dbus_message_iter_get_basic(&entry, &value);
160 printf("%s = %s\n", key, value);
162 dbus_message_iter_next(&dict);
165 if (g_strcmp0(text, "PREINIT") == 0)
168 elapsed = g_timer_elapsed(timer, NULL);
170 g_print("elapsed %f seconds\n", elapsed);
172 g_main_loop_quit(main_loop);
175 static DBusHandlerResult notify_filter(DBusConnection *conn,
176 DBusMessage *msg, void *user_data)
178 if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL)
179 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
181 if (dbus_message_has_interface(msg, INTERFACE) == FALSE)
182 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
184 if (dbus_message_has_path(msg, PATH) == FALSE)
185 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
187 if (dbus_message_has_member(msg, "Notify") == FALSE)
188 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
190 parse_notification(msg);
192 return DBUS_HANDLER_RESULT_HANDLED;
195 static const char *notify_rule = "type=method_call"
196 ",interface=" INTERFACE;
198 int main(int argc, char *argv[])
200 DBusConnection *conn;
206 printf("Usage: dhclient-test <interface name>\n");
212 printf("Create DHCP client for interface %s\n", ifname);
214 main_loop = g_main_loop_new(NULL, FALSE);
216 dbus_error_init(&err);
218 conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, "org.moblin.connman", &err);
220 if (dbus_error_is_set(&err) == TRUE) {
221 fprintf(stderr, "%s\n", err.message);
222 dbus_error_free(&err);
224 fprintf(stderr, "Can't register with system bus\n");
228 dbus_connection_add_filter(conn, notify_filter, NULL, NULL);
230 dbus_bus_add_match(conn, notify_rule, NULL);
231 dbus_connection_flush(conn);
233 printf("Start DHCP operation\n");
235 timer = g_timer_new();
237 start_dhclient(conn, ifname);
239 memset(&sa, 0, sizeof(sa));
240 sa.sa_handler = sig_term;
241 sigaction(SIGINT, &sa, NULL);
242 sigaction(SIGTERM, &sa, NULL);
244 g_main_loop_run(main_loop);
250 g_source_remove(child_watch);
252 g_timer_destroy(timer);
254 dbus_bus_remove_match(conn, notify_rule, NULL);
255 dbus_connection_flush(conn);
257 dbus_connection_remove_filter(conn, notify_filter, NULL);
259 dbus_connection_unref(conn);
261 g_main_loop_unref(main_loop);