5 * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
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.
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.
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
37 #include "dbus_helpers.h"
42 static DBusConnection *connection;
44 static char *ipv4[] = {
52 static char *ipv6[] = {
60 static int cmd_help(char *args[], int num, struct option *options);
62 static int parse_boolean(char *arg)
67 if (strcasecmp(arg, "no") == 0 ||
68 strcasecmp(arg, "false") == 0 ||
69 strcasecmp(arg, "off" ) == 0 ||
70 strcasecmp(arg, "disable" ) == 0 ||
71 strcasecmp(arg, "n") == 0 ||
72 strcasecmp(arg, "f") == 0 ||
73 strcasecmp(arg, "0") == 0)
76 if (strcasecmp(arg, "yes") == 0 ||
77 strcasecmp(arg, "true") == 0 ||
78 strcasecmp(arg, "on") == 0 ||
79 strcasecmp(arg, "enable" ) == 0 ||
80 strcasecmp(arg, "y") == 0 ||
81 strcasecmp(arg, "t") == 0 ||
82 strcasecmp(arg, "1") == 0)
88 static int parse_args(char *arg, struct option *options)
95 for (i = 0; options[i].name != NULL; i++) {
96 if (strcmp(options[i].name, arg) == 0 ||
97 (strncmp(arg, "--", 2) == 0 &&
98 strcmp(&arg[2], options[i].name) == 0))
99 return options[i].val;
105 static void enable_return(DBusMessageIter *iter, const char *error,
108 char *tech = user_data;
111 str = strrchr(tech, '/');
118 fprintf(stdout, "Enabled %s\n", str);
120 fprintf(stderr, "Error %s: %s\n", str, error);
125 static int cmd_enable(char *args[], int num, struct option *options)
128 dbus_bool_t b = TRUE;
136 if (strcmp(args[1], "offlinemode") == 0) {
137 tech = g_strdup(args[1]);
138 return __connmanctl_dbus_set_property(connection, "/",
139 "net.connman.Manager", enable_return, tech,
140 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
143 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
144 return __connmanctl_dbus_set_property(connection, tech,
145 "net.connman.Technology", enable_return, tech,
146 "Powered", DBUS_TYPE_BOOLEAN, &b);
149 static void disable_return(DBusMessageIter *iter, const char *error,
152 char *tech = user_data;
155 str = strrchr(tech, '/');
162 fprintf(stdout, "Disabled %s\n", str);
164 fprintf(stderr, "Error %s: %s\n", str, error);
169 static int cmd_disable(char *args[], int num, struct option *options)
172 dbus_bool_t b = FALSE;
180 if (strcmp(args[1], "offlinemode") == 0) {
181 tech = g_strdup(args[1]);
182 return __connmanctl_dbus_set_property(connection, "/",
183 "net.connman.Manager", disable_return, tech,
184 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
187 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
188 return __connmanctl_dbus_set_property(connection, tech,
189 "net.connman.Technology", disable_return, tech,
190 "Powered", DBUS_TYPE_BOOLEAN, &b);
193 static void state_print(DBusMessageIter *iter, const char *error,
196 DBusMessageIter entry;
199 fprintf(stderr, "Error: %s", error);
203 dbus_message_iter_recurse(iter, &entry);
204 __connmanctl_dbus_print(&entry, " ", " = ", "\n");
205 fprintf(stdout, "\n");
208 static int cmd_state(char *args[], int num, struct option *options)
213 return __connmanctl_dbus_method_call(connection, "/",
214 "net.connman.Manager", "GetProperties",
215 state_print, NULL, DBUS_TYPE_INVALID);
218 static void services_list(DBusMessageIter *iter, const char *error,
222 __connmanctl_services_list(iter);
223 fprintf(stdout, "\n");
225 fprintf(stderr, "Error: %s\n", error);
229 static void services_properties(DBusMessageIter *iter, const char *error,
232 char *path = user_data;
234 DBusMessageIter dict;
237 fprintf(stdout, "%s\n", path);
239 dbus_message_iter_recurse(iter, &dict);
240 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
242 fprintf(stdout, "\n");
245 str = strrchr(path, '/');
251 fprintf(stderr, "Error %s: %s\n", str, error);
257 static int cmd_services(char *args[], int num, struct option *options)
259 char *service_name = NULL;
266 c = parse_args(args[1], options);
273 service_name = args[2];
278 service_name = args[1];
282 if (service_name == NULL) {
283 return __connmanctl_dbus_method_call(connection, "/",
284 "net.connman.Manager", "GetServices",
285 services_list, NULL, DBUS_TYPE_INVALID);
288 path = g_strdup_printf("/net/connman/service/%s", service_name);
289 return __connmanctl_dbus_method_call(connection, path,
290 "net.connman.Service", "GetProperties",
291 services_properties, path, DBUS_TYPE_INVALID);
294 static void technology_print(DBusMessageIter *iter, const char *error,
297 DBusMessageIter array;
300 fprintf(stderr, "Error: %s\n", error);
304 dbus_message_iter_recurse(iter, &array);
305 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
306 DBusMessageIter entry, dict;
309 dbus_message_iter_recurse(&array, &entry);
310 dbus_message_iter_get_basic(&entry, &path);
311 fprintf(stdout, "%s\n", path);
313 dbus_message_iter_next(&entry);
315 dbus_message_iter_recurse(&entry, &dict);
316 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
317 fprintf(stdout, "\n");
319 dbus_message_iter_next(&array);
323 static int cmd_technologies(char *args[], int num, struct option *options)
328 return __connmanctl_dbus_method_call(connection, "/",
329 "net.connman.Manager", "GetTechnologies",
330 technology_print, NULL, DBUS_TYPE_INVALID);
333 static void scan_return(DBusMessageIter *iter, const char *error,
336 char *path = user_data;
339 char *str = strrchr(path, '/');
341 fprintf(stdout, "Scan completed for %s\n", str);
343 fprintf(stderr, "Error %s: %s", path, error);
348 static int cmd_scan(char *args[], int num, struct option *options)
358 path = g_strdup_printf("/net/connman/technology/%s", args[1]);
359 return __connmanctl_dbus_method_call(connection, path,
360 "net.connman.Technology", "Scan",
361 scan_return, path, DBUS_TYPE_INVALID);
364 static void connect_return(DBusMessageIter *iter, const char *error,
367 char *path = user_data;
370 char *str = strrchr(path, '/');
372 fprintf(stdout, "Connected %s\n", str);
374 fprintf(stderr, "Error %s: %s\n", path, error);
379 static int cmd_connect(char *args[], int num, struct option *options)
389 path = g_strdup_printf("/net/connman/service/%s", args[1]);
390 return __connmanctl_dbus_method_call(connection, path,
391 "net.connman.Service", "Connect",
392 connect_return, path, DBUS_TYPE_INVALID);
395 static void disconnect_return(DBusMessageIter *iter, const char *error,
398 char *path = user_data;
401 char *str = strrchr(path, '/');
403 fprintf(stdout, "Disconnected %s\n", str);
405 fprintf(stderr, "Error %s: %s\n", path, error);
410 static int cmd_disconnect(char *args[], int num, struct option *options)
420 path = g_strdup_printf("/net/connman/service/%s", args[1]);
421 return __connmanctl_dbus_method_call(connection, path,
422 "net.connman.Service", "Disconnect",
423 disconnect_return, path, DBUS_TYPE_INVALID);
428 static void config_return(DBusMessageIter *iter, const char *error,
431 char *service_name = user_data;
434 fprintf(stderr, "Error %s: %s\n", service_name, error);
439 struct config_append {
444 static void config_append_ipv4(DBusMessageIter *iter,
447 struct config_append *append = user_data;
448 char **opts = append->opts;
454 while (opts[i] != NULL && ipv4[i] != NULL) {
455 __connmanctl_dbus_append_dict_entry(iter, ipv4[i],
456 DBUS_TYPE_STRING, &opts[i]);
463 static void config_append_ipv6(DBusMessageIter *iter, void *user_data)
465 struct config_append *append = user_data;
466 char **opts = append->opts;
473 if (g_strcmp0(opts[0], "auto") == 0) {
476 switch (parse_boolean(opts[1])) {
481 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
482 DBUS_TYPE_STRING, &str);
489 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
490 DBUS_TYPE_STRING, &str);
494 if (opts[1] != NULL) {
497 if (g_strcmp0(opts[0], "prefered") != 0) {
498 fprintf(stderr, "Error %s: %s\n",
505 __connmanctl_dbus_append_dict_entry(iter,
506 "Privacy", DBUS_TYPE_STRING,
511 } else if (g_strcmp0(opts[0], "manual") == 0) {
514 while (opts[i] != NULL && ipv6[i] != NULL) {
516 int value = atoi(opts[i]);
517 __connmanctl_dbus_append_dict_entry(iter,
518 ipv6[i], DBUS_TYPE_BYTE,
521 __connmanctl_dbus_append_dict_entry(iter,
522 ipv6[i], DBUS_TYPE_STRING,
530 } else if (g_strcmp0(opts[0], "off") != 0) {
531 fprintf(stderr, "Error %s: %s\n", opts[0], strerror(-EINVAL));
536 __connmanctl_dbus_append_dict_entry(iter, "Method", DBUS_TYPE_STRING,
540 static void config_append_str(DBusMessageIter *iter, void *user_data)
542 struct config_append *append = user_data;
543 char **opts = append->opts;
549 while (opts[i] != NULL) {
550 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
558 static void append_servers(DBusMessageIter *iter, void *user_data)
560 struct config_append *append = user_data;
561 char **opts = append->opts;
567 while (opts[i] != NULL && g_strcmp0(opts[i], "--excludes") != 0) {
568 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
576 static void append_excludes(DBusMessageIter *iter, void *user_data)
578 struct config_append *append = user_data;
579 char **opts = append->opts;
580 int i = append->values;
582 if (opts == NULL || opts[i] == NULL ||
583 g_strcmp0(opts[i], "--excludes") != 0)
587 while (opts[i] != NULL) {
588 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
596 static void config_append_proxy(DBusMessageIter *iter, void *user_data)
598 struct config_append *append = user_data;
599 char **opts = append->opts;
604 if (g_strcmp0(opts[0], "manual") == 0) {
605 __connmanctl_dbus_append_dict_string_array(iter, "Servers",
606 append_servers, append);
608 __connmanctl_dbus_append_dict_string_array(iter, "Excludes",
609 append_excludes, append);
611 } else if (g_strcmp0(opts[0], "auto") == 0) {
612 if (opts[1] != NULL) {
613 __connmanctl_dbus_append_dict_entry(iter, "URL",
614 DBUS_TYPE_STRING, &opts[1]);
618 } else if (g_strcmp0(opts[0], "direct") != 0)
621 __connmanctl_dbus_append_dict_entry(iter, "Method",DBUS_TYPE_STRING,
627 static int cmd_config(char *args[], int num, struct option *options)
629 int result = 0, res = 0, index = 2, oldindex = 0;
631 char *service_name, *path;
634 struct config_append append;
636 service_name = args[1];
637 if (service_name == NULL)
640 while (index < num && args[index] != NULL) {
641 c = parse_args(args[index], options);
642 opt_start = &args[index + 1];
643 append.opts = opt_start;
649 path = g_strdup_printf("/net/connman/service/%s", service_name);
653 switch (parse_boolean(*opt_start)) {
668 res = __connmanctl_dbus_set_property(connection,
669 path, "net.connman.Service",
671 g_strdup(service_name),
673 DBUS_TYPE_BOOLEAN, &val);
677 res = __connmanctl_dbus_set_property_dict(connection,
678 path, "net.connman.Service",
679 config_return, g_strdup(service_name),
680 "IPv4.Configuration", DBUS_TYPE_STRING,
681 config_append_ipv4, &append);
682 index += append.values;
686 res = __connmanctl_dbus_set_property_dict(connection,
687 path, "net.connman.Service",
688 config_return, g_strdup(service_name),
689 "IPv6.Configuration", DBUS_TYPE_STRING,
690 config_append_ipv6, &append);
691 index += append.values;
695 res = __connmanctl_dbus_set_property_array(connection,
696 path, "net.connman.Service",
697 config_return, g_strdup(service_name),
698 "Nameservers.Configuration",
699 DBUS_TYPE_STRING, config_append_str,
701 index += append.values;
705 res = __connmanctl_dbus_set_property_array(connection,
706 path, "net.connman.Service",
707 config_return, g_strdup(service_name),
708 "Timeservers.Configuration",
709 DBUS_TYPE_STRING, config_append_str,
711 index += append.values;
715 res = __connmanctl_dbus_set_property_array(connection,
716 path, "net.connman.Service",
717 config_return, g_strdup(service_name),
718 "Domains.Configuration",
719 DBUS_TYPE_STRING, config_append_str,
721 index += append.values;
725 res = __connmanctl_dbus_set_property_dict(connection,
726 path, "net.connman.Service",
727 config_return, g_strdup(service_name),
728 "Proxy.Configuration",
729 DBUS_TYPE_STRING, config_append_proxy,
731 index += append.values;
734 res = __connmanctl_dbus_method_call(connection,
735 path, "net.connman.Service", "Remove",
736 config_return, g_strdup(service_name),
747 if (res == -EINPROGRESS)
748 result = -EINPROGRESS;
750 printf("Error '%s': %s\n", args[oldindex],
761 static DBusHandlerResult monitor_changed(DBusConnection *connection,
762 DBusMessage *message, void *user_data)
764 DBusMessageIter iter;
765 const char *interface, *path;
767 interface = dbus_message_get_interface(message);
768 if (strncmp(interface, "net.connman.", 12) != 0)
769 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
771 interface = strrchr(interface, '.');
772 if (interface != NULL && *interface != '\0')
775 path = strrchr(dbus_message_get_path(message), '/');
776 if (path != NULL && *path != '\0')
779 __connmanctl_save_rl();
781 if (dbus_message_is_signal(message, "net.connman.Manager",
782 "ServicesChanged") == TRUE) {
784 fprintf(stdout, "%-12s %-20s = {\n", interface,
786 dbus_message_iter_init(message, &iter);
787 __connmanctl_services_list(&iter);
788 fprintf(stdout, "\n}\n");
790 __connmanctl_redraw_rl();
792 return DBUS_HANDLER_RESULT_HANDLED;
795 if (dbus_message_is_signal(message, "net.connman.Manager",
796 "TechnologyAdded") == TRUE)
797 path = "TechnologyAdded";
799 if (dbus_message_is_signal(message, "net.connman.Manager",
800 "TechnologyRemoved") == TRUE)
801 path = "TechnologyRemoved";
803 fprintf(stdout, "%-12s %-20s ", interface, path);
804 dbus_message_iter_init(message, &iter);
806 __connmanctl_dbus_print(&iter, "", " = ", " = ");
807 fprintf(stdout, "\n");
809 __connmanctl_redraw_rl();
811 return DBUS_HANDLER_RESULT_HANDLED;
814 static bool monitor_s = false;
815 static bool monitor_t = false;
816 static bool monitor_m = false;
818 static void monitor_add(char *interface)
823 if (monitor_s == false && monitor_t == false && monitor_m == false)
824 dbus_connection_add_filter(connection, monitor_changed,
827 if (g_strcmp0(interface, "Service") == 0) {
828 if (monitor_s == true)
831 } else if (g_strcmp0(interface, "Technology") == 0) {
832 if (monitor_t == true)
835 } else if (g_strcmp0(interface, "Manager") == 0) {
836 if (monitor_m == true)
842 dbus_error_init(&err);
843 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
845 dbus_bus_add_match(connection, rule, &err);
848 if (dbus_error_is_set(&err))
849 fprintf(stderr, "Error: %s\n", err.message);
852 static void monitor_del(char *interface)
856 if (g_strcmp0(interface, "Service") == 0) {
857 if (monitor_s == false)
860 } else if (g_strcmp0(interface, "Technology") == 0) {
861 if (monitor_t == false)
864 } else if (g_strcmp0(interface, "Manager") == 0) {
865 if (monitor_m == false)
871 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
873 dbus_bus_remove_match(connection, rule, NULL);
876 if (monitor_s == false && monitor_t == false && monitor_m == false)
877 dbus_connection_remove_filter(connection, monitor_changed,
881 static int cmd_monitor(char *args[], int num, struct option *options)
890 switch (parse_boolean(args[2])) {
900 c = parse_args(args[1], options);
903 monitor_add("Service");
904 monitor_add("Technology");
905 monitor_add("Manager");
910 monitor_add("Service");
912 monitor_del("Service");
917 monitor_add("Technology");
919 monitor_del("Technology");
924 monitor_add("Manager");
926 monitor_del("Manager");
930 switch(parse_boolean(args[1])) {
932 monitor_del("Service");
933 monitor_del("Technology");
934 monitor_del("Manager");
938 monitor_add("Service");
939 monitor_add("Technology");
940 monitor_add("Manager");
954 static int cmd_exit(char *args[], int num, struct option *options)
959 static struct option service_options[] = {
960 {"properties", required_argument, 0, 'p'},
964 static const char *service_desc[] = {
965 "[<service>] (obsolete)",
969 static struct option config_options[] = {
970 {"nameservers", required_argument, 0, 'n'},
971 {"timeservers", required_argument, 0, 't'},
972 {"domains", required_argument, 0, 'd'},
973 {"ipv6", required_argument, 0, 'v'},
974 {"proxy", required_argument, 0, 'x'},
975 {"autoconnect", required_argument, 0, 'a'},
976 {"ipv4", required_argument, 0, 'i'},
977 {"remove", 0, 0, 'r'},
981 static const char *config_desc[] = {
982 "<dns1> [<dns2>] [<dns3>]",
983 "<ntp1> [<ntp2>] [...]",
984 "<domain1> [<domain2>] [...]",
985 "off|auto [enable|disable|prefered]|\n"
986 "\t\t\tmanual <address> <prefixlength> <gateway>",
987 "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
988 "\t\t\t[exclude <exclude1> [<exclude2>] [...]]",
990 "off|dhcp|manual <address> <prefixlength> <gateway>",
995 static struct option monitor_options[] = {
996 {"services", no_argument, 0, 's'},
997 {"tech", no_argument, 0, 'c'},
998 {"manager", no_argument, 0, 'm'},
1002 static const char *monitor_desc[] = {
1003 "[off] Monitor only services",
1004 "[off] Monitor only technologies",
1005 "[off] Monitor only manager interface",
1009 static const struct {
1011 const char *argument;
1012 struct option *options;
1013 const char **options_desc;
1014 int (*func) (char *args[], int num, struct option *options);
1017 { "enable", "<technology>|offline", NULL, NULL,
1018 cmd_enable, "Enables given technology or offline mode" },
1019 { "disable", "<technology>|offline", NULL, NULL,
1020 cmd_disable, "Disables given technology or offline mode"},
1021 { "state", NULL, NULL, NULL,
1022 cmd_state, "Shows if the system is online or offline" },
1023 { "services", "[<service>]", service_options, &service_desc[0],
1024 cmd_services, "Display services" },
1025 { "technologies", NULL, NULL, NULL,
1026 cmd_technologies, "Display technologies" },
1027 { "scan", "<technology>", NULL, NULL,
1028 cmd_scan, "Scans for new services for given technology" },
1029 { "connect", "<service>", NULL, NULL,
1030 cmd_connect, "Connect a given service" },
1031 { "disconnect", "<service>", NULL, NULL,
1032 cmd_disconnect, "Disconnect a given service" },
1033 { "config", "<service>", config_options, &config_desc[0],
1034 cmd_config, "Set service configuration options" },
1035 { "monitor", "[off]", monitor_options, &monitor_desc[0],
1036 cmd_monitor, "Monitor signals from interfaces" },
1037 { "help", NULL, NULL, NULL,
1038 cmd_help, "Show help" },
1039 { "exit", NULL, NULL, NULL,
1041 { "quit", NULL, NULL, NULL,
1046 static int cmd_help(char *args[], int num, struct option *options)
1048 bool interactive = __connmanctl_is_interactive();
1051 if (interactive == false)
1052 fprintf(stdout, "Usage: connmanctl [[command] [args]]\n");
1054 for (i = 0; cmd_table[i].cmd != NULL; i++) {
1055 const char *cmd = cmd_table[i].cmd;
1056 const char *argument = cmd_table[i].argument;
1057 const char *desc = cmd_table[i].desc;
1059 printf("%-12s%-22s%s\n", cmd != NULL? cmd: "",
1060 argument != NULL? argument: "",
1061 desc != NULL? desc: "");
1063 if (cmd_table[i].options != NULL) {
1064 for (j = 0; cmd_table[i].options[j].name != NULL;
1066 const char *options_desc =
1067 cmd_table[i].options_desc != NULL ?
1068 cmd_table[i].options_desc[j]: "";
1070 printf(" --%-12s%s\n",
1071 cmd_table[i].options[j].name,
1077 if (interactive == false)
1078 fprintf(stdout, "\nNote: arguments and output are considered "
1079 "EXPERIMENTAL for now.\n");
1084 int commands(DBusConnection *dbus_conn, char *argv[], int argc)
1088 connection = dbus_conn;
1090 for (i = 0; cmd_table[i].cmd != NULL; i++) {
1091 if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
1092 cmd_table[i].func != NULL) {
1093 result = cmd_table[i].func(argv, argc,
1094 cmd_table[i].options);
1095 if (result < 0 && result != -EINPROGRESS)
1096 fprintf(stderr, "Error '%s': %s\n", argv[0],
1102 fprintf(stderr, "Error '%s': Unknown command\n", argv[0]);