5 * Copyright (C) 2012 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "client/services.h"
35 #include "src/connman.h"
38 static void append_property_array(DBusMessageIter *iter, char *property,
39 char **data, int num_args)
41 DBusMessageIter value, array;
44 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
46 connman_dbus_array_open(iter, &value);
47 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
48 DBUS_TYPE_STRING_AS_STRING, &array);
50 for (i = 0; i < num_args; i++) {
51 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
53 printf("Added: %s\n", data[i]);
55 dbus_message_iter_close_container(&value, &array);
56 dbus_message_iter_close_container(iter, &value);
59 static void append_property_dict(DBusMessageIter *iter, char *property,
60 char **keys, char **data, int num_args)
62 DBusMessageIter value, dict, entry, dict_key;
66 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
68 /* Top most level is a{sv} */
69 connman_dbus_dict_open_variant(iter, &value);
71 connman_dbus_dict_open(&value, &dict);
73 for (i = 0; i < num_args; i++) {
74 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
76 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
79 if (strcmp(property, "IPv6.Configuration") == 0 &&
80 g_strcmp0(keys[i], "PrefixLength")) {
81 if (data[i] == NULL) {
82 fprintf(stderr, "No values entered!\n");
85 prefix = atoi(data[i]);
87 dbus_message_iter_open_container(&entry,
89 DBUS_TYPE_BYTE_AS_STRING,
91 dbus_message_iter_append_basic(&dict_key,
92 DBUS_TYPE_BYTE, &prefix);
94 dbus_message_iter_open_container(&entry,
96 DBUS_TYPE_STRING_AS_STRING,
98 dbus_message_iter_append_basic(&dict_key,
102 dbus_message_iter_close_container(&entry, &dict_key);
103 dbus_message_iter_close_container(&dict, &entry);
105 /* Close {sv}, then close a{sv} */
106 connman_dbus_dict_close(&value, &dict);
107 connman_dbus_dict_close(iter, &value);
110 void iterate_array(DBusMessageIter *iter)
112 DBusMessageIter array_item;
113 dbus_bool_t key_bool;
116 dbus_message_iter_recurse(iter, &array_item);
117 /* Make sure the entry is not NULL! */
119 while (dbus_message_iter_get_arg_type(&array_item) !=
121 if (dbus_message_iter_get_arg_type(&array_item) ==
123 dbus_message_iter_get_basic(&array_item,
125 printf("%s ", key_str);
126 } else if (dbus_message_iter_get_arg_type(&array_item) ==
128 dbus_message_iter_get_basic(&array_item, &key_bool);
129 printf("%s ", key_bool == TRUE ? "True"
132 dbus_message_iter_next(&array_item);
134 if (dbus_message_iter_get_arg_type(&array_item) ==
139 void iterate_dict(DBusMessageIter *dict, char *string, uint16_t key_int)
141 DBusMessageIter dict_entry, sub_dict_entry;
144 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
145 dbus_message_iter_recurse(dict, &dict_entry);
146 dbus_message_iter_get_basic(&dict_entry, &string);
147 printf("%s=", string);
148 dbus_message_iter_next(&dict_entry);
149 while (dbus_message_iter_get_arg_type(&dict_entry)
150 != DBUS_TYPE_INVALID) {
151 dbus_message_iter_recurse(&dict_entry, &sub_dict_entry);
152 if (dbus_message_iter_get_arg_type(&sub_dict_entry)
153 == DBUS_TYPE_UINT16) {
154 dbus_message_iter_get_basic(&sub_dict_entry,
156 printf("%d ", key_int);
157 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
158 == DBUS_TYPE_STRING) {
159 dbus_message_iter_get_basic(&sub_dict_entry,
161 printf("%s ", string);
162 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
163 == DBUS_TYPE_ARRAY) {
164 iterate_array(&sub_dict_entry);
166 dbus_message_iter_next(&dict_entry);
168 dbus_message_iter_next(dict);
173 /* Get dictionary info about the current service and store it */
174 static void extract_service_properties(DBusMessageIter *dict,
175 struct service_data *service)
177 DBusMessageIter entry, value, array_item;
181 dbus_bool_t key_bool;
183 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
184 dbus_message_iter_recurse(dict, &entry);
185 dbus_message_iter_get_basic(&entry, &key);
186 printf("\n %s = ", key);
187 if (strcmp(key, "Name") == 0 && strlen(key) < 5)
190 dbus_message_iter_next(&entry);
191 dbus_message_iter_recurse(&entry, &value);
192 /* Check if entry is a dictionary itself */
193 if (strcmp(key, "Ethernet") == 0 ||
194 /* if just strcmp, the .Configuration names don't match
195 * and they are iterated with iterate_array instead*/
196 strncmp(key, "IPv4", 4) == 0 ||
197 strncmp(key, "IPv6", 4) == 0 ||
198 strncmp(key, "Proxy", 5) == 0 ||
199 strcmp(key, "Provider") == 0) {
200 dbus_message_iter_recurse(&value, &array_item);
201 iterate_dict(&array_item, key_str, key_uint16);
203 switch (dbus_message_iter_get_arg_type(&value)) {
204 case DBUS_TYPE_ARRAY:
205 iterate_array(&value);
207 case DBUS_TYPE_BOOLEAN:
208 dbus_message_iter_get_basic(&value, &key_bool);
209 printf("%s", key_bool == TRUE ? "True" : "False");
212 dbus_message_iter_get_basic(&value, &key_uint16);
213 printf("%d", key_uint16);
215 case DBUS_TYPE_STRING:
216 dbus_message_iter_get_basic(&value, &key_str);
217 printf("%s", key_str);
220 dbus_message_iter_next(dict);
225 static void match_service_name(DBusMessage *message, char *service_name,
226 struct service_data *service)
228 DBusMessageIter iter, array;
230 dbus_message_iter_init(message, &iter);
231 dbus_message_iter_recurse(&iter, &array);
233 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
234 DBusMessageIter entry, dict;
237 dbus_message_iter_recurse(&array, &entry);
238 dbus_message_iter_get_basic(&entry, &path);
240 service->path = strip_service_path(path);
241 dbus_message_iter_next(&entry);
242 dbus_message_iter_recurse(&entry, &dict);
243 extract_service_name(&dict, service);
244 if (g_strcmp0(service_name, service->name) == 0) {
245 printf(" Matched %s with %s\n\n", service->name,
249 dbus_message_iter_next(&array);
253 void extract_service_name(DBusMessageIter *dict, struct service_data *service)
255 DBusMessageIter dict_entry, value;
259 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
260 dbus_message_iter_recurse(dict, &dict_entry);
261 dbus_message_iter_get_basic(&dict_entry, &key);
262 if (strcmp(key, "Name") == 0) {
263 dbus_message_iter_next(&dict_entry);
264 dbus_message_iter_recurse(&dict_entry, &value);
265 dbus_message_iter_get_basic(&value, &service->name);
267 if (strcmp(key, "AutoConnect") == 0) {
268 dbus_message_iter_next(&dict_entry);
269 dbus_message_iter_recurse(&dict_entry, &value);
270 dbus_message_iter_get_basic(&value, &service->autoconn);
272 if (strcmp(key, "State") == 0) {
273 dbus_message_iter_next(&dict_entry);
274 dbus_message_iter_recurse(&dict_entry, &value);
275 dbus_message_iter_get_basic(&value, &state);
276 if (strcmp(state, "ready") == 0) {
277 service->connected = TRUE;
278 service->online = FALSE;
279 } else if (strcmp(state, "online") == 0) {
280 service->connected = FALSE;
281 service->online = TRUE;
283 service->connected = FALSE;
284 service->online = FALSE;
287 if (strcmp(key, "Favorite") == 0) {
288 dbus_message_iter_next(&dict_entry);
289 dbus_message_iter_recurse(&dict_entry, &value);
290 dbus_message_iter_get_basic(&value, &service->favorite);
292 dbus_message_iter_next(dict);
296 /* Show detailed information about a service */
297 void extract_services(DBusMessage *message, char *service_name)
299 DBusMessageIter iter, array;
301 dbus_message_iter_init(message, &iter);
302 dbus_message_iter_recurse(&iter, &array);
304 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
305 DBusMessageIter entry, dict;
306 struct service_data service;
309 dbus_message_iter_recurse(&array, &entry);
310 dbus_message_iter_get_basic(&entry, &path);
312 service.path = strip_service_path(path);
313 if (g_strcmp0(service.path, service_name) == 0) {
314 printf("[ %s ]\n", service.path);
315 dbus_message_iter_next(&entry);
316 dbus_message_iter_recurse(&entry, &dict);
317 extract_service_properties(&dict, &service);
319 dbus_message_iter_next(&array);
323 /* Support both string names and path names for connecting to services */
324 char *strip_service_path(char *service)
327 service_name = strrchr(service, '/');
328 if (service_name == NULL)
331 return service_name + 1;
334 /* Show a simple list of service names only */
335 void get_services(DBusMessage *message)
337 DBusMessageIter iter, array;
339 dbus_message_iter_init(message, &iter);
340 dbus_message_iter_recurse(&iter, &array);
342 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
343 DBusMessageIter entry, dict;
344 struct service_data service;
347 dbus_message_iter_recurse(&array, &entry);
348 dbus_message_iter_get_basic(&entry, &path);
350 service.path = strip_service_path(path);
351 dbus_message_iter_next(&entry);
352 dbus_message_iter_recurse(&entry, &dict);
353 extract_service_name(&dict, &service);
354 printf("%-1s%-1s%-1s %-20s { %s }\n",
355 service.favorite ? "*" : "",
356 service.autoconn ? "A" : "",
357 service.online ? "O" : (service.connected ? "R" : ""),
358 service.name, service.path);
359 dbus_message_iter_next(&array);
363 const char *find_service(DBusConnection *connection, DBusMessage *message,
364 char *service_name, struct service_data *service)
366 DBusMessageIter iter, array, entry;
369 service_name = strip_service_path(service_name);
370 match_service_name(message, service_name, service);
371 /* Service name did not match, so check if entry is a path */
372 if (g_strcmp0(service_name, service->name)) {
373 dbus_message_iter_init(message, &iter);
374 dbus_message_iter_recurse(&iter, &array);
376 while (dbus_message_iter_get_arg_type(&array) ==
378 dbus_message_iter_recurse(&array, &entry);
379 dbus_message_iter_get_basic(&entry, &path);
381 service->path = strip_service_path(path);
382 if (g_strcmp0(service->path, service_name) == 0)
383 return service->path;
384 dbus_message_iter_next(&array);
386 fprintf(stderr, "'%s' is not a valid service name or path.\n",
388 fprintf(stderr, "Use the 'services' command to find available "
392 return service->path;
395 int set_proxy_manual(DBusConnection *connection, DBusMessage *message,
396 char *name, char **servers, char **excludes,
397 int num_servers, int num_excludes)
399 DBusMessage *message_send;
400 DBusMessageIter iter, value, dict, entry, data;
401 struct service_data service;
403 const char *path_name;
404 char *property = "Proxy.Configuration";
405 char *method = "Method";
406 char *manual = "manual";
408 path_name = find_service(connection, message, name, &service);
409 if (path_name == NULL)
412 path = g_strdup_printf("/net/connman/service/%s", path_name);
413 message_send = dbus_message_new_method_call("net.connman", path,
414 "net.connman.Service",
417 if (message_send == NULL) {
422 dbus_message_iter_init_append(message_send, &iter);
423 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
424 connman_dbus_dict_open_variant(&iter, &value);
425 connman_dbus_dict_open(&value, &dict);
426 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
428 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &method);
429 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
430 DBUS_TYPE_STRING_AS_STRING,
432 dbus_message_iter_append_basic(&data, DBUS_TYPE_STRING, &manual);
433 dbus_message_iter_close_container(&entry, &data);
434 dbus_message_iter_close_container(&dict, &entry);
435 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
437 append_property_array(&entry, "Servers", servers, num_servers);
438 dbus_message_iter_close_container(&dict, &entry);
440 if (num_excludes != 0) {
441 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
443 append_property_array(&entry, "Excludes", excludes,
445 dbus_message_iter_close_container(&dict, &entry);
448 dbus_message_iter_close_container(&value, &dict);
449 dbus_message_iter_close_container(&iter, &value);
450 dbus_connection_send(connection, message_send, NULL);
451 dbus_connection_flush(connection);
452 dbus_message_unref(message_send);
459 int set_service_property(DBusConnection *connection, DBusMessage *message,
460 char *name, char *property, char **keys,
461 void *data, int num_args)
463 DBusMessage *message_send;
464 DBusMessageIter iter;
465 struct service_data service;
467 const char *path_name;
469 path_name = find_service(connection, message, name, &service);
470 if (path_name == NULL)
473 path = g_strdup_printf("/net/connman/service/%s", path_name);
474 message_send = dbus_message_new_method_call("net.connman", path,
475 "net.connman.Service",
478 if (message_send == NULL) {
483 dbus_message_iter_init_append(message_send, &iter);
485 if (strcmp(property, "AutoConnect") == 0)
486 dbus_property_append_basic(&iter, (const char *) property,
487 DBUS_TYPE_BOOLEAN, data);
488 else if ((strcmp(property, "Domains.Configuration") == 0)
489 || (strcmp(property, "Timeservers.Configuration") == 0)
490 || (strcmp(property, "Nameservers.Configuration") == 0))
491 append_property_array(&iter, property, data, num_args);
492 else if ((strcmp(property, "IPv4.Configuration") == 0)
493 || (strcmp(property, "IPv6.Configuration") == 0)
494 || (strcmp(property, "Proxy.Configuration") == 0))
495 append_property_dict(&iter, property, keys, data, num_args);
497 dbus_connection_send(connection, message_send, NULL);
498 dbus_connection_flush(connection);
499 dbus_message_unref(message_send);
505 int remove_service(DBusConnection *connection, DBusMessage *message,
508 struct service_data service;
509 DBusMessage *message_send;
510 const char *path_name;
513 path_name = find_service(connection, message, name, &service);
514 if (path_name == NULL)
517 if (service.favorite == FALSE)
520 path = g_strdup_printf("/net/connman/service/%s", path_name);
521 message_send = dbus_message_new_method_call(CONNMAN_SERVICE, path,
522 CONNMAN_SERVICE_INTERFACE,
524 if (message_send == NULL) {
529 dbus_connection_send(connection, message_send, NULL);
530 dbus_message_unref(message_send);