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
30 #include "client/services.h"
31 #include "src/connman.h"
33 static void append_property_array(DBusMessageIter *iter, char *property,
34 char **data, int num_args)
36 DBusMessageIter value, array;
39 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
41 connman_dbus_array_open(iter, &value);
42 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
43 DBUS_TYPE_STRING_AS_STRING, &array);
45 for (i = 0; i < num_args; i++) {
46 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
48 printf("Added: %s\n", data[i]);
50 dbus_message_iter_close_container(&value, &array);
51 dbus_message_iter_close_container(iter, &value);
54 static void append_property_dict(DBusMessageIter *iter, char *property,
55 char **keys, char **data, int num_args)
57 DBusMessageIter value, dict, entry, dict_key;
61 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
63 /* Top most level is a{sv} */
64 connman_dbus_dict_open_variant(iter, &value);
66 connman_dbus_dict_open(&value, &dict);
68 for (i = 0; i < num_args; i++) {
69 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
71 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
74 if (strcmp(property, "IPv6.Configuration") == 0 &&
75 g_strcmp0(keys[i], "PrefixLength")) {
76 if (data[i] == NULL) {
77 fprintf(stderr, "No values entered!\n");
80 prefix = atoi(data[i]);
82 dbus_message_iter_open_container(&entry,
84 DBUS_TYPE_BYTE_AS_STRING,
86 dbus_message_iter_append_basic(&dict_key,
87 DBUS_TYPE_BYTE, &prefix);
89 dbus_message_iter_open_container(&entry,
91 DBUS_TYPE_STRING_AS_STRING,
93 dbus_message_iter_append_basic(&dict_key,
97 dbus_message_iter_close_container(&entry, &dict_key);
98 dbus_message_iter_close_container(&dict, &entry);
100 /* Close {sv}, then close a{sv} */
101 connman_dbus_dict_close(&value, &dict);
102 connman_dbus_dict_close(iter, &value);
105 void iterate_array(DBusMessageIter *iter)
107 DBusMessageIter array_item;
108 dbus_bool_t key_bool;
111 dbus_message_iter_recurse(iter, &array_item);
112 /* Make sure the entry is not NULL! */
114 while (dbus_message_iter_get_arg_type(&array_item) !=
116 if (dbus_message_iter_get_arg_type(&array_item) ==
118 dbus_message_iter_get_basic(&array_item,
120 printf("%s ", key_str);
121 } else if (dbus_message_iter_get_arg_type(&array_item) ==
123 dbus_message_iter_get_basic(&array_item, &key_bool);
124 printf("%s ", key_bool == TRUE ? "True"
127 dbus_message_iter_next(&array_item);
129 if (dbus_message_iter_get_arg_type(&array_item) ==
134 void iterate_dict(DBusMessageIter *dict, char *string, uint16_t key_int)
136 DBusMessageIter dict_entry, sub_dict_entry;
139 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
140 dbus_message_iter_recurse(dict, &dict_entry);
141 dbus_message_iter_get_basic(&dict_entry, &string);
142 printf("%s=", string);
143 dbus_message_iter_next(&dict_entry);
144 while (dbus_message_iter_get_arg_type(&dict_entry)
145 != DBUS_TYPE_INVALID) {
146 dbus_message_iter_recurse(&dict_entry, &sub_dict_entry);
147 if (dbus_message_iter_get_arg_type(&sub_dict_entry)
148 == DBUS_TYPE_UINT16) {
149 dbus_message_iter_get_basic(&sub_dict_entry,
151 printf("%d ", key_int);
152 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
153 == DBUS_TYPE_STRING) {
154 dbus_message_iter_get_basic(&sub_dict_entry,
156 printf("%s ", string);
157 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
158 == DBUS_TYPE_ARRAY) {
159 iterate_array(&sub_dict_entry);
161 dbus_message_iter_next(&dict_entry);
163 dbus_message_iter_next(dict);
168 /* Get dictionary info about the current service and store it */
169 static void extract_service_properties(DBusMessageIter *dict,
170 struct service_data *service)
172 DBusMessageIter entry, value, array_item;
176 dbus_bool_t key_bool;
178 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
179 dbus_message_iter_recurse(dict, &entry);
180 dbus_message_iter_get_basic(&entry, &key);
181 printf("\n %s = ", key);
182 if (strcmp(key, "Name") == 0 && strlen(key) < 5)
185 dbus_message_iter_next(&entry);
186 dbus_message_iter_recurse(&entry, &value);
187 /* Check if entry is a dictionary itself */
188 if (strcmp(key, "Ethernet") == 0 ||
189 /* if just strcmp, the .Configuration names don't match
190 * and they are iterated with iterate_array instead*/
191 strncmp(key, "IPv4", 4) == 0 ||
192 strncmp(key, "IPv6", 4) == 0 ||
193 strncmp(key, "Proxy", 5) == 0 ||
194 strcmp(key, "Provider") == 0) {
195 dbus_message_iter_recurse(&value, &array_item);
196 iterate_dict(&array_item, key_str, key_uint16);
198 switch (dbus_message_iter_get_arg_type(&value)) {
199 case DBUS_TYPE_ARRAY:
200 iterate_array(&value);
202 case DBUS_TYPE_BOOLEAN:
203 dbus_message_iter_get_basic(&value, &key_bool);
204 printf("%s", key_bool == TRUE ? "True" : "False");
207 dbus_message_iter_get_basic(&value, &key_uint16);
208 printf("%d", key_uint16);
210 case DBUS_TYPE_STRING:
211 dbus_message_iter_get_basic(&value, &key_str);
212 printf("%s", key_str);
215 dbus_message_iter_next(dict);
220 static void match_service_name(DBusMessage *message, char *service_name,
221 struct service_data *service)
223 DBusMessageIter iter, array;
225 dbus_message_iter_init(message, &iter);
226 dbus_message_iter_recurse(&iter, &array);
228 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
229 DBusMessageIter entry, dict;
232 dbus_message_iter_recurse(&array, &entry);
233 dbus_message_iter_get_basic(&entry, &path);
235 service->path = strip_service_path(path);
236 dbus_message_iter_next(&entry);
237 dbus_message_iter_recurse(&entry, &dict);
238 extract_service_name(&dict, service);
239 if (g_strcmp0(service_name, service->name) == 0) {
240 printf(" Matched %s with %s\n\n", service->name,
244 dbus_message_iter_next(&array);
248 void extract_service_name(DBusMessageIter *dict, struct service_data *service)
250 DBusMessageIter dict_entry, value;
254 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
255 dbus_message_iter_recurse(dict, &dict_entry);
256 dbus_message_iter_get_basic(&dict_entry, &key);
257 if (strcmp(key, "Name") == 0) {
258 dbus_message_iter_next(&dict_entry);
259 dbus_message_iter_recurse(&dict_entry, &value);
260 dbus_message_iter_get_basic(&value, &service->name);
262 if (strcmp(key, "AutoConnect") == 0) {
263 dbus_message_iter_next(&dict_entry);
264 dbus_message_iter_recurse(&dict_entry, &value);
265 dbus_message_iter_get_basic(&value, &service->autoconn);
267 if (strcmp(key, "State") == 0) {
268 dbus_message_iter_next(&dict_entry);
269 dbus_message_iter_recurse(&dict_entry, &value);
270 dbus_message_iter_get_basic(&value, &state);
271 if (strcmp(state, "ready") == 0) {
272 service->connected = TRUE;
273 service->online = FALSE;
274 } else if (strcmp(state, "online") == 0) {
275 service->connected = FALSE;
276 service->online = TRUE;
278 service->connected = FALSE;
279 service->online = FALSE;
282 if (strcmp(key, "Favorite") == 0) {
283 dbus_message_iter_next(&dict_entry);
284 dbus_message_iter_recurse(&dict_entry, &value);
285 dbus_message_iter_get_basic(&value, &service->favorite);
287 dbus_message_iter_next(dict);
291 /* Show detailed information about a service */
292 void extract_services(DBusMessage *message, char *service_name)
294 DBusMessageIter iter, array;
296 dbus_message_iter_init(message, &iter);
297 dbus_message_iter_recurse(&iter, &array);
299 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
300 DBusMessageIter entry, dict;
301 struct service_data service;
304 dbus_message_iter_recurse(&array, &entry);
305 dbus_message_iter_get_basic(&entry, &path);
307 service.path = strip_service_path(path);
308 if (g_strcmp0(service.path, service_name) == 0) {
309 printf("[ %s ]\n", service.path);
310 dbus_message_iter_next(&entry);
311 dbus_message_iter_recurse(&entry, &dict);
312 extract_service_properties(&dict, &service);
314 dbus_message_iter_next(&array);
318 /* Support both string names and path names for connecting to services */
319 char *strip_service_path(char *service)
322 service_name = strrchr(service, '/');
323 if (service_name == NULL)
326 return service_name + 1;
329 /* Show a simple list of service names only */
330 void get_services(DBusMessage *message)
332 DBusMessageIter iter, array;
334 dbus_message_iter_init(message, &iter);
335 dbus_message_iter_recurse(&iter, &array);
337 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
338 DBusMessageIter entry, dict;
339 struct service_data service;
342 dbus_message_iter_recurse(&array, &entry);
343 dbus_message_iter_get_basic(&entry, &path);
345 service.path = strip_service_path(path);
346 dbus_message_iter_next(&entry);
347 dbus_message_iter_recurse(&entry, &dict);
348 extract_service_name(&dict, &service);
349 printf("%-1s%-1s%-1s %-20s { %s }\n",
350 service.favorite ? "*" : "",
351 service.autoconn ? "A" : "",
352 service.online ? "O" : (service.connected ? "R" : ""),
353 service.name, service.path);
354 dbus_message_iter_next(&array);
358 const char *find_service(DBusConnection *connection, DBusMessage *message,
359 char *service_name, struct service_data *service)
361 DBusMessageIter iter, array, entry;
364 service_name = strip_service_path(service_name);
365 match_service_name(message, service_name, service);
366 /* Service name did not match, so check if entry is a path */
367 if (g_strcmp0(service_name, service->name)) {
368 dbus_message_iter_init(message, &iter);
369 dbus_message_iter_recurse(&iter, &array);
371 while (dbus_message_iter_get_arg_type(&array) ==
373 dbus_message_iter_recurse(&array, &entry);
374 dbus_message_iter_get_basic(&entry, &path);
376 service->path = strip_service_path(path);
377 if (g_strcmp0(service->path, service_name) == 0)
378 return service->path;
379 dbus_message_iter_next(&array);
381 fprintf(stderr, "'%s' is not a valid service name or path.\n",
383 fprintf(stderr, "Use the 'services' command to find available "
387 return service->path;
390 int set_proxy_manual(DBusConnection *connection, DBusMessage *message,
391 char *name, char **servers, char **excludes,
392 int num_servers, int num_excludes)
394 DBusMessage *message_send;
395 DBusMessageIter iter, value, dict, entry, data;
396 struct service_data service;
398 const char *path_name;
399 char *property = "Proxy.Configuration";
400 char *method = "Method";
401 char *manual = "manual";
403 path_name = find_service(connection, message, name, &service);
404 if (path_name == NULL)
407 path = g_strdup_printf("/net/connman/service/%s", path_name);
408 message_send = dbus_message_new_method_call("net.connman", path,
409 "net.connman.Service",
412 if (message_send == NULL) {
417 dbus_message_iter_init_append(message_send, &iter);
418 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
419 connman_dbus_dict_open_variant(&iter, &value);
420 connman_dbus_dict_open(&value, &dict);
421 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
423 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &method);
424 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
425 DBUS_TYPE_STRING_AS_STRING,
427 dbus_message_iter_append_basic(&data, DBUS_TYPE_STRING, &manual);
428 dbus_message_iter_close_container(&entry, &data);
429 dbus_message_iter_close_container(&dict, &entry);
430 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
432 append_property_array(&entry, "Servers", servers, num_servers);
433 dbus_message_iter_close_container(&dict, &entry);
435 if (num_excludes != 0) {
436 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
438 append_property_array(&entry, "Excludes", excludes,
440 dbus_message_iter_close_container(&dict, &entry);
443 dbus_message_iter_close_container(&value, &dict);
444 dbus_message_iter_close_container(&iter, &value);
445 dbus_connection_send(connection, message_send, NULL);
446 dbus_connection_flush(connection);
447 dbus_message_unref(message_send);
454 int set_service_property(DBusConnection *connection, DBusMessage *message,
455 char *name, char *property, char **keys,
456 void *data, int num_args)
458 DBusMessage *message_send;
459 DBusMessageIter iter;
460 struct service_data service;
462 const char *path_name;
464 path_name = find_service(connection, message, name, &service);
465 if (path_name == NULL)
468 path = g_strdup_printf("/net/connman/service/%s", path_name);
469 message_send = dbus_message_new_method_call("net.connman", path,
470 "net.connman.Service",
473 if (message_send == NULL) {
478 dbus_message_iter_init_append(message_send, &iter);
480 if (strcmp(property, "AutoConnect") == 0)
481 connman_dbus_property_append_basic(&iter,
482 (const char *) property,
483 DBUS_TYPE_BOOLEAN, data);
484 else if ((strcmp(property, "Domains.Configuration") == 0)
485 || (strcmp(property, "Timeservers.Configuration") == 0)
486 || (strcmp(property, "Nameservers.Configuration") == 0))
487 append_property_array(&iter, property, data, num_args);
488 else if ((strcmp(property, "IPv4.Configuration") == 0)
489 || (strcmp(property, "IPv6.Configuration") == 0)
490 || (strcmp(property, "Proxy.Configuration") == 0))
491 append_property_dict(&iter, property, keys, data, num_args);
493 dbus_connection_send(connection, message_send, NULL);
494 dbus_connection_flush(connection);
495 dbus_message_unref(message_send);
501 int remove_service(DBusConnection *connection, DBusMessage *message,
504 struct service_data service;
505 DBusMessage *message_send;
506 const char *path_name;
509 path_name = find_service(connection, message, name, &service);
510 if (path_name == NULL)
513 if (service.favorite == FALSE)
516 path = g_strdup_printf("/net/connman/service/%s", path_name);
517 message_send = dbus_message_new_method_call(CONNMAN_SERVICE, path,
518 CONNMAN_SERVICE_INTERFACE,
520 if (message_send == NULL) {
525 dbus_connection_send(connection, message_send, NULL);
526 dbus_message_unref(message_send);