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 version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include "client/services.h"
30 #include "src/connman.h"
32 static void append_property_array(DBusMessageIter *iter, char *property,
33 char **data, int num_args)
35 DBusMessageIter value, array;
38 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
40 connman_dbus_array_open(iter, &value);
41 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
42 DBUS_TYPE_STRING_AS_STRING, &array);
44 for (i = 0; i < num_args; i++) {
45 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
47 printf("Added: %s\n", data[i]);
49 dbus_message_iter_close_container(&value, &array);
50 dbus_message_iter_close_container(iter, &value);
53 static void append_property_dict(DBusMessageIter *iter, char *property,
54 char **keys, char **data, int num_args)
56 DBusMessageIter value, dict, entry, dict_key;
60 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
62 /* Top most level is a{sv} */
63 connman_dbus_dict_open_variant(iter, &value);
65 connman_dbus_dict_open(&value, &dict);
67 for (i = 0; i < num_args; i++) {
68 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
70 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
73 if (strcmp(property, "IPv6.Configuration") == 0 &&
74 g_strcmp0(keys[i], "PrefixLength")) {
75 if (data[i] == NULL) {
76 fprintf(stderr, "No values entered!\n");
79 prefix = atoi(data[i]);
81 dbus_message_iter_open_container(&entry,
83 DBUS_TYPE_BYTE_AS_STRING,
85 dbus_message_iter_append_basic(&dict_key,
86 DBUS_TYPE_BYTE, &prefix);
88 dbus_message_iter_open_container(&entry,
90 DBUS_TYPE_STRING_AS_STRING,
92 dbus_message_iter_append_basic(&dict_key,
96 dbus_message_iter_close_container(&entry, &dict_key);
97 dbus_message_iter_close_container(&dict, &entry);
99 /* Close {sv}, then close a{sv} */
100 connman_dbus_dict_close(&value, &dict);
101 connman_dbus_dict_close(iter, &value);
104 void iterate_array(DBusMessageIter *iter)
106 DBusMessageIter array_item;
107 dbus_bool_t key_bool;
110 dbus_message_iter_recurse(iter, &array_item);
111 /* Make sure the entry is not NULL! */
113 while (dbus_message_iter_get_arg_type(&array_item) !=
115 if (dbus_message_iter_get_arg_type(&array_item) ==
117 dbus_message_iter_get_basic(&array_item,
119 printf("%s ", key_str);
120 } else if (dbus_message_iter_get_arg_type(&array_item) ==
122 dbus_message_iter_get_basic(&array_item, &key_bool);
123 printf("%s ", key_bool == TRUE ? "True"
126 dbus_message_iter_next(&array_item);
128 if (dbus_message_iter_get_arg_type(&array_item) ==
133 void iterate_dict(DBusMessageIter *dict, char *string, uint16_t key_int)
135 DBusMessageIter dict_entry, sub_dict_entry;
138 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
139 dbus_message_iter_recurse(dict, &dict_entry);
140 dbus_message_iter_get_basic(&dict_entry, &string);
141 printf("%s=", string);
142 dbus_message_iter_next(&dict_entry);
143 while (dbus_message_iter_get_arg_type(&dict_entry)
144 != DBUS_TYPE_INVALID) {
145 dbus_message_iter_recurse(&dict_entry, &sub_dict_entry);
146 if (dbus_message_iter_get_arg_type(&sub_dict_entry)
147 == DBUS_TYPE_UINT16) {
148 dbus_message_iter_get_basic(&sub_dict_entry,
150 printf("%d ", key_int);
151 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
152 == DBUS_TYPE_STRING) {
153 dbus_message_iter_get_basic(&sub_dict_entry,
155 printf("%s ", string);
156 } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
157 == DBUS_TYPE_ARRAY) {
158 iterate_array(&sub_dict_entry);
160 dbus_message_iter_next(&dict_entry);
162 dbus_message_iter_next(dict);
167 /* Get dictionary info about the current service and store it */
168 static void extract_service_properties(DBusMessageIter *dict,
169 struct service_data *service)
171 DBusMessageIter entry, value, array_item;
175 dbus_bool_t key_bool;
177 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
178 dbus_message_iter_recurse(dict, &entry);
179 dbus_message_iter_get_basic(&entry, &key);
180 printf("\n %s = ", key);
181 if (strcmp(key, "Name") == 0 && strlen(key) < 5)
184 dbus_message_iter_next(&entry);
185 dbus_message_iter_recurse(&entry, &value);
186 /* Check if entry is a dictionary itself */
187 if (strcmp(key, "Ethernet") == 0 ||
188 /* if just strcmp, the .Configuration names don't match
189 * and they are iterated with iterate_array instead*/
190 strncmp(key, "IPv4", 4) == 0 ||
191 strncmp(key, "IPv6", 4) == 0 ||
192 strncmp(key, "Proxy", 5) == 0 ||
193 strcmp(key, "Provider") == 0) {
194 dbus_message_iter_recurse(&value, &array_item);
195 iterate_dict(&array_item, key_str, key_uint16);
197 switch (dbus_message_iter_get_arg_type(&value)) {
198 case DBUS_TYPE_ARRAY:
199 iterate_array(&value);
201 case DBUS_TYPE_BOOLEAN:
202 dbus_message_iter_get_basic(&value, &key_bool);
203 printf("%s", key_bool == TRUE ? "True" : "False");
206 dbus_message_iter_get_basic(&value, &key_uint16);
207 printf("%d", key_uint16);
209 case DBUS_TYPE_STRING:
210 dbus_message_iter_get_basic(&value, &key_str);
211 printf("%s", key_str);
214 dbus_message_iter_next(dict);
219 static void match_service_name(DBusMessage *message, char *service_name,
220 struct service_data *service)
222 DBusMessageIter iter, array;
224 dbus_message_iter_init(message, &iter);
225 dbus_message_iter_recurse(&iter, &array);
227 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
228 DBusMessageIter entry, dict;
231 dbus_message_iter_recurse(&array, &entry);
232 dbus_message_iter_get_basic(&entry, &path);
234 service->path = strip_service_path(path);
235 dbus_message_iter_next(&entry);
236 dbus_message_iter_recurse(&entry, &dict);
237 extract_service_name(&dict, service);
238 if (g_strcmp0(service_name, service->name) == 0) {
239 printf(" Matched %s with %s\n\n", service->name,
243 dbus_message_iter_next(&array);
247 void extract_service_name(DBusMessageIter *dict, struct service_data *service)
249 DBusMessageIter dict_entry, value;
253 while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
254 dbus_message_iter_recurse(dict, &dict_entry);
255 dbus_message_iter_get_basic(&dict_entry, &key);
256 if (strcmp(key, "Name") == 0) {
257 dbus_message_iter_next(&dict_entry);
258 dbus_message_iter_recurse(&dict_entry, &value);
259 dbus_message_iter_get_basic(&value, &service->name);
261 if (strcmp(key, "AutoConnect") == 0) {
262 dbus_message_iter_next(&dict_entry);
263 dbus_message_iter_recurse(&dict_entry, &value);
264 dbus_message_iter_get_basic(&value, &service->autoconn);
266 if (strcmp(key, "State") == 0) {
267 dbus_message_iter_next(&dict_entry);
268 dbus_message_iter_recurse(&dict_entry, &value);
269 dbus_message_iter_get_basic(&value, &state);
270 if (strcmp(state, "ready") == 0) {
271 service->connected = TRUE;
272 service->online = FALSE;
273 } else if (strcmp(state, "online") == 0) {
274 service->connected = FALSE;
275 service->online = TRUE;
277 service->connected = FALSE;
278 service->online = FALSE;
281 if (strcmp(key, "Favorite") == 0) {
282 dbus_message_iter_next(&dict_entry);
283 dbus_message_iter_recurse(&dict_entry, &value);
284 dbus_message_iter_get_basic(&value, &service->favorite);
286 dbus_message_iter_next(dict);
290 /* Show detailed information about a service */
291 void extract_services(DBusMessage *message, char *service_name)
293 DBusMessageIter iter, array;
295 dbus_message_iter_init(message, &iter);
296 dbus_message_iter_recurse(&iter, &array);
298 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
299 DBusMessageIter entry, dict;
300 struct service_data service;
303 dbus_message_iter_recurse(&array, &entry);
304 dbus_message_iter_get_basic(&entry, &path);
306 service.path = strip_service_path(path);
307 if (g_strcmp0(service.path, service_name) == 0) {
308 printf("[ %s ]\n", service.path);
309 dbus_message_iter_next(&entry);
310 dbus_message_iter_recurse(&entry, &dict);
311 extract_service_properties(&dict, &service);
313 dbus_message_iter_next(&array);
317 /* Support both string names and path names for connecting to services */
318 char *strip_service_path(char *service)
321 service_name = strrchr(service, '/');
322 if (service_name == NULL)
325 return service_name + 1;
328 /* Show a simple list of service names only */
329 void get_services(DBusMessage *message)
331 DBusMessageIter iter, array;
333 dbus_message_iter_init(message, &iter);
334 dbus_message_iter_recurse(&iter, &array);
336 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
337 DBusMessageIter entry, dict;
338 struct service_data service;
341 dbus_message_iter_recurse(&array, &entry);
342 dbus_message_iter_get_basic(&entry, &path);
344 service.path = strip_service_path(path);
345 dbus_message_iter_next(&entry);
346 dbus_message_iter_recurse(&entry, &dict);
347 extract_service_name(&dict, &service);
348 printf("%-1s%-1s%-1s %-20s { %s }\n",
349 service.favorite ? "*" : "",
350 service.autoconn ? "A" : "",
351 service.online ? "O" : (service.connected ? "R" : ""),
352 service.name, service.path);
353 dbus_message_iter_next(&array);
357 const char *find_service(DBusConnection *connection, DBusMessage *message,
358 char *service_name, struct service_data *service)
360 DBusMessageIter iter, array, entry;
363 service_name = strip_service_path(service_name);
364 match_service_name(message, service_name, service);
365 /* Service name did not match, so check if entry is a path */
366 if (g_strcmp0(service_name, service->name)) {
367 dbus_message_iter_init(message, &iter);
368 dbus_message_iter_recurse(&iter, &array);
370 while (dbus_message_iter_get_arg_type(&array) ==
372 dbus_message_iter_recurse(&array, &entry);
373 dbus_message_iter_get_basic(&entry, &path);
375 service->path = strip_service_path(path);
376 if (g_strcmp0(service->path, service_name) == 0)
377 return service->path;
378 dbus_message_iter_next(&array);
380 fprintf(stderr, "'%s' is not a valid service name or path.\n",
382 fprintf(stderr, "Use the 'services' command to find available "
386 return service->path;
389 int set_proxy_manual(DBusConnection *connection, DBusMessage *message,
390 char *name, char **servers, char **excludes,
391 int num_servers, int num_excludes)
393 DBusMessage *message_send;
394 DBusMessageIter iter, value, dict, entry, data;
395 struct service_data service;
397 const char *path_name;
398 char *property = "Proxy.Configuration";
399 char *method = "Method";
400 char *manual = "manual";
402 path_name = find_service(connection, message, name, &service);
403 if (path_name == NULL)
406 path = g_strdup_printf("/net/connman/service/%s", path_name);
407 message_send = dbus_message_new_method_call("net.connman", path,
408 "net.connman.Service",
411 if (message_send == NULL) {
416 dbus_message_iter_init_append(message_send, &iter);
417 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
418 connman_dbus_dict_open_variant(&iter, &value);
419 connman_dbus_dict_open(&value, &dict);
420 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
422 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &method);
423 dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
424 DBUS_TYPE_STRING_AS_STRING,
426 dbus_message_iter_append_basic(&data, DBUS_TYPE_STRING, &manual);
427 dbus_message_iter_close_container(&entry, &data);
428 dbus_message_iter_close_container(&dict, &entry);
429 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
431 append_property_array(&entry, "Servers", servers, num_servers);
432 dbus_message_iter_close_container(&dict, &entry);
434 if (num_excludes != 0) {
435 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
437 append_property_array(&entry, "Excludes", excludes,
439 dbus_message_iter_close_container(&dict, &entry);
442 dbus_message_iter_close_container(&value, &dict);
443 dbus_message_iter_close_container(&iter, &value);
444 dbus_connection_send(connection, message_send, NULL);
445 dbus_connection_flush(connection);
446 dbus_message_unref(message_send);
453 int set_service_property(DBusConnection *connection, DBusMessage *message,
454 char *name, char *property, char **keys,
455 void *data, int num_args)
457 DBusMessage *message_send;
458 DBusMessageIter iter;
459 struct service_data service;
461 const char *path_name;
463 path_name = find_service(connection, message, name, &service);
464 if (path_name == NULL)
467 path = g_strdup_printf("/net/connman/service/%s", path_name);
468 message_send = dbus_message_new_method_call("net.connman", path,
469 "net.connman.Service",
472 if (message_send == NULL) {
477 dbus_message_iter_init_append(message_send, &iter);
479 if (strcmp(property, "AutoConnect") == 0)
480 connman_dbus_property_append_basic(&iter,
481 (const char *) property,
482 DBUS_TYPE_BOOLEAN, data);
483 else if ((strcmp(property, "Domains.Configuration") == 0)
484 || (strcmp(property, "Timeservers.Configuration") == 0)
485 || (strcmp(property, "Nameservers.Configuration") == 0))
486 append_property_array(&iter, property, data, num_args);
487 else if ((strcmp(property, "IPv4.Configuration") == 0)
488 || (strcmp(property, "IPv6.Configuration") == 0)
489 || (strcmp(property, "Proxy.Configuration") == 0))
490 append_property_dict(&iter, property, keys, data, num_args);
492 dbus_connection_send(connection, message_send, NULL);
493 dbus_connection_flush(connection);
494 dbus_message_unref(message_send);