client: Delete the now obsolete monitor.[hc] files
[platform/upstream/connman.git] / client / commands.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2012-2013  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This program is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU General Public License for more details.
16  *
17  *  You should have received a copy of the GNU General Public License
18  *  along with this program; if not, write to the Free Software
19  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  *
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <getopt.h>
32 #include <stdbool.h>
33
34 #include <glib.h>
35 #include <gdbus.h>
36
37 #include "services.h"
38 #include "technology.h"
39 #include "data_manager.h"
40 #include "interactive.h"
41
42 #include "dbus_helpers.h"
43 #include "input.h"
44
45 #define MANDATORY_ARGS 3
46
47 static char *ipv4[] = {
48         "Method",
49         "Address",
50         "Netmask",
51         "Gateway",
52         NULL
53 };
54
55 static char *ipv6[] = {
56         "Method",
57         "Address",
58         "PrefixLength",
59         "Gateway",
60         "Privacy",
61         NULL
62 };
63
64 static char *proxy_simple[] = {
65         "Method",
66         "URL",
67         NULL
68 };
69
70 static int cmd_help(char *args[], int num, struct option *options);
71
72 static int parse_args(char *arg, struct option *options)
73 {
74         int i;
75
76         if (arg == NULL)
77                 return -1;
78
79         for (i = 0; options[i].name != NULL; i++) {
80                 if (strcmp(options[i].name, arg) == 0 ||
81                                 (strncmp(arg, "--", 2) == 0 &&
82                                         strcmp(&arg[2], options[i].name) == 0))
83                         return options[i].val;
84         }
85
86         return '?';
87 }
88
89 static int cmd_enable(char *args[], int num, struct option *options)
90 {
91         DBusMessage *message;
92         int err;
93
94         if (num > 2)
95                 return -E2BIG;
96
97         if (num < 2)
98                 return -EINVAL;
99
100         if (strcmp(args[1], "offlinemode") == 0) {
101                 err = set_manager(connection, "OfflineMode", TRUE);
102                 if (err == 0)
103                         printf("OfflineMode enabled\n");
104
105                 return 0;
106         }
107
108         message = get_message(connection, "GetTechnologies");
109         if (message == NULL)
110                 return -ENOMEM;
111
112         set_technology(connection, message, "Powered", args[1], TRUE);
113
114         return 0;
115 }
116
117 static int cmd_disable(char *args[], int num, struct option *options)
118 {
119         DBusMessage *message;
120         int err;
121
122         if (num > 2)
123                 return -E2BIG;
124
125         if (num < 2)
126                 return -EINVAL;
127
128         if (strcmp(args[1], "offlinemode") == 0) {
129                 err = set_manager(connection, "OfflineMode", FALSE);
130                 if (err == 0)
131                         printf("OfflineMode enabled\n");
132
133                 return 0;
134         }
135
136         message = get_message(connection, "GetTechnologies");
137         if (message == NULL)
138                 return -ENOMEM;
139
140         set_technology(connection, message, "Powered", args[1], FALSE);
141
142         return 0;
143 }
144
145 static int cmd_state(char *args[], int num, struct option *options)
146 {
147         if (num > 1)
148                 return -E2BIG;
149
150         return list_properties(connection, "GetProperties", NULL);
151 }
152
153 static int cmd_services(char *args[], int num, struct option *options)
154 {
155         char *service_name = NULL;
156         int err = 0;
157         int c;
158         DBusMessage *message;
159
160         if (num > 3)
161                 return -E2BIG;
162
163         c = parse_args(args[1], options);
164         switch (c) {
165         case -1:
166                 break;
167         case 'p':
168                 if (num < 3)
169                         return -EINVAL;
170                 service_name = args[2];
171                 break;
172         default:
173                 if (num > 2)
174                         return -E2BIG;
175                 service_name = args[1];
176                 break;
177         }
178
179         message = get_message(connection, "GetServices");
180         if (message == NULL)
181                 return -ENOMEM;
182
183         err = list_properties(connection, "GetServices", service_name);
184         dbus_message_unref(message);
185
186         return err;
187 }
188
189 static int cmd_technologies(char *args[], int num, struct option *options)
190 {
191         if (num > 1)
192                 return -E2BIG;
193
194         return list_properties(connection, "GetTechnologies", NULL);
195 }
196
197 static int cmd_scan(char *args[], int num, struct option *options)
198 {
199         DBusMessage *message;
200         int err;
201
202         if (num > 2)
203                 return -E2BIG;
204
205         if (num < 2)
206                 return -EINVAL;
207
208         message = get_message(connection, "GetTechnologies");
209         if (message == NULL)
210                 err = -ENOMEM;
211         else {
212                 err = scan_technology(connection, message, args[1]);
213                 if (err == 0)
214                         printf("Scan completed\n");
215         }
216
217         return 0;
218 }
219
220 static int cmd_connect(char *args[], int num, struct option *options)
221 {
222         int err;
223
224         if (num > 2)
225                 return -E2BIG;
226
227         if (num < 2)
228                 return -EINVAL;
229
230         err = connect_service(connection, args[1]);
231         if (err == 0)
232                 printf("Connected\n");
233
234         return 0;
235 }
236
237 static int cmd_disconnect(char *args[], int num, struct option *options)
238 {
239         int err;
240
241         if (num > 2)
242                 return -E2BIG;
243
244         if (num < 2)
245                 return -EINVAL;
246
247         err = disconnect_service(connection, args[1]);
248         if (err == 0)
249                 printf("Disconnected\n");
250
251         return 0;
252 }
253
254 static int cmd_config(char *args[], int num, struct option *options)
255 {
256         int res = 0, index = 2, oldindex = 0;
257         int c;
258         char *service_name;
259         DBusMessage *message;
260         char **opt_start;
261         dbus_bool_t val;
262
263         service_name = args[1];
264         if (service_name == NULL)
265                 return -EINVAL;
266
267         while (index < num && args[index] != NULL) {
268                 c = parse_args(args[index], options);
269                 opt_start = &args[index + 1];
270                 res = 0;
271
272                 message = get_message(connection, "GetServices");
273                 if (message == NULL)
274                         return -ENOMEM;
275
276                 oldindex = index;
277
278                 switch (c) {
279                 case 'a':
280                         switch (parse_boolean(*opt_start)) {
281                         case 1:
282                                 val = TRUE;
283                                 break;
284                         case 0:
285                                 val = FALSE;
286                                 break;
287                         default:
288                                 res = -EINVAL;
289                                 break;
290                         }
291                         if (res == 0)
292                                 res = set_service_property(connection, message,
293                                                 service_name, "AutoConnect",
294                                                 NULL, &val, 0);
295                         break;
296                 case 'i':
297                         res = set_service_property(connection, message,
298                                         service_name, "IPv4.Configuration",
299                                         ipv4, opt_start, 0);
300                         if (res < 0)
301                                 index += 4;
302                         break;
303                 case 'v':
304                         res = set_service_property(connection, message,
305                                         service_name, "IPv6.Configuration",
306                                         ipv6, opt_start, 0);
307                         if (res < 0)
308                                 index += 5;
309                         break;
310                 case 'n':
311                         res = set_service_property(connection, message,
312                                         service_name,
313                                         "Nameservers.Configuration",
314                                         NULL, opt_start, 0);
315                         break;
316                 case 't':
317                         res = set_service_property(connection, message,
318                                         service_name,
319                                         "Timeservers.Configuration",
320                                         NULL, opt_start, 0);
321                         break;
322                 case 'd':
323                         res = set_service_property(connection, message,
324                                         service_name,
325                                         "Domains.Configuration",
326                                         NULL, opt_start, 0);
327                         break;
328                 case 'x':
329                         if (*opt_start == NULL) {
330                                 res = -EINVAL;
331                                 break;
332                         }
333
334                         if (strcmp(*opt_start, "direct") == 0) {
335                                 res = set_service_property(connection, message,
336                                                 service_name,
337                                                 "Proxy.Configuration",
338                                                 proxy_simple, opt_start, 1);
339                                 break;
340                         }
341
342                         if (strcmp(*opt_start, "auto") == 0) {
343                                 res = set_service_property(connection, message,
344                                                 service_name,
345                                                 "Proxy.Configuration",
346                                                 proxy_simple, opt_start, 1);
347                                 break;
348                         }
349
350                         if (strcmp(*opt_start, "manual") == 0) {
351                                         char **url_start = &args[index + 2];
352
353                                         if (*url_start != NULL &&
354                                                 strcmp(*url_start,
355                                                         "servers") == 0) {
356                                                 url_start = &args[index + 3];
357                                                 index++;
358                                         }
359                                         res = store_proxy_input(connection,
360                                                         message, service_name,
361                                                         0, url_start);
362                         }
363
364                         break;
365                 case 'r':
366                         res = remove_service(connection, message, service_name);
367                         break;
368                 default:
369                         res = -EINVAL;
370                         break;
371                 }
372
373                 dbus_message_unref(message);
374
375                 if (res < 0) {
376                         printf("Error '%s': %s\n", args[oldindex],
377                                         strerror(-res));
378                 } else
379                         index += res;
380
381                 index++;
382         }
383
384         return 0;
385 }
386
387 static DBusHandlerResult monitor_changed(DBusConnection *connection,
388                 DBusMessage *message, void *user_data)
389 {
390         DBusMessageIter iter;
391         const char *interface, *path;
392
393         interface = dbus_message_get_interface(message);
394         if (strncmp(interface, "net.connman.", 12) != 0)
395                 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
396
397         interface = strrchr(interface, '.');
398         if (interface != NULL && *interface != '\0')
399                 interface++;
400
401         path = strrchr(dbus_message_get_path(message), '/');
402         if (path != NULL && *path != '\0')
403                 path++;
404
405         if (dbus_message_is_signal(message, "net.connman.Manager",
406                                         "ServicesChanged") == TRUE) {
407
408                 fprintf(stdout, "%-12s %-20s = {\n", interface,
409                                 "ServicesChanged");
410                 dbus_message_iter_init(message, &iter);
411                 __connmanctl_services_list(&iter);
412                 fprintf(stdout, "\n}\n");
413
414                 __connmanctl_redraw_rl();
415
416                 return DBUS_HANDLER_RESULT_HANDLED;
417         }
418
419         if (dbus_message_is_signal(message, "net.connman.Manager",
420                                         "TechnologyAdded") == TRUE)
421                 path = "TechnologyAdded";
422
423         if (dbus_message_is_signal(message, "net.connman.Manager",
424                                         "TechnologyRemoved") == TRUE)
425                 path = "TechnologyRemoved";
426
427         fprintf(stdout, "%-12s %-20s ", interface, path);
428         dbus_message_iter_init(message, &iter);
429
430         __connmanctl_dbus_print(&iter, "", " = ", " = ");
431         fprintf(stdout, "\n");
432
433         return DBUS_HANDLER_RESULT_HANDLED;
434 }
435
436 static bool monitor_s = false;
437 static bool monitor_t = false;
438 static bool monitor_m = false;
439
440 static void monitor_add(char *interface)
441 {
442         char *rule;
443         DBusError err;
444
445         if (monitor_s == false && monitor_t == false && monitor_m == false)
446                 dbus_connection_add_filter(connection, monitor_changed,
447                                 NULL, NULL);
448
449         if (g_strcmp0(interface, "Service") == 0) {
450                 if (monitor_s == true)
451                         return;
452                 monitor_s = true;
453         } else if (g_strcmp0(interface, "Technology") == 0) {
454                 if (monitor_t == true)
455                         return;
456                 monitor_t = true;
457         } else if (g_strcmp0(interface, "Manager") == 0) {
458                 if (monitor_m == true)
459                         return;
460                 monitor_m = true;
461         } else
462                 return;
463
464         dbus_error_init(&err);
465         rule  = g_strdup_printf("type='signal',interface='net.connman.%s'",
466                         interface);
467         dbus_bus_add_match(connection, rule, &err);
468         g_free(rule);
469
470         if (dbus_error_is_set(&err))
471                 fprintf(stderr, "Error: %s\n", err.message);
472 }
473
474 static void monitor_del(char *interface)
475 {
476         char *rule;
477
478         if (g_strcmp0(interface, "Service") == 0) {
479                 if (monitor_s == false)
480                         return;
481                 monitor_s = false;
482         } else if (g_strcmp0(interface, "Technology") == 0) {
483                 if (monitor_t == false)
484                         return;
485                 monitor_t = false;
486         } else if (g_strcmp0(interface, "Manager") == 0) {
487                 if (monitor_m == false)
488                         return;
489                 monitor_m = false;
490         } else
491                 return;
492
493         rule  = g_strdup_printf("type='signal',interface='net.connman.%s'",
494                         interface);
495         dbus_bus_remove_match(connection, rule, NULL);
496         g_free(rule);
497
498         if (monitor_s == false && monitor_t == false && monitor_m == false)
499                 dbus_connection_remove_filter(connection, monitor_changed,
500                                 NULL);
501 }
502
503 static int cmd_monitor(char *args[], int num, struct option *options)
504 {
505         bool add = true;
506         int c;
507
508         if (num > 3)
509                 return -E2BIG;
510
511         if (num == 3) {
512                 switch (parse_boolean(args[2])) {
513                 case 0:
514                         add = false;
515                         break;
516
517                 default:
518                         break;
519                 }
520         }
521
522         c = parse_args(args[1], options);
523         switch (c) {
524         case -1:
525                 monitor_add("Service");
526                 monitor_add("Technology");
527                 monitor_add("Manager");
528                 break;
529
530         case 's':
531                 if (add == true)
532                         monitor_add("Service");
533                 else
534                         monitor_del("Service");
535                 break;
536
537         case 'c':
538                 if (add == true)
539                         monitor_add("Technology");
540                 else
541                         monitor_del("Technology");
542                 break;
543
544         case 'm':
545                 if (add == true)
546                         monitor_add("Manager");
547                 else
548                         monitor_del("Manager");
549                 break;
550
551         default:
552                 switch(parse_boolean(args[1])) {
553                 case 0:
554                         monitor_del("Service");
555                         monitor_del("Technology");
556                         monitor_del("Manager");
557                         break;
558
559                 case 1:
560                         monitor_add("Service");
561                         monitor_add("Technology");
562                         monitor_add("Manager");
563                         break;
564
565                 default:
566                         return -EINVAL;
567                 }
568         }
569
570         if (add == true)
571                 return -EINPROGRESS;
572
573         return 0;
574 }
575
576 static int cmd_exit(char *args[], int num, struct option *options)
577 {
578         return 0;
579 }
580
581 static struct option service_options[] = {
582         {"properties", required_argument, 0, 'p'},
583         { NULL, }
584 };
585
586 static const char *service_desc[] = {
587         "[<service>]      (obsolete)",
588         NULL
589 };
590
591 static struct option config_options[] = {
592         {"nameservers", required_argument, 0, 'n'},
593         {"timeservers", required_argument, 0, 't'},
594         {"domains", required_argument, 0, 'd'},
595         {"ipv6", required_argument, 0, 'v'},
596         {"proxy", required_argument, 0, 'x'},
597         {"autoconnect", required_argument, 0, 'a'},
598         {"ipv4", required_argument, 0, 'i'},
599         {"remove", 0, 0, 'r'},
600         { NULL, }
601 };
602
603 static const char *config_desc[] = {
604         "<dns1> [<dns2>] [<dns3>]",
605         "<ntp1> [<ntp2>] [...]",
606         "<domain1> [<domain2>] [...]",
607         "off|auto|manual <address> <prefixlength> <gateway> <privacy>",
608         "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
609         "                   [exclude <exclude1> [<exclude2>] [...]]",
610         "yes|no",
611         "off|dhcp|manual <address> <prefixlength> <gateway>",
612         "                 Remove service",
613         NULL
614 };
615
616 static struct option monitor_options[] = {
617         {"services", no_argument, 0, 's'},
618         {"tech", no_argument, 0, 'c'},
619         {"manager", no_argument, 0, 'm'},
620         { NULL, }
621 };
622
623 static const char *monitor_desc[] = {
624         "[off]            Monitor only services",
625         "[off]            Monitor only technologies",
626         "[off]            Monitor only manager interface",
627         NULL
628 };
629
630 static const struct {
631         const char *cmd;
632         const char *argument;
633         struct option *options;
634         const char **options_desc;
635         int (*func) (char *args[], int num, struct option *options);
636         const char *desc;
637 } cmd_table[] = {
638         { "enable",       "<technology>|offline", NULL,    NULL,
639           cmd_enable, "Enables given technology or offline mode" },
640         { "disable",      "<technology>|offline", NULL,    NULL,
641           cmd_disable, "Disables given technology or offline mode"},
642         { "state",        NULL,           NULL,            NULL,
643           cmd_state, "Shows if the system is online or offline" },
644         { "services",     "[<service>]",  service_options, &service_desc[0],
645           cmd_services, "Display services" },
646         { "technologies", NULL,           NULL,            NULL,
647           cmd_technologies, "Display technologies" },
648         { "scan",         "<technology>", NULL,            NULL,
649           cmd_scan, "Scans for new services for given technology" },
650         { "connect",      "<service>",    NULL,            NULL,
651           cmd_connect, "Connect a given service" },
652         { "disconnect",   "<service>",    NULL,            NULL,
653           cmd_disconnect, "Disconnect a given service" },
654         { "config",       "<service>",    config_options,  &config_desc[0],
655           cmd_config, "Set service configuration options" },
656         { "monitor",      "[off]",        monitor_options, &monitor_desc[0],
657           cmd_monitor, "Monitor signals from interfaces" },
658         { "help",         NULL,           NULL,            NULL,
659           cmd_help, "Show help" },
660         { "exit",         NULL,           NULL,            NULL,
661           cmd_exit,       "Exit" },
662         { "quit",         NULL,           NULL,            NULL,
663           cmd_exit,       "Quit" },
664         {  NULL, },
665 };
666
667 static int cmd_help(char *args[], int num, struct option *options)
668 {
669         int i, j;
670
671         for (i = 0; cmd_table[i].cmd != NULL; i++) {
672                 const char *cmd = cmd_table[i].cmd;
673                 const char *argument = cmd_table[i].argument;
674                 const char *desc = cmd_table[i].desc;
675
676                 printf("%-12s%-22s%s\n", cmd != NULL? cmd: "",
677                                 argument != NULL? argument: "",
678                                 desc != NULL? desc: "");
679
680                 if (cmd_table[i].options != NULL) {
681                         for (j = 0; cmd_table[i].options[j].name != NULL;
682                              j++) {
683                                 const char *options_desc =
684                                         cmd_table[i].options_desc != NULL ?
685                                         cmd_table[i].options_desc[j]: "";
686
687                                 printf("   --%-12s%s\n",
688                                                 cmd_table[i].options[j].name,
689                                                 options_desc);
690                         }
691                 }
692         }
693
694         return 0;
695 }
696
697 int commands(DBusConnection *connection, char *argv[], int argc)
698 {
699         int i, result;
700
701         for (i = 0; cmd_table[i].cmd != NULL; i++) {
702                 if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
703                                 cmd_table[i].func != NULL) {
704                         result = cmd_table[i].func(argv, argc,
705                                         cmd_table[i].options);
706                         if (result < 0)
707                                 printf("Error '%s': %s\n", argv[0],
708                                                 strerror(-result));
709                         return result;
710                 }
711         }
712
713         return -1;
714 }