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