Add method, domainname and nameserver to proxy configuration
[framework/connectivity/connman.git] / plugins / pacrunner.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 <errno.h>
27
28 #include <gdbus.h>
29
30 #define CONNMAN_API_SUBJECT_TO_CHANGE
31 #include <connman/plugin.h>
32 #include <connman/notifier.h>
33 #include <connman/dbus.h>
34 #include <connman/log.h>
35
36 #define PACRUNNER_SERVICE       "org.pacrunner"
37 #define PACRUNNER_INTERFACE     "org.pacrunner.Manager"
38 #define PACRUNNER_PATH          "/org/pacrunner/manager"
39
40 #define DBUS_TIMEOUT    5000
41
42 static DBusConnection *connection;
43 static dbus_bool_t daemon_running = FALSE;
44
45 static struct connman_service *default_service = NULL;
46 static char *current_config = NULL;
47
48 static void create_config_reply(DBusPendingCall *call, void *user_data)
49 {
50         DBusMessage *reply = dbus_pending_call_steal_reply(call);
51         const char *path;
52
53         DBG("");
54
55         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) {
56                 connman_error("Failed to create proxy configuration");
57                 goto done;
58         }
59
60         if (dbus_message_get_args(reply, NULL, DBUS_TYPE_OBJECT_PATH, &path,
61                                                 DBUS_TYPE_INVALID) == FALSE)
62                 goto done;
63
64         g_free(current_config);
65         current_config = g_strdup(path);
66
67 done:
68         dbus_message_unref(reply);
69 }
70
71 static void append_string(DBusMessageIter *iter, void *user_data)
72 {
73         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, user_data);
74 }
75
76 static void create_proxy_configuration(void)
77 {
78         DBusMessage *msg;
79         DBusMessageIter iter, dict;
80         DBusPendingCall *call;
81         dbus_bool_t result;
82         char *interface;
83         const char *str;
84
85         if (default_service == NULL)
86                 return;
87
88         DBG("");
89
90         msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH,
91                         PACRUNNER_INTERFACE, "CreateProxyConfiguration");
92         if (msg == NULL)
93                 return;
94
95         dbus_message_set_auto_start(msg, FALSE);
96
97         dbus_message_iter_init_append(msg, &iter);
98         connman_dbus_dict_open(&iter, &dict);
99
100         interface = connman_service_get_interface(default_service);
101         if (interface != NULL) {
102                 connman_dbus_dict_append_basic(&dict, "Interface",
103                                                 DBUS_TYPE_STRING, &interface);
104                 g_free(interface);
105         }
106
107         str = connman_service_get_proxy_autoconfig(default_service);
108         if (str != NULL) {
109                 const char *method = "auto";
110                 connman_dbus_dict_append_basic(&dict, "Method",
111                                                 DBUS_TYPE_STRING, &method);
112                 connman_dbus_dict_append_basic(&dict, "URL",
113                                                 DBUS_TYPE_STRING, &str);
114         } else {
115                 const char *method = "direct";
116                 connman_dbus_dict_append_basic(&dict, "Method",
117                                                 DBUS_TYPE_STRING, &method);
118         }
119
120         str = connman_service_get_domainname(default_service);
121         if (str != NULL)
122                 connman_dbus_dict_append_array(&dict, "Domains",
123                                         DBUS_TYPE_STRING, append_string, &str);
124
125         str = connman_service_get_nameserver(default_service);
126         if (str != NULL)
127                 connman_dbus_dict_append_array(&dict, "Nameservers",
128                                         DBUS_TYPE_STRING, append_string, &str);
129
130         connman_dbus_dict_close(&iter, &dict);
131
132         result = dbus_connection_send_with_reply(connection, msg,
133                                                         &call, DBUS_TIMEOUT);
134
135         dbus_message_unref(msg);
136
137         if (result == FALSE || call == NULL)
138                 return;
139
140         dbus_pending_call_set_notify(call, create_config_reply, NULL, NULL);
141
142         dbus_pending_call_unref(call);
143 }
144
145 static void destroy_config_reply(DBusPendingCall *call, void *user_data)
146 {
147         DBusMessage *reply = dbus_pending_call_steal_reply(call);
148
149         DBG("");
150
151         if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
152                 connman_error("Failed to destoy proxy configuration");
153
154         dbus_message_unref(reply);
155 }
156
157 static void destroy_proxy_configuration(void)
158 {
159         DBusMessage *msg;
160         DBusPendingCall *call;
161         dbus_bool_t result;
162
163         if (current_config == NULL)
164                 return;
165
166         DBG("");
167
168         msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_PATH,
169                         PACRUNNER_INTERFACE, "DestroyProxyConfiguration");
170         if (msg == NULL)
171                 return;
172
173         dbus_message_set_auto_start(msg, FALSE);
174
175         dbus_message_append_args(msg, DBUS_TYPE_OBJECT_PATH, &current_config,
176                                                         DBUS_TYPE_INVALID);
177
178         result = dbus_connection_send_with_reply(connection, msg,
179                                                         &call, DBUS_TIMEOUT);
180
181         dbus_message_unref(msg);
182
183         if (result == FALSE || call == NULL)
184                 return;
185
186         dbus_pending_call_set_notify(call, destroy_config_reply, NULL, NULL);
187
188         dbus_pending_call_unref(call);
189
190         g_free(current_config);
191         current_config = NULL;
192 }
193
194 static void default_service_changed(struct connman_service *service)
195 {
196         DBG("service %p", service);
197
198         if (service == default_service)
199                 return;
200
201         default_service = service;
202
203         if (daemon_running == FALSE)
204                 return;
205
206         destroy_proxy_configuration();
207
208         create_proxy_configuration();
209 }
210
211 static struct connman_notifier pacrunner_notifier = {
212         .name                   = "pacrunner",
213         .default_changed        = default_service_changed,
214 };
215
216 static void pacrunner_connect(DBusConnection *conn, void *user_data)
217 {
218         DBG("");
219
220         daemon_running = TRUE;
221
222         create_proxy_configuration();
223 }
224
225 static void pacrunner_disconnect(DBusConnection *conn, void *user_data)
226 {
227         DBG("");
228
229         daemon_running = FALSE;
230
231         g_free(current_config);
232         current_config = NULL;
233 }
234
235 static guint pacrunner_watch;
236
237 static int pacrunner_init(void)
238 {
239         connection = connman_dbus_get_connection();
240         if (connection == NULL)
241                 return -EIO;
242
243         pacrunner_watch = g_dbus_add_service_watch(connection,
244                                         PACRUNNER_SERVICE, pacrunner_connect,
245                                         pacrunner_disconnect, NULL, NULL);
246         if (pacrunner_watch == 0) {
247                 dbus_connection_unref(connection);
248                 return -EIO;
249         }
250
251         connman_notifier_register(&pacrunner_notifier);
252
253         return 0;
254 }
255
256 static void pacrunner_exit(void)
257 {
258         connman_notifier_unregister(&pacrunner_notifier);
259
260         g_dbus_remove_watch(connection, pacrunner_watch);
261
262         destroy_proxy_configuration();
263
264         dbus_connection_unref(connection);
265 }
266
267 CONNMAN_PLUGIN_DEFINE(pacrunner, "PAC runner proxy plugin", VERSION,
268                 CONNMAN_PLUGIN_PRIORITY_DEFAULT, pacrunner_init, pacrunner_exit)