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