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
38 #include "technology.h"
39 #include "data_manager.h"
41 #include "dbus_helpers.h"
45 #define MANDATORY_ARGS 3
47 static DBusConnection *connection;
49 static char *ipv4[] = {
57 static char *ipv6[] = {
65 static int cmd_help(char *args[], int num, struct option *options);
67 static int parse_args(char *arg, struct option *options)
74 for (i = 0; options[i].name != NULL; i++) {
75 if (strcmp(options[i].name, arg) == 0 ||
76 (strncmp(arg, "--", 2) == 0 &&
77 strcmp(&arg[2], options[i].name) == 0))
78 return options[i].val;
84 static void enable_return(DBusMessageIter *iter, const char *error,
87 char *tech = user_data;
90 str = strrchr(tech, '/');
97 fprintf(stdout, "Enabled %s\n", str);
99 fprintf(stderr, "Error %s: %s\n", str, error);
104 static int cmd_enable(char *args[], int num, struct option *options)
107 dbus_bool_t b = TRUE;
115 if (strcmp(args[1], "offlinemode") == 0) {
116 tech = g_strdup(args[1]);
117 return __connmanctl_dbus_set_property(connection, "/",
118 "net.connman.Manager", enable_return, tech,
119 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
122 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
123 return __connmanctl_dbus_set_property(connection, tech,
124 "net.connman.Technology", enable_return, tech,
125 "Powered", DBUS_TYPE_BOOLEAN, &b);
128 static void disable_return(DBusMessageIter *iter, const char *error,
131 char *tech = user_data;
134 str = strrchr(tech, '/');
141 fprintf(stdout, "Disabled %s\n", str);
143 fprintf(stderr, "Error %s: %s\n", str, error);
148 static int cmd_disable(char *args[], int num, struct option *options)
151 dbus_bool_t b = FALSE;
159 if (strcmp(args[1], "offlinemode") == 0) {
160 tech = g_strdup(args[1]);
161 return __connmanctl_dbus_set_property(connection, "/",
162 "net.connman.Manager", disable_return, tech,
163 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
166 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
167 return __connmanctl_dbus_set_property(connection, tech,
168 "net.connman.Technology", disable_return, tech,
169 "Powered", DBUS_TYPE_BOOLEAN, &b);
172 static void state_print(DBusMessageIter *iter, const char *error,
175 DBusMessageIter entry;
178 fprintf(stderr, "Error: %s", error);
182 dbus_message_iter_recurse(iter, &entry);
183 __connmanctl_dbus_print(&entry, " ", " = ", "\n");
184 fprintf(stdout, "\n");
187 static int cmd_state(char *args[], int num, struct option *options)
192 return __connmanctl_dbus_method_call(connection, "/",
193 "net.connman.Manager", "GetProperties",
194 state_print, NULL, DBUS_TYPE_INVALID);
197 static void services_list(DBusMessageIter *iter, const char *error,
201 __connmanctl_services_list(iter);
202 fprintf(stdout, "\n");
204 fprintf(stderr, "Error: %s\n", error);
208 static void services_properties(DBusMessageIter *iter, const char *error,
211 char *path = user_data;
213 DBusMessageIter dict;
216 fprintf(stdout, "%s\n", path);
218 dbus_message_iter_recurse(iter, &dict);
219 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
221 fprintf(stdout, "\n");
224 str = strrchr(path, '/');
230 fprintf(stderr, "Error %s: %s\n", str, error);
236 static int cmd_services(char *args[], int num, struct option *options)
238 char *service_name = NULL;
245 c = parse_args(args[1], options);
252 service_name = args[2];
257 service_name = args[1];
261 if (service_name == NULL) {
262 return __connmanctl_dbus_method_call(connection, "/",
263 "net.connman.Manager", "GetServices",
264 services_list, NULL, DBUS_TYPE_INVALID);
267 path = g_strdup_printf("/net/connman/service/%s", service_name);
268 return __connmanctl_dbus_method_call(connection, path,
269 "net.connman.Service", "GetProperties",
270 services_properties, path, DBUS_TYPE_INVALID);
273 static void technology_print(DBusMessageIter *iter, const char *error,
276 DBusMessageIter array;
279 fprintf(stderr, "Error: %s\n", error);
283 dbus_message_iter_recurse(iter, &array);
284 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
285 DBusMessageIter entry, dict;
288 dbus_message_iter_recurse(&array, &entry);
289 dbus_message_iter_get_basic(&entry, &path);
290 fprintf(stdout, "%s\n", path);
292 dbus_message_iter_next(&entry);
294 dbus_message_iter_recurse(&entry, &dict);
295 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
296 fprintf(stdout, "\n");
298 dbus_message_iter_next(&array);
302 static int cmd_technologies(char *args[], int num, struct option *options)
307 return __connmanctl_dbus_method_call(connection, "/",
308 "net.connman.Manager", "GetTechnologies",
309 technology_print, NULL, DBUS_TYPE_INVALID);
312 static void scan_return(DBusMessageIter *iter, const char *error,
315 char *path = user_data;
318 char *str = strrchr(path, '/');
320 fprintf(stdout, "Scan completed for %s\n", str);
322 fprintf(stderr, "Error %s: %s", path, error);
327 static int cmd_scan(char *args[], int num, struct option *options)
337 path = g_strdup_printf("/net/connman/technology/%s", args[1]);
338 return __connmanctl_dbus_method_call(connection, path,
339 "net.connman.Technology", "Scan",
340 scan_return, path, DBUS_TYPE_INVALID);
343 static void connect_return(DBusMessageIter *iter, const char *error,
346 char *path = user_data;
349 char *str = strrchr(path, '/');
351 fprintf(stdout, "Connected %s\n", str);
353 fprintf(stderr, "Error %s: %s\n", path, error);
358 static int cmd_connect(char *args[], int num, struct option *options)
368 path = g_strdup_printf("/net/connman/service/%s", args[1]);
369 return __connmanctl_dbus_method_call(connection, path,
370 "net.connman.Service", "Connect",
371 connect_return, path, DBUS_TYPE_INVALID);
374 static void disconnect_return(DBusMessageIter *iter, const char *error,
377 char *path = user_data;
380 char *str = strrchr(path, '/');
382 fprintf(stdout, "Disconnected %s\n", str);
384 fprintf(stderr, "Error %s: %s\n", path, error);
389 static int cmd_disconnect(char *args[], int num, struct option *options)
399 path = g_strdup_printf("/net/connman/service/%s", args[1]);
400 return __connmanctl_dbus_method_call(connection, path,
401 "net.connman.Service", "Disconnect",
402 disconnect_return, path, DBUS_TYPE_INVALID);
407 static void config_return(DBusMessageIter *iter, const char *error,
410 char *service_name = user_data;
413 fprintf(stderr, "Error %s: %s\n", service_name, error);
418 struct config_append {
423 static void config_append_ipv4(DBusMessageIter *iter,
426 struct config_append *append = user_data;
427 char **opts = append->opts;
433 while (opts[i] != NULL && ipv4[i] != NULL) {
434 __connmanctl_dbus_append_dict_entry(iter, ipv4[i],
435 DBUS_TYPE_STRING, &opts[i]);
442 static void config_append_ipv6(DBusMessageIter *iter, void *user_data)
444 struct config_append *append = user_data;
445 char **opts = append->opts;
452 if (g_strcmp0(opts[0], "auto") == 0) {
455 switch (parse_boolean(opts[1])) {
460 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
461 DBUS_TYPE_STRING, &str);
468 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
469 DBUS_TYPE_STRING, &str);
473 if (opts[1] != NULL) {
476 if (g_strcmp0(opts[0], "prefered") != 0) {
477 fprintf(stderr, "Error %s: %s\n",
484 __connmanctl_dbus_append_dict_entry(iter,
485 "Privacy", DBUS_TYPE_STRING,
490 } else if (g_strcmp0(opts[0], "manual") == 0) {
493 while (opts[i] != NULL && ipv6[i] != NULL) {
495 int value = atoi(opts[i]);
496 __connmanctl_dbus_append_dict_entry(iter,
497 ipv6[i], DBUS_TYPE_BYTE,
500 __connmanctl_dbus_append_dict_entry(iter,
501 ipv6[i], DBUS_TYPE_STRING,
509 } else if (g_strcmp0(opts[0], "off") != 0) {
510 fprintf(stderr, "Error %s: %s\n", opts[0], strerror(-EINVAL));
515 __connmanctl_dbus_append_dict_entry(iter, "Method", DBUS_TYPE_STRING,
519 static void config_append_str(DBusMessageIter *iter, void *user_data)
521 struct config_append *append = user_data;
522 char **opts = append->opts;
528 while (opts[i] != NULL) {
529 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
537 static void append_servers(DBusMessageIter *iter, void *user_data)
539 struct config_append *append = user_data;
540 char **opts = append->opts;
546 while (opts[i] != NULL && g_strcmp0(opts[i], "--excludes") != 0) {
547 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
555 static void append_excludes(DBusMessageIter *iter, void *user_data)
557 struct config_append *append = user_data;
558 char **opts = append->opts;
559 int i = append->values;
561 if (opts == NULL || opts[i] == NULL ||
562 g_strcmp0(opts[i], "--excludes") != 0)
566 while (opts[i] != NULL) {
567 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
575 static void config_append_proxy(DBusMessageIter *iter, void *user_data)
577 struct config_append *append = user_data;
578 char **opts = append->opts;
583 if (g_strcmp0(opts[0], "manual") == 0) {
584 __connmanctl_dbus_append_dict_string_array(iter, "Servers",
585 append_servers, append);
587 __connmanctl_dbus_append_dict_string_array(iter, "Excludes",
588 append_excludes, append);
590 } else if (g_strcmp0(opts[0], "auto") == 0) {
591 if (opts[1] != NULL) {
592 __connmanctl_dbus_append_dict_entry(iter, "URL",
593 DBUS_TYPE_STRING, &opts[1]);
597 } else if (g_strcmp0(opts[0], "direct") != 0)
600 __connmanctl_dbus_append_dict_entry(iter, "Method",DBUS_TYPE_STRING,
606 static int cmd_config(char *args[], int num, struct option *options)
608 int result = 0, res = 0, index = 2, oldindex = 0;
610 char *service_name, *path;
611 DBusMessage *message;
614 struct config_append append;
616 service_name = args[1];
617 if (service_name == NULL)
620 while (index < num && args[index] != NULL) {
621 c = parse_args(args[index], options);
622 opt_start = &args[index + 1];
623 append.opts = opt_start;
628 message = get_message(connection, "GetServices");
633 path = g_strdup_printf("/net/connman/service/%s", service_name);
637 switch (parse_boolean(*opt_start)) {
652 res = __connmanctl_dbus_set_property(connection,
653 path, "net.connman.Service",
655 g_strdup(service_name),
657 DBUS_TYPE_BOOLEAN, &val);
661 res = __connmanctl_dbus_set_property_dict(connection,
662 path, "net.connman.Service",
663 config_return, g_strdup(service_name),
664 "IPv4.Configuration", DBUS_TYPE_STRING,
665 config_append_ipv4, &append);
666 index += append.values;
670 res = __connmanctl_dbus_set_property_dict(connection,
671 path, "net.connman.Service",
672 config_return, g_strdup(service_name),
673 "IPv6.Configuration", DBUS_TYPE_STRING,
674 config_append_ipv6, &append);
675 index += append.values;
679 res = __connmanctl_dbus_set_property_array(connection,
680 path, "net.connman.Service",
681 config_return, g_strdup(service_name),
682 "Nameservers.Configuration",
683 DBUS_TYPE_STRING, config_append_str,
685 index += append.values;
689 res = __connmanctl_dbus_set_property_array(connection,
690 path, "net.connman.Service",
691 config_return, g_strdup(service_name),
692 "Timeservers.Configuration",
693 DBUS_TYPE_STRING, config_append_str,
695 index += append.values;
699 res = __connmanctl_dbus_set_property_array(connection,
700 path, "net.connman.Service",
701 config_return, g_strdup(service_name),
702 "Domains.Configuration",
703 DBUS_TYPE_STRING, config_append_str,
705 index += append.values;
709 res = __connmanctl_dbus_set_property_dict(connection,
710 path, "net.connman.Service",
711 config_return, g_strdup(service_name),
712 "Proxy.Configuration",
713 DBUS_TYPE_STRING, config_append_proxy,
715 index += append.values;
718 res = __connmanctl_dbus_method_call(connection,
719 path, "net.connman.Service", "Remove",
720 config_return, g_strdup(service_name),
729 dbus_message_unref(message);
732 if (res == -EINPROGRESS)
733 result = -EINPROGRESS;
735 printf("Error '%s': %s\n", args[oldindex],
746 static DBusHandlerResult monitor_changed(DBusConnection *connection,
747 DBusMessage *message, void *user_data)
749 DBusMessageIter iter;
750 const char *interface, *path;
752 interface = dbus_message_get_interface(message);
753 if (strncmp(interface, "net.connman.", 12) != 0)
754 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
756 interface = strrchr(interface, '.');
757 if (interface != NULL && *interface != '\0')
760 path = strrchr(dbus_message_get_path(message), '/');
761 if (path != NULL && *path != '\0')
764 __connmanctl_save_rl();
766 if (dbus_message_is_signal(message, "net.connman.Manager",
767 "ServicesChanged") == TRUE) {
769 fprintf(stdout, "%-12s %-20s = {\n", interface,
771 dbus_message_iter_init(message, &iter);
772 __connmanctl_services_list(&iter);
773 fprintf(stdout, "\n}\n");
775 __connmanctl_redraw_rl();
777 return DBUS_HANDLER_RESULT_HANDLED;
780 if (dbus_message_is_signal(message, "net.connman.Manager",
781 "TechnologyAdded") == TRUE)
782 path = "TechnologyAdded";
784 if (dbus_message_is_signal(message, "net.connman.Manager",
785 "TechnologyRemoved") == TRUE)
786 path = "TechnologyRemoved";
788 fprintf(stdout, "%-12s %-20s ", interface, path);
789 dbus_message_iter_init(message, &iter);
791 __connmanctl_dbus_print(&iter, "", " = ", " = ");
792 fprintf(stdout, "\n");
794 __connmanctl_redraw_rl();
796 return DBUS_HANDLER_RESULT_HANDLED;
799 static bool monitor_s = false;
800 static bool monitor_t = false;
801 static bool monitor_m = false;
803 static void monitor_add(char *interface)
808 if (monitor_s == false && monitor_t == false && monitor_m == false)
809 dbus_connection_add_filter(connection, monitor_changed,
812 if (g_strcmp0(interface, "Service") == 0) {
813 if (monitor_s == true)
816 } else if (g_strcmp0(interface, "Technology") == 0) {
817 if (monitor_t == true)
820 } else if (g_strcmp0(interface, "Manager") == 0) {
821 if (monitor_m == true)
827 dbus_error_init(&err);
828 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
830 dbus_bus_add_match(connection, rule, &err);
833 if (dbus_error_is_set(&err))
834 fprintf(stderr, "Error: %s\n", err.message);
837 static void monitor_del(char *interface)
841 if (g_strcmp0(interface, "Service") == 0) {
842 if (monitor_s == false)
845 } else if (g_strcmp0(interface, "Technology") == 0) {
846 if (monitor_t == false)
849 } else if (g_strcmp0(interface, "Manager") == 0) {
850 if (monitor_m == false)
856 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
858 dbus_bus_remove_match(connection, rule, NULL);
861 if (monitor_s == false && monitor_t == false && monitor_m == false)
862 dbus_connection_remove_filter(connection, monitor_changed,
866 static int cmd_monitor(char *args[], int num, struct option *options)
875 switch (parse_boolean(args[2])) {
885 c = parse_args(args[1], options);
888 monitor_add("Service");
889 monitor_add("Technology");
890 monitor_add("Manager");
895 monitor_add("Service");
897 monitor_del("Service");
902 monitor_add("Technology");
904 monitor_del("Technology");
909 monitor_add("Manager");
911 monitor_del("Manager");
915 switch(parse_boolean(args[1])) {
917 monitor_del("Service");
918 monitor_del("Technology");
919 monitor_del("Manager");
923 monitor_add("Service");
924 monitor_add("Technology");
925 monitor_add("Manager");
939 static int cmd_exit(char *args[], int num, struct option *options)
944 static struct option service_options[] = {
945 {"properties", required_argument, 0, 'p'},
949 static const char *service_desc[] = {
950 "[<service>] (obsolete)",
954 static struct option config_options[] = {
955 {"nameservers", required_argument, 0, 'n'},
956 {"timeservers", required_argument, 0, 't'},
957 {"domains", required_argument, 0, 'd'},
958 {"ipv6", required_argument, 0, 'v'},
959 {"proxy", required_argument, 0, 'x'},
960 {"autoconnect", required_argument, 0, 'a'},
961 {"ipv4", required_argument, 0, 'i'},
962 {"remove", 0, 0, 'r'},
966 static const char *config_desc[] = {
967 "<dns1> [<dns2>] [<dns3>]",
968 "<ntp1> [<ntp2>] [...]",
969 "<domain1> [<domain2>] [...]",
970 "off|auto [enable|disable|prefered]|\n"
971 "\t\t\tmanual <address> <prefixlength> <gateway>",
972 "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
973 "\t\t\t[exclude <exclude1> [<exclude2>] [...]]",
975 "off|dhcp|manual <address> <prefixlength> <gateway>",
980 static struct option monitor_options[] = {
981 {"services", no_argument, 0, 's'},
982 {"tech", no_argument, 0, 'c'},
983 {"manager", no_argument, 0, 'm'},
987 static const char *monitor_desc[] = {
988 "[off] Monitor only services",
989 "[off] Monitor only technologies",
990 "[off] Monitor only manager interface",
994 static const struct {
996 const char *argument;
997 struct option *options;
998 const char **options_desc;
999 int (*func) (char *args[], int num, struct option *options);
1002 { "enable", "<technology>|offline", NULL, NULL,
1003 cmd_enable, "Enables given technology or offline mode" },
1004 { "disable", "<technology>|offline", NULL, NULL,
1005 cmd_disable, "Disables given technology or offline mode"},
1006 { "state", NULL, NULL, NULL,
1007 cmd_state, "Shows if the system is online or offline" },
1008 { "services", "[<service>]", service_options, &service_desc[0],
1009 cmd_services, "Display services" },
1010 { "technologies", NULL, NULL, NULL,
1011 cmd_technologies, "Display technologies" },
1012 { "scan", "<technology>", NULL, NULL,
1013 cmd_scan, "Scans for new services for given technology" },
1014 { "connect", "<service>", NULL, NULL,
1015 cmd_connect, "Connect a given service" },
1016 { "disconnect", "<service>", NULL, NULL,
1017 cmd_disconnect, "Disconnect a given service" },
1018 { "config", "<service>", config_options, &config_desc[0],
1019 cmd_config, "Set service configuration options" },
1020 { "monitor", "[off]", monitor_options, &monitor_desc[0],
1021 cmd_monitor, "Monitor signals from interfaces" },
1022 { "help", NULL, NULL, NULL,
1023 cmd_help, "Show help" },
1024 { "exit", NULL, NULL, NULL,
1026 { "quit", NULL, NULL, NULL,
1031 static int cmd_help(char *args[], int num, struct option *options)
1033 bool interactive = __connmanctl_is_interactive();
1036 if (interactive == false)
1037 fprintf(stdout, "Usage: connmanctl [[command] [args]]\n");
1039 for (i = 0; cmd_table[i].cmd != NULL; i++) {
1040 const char *cmd = cmd_table[i].cmd;
1041 const char *argument = cmd_table[i].argument;
1042 const char *desc = cmd_table[i].desc;
1044 printf("%-12s%-22s%s\n", cmd != NULL? cmd: "",
1045 argument != NULL? argument: "",
1046 desc != NULL? desc: "");
1048 if (cmd_table[i].options != NULL) {
1049 for (j = 0; cmd_table[i].options[j].name != NULL;
1051 const char *options_desc =
1052 cmd_table[i].options_desc != NULL ?
1053 cmd_table[i].options_desc[j]: "";
1055 printf(" --%-12s%s\n",
1056 cmd_table[i].options[j].name,
1062 if (interactive == false)
1063 fprintf(stdout, "\nNote: arguments and output are considered "
1064 "EXPERIMENTAL for now.\n");
1069 int commands(DBusConnection *dbus_conn, char *argv[], int argc)
1073 connection = dbus_conn;
1075 for (i = 0; cmd_table[i].cmd != NULL; i++) {
1076 if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
1077 cmd_table[i].func != NULL) {
1078 result = cmd_table[i].func(argv, argc,
1079 cmd_table[i].options);
1080 if (result < 0 && result != -EINPROGRESS)
1081 fprintf(stderr, "Error '%s': %s\n", argv[0],
1087 fprintf(stderr, "Error '%s': Unknown command\n", argv[0]);