Change service name from org.moblin.connman to net.connman
[framework/connectivity/connman.git] / tools / dhclient-test.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <signal.h>
30 #include <sys/wait.h>
31
32 #include <gdbus.h>
33
34 #define INTERFACE "isc.dhclient"
35 #define PATH "/dhclient"
36
37 static GTimer *timer;
38
39 static GMainLoop *main_loop;
40
41 static guint child_watch = 0;
42 static pid_t pid = 0;
43
44 static void sig_term(int sig)
45 {
46         g_main_loop_quit(main_loop);
47 }
48
49 static void free_pointer(gpointer data, gpointer user_data)
50 {
51         g_free(data);
52 }
53
54 static void dhclient_died(GPid pid, gint status, gpointer user_data)
55 {
56         if (WIFEXITED(status))
57                 printf("exit status %d\n", WEXITSTATUS(status));
58         else
59                 printf("signal %d\n", WTERMSIG(status));
60
61         g_spawn_close_pid(pid);
62
63         child_watch = 0;
64 }
65
66 static void dhclient_setup(gpointer user_data)
67 {
68         printf("dhclient process setup\n");
69 }
70
71 static void add_argument(GPtrArray *array, const char *name,
72                                                 const char *format, ...)
73 {
74         va_list ap;
75         char *str;
76
77         str = g_strdup(name);
78         g_ptr_array_add(array, str);
79
80         va_start(ap, format);
81
82         if (format != NULL) {
83                 str = g_strdup_vprintf(format, ap);
84                 g_ptr_array_add(array, str);
85         }
86
87         va_end(ap);
88 }
89
90 static void start_dhclient(DBusConnection *conn, const char *ifname)
91 {
92         GSpawnFlags flags = G_SPAWN_DO_NOT_REAP_CHILD;
93         GPtrArray *argv;
94         GPtrArray *envp;
95         gboolean result;
96         const char *busname;
97
98         busname = dbus_bus_get_unique_name(conn);
99         busname = "net.connman";
100
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);
115
116         envp = g_ptr_array_new();
117         g_ptr_array_add(envp, NULL);
118
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);
123
124         child_watch = g_child_watch_add(pid, dhclient_died, NULL);
125
126         g_ptr_array_foreach(envp, free_pointer, NULL);
127         g_ptr_array_free(envp, TRUE);
128
129         g_ptr_array_foreach(argv, free_pointer, NULL);
130         g_ptr_array_free(argv, TRUE);
131 }
132
133 static void parse_notification(DBusMessage *msg)
134 {
135         DBusMessageIter iter, dict;
136         dbus_uint32_t pid;
137         gdouble elapsed;
138         const char *text, *key, *value;
139
140         dbus_message_iter_init(msg, &iter);
141
142         dbus_message_iter_get_basic(&iter, &pid);
143         dbus_message_iter_next(&iter);
144
145         dbus_message_iter_get_basic(&iter, &text);
146         dbus_message_iter_next(&iter);
147
148         printf("change %d to %s\n", pid, text);
149
150         dbus_message_iter_recurse(&iter, &dict);
151
152         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
153                 DBusMessageIter entry;
154
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);
159
160                 printf("%s = %s\n", key, value);
161
162                 dbus_message_iter_next(&dict);
163         }
164
165         if (g_strcmp0(text, "PREINIT") == 0)
166                 return;
167
168         elapsed = g_timer_elapsed(timer, NULL);
169
170         g_print("elapsed %f seconds\n", elapsed);
171
172         g_main_loop_quit(main_loop);
173 }
174
175 static DBusHandlerResult notify_filter(DBusConnection *conn,
176                                         DBusMessage *msg, void *user_data)
177 {
178         if (dbus_message_get_type(msg) != DBUS_MESSAGE_TYPE_METHOD_CALL)
179                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
180
181         if (dbus_message_has_interface(msg, INTERFACE) == FALSE)
182                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
183
184         if (dbus_message_has_path(msg, PATH) == FALSE)
185                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
186
187         if (dbus_message_has_member(msg, "Notify") == FALSE)
188                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
189
190         parse_notification(msg);
191
192         return DBUS_HANDLER_RESULT_HANDLED;
193 }
194
195 static const char *notify_rule = "type=method_call"
196                                         ",interface=" INTERFACE;
197
198 int main(int argc, char *argv[])
199 {
200         DBusConnection *conn;
201         DBusError err;
202         struct sigaction sa;
203         const char *ifname;
204
205         if (argc < 2) {
206                 printf("Usage: dhclient-test <interface name>\n");
207                 exit(0);
208         }
209
210         ifname = argv[1];
211
212         printf("Create DHCP client for interface %s\n", ifname);
213
214         main_loop = g_main_loop_new(NULL, FALSE);
215
216         dbus_error_init(&err);
217
218         conn = g_dbus_setup_bus(DBUS_BUS_SYSTEM, "net.connman", &err);
219         if (conn == NULL) {
220                 if (dbus_error_is_set(&err) == TRUE) {
221                         fprintf(stderr, "%s\n", err.message);
222                         dbus_error_free(&err);
223                 } else
224                         fprintf(stderr, "Can't register with system bus\n");
225                 exit(1);
226         }
227
228         dbus_connection_add_filter(conn, notify_filter, NULL, NULL);
229
230         dbus_bus_add_match(conn, notify_rule, NULL);
231         dbus_connection_flush(conn);
232
233         printf("Start DHCP operation\n");
234
235         timer = g_timer_new();
236
237         start_dhclient(conn, ifname);
238
239         memset(&sa, 0, sizeof(sa));
240         sa.sa_handler = sig_term;
241         sigaction(SIGINT, &sa, NULL);
242         sigaction(SIGTERM, &sa, NULL);
243
244         g_main_loop_run(main_loop);
245
246         if (pid > 0)
247                 kill(pid, SIGTERM);
248
249         if (child_watch > 0)
250                 g_source_remove(child_watch);
251
252         g_timer_destroy(timer);
253
254         dbus_bus_remove_match(conn, notify_rule, NULL);
255         dbus_connection_flush(conn);
256
257         dbus_connection_remove_filter(conn, notify_filter, NULL);
258
259         dbus_connection_unref(conn);
260
261         g_main_loop_unref(main_loop);
262
263         return 0;
264 }