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