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[] = {
66 static char *proxy_simple[] = {
72 static int cmd_help(char *args[], int num, struct option *options);
74 static int parse_args(char *arg, struct option *options)
81 for (i = 0; options[i].name != NULL; i++) {
82 if (strcmp(options[i].name, arg) == 0 ||
83 (strncmp(arg, "--", 2) == 0 &&
84 strcmp(&arg[2], options[i].name) == 0))
85 return options[i].val;
91 static void enable_return(DBusMessageIter *iter, const char *error,
94 char *tech = user_data;
97 str = strrchr(tech, '/');
104 fprintf(stdout, "Enabled %s\n", str);
106 fprintf(stderr, "Error %s: %s\n", str, error);
111 static int cmd_enable(char *args[], int num, struct option *options)
114 dbus_bool_t b = TRUE;
122 if (strcmp(args[1], "offlinemode") == 0) {
123 tech = g_strdup(args[1]);
124 return __connmanctl_dbus_set_property(connection, "/",
125 "net.connman.Manager", enable_return, tech,
126 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
129 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
130 return __connmanctl_dbus_set_property(connection, tech,
131 "net.connman.Technology", enable_return, tech,
132 "Powered", DBUS_TYPE_BOOLEAN, &b);
135 static void disable_return(DBusMessageIter *iter, const char *error,
138 char *tech = user_data;
141 str = strrchr(tech, '/');
148 fprintf(stdout, "Disabled %s\n", str);
150 fprintf(stderr, "Error %s: %s\n", str, error);
155 static int cmd_disable(char *args[], int num, struct option *options)
158 dbus_bool_t b = FALSE;
166 if (strcmp(args[1], "offlinemode") == 0) {
167 tech = g_strdup(args[1]);
168 return __connmanctl_dbus_set_property(connection, "/",
169 "net.connman.Manager", disable_return, tech,
170 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
173 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
174 return __connmanctl_dbus_set_property(connection, tech,
175 "net.connman.Technology", disable_return, tech,
176 "Powered", DBUS_TYPE_BOOLEAN, &b);
179 static void state_print(DBusMessageIter *iter, const char *error,
182 DBusMessageIter entry;
185 fprintf(stderr, "Error: %s", error);
189 dbus_message_iter_recurse(iter, &entry);
190 __connmanctl_dbus_print(&entry, " ", " = ", "\n");
191 fprintf(stdout, "\n");
194 static int cmd_state(char *args[], int num, struct option *options)
199 return __connmanctl_dbus_method_call(connection, "/",
200 "net.connman.Manager", "GetProperties",
201 state_print, NULL, DBUS_TYPE_INVALID);
204 static void services_list(DBusMessageIter *iter, const char *error,
208 __connmanctl_services_list(iter);
209 fprintf(stdout, "\n");
211 fprintf(stderr, "Error: %s\n", error);
215 static void services_properties(DBusMessageIter *iter, const char *error,
218 char *path = user_data;
220 DBusMessageIter dict;
223 fprintf(stdout, "%s\n", path);
225 dbus_message_iter_recurse(iter, &dict);
226 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
228 fprintf(stdout, "\n");
231 str = strrchr(path, '/');
237 fprintf(stderr, "Error %s: %s\n", str, error);
243 static int cmd_services(char *args[], int num, struct option *options)
245 char *service_name = NULL;
252 c = parse_args(args[1], options);
259 service_name = args[2];
264 service_name = args[1];
268 if (service_name == NULL) {
269 return __connmanctl_dbus_method_call(connection, "/",
270 "net.connman.Manager", "GetServices",
271 services_list, NULL, DBUS_TYPE_INVALID);
274 path = g_strdup_printf("/net/connman/service/%s", service_name);
275 return __connmanctl_dbus_method_call(connection, path,
276 "net.connman.Service", "GetProperties",
277 services_properties, path, DBUS_TYPE_INVALID);
280 static void technology_print(DBusMessageIter *iter, const char *error,
283 DBusMessageIter array;
286 fprintf(stderr, "Error: %s\n", error);
290 dbus_message_iter_recurse(iter, &array);
291 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
292 DBusMessageIter entry, dict;
295 dbus_message_iter_recurse(&array, &entry);
296 dbus_message_iter_get_basic(&entry, &path);
297 fprintf(stdout, "%s\n", path);
299 dbus_message_iter_next(&entry);
301 dbus_message_iter_recurse(&entry, &dict);
302 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
303 fprintf(stdout, "\n");
305 dbus_message_iter_next(&array);
309 static int cmd_technologies(char *args[], int num, struct option *options)
314 return __connmanctl_dbus_method_call(connection, "/",
315 "net.connman.Manager", "GetTechnologies",
316 technology_print, NULL, DBUS_TYPE_INVALID);
319 static void scan_return(DBusMessageIter *iter, const char *error,
322 char *path = user_data;
325 char *str = strrchr(path, '/');
327 fprintf(stdout, "Scan completed for %s\n", str);
329 fprintf(stderr, "Error %s: %s", path, error);
334 static int cmd_scan(char *args[], int num, struct option *options)
344 path = g_strdup_printf("/net/connman/technology/%s", args[1]);
345 return __connmanctl_dbus_method_call(connection, path,
346 "net.connman.Technology", "Scan",
347 scan_return, path, DBUS_TYPE_INVALID);
350 static void connect_return(DBusMessageIter *iter, const char *error,
353 char *path = user_data;
356 char *str = strrchr(path, '/');
358 fprintf(stdout, "Connected %s\n", str);
360 fprintf(stderr, "Error %s: %s\n", path, error);
365 static int cmd_connect(char *args[], int num, struct option *options)
375 path = g_strdup_printf("/net/connman/service/%s", args[1]);
376 return __connmanctl_dbus_method_call(connection, path,
377 "net.connman.Service", "Connect",
378 connect_return, path, DBUS_TYPE_INVALID);
381 static void disconnect_return(DBusMessageIter *iter, const char *error,
384 char *path = user_data;
387 char *str = strrchr(path, '/');
389 fprintf(stdout, "Disconnected %s\n", str);
391 fprintf(stderr, "Error %s: %s\n", path, error);
396 static int cmd_disconnect(char *args[], int num, struct option *options)
406 path = g_strdup_printf("/net/connman/service/%s", args[1]);
407 return __connmanctl_dbus_method_call(connection, path,
408 "net.connman.Service", "Disconnect",
409 disconnect_return, path, DBUS_TYPE_INVALID);
414 static int cmd_config(char *args[], int num, struct option *options)
416 int res = 0, index = 2, oldindex = 0;
419 DBusMessage *message;
423 service_name = args[1];
424 if (service_name == NULL)
427 while (index < num && args[index] != NULL) {
428 c = parse_args(args[index], options);
429 opt_start = &args[index + 1];
432 message = get_message(connection, "GetServices");
440 switch (parse_boolean(*opt_start)) {
452 res = set_service_property(connection, message,
453 service_name, "AutoConnect",
457 res = set_service_property(connection, message,
458 service_name, "IPv4.Configuration",
464 res = set_service_property(connection, message,
465 service_name, "IPv6.Configuration",
471 res = set_service_property(connection, message,
473 "Nameservers.Configuration",
477 res = set_service_property(connection, message,
479 "Timeservers.Configuration",
483 res = set_service_property(connection, message,
485 "Domains.Configuration",
489 if (*opt_start == NULL) {
494 if (strcmp(*opt_start, "direct") == 0) {
495 res = set_service_property(connection, message,
497 "Proxy.Configuration",
498 proxy_simple, opt_start, 1);
502 if (strcmp(*opt_start, "auto") == 0) {
503 res = set_service_property(connection, message,
505 "Proxy.Configuration",
506 proxy_simple, opt_start, 1);
510 if (strcmp(*opt_start, "manual") == 0) {
511 char **url_start = &args[index + 2];
513 if (*url_start != NULL &&
516 url_start = &args[index + 3];
519 res = store_proxy_input(connection,
520 message, service_name,
526 res = remove_service(connection, message, service_name);
533 dbus_message_unref(message);
536 printf("Error '%s': %s\n", args[oldindex],
547 static DBusHandlerResult monitor_changed(DBusConnection *connection,
548 DBusMessage *message, void *user_data)
550 DBusMessageIter iter;
551 const char *interface, *path;
553 interface = dbus_message_get_interface(message);
554 if (strncmp(interface, "net.connman.", 12) != 0)
555 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
557 interface = strrchr(interface, '.');
558 if (interface != NULL && *interface != '\0')
561 path = strrchr(dbus_message_get_path(message), '/');
562 if (path != NULL && *path != '\0')
565 __connmanctl_save_rl();
567 if (dbus_message_is_signal(message, "net.connman.Manager",
568 "ServicesChanged") == TRUE) {
570 fprintf(stdout, "%-12s %-20s = {\n", interface,
572 dbus_message_iter_init(message, &iter);
573 __connmanctl_services_list(&iter);
574 fprintf(stdout, "\n}\n");
576 __connmanctl_redraw_rl();
578 return DBUS_HANDLER_RESULT_HANDLED;
581 if (dbus_message_is_signal(message, "net.connman.Manager",
582 "TechnologyAdded") == TRUE)
583 path = "TechnologyAdded";
585 if (dbus_message_is_signal(message, "net.connman.Manager",
586 "TechnologyRemoved") == TRUE)
587 path = "TechnologyRemoved";
589 fprintf(stdout, "%-12s %-20s ", interface, path);
590 dbus_message_iter_init(message, &iter);
592 __connmanctl_dbus_print(&iter, "", " = ", " = ");
593 fprintf(stdout, "\n");
595 __connmanctl_redraw_rl();
597 return DBUS_HANDLER_RESULT_HANDLED;
600 static bool monitor_s = false;
601 static bool monitor_t = false;
602 static bool monitor_m = false;
604 static void monitor_add(char *interface)
609 if (monitor_s == false && monitor_t == false && monitor_m == false)
610 dbus_connection_add_filter(connection, monitor_changed,
613 if (g_strcmp0(interface, "Service") == 0) {
614 if (monitor_s == true)
617 } else if (g_strcmp0(interface, "Technology") == 0) {
618 if (monitor_t == true)
621 } else if (g_strcmp0(interface, "Manager") == 0) {
622 if (monitor_m == true)
628 dbus_error_init(&err);
629 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
631 dbus_bus_add_match(connection, rule, &err);
634 if (dbus_error_is_set(&err))
635 fprintf(stderr, "Error: %s\n", err.message);
638 static void monitor_del(char *interface)
642 if (g_strcmp0(interface, "Service") == 0) {
643 if (monitor_s == false)
646 } else if (g_strcmp0(interface, "Technology") == 0) {
647 if (monitor_t == false)
650 } else if (g_strcmp0(interface, "Manager") == 0) {
651 if (monitor_m == false)
657 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
659 dbus_bus_remove_match(connection, rule, NULL);
662 if (monitor_s == false && monitor_t == false && monitor_m == false)
663 dbus_connection_remove_filter(connection, monitor_changed,
667 static int cmd_monitor(char *args[], int num, struct option *options)
676 switch (parse_boolean(args[2])) {
686 c = parse_args(args[1], options);
689 monitor_add("Service");
690 monitor_add("Technology");
691 monitor_add("Manager");
696 monitor_add("Service");
698 monitor_del("Service");
703 monitor_add("Technology");
705 monitor_del("Technology");
710 monitor_add("Manager");
712 monitor_del("Manager");
716 switch(parse_boolean(args[1])) {
718 monitor_del("Service");
719 monitor_del("Technology");
720 monitor_del("Manager");
724 monitor_add("Service");
725 monitor_add("Technology");
726 monitor_add("Manager");
740 static int cmd_exit(char *args[], int num, struct option *options)
745 static struct option service_options[] = {
746 {"properties", required_argument, 0, 'p'},
750 static const char *service_desc[] = {
751 "[<service>] (obsolete)",
755 static struct option config_options[] = {
756 {"nameservers", required_argument, 0, 'n'},
757 {"timeservers", required_argument, 0, 't'},
758 {"domains", required_argument, 0, 'd'},
759 {"ipv6", required_argument, 0, 'v'},
760 {"proxy", required_argument, 0, 'x'},
761 {"autoconnect", required_argument, 0, 'a'},
762 {"ipv4", required_argument, 0, 'i'},
763 {"remove", 0, 0, 'r'},
767 static const char *config_desc[] = {
768 "<dns1> [<dns2>] [<dns3>]",
769 "<ntp1> [<ntp2>] [...]",
770 "<domain1> [<domain2>] [...]",
771 "off|auto|manual <address> <prefixlength> <gateway> <privacy>",
772 "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
773 " [exclude <exclude1> [<exclude2>] [...]]",
775 "off|dhcp|manual <address> <prefixlength> <gateway>",
780 static struct option monitor_options[] = {
781 {"services", no_argument, 0, 's'},
782 {"tech", no_argument, 0, 'c'},
783 {"manager", no_argument, 0, 'm'},
787 static const char *monitor_desc[] = {
788 "[off] Monitor only services",
789 "[off] Monitor only technologies",
790 "[off] Monitor only manager interface",
794 static const struct {
796 const char *argument;
797 struct option *options;
798 const char **options_desc;
799 int (*func) (char *args[], int num, struct option *options);
802 { "enable", "<technology>|offline", NULL, NULL,
803 cmd_enable, "Enables given technology or offline mode" },
804 { "disable", "<technology>|offline", NULL, NULL,
805 cmd_disable, "Disables given technology or offline mode"},
806 { "state", NULL, NULL, NULL,
807 cmd_state, "Shows if the system is online or offline" },
808 { "services", "[<service>]", service_options, &service_desc[0],
809 cmd_services, "Display services" },
810 { "technologies", NULL, NULL, NULL,
811 cmd_technologies, "Display technologies" },
812 { "scan", "<technology>", NULL, NULL,
813 cmd_scan, "Scans for new services for given technology" },
814 { "connect", "<service>", NULL, NULL,
815 cmd_connect, "Connect a given service" },
816 { "disconnect", "<service>", NULL, NULL,
817 cmd_disconnect, "Disconnect a given service" },
818 { "config", "<service>", config_options, &config_desc[0],
819 cmd_config, "Set service configuration options" },
820 { "monitor", "[off]", monitor_options, &monitor_desc[0],
821 cmd_monitor, "Monitor signals from interfaces" },
822 { "help", NULL, NULL, NULL,
823 cmd_help, "Show help" },
824 { "exit", NULL, NULL, NULL,
826 { "quit", NULL, NULL, NULL,
831 static int cmd_help(char *args[], int num, struct option *options)
833 bool interactive = __connmanctl_is_interactive();
836 if (interactive == false)
837 fprintf(stdout, "Usage: connmanctl [[command] [args]]\n");
839 for (i = 0; cmd_table[i].cmd != NULL; i++) {
840 const char *cmd = cmd_table[i].cmd;
841 const char *argument = cmd_table[i].argument;
842 const char *desc = cmd_table[i].desc;
844 printf("%-12s%-22s%s\n", cmd != NULL? cmd: "",
845 argument != NULL? argument: "",
846 desc != NULL? desc: "");
848 if (cmd_table[i].options != NULL) {
849 for (j = 0; cmd_table[i].options[j].name != NULL;
851 const char *options_desc =
852 cmd_table[i].options_desc != NULL ?
853 cmd_table[i].options_desc[j]: "";
855 printf(" --%-12s%s\n",
856 cmd_table[i].options[j].name,
862 if (interactive == false)
863 fprintf(stdout, "\nNote: arguments and output are considered "
864 "EXPERIMENTAL for now.\n");
869 int commands(DBusConnection *dbus_conn, char *argv[], int argc)
873 connection = dbus_conn;
875 for (i = 0; cmd_table[i].cmd != NULL; i++) {
876 if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
877 cmd_table[i].func != NULL) {
878 result = cmd_table[i].func(argv, argc,
879 cmd_table[i].options);
880 if (result < 0 && result != -EINPROGRESS)
881 fprintf(stderr, "Error '%s': %s\n", argv[0],
887 fprintf(stderr, "Error '%s': Unknown command\n", argv[0]);