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