client: Use D-Bus helper functions when setting proxy
[platform/upstream/connman.git] / client / commands.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 <string.h>
30 #include <errno.h>
31 #include <getopt.h>
32 #include <stdbool.h>
33
34 #include <glib.h>
35 #include <gdbus.h>
36
37 #include "services.h"
38 #include "technology.h"
39 #include "data_manager.h"
40
41 #include "dbus_helpers.h"
42 #include "input.h"
43 #include "commands.h"
44
45 #define MANDATORY_ARGS 3
46
47 static DBusConnection *connection;
48
49 static char *ipv4[] = {
50         "Method",
51         "Address",
52         "Netmask",
53         "Gateway",
54         NULL
55 };
56
57 static char *ipv6[] = {
58         "Method",
59         "Address",
60         "PrefixLength",
61         "Gateway",
62         NULL
63 };
64
65 static int cmd_help(char *args[], int num, struct option *options);
66
67 static int parse_args(char *arg, struct option *options)
68 {
69         int i;
70
71         if (arg == NULL)
72                 return -1;
73
74         for (i = 0; options[i].name != NULL; i++) {
75                 if (strcmp(options[i].name, arg) == 0 ||
76                                 (strncmp(arg, "--", 2) == 0 &&
77                                         strcmp(&arg[2], options[i].name) == 0))
78                         return options[i].val;
79         }
80
81         return '?';
82 }
83
84 static void enable_return(DBusMessageIter *iter, const char *error,
85                 void *user_data)
86 {
87         char *tech = user_data;
88         char *str;
89
90         str = strrchr(tech, '/');
91         if (str != NULL)
92                 str++;
93         else
94                 str = tech;
95
96         if (error == NULL) {
97                 fprintf(stdout, "Enabled %s\n", str);
98         } else
99                 fprintf(stderr, "Error %s: %s\n", str, error);
100
101         g_free(user_data);
102 }
103
104 static int cmd_enable(char *args[], int num, struct option *options)
105 {
106         char *tech;
107         dbus_bool_t b = TRUE;
108
109         if (num > 2)
110                 return -E2BIG;
111
112         if (num < 2)
113                 return -EINVAL;
114
115         if (strcmp(args[1], "offlinemode") == 0) {
116                 tech = g_strdup(args[1]);
117                 return __connmanctl_dbus_set_property(connection, "/",
118                                 "net.connman.Manager", enable_return, tech,
119                                 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
120         }
121
122         tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
123         return __connmanctl_dbus_set_property(connection, tech,
124                                 "net.connman.Technology", enable_return, tech,
125                                 "Powered", DBUS_TYPE_BOOLEAN, &b);
126 }
127
128 static void disable_return(DBusMessageIter *iter, const char *error,
129                 void *user_data)
130 {
131         char *tech = user_data;
132         char *str;
133
134         str = strrchr(tech, '/');
135         if (str != NULL)
136                 str++;
137         else
138                 str = tech;
139
140         if (error == NULL) {
141                 fprintf(stdout, "Disabled %s\n", str);
142         } else
143                 fprintf(stderr, "Error %s: %s\n", str, error);
144
145         g_free(user_data);
146 }
147
148 static int cmd_disable(char *args[], int num, struct option *options)
149 {
150         char *tech;
151         dbus_bool_t b = FALSE;
152
153         if (num > 2)
154                 return -E2BIG;
155
156         if (num < 2)
157                 return -EINVAL;
158
159         if (strcmp(args[1], "offlinemode") == 0) {
160                 tech = g_strdup(args[1]);
161                 return __connmanctl_dbus_set_property(connection, "/",
162                                 "net.connman.Manager", disable_return, tech,
163                                 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
164         }
165
166         tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
167         return __connmanctl_dbus_set_property(connection, tech,
168                                 "net.connman.Technology", disable_return, tech,
169                                 "Powered", DBUS_TYPE_BOOLEAN, &b);
170 }
171
172 static void state_print(DBusMessageIter *iter, const char *error,
173                 void *user_data)
174 {
175         DBusMessageIter entry;
176
177         if (error != NULL) {
178                 fprintf(stderr, "Error: %s", error);
179                 return;
180         }
181
182         dbus_message_iter_recurse(iter, &entry);
183         __connmanctl_dbus_print(&entry, "  ", " = ", "\n");
184         fprintf(stdout, "\n");
185 }
186
187 static int cmd_state(char *args[], int num, struct option *options)
188 {
189         if (num > 1)
190                 return -E2BIG;
191
192         return __connmanctl_dbus_method_call(connection, "/",
193                         "net.connman.Manager", "GetProperties",
194                         state_print, NULL, DBUS_TYPE_INVALID);
195 }
196
197 static void services_list(DBusMessageIter *iter, const char *error,
198                 void *user_data)
199 {
200         if (error == NULL) {
201                 __connmanctl_services_list(iter);
202                 fprintf(stdout, "\n");
203         } else {
204                 fprintf(stderr, "Error: %s\n", error);
205         }
206 }
207
208 static void services_properties(DBusMessageIter *iter, const char *error,
209                 void *user_data)
210 {
211         char *path = user_data;
212         char *str;
213         DBusMessageIter dict;
214
215         if (error == NULL) {
216                 fprintf(stdout, "%s\n", path);
217
218                 dbus_message_iter_recurse(iter, &dict);
219                 __connmanctl_dbus_print(&dict, "  ", " = ", "\n");
220
221                 fprintf(stdout, "\n");
222
223         } else {
224                 str = strrchr(path, '/');
225                 if (str != NULL)
226                         str++;
227                 else
228                         str = path;
229
230                 fprintf(stderr, "Error %s: %s\n", str, error);
231         }
232
233         g_free(user_data);
234 }
235
236 static int cmd_services(char *args[], int num, struct option *options)
237 {
238         char *service_name = NULL;
239         char *path;
240         int c;
241
242         if (num > 3)
243                 return -E2BIG;
244
245         c = parse_args(args[1], options);
246         switch (c) {
247         case -1:
248                 break;
249         case 'p':
250                 if (num < 3)
251                         return -EINVAL;
252                 service_name = args[2];
253                 break;
254         default:
255                 if (num > 2)
256                         return -E2BIG;
257                 service_name = args[1];
258                 break;
259         }
260
261         if (service_name == NULL) {
262                 return __connmanctl_dbus_method_call(connection, "/",
263                         "net.connman.Manager", "GetServices",
264                         services_list, NULL, DBUS_TYPE_INVALID);
265         }
266
267         path = g_strdup_printf("/net/connman/service/%s", service_name);
268         return __connmanctl_dbus_method_call(connection, path,
269                         "net.connman.Service", "GetProperties",
270                         services_properties, path, DBUS_TYPE_INVALID);
271 }
272
273 static void technology_print(DBusMessageIter *iter, const char *error,
274                 void *user_data)
275 {
276         DBusMessageIter array;
277
278         if (error != NULL) {
279                 fprintf(stderr, "Error: %s\n", error);
280                 return;
281         }
282
283         dbus_message_iter_recurse(iter, &array);
284         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
285                 DBusMessageIter entry, dict;
286                 const char *path;
287
288                 dbus_message_iter_recurse(&array, &entry);
289                 dbus_message_iter_get_basic(&entry, &path);
290                 fprintf(stdout, "%s\n", path);
291
292                 dbus_message_iter_next(&entry);
293
294                 dbus_message_iter_recurse(&entry, &dict);
295                 __connmanctl_dbus_print(&dict, "  ", " = ", "\n");
296                 fprintf(stdout, "\n");
297
298                 dbus_message_iter_next(&array);
299         }
300 }
301
302 static int cmd_technologies(char *args[], int num, struct option *options)
303 {
304         if (num > 1)
305                 return -E2BIG;
306
307         return __connmanctl_dbus_method_call(connection, "/",
308                         "net.connman.Manager", "GetTechnologies",
309                         technology_print, NULL, DBUS_TYPE_INVALID);
310 }
311
312 static void scan_return(DBusMessageIter *iter, const char *error,
313                 void *user_data)
314 {
315         char *path = user_data;
316
317         if (error == NULL) {
318                 char *str = strrchr(path, '/');
319                 str++;
320                 fprintf(stdout, "Scan completed for %s\n", str);
321         } else
322                 fprintf(stderr, "Error %s: %s", path, error);
323
324         g_free(user_data);
325 }
326
327 static int cmd_scan(char *args[], int num, struct option *options)
328 {
329         char *path;
330
331         if (num > 2)
332                 return -E2BIG;
333
334         if (num < 2)
335                 return -EINVAL;
336
337         path = g_strdup_printf("/net/connman/technology/%s", args[1]);
338         return __connmanctl_dbus_method_call(connection, path,
339                         "net.connman.Technology", "Scan",
340                         scan_return, path, DBUS_TYPE_INVALID);
341 }
342
343 static void connect_return(DBusMessageIter *iter, const char *error,
344                 void *user_data)
345 {
346         char *path = user_data;
347
348         if (error == NULL) {
349                 char *str = strrchr(path, '/');
350                 str++;
351                 fprintf(stdout, "Connected %s\n", str);
352         } else
353                 fprintf(stderr, "Error %s: %s\n", path, error);
354
355         g_free(user_data);
356 }
357
358 static int cmd_connect(char *args[], int num, struct option *options)
359 {
360         char *path;
361
362         if (num > 2)
363                 return -E2BIG;
364
365         if (num < 2)
366                 return -EINVAL;
367
368         path = g_strdup_printf("/net/connman/service/%s", args[1]);
369         return __connmanctl_dbus_method_call(connection, path,
370                         "net.connman.Service", "Connect",
371                         connect_return, path, DBUS_TYPE_INVALID);
372 }
373
374 static void disconnect_return(DBusMessageIter *iter, const char *error,
375                 void *user_data)
376 {
377         char *path = user_data;
378
379         if (error == NULL) {
380                 char *str = strrchr(path, '/');
381                 str++;
382                 fprintf(stdout, "Disconnected %s\n", str);
383         } else
384                 fprintf(stderr, "Error %s: %s\n", path, error);
385
386         g_free(user_data);
387 }
388
389 static int cmd_disconnect(char *args[], int num, struct option *options)
390 {
391         char *path;
392
393         if (num > 2)
394                 return -E2BIG;
395
396         if (num < 2)
397                 return -EINVAL;
398
399         path = g_strdup_printf("/net/connman/service/%s", args[1]);
400         return __connmanctl_dbus_method_call(connection, path,
401                         "net.connman.Service", "Disconnect",
402                         disconnect_return, path, DBUS_TYPE_INVALID);
403
404         return 0;
405 }
406
407 static void config_return(DBusMessageIter *iter, const char *error,
408                 void *user_data)
409 {
410         char *service_name = user_data;
411
412         if (error != NULL)
413                 fprintf(stderr, "Error %s: %s\n", service_name, error);
414
415         g_free(user_data);
416 }
417
418 struct config_append {
419         char **opts;
420         int values;
421 };
422
423 static void config_append_ipv4(DBusMessageIter *iter,
424                 void *user_data)
425 {
426         struct config_append *append = user_data;
427         char **opts = append->opts;
428         int i = 0;
429
430         if (opts == NULL)
431                 return;
432
433         while (opts[i] != NULL && ipv4[i] != NULL) {
434                 __connmanctl_dbus_append_dict_entry(iter, ipv4[i],
435                                 DBUS_TYPE_STRING, &opts[i]);
436                 i++;
437         }
438
439         append->values = i;
440 }
441
442 static void config_append_ipv6(DBusMessageIter *iter, void *user_data)
443 {
444         struct config_append *append = user_data;
445         char **opts = append->opts;
446
447         if (opts == NULL)
448                 return;
449
450         append->values = 1;
451
452         if (g_strcmp0(opts[0], "auto") == 0) {
453                 char *str;
454
455                 switch (parse_boolean(opts[1])) {
456                 case 0:
457                         append->values = 2;
458
459                         str = "disabled";
460                         __connmanctl_dbus_append_dict_entry(iter, "Privacy",
461                                         DBUS_TYPE_STRING, &str);
462                         break;
463
464                 case 1:
465                         append->values = 2;
466
467                         str = "enabled";
468                         __connmanctl_dbus_append_dict_entry(iter, "Privacy",
469                                         DBUS_TYPE_STRING, &str);
470                         break;
471
472                 default:
473                         if (opts[1] != NULL) {
474                                 append->values = 2;
475
476                                 if (g_strcmp0(opts[0], "prefered") != 0) {
477                                         fprintf(stderr, "Error %s: %s\n",
478                                                         opts[1],
479                                                         strerror(-EINVAL));
480                                         return;
481                                 }
482
483                                 str = "prefered";
484                                 __connmanctl_dbus_append_dict_entry(iter,
485                                                 "Privacy", DBUS_TYPE_STRING,
486                                                 &str);
487                         }
488                         break;
489                 }
490         } else if (g_strcmp0(opts[0], "manual") == 0) {
491                 int i = 1;
492
493                 while (opts[i] != NULL && ipv6[i] != NULL) {
494                         if (i == 2) {
495                                 int value = atoi(opts[i]);
496                                 __connmanctl_dbus_append_dict_entry(iter,
497                                                 ipv6[i], DBUS_TYPE_BYTE,
498                                                 &value);
499                         } else {
500                                 __connmanctl_dbus_append_dict_entry(iter,
501                                                 ipv6[i], DBUS_TYPE_STRING,
502                                                 &opts[i]);
503                         }
504                         i++;
505                 }
506
507                 append->values = i;
508
509         } else if (g_strcmp0(opts[0], "off") != 0) {
510                 fprintf(stderr, "Error %s: %s\n", opts[0], strerror(-EINVAL));
511
512                 return;
513         }
514
515         __connmanctl_dbus_append_dict_entry(iter, "Method", DBUS_TYPE_STRING,
516                                 &opts[0]);
517 }
518
519 static void config_append_str(DBusMessageIter *iter, void *user_data)
520 {
521         struct config_append *append = user_data;
522         char **opts = append->opts;
523         int i = 0;
524
525         if (opts == NULL)
526                 return;
527
528         while (opts[i] != NULL) {
529                 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
530                                 &opts[i]);
531                 i++;
532         }
533
534         append->values = i;
535 }
536
537 static void append_servers(DBusMessageIter *iter, void *user_data)
538 {
539         struct config_append *append = user_data;
540         char **opts = append->opts;
541         int i = 1;
542
543         if (opts == NULL)
544                 return;
545
546         while (opts[i] != NULL && g_strcmp0(opts[i], "--excludes") != 0) {
547                 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
548                                 &opts[i]);
549                 i++;
550         }
551
552         append->values = i;
553 }
554
555 static void append_excludes(DBusMessageIter *iter, void *user_data)
556 {
557         struct config_append *append = user_data;
558         char **opts = append->opts;
559         int i = append->values;
560
561         if (opts == NULL || opts[i] == NULL ||
562                         g_strcmp0(opts[i], "--excludes") != 0)
563                 return;
564
565         i++;
566         while (opts[i] != NULL) {
567                 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
568                                 &opts[i]);
569                 i++;
570         }
571
572         append->values = i;
573 }
574
575 static void config_append_proxy(DBusMessageIter *iter, void *user_data)
576 {
577         struct config_append *append = user_data;
578         char **opts = append->opts;
579
580         if (opts == NULL)
581                 return;
582
583         if (g_strcmp0(opts[0], "manual") == 0) {
584                 __connmanctl_dbus_append_dict_string_array(iter, "Servers",
585                                 append_servers, append);
586
587                 __connmanctl_dbus_append_dict_string_array(iter, "Excludes",
588                                 append_excludes, append);
589
590         } else if (g_strcmp0(opts[0], "auto") == 0) {
591                 if (opts[1] != NULL) {
592                         __connmanctl_dbus_append_dict_entry(iter, "URL",
593                                         DBUS_TYPE_STRING, &opts[1]);
594                         append->values++;
595                 }
596
597         } else if (g_strcmp0(opts[0], "direct") != 0)
598                 return;
599
600         __connmanctl_dbus_append_dict_entry(iter, "Method",DBUS_TYPE_STRING,
601                         &opts[0]);
602
603         append->values++;
604 }
605
606 static int cmd_config(char *args[], int num, struct option *options)
607 {
608         int result = 0, res = 0, index = 2, oldindex = 0;
609         int c;
610         char *service_name, *path;
611         DBusMessage *message;
612         char **opt_start;
613         dbus_bool_t val;
614         struct config_append append;
615
616         service_name = args[1];
617         if (service_name == NULL)
618                 return -EINVAL;
619
620         while (index < num && args[index] != NULL) {
621                 c = parse_args(args[index], options);
622                 opt_start = &args[index + 1];
623                 append.opts = opt_start;
624                 append.values = 0;
625
626                 res = 0;
627
628                 message = get_message(connection, "GetServices");
629                 if (message == NULL)
630                         return -ENOMEM;
631
632                 oldindex = index;
633                 path = g_strdup_printf("/net/connman/service/%s", service_name);
634
635                 switch (c) {
636                 case 'a':
637                         switch (parse_boolean(*opt_start)) {
638                         case 1:
639                                 val = TRUE;
640                                 break;
641                         case 0:
642                                 val = FALSE;
643                                 break;
644                         default:
645                                 res = -EINVAL;
646                                 break;
647                         }
648
649                         index++;
650
651                         if (res == 0) {
652                                 res = __connmanctl_dbus_set_property(connection,
653                                                 path, "net.connman.Service",
654                                                 config_return,
655                                                 g_strdup(service_name),
656                                                 "AutoConnect",
657                                                 DBUS_TYPE_BOOLEAN, &val);
658                         }
659                         break;
660                 case 'i':
661                         res = __connmanctl_dbus_set_property_dict(connection,
662                                         path, "net.connman.Service",
663                                         config_return, g_strdup(service_name),
664                                         "IPv4.Configuration", DBUS_TYPE_STRING,
665                                         config_append_ipv4, &append);
666                         index += append.values;
667                         break;
668
669                 case 'v':
670                         res = __connmanctl_dbus_set_property_dict(connection,
671                                         path, "net.connman.Service",
672                                         config_return, g_strdup(service_name),
673                                         "IPv6.Configuration", DBUS_TYPE_STRING,
674                                         config_append_ipv6, &append);
675                         index += append.values;
676                         break;
677
678                 case 'n':
679                         res = __connmanctl_dbus_set_property_array(connection,
680                                         path, "net.connman.Service",
681                                         config_return, g_strdup(service_name),
682                                         "Nameservers.Configuration",
683                                         DBUS_TYPE_STRING, config_append_str,
684                                         &append);
685                         index += append.values;
686                         break;
687
688                 case 't':
689                         res = __connmanctl_dbus_set_property_array(connection,
690                                         path, "net.connman.Service",
691                                         config_return, g_strdup(service_name),
692                                         "Timeservers.Configuration",
693                                         DBUS_TYPE_STRING, config_append_str,
694                                         &append);
695                         index += append.values;
696                         break;
697
698                 case 'd':
699                         res = __connmanctl_dbus_set_property_array(connection,
700                                         path, "net.connman.Service",
701                                         config_return, g_strdup(service_name),
702                                         "Domains.Configuration",
703                                         DBUS_TYPE_STRING, config_append_str,
704                                         &append);
705                         index += append.values;
706                         break;
707
708                 case 'x':
709                         res = __connmanctl_dbus_set_property_dict(connection,
710                                         path, "net.connman.Service",
711                                         config_return, g_strdup(service_name),
712                                         "Proxy.Configuration",
713                                         DBUS_TYPE_STRING, config_append_proxy,
714                                         &append);
715                         index += append.values;
716                         break;
717                 case 'r':
718                         res = __connmanctl_dbus_method_call(connection,
719                                         path, "net.connman.Service", "Remove",
720                                         config_return, g_strdup(service_name),
721                                         DBUS_TYPE_INVALID);
722                         break;
723                 default:
724                         res = -EINVAL;
725                         break;
726                 }
727
728                 g_free(path);
729                 dbus_message_unref(message);
730
731                 if (res < 0) {
732                         if (res == -EINPROGRESS)
733                                 result = -EINPROGRESS;
734                         else
735                                 printf("Error '%s': %s\n", args[oldindex],
736                                                 strerror(-res));
737                 } else
738                         index += res;
739
740                 index++;
741         }
742
743         return result;
744 }
745
746 static DBusHandlerResult monitor_changed(DBusConnection *connection,
747                 DBusMessage *message, void *user_data)
748 {
749         DBusMessageIter iter;
750         const char *interface, *path;
751
752         interface = dbus_message_get_interface(message);
753         if (strncmp(interface, "net.connman.", 12) != 0)
754                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
755
756         interface = strrchr(interface, '.');
757         if (interface != NULL && *interface != '\0')
758                 interface++;
759
760         path = strrchr(dbus_message_get_path(message), '/');
761         if (path != NULL && *path != '\0')
762                 path++;
763
764         __connmanctl_save_rl();
765
766         if (dbus_message_is_signal(message, "net.connman.Manager",
767                                         "ServicesChanged") == TRUE) {
768
769                 fprintf(stdout, "%-12s %-20s = {\n", interface,
770                                 "ServicesChanged");
771                 dbus_message_iter_init(message, &iter);
772                 __connmanctl_services_list(&iter);
773                 fprintf(stdout, "\n}\n");
774
775                 __connmanctl_redraw_rl();
776
777                 return DBUS_HANDLER_RESULT_HANDLED;
778         }
779
780         if (dbus_message_is_signal(message, "net.connman.Manager",
781                                         "TechnologyAdded") == TRUE)
782                 path = "TechnologyAdded";
783
784         if (dbus_message_is_signal(message, "net.connman.Manager",
785                                         "TechnologyRemoved") == TRUE)
786                 path = "TechnologyRemoved";
787
788         fprintf(stdout, "%-12s %-20s ", interface, path);
789         dbus_message_iter_init(message, &iter);
790
791         __connmanctl_dbus_print(&iter, "", " = ", " = ");
792         fprintf(stdout, "\n");
793
794         __connmanctl_redraw_rl();
795
796         return DBUS_HANDLER_RESULT_HANDLED;
797 }
798
799 static bool monitor_s = false;
800 static bool monitor_t = false;
801 static bool monitor_m = false;
802
803 static void monitor_add(char *interface)
804 {
805         char *rule;
806         DBusError err;
807
808         if (monitor_s == false && monitor_t == false && monitor_m == false)
809                 dbus_connection_add_filter(connection, monitor_changed,
810                                 NULL, NULL);
811
812         if (g_strcmp0(interface, "Service") == 0) {
813                 if (monitor_s == true)
814                         return;
815                 monitor_s = true;
816         } else if (g_strcmp0(interface, "Technology") == 0) {
817                 if (monitor_t == true)
818                         return;
819                 monitor_t = true;
820         } else if (g_strcmp0(interface, "Manager") == 0) {
821                 if (monitor_m == true)
822                         return;
823                 monitor_m = true;
824         } else
825                 return;
826
827         dbus_error_init(&err);
828         rule  = g_strdup_printf("type='signal',interface='net.connman.%s'",
829                         interface);
830         dbus_bus_add_match(connection, rule, &err);
831         g_free(rule);
832
833         if (dbus_error_is_set(&err))
834                 fprintf(stderr, "Error: %s\n", err.message);
835 }
836
837 static void monitor_del(char *interface)
838 {
839         char *rule;
840
841         if (g_strcmp0(interface, "Service") == 0) {
842                 if (monitor_s == false)
843                         return;
844                 monitor_s = false;
845         } else if (g_strcmp0(interface, "Technology") == 0) {
846                 if (monitor_t == false)
847                         return;
848                 monitor_t = false;
849         } else if (g_strcmp0(interface, "Manager") == 0) {
850                 if (monitor_m == false)
851                         return;
852                 monitor_m = false;
853         } else
854                 return;
855
856         rule  = g_strdup_printf("type='signal',interface='net.connman.%s'",
857                         interface);
858         dbus_bus_remove_match(connection, rule, NULL);
859         g_free(rule);
860
861         if (monitor_s == false && monitor_t == false && monitor_m == false)
862                 dbus_connection_remove_filter(connection, monitor_changed,
863                                 NULL);
864 }
865
866 static int cmd_monitor(char *args[], int num, struct option *options)
867 {
868         bool add = true;
869         int c;
870
871         if (num > 3)
872                 return -E2BIG;
873
874         if (num == 3) {
875                 switch (parse_boolean(args[2])) {
876                 case 0:
877                         add = false;
878                         break;
879
880                 default:
881                         break;
882                 }
883         }
884
885         c = parse_args(args[1], options);
886         switch (c) {
887         case -1:
888                 monitor_add("Service");
889                 monitor_add("Technology");
890                 monitor_add("Manager");
891                 break;
892
893         case 's':
894                 if (add == true)
895                         monitor_add("Service");
896                 else
897                         monitor_del("Service");
898                 break;
899
900         case 'c':
901                 if (add == true)
902                         monitor_add("Technology");
903                 else
904                         monitor_del("Technology");
905                 break;
906
907         case 'm':
908                 if (add == true)
909                         monitor_add("Manager");
910                 else
911                         monitor_del("Manager");
912                 break;
913
914         default:
915                 switch(parse_boolean(args[1])) {
916                 case 0:
917                         monitor_del("Service");
918                         monitor_del("Technology");
919                         monitor_del("Manager");
920                         break;
921
922                 case 1:
923                         monitor_add("Service");
924                         monitor_add("Technology");
925                         monitor_add("Manager");
926                         break;
927
928                 default:
929                         return -EINVAL;
930                 }
931         }
932
933         if (add == true)
934                 return -EINPROGRESS;
935
936         return 0;
937 }
938
939 static int cmd_exit(char *args[], int num, struct option *options)
940 {
941         return 1;
942 }
943
944 static struct option service_options[] = {
945         {"properties", required_argument, 0, 'p'},
946         { NULL, }
947 };
948
949 static const char *service_desc[] = {
950         "[<service>]      (obsolete)",
951         NULL
952 };
953
954 static struct option config_options[] = {
955         {"nameservers", required_argument, 0, 'n'},
956         {"timeservers", required_argument, 0, 't'},
957         {"domains", required_argument, 0, 'd'},
958         {"ipv6", required_argument, 0, 'v'},
959         {"proxy", required_argument, 0, 'x'},
960         {"autoconnect", required_argument, 0, 'a'},
961         {"ipv4", required_argument, 0, 'i'},
962         {"remove", 0, 0, 'r'},
963         { NULL, }
964 };
965
966 static const char *config_desc[] = {
967         "<dns1> [<dns2>] [<dns3>]",
968         "<ntp1> [<ntp2>] [...]",
969         "<domain1> [<domain2>] [...]",
970         "off|auto [enable|disable|prefered]|\n"
971         "\t\t\tmanual <address> <prefixlength> <gateway>",
972         "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
973         "\t\t\t[exclude <exclude1> [<exclude2>] [...]]",
974         "yes|no",
975         "off|dhcp|manual <address> <prefixlength> <gateway>",
976         "                 Remove service",
977         NULL
978 };
979
980 static struct option monitor_options[] = {
981         {"services", no_argument, 0, 's'},
982         {"tech", no_argument, 0, 'c'},
983         {"manager", no_argument, 0, 'm'},
984         { NULL, }
985 };
986
987 static const char *monitor_desc[] = {
988         "[off]            Monitor only services",
989         "[off]            Monitor only technologies",
990         "[off]            Monitor only manager interface",
991         NULL
992 };
993
994 static const struct {
995         const char *cmd;
996         const char *argument;
997         struct option *options;
998         const char **options_desc;
999         int (*func) (char *args[], int num, struct option *options);
1000         const char *desc;
1001 } cmd_table[] = {
1002         { "enable",       "<technology>|offline", NULL,    NULL,
1003           cmd_enable, "Enables given technology or offline mode" },
1004         { "disable",      "<technology>|offline", NULL,    NULL,
1005           cmd_disable, "Disables given technology or offline mode"},
1006         { "state",        NULL,           NULL,            NULL,
1007           cmd_state, "Shows if the system is online or offline" },
1008         { "services",     "[<service>]",  service_options, &service_desc[0],
1009           cmd_services, "Display services" },
1010         { "technologies", NULL,           NULL,            NULL,
1011           cmd_technologies, "Display technologies" },
1012         { "scan",         "<technology>", NULL,            NULL,
1013           cmd_scan, "Scans for new services for given technology" },
1014         { "connect",      "<service>",    NULL,            NULL,
1015           cmd_connect, "Connect a given service" },
1016         { "disconnect",   "<service>",    NULL,            NULL,
1017           cmd_disconnect, "Disconnect a given service" },
1018         { "config",       "<service>",    config_options,  &config_desc[0],
1019           cmd_config, "Set service configuration options" },
1020         { "monitor",      "[off]",        monitor_options, &monitor_desc[0],
1021           cmd_monitor, "Monitor signals from interfaces" },
1022         { "help",         NULL,           NULL,            NULL,
1023           cmd_help, "Show help" },
1024         { "exit",         NULL,           NULL,            NULL,
1025           cmd_exit,       "Exit" },
1026         { "quit",         NULL,           NULL,            NULL,
1027           cmd_exit,       "Quit" },
1028         {  NULL, },
1029 };
1030
1031 static int cmd_help(char *args[], int num, struct option *options)
1032 {
1033         bool interactive = __connmanctl_is_interactive();
1034         int i, j;
1035
1036         if (interactive == false)
1037                 fprintf(stdout, "Usage: connmanctl [[command] [args]]\n");
1038
1039         for (i = 0; cmd_table[i].cmd != NULL; i++) {
1040                 const char *cmd = cmd_table[i].cmd;
1041                 const char *argument = cmd_table[i].argument;
1042                 const char *desc = cmd_table[i].desc;
1043
1044                 printf("%-12s%-22s%s\n", cmd != NULL? cmd: "",
1045                                 argument != NULL? argument: "",
1046                                 desc != NULL? desc: "");
1047
1048                 if (cmd_table[i].options != NULL) {
1049                         for (j = 0; cmd_table[i].options[j].name != NULL;
1050                              j++) {
1051                                 const char *options_desc =
1052                                         cmd_table[i].options_desc != NULL ?
1053                                         cmd_table[i].options_desc[j]: "";
1054
1055                                 printf("   --%-12s%s\n",
1056                                                 cmd_table[i].options[j].name,
1057                                                 options_desc);
1058                         }
1059                 }
1060         }
1061
1062         if (interactive == false)
1063                 fprintf(stdout, "\nNote: arguments and output are considered "
1064                                 "EXPERIMENTAL for now.\n");
1065
1066         return 0;
1067 }
1068
1069 int commands(DBusConnection *dbus_conn, char *argv[], int argc)
1070 {
1071         int i, result;
1072
1073         connection = dbus_conn;
1074
1075         for (i = 0; cmd_table[i].cmd != NULL; i++) {
1076                 if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
1077                                 cmd_table[i].func != NULL) {
1078                         result = cmd_table[i].func(argv, argc,
1079                                         cmd_table[i].options);
1080                         if (result < 0 && result != -EINPROGRESS)
1081                                 fprintf(stderr, "Error '%s': %s\n", argv[0],
1082                                                 strerror(-result));
1083                         return result;
1084                 }
1085         }
1086
1087         fprintf(stderr, "Error '%s': Unknown command\n", argv[0]);
1088         return -EINVAL;
1089 }