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 char *proxy_simple[] = {
71 static int cmd_help(char *args[], int num, struct option *options);
73 static int parse_args(char *arg, struct option *options)
80 for (i = 0; options[i].name != NULL; i++) {
81 if (strcmp(options[i].name, arg) == 0 ||
82 (strncmp(arg, "--", 2) == 0 &&
83 strcmp(&arg[2], options[i].name) == 0))
84 return options[i].val;
90 static void enable_return(DBusMessageIter *iter, const char *error,
93 char *tech = user_data;
96 str = strrchr(tech, '/');
103 fprintf(stdout, "Enabled %s\n", str);
105 fprintf(stderr, "Error %s: %s\n", str, error);
110 static int cmd_enable(char *args[], int num, struct option *options)
113 dbus_bool_t b = TRUE;
121 if (strcmp(args[1], "offlinemode") == 0) {
122 tech = g_strdup(args[1]);
123 return __connmanctl_dbus_set_property(connection, "/",
124 "net.connman.Manager", enable_return, tech,
125 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
128 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
129 return __connmanctl_dbus_set_property(connection, tech,
130 "net.connman.Technology", enable_return, tech,
131 "Powered", DBUS_TYPE_BOOLEAN, &b);
134 static void disable_return(DBusMessageIter *iter, const char *error,
137 char *tech = user_data;
140 str = strrchr(tech, '/');
147 fprintf(stdout, "Disabled %s\n", str);
149 fprintf(stderr, "Error %s: %s\n", str, error);
154 static int cmd_disable(char *args[], int num, struct option *options)
157 dbus_bool_t b = FALSE;
165 if (strcmp(args[1], "offlinemode") == 0) {
166 tech = g_strdup(args[1]);
167 return __connmanctl_dbus_set_property(connection, "/",
168 "net.connman.Manager", disable_return, tech,
169 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
172 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
173 return __connmanctl_dbus_set_property(connection, tech,
174 "net.connman.Technology", disable_return, tech,
175 "Powered", DBUS_TYPE_BOOLEAN, &b);
178 static void state_print(DBusMessageIter *iter, const char *error,
181 DBusMessageIter entry;
184 fprintf(stderr, "Error: %s", error);
188 dbus_message_iter_recurse(iter, &entry);
189 __connmanctl_dbus_print(&entry, " ", " = ", "\n");
190 fprintf(stdout, "\n");
193 static int cmd_state(char *args[], int num, struct option *options)
198 return __connmanctl_dbus_method_call(connection, "/",
199 "net.connman.Manager", "GetProperties",
200 state_print, NULL, DBUS_TYPE_INVALID);
203 static void services_list(DBusMessageIter *iter, const char *error,
207 __connmanctl_services_list(iter);
208 fprintf(stdout, "\n");
210 fprintf(stderr, "Error: %s\n", error);
214 static void services_properties(DBusMessageIter *iter, const char *error,
217 char *path = user_data;
219 DBusMessageIter dict;
222 fprintf(stdout, "%s\n", path);
224 dbus_message_iter_recurse(iter, &dict);
225 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
227 fprintf(stdout, "\n");
230 str = strrchr(path, '/');
236 fprintf(stderr, "Error %s: %s\n", str, error);
242 static int cmd_services(char *args[], int num, struct option *options)
244 char *service_name = NULL;
251 c = parse_args(args[1], options);
258 service_name = args[2];
263 service_name = args[1];
267 if (service_name == NULL) {
268 return __connmanctl_dbus_method_call(connection, "/",
269 "net.connman.Manager", "GetServices",
270 services_list, NULL, DBUS_TYPE_INVALID);
273 path = g_strdup_printf("/net/connman/service/%s", service_name);
274 return __connmanctl_dbus_method_call(connection, path,
275 "net.connman.Service", "GetProperties",
276 services_properties, path, DBUS_TYPE_INVALID);
279 static void technology_print(DBusMessageIter *iter, const char *error,
282 DBusMessageIter array;
285 fprintf(stderr, "Error: %s\n", error);
289 dbus_message_iter_recurse(iter, &array);
290 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
291 DBusMessageIter entry, dict;
294 dbus_message_iter_recurse(&array, &entry);
295 dbus_message_iter_get_basic(&entry, &path);
296 fprintf(stdout, "%s\n", path);
298 dbus_message_iter_next(&entry);
300 dbus_message_iter_recurse(&entry, &dict);
301 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
302 fprintf(stdout, "\n");
304 dbus_message_iter_next(&array);
308 static int cmd_technologies(char *args[], int num, struct option *options)
313 return __connmanctl_dbus_method_call(connection, "/",
314 "net.connman.Manager", "GetTechnologies",
315 technology_print, NULL, DBUS_TYPE_INVALID);
318 static void scan_return(DBusMessageIter *iter, const char *error,
321 char *path = user_data;
324 char *str = strrchr(path, '/');
326 fprintf(stdout, "Scan completed for %s\n", str);
328 fprintf(stderr, "Error %s: %s", path, error);
333 static int cmd_scan(char *args[], int num, struct option *options)
343 path = g_strdup_printf("/net/connman/technology/%s", args[1]);
344 return __connmanctl_dbus_method_call(connection, path,
345 "net.connman.Technology", "Scan",
346 scan_return, path, DBUS_TYPE_INVALID);
349 static void connect_return(DBusMessageIter *iter, const char *error,
352 char *path = user_data;
355 char *str = strrchr(path, '/');
357 fprintf(stdout, "Connected %s\n", str);
359 fprintf(stderr, "Error %s: %s\n", path, error);
364 static int cmd_connect(char *args[], int num, struct option *options)
374 path = g_strdup_printf("/net/connman/service/%s", args[1]);
375 return __connmanctl_dbus_method_call(connection, path,
376 "net.connman.Service", "Connect",
377 connect_return, path, DBUS_TYPE_INVALID);
380 static void disconnect_return(DBusMessageIter *iter, const char *error,
383 char *path = user_data;
386 char *str = strrchr(path, '/');
388 fprintf(stdout, "Disconnected %s\n", str);
390 fprintf(stderr, "Error %s: %s\n", path, error);
395 static int cmd_disconnect(char *args[], int num, struct option *options)
405 path = g_strdup_printf("/net/connman/service/%s", args[1]);
406 return __connmanctl_dbus_method_call(connection, path,
407 "net.connman.Service", "Disconnect",
408 disconnect_return, path, DBUS_TYPE_INVALID);
413 static void config_return(DBusMessageIter *iter, const char *error,
416 char *service_name = user_data;
419 fprintf(stderr, "Error %s: %s\n", service_name, error);
424 struct config_append {
429 static void config_append_ipv4(DBusMessageIter *iter,
432 struct config_append *append = user_data;
433 char **opts = append->opts;
439 while (opts[i] != NULL && ipv4[i] != NULL) {
440 __connmanctl_dbus_append_dict_entry(iter, ipv4[i],
441 DBUS_TYPE_STRING, &opts[i]);
448 static void config_append_ipv6(DBusMessageIter *iter, void *user_data)
450 struct config_append *append = user_data;
451 char **opts = append->opts;
458 if (g_strcmp0(opts[0], "auto") == 0) {
461 switch (parse_boolean(opts[1])) {
466 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
467 DBUS_TYPE_STRING, &str);
474 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
475 DBUS_TYPE_STRING, &str);
479 if (opts[1] != NULL) {
482 if (g_strcmp0(opts[0], "prefered") != 0) {
483 fprintf(stderr, "Error %s: %s\n",
490 __connmanctl_dbus_append_dict_entry(iter,
491 "Privacy", DBUS_TYPE_STRING,
496 } else if (g_strcmp0(opts[0], "manual") == 0) {
499 while (opts[i] != NULL && ipv6[i] != NULL) {
501 int value = atoi(opts[i]);
502 __connmanctl_dbus_append_dict_entry(iter,
503 ipv6[i], DBUS_TYPE_BYTE,
506 __connmanctl_dbus_append_dict_entry(iter,
507 ipv6[i], DBUS_TYPE_STRING,
515 } else if (g_strcmp0(opts[0], "off") != 0) {
516 fprintf(stderr, "Error %s: %s\n", opts[0], strerror(-EINVAL));
521 __connmanctl_dbus_append_dict_entry(iter, "Method", DBUS_TYPE_STRING,
525 static void config_append_str(DBusMessageIter *iter, void *user_data)
527 struct config_append *append = user_data;
528 char **opts = append->opts;
534 while (opts[i] != NULL) {
535 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
543 static int cmd_config(char *args[], int num, struct option *options)
545 int result = 0, res = 0, index = 2, oldindex = 0;
547 char *service_name, *path;
548 DBusMessage *message;
551 struct config_append append;
553 service_name = args[1];
554 if (service_name == NULL)
557 while (index < num && args[index] != NULL) {
558 c = parse_args(args[index], options);
559 opt_start = &args[index + 1];
560 append.opts = opt_start;
565 message = get_message(connection, "GetServices");
570 path = g_strdup_printf("/net/connman/service/%s", service_name);
574 switch (parse_boolean(*opt_start)) {
589 res = __connmanctl_dbus_set_property(connection,
590 path, "net.connman.Service",
592 g_strdup(service_name),
594 DBUS_TYPE_BOOLEAN, &val);
598 res = __connmanctl_dbus_set_property_dict(connection,
599 path, "net.connman.Service",
600 config_return, g_strdup(service_name),
601 "IPv4.Configuration", DBUS_TYPE_STRING,
602 config_append_ipv4, &append);
603 index += append.values;
607 res = __connmanctl_dbus_set_property_dict(connection,
608 path, "net.connman.Service",
609 config_return, g_strdup(service_name),
610 "IPv6.Configuration", DBUS_TYPE_STRING,
611 config_append_ipv6, &append);
612 index += append.values;
616 res = __connmanctl_dbus_set_property_array(connection,
617 path, "net.connman.Service",
618 config_return, g_strdup(service_name),
619 "Nameservers.Configuration",
620 DBUS_TYPE_STRING, config_append_str,
622 index += append.values;
626 res = __connmanctl_dbus_set_property_array(connection,
627 path, "net.connman.Service",
628 config_return, g_strdup(service_name),
629 "Timeservers.Configuration",
630 DBUS_TYPE_STRING, config_append_str,
632 index += append.values;
636 res = __connmanctl_dbus_set_property_array(connection,
637 path, "net.connman.Service",
638 config_return, g_strdup(service_name),
639 "Domains.Configuration",
640 DBUS_TYPE_STRING, config_append_str,
642 index += append.values;
646 if (*opt_start == NULL) {
651 if (strcmp(*opt_start, "direct") == 0) {
652 res = set_service_property(connection, message,
654 "Proxy.Configuration",
655 proxy_simple, opt_start, 1);
659 if (strcmp(*opt_start, "auto") == 0) {
660 res = set_service_property(connection, message,
662 "Proxy.Configuration",
663 proxy_simple, opt_start, 1);
667 if (strcmp(*opt_start, "manual") == 0) {
668 char **url_start = &args[index + 2];
670 if (*url_start != NULL &&
673 url_start = &args[index + 3];
676 res = store_proxy_input(connection,
677 message, service_name,
683 res = __connmanctl_dbus_method_call(connection,
684 path, "net.connman.Service", "Remove",
685 config_return, g_strdup(service_name),
694 dbus_message_unref(message);
697 if (res == -EINPROGRESS)
698 result = -EINPROGRESS;
700 printf("Error '%s': %s\n", args[oldindex],
711 static DBusHandlerResult monitor_changed(DBusConnection *connection,
712 DBusMessage *message, void *user_data)
714 DBusMessageIter iter;
715 const char *interface, *path;
717 interface = dbus_message_get_interface(message);
718 if (strncmp(interface, "net.connman.", 12) != 0)
719 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
721 interface = strrchr(interface, '.');
722 if (interface != NULL && *interface != '\0')
725 path = strrchr(dbus_message_get_path(message), '/');
726 if (path != NULL && *path != '\0')
729 __connmanctl_save_rl();
731 if (dbus_message_is_signal(message, "net.connman.Manager",
732 "ServicesChanged") == TRUE) {
734 fprintf(stdout, "%-12s %-20s = {\n", interface,
736 dbus_message_iter_init(message, &iter);
737 __connmanctl_services_list(&iter);
738 fprintf(stdout, "\n}\n");
740 __connmanctl_redraw_rl();
742 return DBUS_HANDLER_RESULT_HANDLED;
745 if (dbus_message_is_signal(message, "net.connman.Manager",
746 "TechnologyAdded") == TRUE)
747 path = "TechnologyAdded";
749 if (dbus_message_is_signal(message, "net.connman.Manager",
750 "TechnologyRemoved") == TRUE)
751 path = "TechnologyRemoved";
753 fprintf(stdout, "%-12s %-20s ", interface, path);
754 dbus_message_iter_init(message, &iter);
756 __connmanctl_dbus_print(&iter, "", " = ", " = ");
757 fprintf(stdout, "\n");
759 __connmanctl_redraw_rl();
761 return DBUS_HANDLER_RESULT_HANDLED;
764 static bool monitor_s = false;
765 static bool monitor_t = false;
766 static bool monitor_m = false;
768 static void monitor_add(char *interface)
773 if (monitor_s == false && monitor_t == false && monitor_m == false)
774 dbus_connection_add_filter(connection, monitor_changed,
777 if (g_strcmp0(interface, "Service") == 0) {
778 if (monitor_s == true)
781 } else if (g_strcmp0(interface, "Technology") == 0) {
782 if (monitor_t == true)
785 } else if (g_strcmp0(interface, "Manager") == 0) {
786 if (monitor_m == true)
792 dbus_error_init(&err);
793 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
795 dbus_bus_add_match(connection, rule, &err);
798 if (dbus_error_is_set(&err))
799 fprintf(stderr, "Error: %s\n", err.message);
802 static void monitor_del(char *interface)
806 if (g_strcmp0(interface, "Service") == 0) {
807 if (monitor_s == false)
810 } else if (g_strcmp0(interface, "Technology") == 0) {
811 if (monitor_t == false)
814 } else if (g_strcmp0(interface, "Manager") == 0) {
815 if (monitor_m == false)
821 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
823 dbus_bus_remove_match(connection, rule, NULL);
826 if (monitor_s == false && monitor_t == false && monitor_m == false)
827 dbus_connection_remove_filter(connection, monitor_changed,
831 static int cmd_monitor(char *args[], int num, struct option *options)
840 switch (parse_boolean(args[2])) {
850 c = parse_args(args[1], options);
853 monitor_add("Service");
854 monitor_add("Technology");
855 monitor_add("Manager");
860 monitor_add("Service");
862 monitor_del("Service");
867 monitor_add("Technology");
869 monitor_del("Technology");
874 monitor_add("Manager");
876 monitor_del("Manager");
880 switch(parse_boolean(args[1])) {
882 monitor_del("Service");
883 monitor_del("Technology");
884 monitor_del("Manager");
888 monitor_add("Service");
889 monitor_add("Technology");
890 monitor_add("Manager");
904 static int cmd_exit(char *args[], int num, struct option *options)
909 static struct option service_options[] = {
910 {"properties", required_argument, 0, 'p'},
914 static const char *service_desc[] = {
915 "[<service>] (obsolete)",
919 static struct option config_options[] = {
920 {"nameservers", required_argument, 0, 'n'},
921 {"timeservers", required_argument, 0, 't'},
922 {"domains", required_argument, 0, 'd'},
923 {"ipv6", required_argument, 0, 'v'},
924 {"proxy", required_argument, 0, 'x'},
925 {"autoconnect", required_argument, 0, 'a'},
926 {"ipv4", required_argument, 0, 'i'},
927 {"remove", 0, 0, 'r'},
931 static const char *config_desc[] = {
932 "<dns1> [<dns2>] [<dns3>]",
933 "<ntp1> [<ntp2>] [...]",
934 "<domain1> [<domain2>] [...]",
935 "off|auto [enable|disable|prefered]|\n"
936 "\t\t\tmanual <address> <prefixlength> <gateway>",
937 "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
938 "\t\t\t[exclude <exclude1> [<exclude2>] [...]]",
940 "off|dhcp|manual <address> <prefixlength> <gateway>",
945 static struct option monitor_options[] = {
946 {"services", no_argument, 0, 's'},
947 {"tech", no_argument, 0, 'c'},
948 {"manager", no_argument, 0, 'm'},
952 static const char *monitor_desc[] = {
953 "[off] Monitor only services",
954 "[off] Monitor only technologies",
955 "[off] Monitor only manager interface",
959 static const struct {
961 const char *argument;
962 struct option *options;
963 const char **options_desc;
964 int (*func) (char *args[], int num, struct option *options);
967 { "enable", "<technology>|offline", NULL, NULL,
968 cmd_enable, "Enables given technology or offline mode" },
969 { "disable", "<technology>|offline", NULL, NULL,
970 cmd_disable, "Disables given technology or offline mode"},
971 { "state", NULL, NULL, NULL,
972 cmd_state, "Shows if the system is online or offline" },
973 { "services", "[<service>]", service_options, &service_desc[0],
974 cmd_services, "Display services" },
975 { "technologies", NULL, NULL, NULL,
976 cmd_technologies, "Display technologies" },
977 { "scan", "<technology>", NULL, NULL,
978 cmd_scan, "Scans for new services for given technology" },
979 { "connect", "<service>", NULL, NULL,
980 cmd_connect, "Connect a given service" },
981 { "disconnect", "<service>", NULL, NULL,
982 cmd_disconnect, "Disconnect a given service" },
983 { "config", "<service>", config_options, &config_desc[0],
984 cmd_config, "Set service configuration options" },
985 { "monitor", "[off]", monitor_options, &monitor_desc[0],
986 cmd_monitor, "Monitor signals from interfaces" },
987 { "help", NULL, NULL, NULL,
988 cmd_help, "Show help" },
989 { "exit", NULL, NULL, NULL,
991 { "quit", NULL, NULL, NULL,
996 static int cmd_help(char *args[], int num, struct option *options)
998 bool interactive = __connmanctl_is_interactive();
1001 if (interactive == false)
1002 fprintf(stdout, "Usage: connmanctl [[command] [args]]\n");
1004 for (i = 0; cmd_table[i].cmd != NULL; i++) {
1005 const char *cmd = cmd_table[i].cmd;
1006 const char *argument = cmd_table[i].argument;
1007 const char *desc = cmd_table[i].desc;
1009 printf("%-12s%-22s%s\n", cmd != NULL? cmd: "",
1010 argument != NULL? argument: "",
1011 desc != NULL? desc: "");
1013 if (cmd_table[i].options != NULL) {
1014 for (j = 0; cmd_table[i].options[j].name != NULL;
1016 const char *options_desc =
1017 cmd_table[i].options_desc != NULL ?
1018 cmd_table[i].options_desc[j]: "";
1020 printf(" --%-12s%s\n",
1021 cmd_table[i].options[j].name,
1027 if (interactive == false)
1028 fprintf(stdout, "\nNote: arguments and output are considered "
1029 "EXPERIMENTAL for now.\n");
1034 int commands(DBusConnection *dbus_conn, char *argv[], int argc)
1038 connection = dbus_conn;
1040 for (i = 0; cmd_table[i].cmd != NULL; i++) {
1041 if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
1042 cmd_table[i].func != NULL) {
1043 result = cmd_table[i].func(argv, argc,
1044 cmd_table[i].options);
1045 if (result < 0 && result != -EINPROGRESS)
1046 fprintf(stderr, "Error '%s': %s\n", argv[0],
1052 fprintf(stderr, "Error '%s': Unknown command\n", argv[0]);