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
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 int append_property_array(DBusMessageIter *iter, char *property,
66 char **data, int num_args)
68 DBusMessageIter value, array;
71 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
73 dbus_array_open(iter, &value);
74 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
75 DBUS_TYPE_STRING_AS_STRING, &array);
77 while (data[i] != NULL && strncmp(data[i], "--", 2) != 0) {
78 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
80 if (num_args > 0 && i == num_args)
85 dbus_message_iter_close_container(&value, &array);
86 dbus_message_iter_close_container(iter, &value);
91 static int append_property_dict(DBusMessageIter *iter, char *property,
92 char **keys, char **data, int num_args)
95 DBusMessageIter value, dict, entry, dict_key;
100 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
102 /* Top most level is a{sv} */
103 dbus_dict_open_variant(iter, &value);
105 dbus_dict_open(&value, &dict);
107 if (strcmp(property, "IPv6.Configuration") == 0)
110 while (keys[i] != NULL && data[i] != NULL
111 && strncmp(data[i], "--", 2) != 0) {
113 if (num_args > 0 && i == num_args)
116 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
118 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
121 property_value = data[i];
123 if (is_ipv6 == 1 && g_strcmp0(keys[i], "PrefixLength") == 0) {
124 prefix = atoi(data[i]);
126 dbus_message_iter_open_container(&entry,
128 DBUS_TYPE_BYTE_AS_STRING,
130 dbus_message_iter_append_basic(&dict_key,
131 DBUS_TYPE_BYTE, &prefix);
133 if (is_ipv6 == 1 && strcmp(keys[i], "Privacy") == 0) {
134 switch (parse_boolean(property_value)) {
136 property_value = "disabled";
139 property_value = "enabled";
142 if (strcmp(property_value,
149 dbus_message_iter_open_container(&entry,
151 DBUS_TYPE_STRING_AS_STRING,
153 dbus_message_iter_append_basic(&dict_key,
158 dbus_message_iter_close_container(&entry, &dict_key);
159 dbus_message_iter_close_container(&dict, &entry);
163 /* Close {sv}, then close a{sv} */
164 dbus_dict_close(&value, &dict);
165 dbus_dict_close(iter, &value);
170 void iterate_array(DBusMessageIter *iter)
172 DBusMessageIter array_item;
173 dbus_bool_t key_bool;
176 dbus_message_iter_recurse(iter, &array_item);
177 /* Make sure the entry is not NULL! */
179 while (dbus_message_iter_get_arg_type(&array_item) !=
181 if (dbus_message_iter_get_arg_type(&array_item) ==
183 dbus_message_iter_get_basic(&array_item,
185 printf("%s ", key_str);
186 } else if (dbus_message_iter_get_arg_type(&array_item) ==
188 dbus_message_iter_get_basic(&array_item, &key_bool);
189 printf("%s ", key_bool == TRUE ? "True"
192 dbus_message_iter_next(&array_item);
194 if (dbus_message_iter_get_arg_type(&array_item) ==
199 void iterate_dict(DBusMessageIter *dict, char *string, uint16_t key_int)
201 DBusMessageIter dict_entry, sub_dict_entry;
204 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
205 dbus_message_iter_recurse(dict, &dict_entry);
206 dbus_message_iter_get_basic(&dict_entry, &string);
207 printf("%s=", string);
208 dbus_message_iter_next(&dict_entry);
209 while (dbus_message_iter_get_arg_type(&dict_entry)
210 != DBUS_TYPE_INVALID) {
211 dbus_message_iter_recurse(&dict_entry, &sub_dict_entry);
212 if (dbus_message_iter_get_arg_type(&sub_dict_entry)
213 == DBUS_TYPE_UINT16) {
214 dbus_message_iter_get_basic(&sub_dict_entry,
216 printf("%d ", key_int);
217 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
218 == DBUS_TYPE_STRING) {
219 dbus_message_iter_get_basic(&sub_dict_entry,
221 printf("%s ", string);
222 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
223 == DBUS_TYPE_ARRAY) {
224 iterate_array(&sub_dict_entry);
226 dbus_message_iter_next(&dict_entry);
228 dbus_message_iter_next(dict);
233 /* Get dictionary info about the current service and store it */
234 static void extract_service_properties(DBusMessageIter *dict,
235 struct service_data *service)
237 DBusMessageIter entry, value, array_item;
241 dbus_bool_t key_bool;
243 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
244 dbus_message_iter_recurse(dict, &entry);
245 dbus_message_iter_get_basic(&entry, &key);
246 printf("\n %s = ", key);
247 if (strcmp(key, "Name") == 0 && strlen(key) < 5)
250 dbus_message_iter_next(&entry);
251 dbus_message_iter_recurse(&entry, &value);
252 /* Check if entry is a dictionary itself */
253 if (strcmp(key, "Ethernet") == 0 ||
254 /* if just strcmp, the .Configuration names don't match
255 * and they are iterated with iterate_array instead*/
256 strncmp(key, "IPv4", 4) == 0 ||
257 strncmp(key, "IPv6", 4) == 0 ||
258 strncmp(key, "Proxy", 5) == 0 ||
259 strcmp(key, "Provider") == 0) {
260 dbus_message_iter_recurse(&value, &array_item);
261 iterate_dict(&array_item, key_str, key_uint16);
263 switch (dbus_message_iter_get_arg_type(&value)) {
264 case DBUS_TYPE_ARRAY:
265 iterate_array(&value);
267 case DBUS_TYPE_BOOLEAN:
268 dbus_message_iter_get_basic(&value, &key_bool);
269 printf("%s", key_bool == TRUE ? "True" : "False");
272 dbus_message_iter_get_basic(&value, &key_uint16);
273 printf("%d", key_uint16);
275 case DBUS_TYPE_STRING:
276 dbus_message_iter_get_basic(&value, &key_str);
277 printf("%s", key_str);
280 dbus_message_iter_next(dict);
285 static void match_service_name(DBusMessage *message, char *service_name,
286 struct service_data *service)
288 DBusMessageIter iter, array;
290 dbus_message_iter_init(message, &iter);
291 dbus_message_iter_recurse(&iter, &array);
293 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
294 DBusMessageIter entry, dict;
297 dbus_message_iter_recurse(&array, &entry);
298 dbus_message_iter_get_basic(&entry, &path);
300 service->path = strip_service_path(path);
301 dbus_message_iter_next(&entry);
302 dbus_message_iter_recurse(&entry, &dict);
303 extract_service_name(&dict, service);
304 if (g_strcmp0(service_name, service->name) == 0) {
305 printf(" Matched %s with %s\n\n", service->name,
309 dbus_message_iter_next(&array);
313 void extract_service_name(DBusMessageIter *dict, struct service_data *service)
315 DBusMessageIter dict_entry, value;
319 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
320 dbus_message_iter_recurse(dict, &dict_entry);
321 dbus_message_iter_get_basic(&dict_entry, &key);
322 if (strcmp(key, "Name") == 0) {
323 dbus_message_iter_next(&dict_entry);
324 dbus_message_iter_recurse(&dict_entry, &value);
325 dbus_message_iter_get_basic(&value, &service->name);
327 if (strcmp(key, "AutoConnect") == 0) {
328 dbus_message_iter_next(&dict_entry);
329 dbus_message_iter_recurse(&dict_entry, &value);
330 dbus_message_iter_get_basic(&value, &service->autoconn);
332 if (strcmp(key, "State") == 0) {
333 dbus_message_iter_next(&dict_entry);
334 dbus_message_iter_recurse(&dict_entry, &value);
335 dbus_message_iter_get_basic(&value, &state);
336 if (strcmp(state, "ready") == 0) {
337 service->connected = TRUE;
338 service->online = FALSE;
339 } else if (strcmp(state, "online") == 0) {
340 service->connected = FALSE;
341 service->online = TRUE;
343 service->connected = FALSE;
344 service->online = FALSE;
347 if (strcmp(key, "Favorite") == 0) {
348 dbus_message_iter_next(&dict_entry);
349 dbus_message_iter_recurse(&dict_entry, &value);
350 dbus_message_iter_get_basic(&value, &service->favorite);
352 dbus_message_iter_next(dict);
356 /* Show detailed information about a service */
357 void extract_services(DBusMessage *message, char *service_name)
359 DBusMessageIter iter, array;
361 dbus_message_iter_init(message, &iter);
362 dbus_message_iter_recurse(&iter, &array);
364 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
365 DBusMessageIter entry, dict;
366 struct service_data service;
369 dbus_message_iter_recurse(&array, &entry);
370 dbus_message_iter_get_basic(&entry, &path);
372 service.path = strip_service_path(path);
373 if (g_strcmp0(service.path, service_name) == 0) {
374 printf("[ %s ]\n", service.path);
375 dbus_message_iter_next(&entry);
376 dbus_message_iter_recurse(&entry, &dict);
377 extract_service_properties(&dict, &service);
379 dbus_message_iter_next(&array);
383 /* Support both string names and path names for connecting to services */
384 char *strip_service_path(char *service)
387 service_name = strrchr(service, '/');
388 if (service_name == NULL)
391 return service_name + 1;
394 /* Show a simple list of service names only */
395 void get_services(DBusMessage *message)
397 DBusMessageIter iter, array;
399 dbus_message_iter_init(message, &iter);
400 dbus_message_iter_recurse(&iter, &array);
402 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
403 DBusMessageIter entry, dict;
404 struct service_data service;
407 dbus_message_iter_recurse(&array, &entry);
408 dbus_message_iter_get_basic(&entry, &path);
410 service.path = strip_service_path(path);
411 dbus_message_iter_next(&entry);
412 dbus_message_iter_recurse(&entry, &dict);
413 extract_service_name(&dict, &service);
414 printf("%-1s%-1s%-1s %-20s { %s }\n",
415 service.favorite ? "*" : "",
416 service.autoconn ? "A" : "",
417 service.online ? "O" : (service.connected ? "R" : ""),
418 service.name, service.path);
419 dbus_message_iter_next(&array);
423 const char *find_service(DBusConnection *connection, DBusMessage *message,
424 char *service_name, struct service_data *service)
426 DBusMessageIter iter, array, entry;
429 service_name = strip_service_path(service_name);
430 match_service_name(message, service_name, service);
431 /* Service name did not match, so check if entry is a path */
432 if (g_strcmp0(service_name, service->name)) {
433 dbus_message_iter_init(message, &iter);
434 dbus_message_iter_recurse(&iter, &array);
436 while (dbus_message_iter_get_arg_type(&array) ==
438 dbus_message_iter_recurse(&array, &entry);
439 dbus_message_iter_get_basic(&entry, &path);
441 service->path = strip_service_path(path);
442 if (g_strcmp0(service->path, service_name) == 0)
443 return service->path;
444 dbus_message_iter_next(&array);
446 fprintf(stderr, "'%s' is not a valid service name or path.\n",
448 fprintf(stderr, "Use the 'services' command to find available "
452 return service->path;
455 int set_proxy_manual(DBusConnection *connection, DBusMessage *message,
456 char *name, char **servers, char **excludes,
457 int num_servers, int num_excludes)
459 DBusMessage *message_send;
460 DBusMessageIter iter, value, dict, entry, data;
462 const char *path_name;
463 char *property = "Proxy.Configuration";
464 char *method = "Method";
465 char *manual = "manual";
466 DBusError dbus_error;
468 path_name = strip_service_path(name);
469 if (path_name == NULL)
472 path = g_strdup_printf("/net/connman/service/%s", path_name);
473 message_send = dbus_message_new_method_call("net.connman", path,
474 "net.connman.Service",
477 if (message_send == NULL) {
482 dbus_message_iter_init_append(message_send, &iter);
483 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
484 dbus_dict_open_variant(&iter, &value);
485 dbus_dict_open(&value, &dict);
486 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
488 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &method);
489 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
490 DBUS_TYPE_STRING_AS_STRING,
492 dbus_message_iter_append_basic(&data, DBUS_TYPE_STRING, &manual);
493 dbus_message_iter_close_container(&entry, &data);
494 dbus_message_iter_close_container(&dict, &entry);
495 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
497 append_property_array(&entry, "Servers", servers, num_servers -1);
498 dbus_message_iter_close_container(&dict, &entry);
500 if (num_excludes != 0) {
501 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
503 append_property_array(&entry, "Excludes", excludes,
505 dbus_message_iter_close_container(&dict, &entry);
508 dbus_message_iter_close_container(&value, &dict);
509 dbus_message_iter_close_container(&iter, &value);
511 dbus_error_init(&dbus_error);
512 dbus_connection_send_with_reply_and_block(connection, message_send,
515 if (dbus_error_is_set(&dbus_error) == TRUE) {
516 printf("Error '%s': %s", path, dbus_error.message);
517 dbus_error_free(&dbus_error);
520 dbus_message_unref(message_send);
524 return num_servers + num_excludes;
527 int set_service_property(DBusConnection *connection, DBusMessage *message,
528 char *name, char *property, char **keys,
529 void *data, int num_args)
532 DBusMessage *message_send;
533 DBusMessageIter iter;
535 const char *path_name;
536 DBusError dbus_error;
538 path_name = strip_service_path(name);
539 if (path_name == NULL)
542 path = g_strdup_printf("/net/connman/service/%s", path_name);
543 message_send = dbus_message_new_method_call("net.connman", path,
544 "net.connman.Service",
547 if (message_send == NULL) {
552 dbus_message_iter_init_append(message_send, &iter);
554 if (strcmp(property, "AutoConnect") == 0)
555 dbus_property_append_basic(&iter, (const char *) property,
556 DBUS_TYPE_BOOLEAN, data);
557 else if ((strcmp(property, "Domains.Configuration") == 0)
558 || (strcmp(property, "Timeservers.Configuration") == 0)
559 || (strcmp(property, "Nameservers.Configuration") == 0))
560 num_props = append_property_array(&iter, property, data,
562 else if ((strcmp(property, "IPv4.Configuration") == 0)
563 || (strcmp(property, "IPv6.Configuration") == 0)
564 || (strcmp(property, "Proxy.Configuration") == 0))
565 num_props = append_property_dict(&iter, property, keys, data,
568 if (num_props >= 0) {
569 dbus_error_init(&dbus_error);
570 dbus_connection_send_with_reply_and_block(connection,
571 message_send, -1, &dbus_error);
573 if (dbus_error_is_set(&dbus_error) == TRUE) {
574 printf("Error '%s': %s", path, dbus_error.message);
575 dbus_error_free(&dbus_error);
579 dbus_message_unref(message_send);
585 int remove_service(DBusConnection *connection, DBusMessage *message,
588 struct service_data service;
589 DBusMessage *message_send;
590 const char *path_name;
593 path_name = find_service(connection, message, name, &service);
594 if (path_name == NULL)
597 if (service.favorite == FALSE)
600 path = g_strdup_printf("/net/connman/service/%s", path_name);
601 message_send = dbus_message_new_method_call(CONNMAN_SERVICE, path,
602 CONNMAN_SERVICE_INTERFACE,
604 if (message_send == NULL) {
609 dbus_connection_send(connection, message_send, NULL);
610 dbus_message_unref(message_send);