5 * Copyright (C) 2012-2013 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
39 int parse_boolean(char *arg)
44 if (strcasecmp(arg, "no") == 0 ||
45 strcasecmp(arg, "false") == 0 ||
46 strcasecmp(arg, "off" ) == 0 ||
47 strcasecmp(arg, "disable" ) == 0 ||
48 strcasecmp(arg, "n") == 0 ||
49 strcasecmp(arg, "f") == 0 ||
50 strcasecmp(arg, "0") == 0)
53 if (strcasecmp(arg, "yes") == 0 ||
54 strcasecmp(arg, "true") == 0 ||
55 strcasecmp(arg, "on") == 0 ||
56 strcasecmp(arg, "enable" ) == 0 ||
57 strcasecmp(arg, "y") == 0 ||
58 strcasecmp(arg, "t") == 0 ||
59 strcasecmp(arg, "1") == 0)
65 static void print_service(char *path, DBusMessageIter *iter)
67 char *name = "", *str = NULL;
68 int autoconn = 0, favorite = 0, count = 0;
71 DBusMessageIter entry, val;
73 while (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
75 dbus_message_iter_recurse(iter, &entry);
76 dbus_message_iter_get_basic(&entry, &property);
77 if (strcmp(property, "Name") == 0) {
78 dbus_message_iter_next(&entry);
79 dbus_message_iter_recurse(&entry, &val);
80 dbus_message_iter_get_basic(&val, &name);
82 } else if (strcmp(property, "State") == 0) {
83 dbus_message_iter_next(&entry);
84 dbus_message_iter_recurse(&entry, &val);
85 dbus_message_iter_get_basic(&val, &str);
88 if (strcmp(str, "online") == 0)
90 else if (strcmp(str, "ready") == 0)
94 } else if (strcmp(property, "AutoConnect") == 0) {
95 dbus_message_iter_next(&entry);
96 dbus_message_iter_recurse(&entry, &val);
97 dbus_message_iter_get_basic(&val, &autoconn);
99 } else if (strcmp(property, "Favorite") == 0) {
100 dbus_message_iter_next(&entry);
101 dbus_message_iter_recurse(&entry, &val);
102 dbus_message_iter_get_basic(&val, &favorite);
106 dbus_message_iter_next(iter);
109 str = strrchr(path, '/');
119 fprintf(stdout, "%c%c%c %-20s %s", favorite != 0 ? '*' : ' ',
120 autoconn != 0 ? 'A' : ' ', state, name, str);
122 fprintf(stdout, "%-24s %s", "unchanged", str);
126 static void list_service_array(DBusMessageIter *iter)
128 DBusMessageIter array, dict;
131 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
133 dbus_message_iter_recurse(iter, &array);
134 if (dbus_message_iter_get_arg_type(&array)
135 != DBUS_TYPE_OBJECT_PATH)
138 dbus_message_iter_get_basic(&array, &path);
140 dbus_message_iter_next(&array);
141 if (dbus_message_iter_get_arg_type(&array)
142 == DBUS_TYPE_ARRAY) {
143 dbus_message_iter_recurse(&array, &dict);
144 print_service(path, &dict);
147 if (dbus_message_iter_has_next(iter) == TRUE)
148 fprintf(stdout, "\n");
150 dbus_message_iter_next(iter);
154 void __connmanctl_services_list(DBusMessageIter *iter)
156 DBusMessageIter array;
159 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
162 dbus_message_iter_recurse(iter, &array);
163 list_service_array(&array);
165 dbus_message_iter_next(iter);
166 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
169 fprintf(stdout, "\n}, {");
171 dbus_message_iter_recurse(iter, &array);
172 while (dbus_message_iter_get_arg_type(&array)
173 == DBUS_TYPE_OBJECT_PATH) {
174 dbus_message_iter_get_basic(&array, &path);
175 fprintf(stdout, "\n%-24s %s", "removed", path);
177 dbus_message_iter_next(&array);
183 static int append_property_array(DBusMessageIter *iter, char *property,
184 char **data, int num_args)
186 DBusMessageIter value, array;
189 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
191 dbus_array_open(iter, &value);
192 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
193 DBUS_TYPE_STRING_AS_STRING, &array);
195 while (data[i] != NULL && strncmp(data[i], "--", 2) != 0) {
196 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
198 if (num_args > 0 && i == num_args)
203 dbus_message_iter_close_container(&value, &array);
204 dbus_message_iter_close_container(iter, &value);
209 static int append_property_dict(DBusMessageIter *iter, char *property,
210 char **keys, char **data, int num_args)
213 DBusMessageIter value, dict, entry, dict_key;
215 unsigned char prefix;
216 char *property_value;
218 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
220 /* Top most level is a{sv} */
221 dbus_dict_open_variant(iter, &value);
223 dbus_dict_open(&value, &dict);
225 if (strcmp(property, "IPv6.Configuration") == 0)
228 while (keys[i] != NULL && data[i] != NULL
229 && strncmp(data[i], "--", 2) != 0) {
231 if (num_args > 0 && i == num_args)
234 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
236 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
239 property_value = data[i];
241 if (is_ipv6 == 1 && g_strcmp0(keys[i], "PrefixLength") == 0) {
242 prefix = atoi(data[i]);
244 dbus_message_iter_open_container(&entry,
246 DBUS_TYPE_BYTE_AS_STRING,
248 dbus_message_iter_append_basic(&dict_key,
249 DBUS_TYPE_BYTE, &prefix);
251 if (is_ipv6 == 1 && strcmp(keys[i], "Privacy") == 0) {
252 switch (parse_boolean(property_value)) {
254 property_value = "disabled";
257 property_value = "enabled";
260 if (strcmp(property_value,
267 dbus_message_iter_open_container(&entry,
269 DBUS_TYPE_STRING_AS_STRING,
271 dbus_message_iter_append_basic(&dict_key,
276 dbus_message_iter_close_container(&entry, &dict_key);
277 dbus_message_iter_close_container(&dict, &entry);
281 /* Close {sv}, then close a{sv} */
282 dbus_dict_close(&value, &dict);
283 dbus_dict_close(iter, &value);
288 void iterate_array(DBusMessageIter *iter)
290 DBusMessageIter array_item;
291 dbus_bool_t key_bool;
294 dbus_message_iter_recurse(iter, &array_item);
295 /* Make sure the entry is not NULL! */
297 while (dbus_message_iter_get_arg_type(&array_item) !=
299 if (dbus_message_iter_get_arg_type(&array_item) ==
301 dbus_message_iter_get_basic(&array_item,
303 printf("%s ", key_str);
304 } else if (dbus_message_iter_get_arg_type(&array_item) ==
306 dbus_message_iter_get_basic(&array_item, &key_bool);
307 printf("%s ", key_bool == TRUE ? "True"
310 dbus_message_iter_next(&array_item);
312 if (dbus_message_iter_get_arg_type(&array_item) ==
317 void iterate_dict(DBusMessageIter *dict, char *string, uint16_t key_int)
319 DBusMessageIter dict_entry, sub_dict_entry;
322 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
323 dbus_message_iter_recurse(dict, &dict_entry);
324 dbus_message_iter_get_basic(&dict_entry, &string);
325 printf("%s=", string);
326 dbus_message_iter_next(&dict_entry);
327 while (dbus_message_iter_get_arg_type(&dict_entry)
328 != DBUS_TYPE_INVALID) {
329 dbus_message_iter_recurse(&dict_entry, &sub_dict_entry);
330 if (dbus_message_iter_get_arg_type(&sub_dict_entry)
331 == DBUS_TYPE_UINT16) {
332 dbus_message_iter_get_basic(&sub_dict_entry,
334 printf("%d ", key_int);
335 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
336 == DBUS_TYPE_STRING) {
337 dbus_message_iter_get_basic(&sub_dict_entry,
339 printf("%s ", string);
340 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
341 == DBUS_TYPE_ARRAY) {
342 iterate_array(&sub_dict_entry);
344 dbus_message_iter_next(&dict_entry);
346 dbus_message_iter_next(dict);
351 /* Get dictionary info about the current service and store it */
352 static void extract_service_properties(DBusMessageIter *dict,
353 struct service_data *service)
355 DBusMessageIter entry, value, array_item;
359 dbus_bool_t key_bool;
361 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
362 dbus_message_iter_recurse(dict, &entry);
363 dbus_message_iter_get_basic(&entry, &key);
364 printf("\n %s = ", key);
365 if (strcmp(key, "Name") == 0 && strlen(key) < 5)
368 dbus_message_iter_next(&entry);
369 dbus_message_iter_recurse(&entry, &value);
370 /* Check if entry is a dictionary itself */
371 if (strcmp(key, "Ethernet") == 0 ||
372 /* if just strcmp, the .Configuration names don't match
373 * and they are iterated with iterate_array instead*/
374 strncmp(key, "IPv4", 4) == 0 ||
375 strncmp(key, "IPv6", 4) == 0 ||
376 strncmp(key, "Proxy", 5) == 0 ||
377 strcmp(key, "Provider") == 0) {
378 dbus_message_iter_recurse(&value, &array_item);
379 iterate_dict(&array_item, key_str, key_uint16);
381 switch (dbus_message_iter_get_arg_type(&value)) {
382 case DBUS_TYPE_ARRAY:
383 iterate_array(&value);
385 case DBUS_TYPE_BOOLEAN:
386 dbus_message_iter_get_basic(&value, &key_bool);
387 printf("%s", key_bool == TRUE ? "True" : "False");
390 dbus_message_iter_get_basic(&value, &key_uint16);
391 printf("%d", key_uint16);
393 case DBUS_TYPE_STRING:
394 dbus_message_iter_get_basic(&value, &key_str);
395 printf("%s", key_str);
398 dbus_message_iter_next(dict);
403 void extract_service_name(DBusMessageIter *dict, struct service_data *service)
405 DBusMessageIter dict_entry, value;
409 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
410 dbus_message_iter_recurse(dict, &dict_entry);
411 dbus_message_iter_get_basic(&dict_entry, &key);
412 if (strcmp(key, "Name") == 0) {
413 dbus_message_iter_next(&dict_entry);
414 dbus_message_iter_recurse(&dict_entry, &value);
415 dbus_message_iter_get_basic(&value, &service->name);
417 if (strcmp(key, "AutoConnect") == 0) {
418 dbus_message_iter_next(&dict_entry);
419 dbus_message_iter_recurse(&dict_entry, &value);
420 dbus_message_iter_get_basic(&value, &service->autoconn);
422 if (strcmp(key, "State") == 0) {
423 dbus_message_iter_next(&dict_entry);
424 dbus_message_iter_recurse(&dict_entry, &value);
425 dbus_message_iter_get_basic(&value, &state);
426 if (strcmp(state, "ready") == 0) {
427 service->connected = TRUE;
428 service->online = FALSE;
429 } else if (strcmp(state, "online") == 0) {
430 service->connected = FALSE;
431 service->online = TRUE;
433 service->connected = FALSE;
434 service->online = FALSE;
437 if (strcmp(key, "Favorite") == 0) {
438 dbus_message_iter_next(&dict_entry);
439 dbus_message_iter_recurse(&dict_entry, &value);
440 dbus_message_iter_get_basic(&value, &service->favorite);
442 dbus_message_iter_next(dict);
446 /* Show detailed information about a service */
447 void extract_services(DBusMessage *message, char *service_name)
449 DBusMessageIter iter, array;
451 dbus_message_iter_init(message, &iter);
452 dbus_message_iter_recurse(&iter, &array);
454 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
455 DBusMessageIter entry, dict;
456 struct service_data service;
459 dbus_message_iter_recurse(&array, &entry);
460 dbus_message_iter_get_basic(&entry, &path);
462 service.path = strip_service_path(path);
463 if (g_strcmp0(service.path, service_name) == 0) {
464 printf("[ %s ]\n", service.path);
465 dbus_message_iter_next(&entry);
466 dbus_message_iter_recurse(&entry, &dict);
467 extract_service_properties(&dict, &service);
469 dbus_message_iter_next(&array);
473 /* Support both string names and path names for connecting to services */
474 char *strip_service_path(char *service)
477 service_name = strrchr(service, '/');
478 if (service_name == NULL)
481 return service_name + 1;
484 /* Show a simple list of service names only */
485 void get_services(DBusMessage *message)
487 DBusMessageIter iter, array;
489 dbus_message_iter_init(message, &iter);
490 dbus_message_iter_recurse(&iter, &array);
492 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
493 DBusMessageIter entry, dict;
494 struct service_data service;
497 dbus_message_iter_recurse(&array, &entry);
498 dbus_message_iter_get_basic(&entry, &path);
500 service.path = strip_service_path(path);
501 dbus_message_iter_next(&entry);
502 dbus_message_iter_recurse(&entry, &dict);
503 extract_service_name(&dict, &service);
504 printf("%-1s%-1s%-1s %-20s { %s }\n",
505 service.favorite ? "*" : "",
506 service.autoconn ? "A" : "",
507 service.online ? "O" : (service.connected ? "R" : ""),
508 service.name, service.path);
509 dbus_message_iter_next(&array);
513 int set_proxy_manual(DBusConnection *connection, DBusMessage *message,
514 char *name, char **servers, char **excludes,
515 int num_servers, int num_excludes)
517 DBusMessage *message_send;
518 DBusMessageIter iter, value, dict, entry, data;
520 const char *path_name;
521 char *property = "Proxy.Configuration";
522 char *method = "Method";
523 char *manual = "manual";
524 DBusError dbus_error;
526 path_name = strip_service_path(name);
527 if (path_name == NULL)
530 path = g_strdup_printf("/net/connman/service/%s", path_name);
531 message_send = dbus_message_new_method_call("net.connman", path,
532 "net.connman.Service",
535 if (message_send == NULL) {
540 dbus_message_iter_init_append(message_send, &iter);
541 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
542 dbus_dict_open_variant(&iter, &value);
543 dbus_dict_open(&value, &dict);
544 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
546 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &method);
547 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
548 DBUS_TYPE_STRING_AS_STRING,
550 dbus_message_iter_append_basic(&data, DBUS_TYPE_STRING, &manual);
551 dbus_message_iter_close_container(&entry, &data);
552 dbus_message_iter_close_container(&dict, &entry);
553 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
555 append_property_array(&entry, "Servers", servers, num_servers -1);
556 dbus_message_iter_close_container(&dict, &entry);
558 if (num_excludes != 0) {
559 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
561 append_property_array(&entry, "Excludes", excludes,
563 dbus_message_iter_close_container(&dict, &entry);
566 dbus_message_iter_close_container(&value, &dict);
567 dbus_message_iter_close_container(&iter, &value);
569 dbus_error_init(&dbus_error);
570 dbus_connection_send_with_reply_and_block(connection, message_send,
573 if (dbus_error_is_set(&dbus_error) == TRUE) {
574 printf("Error '%s': %s", path, dbus_error.message);
575 dbus_error_free(&dbus_error);
578 dbus_message_unref(message_send);
582 return num_servers + num_excludes;
585 int set_service_property(DBusConnection *connection, DBusMessage *message,
586 char *name, char *property, char **keys,
587 void *data, int num_args)
590 DBusMessage *message_send;
591 DBusMessageIter iter;
593 const char *path_name;
594 DBusError dbus_error;
596 path_name = strip_service_path(name);
597 if (path_name == NULL)
600 path = g_strdup_printf("/net/connman/service/%s", path_name);
601 message_send = dbus_message_new_method_call("net.connman", path,
602 "net.connman.Service",
605 if (message_send == NULL) {
610 dbus_message_iter_init_append(message_send, &iter);
612 if (strcmp(property, "AutoConnect") == 0)
613 dbus_property_append_basic(&iter, (const char *) property,
614 DBUS_TYPE_BOOLEAN, data);
615 else if ((strcmp(property, "Domains.Configuration") == 0)
616 || (strcmp(property, "Timeservers.Configuration") == 0)
617 || (strcmp(property, "Nameservers.Configuration") == 0))
618 num_props = append_property_array(&iter, property, data,
620 else if ((strcmp(property, "IPv4.Configuration") == 0)
621 || (strcmp(property, "IPv6.Configuration") == 0)
622 || (strcmp(property, "Proxy.Configuration") == 0))
623 num_props = append_property_dict(&iter, property, keys, data,
626 if (num_props >= 0) {
627 dbus_error_init(&dbus_error);
628 dbus_connection_send_with_reply_and_block(connection,
629 message_send, -1, &dbus_error);
631 if (dbus_error_is_set(&dbus_error) == TRUE) {
632 printf("Error '%s': %s", path, dbus_error.message);
633 dbus_error_free(&dbus_error);
637 dbus_message_unref(message_send);
643 int remove_service(DBusConnection *connection, DBusMessage *message,
646 DBusMessage *message_send;
647 const char *path_name;
651 path_name = strip_service_path(name);
652 path = g_strdup_printf("/net/connman/service/%s", path_name);
653 message_send = dbus_message_new_method_call(CONNMAN_SERVICE, path,
654 CONNMAN_SERVICE_INTERFACE,
656 if (message_send == NULL) {
661 dbus_error_init(&err);
662 dbus_connection_send_with_reply_and_block(connection, message_send,
664 if (dbus_error_is_set(&err) == TRUE) {
665 printf("Error '%s' %s\n", path, err.message);
666 dbus_error_free(&err);
669 dbus_message_unref(message_send);