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
36 #include "client/services.h"
39 static void append_property_array(DBusMessageIter *iter, char *property,
40 char **data, int num_args)
42 DBusMessageIter value, array;
45 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
47 dbus_array_open(iter, &value);
48 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
49 DBUS_TYPE_STRING_AS_STRING, &array);
51 for (i = 0; i < num_args; i++) {
52 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
54 printf("Added: %s\n", data[i]);
56 dbus_message_iter_close_container(&value, &array);
57 dbus_message_iter_close_container(iter, &value);
60 static void append_property_dict(DBusMessageIter *iter, char *property,
61 char **keys, char **data, int num_args)
63 DBusMessageIter value, dict, entry, dict_key;
67 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
69 /* Top most level is a{sv} */
70 dbus_dict_open_variant(iter, &value);
72 dbus_dict_open(&value, &dict);
74 for (i = 0; i < num_args; i++) {
75 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
77 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
80 if (strcmp(property, "IPv6.Configuration") == 0 &&
81 g_strcmp0(keys[i], "PrefixLength")) {
82 if (data[i] == NULL) {
83 fprintf(stderr, "No values entered!\n");
86 prefix = atoi(data[i]);
88 dbus_message_iter_open_container(&entry,
90 DBUS_TYPE_BYTE_AS_STRING,
92 dbus_message_iter_append_basic(&dict_key,
93 DBUS_TYPE_BYTE, &prefix);
95 dbus_message_iter_open_container(&entry,
97 DBUS_TYPE_STRING_AS_STRING,
99 dbus_message_iter_append_basic(&dict_key,
103 dbus_message_iter_close_container(&entry, &dict_key);
104 dbus_message_iter_close_container(&dict, &entry);
106 /* Close {sv}, then close a{sv} */
107 dbus_dict_close(&value, &dict);
108 dbus_dict_close(iter, &value);
111 void iterate_array(DBusMessageIter *iter)
113 DBusMessageIter array_item;
114 dbus_bool_t key_bool;
117 dbus_message_iter_recurse(iter, &array_item);
118 /* Make sure the entry is not NULL! */
120 while (dbus_message_iter_get_arg_type(&array_item) !=
122 if (dbus_message_iter_get_arg_type(&array_item) ==
124 dbus_message_iter_get_basic(&array_item,
126 printf("%s ", key_str);
127 } else if (dbus_message_iter_get_arg_type(&array_item) ==
129 dbus_message_iter_get_basic(&array_item, &key_bool);
130 printf("%s ", key_bool == TRUE ? "True"
133 dbus_message_iter_next(&array_item);
135 if (dbus_message_iter_get_arg_type(&array_item) ==
140 void iterate_dict(DBusMessageIter *dict, char *string, uint16_t key_int)
142 DBusMessageIter dict_entry, sub_dict_entry;
145 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
146 dbus_message_iter_recurse(dict, &dict_entry);
147 dbus_message_iter_get_basic(&dict_entry, &string);
148 printf("%s=", string);
149 dbus_message_iter_next(&dict_entry);
150 while (dbus_message_iter_get_arg_type(&dict_entry)
151 != DBUS_TYPE_INVALID) {
152 dbus_message_iter_recurse(&dict_entry, &sub_dict_entry);
153 if (dbus_message_iter_get_arg_type(&sub_dict_entry)
154 == DBUS_TYPE_UINT16) {
155 dbus_message_iter_get_basic(&sub_dict_entry,
157 printf("%d ", key_int);
158 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
159 == DBUS_TYPE_STRING) {
160 dbus_message_iter_get_basic(&sub_dict_entry,
162 printf("%s ", string);
163 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
164 == DBUS_TYPE_ARRAY) {
165 iterate_array(&sub_dict_entry);
167 dbus_message_iter_next(&dict_entry);
169 dbus_message_iter_next(dict);
174 /* Get dictionary info about the current service and store it */
175 static void extract_service_properties(DBusMessageIter *dict,
176 struct service_data *service)
178 DBusMessageIter entry, value, array_item;
182 dbus_bool_t key_bool;
184 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
185 dbus_message_iter_recurse(dict, &entry);
186 dbus_message_iter_get_basic(&entry, &key);
187 printf("\n %s = ", key);
188 if (strcmp(key, "Name") == 0 && strlen(key) < 5)
191 dbus_message_iter_next(&entry);
192 dbus_message_iter_recurse(&entry, &value);
193 /* Check if entry is a dictionary itself */
194 if (strcmp(key, "Ethernet") == 0 ||
195 /* if just strcmp, the .Configuration names don't match
196 * and they are iterated with iterate_array instead*/
197 strncmp(key, "IPv4", 4) == 0 ||
198 strncmp(key, "IPv6", 4) == 0 ||
199 strncmp(key, "Proxy", 5) == 0 ||
200 strcmp(key, "Provider") == 0) {
201 dbus_message_iter_recurse(&value, &array_item);
202 iterate_dict(&array_item, key_str, key_uint16);
204 switch (dbus_message_iter_get_arg_type(&value)) {
205 case DBUS_TYPE_ARRAY:
206 iterate_array(&value);
208 case DBUS_TYPE_BOOLEAN:
209 dbus_message_iter_get_basic(&value, &key_bool);
210 printf("%s", key_bool == TRUE ? "True" : "False");
213 dbus_message_iter_get_basic(&value, &key_uint16);
214 printf("%d", key_uint16);
216 case DBUS_TYPE_STRING:
217 dbus_message_iter_get_basic(&value, &key_str);
218 printf("%s", key_str);
221 dbus_message_iter_next(dict);
226 static void match_service_name(DBusMessage *message, char *service_name,
227 struct service_data *service)
229 DBusMessageIter iter, array;
231 dbus_message_iter_init(message, &iter);
232 dbus_message_iter_recurse(&iter, &array);
234 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
235 DBusMessageIter entry, dict;
238 dbus_message_iter_recurse(&array, &entry);
239 dbus_message_iter_get_basic(&entry, &path);
241 service->path = strip_service_path(path);
242 dbus_message_iter_next(&entry);
243 dbus_message_iter_recurse(&entry, &dict);
244 extract_service_name(&dict, service);
245 if (g_strcmp0(service_name, service->name) == 0) {
246 printf(" Matched %s with %s\n\n", service->name,
250 dbus_message_iter_next(&array);
254 void extract_service_name(DBusMessageIter *dict, struct service_data *service)
256 DBusMessageIter dict_entry, value;
260 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
261 dbus_message_iter_recurse(dict, &dict_entry);
262 dbus_message_iter_get_basic(&dict_entry, &key);
263 if (strcmp(key, "Name") == 0) {
264 dbus_message_iter_next(&dict_entry);
265 dbus_message_iter_recurse(&dict_entry, &value);
266 dbus_message_iter_get_basic(&value, &service->name);
268 if (strcmp(key, "AutoConnect") == 0) {
269 dbus_message_iter_next(&dict_entry);
270 dbus_message_iter_recurse(&dict_entry, &value);
271 dbus_message_iter_get_basic(&value, &service->autoconn);
273 if (strcmp(key, "State") == 0) {
274 dbus_message_iter_next(&dict_entry);
275 dbus_message_iter_recurse(&dict_entry, &value);
276 dbus_message_iter_get_basic(&value, &state);
277 if (strcmp(state, "ready") == 0) {
278 service->connected = TRUE;
279 service->online = FALSE;
280 } else if (strcmp(state, "online") == 0) {
281 service->connected = FALSE;
282 service->online = TRUE;
284 service->connected = FALSE;
285 service->online = FALSE;
288 if (strcmp(key, "Favorite") == 0) {
289 dbus_message_iter_next(&dict_entry);
290 dbus_message_iter_recurse(&dict_entry, &value);
291 dbus_message_iter_get_basic(&value, &service->favorite);
293 dbus_message_iter_next(dict);
297 /* Show detailed information about a service */
298 void extract_services(DBusMessage *message, char *service_name)
300 DBusMessageIter iter, array;
302 dbus_message_iter_init(message, &iter);
303 dbus_message_iter_recurse(&iter, &array);
305 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
306 DBusMessageIter entry, dict;
307 struct service_data service;
310 dbus_message_iter_recurse(&array, &entry);
311 dbus_message_iter_get_basic(&entry, &path);
313 service.path = strip_service_path(path);
314 if (g_strcmp0(service.path, service_name) == 0) {
315 printf("[ %s ]\n", service.path);
316 dbus_message_iter_next(&entry);
317 dbus_message_iter_recurse(&entry, &dict);
318 extract_service_properties(&dict, &service);
320 dbus_message_iter_next(&array);
324 /* Support both string names and path names for connecting to services */
325 char *strip_service_path(char *service)
328 service_name = strrchr(service, '/');
329 if (service_name == NULL)
332 return service_name + 1;
335 /* Show a simple list of service names only */
336 void get_services(DBusMessage *message)
338 DBusMessageIter iter, array;
340 dbus_message_iter_init(message, &iter);
341 dbus_message_iter_recurse(&iter, &array);
343 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
344 DBusMessageIter entry, dict;
345 struct service_data service;
348 dbus_message_iter_recurse(&array, &entry);
349 dbus_message_iter_get_basic(&entry, &path);
351 service.path = strip_service_path(path);
352 dbus_message_iter_next(&entry);
353 dbus_message_iter_recurse(&entry, &dict);
354 extract_service_name(&dict, &service);
355 printf("%-1s%-1s%-1s %-20s { %s }\n",
356 service.favorite ? "*" : "",
357 service.autoconn ? "A" : "",
358 service.online ? "O" : (service.connected ? "R" : ""),
359 service.name, service.path);
360 dbus_message_iter_next(&array);
364 const char *find_service(DBusConnection *connection, DBusMessage *message,
365 char *service_name, struct service_data *service)
367 DBusMessageIter iter, array, entry;
370 service_name = strip_service_path(service_name);
371 match_service_name(message, service_name, service);
372 /* Service name did not match, so check if entry is a path */
373 if (g_strcmp0(service_name, service->name)) {
374 dbus_message_iter_init(message, &iter);
375 dbus_message_iter_recurse(&iter, &array);
377 while (dbus_message_iter_get_arg_type(&array) ==
379 dbus_message_iter_recurse(&array, &entry);
380 dbus_message_iter_get_basic(&entry, &path);
382 service->path = strip_service_path(path);
383 if (g_strcmp0(service->path, service_name) == 0)
384 return service->path;
385 dbus_message_iter_next(&array);
387 fprintf(stderr, "'%s' is not a valid service name or path.\n",
389 fprintf(stderr, "Use the 'services' command to find available "
393 return service->path;
396 int set_proxy_manual(DBusConnection *connection, DBusMessage *message,
397 char *name, char **servers, char **excludes,
398 int num_servers, int num_excludes)
400 DBusMessage *message_send;
401 DBusMessageIter iter, value, dict, entry, data;
402 struct service_data service;
404 const char *path_name;
405 char *property = "Proxy.Configuration";
406 char *method = "Method";
407 char *manual = "manual";
409 path_name = find_service(connection, message, name, &service);
410 if (path_name == NULL)
413 path = g_strdup_printf("/net/connman/service/%s", path_name);
414 message_send = dbus_message_new_method_call("net.connman", path,
415 "net.connman.Service",
418 if (message_send == NULL) {
423 dbus_message_iter_init_append(message_send, &iter);
424 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
425 dbus_dict_open_variant(&iter, &value);
426 dbus_dict_open(&value, &dict);
427 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
429 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &method);
430 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
431 DBUS_TYPE_STRING_AS_STRING,
433 dbus_message_iter_append_basic(&data, DBUS_TYPE_STRING, &manual);
434 dbus_message_iter_close_container(&entry, &data);
435 dbus_message_iter_close_container(&dict, &entry);
436 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
438 append_property_array(&entry, "Servers", servers, num_servers);
439 dbus_message_iter_close_container(&dict, &entry);
441 if (num_excludes != 0) {
442 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
444 append_property_array(&entry, "Excludes", excludes,
446 dbus_message_iter_close_container(&dict, &entry);
449 dbus_message_iter_close_container(&value, &dict);
450 dbus_message_iter_close_container(&iter, &value);
451 dbus_connection_send(connection, message_send, NULL);
452 dbus_connection_flush(connection);
453 dbus_message_unref(message_send);
460 int set_service_property(DBusConnection *connection, DBusMessage *message,
461 char *name, char *property, char **keys,
462 void *data, int num_args)
464 DBusMessage *message_send;
465 DBusMessageIter iter;
466 struct service_data service;
468 const char *path_name;
470 path_name = find_service(connection, message, name, &service);
471 if (path_name == NULL)
474 path = g_strdup_printf("/net/connman/service/%s", path_name);
475 message_send = dbus_message_new_method_call("net.connman", path,
476 "net.connman.Service",
479 if (message_send == NULL) {
484 dbus_message_iter_init_append(message_send, &iter);
486 if (strcmp(property, "AutoConnect") == 0)
487 dbus_property_append_basic(&iter, (const char *) property,
488 DBUS_TYPE_BOOLEAN, data);
489 else if ((strcmp(property, "Domains.Configuration") == 0)
490 || (strcmp(property, "Timeservers.Configuration") == 0)
491 || (strcmp(property, "Nameservers.Configuration") == 0))
492 append_property_array(&iter, property, data, num_args);
493 else if ((strcmp(property, "IPv4.Configuration") == 0)
494 || (strcmp(property, "IPv6.Configuration") == 0)
495 || (strcmp(property, "Proxy.Configuration") == 0))
496 append_property_dict(&iter, property, keys, data, num_args);
498 dbus_connection_send(connection, message_send, NULL);
499 dbus_connection_flush(connection);
500 dbus_message_unref(message_send);
506 int remove_service(DBusConnection *connection, DBusMessage *message,
509 struct service_data service;
510 DBusMessage *message_send;
511 const char *path_name;
514 path_name = find_service(connection, message, name, &service);
515 if (path_name == NULL)
518 if (service.favorite == FALSE)
521 path = g_strdup_printf("/net/connman/service/%s", path_name);
522 message_send = dbus_message_new_method_call(CONNMAN_SERVICE, path,
523 CONNMAN_SERVICE_INTERFACE,
525 if (message_send == NULL) {
530 dbus_connection_send(connection, message_send, NULL);
531 dbus_message_unref(message_send);