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