client: Factor out technology enable and disable commands
[platform/upstream/connman.git] / client / commands.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2012  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
33 #include <glib.h>
34 #include <gdbus.h>
35
36 #include "services.h"
37 #include "technology.h"
38 #include "data_manager.h"
39 #include "monitor.h"
40 #include "interactive.h"
41
42 #define MANDATORY_ARGS 3
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         "Privacy",
58         NULL
59 };
60
61 static char *proxy_simple[] = {
62         "Method",
63         "URL",
64         NULL
65 };
66
67 static int cmd_help(char *args[], int num, struct option *options);
68
69 static int parse_args(char *arg, struct option *options)
70 {
71         int i;
72
73         if (arg == NULL)
74                 return -1;
75
76         for (i = 0; options[i].name != NULL; i++) {
77                 if (strcmp(options[i].name, arg) == 0 ||
78                                 (strncmp(arg, "--", 2) == 0 &&
79                                         strcmp(&arg[2], options[i].name) == 0))
80                         return options[i].val;
81         }
82
83         return '?';
84 }
85
86 int monitor_switch(int argc, char *argv[], int c, DBusConnection *conn)
87 {
88         int error;
89
90         switch (c) {
91         case 's':
92                 error = monitor_connman(conn, "Service", "PropertyChanged");
93                 if (error != 0)
94                         return error;
95                 if (dbus_connection_add_filter(conn, service_property_changed,
96                                                         NULL, NULL) == FALSE)
97                         return -ENOMEM;
98                 printf("Now monitoring the service interface.\n");
99                 break;
100         case 'c':
101                 error = monitor_connman(conn, "Technology", "PropertyChanged");
102                 if (error != 0)
103                         return error;
104                 if (dbus_connection_add_filter(conn, tech_property_changed,
105                                                         NULL, NULL) == FALSE)
106                         return -ENOMEM;
107                 printf("Now monitoring the technology interface.\n");
108                 break;
109         case 'm':
110                 error = monitor_connman(conn, "Manager", "PropertyChanged");
111                 if (error != 0)
112                         return error;
113                 error = monitor_connman(conn, "Manager", "TechnologyAdded");
114                 if (error != 0)
115                         return error;
116                 error = monitor_connman(conn, "Manager", "TechnologyRemoved");
117                 if (error != 0)
118                         return error;
119                 error = monitor_connman(conn, "Manager", "ServicesChanged");
120                 if (error != 0)
121                         return error;
122                 if (dbus_connection_add_filter(conn, manager_property_changed,
123                                                         NULL, NULL) == FALSE)
124                         return -ENOMEM;
125                 if (dbus_connection_add_filter(conn, tech_added_removed,
126                                                         NULL, NULL) == FALSE)
127                         return -ENOMEM;
128                 if (dbus_connection_add_filter(conn, manager_services_changed,
129                                                         NULL, NULL) == FALSE)
130                         return -ENOMEM;
131                 printf("Now monitoring the manager interface.\n");
132                 break;
133         default:
134                 fprintf(stderr, "Command not recognized, please check help\n");
135                 return -EINVAL;
136                 break;
137         }
138         return 0;
139 }
140
141 static int cmd_enable(char *args[], int num, struct option *options)
142 {
143         DBusMessage *message;
144         int err;
145
146         if (num > 2)
147                 return -E2BIG;
148
149         if (num < 2)
150                 return -EINVAL;
151
152         if (strcmp(args[1], "offlinemode") == 0) {
153                 err = set_manager(connection, "OfflineMode", TRUE);
154                 if (err == 0)
155                         printf("OfflineMode enabled\n");
156
157                 return 0;
158         }
159
160         message = get_message(connection, "GetTechnologies");
161         if (message == NULL)
162                 return -ENOMEM;
163
164         set_technology(connection, message, "Powered", args[1], TRUE);
165
166         return 0;
167 }
168
169 static int cmd_disable(char *args[], int num, struct option *options)
170 {
171         DBusMessage *message;
172         int err;
173
174         if (num > 2)
175                 return -E2BIG;
176
177         if (num < 2)
178                 return -EINVAL;
179
180         if (strcmp(args[1], "offlinemode") == 0) {
181                 err = set_manager(connection, "OfflineMode", FALSE);
182                 if (err == 0)
183                         printf("OfflineMode enabled\n");
184
185                 return 0;
186         }
187
188         message = get_message(connection, "GetTechnologies");
189         if (message == NULL)
190                 return -ENOMEM;
191
192         set_technology(connection, message, "Powered", args[1], FALSE);
193
194         return 0;
195 }
196
197 static int cmd_state(char *args[], int num, struct option *options)
198 {
199         if (num > 1)
200                 return -E2BIG;
201
202         return list_properties(connection, "GetProperties", NULL);
203 }
204
205 static int cmd_services(char *args[], int num, struct option *options)
206 {
207         char *service_name = NULL;
208         int err = 0;
209         int c;
210         DBusMessage *message;
211
212         if (num > 3)
213                 return -E2BIG;
214
215         c = parse_args(args[1], options);
216         switch (c) {
217         case -1:
218                 break;
219         case 'p':
220                 if (num < 3)
221                         return -EINVAL;
222                 service_name = args[2];
223                 break;
224         default:
225                 if (num > 2)
226                         return -E2BIG;
227                 service_name = args[1];
228                 break;
229         }
230
231         message = get_message(connection, "GetServices");
232         if (message == NULL)
233                 return -ENOMEM;
234
235         err = list_properties(connection, "GetServices", service_name);
236         dbus_message_unref(message);
237
238         return err;
239 }
240
241 static int cmd_technologies(char *args[], int num, struct option *options)
242 {
243         if (num > 1)
244                 return -E2BIG;
245
246         return list_properties(connection, "GetTechnologies", NULL);
247 }
248
249 static int cmd_scan(char *args[], int num, struct option *options)
250 {
251         DBusMessage *message;
252         int err;
253
254         if (num > 2)
255                 return -E2BIG;
256
257         if (num < 2)
258                 return -EINVAL;
259
260         message = get_message(connection, "GetTechnologies");
261         if (message == NULL)
262                 err = -ENOMEM;
263         else {
264                 err = scan_technology(connection, message, args[1]);
265                 if (err == 0)
266                         printf("Scan completed\n");
267         }
268
269         return 0;
270 }
271
272 static int cmd_connect(char *args[], int num, struct option *options)
273 {
274         int err;
275
276         if (num > 2)
277                 return -E2BIG;
278
279         if (num < 2)
280                 return -EINVAL;
281
282         err = connect_service(connection, args[1]);
283         if (err == 0)
284                 printf("Connected\n");
285
286         return 0;
287 }
288
289 static int cmd_disconnect(char *args[], int num, struct option *options)
290 {
291         int err;
292
293         if (num > 2)
294                 return -E2BIG;
295
296         if (num < 2)
297                 return -EINVAL;
298
299         err = disconnect_service(connection, args[1]);
300         if (err == 0)
301                 printf("Disconnected\n");
302
303         return 0;
304 }
305
306 static int cmd_config(char *args[], int num, struct option *options)
307 {
308         int res = 0, index = 2, oldindex = 0;
309         int c;
310         char *service_name;
311         DBusMessage *message;
312         char **opt_start;
313         dbus_bool_t val;
314
315         service_name = args[1];
316         if (service_name == NULL)
317                 return -EINVAL;
318
319         while (index < num && args[index] != NULL) {
320                 c = parse_args(args[index], options);
321                 opt_start = &args[index + 1];
322                 res = 0;
323
324                 message = get_message(connection, "GetServices");
325                 if (message == NULL)
326                         return -ENOMEM;
327
328                 oldindex = index;
329
330                 switch (c) {
331                 case 'a':
332                         switch (parse_boolean(*opt_start)) {
333                         case 1:
334                                 val = TRUE;
335                                 break;
336                         case 0:
337                                 val = FALSE;
338                                 break;
339                         default:
340                                 res = -EINVAL;
341                                 break;
342                         }
343                         if (res == 0)
344                                 res = set_service_property(connection, message,
345                                                 service_name, "AutoConnect",
346                                                 NULL, &val, 0);
347                         break;
348                 case 'i':
349                         res = set_service_property(connection, message,
350                                         service_name, "IPv4.Configuration",
351                                         ipv4, opt_start, 0);
352                         if (res < 0)
353                                 index += 4;
354                         break;
355                 case 'v':
356                         res = set_service_property(connection, message,
357                                         service_name, "IPv6.Configuration",
358                                         ipv6, opt_start, 0);
359                         if (res < 0)
360                                 index += 5;
361                         break;
362                 case 'n':
363                         res = set_service_property(connection, message,
364                                         service_name,
365                                         "Nameservers.Configuration",
366                                         NULL, opt_start, 0);
367                         break;
368                 case 't':
369                         res = set_service_property(connection, message,
370                                         service_name,
371                                         "Timeservers.Configuration",
372                                         NULL, opt_start, 0);
373                         break;
374                 case 'd':
375                         res = set_service_property(connection, message,
376                                         service_name,
377                                         "Domains.Configuration",
378                                         NULL, opt_start, 0);
379                         break;
380                 case 'x':
381                         if (*opt_start == NULL) {
382                                 res = -EINVAL;
383                                 break;
384                         }
385
386                         if (strcmp(*opt_start, "direct") == 0) {
387                                 res = set_service_property(connection, message,
388                                                 service_name,
389                                                 "Proxy.Configuration",
390                                                 proxy_simple, opt_start, 1);
391                                 break;
392                         }
393
394                         if (strcmp(*opt_start, "auto") == 0) {
395                                 res = set_service_property(connection, message,
396                                                 service_name,
397                                                 "Proxy.Configuration",
398                                                 proxy_simple, opt_start, 1);
399                                 break;
400                         }
401
402                         if (strcmp(*opt_start, "manual") == 0) {
403                                         char **url_start = &args[index + 2];
404
405                                         if (*url_start != NULL &&
406                                                 strcmp(*url_start,
407                                                         "servers") == 0) {
408                                                 url_start = &args[index + 3];
409                                                 index++;
410                                         }
411                                         res = store_proxy_input(connection,
412                                                         message, service_name,
413                                                         0, url_start);
414                         }
415
416                         break;
417                 case 'r':
418                         res = remove_service(connection, message, service_name);
419                         break;
420                 default:
421                         res = -EINVAL;
422                         break;
423                 }
424
425                 dbus_message_unref(message);
426
427                 if (res < 0) {
428                         printf("Error '%s': %s\n", args[oldindex],
429                                         strerror(-res));
430                 } else
431                         index += res;
432
433                 index++;
434         }
435
436         return 0;
437 }
438
439 static int cmd_monitor(char *args[], int num, struct option *options)
440 {
441         return -1;
442 }
443
444 static int cmd_exit(char *args[], int num, struct option *options)
445 {
446         return 0;
447 }
448
449 static struct option service_options[] = {
450         {"properties", required_argument, 0, 'p'},
451         { NULL, }
452 };
453
454 static const char *service_desc[] = {
455         "[<service>]      (obsolete)",
456         NULL
457 };
458
459 static struct option config_options[] = {
460         {"nameservers", required_argument, 0, 'n'},
461         {"timeservers", required_argument, 0, 't'},
462         {"domains", required_argument, 0, 'd'},
463         {"ipv6", required_argument, 0, 'v'},
464         {"proxy", required_argument, 0, 'x'},
465         {"autoconnect", required_argument, 0, 'a'},
466         {"ipv4", required_argument, 0, 'i'},
467         {"remove", 0, 0, 'r'},
468         { NULL, }
469 };
470
471 static const char *config_desc[] = {
472         "<dns1> [<dns2>] [<dns3>]",
473         "<ntp1> [<ntp2>] [...]",
474         "<domain1> [<domain2>] [...]",
475         "off|auto|manual <address> <prefixlength> <gateway> <privacy>",
476         "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
477         "                   [exclude <exclude1> [<exclude2>] [...]]",
478         "yes|no",
479         "off|dhcp|manual <address> <prefixlength> <gateway>",
480         "                 Remove service",
481         NULL
482 };
483
484 static struct option monitor_options[] = {
485         {"services", no_argument, 0, 's'},
486         {"tech", no_argument, 0, 'c'},
487         {"manager", no_argument, 0, 'm'},
488         { NULL, }
489 };
490
491 static const char *monitor_desc[] = {
492         "                 Monitor only services",
493         "                 Monitor only technologies",
494         "                 Monitor only manager interface",
495         NULL
496 };
497
498 static const struct {
499         const char *cmd;
500         const char *argument;
501         struct option *options;
502         const char **options_desc;
503         int (*func) (char *args[], int num, struct option *options);
504         const char *desc;
505 } cmd_table[] = {
506         { "enable",       "<technology>|offline", NULL,    NULL,
507           cmd_enable, "Enables given technology or offline mode" },
508         { "disable",      "<technology>|offline", NULL,    NULL,
509           cmd_disable, "Disables given technology or offline mode"},
510         { "state",        NULL,           NULL,            NULL,
511           cmd_state, "Shows if the system is online or offline" },
512         { "services",     "[<service>]",  service_options, &service_desc[0],
513           cmd_services, "Display services" },
514         { "technologies", NULL,           NULL,            NULL,
515           cmd_technologies, "Display technologies" },
516         { "scan",         "<technology>", NULL,            NULL,
517           cmd_scan, "Scans for new services for given technology" },
518         { "connect",      "<service>",    NULL,            NULL,
519           cmd_connect, "Connect a given service" },
520         { "disconnect",   "<service>",    NULL,            NULL,
521           cmd_disconnect, "Disconnect a given service" },
522         { "config",       "<service>",    config_options,  &config_desc[0],
523           cmd_config, "Set service configuration options" },
524         { "monitor",      NULL,           monitor_options, &monitor_desc[0],
525           cmd_monitor, "Monitor signals from interfaces" },
526         { "help",         NULL,           NULL,            NULL,
527           cmd_help, "Show help" },
528         { "exit",         NULL,           NULL,            NULL,
529           cmd_exit,       "Exit" },
530         { "quit",         NULL,           NULL,            NULL,
531           cmd_exit,       "Quit" },
532         {  NULL, },
533 };
534
535 static int cmd_help(char *args[], int num, struct option *options)
536 {
537         int i, j;
538
539         for (i = 0; cmd_table[i].cmd != NULL; i++) {
540                 const char *cmd = cmd_table[i].cmd;
541                 const char *argument = cmd_table[i].argument;
542                 const char *desc = cmd_table[i].desc;
543
544                 printf("%-12s%-22s%s\n", cmd != NULL? cmd: "",
545                                 argument != NULL? argument: "",
546                                 desc != NULL? desc: "");
547
548                 if (cmd_table[i].options != NULL) {
549                         for (j = 0; cmd_table[i].options[j].name != NULL;
550                              j++) {
551                                 const char *options_desc =
552                                         cmd_table[i].options_desc != NULL ?
553                                         cmd_table[i].options_desc[j]: "";
554
555                                 printf("   --%-12s%s\n",
556                                                 cmd_table[i].options[j].name,
557                                                 options_desc);
558                         }
559                 }
560         }
561
562         return 0;
563 }
564
565 int commands(DBusConnection *connection, char *argv[], int argc)
566 {
567         int i, result;
568
569         for (i = 0; cmd_table[i].cmd != NULL; i++) {
570                 if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
571                                 cmd_table[i].func != NULL) {
572                         result = cmd_table[i].func(argv, argc,
573                                         cmd_table[i].options);
574                         if (result < 0)
575                                 printf("Error '%s': %s\n", argv[0],
576                                                 strerror(-result));
577                         return 0;
578                 }
579         }
580
581         return -1;
582 }
583
584 int commands_no_options(DBusConnection *connection, char *argv[], int argc)
585 {
586         DBusMessage *message = NULL;
587         int error = 0;
588
589         if (strcmp(argv[0], "--help") == 0 || strcmp(argv[0], "help") == 0  ||
590                                                 strcmp(argv[0], "h") == 0) {
591                 printf("Usage: connmanctl [[command] [args]]\n");
592                 cmd_help(NULL, 0, NULL);
593                 printf("\nNote: arguments and output are considered "
594                                 "EXPERIMENTAL for now.\n\n");
595         } else
596                 return -1;
597
598         if (message != NULL)
599                 dbus_message_unref(message);
600
601         return error;
602 }
603
604 int commands_options(DBusConnection *connection, char *argv[], int argc)
605 {
606         int error, c;
607         int option_index = 0;
608
609         if (strcmp(argv[0], "monitor") == 0) {
610                 if (argc > 2) {
611                         fprintf(stderr, "Too many arguments for monitor, "
612                                                                 "see help\n");
613                         return -EINVAL;
614                 }
615                 if (argc < 2) {
616                         error = monitor_connman(connection, "Service",
617                                                         "PropertyChanged");
618                         if (error != 0)
619                                 return error;
620                         error = monitor_connman(connection, "Technology",
621                                                         "PropertyChanged");
622                         if (error != 0)
623                                 return error;
624                         error = monitor_connman(connection, "Manager",
625                                                         "PropertyChanged");
626                         if (error != 0)
627                                 return error;
628                         error = monitor_connman(connection, "Manager",
629                                                         "TechnologyAdded");
630                         if (error != 0)
631                                 return error;
632                         error = monitor_connman(connection, "Manager",
633                                                         "TechnologyRemoved");
634                         if (error != 0)
635                                 return error;
636                         error = monitor_connman(connection, "Manager",
637                                                         "ServicesChanged");
638                         if (error != 0)
639                                 return error;
640                         if (dbus_connection_add_filter(connection,
641                                         service_property_changed, NULL, NULL)
642                                                                 == FALSE)
643                                 return -ENOMEM;
644                         if (dbus_connection_add_filter(connection,
645                                         tech_property_changed, NULL, NULL)
646                                                                 == FALSE)
647                                 return -ENOMEM;
648                         if (dbus_connection_add_filter(connection,
649                                         tech_added_removed, NULL, NULL)
650                                                                 == FALSE)
651                                 return -ENOMEM;
652                         if (dbus_connection_add_filter(connection,
653                                         manager_property_changed, NULL, NULL)
654                                                                 == FALSE)
655                                 return -ENOMEM;
656                         if (dbus_connection_add_filter(connection,
657                                         manager_services_changed, NULL, NULL)
658                                                                 == FALSE)
659                                 return -ENOMEM;
660                         printf("Now monitoring all interfaces.\n");
661                 } else
662                         while ((c = getopt_long(argc, argv, "", monitor_options,
663                                                         &option_index))) {
664                                 if (c == -1) {
665                                         if (option_index == 0) {
666                                                 printf("Monitor takes an "
667                                                         "option, see help\n");
668                                                 return -EINVAL;
669                                         }
670                                         break;
671                                 }
672                                 error = monitor_switch(argc, argv, c, connection);
673                                 if (error != 0)
674                                         return error;
675                                 option_index++;
676                         }
677         } else
678                 return -1;
679         return 0;
680 }