client: Enter interactive shell when no command is specified
[platform/upstream/connman.git] / client / commands.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2012  Intel Corporation. All rights reserved.
6  *  it under the terms of the GNU General Public License version 2 as
7  *  published by the Free Software Foundation.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <getopt.h>
25
26 #include <glib.h>
27 #include <gdbus.h>
28
29 #include "client/services.h"
30 #include "client/technology.h"
31 #include "client/data_manager.h"
32 #include "client/monitor.h"
33 #include "client/interactive.h"
34 #include "gdbus/gdbus.h"
35
36 #define MANDATORY_ARGS 3
37
38 static char *ipv4[] = {
39         "Method",
40         "Address",
41         "Netmask",
42         "Gateway",
43         NULL
44 };
45
46 static char *ipv6[] = {
47         "Method",
48         "Address",
49         "PrefixLength",
50         "Gateway",
51         "Privacy",
52         NULL
53 };
54
55 static char *proxy_simple[] = {
56         "Method",
57         "URL",
58         NULL
59 };
60
61 void show_help(void)
62 {
63         printf("Usage: connmanctl <command> [args]\n"
64         "  enable                             Enables given technology\n"
65         "        <technology>\n"
66         "        offlinemode                  Enables OfflineMode\n"
67         "  disable                            Disables given technology\n"
68         "        <technology>\n"
69         "        offlinemode                  Disables OfflineMode\n"
70         "  state                              Shows if the system is online or offline\n"
71         "  services                           Display list of all services\n"
72         "        --properties <service name>  Show properties of service\n"
73         "  technologies                       Current technology on the system\n"
74         "  scan <technology>                  Scans for new services on the given technology\n"
75         "  connect <service>                  Connect to a given service\n"
76         "  disconnect <service>               Disconnect from service\n"
77         "  config <service> [arg]             Set certain config options\n"
78         "        --autoconnect=y/n            Set autoconnect to service\n"
79         "        --nameservers <names>        Set manual name servers\n"
80         "        --timeservers <names>        Set manual time servers\n"
81         "        --domains <domains>          Set manual domains\n"
82         "        --ipv4                       Set ipv4 configuration\n"
83         "          [METHOD|DHCP|AUTO|MANUAL] [IP] [NETMASK] [GATEWAY]\n"
84         "        --ipv6                       Set ipv6 configuration\n"
85         "          [METHOD|AUTO|MANUAL|OFF] [IP] [PREFIXLENGTH] [GATEWAY]\n"
86         "          [PRIVACY|DISABLED|ENABLED|PREFERED]\n"
87         "        --proxy                      Set proxy configuration\n"
88         "          [METHOD|URL|SERVERS|EXCLUDES]\n"
89         "          if METHOD = manual, enter 'servers' then the list of servers\n"
90         "                         then enter 'excludes' then the list of excludes\n"
91         "  monitor                            Monitor signals from all Connman interfaces\n"
92         "        --services                   Monitor signals from the Service interface\n"
93         "        --tech                       Monitor signals from the Technology interface\n"
94         "        --manager                    Monitor signals from the Manager interface\n"
95         "  help, --help, (no arguments)       Show this dialogue\n"
96         "  exit, quit, q                      Quit interactive mode\n"
97         "\nNote: arguments and output are considered EXPERIMENTAL for now.\n\n");
98 }
99
100 int service_switch(int argc, char *argv[], int c, DBusConnection *conn,
101                                                 struct service_data *service)
102 {
103         const char *name;
104         DBusMessage *message;
105         int error;
106
107         message = get_message(conn, "GetServices");
108
109         switch (c) {
110         case 'p':
111                 name = find_service(conn, message, argv[2], service);
112                 if (name == NULL)
113                         return -ENXIO;
114                 error = list_properties(conn, "GetServices", (char *) name);
115                 if (error != 0)
116                         return error;
117                 break;
118         default:
119                 fprintf(stderr, "Command not recognized, please check help\n");
120                 return -EINVAL;
121                 break;
122         }
123         return 0;
124 }
125
126 int config_switch(int argc, char *argv[], int c, DBusConnection *conn)
127 {
128         DBusMessage *message;
129         int num_args = argc - MANDATORY_ARGS;
130         int error;
131         dbus_bool_t val;
132
133         message = get_message(conn, "GetServices");
134
135         switch (c) {
136         case 'a':
137                 if (*optarg != 'y' || *optarg != 'n' || *optarg != '1' ||
138                                         *optarg != '0' || *optarg != 't' ||
139                                                         *optarg != 'f')
140                         return -EINVAL;
141                 if (*optarg == 'y' || *optarg == '1' ||
142                                                 *optarg == 't')
143                         val = TRUE;
144                 else if (*optarg == 'n' || *optarg == '0' ||
145                                                 *optarg == 'f')
146                         val = FALSE;
147                 error = set_service_property(conn, message, argv[1],
148                                                 "AutoConnect", NULL,
149                                                 &val, 0);
150                 if (error != 0)
151                         return error;
152                 break;
153         case 'i':
154                 error = set_service_property(conn, message, argv[1],
155                                         "IPv4.Configuration", ipv4,
156                                         argv + MANDATORY_ARGS, num_args);
157                 if (error != 0)
158                         return error;
159                 break;
160         case 'v':
161                 error = set_service_property(conn, message, argv[1],
162                                         "IPv6.Configuration", ipv6,
163                                         argv + MANDATORY_ARGS, num_args);
164                 if (error != 0)
165                         return error;
166                 break;
167         case 'n':
168                 error = set_service_property(conn, message, argv[1],
169                                         "Nameservers.Configuration", NULL,
170                                         argv + MANDATORY_ARGS, num_args);
171                 if (error != 0)
172                         return error;
173                 break;
174         case 't':
175                 error = set_service_property(conn, message, argv[1],
176                                         "Timeservers.Configuration", NULL,
177                                         argv + MANDATORY_ARGS, num_args);
178                 if (error != 0)
179                         return error;
180                 break;
181         case 'd':
182                 error = set_service_property(conn, message, argv[1],
183                                         "Domains.Configuration", NULL,
184                                         argv + MANDATORY_ARGS, num_args);
185                 if (error != 0)
186                         return error;
187                 break;
188         case 'x':
189                 if ((strcmp(argv[3], "direct") == 0 && argc < 5) ||
190                         (strcmp(argv[3], "auto") == 0 && argc < 6)) {
191                         error = set_service_property(conn, message, argv[1],
192                                         "Proxy.Configuration", proxy_simple,
193                                         argv + MANDATORY_ARGS, num_args);
194                         if (error != 0)
195                                 return error;
196                 } else if (strcmp(argv[3], "manual") == 0
197                                   && strcmp(argv[4], "servers") == 0
198                                   && argc > 5) {
199                         argc -= 5;
200                         error = store_proxy_input(conn, message, argv[1],
201                                                                 argc, &argv[5]);
202                         if (error != 0)
203                                 return error;
204                 } else {
205                         fprintf(stderr, "Incorrect arguments\n");
206                         return -EINVAL;
207                 }
208                 break;
209         default:
210                 fprintf(stderr, "Command not recognized, please check help\n");
211                 return -EINVAL;
212                 break;
213         }
214         return 0;
215 }
216
217 int monitor_switch(int argc, char *argv[], int c, DBusConnection *conn)
218 {
219         int error;
220
221         switch (c) {
222         case 's':
223                 error = monitor_connman(conn, "Service", "PropertyChanged");
224                 if (error != 0)
225                         return error;
226                 if (dbus_connection_add_filter(conn, service_property_changed,
227                                                         NULL, NULL) == FALSE)
228                         return -ENOMEM;
229                 printf("Now monitoring the service interface.\n");
230                 break;
231         case 'c':
232                 error = monitor_connman(conn, "Technology", "PropertyChanged");
233                 if (error != 0)
234                         return error;
235                 if (dbus_connection_add_filter(conn, tech_property_changed,
236                                                         NULL, NULL) == FALSE)
237                         return -ENOMEM;
238                 printf("Now monitoring the technology interface.\n");
239                 break;
240         case 'm':
241                 error = monitor_connman(conn, "Manager", "PropertyChanged");
242                 if (error != 0)
243                         return error;
244                 error = monitor_connman(conn, "Manager", "TechnologyAdded");
245                 if (error != 0)
246                         return error;
247                 error = monitor_connman(conn, "Manager", "TechnologyRemoved");
248                 if (error != 0)
249                         return error;
250                 error = monitor_connman(conn, "Manager", "ServicesChanged");
251                 if (error != 0)
252                         return error;
253                 if (dbus_connection_add_filter(conn, manager_property_changed,
254                                                         NULL, NULL) == FALSE)
255                         return -ENOMEM;
256                 if (dbus_connection_add_filter(conn, tech_added_removed,
257                                                         NULL, NULL) == FALSE)
258                         return -ENOMEM;
259                 if (dbus_connection_add_filter(conn, manager_services_changed,
260                                                         NULL, NULL) == FALSE)
261                         return -ENOMEM;
262                 printf("Now monitoring the manager interface.\n");
263                 break;
264         default:
265                 fprintf(stderr, "Command not recognized, please check help\n");
266                 return -EINVAL;
267                 break;
268         }
269         return 0;
270 }
271
272 int commands_no_options(DBusConnection *connection, char *argv[], int argc)
273 {
274         int error;
275         DBusMessage *message;
276
277
278         if (strcmp(argv[0], "--help") == 0 || strcmp(argv[0], "help") == 0  ||
279                                                 strcmp(argv[0], "h") == 0) {
280                 show_help();
281         } else if (strcmp(argv[0], "state") == 0) {
282                 if (argc != 1) {
283                         fprintf(stderr, "State cannot accept an argument, "
284                                                                 "see help\n");
285                         return -EINVAL;
286                 }
287                 error = list_properties(connection, "GetProperties", NULL);
288                 if (error != 0)
289                         return error;
290         } else if (strcmp(argv[0], "technologies") == 0) {
291                 if (argc != 1) {
292                         fprintf(stderr, "Tech cannot accept an argument, "
293                                                                 "see help\n");
294                         return -EINVAL;
295                 }
296                 error = list_properties(connection, "GetTechnologies", NULL);
297                 if (error != 0)
298                         return error;
299         } else if (strcmp(argv[0], "connect") == 0) {
300                 if (argc != 2) {
301                         fprintf(stderr, "Connect requires a service name or "
302                                                         "path, see help\n");
303                         return -EINVAL;
304                 }
305                 error = connect_service(connection, strip_service_path(argv[1]));
306                 if (error != 0)
307                         return error;
308                 printf("Connected to: %s\n", strip_service_path(argv[1]));
309         } else if (strcmp(argv[0], "disconnect") == 0) {
310                 if (argc != 2) {
311                         fprintf(stderr, "Disconnect requires a service name or "
312                                                         "path, see help\n");
313                         return -EINVAL;
314                 }
315                 error = disconnect_service(connection, strip_service_path(argv[1]));
316                 if (error != 0)
317                         return error;
318                 printf("Disconnected from: %s\n", strip_service_path(argv[1]));
319         } else if (strcmp(argv[0], "scan") == 0) {
320                 if (argc != 2) {
321                         fprintf(stderr, "Scan requires a service name or path, "
322                                                                 "see help\n");
323                         return -EINVAL;
324                 }
325                 message = get_message(connection, "GetTechnologies");
326                 error = scan_technology(connection, message, argv[1]);
327                 if (error != 0)
328                         return error;
329                 dbus_message_unref(message);
330         } else if (strcmp(argv[0], "enable") == 0) {
331                 if (argc != 2) {
332                         fprintf(stderr, "Enable requires a technology name or "
333                                 "the argument 'offlinemode', see help\n");
334                         return -EINVAL;
335                 }
336                 if (strcmp(argv[1], "offlinemode") == 0) {
337                         error = set_manager(connection, "OfflineMode", TRUE);
338                         if (error != 0)
339                                 return error;
340                         printf("OfflineMode is now enabled\n");
341                 } else {
342                         message = get_message(connection, "GetTechnologies");
343                         error = set_technology(connection, message, "Powered",
344                                                         argv[1], TRUE);
345                         if (error != 0)
346                                 return error;
347                         printf("Enabled %s technology\n", argv[1]);
348                         dbus_message_unref(message);
349                 }
350         } else if (strcmp(argv[0], "disable") == 0) {
351                 if (argc != 2) {
352                         fprintf(stderr, "Disable requires a technology name or "
353                                 "the argument 'offlinemode' see help\n");
354                         return -EINVAL;
355                 }
356                 if (strcmp(argv[1], "offlinemode") == 0) {
357                         error = set_manager(connection, "OfflineMode", FALSE);
358                         if (error != 0)
359                                 return error;
360                         printf("OfflineMode is now disabled\n");
361                 } else {
362                         message = get_message(connection, "GetTechnologies");
363                         error = set_technology(connection, message, "Powered",
364                                                         argv[1], FALSE);
365                         if (error != 0)
366                                 return error;
367                         printf("Disabled %s technology\n", argv[1]);
368                         dbus_message_unref(message);
369                 }
370         } else
371                 return -1;
372         return 0;
373 }
374
375 int commands_options(DBusConnection *connection, char *argv[], int argc)
376 {
377         int error, c;
378         int option_index = 0;
379         struct service_data service;
380
381         static struct option service_options[] = {
382                 {"properties", required_argument, 0, 'p'},
383                 {0, 0, 0, 0}
384         };
385
386         static struct option config_options[] = {
387                 {"nameservers", required_argument, 0, 'n'},
388                 {"timeservers", required_argument, 0, 't'},
389                 {"domains", required_argument, 0, 'd'},
390                 {"ipv6", required_argument, 0, 'v'},
391                 {"proxy", required_argument, 0, 'x'},
392                 {"autoconnect", required_argument, 0, 'a'},
393                 {"ipv4", required_argument, 0, 'i'},
394                 {0, 0, 0, 0}
395         };
396
397         static struct option monitor_options[] = {
398                 {"services", no_argument, 0, 's'},
399                 {"tech", no_argument, 0, 'c'},
400                 {"manager", no_argument, 0, 'm'},
401                 {0, 0, 0, 0}
402         };
403
404         if (strcmp(argv[0], "services") == 0) {
405                 if (argc > 3) {
406                         fprintf(stderr, "Too many arguments for services, "
407                                                                 "see help\n");
408                         return -EINVAL;
409                 }
410                 if (argc < 2) {
411                         printf("List of all services:\n");
412                         error = list_properties(connection, "GetServices", NULL);
413                         if (error != 0)
414                                 return error;
415                 } else {
416                         while ((c = getopt_long(argc, argv, "", service_options,
417                                                 &option_index))) {
418                                 if (c == -1) {
419                                         if (option_index == 0) {
420                                                 printf("Services takes an "
421                                                         "option, see help.\n");
422                                                 return -EINVAL;
423                                         }
424                                         break;
425                                 }
426                                 error = service_switch(argc, argv, c,
427                                                                 connection,
428                                                                 &service);
429                                 if (error != 0)
430                                         return error;
431                                 option_index++;
432                         }
433                 }
434         } else if (strcmp(argv[0], "config") == 0) {
435                 if (argc < 3) {
436                         fprintf(stderr, "Config requires an option, "
437                                                                 "see help\n");
438                         return -EINVAL;
439                 }
440                 while ((c = getopt_long(argc, argv, "", config_options,
441                                                         &option_index))) {
442                         if (c == -1) {
443                                 if (option_index == 0) {
444                                         printf("Config requires an option, "
445                                                         "see help\n");
446                                         return -EINVAL;
447                                 }
448                                 break;
449                         }
450                         error = config_switch(argc, argv, c, connection);
451                         if (error != 0)
452                                 return error;
453                         option_index++;
454                 }
455         } else if (strcmp(argv[0], "monitor") == 0) {
456                 if (argc > 2) {
457                         fprintf(stderr, "Too many arguments for monitor, "
458                                                                 "see help\n");
459                         return -EINVAL;
460                 }
461                 if (argc < 2) {
462                         error = monitor_connman(connection, "Service",
463                                                         "PropertyChanged");
464                         if (error != 0)
465                                 return error;
466                         error = monitor_connman(connection, "Technology",
467                                                         "PropertyChanged");
468                         if (error != 0)
469                                 return error;
470                         error = monitor_connman(connection, "Manager",
471                                                         "PropertyChanged");
472                         if (error != 0)
473                                 return error;
474                         error = monitor_connman(connection, "Manager",
475                                                         "TechnologyAdded");
476                         if (error != 0)
477                                 return error;
478                         error = monitor_connman(connection, "Manager",
479                                                         "TechnologyRemoved");
480                         if (error != 0)
481                                 return error;
482                         error = monitor_connman(connection, "Manager",
483                                                         "ServicesChanged");
484                         if (error != 0)
485                                 return error;
486                         if (dbus_connection_add_filter(connection,
487                                         service_property_changed, NULL, NULL)
488                                                                 == FALSE)
489                                 return -ENOMEM;
490                         if (dbus_connection_add_filter(connection,
491                                         tech_property_changed, NULL, NULL)
492                                                                 == FALSE)
493                                 return -ENOMEM;
494                         if (dbus_connection_add_filter(connection,
495                                         tech_added_removed, NULL, NULL)
496                                                                 == FALSE)
497                                 return -ENOMEM;
498                         if (dbus_connection_add_filter(connection,
499                                         manager_property_changed, NULL, NULL)
500                                                                 == FALSE)
501                                 return -ENOMEM;
502                         if (dbus_connection_add_filter(connection,
503                                         manager_services_changed, NULL, NULL)
504                                                                 == FALSE)
505                                 return -ENOMEM;
506                         printf("Now monitoring all interfaces.\n");
507                 } else
508                         while ((c = getopt_long(argc, argv, "", monitor_options,
509                                                         &option_index))) {
510                                 if (c == -1) {
511                                         if (option_index == 0) {
512                                                 printf("Monitor takes an "
513                                                         "option, see help\n");
514                                                 return -EINVAL;
515                                         }
516                                         break;
517                                 }
518                                 error = monitor_switch(argc, argv, c, connection);
519                                 if (error != 0)
520                                         return error;
521                                 option_index++;
522                         }
523         } else
524                 return -1;
525         return 0;
526 }