Use the correct domain for uDHCP
[connman] / plugins / udhcp.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2008  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 <unistd.h>
28
29 #include <connman/plugin.h>
30 #include <connman/driver.h>
31 #include <connman/dbus.h>
32 #include <connman/log.h>
33
34 #include "inet.h"
35 #include "task.h"
36
37 #define UDHCPC_INTF  "net.busybox.udhcpc"
38 #define UDHCPC_PATH  "/net/busybox/udhcpc"
39
40 static int udhcp_probe(struct connman_element *element)
41 {
42         struct task_data *task;
43         char *argv[9], *envp[2], *ifname;
44         char pidfile[PATH_MAX], script[PATH_MAX];
45
46         DBG("element %p name %s", element, element->name);
47
48         if (access(UDHCPC, X_OK) < 0)
49                 return -errno;
50
51         ifname = inet_index2name(element->index);
52         if (ifname == NULL)
53                 return -ENOMEM;
54
55         snprintf(pidfile, sizeof(pidfile) - 1,
56                                 "%s/udhcpc.%s.pid", STATEDIR, ifname);
57         snprintf(script, sizeof(script) - 1, "%s/udhcpc-script", SCRIPTDIR);
58
59         argv[0] = UDHCPC;
60         argv[1] = "-f";
61         argv[2] = "-i";
62         argv[3] = ifname;
63         argv[4] = "-p";
64         argv[5] = pidfile;
65         argv[6] = "-s";
66         argv[7] = script;
67         argv[8] = NULL;
68
69         envp[0] = NULL;
70
71         task = task_spawn(element->index, argv, envp, NULL, element);
72         if (task == NULL) {
73                 g_free(ifname);
74                 return -EIO;
75         }
76
77         g_free(ifname);
78
79         return 0;
80 }
81
82 static void udhcp_remove(struct connman_element *element)
83 {
84         struct task_data *task;
85
86         DBG("element %p name %s", element, element->name);
87
88         task = task_find_by_index(element->index);
89         if (task == NULL)
90                 return;
91
92         task_kill(task);
93 }
94
95 static struct connman_driver udhcp_driver = {
96         .name           = "udhcp",
97         .type           = CONNMAN_ELEMENT_TYPE_DHCP,
98         .priority       = CONNMAN_DRIVER_PRIORITY_HIGH,
99         .probe          = udhcp_probe,
100         .remove         = udhcp_remove,
101 };
102
103 static void udhcp_bound(DBusMessage *msg, gboolean renew)
104 {
105         struct task_data *task;
106         struct connman_element *element, *parent;
107         const char *interface, *address, *netmask, *broadcast, *gateway, *dns;
108         int index;
109
110         dbus_message_get_args(msg, NULL, DBUS_TYPE_STRING, &interface,
111                                         DBUS_TYPE_STRING, &address,
112                                         DBUS_TYPE_STRING, &netmask,
113                                         DBUS_TYPE_STRING, &broadcast,
114                                         DBUS_TYPE_STRING, &gateway,
115                                         DBUS_TYPE_STRING, &dns,
116                                                         DBUS_TYPE_INVALID);
117
118         DBG("%s ==> address %s gateway %s", interface, address, gateway);
119
120         index = inet_name2index(interface);
121         if (index < 0)
122                 return;
123
124         task = task_find_by_index(index);
125         if (task == NULL)
126                 return;
127
128         parent = task_get_data(task);
129         if (parent == NULL)
130                 return;
131
132         g_free(parent->ipv4.address);
133         parent->ipv4.address = g_strdup(address);
134
135         g_free(parent->ipv4.netmask);
136         parent->ipv4.netmask = g_strdup(netmask);
137
138         g_free(parent->ipv4.broadcast);
139         parent->ipv4.broadcast = g_strdup(broadcast);
140
141         g_free(parent->ipv4.gateway);
142         parent->ipv4.gateway = g_strdup(gateway);
143
144         g_free(parent->ipv4.nameserver);
145         parent->ipv4.nameserver = g_strdup(dns);
146
147         connman_element_update(parent);
148
149         if (renew == TRUE)
150                 return;
151
152         element = connman_element_create(NULL);
153         if (element == NULL)
154                 return;
155
156         element->type = CONNMAN_ELEMENT_TYPE_IPV4;
157         element->index = index;
158
159         if (connman_element_register(element, parent) < 0)
160                 connman_element_unref(element);
161 }
162
163 static DBusHandlerResult udhcp_filter(DBusConnection *conn,
164                                                 DBusMessage *msg, void *data)
165 {
166         if (dbus_message_is_method_call(msg, UDHCPC_INTF, "bound") == TRUE) {
167                 udhcp_bound(msg, FALSE);
168                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
169         }
170
171         if (dbus_message_is_method_call(msg, UDHCPC_INTF, "renew") == TRUE) {
172                 udhcp_bound(msg, TRUE);
173                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
174         }
175
176         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
177 }
178
179 static DBusConnection *connection;
180
181 static const char *udhcp_rule = "path=" UDHCPC_PATH ",interface=" UDHCPC_INTF;
182
183 static int udhcp_init(void)
184 {
185         int err;
186
187         connection = connman_dbus_get_connection();
188
189         dbus_connection_add_filter(connection, udhcp_filter, NULL, NULL);
190
191         dbus_bus_add_match(connection, udhcp_rule, NULL);
192
193         err = connman_driver_register(&udhcp_driver);
194         if (err < 0) {
195                 dbus_connection_unref(connection);
196                 return err;
197         }
198
199         return 0;
200 }
201
202 static void udhcp_exit(void)
203 {
204         connman_driver_unregister(&udhcp_driver);
205
206         dbus_bus_remove_match(connection, udhcp_rule, NULL);
207
208         dbus_connection_remove_filter(connection, udhcp_filter, NULL);
209
210         dbus_connection_unref(connection);
211 }
212
213 CONNMAN_PLUGIN_DEFINE(dhclient, "uDHCP client plugin", VERSION,
214                                                 udhcp_init, udhcp_exit)