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
34 #include "client/services.h"
35 #include "src/connman.h"
37 static void append_property_array(DBusMessageIter *iter, char *property,
38 char **data, int num_args)
40 DBusMessageIter value, array;
43 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
45 connman_dbus_array_open(iter, &value);
46 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
47 DBUS_TYPE_STRING_AS_STRING, &array);
49 for (i = 0; i < num_args; i++) {
50 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
52 printf("Added: %s\n", data[i]);
54 dbus_message_iter_close_container(&value, &array);
55 dbus_message_iter_close_container(iter, &value);
58 static void append_property_dict(DBusMessageIter *iter, char *property,
59 char **keys, char **data, int num_args)
61 DBusMessageIter value, dict, entry, dict_key;
65 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
67 /* Top most level is a{sv} */
68 connman_dbus_dict_open_variant(iter, &value);
70 connman_dbus_dict_open(&value, &dict);
72 for (i = 0; i < num_args; i++) {
73 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
75 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
78 if (strcmp(property, "IPv6.Configuration") == 0 &&
79 g_strcmp0(keys[i], "PrefixLength")) {
80 if (data[i] == NULL) {
81 fprintf(stderr, "No values entered!\n");
84 prefix = atoi(data[i]);
86 dbus_message_iter_open_container(&entry,
88 DBUS_TYPE_BYTE_AS_STRING,
90 dbus_message_iter_append_basic(&dict_key,
91 DBUS_TYPE_BYTE, &prefix);
93 dbus_message_iter_open_container(&entry,
95 DBUS_TYPE_STRING_AS_STRING,
97 dbus_message_iter_append_basic(&dict_key,
101 dbus_message_iter_close_container(&entry, &dict_key);
102 dbus_message_iter_close_container(&dict, &entry);
104 /* Close {sv}, then close a{sv} */
105 connman_dbus_dict_close(&value, &dict);
106 connman_dbus_dict_close(iter, &value);
109 void iterate_array(DBusMessageIter *iter)
111 DBusMessageIter array_item;
112 dbus_bool_t key_bool;
115 dbus_message_iter_recurse(iter, &array_item);
116 /* Make sure the entry is not NULL! */
118 while (dbus_message_iter_get_arg_type(&array_item) !=
120 if (dbus_message_iter_get_arg_type(&array_item) ==
122 dbus_message_iter_get_basic(&array_item,
124 printf("%s ", key_str);
125 } else if (dbus_message_iter_get_arg_type(&array_item) ==
127 dbus_message_iter_get_basic(&array_item, &key_bool);
128 printf("%s ", key_bool == TRUE ? "True"
131 dbus_message_iter_next(&array_item);
133 if (dbus_message_iter_get_arg_type(&array_item) ==
138 void iterate_dict(DBusMessageIter *dict, char *string, uint16_t key_int)
140 DBusMessageIter dict_entry, sub_dict_entry;
143 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
144 dbus_message_iter_recurse(dict, &dict_entry);
145 dbus_message_iter_get_basic(&dict_entry, &string);
146 printf("%s=", string);
147 dbus_message_iter_next(&dict_entry);
148 while (dbus_message_iter_get_arg_type(&dict_entry)
149 != DBUS_TYPE_INVALID) {
150 dbus_message_iter_recurse(&dict_entry, &sub_dict_entry);
151 if (dbus_message_iter_get_arg_type(&sub_dict_entry)
152 == DBUS_TYPE_UINT16) {
153 dbus_message_iter_get_basic(&sub_dict_entry,
155 printf("%d ", key_int);
156 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
157 == DBUS_TYPE_STRING) {
158 dbus_message_iter_get_basic(&sub_dict_entry,
160 printf("%s ", string);
161 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
162 == DBUS_TYPE_ARRAY) {
163 iterate_array(&sub_dict_entry);
165 dbus_message_iter_next(&dict_entry);
167 dbus_message_iter_next(dict);
172 /* Get dictionary info about the current service and store it */
173 static void extract_service_properties(DBusMessageIter *dict,
174 struct service_data *service)
176 DBusMessageIter entry, value, array_item;
180 dbus_bool_t key_bool;
182 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
183 dbus_message_iter_recurse(dict, &entry);
184 dbus_message_iter_get_basic(&entry, &key);
185 printf("\n %s = ", key);
186 if (strcmp(key, "Name") == 0 && strlen(key) < 5)
189 dbus_message_iter_next(&entry);
190 dbus_message_iter_recurse(&entry, &value);
191 /* Check if entry is a dictionary itself */
192 if (strcmp(key, "Ethernet") == 0 ||
193 /* if just strcmp, the .Configuration names don't match
194 * and they are iterated with iterate_array instead*/
195 strncmp(key, "IPv4", 4) == 0 ||
196 strncmp(key, "IPv6", 4) == 0 ||
197 strncmp(key, "Proxy", 5) == 0 ||
198 strcmp(key, "Provider") == 0) {
199 dbus_message_iter_recurse(&value, &array_item);
200 iterate_dict(&array_item, key_str, key_uint16);
202 switch (dbus_message_iter_get_arg_type(&value)) {
203 case DBUS_TYPE_ARRAY:
204 iterate_array(&value);
206 case DBUS_TYPE_BOOLEAN:
207 dbus_message_iter_get_basic(&value, &key_bool);
208 printf("%s", key_bool == TRUE ? "True" : "False");
211 dbus_message_iter_get_basic(&value, &key_uint16);
212 printf("%d", key_uint16);
214 case DBUS_TYPE_STRING:
215 dbus_message_iter_get_basic(&value, &key_str);
216 printf("%s", key_str);
219 dbus_message_iter_next(dict);
224 static void match_service_name(DBusMessage *message, char *service_name,
225 struct service_data *service)
227 DBusMessageIter iter, array;
229 dbus_message_iter_init(message, &iter);
230 dbus_message_iter_recurse(&iter, &array);
232 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
233 DBusMessageIter entry, dict;
236 dbus_message_iter_recurse(&array, &entry);
237 dbus_message_iter_get_basic(&entry, &path);
239 service->path = strip_service_path(path);
240 dbus_message_iter_next(&entry);
241 dbus_message_iter_recurse(&entry, &dict);
242 extract_service_name(&dict, service);
243 if (g_strcmp0(service_name, service->name) == 0) {
244 printf(" Matched %s with %s\n\n", service->name,
248 dbus_message_iter_next(&array);
252 void extract_service_name(DBusMessageIter *dict, struct service_data *service)
254 DBusMessageIter dict_entry, value;
258 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
259 dbus_message_iter_recurse(dict, &dict_entry);
260 dbus_message_iter_get_basic(&dict_entry, &key);
261 if (strcmp(key, "Name") == 0) {
262 dbus_message_iter_next(&dict_entry);
263 dbus_message_iter_recurse(&dict_entry, &value);
264 dbus_message_iter_get_basic(&value, &service->name);
266 if (strcmp(key, "AutoConnect") == 0) {
267 dbus_message_iter_next(&dict_entry);
268 dbus_message_iter_recurse(&dict_entry, &value);
269 dbus_message_iter_get_basic(&value, &service->autoconn);
271 if (strcmp(key, "State") == 0) {
272 dbus_message_iter_next(&dict_entry);
273 dbus_message_iter_recurse(&dict_entry, &value);
274 dbus_message_iter_get_basic(&value, &state);
275 if (strcmp(state, "ready") == 0) {
276 service->connected = TRUE;
277 service->online = FALSE;
278 } else if (strcmp(state, "online") == 0) {
279 service->connected = FALSE;
280 service->online = TRUE;
282 service->connected = FALSE;
283 service->online = FALSE;
286 if (strcmp(key, "Favorite") == 0) {
287 dbus_message_iter_next(&dict_entry);
288 dbus_message_iter_recurse(&dict_entry, &value);
289 dbus_message_iter_get_basic(&value, &service->favorite);
291 dbus_message_iter_next(dict);
295 /* Show detailed information about a service */
296 void extract_services(DBusMessage *message, char *service_name)
298 DBusMessageIter iter, array;
300 dbus_message_iter_init(message, &iter);
301 dbus_message_iter_recurse(&iter, &array);
303 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
304 DBusMessageIter entry, dict;
305 struct service_data service;
308 dbus_message_iter_recurse(&array, &entry);
309 dbus_message_iter_get_basic(&entry, &path);
311 service.path = strip_service_path(path);
312 if (g_strcmp0(service.path, service_name) == 0) {
313 printf("[ %s ]\n", service.path);
314 dbus_message_iter_next(&entry);
315 dbus_message_iter_recurse(&entry, &dict);
316 extract_service_properties(&dict, &service);
318 dbus_message_iter_next(&array);
322 /* Support both string names and path names for connecting to services */
323 char *strip_service_path(char *service)
326 service_name = strrchr(service, '/');
327 if (service_name == NULL)
330 return service_name + 1;
333 /* Show a simple list of service names only */
334 void get_services(DBusMessage *message)
336 DBusMessageIter iter, array;
338 dbus_message_iter_init(message, &iter);
339 dbus_message_iter_recurse(&iter, &array);
341 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
342 DBusMessageIter entry, dict;
343 struct service_data service;
346 dbus_message_iter_recurse(&array, &entry);
347 dbus_message_iter_get_basic(&entry, &path);
349 service.path = strip_service_path(path);
350 dbus_message_iter_next(&entry);
351 dbus_message_iter_recurse(&entry, &dict);
352 extract_service_name(&dict, &service);
353 printf("%-1s%-1s%-1s %-20s { %s }\n",
354 service.favorite ? "*" : "",
355 service.autoconn ? "A" : "",
356 service.online ? "O" : (service.connected ? "R" : ""),
357 service.name, service.path);
358 dbus_message_iter_next(&array);
362 const char *find_service(DBusConnection *connection, DBusMessage *message,
363 char *service_name, struct service_data *service)
365 DBusMessageIter iter, array, entry;
368 service_name = strip_service_path(service_name);
369 match_service_name(message, service_name, service);
370 /* Service name did not match, so check if entry is a path */
371 if (g_strcmp0(service_name, service->name)) {
372 dbus_message_iter_init(message, &iter);
373 dbus_message_iter_recurse(&iter, &array);
375 while (dbus_message_iter_get_arg_type(&array) ==
377 dbus_message_iter_recurse(&array, &entry);
378 dbus_message_iter_get_basic(&entry, &path);
380 service->path = strip_service_path(path);
381 if (g_strcmp0(service->path, service_name) == 0)
382 return service->path;
383 dbus_message_iter_next(&array);
385 fprintf(stderr, "'%s' is not a valid service name or path.\n",
387 fprintf(stderr, "Use the 'services' command to find available "
391 return service->path;
394 int set_proxy_manual(DBusConnection *connection, DBusMessage *message,
395 char *name, char **servers, char **excludes,
396 int num_servers, int num_excludes)
398 DBusMessage *message_send;
399 DBusMessageIter iter, value, dict, entry, data;
400 struct service_data service;
402 const char *path_name;
403 char *property = "Proxy.Configuration";
404 char *method = "Method";
405 char *manual = "manual";
407 path_name = find_service(connection, message, name, &service);
408 if (path_name == NULL)
411 path = g_strdup_printf("/net/connman/service/%s", path_name);
412 message_send = dbus_message_new_method_call("net.connman", path,
413 "net.connman.Service",
416 if (message_send == NULL) {
421 dbus_message_iter_init_append(message_send, &iter);
422 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
423 connman_dbus_dict_open_variant(&iter, &value);
424 connman_dbus_dict_open(&value, &dict);
425 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
427 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &method);
428 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
429 DBUS_TYPE_STRING_AS_STRING,
431 dbus_message_iter_append_basic(&data, DBUS_TYPE_STRING, &manual);
432 dbus_message_iter_close_container(&entry, &data);
433 dbus_message_iter_close_container(&dict, &entry);
434 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
436 append_property_array(&entry, "Servers", servers, num_servers);
437 dbus_message_iter_close_container(&dict, &entry);
439 if (num_excludes != 0) {
440 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
442 append_property_array(&entry, "Excludes", excludes,
444 dbus_message_iter_close_container(&dict, &entry);
447 dbus_message_iter_close_container(&value, &dict);
448 dbus_message_iter_close_container(&iter, &value);
449 dbus_connection_send(connection, message_send, NULL);
450 dbus_connection_flush(connection);
451 dbus_message_unref(message_send);
458 int set_service_property(DBusConnection *connection, DBusMessage *message,
459 char *name, char *property, char **keys,
460 void *data, int num_args)
462 DBusMessage *message_send;
463 DBusMessageIter iter;
464 struct service_data service;
466 const char *path_name;
468 path_name = find_service(connection, message, name, &service);
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);
484 if (strcmp(property, "AutoConnect") == 0)
485 connman_dbus_property_append_basic(&iter,
486 (const char *) property,
487 DBUS_TYPE_BOOLEAN, data);
488 else if ((strcmp(property, "Domains.Configuration") == 0)
489 || (strcmp(property, "Timeservers.Configuration") == 0)
490 || (strcmp(property, "Nameservers.Configuration") == 0))
491 append_property_array(&iter, property, data, num_args);
492 else if ((strcmp(property, "IPv4.Configuration") == 0)
493 || (strcmp(property, "IPv6.Configuration") == 0)
494 || (strcmp(property, "Proxy.Configuration") == 0))
495 append_property_dict(&iter, property, keys, data, num_args);
497 dbus_connection_send(connection, message_send, NULL);
498 dbus_connection_flush(connection);
499 dbus_message_unref(message_send);
505 int remove_service(DBusConnection *connection, DBusMessage *message,
508 struct service_data service;
509 DBusMessage *message_send;
510 const char *path_name;
513 path_name = find_service(connection, message, name, &service);
514 if (path_name == NULL)
517 if (service.favorite == FALSE)
520 path = g_strdup_printf("/net/connman/service/%s", path_name);
521 message_send = dbus_message_new_method_call(CONNMAN_SERVICE, path,
522 CONNMAN_SERVICE_INTERFACE,
524 if (message_send == NULL) {
529 dbus_connection_send(connection, message_send, NULL);
530 dbus_message_unref(message_send);