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 *vpnconnection_hash;
50 static GHashTable *peer_hash;
51 static GHashTable *technology_hash;
52 static char *session_notify_path;
53 static char *session_path;
54 static bool session_connected;
56 struct connman_option {
62 static char *ipv4[] = {
70 static char *ipv6[] = {
78 static int cmd_help(char *args[], int num, struct connman_option *options);
80 static bool check_dbus_name(const char *name)
83 * Valid dbus chars should be [A-Z][a-z][0-9]_
84 * and should not start with number.
88 if (!name || name[0] == '\0')
91 for (i = 0; name[i] != '\0'; i++)
92 if (!((name[i] >= 'A' && name[i] <= 'Z') ||
93 (name[i] >= 'a' && name[i] <= 'z') ||
94 (name[i] >= '0' && name[i] <= '9') ||
101 static int parse_boolean(char *arg)
106 if (strcasecmp(arg, "no") == 0 ||
107 strcasecmp(arg, "false") == 0 ||
108 strcasecmp(arg, "off" ) == 0 ||
109 strcasecmp(arg, "disable" ) == 0 ||
110 strcasecmp(arg, "n") == 0 ||
111 strcasecmp(arg, "f") == 0 ||
112 strcasecmp(arg, "0") == 0)
115 if (strcasecmp(arg, "yes") == 0 ||
116 strcasecmp(arg, "true") == 0 ||
117 strcasecmp(arg, "on") == 0 ||
118 strcasecmp(arg, "enable" ) == 0 ||
119 strcasecmp(arg, "y") == 0 ||
120 strcasecmp(arg, "t") == 0 ||
121 strcasecmp(arg, "1") == 0)
127 static int parse_args(char *arg, struct connman_option *options)
134 for (i = 0; options[i].name; i++) {
135 if (strcmp(options[i].name, arg) == 0 ||
136 (strncmp(arg, "--", 2) == 0 &&
137 strcmp(&arg[2], options[i].name) == 0))
138 return options[i].val;
144 static int enable_return(DBusMessageIter *iter, const char *error,
147 char *tech = user_data;
150 str = strrchr(tech, '/');
157 fprintf(stdout, "Enabled %s\n", str);
159 fprintf(stderr, "Error %s: %s\n", str, error);
166 static int cmd_enable(char *args[], int num, struct connman_option *options)
169 dbus_bool_t b = TRUE;
177 if (check_dbus_name(args[1]) == false)
180 if (strcmp(args[1], "offline") == 0) {
181 tech = g_strdup(args[1]);
182 return __connmanctl_dbus_set_property(connection, "/",
183 "net.connman.Manager", enable_return, tech,
184 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
187 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
188 return __connmanctl_dbus_set_property(connection, tech,
189 "net.connman.Technology", enable_return, tech,
190 "Powered", DBUS_TYPE_BOOLEAN, &b);
193 static int disable_return(DBusMessageIter *iter, const char *error,
196 char *tech = user_data;
199 str = strrchr(tech, '/');
206 fprintf(stdout, "Disabled %s\n", str);
208 fprintf(stderr, "Error %s: %s\n", str, error);
215 static int cmd_disable(char *args[], int num, struct connman_option *options)
218 dbus_bool_t b = FALSE;
226 if (check_dbus_name(args[1]) == false)
229 if (strcmp(args[1], "offline") == 0) {
230 tech = g_strdup(args[1]);
231 return __connmanctl_dbus_set_property(connection, "/",
232 "net.connman.Manager", disable_return, tech,
233 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
236 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
237 return __connmanctl_dbus_set_property(connection, tech,
238 "net.connman.Technology", disable_return, tech,
239 "Powered", DBUS_TYPE_BOOLEAN, &b);
242 static int state_print(DBusMessageIter *iter, const char *error,
245 DBusMessageIter entry;
248 fprintf(stderr, "Error: %s", error);
252 dbus_message_iter_recurse(iter, &entry);
253 __connmanctl_dbus_print(&entry, " ", " = ", "\n");
254 fprintf(stdout, "\n");
259 static int cmd_state(char *args[], int num, struct connman_option *options)
264 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
265 CONNMAN_PATH, "net.connman.Manager", "GetProperties",
266 state_print, NULL, NULL, NULL);
269 static int clock_print(DBusMessageIter *iter, const char *error,
272 DBusMessageIter entry;
275 fprintf(stderr, "Error: %s", error);
279 dbus_message_iter_recurse(iter, &entry);
280 __connmanctl_dbus_print(&entry, " ", " = ", "\n");
281 fprintf(stdout, "\n");
286 static int cmd_clock(char *args[], int num, struct connman_option *options)
291 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
292 CONNMAN_PATH, "net.connman.Clock", "GetProperties",
293 clock_print, NULL, NULL, NULL);
296 static int services_list(DBusMessageIter *iter, const char *error,
300 __connmanctl_services_list(iter);
301 fprintf(stdout, "\n");
303 fprintf(stderr, "Error: %s\n", error);
309 static int peers_list(DBusMessageIter *iter,
310 const char *error, void *user_data)
313 __connmanctl_peers_list(iter);
314 fprintf(stdout, "\n");
316 fprintf(stderr, "Error: %s\n", error);
321 static int object_properties(DBusMessageIter *iter,
322 const char *error, void *user_data)
324 char *path = user_data;
326 DBusMessageIter dict;
329 fprintf(stdout, "%s\n", path);
331 dbus_message_iter_recurse(iter, &dict);
332 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
334 fprintf(stdout, "\n");
337 str = strrchr(path, '/');
343 fprintf(stderr, "Error %s: %s\n", str, error);
351 static int cmd_services(char *args[], int num, struct connman_option *options)
353 char *service_name = NULL;
360 c = parse_args(args[1], options);
367 service_name = args[2];
372 service_name = args[1];
377 return __connmanctl_dbus_method_call(connection,
378 CONNMAN_SERVICE, CONNMAN_PATH,
379 "net.connman.Manager", "GetServices",
380 services_list, NULL, NULL, NULL);
383 if (check_dbus_name(service_name) == false)
386 path = g_strdup_printf("/net/connman/service/%s", service_name);
387 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
388 "net.connman.Service", "GetProperties",
389 object_properties, path, NULL, NULL);
392 static int cmd_peers(char *args[], int num, struct connman_option *options)
394 char *peer_name = NULL;
404 return __connmanctl_dbus_method_call(connection,
405 CONNMAN_SERVICE, CONNMAN_PATH,
406 "net.connman.Manager", "GetPeers",
407 peers_list, NULL, NULL, NULL);
410 if (check_dbus_name(peer_name) == false)
413 path = g_strdup_printf("/net/connman/peer/%s", peer_name);
414 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
415 path, "net.connman.Peer", "GetProperties",
416 object_properties, path, NULL, NULL);
419 static int technology_print(DBusMessageIter *iter, const char *error,
422 DBusMessageIter array;
425 fprintf(stderr, "Error: %s\n", error);
429 dbus_message_iter_recurse(iter, &array);
430 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
431 DBusMessageIter entry, dict;
434 dbus_message_iter_recurse(&array, &entry);
435 dbus_message_iter_get_basic(&entry, &path);
436 fprintf(stdout, "%s\n", path);
438 dbus_message_iter_next(&entry);
440 dbus_message_iter_recurse(&entry, &dict);
441 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
442 fprintf(stdout, "\n");
444 dbus_message_iter_next(&array);
450 static int cmd_technologies(char *args[], int num,
451 struct connman_option *options)
456 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
457 CONNMAN_PATH, "net.connman.Manager", "GetTechnologies",
458 technology_print, NULL, NULL, NULL);
461 struct tether_enable {
466 static int tether_set_return(DBusMessageIter *iter, const char *error,
469 struct tether_enable *tether = user_data;
472 str = strrchr(tether->path, '/');
479 fprintf(stdout, "%s tethering for %s\n",
480 tether->enable ? "Enabled" : "Disabled",
483 fprintf(stderr, "Error %s %s tethering: %s\n",
485 "enabling" : "disabling", str, error);
487 g_free(tether->path);
493 static int tether_set(char *technology, int set_tethering)
495 struct tether_enable *tether = g_new(struct tether_enable, 1);
497 switch(set_tethering) {
499 tether->enable = TRUE;
502 tether->enable = FALSE;
509 tether->path = g_strdup_printf("/net/connman/technology/%s",
512 return __connmanctl_dbus_set_property(connection, tether->path,
513 "net.connman.Technology", tether_set_return,
514 tether, "Tethering", DBUS_TYPE_BOOLEAN,
518 struct tether_properties {
520 int passphrase_result;
524 static int tether_update(struct tether_properties *tether)
528 if (tether->ssid_result == 0 && tether->passphrase_result == 0) {
529 ret = tether_set("wifi", tether->set_tethering);
534 if (tether->ssid_result != -EINPROGRESS &&
535 tether->passphrase_result != -EINPROGRESS) {
543 static int tether_set_ssid_return(DBusMessageIter *iter, const char *error,
546 struct tether_properties *tether = user_data;
549 fprintf(stdout, "Wifi SSID set\n");
550 tether->ssid_result = 0;
552 fprintf(stderr, "Error setting wifi SSID: %s\n", error);
553 tether->ssid_result = -EINVAL;
556 return tether_update(tether);
559 static int tether_set_passphrase_return(DBusMessageIter *iter,
560 const char *error, void *user_data)
562 struct tether_properties *tether = user_data;
565 fprintf(stdout, "Wifi passphrase set\n");
566 tether->passphrase_result = 0;
568 fprintf(stderr, "Error setting wifi passphrase: %s\n", error);
569 tether->passphrase_result = -EINVAL;
572 return tether_update(tether);
575 static int tether_set_ssid(char *ssid, char *passphrase, int set_tethering)
577 struct tether_properties *tether = g_new(struct tether_properties, 1);
579 tether->set_tethering = set_tethering;
581 tether->ssid_result = __connmanctl_dbus_set_property(connection,
582 "/net/connman/technology/wifi",
583 "net.connman.Technology",
584 tether_set_ssid_return, tether,
585 "TetheringIdentifier", DBUS_TYPE_STRING, &ssid);
587 tether->passphrase_result =__connmanctl_dbus_set_property(connection,
588 "/net/connman/technology/wifi",
589 "net.connman.Technology",
590 tether_set_passphrase_return, tether,
591 "TetheringPassphrase", DBUS_TYPE_STRING, &passphrase);
593 if (tether->ssid_result != -EINPROGRESS &&
594 tether->passphrase_result != -EINPROGRESS) {
602 static int cmd_tether(char *args[], int num, struct connman_option *options)
604 char *ssid, *passphrase;
610 passphrase = args[num - 1];
611 ssid = args[num - 2];
613 set_tethering = parse_boolean(args[2]);
615 if (strcmp(args[1], "wifi") == 0) {
620 if (num == 5 && set_tethering == -1)
627 return tether_set_ssid(ssid, passphrase, set_tethering);
633 if (set_tethering == -1)
636 if (check_dbus_name(args[1]) == false)
639 return tether_set(args[1], set_tethering);
642 static int scan_return(DBusMessageIter *iter, const char *error,
645 char *path = user_data;
648 char *str = strrchr(path, '/');
650 fprintf(stdout, "Scan completed for %s\n", str);
652 fprintf(stderr, "Error %s: %s\n", path, error);
659 static int cmd_scan(char *args[], int num, struct connman_option *options)
669 if (check_dbus_name(args[1]) == false)
672 path = g_strdup_printf("/net/connman/technology/%s", args[1]);
673 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
674 "net.connman.Technology", "Scan",
675 scan_return, path, NULL, NULL);
678 static int connect_return(DBusMessageIter *iter, const char *error,
681 char *path = user_data;
684 char *str = strrchr(path, '/');
686 fprintf(stdout, "Connected %s\n", str);
688 fprintf(stderr, "Error %s: %s\n", path, error);
695 static int cmd_connect(char *args[], int num, struct connman_option *options)
697 const char *iface = "net.connman.Service";
706 if (check_dbus_name(args[1]) == false)
709 if (g_strstr_len(args[1], 5, "peer_") == args[1]) {
710 iface = "net.connman.Peer";
711 path = g_strdup_printf("/net/connman/peer/%s", args[1]);
713 path = g_strdup_printf("/net/connman/service/%s", args[1]);
715 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
716 iface, "Connect", connect_return, path, NULL, NULL);
719 static int disconnect_return(DBusMessageIter *iter, const char *error,
722 char *path = user_data;
725 char *str = strrchr(path, '/');
727 fprintf(stdout, "Disconnected %s\n", str);
729 fprintf(stderr, "Error %s: %s\n", path, error);
736 static int cmd_disconnect(char *args[], int num, struct connman_option *options)
738 const char *iface = "net.connman.Service";
747 if (check_dbus_name(args[1]) == false)
750 if (g_strstr_len(args[1], 5, "peer_") == args[1]) {
751 iface = "net.connman.Peer";
752 path = g_strdup_printf("/net/connman/peer/%s", args[1]);
754 path = g_strdup_printf("/net/connman/service/%s", args[1]);
756 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
757 path, iface, "Disconnect",
758 disconnect_return, path, NULL, NULL);
761 struct move_service {
766 static int move_before_return(DBusMessageIter *iter, const char *error,
769 struct move_service *services = user_data;
774 service = strrchr(services->service, '/');
776 target = strrchr(services->target, '/');
778 fprintf(stdout, "Moved %s before %s\n", service, target);
780 fprintf(stderr, "Error %s: %s\n", services->service, error);
782 g_free(services->service);
783 g_free(services->target);
789 static void move_before_append_args(DBusMessageIter *iter, void *user_data)
791 char *path = user_data;
793 dbus_message_iter_append_basic(iter,
794 DBUS_TYPE_OBJECT_PATH, &path);
799 static int cmd_service_move_before(char *args[], int num,
800 struct connman_option *options)
802 const char *iface = "net.connman.Service";
803 struct move_service *services;
811 if (check_dbus_name(args[1]) == false)
814 services = g_new(struct move_service, 1);
816 services->service = g_strdup_printf("/net/connman/service/%s", args[1]);
817 services->target = g_strdup_printf("/net/connman/service/%s", args[2]);
819 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
820 services->service, iface, "MoveBefore",
821 move_before_return, services,
822 move_before_append_args,
826 static int move_after_return(DBusMessageIter *iter, const char *error,
829 struct move_service *services = user_data;
834 service = strrchr(services->service, '/');
836 target = strrchr(services->target, '/');
838 fprintf(stdout, "Moved %s after %s\n", service, target);
840 fprintf(stderr, "Error %s: %s\n", services->service, error);
842 g_free(services->service);
843 g_free(services->target);
849 static void move_after_append_args(DBusMessageIter *iter, void *user_data)
851 char *path = user_data;
853 dbus_message_iter_append_basic(iter,
854 DBUS_TYPE_OBJECT_PATH, &path);
859 static int cmd_service_move_after(char *args[], int num,
860 struct connman_option *options)
862 const char *iface = "net.connman.Service";
863 struct move_service *services;
871 if (check_dbus_name(args[1]) == false)
874 services = g_new(struct move_service, 1);
876 services->service = g_strdup_printf("/net/connman/service/%s", args[1]);
877 services->target = g_strdup_printf("/net/connman/service/%s", args[2]);
879 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
880 services->service, iface, "MoveAfter",
881 move_after_return, services,
882 move_after_append_args,
886 static int config_return(DBusMessageIter *iter, const char *error,
889 char *service_name = user_data;
892 fprintf(stderr, "Error %s: %s\n", service_name, error);
899 struct config_append {
904 static void config_append_ipv4(DBusMessageIter *iter,
907 struct config_append *append = user_data;
908 char **opts = append->opts;
914 while (opts[i] && ipv4[i]) {
915 __connmanctl_dbus_append_dict_entry(iter, ipv4[i],
916 DBUS_TYPE_STRING, &opts[i]);
923 static void config_append_ipv6(DBusMessageIter *iter, void *user_data)
925 struct config_append *append = user_data;
926 char **opts = append->opts;
933 if (g_strcmp0(opts[0], "auto") == 0) {
936 switch (parse_boolean(opts[1])) {
941 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
942 DBUS_TYPE_STRING, &str);
949 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
950 DBUS_TYPE_STRING, &str);
957 if (g_strcmp0(opts[1], "prefered") != 0 &&
960 fprintf(stderr, "Error %s: %s\n",
967 __connmanctl_dbus_append_dict_entry(iter,
968 "Privacy", DBUS_TYPE_STRING,
973 } else if (g_strcmp0(opts[0], "manual") == 0) {
976 while (opts[i] && ipv6[i]) {
978 int value = atoi(opts[i]);
979 __connmanctl_dbus_append_dict_entry(iter,
980 ipv6[i], DBUS_TYPE_BYTE,
983 __connmanctl_dbus_append_dict_entry(iter,
984 ipv6[i], DBUS_TYPE_STRING,
992 } else if (g_strcmp0(opts[0], "off") != 0) {
993 fprintf(stderr, "Error %s: %s\n", opts[0], strerror(EINVAL));
998 __connmanctl_dbus_append_dict_entry(iter, "Method", DBUS_TYPE_STRING,
1002 static void config_append_str(DBusMessageIter *iter, void *user_data)
1004 struct config_append *append = user_data;
1005 char **opts = append->opts;
1012 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1020 static void append_servers(DBusMessageIter *iter, void *user_data)
1022 struct config_append *append = user_data;
1023 char **opts = append->opts;
1029 while (opts[i] && g_strcmp0(opts[i], "--excludes") != 0) {
1030 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1038 static void append_excludes(DBusMessageIter *iter, void *user_data)
1040 struct config_append *append = user_data;
1041 char **opts = append->opts;
1042 int i = append->values;
1044 if (!opts || !opts[i] ||
1045 g_strcmp0(opts[i], "--excludes") != 0)
1050 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1058 static void config_append_proxy(DBusMessageIter *iter, void *user_data)
1060 struct config_append *append = user_data;
1061 char **opts = append->opts;
1066 if (g_strcmp0(opts[0], "manual") == 0) {
1067 __connmanctl_dbus_append_dict_string_array(iter, "Servers",
1068 append_servers, append);
1070 __connmanctl_dbus_append_dict_string_array(iter, "Excludes",
1071 append_excludes, append);
1073 } else if (g_strcmp0(opts[0], "auto") == 0) {
1075 __connmanctl_dbus_append_dict_entry(iter, "URL",
1076 DBUS_TYPE_STRING, &opts[1]);
1080 } else if (g_strcmp0(opts[0], "direct") != 0)
1083 __connmanctl_dbus_append_dict_entry(iter, "Method",DBUS_TYPE_STRING,
1089 static int cmd_config(char *args[], int num, struct connman_option *options)
1091 int result = 0, res = 0, index = 2, oldindex = 0;
1093 char *service_name, *path;
1096 struct config_append append;
1098 service_name = args[1];
1102 if (check_dbus_name(service_name) == false)
1105 while (index < num && args[index]) {
1106 c = parse_args(args[index], options);
1107 opt_start = &args[index + 1];
1108 append.opts = opt_start;
1114 path = g_strdup_printf("/net/connman/service/%s", service_name);
1118 switch (parse_boolean(*opt_start)) {
1133 res = __connmanctl_dbus_set_property(connection,
1134 path, "net.connman.Service",
1136 g_strdup(service_name),
1138 DBUS_TYPE_BOOLEAN, &val);
1142 res = __connmanctl_dbus_set_property_dict(connection,
1143 path, "net.connman.Service",
1144 config_return, g_strdup(service_name),
1145 "IPv4.Configuration", DBUS_TYPE_STRING,
1146 config_append_ipv4, &append);
1147 index += append.values;
1151 res = __connmanctl_dbus_set_property_dict(connection,
1152 path, "net.connman.Service",
1153 config_return, g_strdup(service_name),
1154 "IPv6.Configuration", DBUS_TYPE_STRING,
1155 config_append_ipv6, &append);
1156 index += append.values;
1160 res = __connmanctl_dbus_set_property_array(connection,
1161 path, "net.connman.Service",
1162 config_return, g_strdup(service_name),
1163 "Nameservers.Configuration",
1164 DBUS_TYPE_STRING, config_append_str,
1166 index += append.values;
1170 res = __connmanctl_dbus_set_property_array(connection,
1171 path, "net.connman.Service",
1172 config_return, g_strdup(service_name),
1173 "Timeservers.Configuration",
1174 DBUS_TYPE_STRING, config_append_str,
1176 index += append.values;
1180 res = __connmanctl_dbus_set_property_array(connection,
1181 path, "net.connman.Service",
1182 config_return, g_strdup(service_name),
1183 "Domains.Configuration",
1184 DBUS_TYPE_STRING, config_append_str,
1186 index += append.values;
1190 res = __connmanctl_dbus_set_property_dict(connection,
1191 path, "net.connman.Service",
1192 config_return, g_strdup(service_name),
1193 "Proxy.Configuration",
1194 DBUS_TYPE_STRING, config_append_proxy,
1196 index += append.values;
1199 res = __connmanctl_dbus_method_call(connection,
1200 CONNMAN_SERVICE, path,
1201 "net.connman.Service", "Remove",
1202 config_return, g_strdup(service_name),
1213 if (res == -EINPROGRESS)
1214 result = -EINPROGRESS;
1216 printf("Error '%s': %s\n", args[oldindex],
1227 static DBusHandlerResult monitor_changed(DBusConnection *connection,
1228 DBusMessage *message, void *user_data)
1230 DBusMessageIter iter;
1231 const char *interface, *path;
1233 interface = dbus_message_get_interface(message);
1235 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1237 if (strncmp(interface, "net.connman.", 12) != 0)
1238 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1240 if (!strcmp(interface, "net.connman.Agent") ||
1241 !strcmp(interface, "net.connman.vpn.Agent") ||
1242 !strcmp(interface, "net.connman.Session") ||
1243 !strcmp(interface, "net.connman.Notification"))
1244 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1246 interface = strrchr(interface, '.');
1247 if (interface && *interface != '\0')
1250 path = strrchr(dbus_message_get_path(message), '/');
1251 if (path && *path != '\0')
1254 __connmanctl_save_rl();
1256 if (dbus_message_is_signal(message, "net.connman.Manager",
1257 "ServicesChanged")) {
1259 fprintf(stdout, "%-12s %-20s = {\n", interface,
1261 dbus_message_iter_init(message, &iter);
1262 __connmanctl_services_list(&iter);
1263 fprintf(stdout, "\n}\n");
1265 __connmanctl_redraw_rl();
1267 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1268 } else if (dbus_message_is_signal(message, "net.connman.Manager",
1270 fprintf(stdout, "%-12s %-20s = {\n", interface,
1272 dbus_message_iter_init(message, &iter);
1273 __connmanctl_peers_list(&iter);
1274 fprintf(stdout, "\n}\n");
1276 __connmanctl_redraw_rl();
1278 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1279 } else if (dbus_message_is_signal(message, "net.connman.vpn.Manager",
1280 "ConnectionAdded") ||
1281 dbus_message_is_signal(message,
1282 "net.connman.vpn.Manager",
1283 "ConnectionRemoved")) {
1284 interface = "vpn.Manager";
1285 path = dbus_message_get_member(message);
1287 } else if (dbus_message_is_signal(message, "net.connman.Manager",
1288 "TechnologyAdded") ||
1289 dbus_message_is_signal(message, "net.connman.Manager",
1290 "TechnologyRemoved"))
1291 path = dbus_message_get_member(message);
1293 fprintf(stdout, "%-12s %-20s ", interface, path);
1294 dbus_message_iter_init(message, &iter);
1296 __connmanctl_dbus_print(&iter, "", " = ", " = ");
1297 fprintf(stdout, "\n");
1299 __connmanctl_redraw_rl();
1301 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1308 { "Service", false },
1309 { "Technology", false },
1310 { "Manager", false },
1311 { "vpn.Manager", false },
1312 { "vpn.Connection", false },
1316 static void monitor_add(char *interface)
1318 bool add_filter = true, found = false;
1323 for (i = 0; monitor[i].interface; i++) {
1324 if (monitor[i].enabled == true)
1327 if (g_strcmp0(interface, monitor[i].interface) == 0) {
1328 if (monitor[i].enabled == true)
1331 monitor[i].enabled = true;
1339 if (add_filter == true)
1340 dbus_connection_add_filter(connection, monitor_changed,
1343 dbus_error_init(&err);
1344 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
1346 dbus_bus_add_match(connection, rule, &err);
1349 if (dbus_error_is_set(&err))
1350 fprintf(stderr, "Error: %s\n", err.message);
1353 static void monitor_del(char *interface)
1355 bool del_filter = true, found = false;
1360 for (i = 0; monitor[i].interface; i++) {
1361 if (g_strcmp0(interface, monitor[i].interface) == 0) {
1362 if (monitor[i].enabled == false)
1365 monitor[i].enabled = false;
1369 if (monitor[i].enabled == true)
1376 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
1378 dbus_bus_remove_match(connection, rule, NULL);
1381 if (del_filter == true)
1382 dbus_connection_remove_filter(connection, monitor_changed,
1386 static int cmd_monitor(char *args[], int num, struct connman_option *options)
1395 switch (parse_boolean(args[2])) {
1405 c = parse_args(args[1], options);
1408 monitor_add("Service");
1409 monitor_add("Technology");
1410 monitor_add("Manager");
1411 monitor_add("vpn.Manager");
1412 monitor_add("vpn.Connection");
1417 monitor_add("Service");
1419 monitor_del("Service");
1424 monitor_add("Technology");
1426 monitor_del("Technology");
1431 monitor_add("Manager");
1433 monitor_del("Manager");
1438 monitor_add("vpn.Manager");
1440 monitor_del("vpn.Manager");
1445 monitor_add("vpn.Connection");
1447 monitor_del("vpn.Connection");
1451 switch(parse_boolean(args[1])) {
1453 monitor_del("Service");
1454 monitor_del("Technology");
1455 monitor_del("Manager");
1456 monitor_del("vpn.Manager");
1457 monitor_del("vpn.Connection");
1461 monitor_add("Service");
1462 monitor_add("Technology");
1463 monitor_add("Manager");
1464 monitor_add("vpn.Manager");
1465 monitor_add("vpn.Connection");
1474 return -EINPROGRESS;
1479 static int cmd_agent(char *args[], int num, struct connman_option *options)
1481 if (!__connmanctl_is_interactive()) {
1482 fprintf(stderr, "Error: Not supported in non-interactive "
1493 switch(parse_boolean(args[1])) {
1495 __connmanctl_agent_unregister(connection);
1499 if (__connmanctl_agent_register(connection) == -EINPROGRESS)
1500 return -EINPROGRESS;
1512 static int vpnconnections_properties(DBusMessageIter *iter, const char *error,
1515 char *path = user_data;
1517 DBusMessageIter dict;
1520 fprintf(stdout, "%s\n", path);
1522 dbus_message_iter_recurse(iter, &dict);
1523 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
1525 fprintf(stdout, "\n");
1528 str = strrchr(path, '/');
1534 fprintf(stderr, "Error %s: %s\n", str, error);
1542 static int vpnconnections_list(DBusMessageIter *iter, const char *error,
1546 __connmanctl_vpnconnections_list(iter);
1548 fprintf(stderr, "Error: %s\n", error);
1553 static int cmd_vpnconnections(char *args[], int num,
1554 struct connman_option *options)
1556 char *vpnconnection_name, *path;
1561 vpnconnection_name = args[1];
1563 if (!vpnconnection_name)
1564 return __connmanctl_dbus_method_call(connection,
1565 VPN_SERVICE, VPN_PATH,
1566 "net.connman.vpn.Manager", "GetConnections",
1567 vpnconnections_list, NULL,
1570 if (check_dbus_name(vpnconnection_name) == false)
1573 path = g_strdup_printf("/net/connman/vpn/connection/%s",
1574 vpnconnection_name);
1575 return __connmanctl_dbus_method_call(connection, VPN_SERVICE, path,
1576 "net.connman.vpn.Connection", "GetProperties",
1577 vpnconnections_properties, path, NULL, NULL);
1581 static int cmd_vpnagent(char *args[], int num, struct connman_option *options)
1583 if (!__connmanctl_is_interactive()) {
1584 fprintf(stderr, "Error: Not supported in non-interactive "
1595 switch(parse_boolean(args[1])) {
1597 __connmanctl_vpn_agent_unregister(connection);
1601 if (__connmanctl_vpn_agent_register(connection) ==
1603 return -EINPROGRESS;
1615 static DBusMessage *session_release(DBusConnection *connection,
1616 DBusMessage *message, void *user_data)
1618 __connmanctl_save_rl();
1620 fprintf(stdout, "Session %s released\n", session_path);
1622 __connmanctl_redraw_rl();
1624 g_free(session_path);
1625 session_path = NULL;
1626 session_connected = false;
1628 return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
1631 static DBusMessage *session_update(DBusConnection *connection,
1632 DBusMessage *message, void *user_data)
1634 DBusMessageIter iter, dict;
1636 __connmanctl_save_rl();
1638 fprintf(stdout, "Session Update = {\n");
1640 dbus_message_iter_init(message, &iter);
1641 dbus_message_iter_recurse(&iter, &dict);
1643 __connmanctl_dbus_print(&dict, "", " = ", "\n");
1644 fprintf(stdout, "\n}\n");
1646 dbus_message_iter_recurse(&iter, &dict);
1648 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1649 DBusMessageIter entry, variant;
1650 char *field, *state;
1652 dbus_message_iter_recurse(&dict, &entry);
1654 dbus_message_iter_get_basic(&entry, &field);
1656 if (dbus_message_iter_get_arg_type(&entry)
1658 && !strcmp(field, "State")) {
1660 dbus_message_iter_next(&entry);
1661 dbus_message_iter_recurse(&entry, &variant);
1662 if (dbus_message_iter_get_arg_type(&variant)
1663 != DBUS_TYPE_STRING)
1666 dbus_message_iter_get_basic(&variant, &state);
1668 if (!session_connected && (!strcmp(state, "connected")
1669 || !strcmp(state, "online"))) {
1671 fprintf(stdout, "Session %s connected\n",
1673 session_connected = true;
1678 if (!strcmp(state, "disconnected") &&
1679 session_connected) {
1681 fprintf(stdout, "Session %s disconnected\n",
1683 session_connected = false;
1688 dbus_message_iter_next(&dict);
1691 __connmanctl_redraw_rl();
1693 return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
1696 static const GDBusMethodTable notification_methods[] = {
1697 { GDBUS_METHOD("Release", NULL, NULL, session_release) },
1698 { GDBUS_METHOD("Update", GDBUS_ARGS({"settings", "a{sv}"}),
1699 NULL, session_update) },
1703 static int session_notify_add(const char *path)
1705 if (session_notify_path)
1708 if (!g_dbus_register_interface(connection, path,
1709 "net.connman.Notification",
1710 notification_methods, NULL, NULL,
1712 fprintf(stderr, "Error: Failed to register VPN Agent "
1717 session_notify_path = g_strdup(path);
1722 static void session_notify_remove(void)
1724 if (!session_notify_path)
1727 g_dbus_unregister_interface(connection, session_notify_path,
1728 "net.connman.Notification");
1730 g_free(session_notify_path);
1731 session_notify_path = NULL;
1734 static int session_connect_cb(DBusMessageIter *iter, const char *error,
1738 fprintf(stderr, "Error: %s", error);
1742 return -EINPROGRESS;
1746 static int session_connect(void)
1748 return __connmanctl_dbus_method_call(connection, "net.connman",
1749 session_path, "net.connman.Session", "Connect",
1750 session_connect_cb, NULL, NULL, NULL);
1753 static int session_disconnect_cb(DBusMessageIter *iter, const char *error,
1757 fprintf(stderr, "Error: %s", error);
1762 static int session_disconnect(void)
1764 return __connmanctl_dbus_method_call(connection, "net.connman",
1765 session_path, "net.connman.Session", "Disconnect",
1766 session_disconnect_cb, NULL, NULL, NULL);
1769 static int session_create_cb(DBusMessageIter *iter, const char *error,
1772 gboolean connect = GPOINTER_TO_INT(user_data);
1776 fprintf(stderr, "Error creating session: %s", error);
1777 session_notify_remove();
1781 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH) {
1782 fprintf(stderr, "Error creating session: No session path\n");
1786 g_free(session_path);
1788 dbus_message_iter_get_basic(iter, &str);
1789 session_path = g_strdup(str);
1791 fprintf(stdout, "Session %s created\n", session_path);
1794 return session_connect();
1796 return -EINPROGRESS;
1799 static void session_create_append(DBusMessageIter *iter, void *user_data)
1801 const char *notify_path = user_data;
1803 __connmanctl_dbus_append_dict(iter, NULL, NULL);
1805 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
1809 static int session_create(gboolean connect)
1814 notify_path = g_strdup_printf("/net/connman/connmanctl%d", getpid());
1815 session_notify_add(notify_path);
1817 res = __connmanctl_dbus_method_call(connection, "net.connman", "/",
1818 "net.connman.Manager", "CreateSession",
1819 session_create_cb, GINT_TO_POINTER(connect),
1820 session_create_append, notify_path);
1822 g_free(notify_path);
1824 if (res < 0 && res != -EINPROGRESS)
1825 session_notify_remove();
1830 static int session_destroy_cb(DBusMessageIter *iter, const char *error,
1834 fprintf(stderr, "Error destroying session: %s", error);
1838 fprintf(stdout, "Session %s ended\n", session_path);
1840 g_free(session_path);
1841 session_path = NULL;
1842 session_connected = false;
1847 static void session_destroy_append(DBusMessageIter *iter, void *user_data)
1849 const char *path = user_data;
1851 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
1854 static int session_destroy(void)
1856 return __connmanctl_dbus_method_call(connection, "net.connman", "/",
1857 "net.connman.Manager", "DestroySession",
1858 session_destroy_cb, NULL,
1859 session_destroy_append, session_path);
1862 static int session_config_return(DBusMessageIter *iter, const char *error,
1865 char *property_name = user_data;
1868 fprintf(stderr, "Error setting session %s: %s\n",
1869 property_name, error);
1874 static void session_config_append_array(DBusMessageIter *iter,
1877 struct config_append *append = user_data;
1878 char **opts = append->opts;
1884 while (opts[i] && strncmp(opts[i], "--", 2) != 0) {
1885 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1893 static int session_config(char *args[], int num,
1894 struct connman_option *options)
1896 int index = 0, res = 0;
1897 struct config_append append;
1900 dbus_bool_t source_ip_rule;
1902 while (index < num && args[index]) {
1903 append.opts = &args[index];
1906 c = parse_args(args[index], options);
1910 res = __connmanctl_dbus_session_change_array(connection,
1911 session_path, session_config_return,
1912 "AllowedBearers", "AllowedBearers",
1913 session_config_append_array, &append);
1916 if (!args[index + 1]) {
1921 res = __connmanctl_dbus_session_change(connection,
1922 session_path, session_config_return,
1923 "ConnectionType", "ConnectionType",
1924 DBUS_TYPE_STRING, &args[index + 1]);
1928 if (index + 1 < num)
1929 ifname = args[index + 1];
1933 res = __connmanctl_dbus_session_change(connection,
1934 session_path, session_config_return,
1935 "AllowedInterface", "AllowedInterface",
1936 DBUS_TYPE_STRING, &ifname);
1940 if (!args[index + 1]) {
1944 switch (parse_boolean(args[index + 1])) {
1946 source_ip_rule = TRUE;
1949 source_ip_rule = FALSE;
1956 res = __connmanctl_dbus_session_change(connection,
1957 session_path, session_config_return,
1958 "SourceIPRule", "SourceIPRule",
1959 DBUS_TYPE_BOOLEAN, &source_ip_rule);
1967 if (res < 0 && res != -EINPROGRESS) {
1968 printf("Error '%s': %s\n", args[index],
1973 index += append.values;
1979 static int cmd_session(char *args[], int num, struct connman_option *options)
1988 switch(parse_boolean(command)) {
1992 return session_destroy();
1997 return session_create(FALSE);
2000 if (!strcmp(command, "connect")) {
2002 return session_create(TRUE);
2004 return session_connect();
2006 } else if (!strcmp(command, "disconnect")) {
2008 if (!session_path) {
2009 fprintf(stdout, "Session does not exist\n");
2013 return session_disconnect();
2014 } else if (!strcmp(command, "config")) {
2015 if (!session_path) {
2016 fprintf(stdout, "Session does not exist\n");
2023 return session_config(&args[2], num - 2, options);
2031 static int cmd_exit(char *args[], int num, struct connman_option *options)
2036 static char *lookup_key_from_table(GHashTable *hash, const char *text,
2040 static GHashTableIter iter;
2041 gpointer key, value;
2044 g_hash_table_iter_init(&iter, hash);
2048 while (g_hash_table_iter_next(&iter, &key, &value))
2049 if (strncmp(text, key, len) == 0)
2055 static char *lookup_service_arg(const char *text, int state)
2057 if (__connmanctl_input_calc_level() > 1) {
2058 __connmanctl_input_lookup_end();
2062 return lookup_key_from_table(service_hash, text, state);
2065 static char *lookup_peer(const char *text, int state)
2067 static GHashTableIter iter;
2068 gpointer key, value;
2072 g_hash_table_iter_init(&iter, peer_hash);
2076 while (g_hash_table_iter_next(&iter, &key, &value)) {
2077 const char *peer = key;
2078 if (strncmp(text, peer, len) == 0)
2079 return strdup(peer);
2085 static char *lookup_peer_arg(const char *text, int state)
2087 if (__connmanctl_input_calc_level() > 1) {
2088 __connmanctl_input_lookup_end();
2092 return lookup_peer(text, state);
2095 static char *lookup_technology(const char *text, int state)
2098 static GHashTableIter iter;
2099 gpointer key, value;
2102 g_hash_table_iter_init(&iter, technology_hash);
2106 while (g_hash_table_iter_next(&iter, &key, &value)) {
2107 const char *technology = key;
2108 if (strncmp(text, technology, len) == 0)
2109 return strdup(technology);
2115 static char *lookup_technology_arg(const char *text, int state)
2117 if (__connmanctl_input_calc_level() > 1) {
2118 __connmanctl_input_lookup_end();
2122 return lookup_technology(text, state);
2125 static char *lookup_technology_offline(const char *text, int state)
2128 static bool end = false;
2131 if (__connmanctl_input_calc_level() > 1) {
2132 __connmanctl_input_lookup_end();
2144 str = lookup_technology(text, state);
2150 if (strncmp(text, "offline", len) == 0)
2151 return strdup("offline");
2156 static char *lookup_on_off(const char *text, int state)
2158 char *onoff[] = { "on", "off", NULL };
2169 while (onoff[idx]) {
2173 if (!strncmp(text, str, len))
2180 static char *lookup_tether(const char *text, int state)
2184 level = __connmanctl_input_calc_level();
2186 return lookup_technology(text, state);
2189 return lookup_on_off(text, state);
2191 __connmanctl_input_lookup_end();
2196 static char *lookup_agent(const char *text, int state)
2198 if (__connmanctl_input_calc_level() > 1) {
2199 __connmanctl_input_lookup_end();
2203 return lookup_on_off(text, state);
2206 static char *lookup_vpnconnection_arg(const char *text, int state)
2208 if (__connmanctl_input_calc_level() > 1) {
2209 __connmanctl_input_lookup_end();
2213 return lookup_key_from_table(vpnconnection_hash, text, state);
2216 static struct connman_option service_options[] = {
2217 {"properties", 'p', "[<service>] (obsolete)"},
2221 static struct connman_option config_options[] = {
2222 {"nameservers", 'n', "<dns1> [<dns2>] [<dns3>]"},
2223 {"timeservers", 't', "<ntp1> [<ntp2>] [...]"},
2224 {"domains", 'd', "<domain1> [<domain2>] [...]"},
2225 {"ipv6", 'v', "off|auto [enable|disable|preferred]|\n"
2226 "\t\t\tmanual <address> <prefixlength> <gateway>"},
2227 {"proxy", 'x', "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
2228 "\t\t\t[exclude <exclude1> [<exclude2>] [...]]"},
2229 {"autoconnect", 'a', "yes|no"},
2230 {"ipv4", 'i', "off|dhcp|manual <address> <netmask> <gateway>"},
2231 {"remove", 'r', " Remove service"},
2235 static struct connman_option monitor_options[] = {
2236 {"services", 's', "[off] Monitor only services"},
2237 {"tech", 'c', "[off] Monitor only technologies"},
2238 {"manager", 'm', "[off] Monitor only manager interface"},
2239 {"vpnmanager", 'M', "[off] Monitor only VPN manager "
2241 {"vpnconnection", 'C', "[off] Monitor only VPN "
2246 static struct connman_option session_options[] = {
2247 {"bearers", 'b', "<technology1> [<technology2> [...]]"},
2248 {"type", 't', "local|internet|any"},
2249 {"ifname", 'i', "[<interface_name>]"},
2250 {"srciprule", 's', "yes|no"},
2254 static char *lookup_options(struct connman_option *options, const char *text,
2266 while (options[idx].name) {
2267 str = options[idx].name;
2270 if (str && strncmp(text, str, len) == 0)
2277 static char *lookup_monitor(const char *text, int state)
2281 level = __connmanctl_input_calc_level();
2284 return lookup_options(monitor_options, text, state);
2287 return lookup_on_off(text, state);
2289 __connmanctl_input_lookup_end();
2293 static char *lookup_config(const char *text, int state)
2295 if (__connmanctl_input_calc_level() < 2)
2296 return lookup_key_from_table(service_hash, text, state);
2298 return lookup_options(config_options, text, state);
2301 static char *lookup_session(const char *text, int state)
2303 return lookup_options(session_options, text, state);
2306 static int peer_service_cb(DBusMessageIter *iter, const char *error,
2309 bool registration = GPOINTER_TO_INT(user_data);
2312 fprintf(stderr, "Error %s peer service: %s\n",
2313 registration ? "registering" : "unregistering", error);
2315 fprintf(stdout, "Peer service %s\n",
2316 registration ? "registered" : "unregistered");
2321 struct _peer_service {
2322 unsigned char *bjr_query;
2324 unsigned char *bjr_response;
2325 int bjr_response_len;
2326 unsigned char *wfd_ies;
2333 static void append_dict_entry_fixed_array(DBusMessageIter *iter,
2334 const char *property, void *value, int length)
2336 DBusMessageIter dict_entry, variant, array;
2338 dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY,
2340 dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING,
2342 dbus_message_iter_open_container(&dict_entry, DBUS_TYPE_VARIANT,
2343 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
2345 dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
2346 DBUS_TYPE_BYTE_AS_STRING, &array);
2347 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
2349 dbus_message_iter_close_container(&variant, &array);
2350 dbus_message_iter_close_container(&dict_entry, &variant);
2351 dbus_message_iter_close_container(iter, &dict_entry);
2354 static void append_peer_service_dict(DBusMessageIter *iter, void *user_data)
2356 struct _peer_service *service = user_data;
2358 if (service->bjr_query && service->bjr_response) {
2359 append_dict_entry_fixed_array(iter, "BonjourQuery",
2360 &service->bjr_query, service->bjr_query_len);
2361 append_dict_entry_fixed_array(iter, "BonjourResponse",
2362 &service->bjr_response, service->bjr_response_len);
2363 } else if (service->upnp_service && service->version) {
2364 __connmanctl_dbus_append_dict_entry(iter, "UpnpVersion",
2365 DBUS_TYPE_INT32, &service->version);
2366 __connmanctl_dbus_append_dict_entry(iter, "UpnpService",
2367 DBUS_TYPE_STRING, &service->upnp_service);
2368 } else if (service->wfd_ies) {
2369 append_dict_entry_fixed_array(iter, "WiFiDisplayIEs",
2370 &service->wfd_ies, service->wfd_ies_len);
2374 static void peer_service_append(DBusMessageIter *iter, void *user_data)
2376 struct _peer_service *service = user_data;
2379 __connmanctl_dbus_append_dict(iter, append_peer_service_dict, service);
2381 if (service->master < 0)
2384 master = service->master == 1 ? TRUE : FALSE;
2385 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &master);
2388 static struct _peer_service *fill_in_peer_service(unsigned char *bjr_query,
2389 int bjr_query_len, unsigned char *bjr_response,
2390 int bjr_response_len, char *upnp_service,
2391 int version, unsigned char *wfd_ies,
2394 struct _peer_service *service;
2396 service = dbus_malloc0(sizeof(*service));
2398 #if defined TIZEN_EXT
2403 if (bjr_query_len && bjr_response_len) {
2404 service->bjr_query = dbus_malloc0(bjr_query_len);
2405 #if defined TIZEN_EXT
2406 if(!service->bjr_query) {
2411 memcpy(service->bjr_query, bjr_query, bjr_query_len);
2412 service->bjr_query_len = bjr_query_len;
2414 service->bjr_response = dbus_malloc0(bjr_response_len);
2415 #if defined TIZEN_EXT
2416 if(!service->bjr_response) {
2417 dbus_free(service->bjr_query);
2422 memcpy(service->bjr_response, bjr_response, bjr_response_len);
2423 service->bjr_response_len = bjr_response_len;
2424 } else if (upnp_service && version) {
2425 service->upnp_service = strdup(upnp_service);
2426 service->version = version;
2427 } else if (wfd_ies && wfd_ies_len) {
2428 service->wfd_ies = dbus_malloc0(wfd_ies_len);
2429 #if defined TIZEN_EXT
2430 if (!service->wfd_ies) {
2435 memcpy(service->wfd_ies, wfd_ies, wfd_ies_len);
2436 service->wfd_ies_len = wfd_ies_len;
2445 static void free_peer_service(struct _peer_service *service)
2447 dbus_free(service->bjr_query);
2448 dbus_free(service->bjr_response);
2449 dbus_free(service->wfd_ies);
2450 free(service->upnp_service);
2454 static int peer_service_register(unsigned char *bjr_query, int bjr_query_len,
2455 unsigned char *bjr_response, int bjr_response_len,
2456 char *upnp_service, int version,
2457 unsigned char *wfd_ies, int wfd_ies_len, int master)
2459 struct _peer_service *service;
2460 bool registration = true;
2463 service = fill_in_peer_service(bjr_query, bjr_query_len, bjr_response,
2464 bjr_response_len, upnp_service, version,
2465 wfd_ies, wfd_ies_len);
2469 service->master = master;
2471 ret = __connmanctl_dbus_method_call(connection, "net.connman", "/",
2472 "net.connman.Manager", "RegisterPeerService",
2473 peer_service_cb, GINT_TO_POINTER(registration),
2474 peer_service_append, service);
2476 free_peer_service(service);
2481 static int peer_service_unregister(unsigned char *bjr_query, int bjr_query_len,
2482 unsigned char *bjr_response, int bjr_response_len,
2483 char *upnp_service, int version,
2484 unsigned char *wfd_ies, int wfd_ies_len)
2486 struct _peer_service *service;
2487 bool registration = false;
2490 service = fill_in_peer_service(bjr_query, bjr_query_len, bjr_response,
2491 bjr_response_len, upnp_service, version,
2492 wfd_ies, wfd_ies_len);
2496 service->master = -1;
2498 ret = __connmanctl_dbus_method_call(connection, "net.connman", "/",
2499 "net.connman.Manager", "UnregisterPeerService",
2500 peer_service_cb, GINT_TO_POINTER(registration),
2501 peer_service_append, service);
2503 free_peer_service(service);
2508 static int parse_spec_array(char *command, unsigned char spec[1024])
2510 int length, pos, end;
2514 end = strlen(command);
2515 for (e = NULL, length = pos = 0; command[pos] != '\0'; length++) {
2519 b[0] = command[pos];
2520 b[1] = command[pos+1];
2522 spec[length] = strtol(b, &e, 16);
2523 if (e && *e != '\0')
2532 static int cmd_peer_service(char *args[], int num,
2533 struct connman_option *options)
2535 unsigned char bjr_query[1024] = {};
2536 unsigned char bjr_response[1024] = {};
2537 unsigned char wfd_ies[1024] = {};
2538 char *upnp_service = NULL;
2539 int bjr_query_len = 0, bjr_response_len = 0;
2540 int version = 0, master = 0, wfd_ies_len = 0;
2546 if (!strcmp(args[2], "wfd_ies")) {
2547 wfd_ies_len = parse_spec_array(args[3], wfd_ies);
2548 if (wfd_ies_len == -EINVAL)
2558 if (!strcmp(args[2], "bjr_query")) {
2559 if (strcmp(args[4], "bjr_response"))
2561 bjr_query_len = parse_spec_array(args[3], bjr_query);
2562 bjr_response_len = parse_spec_array(args[5], bjr_response);
2564 if (bjr_query_len == -EINVAL || bjr_response_len == -EINVAL)
2566 } else if (!strcmp(args[2], "upnp_service")) {
2569 if (strcmp(args[4], "upnp_version"))
2571 upnp_service = args[3];
2572 version = strtol(args[5], &e, 10);
2579 master = parse_boolean(args[6]);
2584 if (!strcmp(args[1], "register")) {
2585 return peer_service_register(bjr_query, bjr_query_len,
2586 bjr_response, bjr_response_len, upnp_service,
2587 version, wfd_ies, wfd_ies_len, master);
2588 } else if (!strcmp(args[1], "unregister")) {
2589 return peer_service_unregister(bjr_query, bjr_query_len,
2590 bjr_response, bjr_response_len, upnp_service,
2591 version, wfd_ies, wfd_ies_len);
2597 static const struct {
2599 const char *argument;
2600 struct connman_option *options;
2601 int (*func) (char *args[], int num, struct connman_option *options);
2603 __connmanctl_lookup_cb cb;
2605 { "state", NULL, NULL, cmd_state,
2606 "Shows if the system is online or offline", NULL },
2607 { "technologies", NULL, NULL, cmd_technologies,
2608 "Display technologies", NULL },
2609 { "clock", NULL, NULL, cmd_clock,
2610 "Get System Clock Properties", NULL },
2611 { "enable", "<technology>|offline", NULL, cmd_enable,
2612 "Enables given technology or offline mode",
2613 lookup_technology_offline },
2614 { "disable", "<technology>|offline", NULL, cmd_disable,
2615 "Disables given technology or offline mode",
2616 lookup_technology_offline },
2617 { "tether", "<technology> on|off\n"
2618 " wifi [on|off] <ssid> <passphrase> ",
2620 "Enable, disable tethering, set SSID and passphrase for wifi",
2622 { "services", "[<service>]", service_options, cmd_services,
2623 "Display services", lookup_service_arg },
2624 { "peers", "[peer]", NULL, cmd_peers,
2625 "Display peers", lookup_peer_arg },
2626 { "scan", "<technology>", NULL, cmd_scan,
2627 "Scans for new services for given technology",
2628 lookup_technology_arg },
2629 { "connect", "<service/peer>", NULL, cmd_connect,
2630 "Connect a given service or peer", lookup_service_arg },
2631 { "disconnect", "<service/peer>", NULL, cmd_disconnect,
2632 "Disconnect a given service or peer", lookup_service_arg },
2633 { "move-before", "<service> <target service> ", NULL,
2634 cmd_service_move_before, "Move <service> before <target service>",
2635 lookup_service_arg },
2636 { "move-after", "<service> <target service> ", NULL,
2637 cmd_service_move_after, "Move <service> after <target service>",
2638 lookup_service_arg },
2639 { "config", "<service>", config_options, cmd_config,
2640 "Set service configuration options", lookup_config },
2641 { "monitor", "[off]", monitor_options, cmd_monitor,
2642 "Monitor signals from interfaces", lookup_monitor },
2643 { "agent", "on|off", NULL, cmd_agent,
2644 "Agent mode", lookup_agent },
2645 { "vpnconnections", "[<connection>]", NULL, cmd_vpnconnections,
2646 "Display VPN connections", lookup_vpnconnection_arg },
2647 { "vpnagent", "on|off", NULL, cmd_vpnagent,
2648 "VPN Agent mode", lookup_agent },
2649 { "session", "on|off|connect|disconnect|config", session_options,
2650 cmd_session, "Enable or disable a session", lookup_session },
2651 { "peer_service", "register|unregister <specs> <master>\n"
2652 "Where specs are:\n"
2653 "\tbjr_query <query> bjr_response <response>\n"
2654 "\tupnp_service <service> upnp_version <version>\n"
2655 "\twfd_ies <ies>\n", NULL,
2656 cmd_peer_service, "(Un)Register a Peer Service", NULL },
2657 { "help", NULL, NULL, cmd_help,
2658 "Show help", NULL },
2659 { "exit", NULL, NULL, cmd_exit,
2661 { "quit", NULL, NULL, cmd_exit,
2666 static int cmd_help(char *args[], int num, struct connman_option *options)
2668 bool interactive = __connmanctl_is_interactive();
2671 if (interactive == false)
2672 fprintf(stdout, "Usage: connmanctl [[command] [args]]\n");
2674 for (i = 0; cmd_table[i].cmd; i++) {
2675 const char *cmd = cmd_table[i].cmd;
2676 const char *argument = cmd_table[i].argument;
2677 const char *desc = cmd_table[i].desc;
2679 printf("%-16s%-22s%s\n", cmd? cmd: "",
2680 argument? argument: "",
2683 if (cmd_table[i].options) {
2684 for (j = 0; cmd_table[i].options[j].name;
2686 const char *options_desc =
2687 cmd_table[i].options[j].desc ?
2688 cmd_table[i].options[j].desc: "";
2690 printf(" --%-16s%s\n",
2691 cmd_table[i].options[j].name,
2697 if (interactive == false)
2698 fprintf(stdout, "\nNote: arguments and output are considered "
2699 "EXPERIMENTAL for now.\n");
2704 __connmanctl_lookup_cb __connmanctl_get_lookup_func(const char *text)
2706 int i, cmdlen, textlen;
2711 textlen = strlen(text);
2713 for (i = 0; cmd_table[i].cmd; i++) {
2714 cmdlen = strlen(cmd_table[i].cmd);
2716 if (textlen > cmdlen && text[cmdlen] != ' ')
2719 if (strncmp(cmd_table[i].cmd, text, cmdlen) == 0)
2720 return cmd_table[i].cb;
2726 int __connmanctl_commands(DBusConnection *dbus_conn, char *argv[], int argc)
2730 connection = dbus_conn;
2732 for (i = 0; cmd_table[i].cmd; i++) {
2733 if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
2734 cmd_table[i].func) {
2735 result = cmd_table[i].func(argv, argc,
2736 cmd_table[i].options);
2737 if (result < 0 && result != -EINPROGRESS)
2738 fprintf(stderr, "Error '%s': %s\n", argv[0],
2744 fprintf(stderr, "Error '%s': Unknown command\n", argv[0]);
2748 char *__connmanctl_lookup_command(const char *text, int state)
2758 while (cmd_table[i].cmd) {
2759 const char *command = cmd_table[i].cmd;
2763 if (strncmp(text, command, len) == 0)
2764 return strdup(command);
2770 static char *get_path(char *full_path)
2774 path = strrchr(full_path, '/');
2775 if (path && *path != '\0')
2783 static void add_service_id(const char *path)
2785 g_hash_table_replace(service_hash, g_strdup(path),
2786 GINT_TO_POINTER(TRUE));
2789 static void remove_service_id(const char *path)
2791 g_hash_table_remove(service_hash, path);
2794 static void services_added(DBusMessageIter *iter)
2796 DBusMessageIter array;
2799 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
2801 dbus_message_iter_recurse(iter, &array);
2802 if (dbus_message_iter_get_arg_type(&array) !=
2803 DBUS_TYPE_OBJECT_PATH)
2806 dbus_message_iter_get_basic(&array, &path);
2807 add_service_id(get_path(path));
2809 dbus_message_iter_next(iter);
2813 static void update_services(DBusMessageIter *iter)
2815 DBusMessageIter array;
2818 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2821 dbus_message_iter_recurse(iter, &array);
2822 services_added(&array);
2824 dbus_message_iter_next(iter);
2825 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2828 dbus_message_iter_recurse(iter, &array);
2829 while (dbus_message_iter_get_arg_type(&array) ==
2830 DBUS_TYPE_OBJECT_PATH) {
2831 dbus_message_iter_get_basic(&array, &path);
2832 remove_service_id(get_path(path));
2834 dbus_message_iter_next(&array);
2838 static int populate_service_hash(DBusMessageIter *iter, const char *error,
2842 fprintf(stderr, "Error getting services: %s", error);
2846 update_services(iter);
2850 static void add_vpnconnection_id(const char *path)
2852 g_hash_table_replace(vpnconnection_hash, g_strdup(path),
2853 GINT_TO_POINTER(TRUE));
2856 static void remove_vpnconnection_id(const char *path)
2858 g_hash_table_remove(vpnconnection_hash, path);
2861 static void vpnconnection_added(DBusMessageIter *iter)
2865 dbus_message_iter_get_basic(iter, &path);
2866 add_vpnconnection_id(get_path(path));
2869 static void vpnconnection_removed(DBusMessageIter *iter)
2873 dbus_message_iter_get_basic(iter, &path);
2874 remove_vpnconnection_id(get_path(path));
2877 static void add_vpnconnections(DBusMessageIter *iter)
2879 DBusMessageIter array;
2882 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
2884 dbus_message_iter_recurse(iter, &array);
2885 if (dbus_message_iter_get_arg_type(&array) !=
2886 DBUS_TYPE_OBJECT_PATH)
2889 dbus_message_iter_get_basic(&array, &path);
2890 add_vpnconnection_id(get_path(path));
2892 dbus_message_iter_next(iter);
2896 static int populate_vpnconnection_hash(DBusMessageIter *iter, const char *error,
2899 DBusMessageIter array;
2902 fprintf(stderr, "Error getting VPN connections: %s", error);
2906 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2909 dbus_message_iter_recurse(iter, &array);
2911 add_vpnconnections(&array);
2916 static void add_peer_id(const char *path)
2918 g_hash_table_replace(peer_hash, g_strdup(path), GINT_TO_POINTER(TRUE));
2921 static void remove_peer_id(const char *path)
2923 g_hash_table_remove(peer_hash, path);
2926 static void peers_added(DBusMessageIter *iter)
2928 DBusMessageIter array;
2931 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
2933 dbus_message_iter_recurse(iter, &array);
2934 if (dbus_message_iter_get_arg_type(&array) !=
2935 DBUS_TYPE_OBJECT_PATH)
2938 dbus_message_iter_get_basic(&array, &path);
2939 add_peer_id(get_path(path));
2941 dbus_message_iter_next(iter);
2945 static void update_peers(DBusMessageIter *iter)
2947 DBusMessageIter array;
2950 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2953 dbus_message_iter_recurse(iter, &array);
2954 peers_added(&array);
2956 dbus_message_iter_next(iter);
2957 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2960 dbus_message_iter_recurse(iter, &array);
2961 while (dbus_message_iter_get_arg_type(&array) ==
2962 DBUS_TYPE_OBJECT_PATH) {
2963 dbus_message_iter_get_basic(&array, &path);
2964 remove_peer_id(get_path(path));
2966 dbus_message_iter_next(&array);
2970 static int populate_peer_hash(DBusMessageIter *iter,
2971 const char *error, void *user_data)
2974 fprintf(stderr, "Error getting peers: %s", error);
2982 static void add_technology_id(const char *path)
2984 g_hash_table_replace(technology_hash, g_strdup(path),
2985 GINT_TO_POINTER(TRUE));
2988 static void remove_technology_id(const char *path)
2990 g_hash_table_remove(technology_hash, path);
2993 static void remove_technology(DBusMessageIter *iter)
2997 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
3000 dbus_message_iter_get_basic(iter, &path);
3001 remove_technology_id(get_path(path));
3004 static void add_technology(DBusMessageIter *iter)
3008 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
3011 dbus_message_iter_get_basic(iter, &path);
3012 add_technology_id(get_path(path));
3015 static void update_technologies(DBusMessageIter *iter)
3017 DBusMessageIter array;
3019 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
3022 dbus_message_iter_recurse(iter, &array);
3024 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
3025 DBusMessageIter object_path;
3027 dbus_message_iter_recurse(&array, &object_path);
3029 add_technology(&object_path);
3031 dbus_message_iter_next(&array);
3035 static int populate_technology_hash(DBusMessageIter *iter, const char *error,
3039 fprintf(stderr, "Error getting technologies: %s", error);
3043 update_technologies(iter);
3048 static DBusHandlerResult monitor_completions_changed(
3049 DBusConnection *connection,
3050 DBusMessage *message, void *user_data)
3052 bool *enabled = user_data;
3053 DBusMessageIter iter;
3054 DBusHandlerResult handled;
3057 handled = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3059 handled = DBUS_HANDLER_RESULT_HANDLED;
3061 if (dbus_message_is_signal(message, "net.connman.Manager",
3062 "ServicesChanged")) {
3063 dbus_message_iter_init(message, &iter);
3064 update_services(&iter);
3068 if (dbus_message_is_signal(message, "net.connman.vpn.Manager",
3069 "ConnectionAdded")) {
3070 dbus_message_iter_init(message, &iter);
3071 vpnconnection_added(&iter);
3075 if (dbus_message_is_signal(message, "net.connman.vpn.Manager",
3076 "ConnectionRemoved")) {
3077 dbus_message_iter_init(message, &iter);
3078 vpnconnection_removed(&iter);
3082 if (dbus_message_is_signal(message, "net.connman.Manager",
3084 dbus_message_iter_init(message, &iter);
3085 update_peers(&iter);
3089 if (dbus_message_is_signal(message, "net.connman.Manager",
3090 "TechnologyAdded")) {
3091 dbus_message_iter_init(message, &iter);
3092 add_technology(&iter);
3096 if (dbus_message_is_signal(message, "net.connman.Manager",
3097 "TechnologyRemoved")) {
3098 dbus_message_iter_init(message, &iter);
3099 remove_technology(&iter);
3103 if (!g_strcmp0(dbus_message_get_interface(message),
3104 "net.connman.Manager"))
3107 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3110 void __connmanctl_monitor_completions(DBusConnection *dbus_conn)
3112 bool *manager_enabled = NULL;
3116 for (i = 0; monitor[i].interface; i++) {
3117 if (!strcmp(monitor[i].interface, "Manager")) {
3118 manager_enabled = &monitor[i].enabled;
3124 g_hash_table_destroy(service_hash);
3125 g_hash_table_destroy(vpnconnection_hash);
3126 g_hash_table_destroy(technology_hash);
3128 dbus_bus_remove_match(connection,
3129 "type='signal',interface='net.connman.Manager'", NULL);
3130 dbus_bus_remove_match(connection,
3131 "type='signal',interface='net.connman.vpn.Manager'",
3133 dbus_connection_remove_filter(connection,
3134 monitor_completions_changed,
3139 connection = dbus_conn;
3141 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
3144 vpnconnection_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
3147 peer_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
3150 technology_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
3153 __connmanctl_dbus_method_call(connection,
3154 CONNMAN_SERVICE, CONNMAN_PATH,
3155 "net.connman.Manager", "GetServices",
3156 populate_service_hash, NULL, NULL, NULL);
3158 __connmanctl_dbus_method_call(connection,
3159 VPN_SERVICE, CONNMAN_PATH,
3160 "net.connman.vpn.Manager", "GetConnections",
3161 populate_vpnconnection_hash, NULL, NULL, NULL);
3163 __connmanctl_dbus_method_call(connection,
3164 CONNMAN_SERVICE, CONNMAN_PATH,
3165 "net.connman.Manager", "GetPeers",
3166 populate_peer_hash, NULL, NULL, NULL);
3168 __connmanctl_dbus_method_call(connection,
3169 CONNMAN_SERVICE, CONNMAN_PATH,
3170 "net.connman.Manager", "GetTechnologies",
3171 populate_technology_hash, NULL, NULL, NULL);
3173 dbus_connection_add_filter(connection,
3174 monitor_completions_changed, manager_enabled,
3177 dbus_error_init(&err);
3178 dbus_bus_add_match(connection,
3179 "type='signal',interface='net.connman.Manager'", &err);
3181 if (dbus_error_is_set(&err)) {
3182 fprintf(stderr, "Error: %s\n", err.message);
3186 dbus_bus_add_match(connection,
3187 "type='signal',interface='net.connman.vpn.Manager'",
3190 if (dbus_error_is_set(&err))
3191 fprintf(stderr, "Error: %s\n", err.message);