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)
94 DBusMessageIter value, dict, entry, dict_key;
98 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
100 /* Top most level is a{sv} */
101 dbus_dict_open_variant(iter, &value);
103 dbus_dict_open(&value, &dict);
105 while (keys[i] != NULL && data[i] != NULL
106 && strncmp(data[i], "--", 2) != 0) {
108 if (num_args > 0 && i == num_args)
111 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
113 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
116 if (strcmp(property, "IPv6.Configuration") == 0 &&
117 g_strcmp0(keys[i], "PrefixLength")) {
118 if (data[i] == NULL) {
119 fprintf(stderr, "No values entered!\n");
122 prefix = atoi(data[i]);
124 dbus_message_iter_open_container(&entry,
126 DBUS_TYPE_BYTE_AS_STRING,
128 dbus_message_iter_append_basic(&dict_key,
129 DBUS_TYPE_BYTE, &prefix);
131 dbus_message_iter_open_container(&entry,
133 DBUS_TYPE_STRING_AS_STRING,
135 dbus_message_iter_append_basic(&dict_key,
139 dbus_message_iter_close_container(&entry, &dict_key);
140 dbus_message_iter_close_container(&dict, &entry);
144 /* Close {sv}, then close a{sv} */
145 dbus_dict_close(&value, &dict);
146 dbus_dict_close(iter, &value);
151 void iterate_array(DBusMessageIter *iter)
153 DBusMessageIter array_item;
154 dbus_bool_t key_bool;
157 dbus_message_iter_recurse(iter, &array_item);
158 /* Make sure the entry is not NULL! */
160 while (dbus_message_iter_get_arg_type(&array_item) !=
162 if (dbus_message_iter_get_arg_type(&array_item) ==
164 dbus_message_iter_get_basic(&array_item,
166 printf("%s ", key_str);
167 } else if (dbus_message_iter_get_arg_type(&array_item) ==
169 dbus_message_iter_get_basic(&array_item, &key_bool);
170 printf("%s ", key_bool == TRUE ? "True"
173 dbus_message_iter_next(&array_item);
175 if (dbus_message_iter_get_arg_type(&array_item) ==
180 void iterate_dict(DBusMessageIter *dict, char *string, uint16_t key_int)
182 DBusMessageIter dict_entry, sub_dict_entry;
185 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
186 dbus_message_iter_recurse(dict, &dict_entry);
187 dbus_message_iter_get_basic(&dict_entry, &string);
188 printf("%s=", string);
189 dbus_message_iter_next(&dict_entry);
190 while (dbus_message_iter_get_arg_type(&dict_entry)
191 != DBUS_TYPE_INVALID) {
192 dbus_message_iter_recurse(&dict_entry, &sub_dict_entry);
193 if (dbus_message_iter_get_arg_type(&sub_dict_entry)
194 == DBUS_TYPE_UINT16) {
195 dbus_message_iter_get_basic(&sub_dict_entry,
197 printf("%d ", key_int);
198 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
199 == DBUS_TYPE_STRING) {
200 dbus_message_iter_get_basic(&sub_dict_entry,
202 printf("%s ", string);
203 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
204 == DBUS_TYPE_ARRAY) {
205 iterate_array(&sub_dict_entry);
207 dbus_message_iter_next(&dict_entry);
209 dbus_message_iter_next(dict);
214 /* Get dictionary info about the current service and store it */
215 static void extract_service_properties(DBusMessageIter *dict,
216 struct service_data *service)
218 DBusMessageIter entry, value, array_item;
222 dbus_bool_t key_bool;
224 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
225 dbus_message_iter_recurse(dict, &entry);
226 dbus_message_iter_get_basic(&entry, &key);
227 printf("\n %s = ", key);
228 if (strcmp(key, "Name") == 0 && strlen(key) < 5)
231 dbus_message_iter_next(&entry);
232 dbus_message_iter_recurse(&entry, &value);
233 /* Check if entry is a dictionary itself */
234 if (strcmp(key, "Ethernet") == 0 ||
235 /* if just strcmp, the .Configuration names don't match
236 * and they are iterated with iterate_array instead*/
237 strncmp(key, "IPv4", 4) == 0 ||
238 strncmp(key, "IPv6", 4) == 0 ||
239 strncmp(key, "Proxy", 5) == 0 ||
240 strcmp(key, "Provider") == 0) {
241 dbus_message_iter_recurse(&value, &array_item);
242 iterate_dict(&array_item, key_str, key_uint16);
244 switch (dbus_message_iter_get_arg_type(&value)) {
245 case DBUS_TYPE_ARRAY:
246 iterate_array(&value);
248 case DBUS_TYPE_BOOLEAN:
249 dbus_message_iter_get_basic(&value, &key_bool);
250 printf("%s", key_bool == TRUE ? "True" : "False");
253 dbus_message_iter_get_basic(&value, &key_uint16);
254 printf("%d", key_uint16);
256 case DBUS_TYPE_STRING:
257 dbus_message_iter_get_basic(&value, &key_str);
258 printf("%s", key_str);
261 dbus_message_iter_next(dict);
266 static void match_service_name(DBusMessage *message, char *service_name,
267 struct service_data *service)
269 DBusMessageIter iter, array;
271 dbus_message_iter_init(message, &iter);
272 dbus_message_iter_recurse(&iter, &array);
274 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
275 DBusMessageIter entry, dict;
278 dbus_message_iter_recurse(&array, &entry);
279 dbus_message_iter_get_basic(&entry, &path);
281 service->path = strip_service_path(path);
282 dbus_message_iter_next(&entry);
283 dbus_message_iter_recurse(&entry, &dict);
284 extract_service_name(&dict, service);
285 if (g_strcmp0(service_name, service->name) == 0) {
286 printf(" Matched %s with %s\n\n", service->name,
290 dbus_message_iter_next(&array);
294 void extract_service_name(DBusMessageIter *dict, struct service_data *service)
296 DBusMessageIter dict_entry, value;
300 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
301 dbus_message_iter_recurse(dict, &dict_entry);
302 dbus_message_iter_get_basic(&dict_entry, &key);
303 if (strcmp(key, "Name") == 0) {
304 dbus_message_iter_next(&dict_entry);
305 dbus_message_iter_recurse(&dict_entry, &value);
306 dbus_message_iter_get_basic(&value, &service->name);
308 if (strcmp(key, "AutoConnect") == 0) {
309 dbus_message_iter_next(&dict_entry);
310 dbus_message_iter_recurse(&dict_entry, &value);
311 dbus_message_iter_get_basic(&value, &service->autoconn);
313 if (strcmp(key, "State") == 0) {
314 dbus_message_iter_next(&dict_entry);
315 dbus_message_iter_recurse(&dict_entry, &value);
316 dbus_message_iter_get_basic(&value, &state);
317 if (strcmp(state, "ready") == 0) {
318 service->connected = TRUE;
319 service->online = FALSE;
320 } else if (strcmp(state, "online") == 0) {
321 service->connected = FALSE;
322 service->online = TRUE;
324 service->connected = FALSE;
325 service->online = FALSE;
328 if (strcmp(key, "Favorite") == 0) {
329 dbus_message_iter_next(&dict_entry);
330 dbus_message_iter_recurse(&dict_entry, &value);
331 dbus_message_iter_get_basic(&value, &service->favorite);
333 dbus_message_iter_next(dict);
337 /* Show detailed information about a service */
338 void extract_services(DBusMessage *message, char *service_name)
340 DBusMessageIter iter, array;
342 dbus_message_iter_init(message, &iter);
343 dbus_message_iter_recurse(&iter, &array);
345 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
346 DBusMessageIter entry, dict;
347 struct service_data service;
350 dbus_message_iter_recurse(&array, &entry);
351 dbus_message_iter_get_basic(&entry, &path);
353 service.path = strip_service_path(path);
354 if (g_strcmp0(service.path, service_name) == 0) {
355 printf("[ %s ]\n", service.path);
356 dbus_message_iter_next(&entry);
357 dbus_message_iter_recurse(&entry, &dict);
358 extract_service_properties(&dict, &service);
360 dbus_message_iter_next(&array);
364 /* Support both string names and path names for connecting to services */
365 char *strip_service_path(char *service)
368 service_name = strrchr(service, '/');
369 if (service_name == NULL)
372 return service_name + 1;
375 /* Show a simple list of service names only */
376 void get_services(DBusMessage *message)
378 DBusMessageIter iter, array;
380 dbus_message_iter_init(message, &iter);
381 dbus_message_iter_recurse(&iter, &array);
383 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
384 DBusMessageIter entry, dict;
385 struct service_data service;
388 dbus_message_iter_recurse(&array, &entry);
389 dbus_message_iter_get_basic(&entry, &path);
391 service.path = strip_service_path(path);
392 dbus_message_iter_next(&entry);
393 dbus_message_iter_recurse(&entry, &dict);
394 extract_service_name(&dict, &service);
395 printf("%-1s%-1s%-1s %-20s { %s }\n",
396 service.favorite ? "*" : "",
397 service.autoconn ? "A" : "",
398 service.online ? "O" : (service.connected ? "R" : ""),
399 service.name, service.path);
400 dbus_message_iter_next(&array);
404 const char *find_service(DBusConnection *connection, DBusMessage *message,
405 char *service_name, struct service_data *service)
407 DBusMessageIter iter, array, entry;
410 service_name = strip_service_path(service_name);
411 match_service_name(message, service_name, service);
412 /* Service name did not match, so check if entry is a path */
413 if (g_strcmp0(service_name, service->name)) {
414 dbus_message_iter_init(message, &iter);
415 dbus_message_iter_recurse(&iter, &array);
417 while (dbus_message_iter_get_arg_type(&array) ==
419 dbus_message_iter_recurse(&array, &entry);
420 dbus_message_iter_get_basic(&entry, &path);
422 service->path = strip_service_path(path);
423 if (g_strcmp0(service->path, service_name) == 0)
424 return service->path;
425 dbus_message_iter_next(&array);
427 fprintf(stderr, "'%s' is not a valid service name or path.\n",
429 fprintf(stderr, "Use the 'services' command to find available "
433 return service->path;
436 int set_proxy_manual(DBusConnection *connection, DBusMessage *message,
437 char *name, char **servers, char **excludes,
438 int num_servers, int num_excludes)
440 DBusMessage *message_send;
441 DBusMessageIter iter, value, dict, entry, data;
442 struct service_data service;
444 const char *path_name;
445 char *property = "Proxy.Configuration";
446 char *method = "Method";
447 char *manual = "manual";
449 path_name = find_service(connection, message, name, &service);
450 if (path_name == NULL)
453 path = g_strdup_printf("/net/connman/service/%s", path_name);
454 message_send = dbus_message_new_method_call("net.connman", path,
455 "net.connman.Service",
458 if (message_send == NULL) {
463 dbus_message_iter_init_append(message_send, &iter);
464 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
465 dbus_dict_open_variant(&iter, &value);
466 dbus_dict_open(&value, &dict);
467 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
469 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &method);
470 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
471 DBUS_TYPE_STRING_AS_STRING,
473 dbus_message_iter_append_basic(&data, DBUS_TYPE_STRING, &manual);
474 dbus_message_iter_close_container(&entry, &data);
475 dbus_message_iter_close_container(&dict, &entry);
476 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
478 append_property_array(&entry, "Servers", servers, num_servers -1);
479 dbus_message_iter_close_container(&dict, &entry);
481 if (num_excludes != 0) {
482 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
484 append_property_array(&entry, "Excludes", excludes,
486 dbus_message_iter_close_container(&dict, &entry);
489 dbus_message_iter_close_container(&value, &dict);
490 dbus_message_iter_close_container(&iter, &value);
491 dbus_connection_send(connection, message_send, NULL);
492 dbus_connection_flush(connection);
493 dbus_message_unref(message_send);
497 return num_servers + num_excludes;
500 int set_service_property(DBusConnection *connection, DBusMessage *message,
501 char *name, char *property, char **keys,
502 void *data, int num_args)
505 DBusMessage *message_send;
506 DBusMessageIter iter;
507 struct service_data service;
509 const char *path_name;
511 path_name = find_service(connection, message, name, &service);
512 if (path_name == NULL)
515 path = g_strdup_printf("/net/connman/service/%s", path_name);
516 message_send = dbus_message_new_method_call("net.connman", path,
517 "net.connman.Service",
520 if (message_send == NULL) {
525 dbus_message_iter_init_append(message_send, &iter);
527 if (strcmp(property, "AutoConnect") == 0)
528 dbus_property_append_basic(&iter, (const char *) property,
529 DBUS_TYPE_BOOLEAN, data);
530 else if ((strcmp(property, "Domains.Configuration") == 0)
531 || (strcmp(property, "Timeservers.Configuration") == 0)
532 || (strcmp(property, "Nameservers.Configuration") == 0))
533 num_props = append_property_array(&iter, property, data,
535 else if ((strcmp(property, "IPv4.Configuration") == 0)
536 || (strcmp(property, "IPv6.Configuration") == 0)
537 || (strcmp(property, "Proxy.Configuration") == 0))
538 num_props = append_property_dict(&iter, property, keys, data,
541 dbus_connection_send(connection, message_send, NULL);
542 dbus_connection_flush(connection);
543 dbus_message_unref(message_send);
549 int remove_service(DBusConnection *connection, DBusMessage *message,
552 struct service_data service;
553 DBusMessage *message_send;
554 const char *path_name;
557 path_name = find_service(connection, message, name, &service);
558 if (path_name == NULL)
561 if (service.favorite == FALSE)
564 path = g_strdup_printf("/net/connman/service/%s", path_name);
565 message_send = dbus_message_new_method_call(CONNMAN_SERVICE, path,
566 CONNMAN_SERVICE_INTERFACE,
568 if (message_send == NULL) {
573 dbus_connection_send(connection, message_send, NULL);
574 dbus_message_unref(message_send);