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