client: Use D-Bus helpers for Technology GetTechnologies method call
[platform/upstream/connman.git] / client / services.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2012-2013  Intel Corporation. All rights reserved.
6  *
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.
11  *
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.
16  *
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
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <stdint.h>
30 #include <string.h>
31 #include <unistd.h>
32 #include <errno.h>
33
34 #include <glib.h>
35
36 #include "services.h"
37 #include "dbus.h"
38
39 int parse_boolean(char *arg)
40 {
41         if (arg == NULL)
42                 return -1;
43
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)
51                 return 0;
52
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)
60                 return 1;
61
62         return -1;
63 }
64
65 static void print_service(char *path, DBusMessageIter *iter)
66 {
67         char *name = "", *str = NULL;
68         int autoconn = 0, favorite = 0, count = 0;
69         char *property;
70         char state = ' ';
71         DBusMessageIter entry, val;
72
73         while (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_INVALID) {
74
75                 dbus_message_iter_recurse(iter, &entry);
76                 dbus_message_iter_get_basic(&entry, &property);
77                 if (strcmp(property, "Name") == 0) {
78                         dbus_message_iter_next(&entry);
79                         dbus_message_iter_recurse(&entry, &val);
80                         dbus_message_iter_get_basic(&val, &name);
81
82                 } else if (strcmp(property, "State") == 0) {
83                         dbus_message_iter_next(&entry);
84                         dbus_message_iter_recurse(&entry, &val);
85                         dbus_message_iter_get_basic(&val, &str);
86
87                         if (str != NULL) {
88                                 if (strcmp(str, "online") == 0)
89                                         state = 'O';
90                                 else if (strcmp(str, "ready") == 0)
91                                         state = 'R';
92                         }
93
94                 } else if (strcmp(property, "AutoConnect") == 0) {
95                         dbus_message_iter_next(&entry);
96                         dbus_message_iter_recurse(&entry, &val);
97                         dbus_message_iter_get_basic(&val, &autoconn);
98
99                 } else if (strcmp(property, "Favorite") == 0) {
100                         dbus_message_iter_next(&entry);
101                         dbus_message_iter_recurse(&entry, &val);
102                         dbus_message_iter_get_basic(&val, &favorite);
103                 }
104
105                 count++;
106                 dbus_message_iter_next(iter);
107         }
108
109         str = strrchr(path, '/');
110         if (str != NULL)
111                 str++;
112         else
113                 str = path;
114
115         if (count > 0) {
116                 if (*name == '\0')
117                         name = "<hidden>";
118
119                 fprintf(stdout, "%c%c%c %-20s %s", favorite != 0 ? '*' : ' ',
120                                 autoconn != 0 ? 'A' : ' ', state, name, str);
121         } else
122                 fprintf(stdout, "%-24s %s", "unchanged", str);
123
124 }
125
126 static void list_service_array(DBusMessageIter *iter)
127 {
128         DBusMessageIter array, dict;
129         char *path = NULL;
130
131         while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
132
133                 dbus_message_iter_recurse(iter, &array);
134                 if (dbus_message_iter_get_arg_type(&array)
135                                 != DBUS_TYPE_OBJECT_PATH)
136                         return;
137
138                 dbus_message_iter_get_basic(&array, &path);
139
140                 dbus_message_iter_next(&array);
141                 if (dbus_message_iter_get_arg_type(&array)
142                                 == DBUS_TYPE_ARRAY) {
143                         dbus_message_iter_recurse(&array, &dict);
144                         print_service(path, &dict);
145                 }
146
147                 if (dbus_message_iter_has_next(iter) == TRUE)
148                         fprintf(stdout, "\n");
149
150                 dbus_message_iter_next(iter);
151         }
152 }
153
154 void __connmanctl_services_list(DBusMessageIter *iter)
155 {
156         DBusMessageIter array;
157         char *path;
158
159         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
160                 return;
161
162         dbus_message_iter_recurse(iter, &array);
163         list_service_array(&array);
164
165         dbus_message_iter_next(iter);
166         if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
167                 return;
168
169         fprintf(stdout, "\n}, {");
170
171         dbus_message_iter_recurse(iter, &array);
172         while (dbus_message_iter_get_arg_type(&array)
173                         == DBUS_TYPE_OBJECT_PATH) {
174                 dbus_message_iter_get_basic(&array, &path);
175                 fprintf(stdout, "\n%-24s %s", "removed", path);
176
177                 dbus_message_iter_next(&array);
178         }
179
180 }
181
182
183 static int append_property_array(DBusMessageIter *iter, char *property,
184                                                 char **data, int num_args)
185 {
186         DBusMessageIter value, array;
187         int i = 0;
188
189         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
190
191         dbus_array_open(iter, &value);
192         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
193                                          DBUS_TYPE_STRING_AS_STRING, &array);
194
195         while (data[i] != NULL && strncmp(data[i], "--", 2) != 0) {
196                 dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING,
197                                                 &data[i]);
198                 if (num_args > 0 && i == num_args)
199                         break;
200                 i++;
201         }
202
203         dbus_message_iter_close_container(&value, &array);
204         dbus_message_iter_close_container(iter, &value);
205
206         return i;
207 }
208
209 static int append_property_dict(DBusMessageIter *iter, char *property,
210                                         char **keys, char **data, int num_args)
211 {
212         int is_ipv6 = 0;
213         DBusMessageIter value, dict, entry, dict_key;
214         int i = 0;
215         unsigned char prefix;
216         char *property_value;
217
218         dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &property);
219
220         /* Top most level is a{sv} */
221         dbus_dict_open_variant(iter, &value);
222
223         dbus_dict_open(&value, &dict);
224
225         if (strcmp(property, "IPv6.Configuration") == 0)
226                 is_ipv6 = 1;
227
228         while (keys[i] != NULL && data[i] != NULL
229                         && strncmp(data[i], "--", 2) != 0) {
230
231                 if (num_args > 0 && i == num_args)
232                         break;
233
234                 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
235                                                         NULL, &entry);
236                 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING,
237                                                         &keys[i]);
238
239                 property_value = data[i];
240
241                 if (is_ipv6 == 1 && g_strcmp0(keys[i], "PrefixLength") == 0) {
242                         prefix = atoi(data[i]);
243
244                         dbus_message_iter_open_container(&entry,
245                                                 DBUS_TYPE_VARIANT,
246                                                 DBUS_TYPE_BYTE_AS_STRING,
247                                                 &dict_key);
248                         dbus_message_iter_append_basic(&dict_key,
249                                                        DBUS_TYPE_BYTE, &prefix);
250                 } else {
251                         if (is_ipv6 == 1 && strcmp(keys[i], "Privacy") == 0) {
252                                 switch (parse_boolean(property_value)) {
253                                 case 0:
254                                         property_value = "disabled";
255                                         break;
256                                 case 1:
257                                         property_value = "enabled";
258                                         break;
259                                 case -1:
260                                         if (strcmp(property_value,
261                                                         "prefered") != 0)
262                                                 return -EINVAL;
263                                         break;
264                                 }
265                         }
266
267                         dbus_message_iter_open_container(&entry,
268                                                  DBUS_TYPE_VARIANT,
269                                                  DBUS_TYPE_STRING_AS_STRING,
270                                                  &dict_key);
271                         dbus_message_iter_append_basic(&dict_key,
272                                                         DBUS_TYPE_STRING,
273                                                         &property_value);
274                 }
275
276                 dbus_message_iter_close_container(&entry, &dict_key);
277                 dbus_message_iter_close_container(&dict, &entry);
278
279                 i++;
280         }
281         /* Close {sv}, then close a{sv} */
282         dbus_dict_close(&value, &dict);
283         dbus_dict_close(iter, &value);
284
285         return i;
286 }
287
288 void iterate_array(DBusMessageIter *iter)
289 {
290         DBusMessageIter array_item;
291         dbus_bool_t key_bool;
292         char *key_str;
293
294         dbus_message_iter_recurse(iter, &array_item);
295         /* Make sure the entry is not NULL! */
296         printf("[ ");
297         while (dbus_message_iter_get_arg_type(&array_item) !=
298                                         DBUS_TYPE_INVALID) {
299                 if (dbus_message_iter_get_arg_type(&array_item) ==
300                                         DBUS_TYPE_STRING) {
301                         dbus_message_iter_get_basic(&array_item,
302                                                 &key_str);
303                         printf("%s ", key_str);
304                 } else if (dbus_message_iter_get_arg_type(&array_item) ==
305                                         DBUS_TYPE_BOOLEAN) {
306                         dbus_message_iter_get_basic(&array_item, &key_bool);
307                         printf("%s ", key_bool == TRUE ? "True"
308                                                 : "False");
309                 }
310                 dbus_message_iter_next(&array_item);
311         }
312         if (dbus_message_iter_get_arg_type(&array_item) ==
313                                         DBUS_TYPE_INVALID)
314                 printf("] ");
315 }
316
317 void iterate_dict(DBusMessageIter *dict, char *string, uint16_t key_int)
318 {
319         DBusMessageIter dict_entry, sub_dict_entry;
320
321         printf("{ ");
322         while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
323                 dbus_message_iter_recurse(dict, &dict_entry);
324                 dbus_message_iter_get_basic(&dict_entry, &string);
325                 printf("%s=", string);
326                 dbus_message_iter_next(&dict_entry);
327                 while (dbus_message_iter_get_arg_type(&dict_entry)
328                                                         != DBUS_TYPE_INVALID) {
329                         dbus_message_iter_recurse(&dict_entry, &sub_dict_entry);
330                         if (dbus_message_iter_get_arg_type(&sub_dict_entry)
331                                                         == DBUS_TYPE_UINT16) {
332                                 dbus_message_iter_get_basic(&sub_dict_entry,
333                                                                 &key_int);
334                                 printf("%d ", key_int);
335                         } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
336                                                         == DBUS_TYPE_STRING) {
337                                 dbus_message_iter_get_basic(&sub_dict_entry,
338                                                                 &string);
339                                 printf("%s ", string);
340                         } else if (dbus_message_iter_get_arg_type(&sub_dict_entry)
341                                                         == DBUS_TYPE_ARRAY) {
342                                 iterate_array(&sub_dict_entry);
343                         }
344                         dbus_message_iter_next(&dict_entry);
345                 }
346                 dbus_message_iter_next(dict);
347         }
348         printf("}");
349 }
350
351 /* Get dictionary info about the current service and store it */
352 static void extract_service_properties(DBusMessageIter *dict,
353                                 struct service_data *service)
354 {
355         DBusMessageIter entry, value, array_item;
356         char *key;
357         char *key_str;
358         uint16_t key_uint16;
359         dbus_bool_t key_bool;
360
361         while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
362                 dbus_message_iter_recurse(dict, &entry);
363                 dbus_message_iter_get_basic(&entry, &key);
364                 printf("\n  %s = ", key);
365                 if (strcmp(key, "Name") == 0 && strlen(key) < 5)
366                         service->name = key;
367
368                 dbus_message_iter_next(&entry);
369                 dbus_message_iter_recurse(&entry, &value);
370                 /* Check if entry is a dictionary itself */
371                 if (strcmp(key, "Ethernet") == 0 ||
372                         /* if just strcmp, the .Configuration names don't match
373                          * and they are iterated with iterate_array instead*/
374                                 strncmp(key, "IPv4", 4) == 0 ||
375                                 strncmp(key, "IPv6", 4) == 0 ||
376                                 strncmp(key, "Proxy", 5) == 0 ||
377                                 strcmp(key, "Provider") == 0) {
378                         dbus_message_iter_recurse(&value, &array_item);
379                         iterate_dict(&array_item, key_str, key_uint16);
380                 } else
381                 switch (dbus_message_iter_get_arg_type(&value)) {
382                 case DBUS_TYPE_ARRAY:
383                         iterate_array(&value);
384                         break;
385                 case DBUS_TYPE_BOOLEAN:
386                         dbus_message_iter_get_basic(&value, &key_bool);
387                         printf("%s", key_bool == TRUE ? "True" : "False");
388                         break;
389                 case DBUS_TYPE_BYTE:
390                         dbus_message_iter_get_basic(&value, &key_uint16);
391                         printf("%d", key_uint16);
392                         break;
393                 case DBUS_TYPE_STRING:
394                         dbus_message_iter_get_basic(&value, &key_str);
395                         printf("%s", key_str);
396                         break;
397                 }
398                 dbus_message_iter_next(dict);
399         }
400         printf("\n\n");
401 }
402
403 void extract_service_name(DBusMessageIter *dict, struct service_data *service)
404 {
405         DBusMessageIter dict_entry, value;
406         const char *key;
407         const char *state;
408
409         while (dbus_message_iter_get_arg_type(dict) == DBUS_TYPE_DICT_ENTRY) {
410                 dbus_message_iter_recurse(dict, &dict_entry);
411                 dbus_message_iter_get_basic(&dict_entry, &key);
412                 if (strcmp(key, "Name") == 0) {
413                         dbus_message_iter_next(&dict_entry);
414                         dbus_message_iter_recurse(&dict_entry, &value);
415                         dbus_message_iter_get_basic(&value, &service->name);
416                 }
417                 if (strcmp(key, "AutoConnect") == 0) {
418                         dbus_message_iter_next(&dict_entry);
419                         dbus_message_iter_recurse(&dict_entry, &value);
420                         dbus_message_iter_get_basic(&value, &service->autoconn);
421                 }
422                 if (strcmp(key, "State") == 0) {
423                         dbus_message_iter_next(&dict_entry);
424                         dbus_message_iter_recurse(&dict_entry, &value);
425                         dbus_message_iter_get_basic(&value, &state);
426                         if (strcmp(state, "ready") == 0) {
427                                 service->connected = TRUE;
428                                 service->online = FALSE;
429                         } else if (strcmp(state, "online") == 0) {
430                                 service->connected = FALSE;
431                                 service->online = TRUE;
432                         } else {
433                                 service->connected = FALSE;
434                                 service->online = FALSE;
435                         }
436                 }
437                 if (strcmp(key, "Favorite") == 0) {
438                         dbus_message_iter_next(&dict_entry);
439                         dbus_message_iter_recurse(&dict_entry, &value);
440                         dbus_message_iter_get_basic(&value, &service->favorite);
441                 }
442                 dbus_message_iter_next(dict);
443         }
444 }
445
446 /* Show detailed information about a service */
447 void extract_services(DBusMessage *message, char *service_name)
448 {
449         DBusMessageIter iter, array;
450
451         dbus_message_iter_init(message, &iter);
452         dbus_message_iter_recurse(&iter, &array);
453
454         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
455                 DBusMessageIter entry, dict;
456                 struct service_data service;
457                 char *path;
458
459                 dbus_message_iter_recurse(&array, &entry);
460                 dbus_message_iter_get_basic(&entry, &path);
461
462                 service.path = strip_service_path(path);
463                 if (g_strcmp0(service.path, service_name) == 0) {
464                         printf("[ %s ]\n", service.path);
465                         dbus_message_iter_next(&entry);
466                         dbus_message_iter_recurse(&entry, &dict);
467                         extract_service_properties(&dict, &service);
468                 }
469                 dbus_message_iter_next(&array);
470         }
471 }
472
473 /* Support both string names and path names for connecting to services */
474 char *strip_service_path(char *service)
475 {
476         char *service_name;
477         service_name = strrchr(service, '/');
478         if (service_name == NULL)
479                 return service;
480         else
481                 return service_name + 1;
482 }
483
484 /* Show a simple list of service names only */
485 void get_services(DBusMessage *message)
486 {
487         DBusMessageIter iter, array;
488
489         dbus_message_iter_init(message, &iter);
490         dbus_message_iter_recurse(&iter, &array);
491
492         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
493                 DBusMessageIter entry, dict;
494                 struct service_data service;
495                 char *path;
496
497                 dbus_message_iter_recurse(&array, &entry);
498                 dbus_message_iter_get_basic(&entry, &path);
499
500                 service.path = strip_service_path(path);
501                 dbus_message_iter_next(&entry);
502                 dbus_message_iter_recurse(&entry, &dict);
503                 extract_service_name(&dict, &service);
504                 printf("%-1s%-1s%-1s %-20s { %s }\n",
505                         service.favorite ? "*" : "",
506                         service.autoconn ? "A" : "",
507                         service.online ? "O" : (service.connected ? "R" : ""),
508                         service.name, service.path);
509                 dbus_message_iter_next(&array);
510         }
511 }
512
513 int set_proxy_manual(DBusConnection *connection, DBusMessage *message,
514                                 char *name, char **servers, char **excludes,
515                                 int num_servers, int num_excludes)
516 {
517         DBusMessage *message_send;
518         DBusMessageIter iter, value, dict, entry, data;
519         char *path;
520         const char *path_name;
521         char *property = "Proxy.Configuration";
522         char *method = "Method";
523         char *manual = "manual";
524         DBusError dbus_error;
525
526         path_name = strip_service_path(name);
527         if (path_name == NULL)
528                 return -ENXIO;
529
530         path = g_strdup_printf("/net/connman/service/%s", path_name);
531         message_send = dbus_message_new_method_call("net.connman", path,
532                                                         "net.connman.Service",
533                                                         "SetProperty");
534
535         if (message_send == NULL) {
536                 g_free(path);
537                 return -ENOMEM;
538         }
539
540         dbus_message_iter_init_append(message_send, &iter);
541         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &property);
542         dbus_dict_open_variant(&iter, &value);
543         dbus_dict_open(&value, &dict);
544         dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
545                                                         &entry);
546         dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &method);
547         dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT,
548                                                 DBUS_TYPE_STRING_AS_STRING,
549                                                 &data);
550         dbus_message_iter_append_basic(&data, DBUS_TYPE_STRING, &manual);
551         dbus_message_iter_close_container(&entry, &data);
552         dbus_message_iter_close_container(&dict, &entry);
553         dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL,
554                                                         &entry);
555         append_property_array(&entry, "Servers", servers, num_servers -1);
556         dbus_message_iter_close_container(&dict, &entry);
557
558         if (num_excludes != 0) {
559                 dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY,
560                                                         NULL, &entry);
561                 append_property_array(&entry, "Excludes", excludes,
562                                                         num_excludes -1);
563                 dbus_message_iter_close_container(&dict, &entry);
564         }
565
566         dbus_message_iter_close_container(&value, &dict);
567         dbus_message_iter_close_container(&iter, &value);
568
569         dbus_error_init(&dbus_error);
570         dbus_connection_send_with_reply_and_block(connection, message_send,
571                         -1, &dbus_error);
572
573         if (dbus_error_is_set(&dbus_error) == TRUE) {
574                 printf("Error '%s': %s", path, dbus_error.message);
575                 dbus_error_free(&dbus_error);
576         }
577
578         dbus_message_unref(message_send);
579
580         g_free(path);
581
582         return num_servers + num_excludes;
583 }
584
585 int set_service_property(DBusConnection *connection, DBusMessage *message,
586                                 char *name, char *property, char **keys,
587                                 void *data, int num_args)
588 {
589         int num_props = 1;
590         DBusMessage *message_send;
591         DBusMessageIter iter;
592         char *path;
593         const char *path_name;
594         DBusError dbus_error;
595
596         path_name = strip_service_path(name);
597         if (path_name == NULL)
598                 return -ENXIO;
599
600         path = g_strdup_printf("/net/connman/service/%s", path_name);
601         message_send = dbus_message_new_method_call("net.connman", path,
602                                                         "net.connman.Service",
603                                                         "SetProperty");
604
605         if (message_send == NULL) {
606                 g_free(path);
607                 return -ENOMEM;
608         }
609
610         dbus_message_iter_init_append(message_send, &iter);
611
612         if (strcmp(property, "AutoConnect") == 0)
613                 dbus_property_append_basic(&iter, (const char *) property,
614                                                 DBUS_TYPE_BOOLEAN, data);
615         else if ((strcmp(property, "Domains.Configuration") == 0)
616                         || (strcmp(property, "Timeservers.Configuration") == 0)
617                         || (strcmp(property, "Nameservers.Configuration") == 0))
618                 num_props = append_property_array(&iter, property, data,
619                                 num_args);
620         else if ((strcmp(property, "IPv4.Configuration") == 0)
621                         || (strcmp(property, "IPv6.Configuration") == 0)
622                         || (strcmp(property, "Proxy.Configuration") == 0))
623                 num_props = append_property_dict(&iter, property, keys, data,
624                                 num_args);
625
626         if (num_props >= 0) {
627                 dbus_error_init(&dbus_error);
628                 dbus_connection_send_with_reply_and_block(connection,
629                                 message_send, -1, &dbus_error);
630
631                 if (dbus_error_is_set(&dbus_error) == TRUE) {
632                         printf("Error '%s': %s", path, dbus_error.message);
633                         dbus_error_free(&dbus_error);
634                 }
635         }
636
637         dbus_message_unref(message_send);
638         g_free(path);
639
640         return num_props;
641 }
642
643 int remove_service(DBusConnection *connection, DBusMessage *message,
644                                                                 char *name)
645 {
646         DBusMessage *message_send;
647         const char *path_name;
648         char *path;
649         DBusError err;
650
651         path_name = strip_service_path(name);
652         path = g_strdup_printf("/net/connman/service/%s", path_name);
653         message_send = dbus_message_new_method_call(CONNMAN_SERVICE, path,
654                                                 CONNMAN_SERVICE_INTERFACE,
655                                                 "Remove");
656         if (message_send == NULL) {
657                 g_free(path);
658                 return -ENOMEM;
659         }
660
661         dbus_error_init(&err);
662         dbus_connection_send_with_reply_and_block(connection, message_send,
663                         -1, &err);
664         if (dbus_error_is_set(&err) == TRUE) {
665                 printf("Error '%s' %s\n", path, err.message);
666                 dbus_error_free(&err);
667         }
668
669         dbus_message_unref(message_send);
670         g_free(path);
671
672         return 0;
673 }