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 void 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 for (i = 0; i < num_args; i++) {
78 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
80 printf("Added: %s\n", data[i]);
82 dbus_message_iter_close_container(&value, &array);
83 dbus_message_iter_close_container(iter, &value);
86 static void append_property_dict(DBusMessageIter *iter, char *property,
87 char **keys, char **data, int num_args)
89 DBusMessageIter value, dict, entry, dict_key;
93 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
95 /* Top most level is a{sv} */
96 dbus_dict_open_variant(iter, &value);
98 dbus_dict_open(&value, &dict);
100 for (i = 0; i < num_args; i++) {
101 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
103 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
106 if (strcmp(property, "IPv6.Configuration") == 0 &&
107 g_strcmp0(keys[i], "PrefixLength")) {
108 if (data[i] == NULL) {
109 fprintf(stderr, "No values entered!\n");
112 prefix = atoi(data[i]);
114 dbus_message_iter_open_container(&entry,
116 DBUS_TYPE_BYTE_AS_STRING,
118 dbus_message_iter_append_basic(&dict_key,
119 DBUS_TYPE_BYTE, &prefix);
121 dbus_message_iter_open_container(&entry,
123 DBUS_TYPE_STRING_AS_STRING,
125 dbus_message_iter_append_basic(&dict_key,
129 dbus_message_iter_close_container(&entry, &dict_key);
130 dbus_message_iter_close_container(&dict, &entry);
132 /* Close {sv}, then close a{sv} */
133 dbus_dict_close(&value, &dict);
134 dbus_dict_close(iter, &value);
137 void iterate_array(DBusMessageIter *iter)
139 DBusMessageIter array_item;
140 dbus_bool_t key_bool;
143 dbus_message_iter_recurse(iter, &array_item);
144 /* Make sure the entry is not NULL! */
146 while (dbus_message_iter_get_arg_type(&array_item) !=
148 if (dbus_message_iter_get_arg_type(&array_item) ==
150 dbus_message_iter_get_basic(&array_item,
152 printf("%s ", key_str);
153 } else if (dbus_message_iter_get_arg_type(&array_item) ==
155 dbus_message_iter_get_basic(&array_item, &key_bool);
156 printf("%s ", key_bool == TRUE ? "True"
159 dbus_message_iter_next(&array_item);
161 if (dbus_message_iter_get_arg_type(&array_item) ==
166 void iterate_dict(DBusMessageIter *dict, char *string, uint16_t key_int)
168 DBusMessageIter dict_entry, sub_dict_entry;
171 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
172 dbus_message_iter_recurse(dict, &dict_entry);
173 dbus_message_iter_get_basic(&dict_entry, &string);
174 printf("%s=", string);
175 dbus_message_iter_next(&dict_entry);
176 while (dbus_message_iter_get_arg_type(&dict_entry)
177 != DBUS_TYPE_INVALID) {
178 dbus_message_iter_recurse(&dict_entry, &sub_dict_entry);
179 if (dbus_message_iter_get_arg_type(&sub_dict_entry)
180 == DBUS_TYPE_UINT16) {
181 dbus_message_iter_get_basic(&sub_dict_entry,
183 printf("%d ", key_int);
184 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
185 == DBUS_TYPE_STRING) {
186 dbus_message_iter_get_basic(&sub_dict_entry,
188 printf("%s ", string);
189 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
190 == DBUS_TYPE_ARRAY) {
191 iterate_array(&sub_dict_entry);
193 dbus_message_iter_next(&dict_entry);
195 dbus_message_iter_next(dict);
200 /* Get dictionary info about the current service and store it */
201 static void extract_service_properties(DBusMessageIter *dict,
202 struct service_data *service)
204 DBusMessageIter entry, value, array_item;
208 dbus_bool_t key_bool;
210 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
211 dbus_message_iter_recurse(dict, &entry);
212 dbus_message_iter_get_basic(&entry, &key);
213 printf("\n %s = ", key);
214 if (strcmp(key, "Name") == 0 && strlen(key) < 5)
217 dbus_message_iter_next(&entry);
218 dbus_message_iter_recurse(&entry, &value);
219 /* Check if entry is a dictionary itself */
220 if (strcmp(key, "Ethernet") == 0 ||
221 /* if just strcmp, the .Configuration names don't match
222 * and they are iterated with iterate_array instead*/
223 strncmp(key, "IPv4", 4) == 0 ||
224 strncmp(key, "IPv6", 4) == 0 ||
225 strncmp(key, "Proxy", 5) == 0 ||
226 strcmp(key, "Provider") == 0) {
227 dbus_message_iter_recurse(&value, &array_item);
228 iterate_dict(&array_item, key_str, key_uint16);
230 switch (dbus_message_iter_get_arg_type(&value)) {
231 case DBUS_TYPE_ARRAY:
232 iterate_array(&value);
234 case DBUS_TYPE_BOOLEAN:
235 dbus_message_iter_get_basic(&value, &key_bool);
236 printf("%s", key_bool == TRUE ? "True" : "False");
239 dbus_message_iter_get_basic(&value, &key_uint16);
240 printf("%d", key_uint16);
242 case DBUS_TYPE_STRING:
243 dbus_message_iter_get_basic(&value, &key_str);
244 printf("%s", key_str);
247 dbus_message_iter_next(dict);
252 static void match_service_name(DBusMessage *message, char *service_name,
253 struct service_data *service)
255 DBusMessageIter iter, array;
257 dbus_message_iter_init(message, &iter);
258 dbus_message_iter_recurse(&iter, &array);
260 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
261 DBusMessageIter entry, dict;
264 dbus_message_iter_recurse(&array, &entry);
265 dbus_message_iter_get_basic(&entry, &path);
267 service->path = strip_service_path(path);
268 dbus_message_iter_next(&entry);
269 dbus_message_iter_recurse(&entry, &dict);
270 extract_service_name(&dict, service);
271 if (g_strcmp0(service_name, service->name) == 0) {
272 printf(" Matched %s with %s\n\n", service->name,
276 dbus_message_iter_next(&array);
280 void extract_service_name(DBusMessageIter *dict, struct service_data *service)
282 DBusMessageIter dict_entry, value;
286 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
287 dbus_message_iter_recurse(dict, &dict_entry);
288 dbus_message_iter_get_basic(&dict_entry, &key);
289 if (strcmp(key, "Name") == 0) {
290 dbus_message_iter_next(&dict_entry);
291 dbus_message_iter_recurse(&dict_entry, &value);
292 dbus_message_iter_get_basic(&value, &service->name);
294 if (strcmp(key, "AutoConnect") == 0) {
295 dbus_message_iter_next(&dict_entry);
296 dbus_message_iter_recurse(&dict_entry, &value);
297 dbus_message_iter_get_basic(&value, &service->autoconn);
299 if (strcmp(key, "State") == 0) {
300 dbus_message_iter_next(&dict_entry);
301 dbus_message_iter_recurse(&dict_entry, &value);
302 dbus_message_iter_get_basic(&value, &state);
303 if (strcmp(state, "ready") == 0) {
304 service->connected = TRUE;
305 service->online = FALSE;
306 } else if (strcmp(state, "online") == 0) {
307 service->connected = FALSE;
308 service->online = TRUE;
310 service->connected = FALSE;
311 service->online = FALSE;
314 if (strcmp(key, "Favorite") == 0) {
315 dbus_message_iter_next(&dict_entry);
316 dbus_message_iter_recurse(&dict_entry, &value);
317 dbus_message_iter_get_basic(&value, &service->favorite);
319 dbus_message_iter_next(dict);
323 /* Show detailed information about a service */
324 void extract_services(DBusMessage *message, char *service_name)
326 DBusMessageIter iter, array;
328 dbus_message_iter_init(message, &iter);
329 dbus_message_iter_recurse(&iter, &array);
331 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
332 DBusMessageIter entry, dict;
333 struct service_data service;
336 dbus_message_iter_recurse(&array, &entry);
337 dbus_message_iter_get_basic(&entry, &path);
339 service.path = strip_service_path(path);
340 if (g_strcmp0(service.path, service_name) == 0) {
341 printf("[ %s ]\n", service.path);
342 dbus_message_iter_next(&entry);
343 dbus_message_iter_recurse(&entry, &dict);
344 extract_service_properties(&dict, &service);
346 dbus_message_iter_next(&array);
350 /* Support both string names and path names for connecting to services */
351 char *strip_service_path(char *service)
354 service_name = strrchr(service, '/');
355 if (service_name == NULL)
358 return service_name + 1;
361 /* Show a simple list of service names only */
362 void get_services(DBusMessage *message)
364 DBusMessageIter iter, array;
366 dbus_message_iter_init(message, &iter);
367 dbus_message_iter_recurse(&iter, &array);
369 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
370 DBusMessageIter entry, dict;
371 struct service_data service;
374 dbus_message_iter_recurse(&array, &entry);
375 dbus_message_iter_get_basic(&entry, &path);
377 service.path = strip_service_path(path);
378 dbus_message_iter_next(&entry);
379 dbus_message_iter_recurse(&entry, &dict);
380 extract_service_name(&dict, &service);
381 printf("%-1s%-1s%-1s %-20s { %s }\n",
382 service.favorite ? "*" : "",
383 service.autoconn ? "A" : "",
384 service.online ? "O" : (service.connected ? "R" : ""),
385 service.name, service.path);
386 dbus_message_iter_next(&array);
390 const char *find_service(DBusConnection *connection, DBusMessage *message,
391 char *service_name, struct service_data *service)
393 DBusMessageIter iter, array, entry;
396 service_name = strip_service_path(service_name);
397 match_service_name(message, service_name, service);
398 /* Service name did not match, so check if entry is a path */
399 if (g_strcmp0(service_name, service->name)) {
400 dbus_message_iter_init(message, &iter);
401 dbus_message_iter_recurse(&iter, &array);
403 while (dbus_message_iter_get_arg_type(&array) ==
405 dbus_message_iter_recurse(&array, &entry);
406 dbus_message_iter_get_basic(&entry, &path);
408 service->path = strip_service_path(path);
409 if (g_strcmp0(service->path, service_name) == 0)
410 return service->path;
411 dbus_message_iter_next(&array);
413 fprintf(stderr, "'%s' is not a valid service name or path.\n",
415 fprintf(stderr, "Use the 'services' command to find available "
419 return service->path;
422 int set_proxy_manual(DBusConnection *connection, DBusMessage *message,
423 char *name, char **servers, char **excludes,
424 int num_servers, int num_excludes)
426 DBusMessage *message_send;
427 DBusMessageIter iter, value, dict, entry, data;
428 struct service_data service;
430 const char *path_name;
431 char *property = "Proxy.Configuration";
432 char *method = "Method";
433 char *manual = "manual";
435 path_name = find_service(connection, message, name, &service);
436 if (path_name == NULL)
439 path = g_strdup_printf("/net/connman/service/%s", path_name);
440 message_send = dbus_message_new_method_call("net.connman", path,
441 "net.connman.Service",
444 if (message_send == NULL) {
449 dbus_message_iter_init_append(message_send, &iter);
450 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
451 dbus_dict_open_variant(&iter, &value);
452 dbus_dict_open(&value, &dict);
453 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
455 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &method);
456 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
457 DBUS_TYPE_STRING_AS_STRING,
459 dbus_message_iter_append_basic(&data, DBUS_TYPE_STRING, &manual);
460 dbus_message_iter_close_container(&entry, &data);
461 dbus_message_iter_close_container(&dict, &entry);
462 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
464 append_property_array(&entry, "Servers", servers, num_servers);
465 dbus_message_iter_close_container(&dict, &entry);
467 if (num_excludes != 0) {
468 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
470 append_property_array(&entry, "Excludes", excludes,
472 dbus_message_iter_close_container(&dict, &entry);
475 dbus_message_iter_close_container(&value, &dict);
476 dbus_message_iter_close_container(&iter, &value);
477 dbus_connection_send(connection, message_send, NULL);
478 dbus_connection_flush(connection);
479 dbus_message_unref(message_send);
486 int set_service_property(DBusConnection *connection, DBusMessage *message,
487 char *name, char *property, char **keys,
488 void *data, int num_args)
490 DBusMessage *message_send;
491 DBusMessageIter iter;
492 struct service_data service;
494 const char *path_name;
496 path_name = find_service(connection, message, name, &service);
497 if (path_name == NULL)
500 path = g_strdup_printf("/net/connman/service/%s", path_name);
501 message_send = dbus_message_new_method_call("net.connman", path,
502 "net.connman.Service",
505 if (message_send == NULL) {
510 dbus_message_iter_init_append(message_send, &iter);
512 if (strcmp(property, "AutoConnect") == 0)
513 dbus_property_append_basic(&iter, (const char *) property,
514 DBUS_TYPE_BOOLEAN, data);
515 else if ((strcmp(property, "Domains.Configuration") == 0)
516 || (strcmp(property, "Timeservers.Configuration") == 0)
517 || (strcmp(property, "Nameservers.Configuration") == 0))
518 append_property_array(&iter, property, data, num_args);
519 else if ((strcmp(property, "IPv4.Configuration") == 0)
520 || (strcmp(property, "IPv6.Configuration") == 0)
521 || (strcmp(property, "Proxy.Configuration") == 0))
522 append_property_dict(&iter, property, keys, data, num_args);
524 dbus_connection_send(connection, message_send, NULL);
525 dbus_connection_flush(connection);
526 dbus_message_unref(message_send);
532 int remove_service(DBusConnection *connection, DBusMessage *message,
535 struct service_data service;
536 DBusMessage *message_send;
537 const char *path_name;
540 path_name = find_service(connection, message, name, &service);
541 if (path_name == NULL)
544 if (service.favorite == FALSE)
547 path = g_strdup_printf("/net/connman/service/%s", path_name);
548 message_send = dbus_message_new_method_call(CONNMAN_SERVICE, path,
549 CONNMAN_SERVICE_INTERFACE,
551 if (message_send == NULL) {
556 dbus_connection_send(connection, message_send, NULL);
557 dbus_message_unref(message_send);