device: Include Reason in Disconnect Skip Warning
[framework/connectivity/connman.git] / plugins / nmcompat.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 <gdbus.h>
27
28 #define CONNMAN_API_SUBJECT_TO_CHANGE
29 #include <connman/plugin.h>
30 #include <connman/log.h>
31 #include <connman/notifier.h>
32 #include <connman/dbus.h>
33
34 enum {
35         NM_STATE_UNKNOWN = 0,
36         NM_STATE_ASLEEP,
37         NM_STATE_CONNECTING,
38         NM_STATE_CONNECTED,
39         NM_STATE_DISCONNECTED
40 };
41
42 #define NM_SERVICE    "org.freedesktop.NetworkManager"
43 #define NM_PATH       "/org/freedesktop/NetworkManager"
44 #define NM_INTERFACE  NM_SERVICE
45
46 #define DBUS_PROPERTIES_INTERFACE       "org.freedesktop.DBus.Properties"
47
48 static DBusConnection *connection = NULL;
49 static dbus_uint32_t state = NM_STATE_UNKNOWN;
50
51
52 static void nm_send_signal(const char *name, dbus_uint32_t state)
53 {
54         DBusMessage *signal;
55
56         signal = dbus_message_new_signal(NM_PATH, NM_INTERFACE, name);
57         if (signal == NULL)
58                 return;
59
60         dbus_message_append_args(signal, DBUS_TYPE_UINT32, &state,
61                                 DBUS_TYPE_INVALID);
62
63         g_dbus_send_message(connection, signal);
64 }
65
66 static void nm_send_prop_signal(dbus_uint32_t state)
67 {
68         const char *key = "State";
69         DBusMessageIter iter, dict, dict_entry, dict_val;
70         DBusMessage *signal;
71
72         signal = dbus_message_new_signal(NM_PATH, NM_INTERFACE,
73                                                 "PropertiesChanged");
74         if (signal == NULL)
75                 return;
76
77         dbus_message_iter_init_append(signal, &iter);
78
79         dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
80                                         DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
81                                         DBUS_TYPE_STRING_AS_STRING
82                                         DBUS_TYPE_VARIANT_AS_STRING
83                                         DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
84                                         &dict);
85
86         dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
87                         NULL, &dict_entry);
88
89         dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING,
90                                         &key);
91
92         dbus_message_iter_open_container(&dict_entry,
93                                         DBUS_TYPE_VARIANT,
94                                         DBUS_TYPE_UINT32_AS_STRING, &dict_val);
95
96         dbus_message_iter_append_basic(&dict_val, DBUS_TYPE_UINT32, &state);
97
98         dbus_message_iter_close_container(&dict_entry, &dict_val);
99         dbus_message_iter_close_container(&dict, &dict_entry);
100         dbus_message_iter_close_container(&iter, &dict);
101
102         g_dbus_send_message(connection, signal);
103 }
104
105 static void default_changed(struct connman_service *service)
106 {
107         if (service != NULL)
108                 state = NM_STATE_CONNECTED;
109         else
110                 state = NM_STATE_DISCONNECTED;
111
112         DBG("%p %d", service, state);
113
114         /* older deprecated signal, in case applications still use this */
115         nm_send_signal("StateChange", state);
116
117         /* the preferred current signal */
118         nm_send_signal("StateChanged", state);
119
120         nm_send_prop_signal(state);
121 }
122
123 static struct connman_notifier notifier = {
124         .name           = "nmcompat",
125         .priority       = CONNMAN_NOTIFIER_PRIORITY_DEFAULT,
126         .default_changed= default_changed,
127 };
128
129 static DBusMessage *nm_sleep(DBusConnection *conn,
130                                         DBusMessage *msg, void *data)
131 {
132         DBusMessage *reply;
133
134         DBG("conn %p", conn);
135
136         reply = dbus_message_new_method_return(msg);
137         if (reply == NULL)
138                 return NULL;
139
140         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
141
142         return reply;
143 }
144
145 static DBusMessage *nm_wake(DBusConnection *conn,
146                                         DBusMessage *msg, void *data)
147 {
148         DBusMessage *reply;
149
150         DBG("conn %p", conn);
151
152         reply = dbus_message_new_method_return(msg);
153         if (reply == NULL)
154                 return NULL;
155
156         dbus_message_append_args(reply, DBUS_TYPE_INVALID);
157
158         return reply;
159 }
160
161 static DBusMessage *nm_state(DBusConnection *conn,
162                                         DBusMessage *msg, void *data)
163 {
164         DBusMessage *reply;
165
166         DBG("conn %p", conn);
167
168         reply = dbus_message_new_method_return(msg);
169         if (reply == NULL)
170                 return NULL;
171
172         dbus_message_append_args(reply, DBUS_TYPE_UINT32, &state,
173                                                         DBUS_TYPE_INVALID);
174
175         return reply;
176 }
177
178 static GDBusMethodTable nm_methods[] = {
179         { "sleep", "",  "",   nm_sleep        },
180         { "wake",  "",  "",   nm_wake         },
181         { "state", "",  "u",  nm_state        },
182         { },
183 };
184
185 static DBusMessage *nm_prop_get(DBusConnection *conn,
186                                 DBusMessage *msg, void *data)
187 {
188         DBusMessageIter iter, value;
189         const char *interface, *key;
190         DBusMessage *reply;
191
192         DBG("conn %p", conn);
193
194         reply = dbus_message_new_method_return(msg);
195         if (reply == NULL)
196                 return NULL;
197
198         dbus_message_get_args(msg, NULL,
199                                 DBUS_TYPE_STRING, &interface,
200                                 DBUS_TYPE_STRING, &key,
201                                 DBUS_TYPE_INVALID);
202
203         if (g_strcmp0(key, "State") == 0) {
204                 dbus_message_iter_init_append(reply, &iter);
205
206                 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
207                                                 DBUS_TYPE_UINT32_AS_STRING,
208                                                 &value);
209                 dbus_message_iter_append_basic(&value, DBUS_TYPE_UINT32,
210                                                 &state);
211                 dbus_message_iter_close_container(&iter, &value);
212         } else {
213                 dbus_message_unref(reply);
214                 return dbus_message_new_error(msg, DBUS_ERROR_FAILED,
215                                                 "Unsupported property");
216         }
217
218         return reply;
219 }
220
221 static GDBusMethodTable nm_prop_methods[] = {
222         { "Get", "ss",  "v",   nm_prop_get      },
223         { },
224 };
225
226 static int nmcompat_init(void)
227 {
228         gboolean ret;
229
230         DBG("");
231
232         connection = connman_dbus_get_connection();
233         if (connection == NULL)
234                 return -1;
235
236         if (g_dbus_request_name(connection, NM_SERVICE, NULL) == FALSE) {
237                 connman_error("nmcompat: can't register nm service\n");
238                 return -1;
239         }
240
241         if (connman_notifier_register(&notifier) < 0) {
242                 connman_error("nmcompat: failed to register notifier");
243                 return -1;
244         }
245
246         ret = g_dbus_register_interface(connection, NM_PATH, NM_INTERFACE,
247                                         nm_methods, NULL, NULL, NULL, NULL);
248         if (ret == FALSE) {
249                 connman_error("nmcompat: can't register " NM_INTERFACE);
250                 return -1;
251         }
252
253         ret = g_dbus_register_interface(connection, NM_PATH,
254                                         DBUS_PROPERTIES_INTERFACE,
255                                         nm_prop_methods, NULL, NULL,
256                                         NULL, NULL);
257         if (ret == FALSE) {
258                 connman_error("nmcompat: can't register "
259                                 DBUS_PROPERTIES_INTERFACE);
260                 return -1;
261         }
262
263         return 0;
264 }
265
266 static void nmcompat_exit(void)
267 {
268         DBG("");
269
270         connman_notifier_unregister(&notifier);
271
272         if (connection == NULL)
273                 return;
274
275         g_dbus_unregister_interface(connection, NM_PATH, NM_INTERFACE);
276
277         dbus_connection_unref(connection);
278 }
279
280 CONNMAN_PLUGIN_DEFINE(nmcompat, "NetworkManager compatibility interfaces",
281                         VERSION, CONNMAN_PLUGIN_PRIORITY_DEFAULT,
282                         nmcompat_init, nmcompat_exit)