5 * Copyright (C) 2012-2014 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
32 #include <sys/types.h>
39 #include "dbus_helpers.h"
45 #include "vpnconnections.h"
47 static DBusConnection *connection;
48 static GHashTable *service_hash;
49 static GHashTable *peer_hash;
50 static GHashTable *technology_hash;
51 static char *session_notify_path;
52 static char *session_path;
53 static bool session_connected;
55 struct connman_option {
61 static char *ipv4[] = {
69 static char *ipv6[] = {
77 static int cmd_help(char *args[], int num, struct connman_option *options);
79 static bool check_dbus_name(const char *name)
82 * Valid dbus chars should be [A-Z][a-z][0-9]_
83 * and should not start with number.
87 if (!name || name[0] == '\0')
90 for (i = 0; name[i] != '\0'; i++)
91 if (!((name[i] >= 'A' && name[i] <= 'Z') ||
92 (name[i] >= 'a' && name[i] <= 'z') ||
93 (name[i] >= '0' && name[i] <= '9') ||
100 static int parse_boolean(char *arg)
105 if (strcasecmp(arg, "no") == 0 ||
106 strcasecmp(arg, "false") == 0 ||
107 strcasecmp(arg, "off" ) == 0 ||
108 strcasecmp(arg, "disable" ) == 0 ||
109 strcasecmp(arg, "n") == 0 ||
110 strcasecmp(arg, "f") == 0 ||
111 strcasecmp(arg, "0") == 0)
114 if (strcasecmp(arg, "yes") == 0 ||
115 strcasecmp(arg, "true") == 0 ||
116 strcasecmp(arg, "on") == 0 ||
117 strcasecmp(arg, "enable" ) == 0 ||
118 strcasecmp(arg, "y") == 0 ||
119 strcasecmp(arg, "t") == 0 ||
120 strcasecmp(arg, "1") == 0)
126 static int parse_args(char *arg, struct connman_option *options)
133 for (i = 0; options[i].name; i++) {
134 if (strcmp(options[i].name, arg) == 0 ||
135 (strncmp(arg, "--", 2) == 0 &&
136 strcmp(&arg[2], options[i].name) == 0))
137 return options[i].val;
143 static int enable_return(DBusMessageIter *iter, const char *error,
146 char *tech = user_data;
149 str = strrchr(tech, '/');
156 fprintf(stdout, "Enabled %s\n", str);
158 fprintf(stderr, "Error %s: %s\n", str, error);
165 static int cmd_enable(char *args[], int num, struct connman_option *options)
168 dbus_bool_t b = TRUE;
176 if (check_dbus_name(args[1]) == false)
179 if (strcmp(args[1], "offline") == 0) {
180 tech = g_strdup(args[1]);
181 return __connmanctl_dbus_set_property(connection, "/",
182 "net.connman.Manager", enable_return, tech,
183 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
186 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
187 return __connmanctl_dbus_set_property(connection, tech,
188 "net.connman.Technology", enable_return, tech,
189 "Powered", DBUS_TYPE_BOOLEAN, &b);
192 static int disable_return(DBusMessageIter *iter, const char *error,
195 char *tech = user_data;
198 str = strrchr(tech, '/');
205 fprintf(stdout, "Disabled %s\n", str);
207 fprintf(stderr, "Error %s: %s\n", str, error);
214 static int cmd_disable(char *args[], int num, struct connman_option *options)
217 dbus_bool_t b = FALSE;
225 if (check_dbus_name(args[1]) == false)
228 if (strcmp(args[1], "offline") == 0) {
229 tech = g_strdup(args[1]);
230 return __connmanctl_dbus_set_property(connection, "/",
231 "net.connman.Manager", disable_return, tech,
232 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
235 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
236 return __connmanctl_dbus_set_property(connection, tech,
237 "net.connman.Technology", disable_return, tech,
238 "Powered", DBUS_TYPE_BOOLEAN, &b);
241 static int state_print(DBusMessageIter *iter, const char *error,
244 DBusMessageIter entry;
247 fprintf(stderr, "Error: %s", error);
251 dbus_message_iter_recurse(iter, &entry);
252 __connmanctl_dbus_print(&entry, " ", " = ", "\n");
253 fprintf(stdout, "\n");
258 static int cmd_state(char *args[], int num, struct connman_option *options)
263 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
264 CONNMAN_PATH, "net.connman.Manager", "GetProperties",
265 state_print, NULL, NULL, NULL);
268 static int services_list(DBusMessageIter *iter, const char *error,
272 __connmanctl_services_list(iter);
273 fprintf(stdout, "\n");
275 fprintf(stderr, "Error: %s\n", error);
281 static int peers_list(DBusMessageIter *iter,
282 const char *error, void *user_data)
285 __connmanctl_peers_list(iter);
286 fprintf(stdout, "\n");
288 fprintf(stderr, "Error: %s\n", error);
293 static int object_properties(DBusMessageIter *iter,
294 const char *error, void *user_data)
296 char *path = user_data;
298 DBusMessageIter dict;
301 fprintf(stdout, "%s\n", path);
303 dbus_message_iter_recurse(iter, &dict);
304 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
306 fprintf(stdout, "\n");
309 str = strrchr(path, '/');
315 fprintf(stderr, "Error %s: %s\n", str, error);
323 static int cmd_services(char *args[], int num, struct connman_option *options)
325 char *service_name = NULL;
332 c = parse_args(args[1], options);
339 service_name = args[2];
344 service_name = args[1];
349 return __connmanctl_dbus_method_call(connection,
350 CONNMAN_SERVICE, CONNMAN_PATH,
351 "net.connman.Manager", "GetServices",
352 services_list, NULL, NULL, NULL);
355 if (check_dbus_name(service_name) == false)
358 path = g_strdup_printf("/net/connman/service/%s", service_name);
359 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
360 "net.connman.Service", "GetProperties",
361 object_properties, path, NULL, NULL);
364 static int cmd_peers(char *args[], int num, struct connman_option *options)
366 char *peer_name = NULL;
376 return __connmanctl_dbus_method_call(connection,
377 CONNMAN_SERVICE, CONNMAN_PATH,
378 "net.connman.Manager", "GetPeers",
379 peers_list, NULL, NULL, NULL);
382 if (check_dbus_name(peer_name) == false)
385 path = g_strdup_printf("/net/connman/peer/%s", peer_name);
386 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
387 path, "net.connman.Peer", "GetProperties",
388 object_properties, path, NULL, NULL);
391 static int technology_print(DBusMessageIter *iter, const char *error,
394 DBusMessageIter array;
397 fprintf(stderr, "Error: %s\n", error);
401 dbus_message_iter_recurse(iter, &array);
402 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
403 DBusMessageIter entry, dict;
406 dbus_message_iter_recurse(&array, &entry);
407 dbus_message_iter_get_basic(&entry, &path);
408 fprintf(stdout, "%s\n", path);
410 dbus_message_iter_next(&entry);
412 dbus_message_iter_recurse(&entry, &dict);
413 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
414 fprintf(stdout, "\n");
416 dbus_message_iter_next(&array);
422 static int cmd_technologies(char *args[], int num,
423 struct connman_option *options)
428 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
429 CONNMAN_PATH, "net.connman.Manager", "GetTechnologies",
430 technology_print, NULL, NULL, NULL);
433 struct tether_enable {
438 static int tether_set_return(DBusMessageIter *iter, const char *error,
441 struct tether_enable *tether = user_data;
444 str = strrchr(tether->path, '/');
451 fprintf(stdout, "%s tethering for %s\n",
452 tether->enable ? "Enabled" : "Disabled",
455 fprintf(stderr, "Error %s %s tethering: %s\n",
457 "enabling" : "disabling", str, error);
459 g_free(tether->path);
465 static int tether_set(char *technology, int set_tethering)
467 struct tether_enable *tether = g_new(struct tether_enable, 1);
469 switch(set_tethering) {
471 tether->enable = TRUE;
474 tether->enable = FALSE;
481 tether->path = g_strdup_printf("/net/connman/technology/%s",
484 return __connmanctl_dbus_set_property(connection, tether->path,
485 "net.connman.Technology", tether_set_return,
486 tether, "Tethering", DBUS_TYPE_BOOLEAN,
490 struct tether_properties {
492 int passphrase_result;
496 static int tether_update(struct tether_properties *tether)
498 if (tether->ssid_result == 0 && tether->passphrase_result == 0)
499 return tether_set("wifi", tether->set_tethering);
501 if (tether->ssid_result != -EINPROGRESS &&
502 tether->passphrase_result != -EINPROGRESS) {
510 static int tether_set_ssid_return(DBusMessageIter *iter, const char *error,
513 struct tether_properties *tether = user_data;
516 fprintf(stdout, "Wifi SSID set\n");
517 tether->ssid_result = 0;
519 fprintf(stderr, "Error setting wifi SSID: %s\n", error);
520 tether->ssid_result = -EINVAL;
523 return tether_update(tether);
526 static int tether_set_passphrase_return(DBusMessageIter *iter,
527 const char *error, void *user_data)
529 struct tether_properties *tether = user_data;
532 fprintf(stdout, "Wifi passphrase set\n");
533 tether->passphrase_result = 0;
535 fprintf(stderr, "Error setting wifi passphrase: %s\n", error);
536 tether->passphrase_result = -EINVAL;
539 return tether_update(tether);
542 static int tether_set_ssid(char *ssid, char *passphrase, int set_tethering)
544 struct tether_properties *tether = g_new(struct tether_properties, 1);
546 tether->set_tethering = set_tethering;
548 tether->ssid_result = __connmanctl_dbus_set_property(connection,
549 "/net/connman/technology/wifi",
550 "net.connman.Technology",
551 tether_set_ssid_return, tether,
552 "TetheringIdentifier", DBUS_TYPE_STRING, &ssid);
554 tether->passphrase_result =__connmanctl_dbus_set_property(connection,
555 "/net/connman/technology/wifi",
556 "net.connman.Technology",
557 tether_set_passphrase_return, tether,
558 "TetheringPassphrase", DBUS_TYPE_STRING, &passphrase);
560 if (tether->ssid_result != -EINPROGRESS &&
561 tether->passphrase_result != -EINPROGRESS) {
569 static int cmd_tether(char *args[], int num, struct connman_option *options)
571 char *ssid, *passphrase;
577 passphrase = args[num - 1];
578 ssid = args[num - 2];
580 set_tethering = parse_boolean(args[2]);
582 if (strcmp(args[1], "wifi") == 0) {
587 if (num == 5 && set_tethering == -1)
594 return tether_set_ssid(ssid, passphrase, set_tethering);
600 if (set_tethering == -1)
603 if (check_dbus_name(args[1]) == false)
606 return tether_set(args[1], set_tethering);
609 static int scan_return(DBusMessageIter *iter, const char *error,
612 char *path = user_data;
615 char *str = strrchr(path, '/');
617 fprintf(stdout, "Scan completed for %s\n", str);
619 fprintf(stderr, "Error %s: %s\n", path, error);
626 static int cmd_scan(char *args[], int num, struct connman_option *options)
636 if (check_dbus_name(args[1]) == false)
639 path = g_strdup_printf("/net/connman/technology/%s", args[1]);
640 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
641 "net.connman.Technology", "Scan",
642 scan_return, path, NULL, NULL);
645 static int connect_return(DBusMessageIter *iter, const char *error,
648 char *path = user_data;
651 char *str = strrchr(path, '/');
653 fprintf(stdout, "Connected %s\n", str);
655 fprintf(stderr, "Error %s: %s\n", path, error);
662 static int cmd_connect(char *args[], int num, struct connman_option *options)
664 const char *iface = "net.connman.Service";
673 if (check_dbus_name(args[1]) == false)
676 if (g_strstr_len(args[1], 5, "peer_") == args[1]) {
677 iface = "net.connman.Peer";
678 path = g_strdup_printf("/net/connman/peer/%s", args[1]);
680 path = g_strdup_printf("/net/connman/service/%s", args[1]);
682 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
683 iface, "Connect", connect_return, path, NULL, NULL);
686 static int disconnect_return(DBusMessageIter *iter, const char *error,
689 char *path = user_data;
692 char *str = strrchr(path, '/');
694 fprintf(stdout, "Disconnected %s\n", str);
696 fprintf(stderr, "Error %s: %s\n", path, error);
703 static int cmd_disconnect(char *args[], int num, struct connman_option *options)
705 const char *iface = "net.connman.Service";
714 if (check_dbus_name(args[1]) == false)
717 if (g_strstr_len(args[1], 5, "peer_") == args[1]) {
718 iface = "net.connman.Peer";
719 path = g_strdup_printf("/net/connman/peer/%s", args[1]);
721 path = g_strdup_printf("/net/connman/service/%s", args[1]);
723 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
724 path, iface, "Disconnect",
725 disconnect_return, path, NULL, NULL);
728 static int config_return(DBusMessageIter *iter, const char *error,
731 char *service_name = user_data;
734 fprintf(stderr, "Error %s: %s\n", service_name, error);
741 struct config_append {
746 static void config_append_ipv4(DBusMessageIter *iter,
749 struct config_append *append = user_data;
750 char **opts = append->opts;
756 while (opts[i] && ipv4[i]) {
757 __connmanctl_dbus_append_dict_entry(iter, ipv4[i],
758 DBUS_TYPE_STRING, &opts[i]);
765 static void config_append_ipv6(DBusMessageIter *iter, void *user_data)
767 struct config_append *append = user_data;
768 char **opts = append->opts;
775 if (g_strcmp0(opts[0], "auto") == 0) {
778 switch (parse_boolean(opts[1])) {
783 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
784 DBUS_TYPE_STRING, &str);
791 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
792 DBUS_TYPE_STRING, &str);
799 if (g_strcmp0(opts[1], "prefered") != 0 &&
802 fprintf(stderr, "Error %s: %s\n",
809 __connmanctl_dbus_append_dict_entry(iter,
810 "Privacy", DBUS_TYPE_STRING,
815 } else if (g_strcmp0(opts[0], "manual") == 0) {
818 while (opts[i] && ipv6[i]) {
820 int value = atoi(opts[i]);
821 __connmanctl_dbus_append_dict_entry(iter,
822 ipv6[i], DBUS_TYPE_BYTE,
825 __connmanctl_dbus_append_dict_entry(iter,
826 ipv6[i], DBUS_TYPE_STRING,
834 } else if (g_strcmp0(opts[0], "off") != 0) {
835 fprintf(stderr, "Error %s: %s\n", opts[0], strerror(EINVAL));
840 __connmanctl_dbus_append_dict_entry(iter, "Method", DBUS_TYPE_STRING,
844 static void config_append_str(DBusMessageIter *iter, void *user_data)
846 struct config_append *append = user_data;
847 char **opts = append->opts;
854 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
862 static void append_servers(DBusMessageIter *iter, void *user_data)
864 struct config_append *append = user_data;
865 char **opts = append->opts;
871 while (opts[i] && g_strcmp0(opts[i], "--excludes") != 0) {
872 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
880 static void append_excludes(DBusMessageIter *iter, void *user_data)
882 struct config_append *append = user_data;
883 char **opts = append->opts;
884 int i = append->values;
886 if (!opts || !opts[i] ||
887 g_strcmp0(opts[i], "--excludes") != 0)
892 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
900 static void config_append_proxy(DBusMessageIter *iter, void *user_data)
902 struct config_append *append = user_data;
903 char **opts = append->opts;
908 if (g_strcmp0(opts[0], "manual") == 0) {
909 __connmanctl_dbus_append_dict_string_array(iter, "Servers",
910 append_servers, append);
912 __connmanctl_dbus_append_dict_string_array(iter, "Excludes",
913 append_excludes, append);
915 } else if (g_strcmp0(opts[0], "auto") == 0) {
917 __connmanctl_dbus_append_dict_entry(iter, "URL",
918 DBUS_TYPE_STRING, &opts[1]);
922 } else if (g_strcmp0(opts[0], "direct") != 0)
925 __connmanctl_dbus_append_dict_entry(iter, "Method",DBUS_TYPE_STRING,
931 static int cmd_config(char *args[], int num, struct connman_option *options)
933 int result = 0, res = 0, index = 2, oldindex = 0;
935 char *service_name, *path;
938 struct config_append append;
940 service_name = args[1];
944 if (check_dbus_name(service_name) == false)
947 while (index < num && args[index]) {
948 c = parse_args(args[index], options);
949 opt_start = &args[index + 1];
950 append.opts = opt_start;
956 path = g_strdup_printf("/net/connman/service/%s", service_name);
960 switch (parse_boolean(*opt_start)) {
975 res = __connmanctl_dbus_set_property(connection,
976 path, "net.connman.Service",
978 g_strdup(service_name),
980 DBUS_TYPE_BOOLEAN, &val);
984 res = __connmanctl_dbus_set_property_dict(connection,
985 path, "net.connman.Service",
986 config_return, g_strdup(service_name),
987 "IPv4.Configuration", DBUS_TYPE_STRING,
988 config_append_ipv4, &append);
989 index += append.values;
993 res = __connmanctl_dbus_set_property_dict(connection,
994 path, "net.connman.Service",
995 config_return, g_strdup(service_name),
996 "IPv6.Configuration", DBUS_TYPE_STRING,
997 config_append_ipv6, &append);
998 index += append.values;
1002 res = __connmanctl_dbus_set_property_array(connection,
1003 path, "net.connman.Service",
1004 config_return, g_strdup(service_name),
1005 "Nameservers.Configuration",
1006 DBUS_TYPE_STRING, config_append_str,
1008 index += append.values;
1012 res = __connmanctl_dbus_set_property_array(connection,
1013 path, "net.connman.Service",
1014 config_return, g_strdup(service_name),
1015 "Timeservers.Configuration",
1016 DBUS_TYPE_STRING, config_append_str,
1018 index += append.values;
1022 res = __connmanctl_dbus_set_property_array(connection,
1023 path, "net.connman.Service",
1024 config_return, g_strdup(service_name),
1025 "Domains.Configuration",
1026 DBUS_TYPE_STRING, config_append_str,
1028 index += append.values;
1032 res = __connmanctl_dbus_set_property_dict(connection,
1033 path, "net.connman.Service",
1034 config_return, g_strdup(service_name),
1035 "Proxy.Configuration",
1036 DBUS_TYPE_STRING, config_append_proxy,
1038 index += append.values;
1041 res = __connmanctl_dbus_method_call(connection,
1042 CONNMAN_SERVICE, path,
1043 "net.connman.Service", "Remove",
1044 config_return, g_strdup(service_name),
1055 if (res == -EINPROGRESS)
1056 result = -EINPROGRESS;
1058 printf("Error '%s': %s\n", args[oldindex],
1069 static DBusHandlerResult monitor_changed(DBusConnection *connection,
1070 DBusMessage *message, void *user_data)
1072 DBusMessageIter iter;
1073 const char *interface, *path;
1075 interface = dbus_message_get_interface(message);
1077 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1079 if (strncmp(interface, "net.connman.", 12) != 0)
1080 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1082 if (!strcmp(interface, "net.connman.Agent") ||
1083 !strcmp(interface, "net.connman.vpn.Agent") ||
1084 !strcmp(interface, "net.connman.Session") ||
1085 !strcmp(interface, "net.connman.Notification"))
1086 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1088 interface = strrchr(interface, '.');
1089 if (interface && *interface != '\0')
1092 path = strrchr(dbus_message_get_path(message), '/');
1093 if (path && *path != '\0')
1096 __connmanctl_save_rl();
1098 if (dbus_message_is_signal(message, "net.connman.Manager",
1099 "ServicesChanged")) {
1101 fprintf(stdout, "%-12s %-20s = {\n", interface,
1103 dbus_message_iter_init(message, &iter);
1104 __connmanctl_services_list(&iter);
1105 fprintf(stdout, "\n}\n");
1107 __connmanctl_redraw_rl();
1109 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1110 } else if (dbus_message_is_signal(message, "net.connman.Manager",
1112 fprintf(stdout, "%-12s %-20s = {\n", interface,
1114 dbus_message_iter_init(message, &iter);
1115 __connmanctl_peers_list(&iter);
1116 fprintf(stdout, "\n}\n");
1118 __connmanctl_redraw_rl();
1120 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1121 } else if (dbus_message_is_signal(message, "net.connman.vpn.Manager",
1122 "ConnectionAdded") ||
1123 dbus_message_is_signal(message,
1124 "net.connman.vpn.Manager",
1125 "ConnectionRemoved")) {
1126 interface = "vpn.Manager";
1127 path = dbus_message_get_member(message);
1129 } else if (dbus_message_is_signal(message, "net.connman.Manager",
1130 "TechnologyAdded") ||
1131 dbus_message_is_signal(message, "net.connman.Manager",
1132 "TechnologyRemoved"))
1133 path = dbus_message_get_member(message);
1135 fprintf(stdout, "%-12s %-20s ", interface, path);
1136 dbus_message_iter_init(message, &iter);
1138 __connmanctl_dbus_print(&iter, "", " = ", " = ");
1139 fprintf(stdout, "\n");
1141 __connmanctl_redraw_rl();
1143 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1150 { "Service", false },
1151 { "Technology", false },
1152 { "Manager", false },
1153 { "vpn.Manager", false },
1154 { "vpn.Connection", false },
1158 static void monitor_add(char *interface)
1160 bool add_filter = true, found = false;
1165 for (i = 0; monitor[i].interface; i++) {
1166 if (monitor[i].enabled == true)
1169 if (g_strcmp0(interface, monitor[i].interface) == 0) {
1170 if (monitor[i].enabled == true)
1173 monitor[i].enabled = true;
1181 if (add_filter == true)
1182 dbus_connection_add_filter(connection, monitor_changed,
1185 dbus_error_init(&err);
1186 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
1188 dbus_bus_add_match(connection, rule, &err);
1191 if (dbus_error_is_set(&err))
1192 fprintf(stderr, "Error: %s\n", err.message);
1195 static void monitor_del(char *interface)
1197 bool del_filter = true, found = false;
1202 for (i = 0; monitor[i].interface; i++) {
1203 if (g_strcmp0(interface, monitor[i].interface) == 0) {
1204 if (monitor[i].enabled == false)
1207 monitor[i].enabled = false;
1211 if (monitor[i].enabled == true)
1218 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
1220 dbus_bus_remove_match(connection, rule, NULL);
1223 if (del_filter == true)
1224 dbus_connection_remove_filter(connection, monitor_changed,
1228 static int cmd_monitor(char *args[], int num, struct connman_option *options)
1237 switch (parse_boolean(args[2])) {
1247 c = parse_args(args[1], options);
1250 monitor_add("Service");
1251 monitor_add("Technology");
1252 monitor_add("Manager");
1253 monitor_add("vpn.Manager");
1254 monitor_add("vpn.Connection");
1259 monitor_add("Service");
1261 monitor_del("Service");
1266 monitor_add("Technology");
1268 monitor_del("Technology");
1273 monitor_add("Manager");
1275 monitor_del("Manager");
1280 monitor_add("vpn.Manager");
1282 monitor_del("vpn.Manager");
1287 monitor_add("vpn.Connection");
1289 monitor_del("vpn.Connection");
1293 switch(parse_boolean(args[1])) {
1295 monitor_del("Service");
1296 monitor_del("Technology");
1297 monitor_del("Manager");
1298 monitor_del("vpn.Manager");
1299 monitor_del("vpn.Connection");
1303 monitor_add("Service");
1304 monitor_add("Technology");
1305 monitor_add("Manager");
1306 monitor_add("vpn.Manager");
1307 monitor_add("vpn.Connection");
1316 return -EINPROGRESS;
1321 static int cmd_agent(char *args[], int num, struct connman_option *options)
1323 if (!__connmanctl_is_interactive()) {
1324 fprintf(stderr, "Error: Not supported in non-interactive "
1335 switch(parse_boolean(args[1])) {
1337 __connmanctl_agent_unregister(connection);
1341 if (__connmanctl_agent_register(connection) == -EINPROGRESS)
1342 return -EINPROGRESS;
1354 static int vpnconnections_properties(DBusMessageIter *iter, const char *error,
1357 char *path = user_data;
1359 DBusMessageIter dict;
1362 fprintf(stdout, "%s\n", path);
1364 dbus_message_iter_recurse(iter, &dict);
1365 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
1367 fprintf(stdout, "\n");
1370 str = strrchr(path, '/');
1376 fprintf(stderr, "Error %s: %s\n", str, error);
1384 static int vpnconnections_list(DBusMessageIter *iter, const char *error,
1388 __connmanctl_vpnconnections_list(iter);
1390 fprintf(stderr, "Error: %s\n", error);
1395 static int cmd_vpnconnections(char *args[], int num,
1396 struct connman_option *options)
1398 char *vpnconnection_name, *path;
1403 vpnconnection_name = args[1];
1405 if (!vpnconnection_name)
1406 return __connmanctl_dbus_method_call(connection,
1407 VPN_SERVICE, VPN_PATH,
1408 "net.connman.vpn.Manager", "GetConnections",
1409 vpnconnections_list, NULL,
1412 if (check_dbus_name(vpnconnection_name) == false)
1415 path = g_strdup_printf("/net/connman/vpn/connection/%s",
1416 vpnconnection_name);
1417 return __connmanctl_dbus_method_call(connection, VPN_SERVICE, path,
1418 "net.connman.vpn.Connection", "GetProperties",
1419 vpnconnections_properties, path, NULL, NULL);
1423 static int cmd_vpnagent(char *args[], int num, struct connman_option *options)
1425 if (!__connmanctl_is_interactive()) {
1426 fprintf(stderr, "Error: Not supported in non-interactive "
1437 switch(parse_boolean(args[1])) {
1439 __connmanctl_vpn_agent_unregister(connection);
1443 if (__connmanctl_vpn_agent_register(connection) ==
1445 return -EINPROGRESS;
1457 static DBusMessage *session_release(DBusConnection *connection,
1458 DBusMessage *message, void *user_data)
1460 __connmanctl_save_rl();
1462 fprintf(stdout, "Session %s released\n", session_path);
1464 __connmanctl_redraw_rl();
1466 g_free(session_path);
1467 session_path = NULL;
1468 session_connected = false;
1470 return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
1473 static DBusMessage *session_update(DBusConnection *connection,
1474 DBusMessage *message, void *user_data)
1476 DBusMessageIter iter, dict;
1478 __connmanctl_save_rl();
1480 fprintf(stdout, "Session Update = {\n");
1482 dbus_message_iter_init(message, &iter);
1483 dbus_message_iter_recurse(&iter, &dict);
1485 __connmanctl_dbus_print(&dict, "", " = ", "\n");
1486 fprintf(stdout, "\n}\n");
1488 dbus_message_iter_recurse(&iter, &dict);
1490 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1491 DBusMessageIter entry, variant;
1492 char *field, *state;
1494 dbus_message_iter_recurse(&dict, &entry);
1496 dbus_message_iter_get_basic(&entry, &field);
1498 if (dbus_message_iter_get_arg_type(&entry)
1500 && !strcmp(field, "State")) {
1502 dbus_message_iter_next(&entry);
1503 dbus_message_iter_recurse(&entry, &variant);
1504 if (dbus_message_iter_get_arg_type(&variant)
1505 != DBUS_TYPE_STRING)
1508 dbus_message_iter_get_basic(&variant, &state);
1510 if (!session_connected && (!strcmp(state, "connected")
1511 || !strcmp(state, "online"))) {
1513 fprintf(stdout, "Session %s connected\n",
1515 session_connected = true;
1520 if (!strcmp(state, "disconnected") &&
1521 session_connected) {
1523 fprintf(stdout, "Session %s disconnected\n",
1525 session_connected = false;
1530 dbus_message_iter_next(&dict);
1533 __connmanctl_redraw_rl();
1535 return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
1538 static const GDBusMethodTable notification_methods[] = {
1539 { GDBUS_METHOD("Release", NULL, NULL, session_release) },
1540 { GDBUS_METHOD("Update", GDBUS_ARGS({"settings", "a{sv}"}),
1541 NULL, session_update) },
1545 static int session_notify_add(const char *path)
1547 if (session_notify_path)
1550 if (!g_dbus_register_interface(connection, path,
1551 "net.connman.Notification",
1552 notification_methods, NULL, NULL,
1554 fprintf(stderr, "Error: Failed to register VPN Agent "
1559 session_notify_path = g_strdup(path);
1564 static void session_notify_remove(void)
1566 if (!session_notify_path)
1569 g_dbus_unregister_interface(connection, session_notify_path,
1570 "net.connman.Notification");
1572 g_free(session_notify_path);
1573 session_notify_path = NULL;
1576 static int session_connect_cb(DBusMessageIter *iter, const char *error,
1580 fprintf(stderr, "Error: %s", error);
1584 return -EINPROGRESS;
1588 static int session_connect(void)
1590 return __connmanctl_dbus_method_call(connection, "net.connman",
1591 session_path, "net.connman.Session", "Connect",
1592 session_connect_cb, NULL, NULL, NULL);
1595 static int session_disconnect_cb(DBusMessageIter *iter, const char *error,
1599 fprintf(stderr, "Error: %s", error);
1604 static int session_disconnect(void)
1606 return __connmanctl_dbus_method_call(connection, "net.connman",
1607 session_path, "net.connman.Session", "Disconnect",
1608 session_disconnect_cb, NULL, NULL, NULL);
1611 static int session_create_cb(DBusMessageIter *iter, const char *error,
1614 gboolean connect = GPOINTER_TO_INT(user_data);
1618 fprintf(stderr, "Error creating session: %s", error);
1619 session_notify_remove();
1623 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH) {
1624 fprintf(stderr, "Error creating session: No session path\n");
1628 g_free(session_path);
1630 dbus_message_iter_get_basic(iter, &str);
1631 session_path = g_strdup(str);
1633 fprintf(stdout, "Session %s created\n", session_path);
1636 return session_connect();
1638 return -EINPROGRESS;
1641 static void session_create_append(DBusMessageIter *iter, void *user_data)
1643 const char *notify_path = user_data;
1645 __connmanctl_dbus_append_dict(iter, NULL, NULL);
1647 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
1651 static int session_create(gboolean connect)
1656 notify_path = g_strdup_printf("/net/connman/connmanctl%d", getpid());
1657 session_notify_add(notify_path);
1659 res = __connmanctl_dbus_method_call(connection, "net.connman", "/",
1660 "net.connman.Manager", "CreateSession",
1661 session_create_cb, GINT_TO_POINTER(connect),
1662 session_create_append, notify_path);
1664 g_free(notify_path);
1666 if (res < 0 && res != -EINPROGRESS)
1667 session_notify_remove();
1672 static int session_destroy_cb(DBusMessageIter *iter, const char *error,
1676 fprintf(stderr, "Error destroying session: %s", error);
1680 fprintf(stdout, "Session %s ended\n", session_path);
1682 g_free(session_path);
1683 session_path = NULL;
1684 session_connected = false;
1689 static void session_destroy_append(DBusMessageIter *iter, void *user_data)
1691 const char *path = user_data;
1693 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
1696 static int session_destroy(void)
1698 return __connmanctl_dbus_method_call(connection, "net.connman", "/",
1699 "net.connman.Manager", "DestroySession",
1700 session_destroy_cb, NULL,
1701 session_destroy_append, session_path);
1704 static int session_config_return(DBusMessageIter *iter, const char *error,
1707 char *property_name = user_data;
1710 fprintf(stderr, "Error setting session %s: %s\n",
1711 property_name, error);
1716 static void session_config_append_array(DBusMessageIter *iter,
1719 struct config_append *append = user_data;
1720 char **opts = append->opts;
1726 while (opts[i] && strncmp(opts[i], "--", 2) != 0) {
1727 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1735 static int session_config(char *args[], int num,
1736 struct connman_option *options)
1738 int index = 0, res = 0;
1739 struct config_append append;
1742 while (index < num && args[index]) {
1743 append.opts = &args[index];
1746 c = parse_args(args[index], options);
1750 res = __connmanctl_dbus_session_change_array(connection,
1751 session_path, session_config_return,
1752 "AllowedBearers", "AllowedBearers",
1753 session_config_append_array, &append);
1756 if (!args[index + 1]) {
1761 res = __connmanctl_dbus_session_change(connection,
1762 session_path, session_config_return,
1763 "ConnectionType", "ConnectionType",
1764 DBUS_TYPE_STRING, &args[index + 1]);
1772 if (res < 0 && res != -EINPROGRESS) {
1773 printf("Error '%s': %s\n", args[index],
1778 index += append.values;
1784 static int cmd_session(char *args[], int num, struct connman_option *options)
1793 switch(parse_boolean(command)) {
1797 return session_destroy();
1802 return session_create(FALSE);
1805 if (!strcmp(command, "connect")) {
1807 return session_create(TRUE);
1809 return session_connect();
1811 } else if (!strcmp(command, "disconnect")) {
1813 if (!session_path) {
1814 fprintf(stdout, "Session does not exist\n");
1818 return session_disconnect();
1819 } else if (!strcmp(command, "config")) {
1820 if (!session_path) {
1821 fprintf(stdout, "Session does not exist\n");
1828 return session_config(&args[2], num - 2, options);
1836 static int cmd_exit(char *args[], int num, struct connman_option *options)
1841 static char *lookup_service(const char *text, int state)
1844 static GHashTableIter iter;
1845 gpointer key, value;
1848 g_hash_table_iter_init(&iter, service_hash);
1852 while (g_hash_table_iter_next(&iter, &key, &value)) {
1853 const char *service = key;
1854 if (strncmp(text, service, len) == 0)
1855 return strdup(service);
1861 static char *lookup_service_arg(const char *text, int state)
1863 if (__connmanctl_input_calc_level() > 1) {
1864 __connmanctl_input_lookup_end();
1868 return lookup_service(text, state);
1871 static char *lookup_peer(const char *text, int state)
1873 static GHashTableIter iter;
1874 gpointer key, value;
1878 g_hash_table_iter_init(&iter, peer_hash);
1882 while (g_hash_table_iter_next(&iter, &key, &value)) {
1883 const char *peer = key;
1884 if (strncmp(text, peer, len) == 0)
1885 return strdup(peer);
1891 static char *lookup_peer_arg(const char *text, int state)
1893 if (__connmanctl_input_calc_level() > 1) {
1894 __connmanctl_input_lookup_end();
1898 return lookup_peer(text, state);
1901 static char *lookup_technology(const char *text, int state)
1904 static GHashTableIter iter;
1905 gpointer key, value;
1908 g_hash_table_iter_init(&iter, technology_hash);
1912 while (g_hash_table_iter_next(&iter, &key, &value)) {
1913 const char *technology = key;
1914 if (strncmp(text, technology, len) == 0)
1915 return strdup(technology);
1921 static char *lookup_technology_arg(const char *text, int state)
1923 if (__connmanctl_input_calc_level() > 1) {
1924 __connmanctl_input_lookup_end();
1928 return lookup_technology(text, state);
1931 static char *lookup_technology_offline(const char *text, int state)
1934 static bool end = false;
1937 if (__connmanctl_input_calc_level() > 1) {
1938 __connmanctl_input_lookup_end();
1950 str = lookup_technology(text, state);
1956 if (strncmp(text, "offline", len) == 0)
1957 return strdup("offline");
1962 static char *lookup_on_off(const char *text, int state)
1964 char *onoff[] = { "on", "off", NULL };
1975 while (onoff[idx]) {
1979 if (!strncmp(text, str, len))
1986 static char *lookup_tether(const char *text, int state)
1990 level = __connmanctl_input_calc_level();
1992 return lookup_technology(text, state);
1995 return lookup_on_off(text, state);
1997 __connmanctl_input_lookup_end();
2002 static char *lookup_agent(const char *text, int state)
2004 if (__connmanctl_input_calc_level() > 1) {
2005 __connmanctl_input_lookup_end();
2009 return lookup_on_off(text, state);
2012 static struct connman_option service_options[] = {
2013 {"properties", 'p', "[<service>] (obsolete)"},
2017 static struct connman_option config_options[] = {
2018 {"nameservers", 'n', "<dns1> [<dns2>] [<dns3>]"},
2019 {"timeservers", 't', "<ntp1> [<ntp2>] [...]"},
2020 {"domains", 'd', "<domain1> [<domain2>] [...]"},
2021 {"ipv6", 'v', "off|auto [enable|disable|preferred]|\n"
2022 "\t\t\tmanual <address> <prefixlength> <gateway>"},
2023 {"proxy", 'x', "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
2024 "\t\t\t[exclude <exclude1> [<exclude2>] [...]]"},
2025 {"autoconnect", 'a', "yes|no"},
2026 {"ipv4", 'i', "off|dhcp|manual <address> <netmask> <gateway>"},
2027 {"remove", 'r', " Remove service"},
2031 static struct connman_option monitor_options[] = {
2032 {"services", 's', "[off] Monitor only services"},
2033 {"tech", 'c', "[off] Monitor only technologies"},
2034 {"manager", 'm', "[off] Monitor only manager interface"},
2035 {"vpnmanager", 'M', "[off] Monitor only VPN manager "
2037 {"vpnconnection", 'C', "[off] Monitor only VPN "
2042 static struct connman_option session_options[] = {
2043 {"bearers", 'b', "<technology1> [<technology2> [...]]"},
2044 {"type", 't', "local|internet|any"},
2048 static char *lookup_options(struct connman_option *options, const char *text,
2060 while (options[idx].name) {
2061 str = options[idx].name;
2064 if (str && strncmp(text, str, len) == 0)
2071 static char *lookup_monitor(const char *text, int state)
2075 level = __connmanctl_input_calc_level();
2078 return lookup_options(monitor_options, text, state);
2081 return lookup_on_off(text, state);
2083 __connmanctl_input_lookup_end();
2087 static char *lookup_config(const char *text, int state)
2089 if (__connmanctl_input_calc_level() < 2)
2090 return lookup_service(text, state);
2092 return lookup_options(config_options, text, state);
2095 static char *lookup_session(const char *text, int state)
2097 return lookup_options(session_options, text, state);
2100 static int peer_service_cb(DBusMessageIter *iter, const char *error,
2103 bool registration = GPOINTER_TO_INT(user_data);
2106 fprintf(stderr, "Error %s peer service: %s\n",
2107 registration ? "registering" : "unregistering", error);
2109 fprintf(stdout, "Peer service %s\n",
2110 registration ? "registered" : "unregistered");
2115 struct _peer_service {
2116 unsigned char *bjr_query;
2118 unsigned char *bjr_response;
2119 int bjr_response_len;
2120 unsigned char *wfd_ies;
2127 static void append_dict_entry_fixed_array(DBusMessageIter *iter,
2128 const char *property, void *value, int length)
2130 DBusMessageIter dict_entry, variant, array;
2132 dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY,
2134 dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING,
2136 dbus_message_iter_open_container(&dict_entry, DBUS_TYPE_VARIANT,
2137 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
2139 dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
2140 DBUS_TYPE_BYTE_AS_STRING, &array);
2141 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
2143 dbus_message_iter_close_container(&variant, &array);
2144 dbus_message_iter_close_container(&dict_entry, &variant);
2145 dbus_message_iter_close_container(iter, &dict_entry);
2148 static void append_peer_service_dict(DBusMessageIter *iter, void *user_data)
2150 struct _peer_service *service = user_data;
2152 if (service->bjr_query && service->bjr_response) {
2153 append_dict_entry_fixed_array(iter, "BonjourQuery",
2154 &service->bjr_query, service->bjr_query_len);
2155 append_dict_entry_fixed_array(iter, "BonjourResponse",
2156 &service->bjr_response, service->bjr_response_len);
2157 } else if (service->upnp_service && service->version) {
2158 __connmanctl_dbus_append_dict_entry(iter, "UpnpVersion",
2159 DBUS_TYPE_INT32, &service->version);
2160 __connmanctl_dbus_append_dict_entry(iter, "UpnpService",
2161 DBUS_TYPE_STRING, &service->upnp_service);
2162 } else if (service->wfd_ies) {
2163 append_dict_entry_fixed_array(iter, "WiFiDisplayIEs",
2164 &service->wfd_ies, service->wfd_ies_len);
2168 static void peer_service_append(DBusMessageIter *iter, void *user_data)
2170 struct _peer_service *service = user_data;
2173 __connmanctl_dbus_append_dict(iter, append_peer_service_dict, service);
2175 if (service->master < 0)
2178 master = service->master == 1 ? TRUE : FALSE;
2179 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &master);
2182 static struct _peer_service *fill_in_peer_service(unsigned char *bjr_query,
2183 int bjr_query_len, unsigned char *bjr_response,
2184 int bjr_response_len, char *upnp_service,
2185 int version, unsigned char *wfd_ies,
2188 struct _peer_service *service;
2190 service = dbus_malloc0(sizeof(*service));
2192 if (bjr_query_len && bjr_response_len) {
2193 service->bjr_query = dbus_malloc0(bjr_query_len);
2194 memcpy(service->bjr_query, bjr_query, bjr_query_len);
2195 service->bjr_query_len = bjr_query_len;
2197 service->bjr_response = dbus_malloc0(bjr_response_len);
2198 memcpy(service->bjr_response, bjr_response, bjr_response_len);
2199 service->bjr_response_len = bjr_response_len;
2200 } else if (upnp_service && version) {
2201 service->upnp_service = strdup(upnp_service);
2202 service->version = version;
2203 } else if (wfd_ies && wfd_ies_len) {
2204 service->wfd_ies = dbus_malloc0(wfd_ies_len);
2205 memcpy(service->wfd_ies, wfd_ies, wfd_ies_len);
2206 service->wfd_ies_len = wfd_ies_len;
2215 static void free_peer_service(struct _peer_service *service)
2217 dbus_free(service->bjr_query);
2218 dbus_free(service->bjr_response);
2219 dbus_free(service->wfd_ies);
2220 free(service->upnp_service);
2224 static int peer_service_register(unsigned char *bjr_query, int bjr_query_len,
2225 unsigned char *bjr_response, int bjr_response_len,
2226 char *upnp_service, int version,
2227 unsigned char *wfd_ies, int wfd_ies_len, int master)
2229 struct _peer_service *service;
2230 bool registration = true;
2233 service = fill_in_peer_service(bjr_query, bjr_query_len, bjr_response,
2234 bjr_response_len, upnp_service, version,
2235 wfd_ies, wfd_ies_len);
2239 service->master = master;
2241 ret = __connmanctl_dbus_method_call(connection, "net.connman", "/",
2242 "net.connman.Manager", "RegisterPeerService",
2243 peer_service_cb, GINT_TO_POINTER(registration),
2244 peer_service_append, service);
2246 free_peer_service(service);
2251 static int peer_service_unregister(unsigned char *bjr_query, int bjr_query_len,
2252 unsigned char *bjr_response, int bjr_response_len,
2253 char *upnp_service, int version,
2254 unsigned char *wfd_ies, int wfd_ies_len)
2256 struct _peer_service *service;
2257 bool registration = false;
2260 service = fill_in_peer_service(bjr_query, bjr_query_len, bjr_response,
2261 bjr_response_len, upnp_service, version,
2262 wfd_ies, wfd_ies_len);
2266 service->master = -1;
2268 ret = __connmanctl_dbus_method_call(connection, "net.connman", "/",
2269 "net.connman.Manager", "UnregisterPeerService",
2270 peer_service_cb, GINT_TO_POINTER(registration),
2271 peer_service_append, service);
2273 free_peer_service(service);
2278 static int parse_spec_array(char *command, unsigned char spec[1024])
2280 int length, pos, end;
2284 end = strlen(command);
2285 for (e = NULL, length = pos = 0; command[pos] != '\0'; length++) {
2289 b[0] = command[pos];
2290 b[1] = command[pos+1];
2292 spec[length] = strtol(b, &e, 16);
2293 if (e && *e != '\0')
2302 static int cmd_peer_service(char *args[], int num,
2303 struct connman_option *options)
2305 unsigned char bjr_query[1024] = {};
2306 unsigned char bjr_response[1024] = {};
2307 unsigned char wfd_ies[1024] = {};
2308 char *upnp_service = NULL;
2309 int bjr_query_len = 0, bjr_response_len = 0;
2310 int version = 0, master = 0, wfd_ies_len = 0;
2316 if (!strcmp(args[2], "wfd_ies")) {
2317 wfd_ies_len = parse_spec_array(args[3], wfd_ies);
2318 if (wfd_ies_len == -EINVAL)
2328 if (!strcmp(args[2], "bjr_query")) {
2329 if (strcmp(args[4], "bjr_response"))
2331 bjr_query_len = parse_spec_array(args[3], bjr_query);
2332 bjr_response_len = parse_spec_array(args[5], bjr_response);
2334 if (bjr_query_len == -EINVAL || bjr_response_len == -EINVAL)
2336 } else if (!strcmp(args[2], "upnp_service")) {
2339 if (strcmp(args[4], "upnp_version"))
2341 upnp_service = args[3];
2342 version = strtol(args[5], &e, 10);
2349 master = parse_boolean(args[6]);
2354 if (!strcmp(args[1], "register")) {
2355 return peer_service_register(bjr_query, bjr_query_len,
2356 bjr_response, bjr_response_len, upnp_service,
2357 version, wfd_ies, wfd_ies_len, master);
2358 } else if (!strcmp(args[1], "unregister")) {
2359 return peer_service_unregister(bjr_query, bjr_query_len,
2360 bjr_response, bjr_response_len, upnp_service,
2361 version, wfd_ies, wfd_ies_len);
2367 static const struct {
2369 const char *argument;
2370 struct connman_option *options;
2371 int (*func) (char *args[], int num, struct connman_option *options);
2373 __connmanctl_lookup_cb cb;
2375 { "state", NULL, NULL, cmd_state,
2376 "Shows if the system is online or offline", NULL },
2377 { "technologies", NULL, NULL, cmd_technologies,
2378 "Display technologies", NULL },
2379 { "enable", "<technology>|offline", NULL, cmd_enable,
2380 "Enables given technology or offline mode",
2381 lookup_technology_offline },
2382 { "disable", "<technology>|offline", NULL, cmd_disable,
2383 "Disables given technology or offline mode",
2384 lookup_technology_offline },
2385 { "tether", "<technology> on|off\n"
2386 " wifi [on|off] <ssid> <passphrase> ",
2388 "Enable, disable tethering, set SSID and passphrase for wifi",
2390 { "services", "[<service>]", service_options, cmd_services,
2391 "Display services", lookup_service_arg },
2392 { "peers", "[peer]", NULL, cmd_peers,
2393 "Display peers", lookup_peer_arg },
2394 { "scan", "<technology>", NULL, cmd_scan,
2395 "Scans for new services for given technology",
2396 lookup_technology_arg },
2397 { "connect", "<service/peer>", NULL, cmd_connect,
2398 "Connect a given service or peer", lookup_service_arg },
2399 { "disconnect", "<service/peer>", NULL, cmd_disconnect,
2400 "Disconnect a given service or peer", lookup_service_arg },
2401 { "config", "<service>", config_options, cmd_config,
2402 "Set service configuration options", lookup_config },
2403 { "monitor", "[off]", monitor_options, cmd_monitor,
2404 "Monitor signals from interfaces", lookup_monitor },
2405 { "agent", "on|off", NULL, cmd_agent,
2406 "Agent mode", lookup_agent },
2407 {"vpnconnections", "[<connection>]", NULL, cmd_vpnconnections,
2408 "Display VPN connections", NULL },
2409 { "vpnagent", "on|off", NULL, cmd_vpnagent,
2410 "VPN Agent mode", lookup_agent },
2411 { "session", "on|off|connect|disconnect|config", session_options,
2412 cmd_session, "Enable or disable a session", lookup_session },
2413 { "peer_service", "register|unregister <specs> <master>\n"
2414 "Where specs are:\n"
2415 "\tbjr_query <query> bjr_response <response>\n"
2416 "\tupnp_service <service> upnp_version <version>\n"
2417 "\twfd_ies <ies>\n", NULL,
2418 cmd_peer_service, "(Un)Register a Peer Service", NULL },
2419 { "help", NULL, NULL, cmd_help,
2420 "Show help", NULL },
2421 { "exit", NULL, NULL, cmd_exit,
2423 { "quit", NULL, NULL, cmd_exit,
2428 static int cmd_help(char *args[], int num, struct connman_option *options)
2430 bool interactive = __connmanctl_is_interactive();
2433 if (interactive == false)
2434 fprintf(stdout, "Usage: connmanctl [[command] [args]]\n");
2436 for (i = 0; cmd_table[i].cmd; i++) {
2437 const char *cmd = cmd_table[i].cmd;
2438 const char *argument = cmd_table[i].argument;
2439 const char *desc = cmd_table[i].desc;
2441 printf("%-16s%-22s%s\n", cmd? cmd: "",
2442 argument? argument: "",
2445 if (cmd_table[i].options) {
2446 for (j = 0; cmd_table[i].options[j].name;
2448 const char *options_desc =
2449 cmd_table[i].options[j].desc ?
2450 cmd_table[i].options[j].desc: "";
2452 printf(" --%-16s%s\n",
2453 cmd_table[i].options[j].name,
2459 if (interactive == false)
2460 fprintf(stdout, "\nNote: arguments and output are considered "
2461 "EXPERIMENTAL for now.\n");
2466 __connmanctl_lookup_cb __connmanctl_get_lookup_func(const char *text)
2468 int i, cmdlen, textlen;
2473 textlen = strlen(text);
2475 for (i = 0; cmd_table[i].cmd; i++) {
2476 cmdlen = strlen(cmd_table[i].cmd);
2478 if (textlen > cmdlen && text[cmdlen] != ' ')
2481 if (strncmp(cmd_table[i].cmd, text, cmdlen) == 0)
2482 return cmd_table[i].cb;
2488 int __connmanctl_commands(DBusConnection *dbus_conn, char *argv[], int argc)
2492 connection = dbus_conn;
2494 for (i = 0; cmd_table[i].cmd; i++) {
2495 if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
2496 cmd_table[i].func) {
2497 result = cmd_table[i].func(argv, argc,
2498 cmd_table[i].options);
2499 if (result < 0 && result != -EINPROGRESS)
2500 fprintf(stderr, "Error '%s': %s\n", argv[0],
2506 fprintf(stderr, "Error '%s': Unknown command\n", argv[0]);
2510 char *__connmanctl_lookup_command(const char *text, int state)
2520 while (cmd_table[i].cmd) {
2521 const char *command = cmd_table[i].cmd;
2525 if (strncmp(text, command, len) == 0)
2526 return strdup(command);
2532 static char *get_path(char *full_path)
2536 path = strrchr(full_path, '/');
2537 if (path && *path != '\0')
2545 static void add_service_id(const char *path)
2547 g_hash_table_replace(service_hash, g_strdup(path),
2548 GINT_TO_POINTER(TRUE));
2551 static void remove_service_id(const char *path)
2553 g_hash_table_remove(service_hash, path);
2556 static void services_added(DBusMessageIter *iter)
2558 DBusMessageIter array;
2561 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
2563 dbus_message_iter_recurse(iter, &array);
2564 if (dbus_message_iter_get_arg_type(&array) !=
2565 DBUS_TYPE_OBJECT_PATH)
2568 dbus_message_iter_get_basic(&array, &path);
2569 add_service_id(get_path(path));
2571 dbus_message_iter_next(iter);
2575 static void update_services(DBusMessageIter *iter)
2577 DBusMessageIter array;
2580 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2583 dbus_message_iter_recurse(iter, &array);
2584 services_added(&array);
2586 dbus_message_iter_next(iter);
2587 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2590 dbus_message_iter_recurse(iter, &array);
2591 while (dbus_message_iter_get_arg_type(&array) ==
2592 DBUS_TYPE_OBJECT_PATH) {
2593 dbus_message_iter_get_basic(&array, &path);
2594 remove_service_id(get_path(path));
2596 dbus_message_iter_next(&array);
2600 static int populate_service_hash(DBusMessageIter *iter, const char *error,
2604 fprintf(stderr, "Error getting services: %s", error);
2608 update_services(iter);
2612 static void add_peer_id(const char *path)
2614 g_hash_table_replace(peer_hash, g_strdup(path), GINT_TO_POINTER(TRUE));
2617 static void remove_peer_id(const char *path)
2619 g_hash_table_remove(peer_hash, path);
2622 static void peers_added(DBusMessageIter *iter)
2624 DBusMessageIter array;
2627 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
2629 dbus_message_iter_recurse(iter, &array);
2630 if (dbus_message_iter_get_arg_type(&array) !=
2631 DBUS_TYPE_OBJECT_PATH)
2634 dbus_message_iter_get_basic(&array, &path);
2635 add_peer_id(get_path(path));
2637 dbus_message_iter_next(iter);
2641 static void update_peers(DBusMessageIter *iter)
2643 DBusMessageIter array;
2646 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2649 dbus_message_iter_recurse(iter, &array);
2650 peers_added(&array);
2652 dbus_message_iter_next(iter);
2653 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2656 dbus_message_iter_recurse(iter, &array);
2657 while (dbus_message_iter_get_arg_type(&array) ==
2658 DBUS_TYPE_OBJECT_PATH) {
2659 dbus_message_iter_get_basic(&array, &path);
2660 remove_peer_id(get_path(path));
2662 dbus_message_iter_next(&array);
2666 static int populate_peer_hash(DBusMessageIter *iter,
2667 const char *error, void *user_data)
2670 fprintf(stderr, "Error getting peers: %s", error);
2678 static void add_technology_id(const char *path)
2680 g_hash_table_replace(technology_hash, g_strdup(path),
2681 GINT_TO_POINTER(TRUE));
2684 static void remove_technology_id(const char *path)
2686 g_hash_table_remove(technology_hash, path);
2689 static void remove_technology(DBusMessageIter *iter)
2693 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
2696 dbus_message_iter_get_basic(iter, &path);
2697 remove_technology_id(get_path(path));
2700 static void add_technology(DBusMessageIter *iter)
2704 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
2707 dbus_message_iter_get_basic(iter, &path);
2708 add_technology_id(get_path(path));
2711 static void update_technologies(DBusMessageIter *iter)
2713 DBusMessageIter array;
2715 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2718 dbus_message_iter_recurse(iter, &array);
2720 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
2721 DBusMessageIter object_path;
2723 dbus_message_iter_recurse(&array, &object_path);
2725 add_technology(&object_path);
2727 dbus_message_iter_next(&array);
2731 static int populate_technology_hash(DBusMessageIter *iter, const char *error,
2735 fprintf(stderr, "Error getting technologies: %s", error);
2739 update_technologies(iter);
2744 static DBusHandlerResult monitor_completions_changed(
2745 DBusConnection *connection,
2746 DBusMessage *message, void *user_data)
2748 bool *enabled = user_data;
2749 DBusMessageIter iter;
2750 DBusHandlerResult handled;
2753 handled = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2755 handled = DBUS_HANDLER_RESULT_HANDLED;
2757 if (dbus_message_is_signal(message, "net.connman.Manager",
2758 "ServicesChanged")) {
2759 dbus_message_iter_init(message, &iter);
2760 update_services(&iter);
2764 if (dbus_message_is_signal(message, "net.connman.Manager",
2766 dbus_message_iter_init(message, &iter);
2767 update_peers(&iter);
2771 if (dbus_message_is_signal(message, "net.connman.Manager",
2772 "TechnologyAdded")) {
2773 dbus_message_iter_init(message, &iter);
2774 add_technology(&iter);
2778 if (dbus_message_is_signal(message, "net.connman.Manager",
2779 "TechnologyRemoved")) {
2780 dbus_message_iter_init(message, &iter);
2781 remove_technology(&iter);
2785 if (!g_strcmp0(dbus_message_get_interface(message),
2786 "net.connman.Manager"))
2789 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2792 void __connmanctl_monitor_completions(DBusConnection *dbus_conn)
2794 bool *manager_enabled = NULL;
2798 for (i = 0; monitor[i].interface; i++) {
2799 if (!strcmp(monitor[i].interface, "Manager")) {
2800 manager_enabled = &monitor[i].enabled;
2806 g_hash_table_destroy(service_hash);
2807 g_hash_table_destroy(technology_hash);
2809 dbus_bus_remove_match(connection,
2810 "type='signal',interface='net.connman.Manager'", NULL);
2811 dbus_connection_remove_filter(connection,
2812 monitor_completions_changed,
2817 connection = dbus_conn;
2819 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2822 peer_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2825 technology_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2828 __connmanctl_dbus_method_call(connection,
2829 CONNMAN_SERVICE, CONNMAN_PATH,
2830 "net.connman.Manager", "GetServices",
2831 populate_service_hash, NULL, NULL, NULL);
2833 __connmanctl_dbus_method_call(connection,
2834 CONNMAN_SERVICE, CONNMAN_PATH,
2835 "net.connman.Manager", "GetPeers",
2836 populate_peer_hash, NULL, NULL, NULL);
2838 __connmanctl_dbus_method_call(connection,
2839 CONNMAN_SERVICE, CONNMAN_PATH,
2840 "net.connman.Manager", "GetTechnologies",
2841 populate_technology_hash, NULL, NULL, NULL);
2843 dbus_connection_add_filter(connection,
2844 monitor_completions_changed, manager_enabled,
2847 dbus_error_init(&err);
2848 dbus_bus_add_match(connection,
2849 "type='signal',interface='net.connman.Manager'", &err);
2851 if (dbus_error_is_set(&err))
2852 fprintf(stderr, "Error: %s\n", err.message);