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>
38 #include "dbus_helpers.h"
44 #include "vpnconnections.h"
46 static DBusConnection *connection;
47 static GHashTable *service_hash;
48 static GHashTable *peer_hash;
49 static GHashTable *technology_hash;
50 static char *session_notify_path;
51 static char *session_path;
52 static bool session_connected;
54 struct connman_option {
60 static char *ipv4[] = {
68 static char *ipv6[] = {
76 static int cmd_help(char *args[], int num, struct connman_option *options);
78 static bool check_dbus_name(const char *name)
81 * Valid dbus chars should be [A-Z][a-z][0-9]_
82 * and should not start with number.
86 if (!name || name[0] == '\0')
89 for (i = 0; name[i] != '\0'; i++)
90 if (!((name[i] >= 'A' && name[i] <= 'Z') ||
91 (name[i] >= 'a' && name[i] <= 'z') ||
92 (name[i] >= '0' && name[i] <= '9') ||
99 static int parse_boolean(char *arg)
104 if (strcasecmp(arg, "no") == 0 ||
105 strcasecmp(arg, "false") == 0 ||
106 strcasecmp(arg, "off" ) == 0 ||
107 strcasecmp(arg, "disable" ) == 0 ||
108 strcasecmp(arg, "n") == 0 ||
109 strcasecmp(arg, "f") == 0 ||
110 strcasecmp(arg, "0") == 0)
113 if (strcasecmp(arg, "yes") == 0 ||
114 strcasecmp(arg, "true") == 0 ||
115 strcasecmp(arg, "on") == 0 ||
116 strcasecmp(arg, "enable" ) == 0 ||
117 strcasecmp(arg, "y") == 0 ||
118 strcasecmp(arg, "t") == 0 ||
119 strcasecmp(arg, "1") == 0)
125 static int parse_args(char *arg, struct connman_option *options)
132 for (i = 0; options[i].name; i++) {
133 if (strcmp(options[i].name, arg) == 0 ||
134 (strncmp(arg, "--", 2) == 0 &&
135 strcmp(&arg[2], options[i].name) == 0))
136 return options[i].val;
142 static int enable_return(DBusMessageIter *iter, const char *error,
145 char *tech = user_data;
148 str = strrchr(tech, '/');
155 fprintf(stdout, "Enabled %s\n", str);
157 fprintf(stderr, "Error %s: %s\n", str, error);
164 static int cmd_enable(char *args[], int num, struct connman_option *options)
167 dbus_bool_t b = TRUE;
175 if (check_dbus_name(args[1]) == false)
178 if (strcmp(args[1], "offline") == 0) {
179 tech = g_strdup(args[1]);
180 return __connmanctl_dbus_set_property(connection, "/",
181 "net.connman.Manager", enable_return, tech,
182 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
185 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
186 return __connmanctl_dbus_set_property(connection, tech,
187 "net.connman.Technology", enable_return, tech,
188 "Powered", DBUS_TYPE_BOOLEAN, &b);
191 static int disable_return(DBusMessageIter *iter, const char *error,
194 char *tech = user_data;
197 str = strrchr(tech, '/');
204 fprintf(stdout, "Disabled %s\n", str);
206 fprintf(stderr, "Error %s: %s\n", str, error);
213 static int cmd_disable(char *args[], int num, struct connman_option *options)
216 dbus_bool_t b = FALSE;
224 if (check_dbus_name(args[1]) == false)
227 if (strcmp(args[1], "offline") == 0) {
228 tech = g_strdup(args[1]);
229 return __connmanctl_dbus_set_property(connection, "/",
230 "net.connman.Manager", disable_return, tech,
231 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
234 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
235 return __connmanctl_dbus_set_property(connection, tech,
236 "net.connman.Technology", disable_return, tech,
237 "Powered", DBUS_TYPE_BOOLEAN, &b);
240 static int state_print(DBusMessageIter *iter, const char *error,
243 DBusMessageIter entry;
246 fprintf(stderr, "Error: %s", error);
250 dbus_message_iter_recurse(iter, &entry);
251 __connmanctl_dbus_print(&entry, " ", " = ", "\n");
252 fprintf(stdout, "\n");
257 static int cmd_state(char *args[], int num, struct connman_option *options)
262 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
263 CONNMAN_PATH, "net.connman.Manager", "GetProperties",
264 state_print, NULL, NULL, NULL);
267 static int services_list(DBusMessageIter *iter, const char *error,
271 __connmanctl_services_list(iter);
272 fprintf(stdout, "\n");
274 fprintf(stderr, "Error: %s\n", error);
280 static int peers_list(DBusMessageIter *iter,
281 const char *error, void *user_data)
284 __connmanctl_peers_list(iter);
285 fprintf(stdout, "\n");
287 fprintf(stderr, "Error: %s\n", error);
292 static int object_properties(DBusMessageIter *iter,
293 const char *error, void *user_data)
295 char *path = user_data;
297 DBusMessageIter dict;
300 fprintf(stdout, "%s\n", path);
302 dbus_message_iter_recurse(iter, &dict);
303 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
305 fprintf(stdout, "\n");
308 str = strrchr(path, '/');
314 fprintf(stderr, "Error %s: %s\n", str, error);
322 static int cmd_services(char *args[], int num, struct connman_option *options)
324 char *service_name = NULL;
331 c = parse_args(args[1], options);
338 service_name = args[2];
343 service_name = args[1];
348 return __connmanctl_dbus_method_call(connection,
349 CONNMAN_SERVICE, CONNMAN_PATH,
350 "net.connman.Manager", "GetServices",
351 services_list, NULL, NULL, NULL);
354 if (check_dbus_name(service_name) == false)
357 path = g_strdup_printf("/net/connman/service/%s", service_name);
358 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
359 "net.connman.Service", "GetProperties",
360 object_properties, path, NULL, NULL);
363 static int cmd_peers(char *args[], int num, struct connman_option *options)
365 char *peer_name = NULL;
375 return __connmanctl_dbus_method_call(connection,
376 CONNMAN_SERVICE, CONNMAN_PATH,
377 "net.connman.Manager", "GetPeers",
378 peers_list, NULL, NULL, NULL);
381 if (check_dbus_name(peer_name) == false)
384 path = g_strdup_printf("/net/connman/peer/%s", peer_name);
385 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
386 path, "net.connman.Peer", "GetProperties",
387 object_properties, path, NULL, NULL);
390 static int technology_print(DBusMessageIter *iter, const char *error,
393 DBusMessageIter array;
396 fprintf(stderr, "Error: %s\n", error);
400 dbus_message_iter_recurse(iter, &array);
401 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
402 DBusMessageIter entry, dict;
405 dbus_message_iter_recurse(&array, &entry);
406 dbus_message_iter_get_basic(&entry, &path);
407 fprintf(stdout, "%s\n", path);
409 dbus_message_iter_next(&entry);
411 dbus_message_iter_recurse(&entry, &dict);
412 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
413 fprintf(stdout, "\n");
415 dbus_message_iter_next(&array);
421 static int cmd_technologies(char *args[], int num,
422 struct connman_option *options)
427 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
428 CONNMAN_PATH, "net.connman.Manager", "GetTechnologies",
429 technology_print, NULL, NULL, NULL);
432 struct tether_enable {
437 static int tether_set_return(DBusMessageIter *iter, const char *error,
440 struct tether_enable *tether = user_data;
443 str = strrchr(tether->path, '/');
450 fprintf(stdout, "%s tethering for %s\n",
451 tether->enable ? "Enabled" : "Disabled",
454 fprintf(stderr, "Error %s %s tethering: %s\n",
456 "enabling" : "disabling", str, error);
458 g_free(tether->path);
464 static int tether_set(char *technology, int set_tethering)
466 struct tether_enable *tether = g_new(struct tether_enable, 1);
468 switch(set_tethering) {
470 tether->enable = TRUE;
473 tether->enable = FALSE;
480 tether->path = g_strdup_printf("/net/connman/technology/%s",
483 return __connmanctl_dbus_set_property(connection, tether->path,
484 "net.connman.Technology", tether_set_return,
485 tether, "Tethering", DBUS_TYPE_BOOLEAN,
489 struct tether_properties {
491 int passphrase_result;
495 static int tether_update(struct tether_properties *tether)
497 if (tether->ssid_result == 0 && tether->passphrase_result == 0)
498 return tether_set("wifi", tether->set_tethering);
500 if (tether->ssid_result != -EINPROGRESS &&
501 tether->passphrase_result != -EINPROGRESS) {
509 static int tether_set_ssid_return(DBusMessageIter *iter, const char *error,
512 struct tether_properties *tether = user_data;
515 fprintf(stdout, "Wifi SSID set\n");
516 tether->ssid_result = 0;
518 fprintf(stderr, "Error setting wifi SSID: %s\n", error);
519 tether->ssid_result = -EINVAL;
522 return tether_update(tether);
525 static int tether_set_passphrase_return(DBusMessageIter *iter,
526 const char *error, void *user_data)
528 struct tether_properties *tether = user_data;
531 fprintf(stdout, "Wifi passphrase set\n");
532 tether->passphrase_result = 0;
534 fprintf(stderr, "Error setting wifi passphrase: %s\n", error);
535 tether->passphrase_result = -EINVAL;
538 return tether_update(tether);
541 static int tether_set_ssid(char *ssid, char *passphrase, int set_tethering)
543 struct tether_properties *tether = g_new(struct tether_properties, 1);
545 tether->set_tethering = set_tethering;
547 tether->ssid_result = __connmanctl_dbus_set_property(connection,
548 "/net/connman/technology/wifi",
549 "net.connman.Technology",
550 tether_set_ssid_return, tether,
551 "TetheringIdentifier", DBUS_TYPE_STRING, &ssid);
553 tether->passphrase_result =__connmanctl_dbus_set_property(connection,
554 "/net/connman/technology/wifi",
555 "net.connman.Technology",
556 tether_set_passphrase_return, tether,
557 "TetheringPassphrase", DBUS_TYPE_STRING, &passphrase);
559 if (tether->ssid_result != -EINPROGRESS &&
560 tether->passphrase_result != -EINPROGRESS) {
568 static int cmd_tether(char *args[], int num, struct connman_option *options)
570 char *ssid, *passphrase;
576 passphrase = args[num - 1];
577 ssid = args[num - 2];
579 set_tethering = parse_boolean(args[2]);
581 if (strcmp(args[1], "wifi") == 0) {
586 if (num == 5 && set_tethering == -1)
593 return tether_set_ssid(ssid, passphrase, set_tethering);
599 if (set_tethering == -1)
602 if (check_dbus_name(args[1]) == false)
605 return tether_set(args[1], set_tethering);
608 static int scan_return(DBusMessageIter *iter, const char *error,
611 char *path = user_data;
614 char *str = strrchr(path, '/');
616 fprintf(stdout, "Scan completed for %s\n", str);
618 fprintf(stderr, "Error %s: %s\n", path, error);
625 static int cmd_scan(char *args[], int num, struct connman_option *options)
635 if (check_dbus_name(args[1]) == false)
638 path = g_strdup_printf("/net/connman/technology/%s", args[1]);
639 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
640 "net.connman.Technology", "Scan",
641 scan_return, path, NULL, NULL);
644 static int connect_return(DBusMessageIter *iter, const char *error,
647 char *path = user_data;
650 char *str = strrchr(path, '/');
652 fprintf(stdout, "Connected %s\n", str);
654 fprintf(stderr, "Error %s: %s\n", path, error);
661 static int cmd_connect(char *args[], int num, struct connman_option *options)
671 if (check_dbus_name(args[1]) == false)
674 path = g_strdup_printf("/net/connman/service/%s", args[1]);
675 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
676 "net.connman.Service", "Connect",
677 connect_return, path, NULL, NULL);
680 static int disconnect_return(DBusMessageIter *iter, const char *error,
683 char *path = user_data;
686 char *str = strrchr(path, '/');
688 fprintf(stdout, "Disconnected %s\n", str);
690 fprintf(stderr, "Error %s: %s\n", path, error);
697 static int cmd_disconnect(char *args[], int num, struct connman_option *options)
707 if (check_dbus_name(args[1]) == false)
710 path = g_strdup_printf("/net/connman/service/%s", args[1]);
711 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
712 "net.connman.Service", "Disconnect",
713 disconnect_return, path, NULL, NULL);
716 static int config_return(DBusMessageIter *iter, const char *error,
719 char *service_name = user_data;
722 fprintf(stderr, "Error %s: %s\n", service_name, error);
729 struct config_append {
734 static void config_append_ipv4(DBusMessageIter *iter,
737 struct config_append *append = user_data;
738 char **opts = append->opts;
744 while (opts[i] && ipv4[i]) {
745 __connmanctl_dbus_append_dict_entry(iter, ipv4[i],
746 DBUS_TYPE_STRING, &opts[i]);
753 static void config_append_ipv6(DBusMessageIter *iter, void *user_data)
755 struct config_append *append = user_data;
756 char **opts = append->opts;
763 if (g_strcmp0(opts[0], "auto") == 0) {
766 switch (parse_boolean(opts[1])) {
771 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
772 DBUS_TYPE_STRING, &str);
779 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
780 DBUS_TYPE_STRING, &str);
787 if (g_strcmp0(opts[1], "prefered") != 0 &&
790 fprintf(stderr, "Error %s: %s\n",
797 __connmanctl_dbus_append_dict_entry(iter,
798 "Privacy", DBUS_TYPE_STRING,
803 } else if (g_strcmp0(opts[0], "manual") == 0) {
806 while (opts[i] && ipv6[i]) {
808 int value = atoi(opts[i]);
809 __connmanctl_dbus_append_dict_entry(iter,
810 ipv6[i], DBUS_TYPE_BYTE,
813 __connmanctl_dbus_append_dict_entry(iter,
814 ipv6[i], DBUS_TYPE_STRING,
822 } else if (g_strcmp0(opts[0], "off") != 0) {
823 fprintf(stderr, "Error %s: %s\n", opts[0], strerror(EINVAL));
828 __connmanctl_dbus_append_dict_entry(iter, "Method", DBUS_TYPE_STRING,
832 static void config_append_str(DBusMessageIter *iter, void *user_data)
834 struct config_append *append = user_data;
835 char **opts = append->opts;
842 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
850 static void append_servers(DBusMessageIter *iter, void *user_data)
852 struct config_append *append = user_data;
853 char **opts = append->opts;
859 while (opts[i] && g_strcmp0(opts[i], "--excludes") != 0) {
860 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
868 static void append_excludes(DBusMessageIter *iter, void *user_data)
870 struct config_append *append = user_data;
871 char **opts = append->opts;
872 int i = append->values;
874 if (!opts || !opts[i] ||
875 g_strcmp0(opts[i], "--excludes") != 0)
880 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
888 static void config_append_proxy(DBusMessageIter *iter, void *user_data)
890 struct config_append *append = user_data;
891 char **opts = append->opts;
896 if (g_strcmp0(opts[0], "manual") == 0) {
897 __connmanctl_dbus_append_dict_string_array(iter, "Servers",
898 append_servers, append);
900 __connmanctl_dbus_append_dict_string_array(iter, "Excludes",
901 append_excludes, append);
903 } else if (g_strcmp0(opts[0], "auto") == 0) {
905 __connmanctl_dbus_append_dict_entry(iter, "URL",
906 DBUS_TYPE_STRING, &opts[1]);
910 } else if (g_strcmp0(opts[0], "direct") != 0)
913 __connmanctl_dbus_append_dict_entry(iter, "Method",DBUS_TYPE_STRING,
919 static int cmd_config(char *args[], int num, struct connman_option *options)
921 int result = 0, res = 0, index = 2, oldindex = 0;
923 char *service_name, *path;
926 struct config_append append;
928 service_name = args[1];
932 if (check_dbus_name(service_name) == false)
935 while (index < num && args[index]) {
936 c = parse_args(args[index], options);
937 opt_start = &args[index + 1];
938 append.opts = opt_start;
944 path = g_strdup_printf("/net/connman/service/%s", service_name);
948 switch (parse_boolean(*opt_start)) {
963 res = __connmanctl_dbus_set_property(connection,
964 path, "net.connman.Service",
966 g_strdup(service_name),
968 DBUS_TYPE_BOOLEAN, &val);
972 res = __connmanctl_dbus_set_property_dict(connection,
973 path, "net.connman.Service",
974 config_return, g_strdup(service_name),
975 "IPv4.Configuration", DBUS_TYPE_STRING,
976 config_append_ipv4, &append);
977 index += append.values;
981 res = __connmanctl_dbus_set_property_dict(connection,
982 path, "net.connman.Service",
983 config_return, g_strdup(service_name),
984 "IPv6.Configuration", DBUS_TYPE_STRING,
985 config_append_ipv6, &append);
986 index += append.values;
990 res = __connmanctl_dbus_set_property_array(connection,
991 path, "net.connman.Service",
992 config_return, g_strdup(service_name),
993 "Nameservers.Configuration",
994 DBUS_TYPE_STRING, config_append_str,
996 index += append.values;
1000 res = __connmanctl_dbus_set_property_array(connection,
1001 path, "net.connman.Service",
1002 config_return, g_strdup(service_name),
1003 "Timeservers.Configuration",
1004 DBUS_TYPE_STRING, config_append_str,
1006 index += append.values;
1010 res = __connmanctl_dbus_set_property_array(connection,
1011 path, "net.connman.Service",
1012 config_return, g_strdup(service_name),
1013 "Domains.Configuration",
1014 DBUS_TYPE_STRING, config_append_str,
1016 index += append.values;
1020 res = __connmanctl_dbus_set_property_dict(connection,
1021 path, "net.connman.Service",
1022 config_return, g_strdup(service_name),
1023 "Proxy.Configuration",
1024 DBUS_TYPE_STRING, config_append_proxy,
1026 index += append.values;
1029 res = __connmanctl_dbus_method_call(connection,
1030 CONNMAN_SERVICE, path,
1031 "net.connman.Service", "Remove",
1032 config_return, g_strdup(service_name),
1043 if (res == -EINPROGRESS)
1044 result = -EINPROGRESS;
1046 printf("Error '%s': %s\n", args[oldindex],
1057 static DBusHandlerResult monitor_changed(DBusConnection *connection,
1058 DBusMessage *message, void *user_data)
1060 DBusMessageIter iter;
1061 const char *interface, *path;
1063 interface = dbus_message_get_interface(message);
1065 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1067 if (strncmp(interface, "net.connman.", 12) != 0)
1068 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1070 if (!strcmp(interface, "net.connman.Agent") ||
1071 !strcmp(interface, "net.connman.vpn.Agent") ||
1072 !strcmp(interface, "net.connman.Session") ||
1073 !strcmp(interface, "net.connman.Notification"))
1074 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1076 interface = strrchr(interface, '.');
1077 if (interface && *interface != '\0')
1080 path = strrchr(dbus_message_get_path(message), '/');
1081 if (path && *path != '\0')
1084 __connmanctl_save_rl();
1086 if (dbus_message_is_signal(message, "net.connman.Manager",
1087 "ServicesChanged")) {
1089 fprintf(stdout, "%-12s %-20s = {\n", interface,
1091 dbus_message_iter_init(message, &iter);
1092 __connmanctl_services_list(&iter);
1093 fprintf(stdout, "\n}\n");
1095 __connmanctl_redraw_rl();
1097 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1098 } else if (dbus_message_is_signal(message, "net.connman.Manager",
1100 fprintf(stdout, "%-12s %-20s = {\n", interface,
1102 dbus_message_iter_init(message, &iter);
1103 __connmanctl_peers_list(&iter);
1104 fprintf(stdout, "\n}\n");
1106 __connmanctl_redraw_rl();
1108 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1109 } else if (dbus_message_is_signal(message, "net.connman.vpn.Manager",
1110 "ConnectionAdded") ||
1111 dbus_message_is_signal(message,
1112 "net.connman.vpn.Manager",
1113 "ConnectionRemoved")) {
1114 interface = "vpn.Manager";
1115 path = dbus_message_get_member(message);
1117 } else if (dbus_message_is_signal(message, "net.connman.Manager",
1118 "TechnologyAdded") ||
1119 dbus_message_is_signal(message, "net.connman.Manager",
1120 "TechnologyRemoved"))
1121 path = dbus_message_get_member(message);
1123 fprintf(stdout, "%-12s %-20s ", interface, path);
1124 dbus_message_iter_init(message, &iter);
1126 __connmanctl_dbus_print(&iter, "", " = ", " = ");
1127 fprintf(stdout, "\n");
1129 __connmanctl_redraw_rl();
1131 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1138 { "Service", false },
1139 { "Technology", false },
1140 { "Manager", false },
1141 { "vpn.Manager", false },
1142 { "vpn.Connection", false },
1146 static void monitor_add(char *interface)
1148 bool add_filter = true, found = false;
1153 for (i = 0; monitor[i].interface; i++) {
1154 if (monitor[i].enabled == true)
1157 if (g_strcmp0(interface, monitor[i].interface) == 0) {
1158 if (monitor[i].enabled == true)
1161 monitor[i].enabled = true;
1169 if (add_filter == true)
1170 dbus_connection_add_filter(connection, monitor_changed,
1173 dbus_error_init(&err);
1174 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
1176 dbus_bus_add_match(connection, rule, &err);
1179 if (dbus_error_is_set(&err))
1180 fprintf(stderr, "Error: %s\n", err.message);
1183 static void monitor_del(char *interface)
1185 bool del_filter = true, found = false;
1190 for (i = 0; monitor[i].interface; i++) {
1191 if (g_strcmp0(interface, monitor[i].interface) == 0) {
1192 if (monitor[i].enabled == false)
1195 monitor[i].enabled = false;
1199 if (monitor[i].enabled == true)
1206 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
1208 dbus_bus_remove_match(connection, rule, NULL);
1211 if (del_filter == true)
1212 dbus_connection_remove_filter(connection, monitor_changed,
1216 static int cmd_monitor(char *args[], int num, struct connman_option *options)
1225 switch (parse_boolean(args[2])) {
1235 c = parse_args(args[1], options);
1238 monitor_add("Service");
1239 monitor_add("Technology");
1240 monitor_add("Manager");
1241 monitor_add("vpn.Manager");
1242 monitor_add("vpn.Connection");
1247 monitor_add("Service");
1249 monitor_del("Service");
1254 monitor_add("Technology");
1256 monitor_del("Technology");
1261 monitor_add("Manager");
1263 monitor_del("Manager");
1268 monitor_add("vpn.Manager");
1270 monitor_del("vpn.Manager");
1275 monitor_add("vpn.Connection");
1277 monitor_del("vpn.Connection");
1281 switch(parse_boolean(args[1])) {
1283 monitor_del("Service");
1284 monitor_del("Technology");
1285 monitor_del("Manager");
1286 monitor_del("vpn.Manager");
1287 monitor_del("vpn.Connection");
1291 monitor_add("Service");
1292 monitor_add("Technology");
1293 monitor_add("Manager");
1294 monitor_add("vpn.Manager");
1295 monitor_add("vpn.Connection");
1304 return -EINPROGRESS;
1309 static int cmd_agent(char *args[], int num, struct connman_option *options)
1311 if (!__connmanctl_is_interactive()) {
1312 fprintf(stderr, "Error: Not supported in non-interactive "
1323 switch(parse_boolean(args[1])) {
1325 __connmanctl_agent_unregister(connection);
1329 if (__connmanctl_agent_register(connection) == -EINPROGRESS)
1330 return -EINPROGRESS;
1342 static int vpnconnections_properties(DBusMessageIter *iter, const char *error,
1345 char *path = user_data;
1347 DBusMessageIter dict;
1350 fprintf(stdout, "%s\n", path);
1352 dbus_message_iter_recurse(iter, &dict);
1353 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
1355 fprintf(stdout, "\n");
1358 str = strrchr(path, '/');
1364 fprintf(stderr, "Error %s: %s\n", str, error);
1372 static int vpnconnections_list(DBusMessageIter *iter, const char *error,
1376 __connmanctl_vpnconnections_list(iter);
1378 fprintf(stderr, "Error: %s\n", error);
1383 static int cmd_vpnconnections(char *args[], int num,
1384 struct connman_option *options)
1386 char *vpnconnection_name, *path;
1391 vpnconnection_name = args[1];
1393 if (!vpnconnection_name)
1394 return __connmanctl_dbus_method_call(connection,
1395 VPN_SERVICE, VPN_PATH,
1396 "net.connman.vpn.Manager", "GetConnections",
1397 vpnconnections_list, NULL,
1400 if (check_dbus_name(vpnconnection_name) == false)
1403 path = g_strdup_printf("/net/connman/vpn/connection/%s",
1404 vpnconnection_name);
1405 return __connmanctl_dbus_method_call(connection, VPN_SERVICE, path,
1406 "net.connman.vpn.Connection", "GetProperties",
1407 vpnconnections_properties, path, NULL, NULL);
1411 static int cmd_vpnagent(char *args[], int num, struct connman_option *options)
1413 if (!__connmanctl_is_interactive()) {
1414 fprintf(stderr, "Error: Not supported in non-interactive "
1425 switch(parse_boolean(args[1])) {
1427 __connmanctl_vpn_agent_unregister(connection);
1431 if (__connmanctl_vpn_agent_register(connection) ==
1433 return -EINPROGRESS;
1445 static DBusMessage *session_release(DBusConnection *connection,
1446 DBusMessage *message, void *user_data)
1448 __connmanctl_save_rl();
1450 fprintf(stdout, "Session %s released\n", session_path);
1452 __connmanctl_redraw_rl();
1454 g_free(session_path);
1455 session_path = NULL;
1456 session_connected = false;
1458 return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
1461 static DBusMessage *session_update(DBusConnection *connection,
1462 DBusMessage *message, void *user_data)
1464 DBusMessageIter iter, dict;
1466 __connmanctl_save_rl();
1468 fprintf(stdout, "Session Update = {\n");
1470 dbus_message_iter_init(message, &iter);
1471 dbus_message_iter_recurse(&iter, &dict);
1473 __connmanctl_dbus_print(&dict, "", " = ", "\n");
1474 fprintf(stdout, "\n}\n");
1476 dbus_message_iter_recurse(&iter, &dict);
1478 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1479 DBusMessageIter entry, variant;
1480 char *field, *state;
1482 dbus_message_iter_recurse(&dict, &entry);
1484 dbus_message_iter_get_basic(&entry, &field);
1486 if (dbus_message_iter_get_arg_type(&entry)
1488 && !strcmp(field, "State")) {
1490 dbus_message_iter_next(&entry);
1491 dbus_message_iter_recurse(&entry, &variant);
1492 if (dbus_message_iter_get_arg_type(&variant)
1493 != DBUS_TYPE_STRING)
1496 dbus_message_iter_get_basic(&variant, &state);
1498 if (!session_connected && (!strcmp(state, "connected")
1499 || !strcmp(state, "online"))) {
1501 fprintf(stdout, "Session %s connected\n",
1503 session_connected = true;
1508 if (!strcmp(state, "disconnected") &&
1509 session_connected) {
1511 fprintf(stdout, "Session %s disconnected\n",
1513 session_connected = false;
1518 dbus_message_iter_next(&dict);
1521 __connmanctl_redraw_rl();
1523 return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
1526 static const GDBusMethodTable notification_methods[] = {
1527 { GDBUS_METHOD("Release", NULL, NULL, session_release) },
1528 { GDBUS_METHOD("Update", GDBUS_ARGS({"settings", "a{sv}"}),
1529 NULL, session_update) },
1533 static int session_notify_add(const char *path)
1535 if (session_notify_path)
1538 if (!g_dbus_register_interface(connection, path,
1539 "net.connman.Notification",
1540 notification_methods, NULL, NULL,
1542 fprintf(stderr, "Error: Failed to register VPN Agent "
1547 session_notify_path = g_strdup(path);
1552 static void session_notify_remove(void)
1554 if (!session_notify_path)
1557 g_dbus_unregister_interface(connection, session_notify_path,
1558 "net.connman.Notification");
1560 g_free(session_notify_path);
1561 session_notify_path = NULL;
1564 static int session_connect_cb(DBusMessageIter *iter, const char *error,
1568 fprintf(stderr, "Error: %s", error);
1572 return -EINPROGRESS;
1576 static int session_connect(void)
1578 return __connmanctl_dbus_method_call(connection, "net.connman",
1579 session_path, "net.connman.Session", "Connect",
1580 session_connect_cb, NULL, NULL, NULL);
1583 static int session_disconnect_cb(DBusMessageIter *iter, const char *error,
1587 fprintf(stderr, "Error: %s", error);
1592 static int session_disconnect(void)
1594 return __connmanctl_dbus_method_call(connection, "net.connman",
1595 session_path, "net.connman.Session", "Disconnect",
1596 session_disconnect_cb, NULL, NULL, NULL);
1599 static int session_create_cb(DBusMessageIter *iter, const char *error,
1602 gboolean connect = GPOINTER_TO_INT(user_data);
1606 fprintf(stderr, "Error creating session: %s", error);
1607 session_notify_remove();
1611 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH) {
1612 fprintf(stderr, "Error creating session: No session path\n");
1616 g_free(session_path);
1618 dbus_message_iter_get_basic(iter, &str);
1619 session_path = g_strdup(str);
1621 fprintf(stdout, "Session %s created\n", session_path);
1624 return session_connect();
1626 return -EINPROGRESS;
1629 static void session_create_append(DBusMessageIter *iter, void *user_data)
1631 const char *notify_path = user_data;
1633 __connmanctl_dbus_append_dict(iter, NULL, NULL);
1635 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
1639 static int session_create(gboolean connect)
1644 notify_path = g_strdup_printf("/net/connman/connmanctl%d", getpid());
1645 session_notify_add(notify_path);
1647 res = __connmanctl_dbus_method_call(connection, "net.connman", "/",
1648 "net.connman.Manager", "CreateSession",
1649 session_create_cb, GINT_TO_POINTER(connect),
1650 session_create_append, notify_path);
1652 g_free(notify_path);
1654 if (res < 0 && res != -EINPROGRESS)
1655 session_notify_remove();
1660 static int session_destroy_cb(DBusMessageIter *iter, const char *error,
1664 fprintf(stderr, "Error destroying session: %s", error);
1668 fprintf(stdout, "Session %s ended\n", session_path);
1670 g_free(session_path);
1671 session_path = NULL;
1672 session_connected = false;
1677 static void session_destroy_append(DBusMessageIter *iter, void *user_data)
1679 const char *path = user_data;
1681 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
1684 static int session_destroy(void)
1686 return __connmanctl_dbus_method_call(connection, "net.connman", "/",
1687 "net.connman.Manager", "DestroySession",
1688 session_destroy_cb, NULL,
1689 session_destroy_append, session_path);
1692 static int session_config_return(DBusMessageIter *iter, const char *error,
1695 char *property_name = user_data;
1698 fprintf(stderr, "Error setting session %s: %s\n",
1699 property_name, error);
1704 static void session_config_append_array(DBusMessageIter *iter,
1707 struct config_append *append = user_data;
1708 char **opts = append->opts;
1714 while (opts[i] && strncmp(opts[i], "--", 2) != 0) {
1715 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1723 static int session_config(char *args[], int num,
1724 struct connman_option *options)
1726 int index = 0, res = 0;
1727 struct config_append append;
1730 while (index < num && args[index]) {
1731 append.opts = &args[index];
1734 c = parse_args(args[index], options);
1738 res = __connmanctl_dbus_session_change_array(connection,
1739 session_path, session_config_return,
1740 "AllowedBearers", "AllowedBearers",
1741 session_config_append_array, &append);
1744 if (!args[index + 1]) {
1749 res = __connmanctl_dbus_session_change(connection,
1750 session_path, session_config_return,
1751 "ConnectionType", "ConnectionType",
1752 DBUS_TYPE_STRING, &args[index + 1]);
1760 if (res < 0 && res != -EINPROGRESS) {
1761 printf("Error '%s': %s\n", args[index],
1766 index += append.values;
1772 static int cmd_session(char *args[], int num, struct connman_option *options)
1781 switch(parse_boolean(command)) {
1785 return session_destroy();
1790 return session_create(FALSE);
1793 if (!strcmp(command, "connect")) {
1795 return session_create(TRUE);
1797 return session_connect();
1799 } else if (!strcmp(command, "disconnect")) {
1801 if (!session_path) {
1802 fprintf(stdout, "Session does not exist\n");
1806 return session_disconnect();
1807 } else if (!strcmp(command, "config")) {
1808 if (!session_path) {
1809 fprintf(stdout, "Session does not exist\n");
1816 return session_config(&args[2], num - 2, options);
1824 static int cmd_exit(char *args[], int num, struct connman_option *options)
1829 static char *lookup_service(const char *text, int state)
1832 static GHashTableIter iter;
1833 gpointer key, value;
1836 g_hash_table_iter_init(&iter, service_hash);
1840 while (g_hash_table_iter_next(&iter, &key, &value)) {
1841 const char *service = key;
1842 if (strncmp(text, service, len) == 0)
1843 return strdup(service);
1849 static char *lookup_service_arg(const char *text, int state)
1851 if (__connmanctl_input_calc_level() > 1) {
1852 __connmanctl_input_lookup_end();
1856 return lookup_service(text, state);
1859 static char *lookup_peer(const char *text, int state)
1861 static GHashTableIter iter;
1862 gpointer key, value;
1866 g_hash_table_iter_init(&iter, peer_hash);
1870 while (g_hash_table_iter_next(&iter, &key, &value)) {
1871 const char *peer = key;
1872 if (strncmp(text, peer, len) == 0)
1873 return strdup(peer);
1879 static char *lookup_peer_arg(const char *text, int state)
1881 if (__connmanctl_input_calc_level() > 1) {
1882 __connmanctl_input_lookup_end();
1886 return lookup_peer(text, state);
1889 static char *lookup_technology(const char *text, int state)
1892 static GHashTableIter iter;
1893 gpointer key, value;
1896 g_hash_table_iter_init(&iter, technology_hash);
1900 while (g_hash_table_iter_next(&iter, &key, &value)) {
1901 const char *technology = key;
1902 if (strncmp(text, technology, len) == 0)
1903 return strdup(technology);
1909 static char *lookup_technology_arg(const char *text, int state)
1911 if (__connmanctl_input_calc_level() > 1) {
1912 __connmanctl_input_lookup_end();
1916 return lookup_technology(text, state);
1919 static char *lookup_technology_offline(const char *text, int state)
1922 static bool end = false;
1925 if (__connmanctl_input_calc_level() > 1) {
1926 __connmanctl_input_lookup_end();
1938 str = lookup_technology(text, state);
1944 if (strncmp(text, "offline", len) == 0)
1945 return strdup("offline");
1950 static char *lookup_on_off(const char *text, int state)
1952 char *onoff[] = { "on", "off", NULL };
1963 while (onoff[idx]) {
1967 if (!strncmp(text, str, len))
1974 static char *lookup_tether(const char *text, int state)
1978 level = __connmanctl_input_calc_level();
1980 return lookup_technology(text, state);
1983 return lookup_on_off(text, state);
1985 __connmanctl_input_lookup_end();
1990 static char *lookup_agent(const char *text, int state)
1992 if (__connmanctl_input_calc_level() > 1) {
1993 __connmanctl_input_lookup_end();
1997 return lookup_on_off(text, state);
2000 static struct connman_option service_options[] = {
2001 {"properties", 'p', "[<service>] (obsolete)"},
2005 static struct connman_option config_options[] = {
2006 {"nameservers", 'n', "<dns1> [<dns2>] [<dns3>]"},
2007 {"timeservers", 't', "<ntp1> [<ntp2>] [...]"},
2008 {"domains", 'd', "<domain1> [<domain2>] [...]"},
2009 {"ipv6", 'v', "off|auto [enable|disable|preferred]|\n"
2010 "\t\t\tmanual <address> <prefixlength> <gateway>"},
2011 {"proxy", 'x', "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
2012 "\t\t\t[exclude <exclude1> [<exclude2>] [...]]"},
2013 {"autoconnect", 'a', "yes|no"},
2014 {"ipv4", 'i', "off|dhcp|manual <address> <netmask> <gateway>"},
2015 {"remove", 'r', " Remove service"},
2019 static struct connman_option monitor_options[] = {
2020 {"services", 's', "[off] Monitor only services"},
2021 {"tech", 'c', "[off] Monitor only technologies"},
2022 {"manager", 'm', "[off] Monitor only manager interface"},
2023 {"vpnmanager", 'M', "[off] Monitor only VPN manager "
2025 {"vpnconnection", 'C', "[off] Monitor only VPN "
2030 static struct connman_option session_options[] = {
2031 {"bearers", 'b', "<technology1> [<technology2> [...]]"},
2032 {"type", 't', "local|internet|any"},
2036 static char *lookup_options(struct connman_option *options, const char *text,
2048 while (options[idx].name) {
2049 str = options[idx].name;
2052 if (str && strncmp(text, str, len) == 0)
2059 static char *lookup_monitor(const char *text, int state)
2063 level = __connmanctl_input_calc_level();
2066 return lookup_options(monitor_options, text, state);
2069 return lookup_on_off(text, state);
2071 __connmanctl_input_lookup_end();
2075 static char *lookup_config(const char *text, int state)
2077 if (__connmanctl_input_calc_level() < 2)
2078 return lookup_service(text, state);
2080 return lookup_options(config_options, text, state);
2083 static char *lookup_session(const char *text, int state)
2085 return lookup_options(session_options, text, state);
2088 static const struct {
2090 const char *argument;
2091 struct connman_option *options;
2092 int (*func) (char *args[], int num, struct connman_option *options);
2094 __connmanctl_lookup_cb cb;
2096 { "state", NULL, NULL, cmd_state,
2097 "Shows if the system is online or offline", NULL },
2098 { "technologies", NULL, NULL, cmd_technologies,
2099 "Display technologies", NULL },
2100 { "enable", "<technology>|offline", NULL, cmd_enable,
2101 "Enables given technology or offline mode",
2102 lookup_technology_offline },
2103 { "disable", "<technology>|offline", NULL, cmd_disable,
2104 "Disables given technology or offline mode",
2105 lookup_technology_offline },
2106 { "tether", "<technology> on|off\n"
2107 " wifi [on|off] <ssid> <passphrase> ",
2109 "Enable, disable tethering, set SSID and passphrase for wifi",
2111 { "services", "[<service>]", service_options, cmd_services,
2112 "Display services", lookup_service_arg },
2113 { "peers", "[peer]", NULL, cmd_peers,
2114 "Display peers", lookup_peer_arg },
2115 { "scan", "<technology>", NULL, cmd_scan,
2116 "Scans for new services for given technology",
2117 lookup_technology_arg },
2118 { "connect", "<service>", NULL, cmd_connect,
2119 "Connect a given service", lookup_service_arg },
2120 { "disconnect", "<service>", NULL, cmd_disconnect,
2121 "Disconnect a given service", lookup_service_arg },
2122 { "config", "<service>", config_options, cmd_config,
2123 "Set service configuration options", lookup_config },
2124 { "monitor", "[off]", monitor_options, cmd_monitor,
2125 "Monitor signals from interfaces", lookup_monitor },
2126 { "agent", "on|off", NULL, cmd_agent,
2127 "Agent mode", lookup_agent },
2128 {"vpnconnections", "[<connection>]", NULL, cmd_vpnconnections,
2129 "Display VPN connections", NULL },
2130 { "vpnagent", "on|off", NULL, cmd_vpnagent,
2131 "VPN Agent mode", lookup_agent },
2132 { "session", "on|off|connect|disconnect|config", session_options,
2133 cmd_session, "Enable or disable a session", lookup_session },
2134 { "help", NULL, NULL, cmd_help,
2135 "Show help", NULL },
2136 { "exit", NULL, NULL, cmd_exit,
2138 { "quit", NULL, NULL, cmd_exit,
2143 static int cmd_help(char *args[], int num, struct connman_option *options)
2145 bool interactive = __connmanctl_is_interactive();
2148 if (interactive == false)
2149 fprintf(stdout, "Usage: connmanctl [[command] [args]]\n");
2151 for (i = 0; cmd_table[i].cmd; i++) {
2152 const char *cmd = cmd_table[i].cmd;
2153 const char *argument = cmd_table[i].argument;
2154 const char *desc = cmd_table[i].desc;
2156 printf("%-16s%-22s%s\n", cmd? cmd: "",
2157 argument? argument: "",
2160 if (cmd_table[i].options) {
2161 for (j = 0; cmd_table[i].options[j].name;
2163 const char *options_desc =
2164 cmd_table[i].options[j].desc ?
2165 cmd_table[i].options[j].desc: "";
2167 printf(" --%-16s%s\n",
2168 cmd_table[i].options[j].name,
2174 if (interactive == false)
2175 fprintf(stdout, "\nNote: arguments and output are considered "
2176 "EXPERIMENTAL for now.\n");
2181 __connmanctl_lookup_cb __connmanctl_get_lookup_func(const char *text)
2183 int i, cmdlen, textlen;
2188 textlen = strlen(text);
2190 for (i = 0; cmd_table[i].cmd; i++) {
2191 cmdlen = strlen(cmd_table[i].cmd);
2193 if (textlen > cmdlen && text[cmdlen] != ' ')
2196 if (strncmp(cmd_table[i].cmd, text, cmdlen) == 0)
2197 return cmd_table[i].cb;
2203 int __connmanctl_commands(DBusConnection *dbus_conn, char *argv[], int argc)
2207 connection = dbus_conn;
2209 for (i = 0; cmd_table[i].cmd; i++) {
2210 if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
2211 cmd_table[i].func) {
2212 result = cmd_table[i].func(argv, argc,
2213 cmd_table[i].options);
2214 if (result < 0 && result != -EINPROGRESS)
2215 fprintf(stderr, "Error '%s': %s\n", argv[0],
2221 fprintf(stderr, "Error '%s': Unknown command\n", argv[0]);
2225 char *__connmanctl_lookup_command(const char *text, int state)
2235 while (cmd_table[i].cmd) {
2236 const char *command = cmd_table[i].cmd;
2240 if (strncmp(text, command, len) == 0)
2241 return strdup(command);
2247 static char *get_path(char *full_path)
2251 path = strrchr(full_path, '/');
2252 if (path && *path != '\0')
2260 static void add_service_id(const char *path)
2262 g_hash_table_replace(service_hash, g_strdup(path),
2263 GINT_TO_POINTER(TRUE));
2266 static void remove_service_id(const char *path)
2268 g_hash_table_remove(service_hash, path);
2271 static void services_added(DBusMessageIter *iter)
2273 DBusMessageIter array;
2276 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
2278 dbus_message_iter_recurse(iter, &array);
2279 if (dbus_message_iter_get_arg_type(&array) !=
2280 DBUS_TYPE_OBJECT_PATH)
2283 dbus_message_iter_get_basic(&array, &path);
2284 add_service_id(get_path(path));
2286 dbus_message_iter_next(iter);
2290 static void update_services(DBusMessageIter *iter)
2292 DBusMessageIter array;
2295 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2298 dbus_message_iter_recurse(iter, &array);
2299 services_added(&array);
2301 dbus_message_iter_next(iter);
2302 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2305 dbus_message_iter_recurse(iter, &array);
2306 while (dbus_message_iter_get_arg_type(&array) ==
2307 DBUS_TYPE_OBJECT_PATH) {
2308 dbus_message_iter_get_basic(&array, &path);
2309 remove_service_id(get_path(path));
2311 dbus_message_iter_next(&array);
2315 static int populate_service_hash(DBusMessageIter *iter, const char *error,
2318 update_services(iter);
2322 static void add_peer_id(const char *path)
2324 g_hash_table_replace(peer_hash, g_strdup(path), GINT_TO_POINTER(TRUE));
2327 static void remove_peer_id(const char *path)
2329 g_hash_table_remove(peer_hash, path);
2332 static void peers_added(DBusMessageIter *iter)
2334 DBusMessageIter array;
2337 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
2339 dbus_message_iter_recurse(iter, &array);
2340 if (dbus_message_iter_get_arg_type(&array) !=
2341 DBUS_TYPE_OBJECT_PATH)
2344 dbus_message_iter_get_basic(&array, &path);
2345 add_peer_id(get_path(path));
2347 dbus_message_iter_next(iter);
2351 static void update_peers(DBusMessageIter *iter)
2353 DBusMessageIter array;
2356 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2359 dbus_message_iter_recurse(iter, &array);
2360 peers_added(&array);
2362 dbus_message_iter_next(iter);
2363 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2366 dbus_message_iter_recurse(iter, &array);
2367 while (dbus_message_iter_get_arg_type(&array) ==
2368 DBUS_TYPE_OBJECT_PATH) {
2369 dbus_message_iter_get_basic(&array, &path);
2370 remove_peer_id(get_path(path));
2372 dbus_message_iter_next(&array);
2376 static int populate_peer_hash(DBusMessageIter *iter,
2377 const char *error, void *user_data)
2383 static void add_technology_id(const char *path)
2385 g_hash_table_replace(technology_hash, g_strdup(path),
2386 GINT_TO_POINTER(TRUE));
2389 static void remove_technology_id(const char *path)
2391 g_hash_table_remove(technology_hash, path);
2394 static void remove_technology(DBusMessageIter *iter)
2398 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
2401 dbus_message_iter_get_basic(iter, &path);
2402 remove_technology_id(get_path(path));
2405 static void add_technology(DBusMessageIter *iter)
2409 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
2412 dbus_message_iter_get_basic(iter, &path);
2413 add_technology_id(get_path(path));
2416 static void update_technologies(DBusMessageIter *iter)
2418 DBusMessageIter array;
2420 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2423 dbus_message_iter_recurse(iter, &array);
2425 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
2426 DBusMessageIter object_path;
2428 dbus_message_iter_recurse(&array, &object_path);
2430 add_technology(&object_path);
2432 dbus_message_iter_next(&array);
2436 static int populate_technology_hash(DBusMessageIter *iter, const char *error,
2439 update_technologies(iter);
2444 static DBusHandlerResult monitor_completions_changed(
2445 DBusConnection *connection,
2446 DBusMessage *message, void *user_data)
2448 bool *enabled = user_data;
2449 DBusMessageIter iter;
2450 DBusHandlerResult handled;
2453 handled = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2455 handled = DBUS_HANDLER_RESULT_HANDLED;
2457 if (dbus_message_is_signal(message, "net.connman.Manager",
2458 "ServicesChanged")) {
2459 dbus_message_iter_init(message, &iter);
2460 update_services(&iter);
2464 if (dbus_message_is_signal(message, "net.connman.Manager",
2466 dbus_message_iter_init(message, &iter);
2467 update_peers(&iter);
2471 if (dbus_message_is_signal(message, "net.connman.Manager",
2472 "TechnologyAdded")) {
2473 dbus_message_iter_init(message, &iter);
2474 add_technology(&iter);
2478 if (dbus_message_is_signal(message, "net.connman.Manager",
2479 "TechnologyRemoved")) {
2480 dbus_message_iter_init(message, &iter);
2481 remove_technology(&iter);
2485 if (!g_strcmp0(dbus_message_get_interface(message),
2486 "net.connman.Manager"))
2489 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2492 void __connmanctl_monitor_completions(DBusConnection *dbus_conn)
2494 bool *manager_enabled = NULL;
2498 for (i = 0; monitor[i].interface; i++) {
2499 if (!strcmp(monitor[i].interface, "Manager")) {
2500 manager_enabled = &monitor[i].enabled;
2506 g_hash_table_destroy(service_hash);
2507 g_hash_table_destroy(technology_hash);
2509 dbus_bus_remove_match(connection,
2510 "type='signal',interface='net.connman.Manager'", NULL);
2511 dbus_connection_remove_filter(connection,
2512 monitor_completions_changed,
2517 connection = dbus_conn;
2519 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2522 peer_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2525 technology_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
2528 __connmanctl_dbus_method_call(connection,
2529 CONNMAN_SERVICE, CONNMAN_PATH,
2530 "net.connman.Manager", "GetServices",
2531 populate_service_hash, NULL, NULL, NULL);
2533 __connmanctl_dbus_method_call(connection,
2534 CONNMAN_SERVICE, CONNMAN_PATH,
2535 "net.connman.Manager", "GetPeers",
2536 populate_peer_hash, NULL, NULL, NULL);
2538 __connmanctl_dbus_method_call(connection,
2539 CONNMAN_SERVICE, CONNMAN_PATH,
2540 "net.connman.Manager", "GetTechnologies",
2541 populate_technology_hash, NULL, NULL, NULL);
2543 dbus_connection_add_filter(connection,
2544 monitor_completions_changed, manager_enabled,
2547 dbus_error_init(&err);
2548 dbus_bus_add_match(connection,
2549 "type='signal',interface='net.connman.Manager'", &err);
2551 if (dbus_error_is_set(&err))
2552 fprintf(stderr, "Error: %s\n", err.message);