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"
42 #include "tethering.h"
46 #include "vpnconnections.h"
48 static DBusConnection *connection;
49 static GHashTable *service_hash;
50 static GHashTable *vpnconnection_hash;
51 static GHashTable *peer_hash;
52 static GHashTable *technology_hash;
53 static char *session_notify_path;
54 static char *session_path;
55 static bool session_connected;
57 struct connman_option {
63 static char *ipv4[] = {
71 static char *ipv6[] = {
79 static int cmd_help(char *args[], int num, struct connman_option *options);
81 static bool check_dbus_name(const char *name)
84 * Valid dbus chars should be [A-Z][a-z][0-9]_
85 * and should not start with number.
89 if (!name || name[0] == '\0')
92 for (i = 0; name[i] != '\0'; i++)
93 if (!((name[i] >= 'A' && name[i] <= 'Z') ||
94 (name[i] >= 'a' && name[i] <= 'z') ||
95 (name[i] >= '0' && name[i] <= '9') ||
102 static int parse_boolean(char *arg)
107 if (strcasecmp(arg, "no") == 0 ||
108 strcasecmp(arg, "false") == 0 ||
109 strcasecmp(arg, "off" ) == 0 ||
110 strcasecmp(arg, "disable" ) == 0 ||
111 strcasecmp(arg, "n") == 0 ||
112 strcasecmp(arg, "f") == 0 ||
113 strcasecmp(arg, "0") == 0)
116 if (strcasecmp(arg, "yes") == 0 ||
117 strcasecmp(arg, "true") == 0 ||
118 strcasecmp(arg, "on") == 0 ||
119 strcasecmp(arg, "enable" ) == 0 ||
120 strcasecmp(arg, "y") == 0 ||
121 strcasecmp(arg, "t") == 0 ||
122 strcasecmp(arg, "1") == 0)
128 static int parse_args(char *arg, struct connman_option *options)
135 for (i = 0; options[i].name; i++) {
136 if (strcmp(options[i].name, arg) == 0 ||
137 (strncmp(arg, "--", 2) == 0 &&
138 strcmp(&arg[2], options[i].name) == 0))
139 return options[i].val;
145 static int enable_return(DBusMessageIter *iter, int errnum, const char *error,
148 char *tech = user_data;
151 str = strrchr(tech, '/');
159 fprintf(stdout, "Enabled %s\n", str);
162 fprintf(stderr, "%s is not available\n", str);
165 fprintf(stderr, "%s is already enabled\n", str);
168 fprintf(stderr, "Error %s: %s\n", str, error);
176 static int cmd_enable(char *args[], int num, struct connman_option *options)
179 dbus_bool_t b = TRUE;
187 if (check_dbus_name(args[1]) == false)
190 if (strcmp(args[1], "offline") == 0) {
191 tech = g_strdup(args[1]);
192 return __connmanctl_dbus_set_property(connection, "/",
193 "net.connman.Manager", enable_return, tech,
194 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
197 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
198 return __connmanctl_dbus_set_property(connection, tech,
199 "net.connman.Technology", enable_return, tech,
200 "Powered", DBUS_TYPE_BOOLEAN, &b);
203 static int disable_return(DBusMessageIter *iter, int errnum, const char *error,
206 char *tech = user_data;
209 str = strrchr(tech, '/');
217 fprintf(stdout, "Disable %s\n", str);
220 fprintf(stderr, "%s is not available\n", str);
223 fprintf(stderr, "%s is already disabled\n", str);
226 fprintf(stderr, "Error %s: %s\n", str, error);
234 static int cmd_disable(char *args[], int num, struct connman_option *options)
237 dbus_bool_t b = FALSE;
245 if (check_dbus_name(args[1]) == false)
248 if (strcmp(args[1], "offline") == 0) {
249 tech = g_strdup(args[1]);
250 return __connmanctl_dbus_set_property(connection, "/",
251 "net.connman.Manager", disable_return, tech,
252 "OfflineMode", DBUS_TYPE_BOOLEAN, &b);
255 tech = g_strdup_printf("/net/connman/technology/%s", args[1]);
256 return __connmanctl_dbus_set_property(connection, tech,
257 "net.connman.Technology", disable_return, tech,
258 "Powered", DBUS_TYPE_BOOLEAN, &b);
261 static int state_print(DBusMessageIter *iter, int errnum, const char *error,
264 DBusMessageIter entry;
267 fprintf(stderr, "Error: %s\n", error);
271 dbus_message_iter_recurse(iter, &entry);
272 __connmanctl_dbus_print(&entry, " ", " = ", "\n");
273 fprintf(stdout, "\n");
278 static int cmd_state(char *args[], int num, struct connman_option *options)
283 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
284 CONNMAN_PATH, "net.connman.Manager", "GetProperties",
285 state_print, NULL, NULL, NULL);
288 static int clock_print(DBusMessageIter *iter, int errnum, const char *error,
291 DBusMessageIter entry;
294 fprintf(stderr, "Error: %s\n", error);
298 dbus_message_iter_recurse(iter, &entry);
299 __connmanctl_dbus_print(&entry, " ", " = ", "\n");
300 fprintf(stdout, "\n");
305 static int cmd_clock(char *args[], int num, struct connman_option *options)
310 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
311 CONNMAN_PATH, "net.connman.Clock", "GetProperties",
312 clock_print, NULL, NULL, NULL);
315 static int services_list(DBusMessageIter *iter, int errnum, const char *error,
319 __connmanctl_services_list(iter);
320 fprintf(stdout, "\n");
322 fprintf(stderr, "Error: %s\n", error);
328 static int peers_list(DBusMessageIter *iter, int errnum,
329 const char *error, void *user_data)
332 __connmanctl_peers_list(iter);
333 fprintf(stdout, "\n");
335 fprintf(stderr, "Error: %s\n", error);
340 static int tethering_clients_list(DBusMessageIter *iter, int errnum,
341 const char *error, void *user_data)
344 __connmanctl_tethering_clients_list(iter);
345 fprintf(stdout, "\n");
347 fprintf(stderr, "Error: %s\n", error);
352 static int object_properties(DBusMessageIter *iter, int errnum,
353 const char *error, void *user_data)
355 char *path = user_data;
357 DBusMessageIter dict;
360 fprintf(stdout, "%s\n", path);
362 dbus_message_iter_recurse(iter, &dict);
363 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
365 fprintf(stdout, "\n");
368 str = strrchr(path, '/');
374 fprintf(stderr, "Error %s: %s\n", str, error);
382 static int cmd_services(char *args[], int num, struct connman_option *options)
384 char *service_name = NULL;
391 c = parse_args(args[1], options);
398 service_name = args[2];
403 service_name = args[1];
408 return __connmanctl_dbus_method_call(connection,
409 CONNMAN_SERVICE, CONNMAN_PATH,
410 "net.connman.Manager", "GetServices",
411 services_list, NULL, NULL, NULL);
414 if (check_dbus_name(service_name) == false)
417 path = g_strdup_printf("/net/connman/service/%s", service_name);
418 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
419 "net.connman.Service", "GetProperties",
420 object_properties, path, NULL, NULL);
423 static int cmd_peers(char *args[], int num, struct connman_option *options)
425 char *peer_name = NULL;
435 return __connmanctl_dbus_method_call(connection,
436 CONNMAN_SERVICE, CONNMAN_PATH,
437 "net.connman.Manager", "GetPeers",
438 peers_list, NULL, NULL, NULL);
441 if (check_dbus_name(peer_name) == false)
444 path = g_strdup_printf("/net/connman/peer/%s", peer_name);
445 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
446 path, "net.connman.Peer", "GetProperties",
447 object_properties, path, NULL, NULL);
450 static int technology_print(DBusMessageIter *iter, int errnum, const char *error,
453 DBusMessageIter array;
456 fprintf(stderr, "Error: %s\n", error);
460 dbus_message_iter_recurse(iter, &array);
461 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
462 DBusMessageIter entry, dict;
465 dbus_message_iter_recurse(&array, &entry);
466 dbus_message_iter_get_basic(&entry, &path);
467 fprintf(stdout, "%s\n", path);
469 dbus_message_iter_next(&entry);
471 dbus_message_iter_recurse(&entry, &dict);
472 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
473 fprintf(stdout, "\n");
475 dbus_message_iter_next(&array);
481 static int cmd_technologies(char *args[], int num,
482 struct connman_option *options)
487 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
488 CONNMAN_PATH, "net.connman.Manager", "GetTechnologies",
489 technology_print, NULL, NULL, NULL);
492 struct tether_enable {
497 static int tether_set_return(DBusMessageIter *iter, int errnum,
498 const char *error, void *user_data)
500 struct tether_enable *tether = user_data;
503 str = strrchr(tether->path, '/');
510 fprintf(stdout, "%s tethering for %s\n",
511 tether->enable ? "Enabled" : "Disabled",
514 fprintf(stderr, "Error %s %s tethering: %s\n",
516 "enabling" : "disabling", str, error);
518 g_free(tether->path);
524 static int tether_set(char *technology, int set_tethering)
526 struct tether_enable *tether = g_new(struct tether_enable, 1);
528 switch(set_tethering) {
530 tether->enable = TRUE;
533 tether->enable = FALSE;
540 tether->path = g_strdup_printf("/net/connman/technology/%s",
543 return __connmanctl_dbus_set_property(connection, tether->path,
544 "net.connman.Technology", tether_set_return,
545 tether, "Tethering", DBUS_TYPE_BOOLEAN,
549 struct tether_properties {
551 int passphrase_result;
555 static int tether_update(struct tether_properties *tether)
559 if (tether->ssid_result == 0 && tether->passphrase_result == 0) {
560 ret = tether_set("wifi", tether->set_tethering);
565 if (tether->ssid_result != -EINPROGRESS &&
566 tether->passphrase_result != -EINPROGRESS) {
574 static int tether_set_ssid_return(DBusMessageIter *iter, int errnum,
575 const char *error, void *user_data)
577 struct tether_properties *tether = user_data;
580 fprintf(stdout, "Wifi SSID set\n");
581 tether->ssid_result = 0;
583 fprintf(stderr, "Error setting wifi SSID: %s\n", error);
584 tether->ssid_result = -EINVAL;
587 return tether_update(tether);
590 static int tether_set_passphrase_return(DBusMessageIter *iter, int errnum,
591 const char *error, void *user_data)
593 struct tether_properties *tether = user_data;
596 fprintf(stdout, "Wifi passphrase set\n");
597 tether->passphrase_result = 0;
599 fprintf(stderr, "Error setting wifi passphrase: %s\n", error);
600 tether->passphrase_result = -EINVAL;
603 return tether_update(tether);
606 static int tether_set_ssid(char *ssid, char *passphrase, int set_tethering)
608 struct tether_properties *tether = g_new(struct tether_properties, 1);
610 tether->set_tethering = set_tethering;
612 tether->ssid_result = __connmanctl_dbus_set_property(connection,
613 "/net/connman/technology/wifi",
614 "net.connman.Technology",
615 tether_set_ssid_return, tether,
616 "TetheringIdentifier", DBUS_TYPE_STRING, &ssid);
618 tether->passphrase_result =__connmanctl_dbus_set_property(connection,
619 "/net/connman/technology/wifi",
620 "net.connman.Technology",
621 tether_set_passphrase_return, tether,
622 "TetheringPassphrase", DBUS_TYPE_STRING, &passphrase);
624 if (tether->ssid_result != -EINPROGRESS &&
625 tether->passphrase_result != -EINPROGRESS) {
633 static int cmd_tether(char *args[], int num, struct connman_option *options)
635 char *ssid, *passphrase;
641 passphrase = args[num - 1];
642 ssid = args[num - 2];
644 set_tethering = parse_boolean(args[2]);
646 if (strcmp(args[1], "wifi") == 0) {
651 if (num == 5 && set_tethering == -1)
658 return tether_set_ssid(ssid, passphrase, set_tethering);
664 if (set_tethering == -1)
667 if (check_dbus_name(args[1]) == false)
670 return tether_set(args[1], set_tethering);
673 static int cmd_tethering_clients(char *args[], int num, struct connman_option *options)
678 return __connmanctl_dbus_method_call(connection,
679 CONNMAN_SERVICE, CONNMAN_PATH,
680 "net.connman.Manager", "GetTetheringClients",
681 tethering_clients_list, NULL, NULL, NULL);
684 static int scan_return(DBusMessageIter *iter, int ernnum, const char *error,
687 char *path = user_data;
690 char *str = strrchr(path, '/');
692 fprintf(stdout, "Scan completed for %s\n", str);
694 fprintf(stderr, "Error %s: %s\n", path, error);
701 static int cmd_scan(char *args[], int num, struct connman_option *options)
711 if (check_dbus_name(args[1]) == false)
714 path = g_strdup_printf("/net/connman/technology/%s", args[1]);
715 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
716 "net.connman.Technology", "Scan",
717 scan_return, path, NULL, NULL);
720 static int connect_return(DBusMessageIter *iter, int errnum,
721 const char *error, void *user_data)
723 char *path = user_data;
726 char *str = strrchr(path, '/');
728 fprintf(stdout, "Connected %s\n", str);
730 fprintf(stderr, "Error %s: %s\n", path, error);
737 static int cmd_connect(char *args[], int num, struct connman_option *options)
739 const char *iface = "net.connman.Service";
748 if (check_dbus_name(args[1]) == false)
751 if (g_strstr_len(args[1], 5, "peer_") == args[1]) {
752 iface = "net.connman.Peer";
753 path = g_strdup_printf("/net/connman/peer/%s", args[1]);
755 path = g_strdup_printf("/net/connman/service/%s", args[1]);
757 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
758 iface, "Connect", connect_return, path, NULL, NULL);
761 static int disconnect_return(DBusMessageIter *iter, int errnum,
762 const char *error, void *user_data)
764 char *path = user_data;
767 char *str = strrchr(path, '/');
769 fprintf(stdout, "Disconnected %s\n", str);
771 fprintf(stderr, "Error %s: %s\n", path, error);
778 static int cmd_disconnect(char *args[], int num, struct connman_option *options)
780 const char *iface = "net.connman.Service";
789 if (check_dbus_name(args[1]) == false)
792 if (g_strstr_len(args[1], 5, "peer_") == args[1]) {
793 iface = "net.connman.Peer";
794 path = g_strdup_printf("/net/connman/peer/%s", args[1]);
796 path = g_strdup_printf("/net/connman/service/%s", args[1]);
798 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
799 path, iface, "Disconnect",
800 disconnect_return, path, NULL, NULL);
803 struct move_service {
808 static int move_before_return(DBusMessageIter *iter, int errnum,
809 const char *error, void *user_data)
811 struct move_service *services = user_data;
816 service = strrchr(services->service, '/');
818 target = strrchr(services->target, '/');
820 fprintf(stdout, "Moved %s before %s\n", service, target);
822 fprintf(stderr, "Error %s: %s\n", services->service, error);
824 g_free(services->service);
825 g_free(services->target);
831 static void move_before_append_args(DBusMessageIter *iter, void *user_data)
833 char *path = user_data;
835 dbus_message_iter_append_basic(iter,
836 DBUS_TYPE_OBJECT_PATH, &path);
839 static int cmd_service_move_before(char *args[], int num,
840 struct connman_option *options)
842 const char *iface = "net.connman.Service";
843 struct move_service *services;
851 if (check_dbus_name(args[1]) == false)
854 services = g_new(struct move_service, 1);
856 services->service = g_strdup_printf("/net/connman/service/%s", args[1]);
857 services->target = g_strdup_printf("/net/connman/service/%s", args[2]);
859 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
860 services->service, iface, "MoveBefore",
861 move_before_return, services,
862 move_before_append_args,
866 static int move_after_return(DBusMessageIter *iter, int errnum,
867 const char *error, void *user_data)
869 struct move_service *services = user_data;
874 service = strrchr(services->service, '/');
876 target = strrchr(services->target, '/');
878 fprintf(stdout, "Moved %s after %s\n", service, target);
880 fprintf(stderr, "Error %s: %s\n", services->service, error);
882 g_free(services->service);
883 g_free(services->target);
889 static void move_after_append_args(DBusMessageIter *iter, void *user_data)
891 char *path = user_data;
893 dbus_message_iter_append_basic(iter,
894 DBUS_TYPE_OBJECT_PATH, &path);
897 static int cmd_service_move_after(char *args[], int num,
898 struct connman_option *options)
900 const char *iface = "net.connman.Service";
901 struct move_service *services;
909 if (check_dbus_name(args[1]) == false)
912 services = g_new(struct move_service, 1);
914 services->service = g_strdup_printf("/net/connman/service/%s", args[1]);
915 services->target = g_strdup_printf("/net/connman/service/%s", args[2]);
917 return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
918 services->service, iface, "MoveAfter",
919 move_after_return, services,
920 move_after_append_args,
924 static int config_return(DBusMessageIter *iter, int errnum,
925 const char *error, void *user_data)
927 char *service_name = user_data;
930 fprintf(stderr, "Error %s: %s\n", service_name, error);
937 struct config_append {
942 struct session_options {
946 struct connman_option *options;
949 static void config_append_ipv4(DBusMessageIter *iter,
952 struct config_append *append = user_data;
953 char **opts = append->opts;
959 while (opts[i] && ipv4[i]) {
960 __connmanctl_dbus_append_dict_entry(iter, ipv4[i],
961 DBUS_TYPE_STRING, &opts[i]);
968 static void config_append_ipv6(DBusMessageIter *iter, void *user_data)
970 struct config_append *append = user_data;
971 char **opts = append->opts;
978 if (g_strcmp0(opts[0], "auto") == 0) {
981 switch (parse_boolean(opts[1])) {
986 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
987 DBUS_TYPE_STRING, &str);
994 __connmanctl_dbus_append_dict_entry(iter, "Privacy",
995 DBUS_TYPE_STRING, &str);
1002 if (g_strcmp0(opts[1], "prefered") != 0 &&
1004 "preferred") != 0) {
1005 fprintf(stderr, "Error %s: %s\n",
1012 __connmanctl_dbus_append_dict_entry(iter,
1013 "Privacy", DBUS_TYPE_STRING,
1018 } else if (g_strcmp0(opts[0], "manual") == 0) {
1021 while (opts[i] && ipv6[i]) {
1023 int value = atoi(opts[i]);
1024 __connmanctl_dbus_append_dict_entry(iter,
1025 ipv6[i], DBUS_TYPE_BYTE,
1028 __connmanctl_dbus_append_dict_entry(iter,
1029 ipv6[i], DBUS_TYPE_STRING,
1037 } else if (g_strcmp0(opts[0], "off") != 0) {
1038 fprintf(stderr, "Error %s: %s\n", opts[0], strerror(EINVAL));
1043 __connmanctl_dbus_append_dict_entry(iter, "Method", DBUS_TYPE_STRING,
1047 static void config_append_str(DBusMessageIter *iter, void *user_data)
1049 struct config_append *append = user_data;
1050 char **opts = append->opts;
1057 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1065 static void append_servers(DBusMessageIter *iter, void *user_data)
1067 struct config_append *append = user_data;
1068 char **opts = append->opts;
1074 while (opts[i] && g_strcmp0(opts[i], "--excludes") != 0) {
1075 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1083 static void append_excludes(DBusMessageIter *iter, void *user_data)
1085 struct config_append *append = user_data;
1086 char **opts = append->opts;
1087 int i = append->values;
1089 if (!opts || !opts[i] ||
1090 g_strcmp0(opts[i], "--excludes") != 0)
1095 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1103 static void config_append_proxy(DBusMessageIter *iter, void *user_data)
1105 struct config_append *append = user_data;
1106 char **opts = append->opts;
1111 if (g_strcmp0(opts[0], "manual") == 0) {
1112 __connmanctl_dbus_append_dict_string_array(iter, "Servers",
1113 append_servers, append);
1115 __connmanctl_dbus_append_dict_string_array(iter, "Excludes",
1116 append_excludes, append);
1118 } else if (g_strcmp0(opts[0], "auto") == 0) {
1120 __connmanctl_dbus_append_dict_entry(iter, "URL",
1121 DBUS_TYPE_STRING, &opts[1]);
1125 } else if (g_strcmp0(opts[0], "direct") != 0)
1128 __connmanctl_dbus_append_dict_entry(iter, "Method",DBUS_TYPE_STRING,
1134 static int cmd_config(char *args[], int num, struct connman_option *options)
1136 int result = 0, res = 0, index = 2, oldindex = 0;
1138 char *service_name, *path;
1141 struct config_append append;
1143 service_name = args[1];
1147 if (check_dbus_name(service_name) == false)
1150 while (index < num && args[index]) {
1151 c = parse_args(args[index], options);
1152 opt_start = &args[index + 1];
1153 append.opts = opt_start;
1159 path = g_strdup_printf("/net/connman/service/%s", service_name);
1163 switch (parse_boolean(*opt_start)) {
1178 res = __connmanctl_dbus_set_property(connection,
1179 path, "net.connman.Service",
1181 g_strdup(service_name),
1183 DBUS_TYPE_BOOLEAN, &val);
1187 res = __connmanctl_dbus_set_property_dict(connection,
1188 path, "net.connman.Service",
1189 config_return, g_strdup(service_name),
1190 "IPv4.Configuration", DBUS_TYPE_STRING,
1191 config_append_ipv4, &append);
1192 index += append.values;
1196 res = __connmanctl_dbus_set_property_dict(connection,
1197 path, "net.connman.Service",
1198 config_return, g_strdup(service_name),
1199 "IPv6.Configuration", DBUS_TYPE_STRING,
1200 config_append_ipv6, &append);
1201 index += append.values;
1205 res = __connmanctl_dbus_set_property_array(connection,
1206 path, "net.connman.Service",
1207 config_return, g_strdup(service_name),
1208 "Nameservers.Configuration",
1209 DBUS_TYPE_STRING, config_append_str,
1211 index += append.values;
1215 res = __connmanctl_dbus_set_property_array(connection,
1216 path, "net.connman.Service",
1217 config_return, g_strdup(service_name),
1218 "Timeservers.Configuration",
1219 DBUS_TYPE_STRING, config_append_str,
1221 index += append.values;
1225 res = __connmanctl_dbus_set_property_array(connection,
1226 path, "net.connman.Service",
1227 config_return, g_strdup(service_name),
1228 "Domains.Configuration",
1229 DBUS_TYPE_STRING, config_append_str,
1231 index += append.values;
1235 res = __connmanctl_dbus_set_property_dict(connection,
1236 path, "net.connman.Service",
1237 config_return, g_strdup(service_name),
1238 "Proxy.Configuration",
1239 DBUS_TYPE_STRING, config_append_proxy,
1241 index += append.values;
1244 res = __connmanctl_dbus_method_call(connection,
1245 CONNMAN_SERVICE, path,
1246 "net.connman.Service", "Remove",
1247 config_return, g_strdup(service_name),
1252 switch (parse_boolean(*opt_start)) {
1264 res = __connmanctl_dbus_set_property(connection,
1265 path, "net.connman.Service",
1267 g_strdup(service_name),
1268 "mDNS.Configuration",
1269 DBUS_TYPE_BOOLEAN, &val);
1282 if (res == -EINPROGRESS)
1283 result = -EINPROGRESS;
1285 printf("Error '%s': %s\n", args[oldindex],
1296 static DBusHandlerResult monitor_changed(DBusConnection *connection,
1297 DBusMessage *message, void *user_data)
1299 DBusMessageIter iter;
1300 const char *interface, *path;
1302 interface = dbus_message_get_interface(message);
1304 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1306 if (strncmp(interface, "net.connman.", 12) != 0)
1307 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1309 if (!strcmp(interface, "net.connman.Agent") ||
1310 !strcmp(interface, "net.connman.vpn.Agent") ||
1311 !strcmp(interface, "net.connman.Session") ||
1312 !strcmp(interface, "net.connman.Notification"))
1313 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1315 interface = strrchr(interface, '.');
1316 if (interface && *interface != '\0')
1319 path = strrchr(dbus_message_get_path(message), '/');
1320 if (path && *path != '\0')
1323 __connmanctl_save_rl();
1325 if (dbus_message_is_signal(message, "net.connman.Manager",
1326 "ServicesChanged")) {
1328 fprintf(stdout, "%-12s %-20s = {\n", interface,
1330 dbus_message_iter_init(message, &iter);
1331 __connmanctl_services_list(&iter);
1332 fprintf(stdout, "\n}\n");
1334 __connmanctl_redraw_rl();
1336 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1337 } else if (dbus_message_is_signal(message, "net.connman.Manager",
1339 fprintf(stdout, "%-12s %-20s = {\n", interface,
1341 dbus_message_iter_init(message, &iter);
1342 __connmanctl_peers_list(&iter);
1343 fprintf(stdout, "\n}\n");
1345 __connmanctl_redraw_rl();
1347 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1348 } else if (dbus_message_is_signal(message, "net.connman.vpn.Manager",
1349 "ConnectionAdded") ||
1350 dbus_message_is_signal(message,
1351 "net.connman.vpn.Manager",
1352 "ConnectionRemoved")) {
1353 interface = "vpn.Manager";
1354 path = dbus_message_get_member(message);
1356 } else if (dbus_message_is_signal(message, "net.connman.Manager",
1357 "TechnologyAdded") ||
1358 dbus_message_is_signal(message, "net.connman.Manager",
1359 "TechnologyRemoved"))
1360 path = dbus_message_get_member(message);
1362 fprintf(stdout, "%-12s %-20s ", interface, path);
1363 dbus_message_iter_init(message, &iter);
1365 __connmanctl_dbus_print(&iter, "", " = ", " = ");
1366 fprintf(stdout, "\n");
1368 __connmanctl_redraw_rl();
1370 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1377 { "Service", false },
1378 { "Technology", false },
1379 { "Manager", false },
1380 { "vpn.Manager", false },
1381 { "vpn.Connection", false },
1385 static void monitor_add(char *interface)
1387 bool add_filter = true, found = false;
1392 for (i = 0; monitor[i].interface; i++) {
1393 if (monitor[i].enabled == true)
1396 if (g_strcmp0(interface, monitor[i].interface) == 0) {
1397 if (monitor[i].enabled == true)
1400 monitor[i].enabled = true;
1408 if (add_filter == true)
1409 dbus_connection_add_filter(connection, monitor_changed,
1412 dbus_error_init(&err);
1413 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
1415 dbus_bus_add_match(connection, rule, &err);
1418 if (dbus_error_is_set(&err))
1419 fprintf(stderr, "Error: %s\n", err.message);
1422 static void monitor_del(char *interface)
1424 bool del_filter = true, found = false;
1429 for (i = 0; monitor[i].interface; i++) {
1430 if (g_strcmp0(interface, monitor[i].interface) == 0) {
1431 if (monitor[i].enabled == false)
1434 monitor[i].enabled = false;
1438 if (monitor[i].enabled == true)
1445 rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
1447 dbus_bus_remove_match(connection, rule, NULL);
1450 if (del_filter == true)
1451 dbus_connection_remove_filter(connection, monitor_changed,
1455 static int cmd_monitor(char *args[], int num, struct connman_option *options)
1464 switch (parse_boolean(args[2])) {
1474 c = parse_args(args[1], options);
1477 monitor_add("Service");
1478 monitor_add("Technology");
1479 monitor_add("Manager");
1480 monitor_add("vpn.Manager");
1481 monitor_add("vpn.Connection");
1486 monitor_add("Service");
1488 monitor_del("Service");
1493 monitor_add("Technology");
1495 monitor_del("Technology");
1500 monitor_add("Manager");
1502 monitor_del("Manager");
1507 monitor_add("vpn.Manager");
1509 monitor_del("vpn.Manager");
1514 monitor_add("vpn.Connection");
1516 monitor_del("vpn.Connection");
1520 switch(parse_boolean(args[1])) {
1522 monitor_del("Service");
1523 monitor_del("Technology");
1524 monitor_del("Manager");
1525 monitor_del("vpn.Manager");
1526 monitor_del("vpn.Connection");
1530 monitor_add("Service");
1531 monitor_add("Technology");
1532 monitor_add("Manager");
1533 monitor_add("vpn.Manager");
1534 monitor_add("vpn.Connection");
1543 return -EINPROGRESS;
1548 static int cmd_agent(char *args[], int num, struct connman_option *options)
1550 if (!__connmanctl_is_interactive()) {
1551 fprintf(stderr, "Error: Not supported in non-interactive "
1562 switch(parse_boolean(args[1])) {
1564 __connmanctl_agent_unregister(connection);
1568 if (__connmanctl_agent_register(connection) == -EINPROGRESS)
1569 return -EINPROGRESS;
1581 static int vpnconnections_properties(DBusMessageIter *iter, int errnum,
1582 const char *error, void *user_data)
1584 char *path = user_data;
1586 DBusMessageIter dict;
1589 fprintf(stdout, "%s\n", path);
1591 dbus_message_iter_recurse(iter, &dict);
1592 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
1594 fprintf(stdout, "\n");
1597 str = strrchr(path, '/');
1603 fprintf(stderr, "Error %s: %s\n", str, error);
1611 static int vpnconnections_list(DBusMessageIter *iter, int errnum,
1612 const char *error, void *user_data)
1615 __connmanctl_vpnconnections_list(iter);
1617 fprintf(stderr, "Error: %s\n", error);
1622 static int cmd_vpnconnections(char *args[], int num,
1623 struct connman_option *options)
1625 char *vpnconnection_name, *path;
1630 vpnconnection_name = args[1];
1632 if (!vpnconnection_name)
1633 return __connmanctl_dbus_method_call(connection,
1634 VPN_SERVICE, VPN_PATH,
1635 "net.connman.vpn.Manager", "GetConnections",
1636 vpnconnections_list, NULL,
1639 if (check_dbus_name(vpnconnection_name) == false)
1642 path = g_strdup_printf("/net/connman/vpn/connection/%s",
1643 vpnconnection_name);
1644 return __connmanctl_dbus_method_call(connection, VPN_SERVICE, path,
1645 "net.connman.vpn.Connection", "GetProperties",
1646 vpnconnections_properties, path, NULL, NULL);
1650 static int cmd_vpnagent(char *args[], int num, struct connman_option *options)
1652 if (!__connmanctl_is_interactive()) {
1653 fprintf(stderr, "Error: Not supported in non-interactive "
1664 switch(parse_boolean(args[1])) {
1666 __connmanctl_vpn_agent_unregister(connection);
1670 if (__connmanctl_vpn_agent_register(connection) ==
1672 return -EINPROGRESS;
1684 static DBusMessage *session_release(DBusConnection *connection,
1685 DBusMessage *message, void *user_data)
1687 __connmanctl_save_rl();
1689 fprintf(stdout, "Session %s released\n", session_path);
1691 __connmanctl_redraw_rl();
1693 g_free(session_path);
1694 session_path = NULL;
1695 session_connected = false;
1697 return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
1700 static DBusMessage *session_update(DBusConnection *connection,
1701 DBusMessage *message, void *user_data)
1703 DBusMessageIter iter, dict;
1705 __connmanctl_save_rl();
1707 fprintf(stdout, "Session Update = {\n");
1709 dbus_message_iter_init(message, &iter);
1710 dbus_message_iter_recurse(&iter, &dict);
1712 __connmanctl_dbus_print(&dict, "", " = ", "\n");
1713 fprintf(stdout, "\n}\n");
1715 dbus_message_iter_recurse(&iter, &dict);
1717 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
1718 DBusMessageIter entry, variant;
1719 char *field, *state;
1721 dbus_message_iter_recurse(&dict, &entry);
1723 dbus_message_iter_get_basic(&entry, &field);
1725 if (dbus_message_iter_get_arg_type(&entry)
1727 && !strcmp(field, "State")) {
1729 dbus_message_iter_next(&entry);
1730 dbus_message_iter_recurse(&entry, &variant);
1731 if (dbus_message_iter_get_arg_type(&variant)
1732 != DBUS_TYPE_STRING)
1735 dbus_message_iter_get_basic(&variant, &state);
1737 if (!session_connected && (!strcmp(state, "connected")
1738 || !strcmp(state, "online"))) {
1740 fprintf(stdout, "Session %s connected\n",
1742 session_connected = true;
1747 if (!strcmp(state, "disconnected") &&
1748 session_connected) {
1750 fprintf(stdout, "Session %s disconnected\n",
1752 session_connected = false;
1757 dbus_message_iter_next(&dict);
1760 __connmanctl_redraw_rl();
1762 return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
1765 static const GDBusMethodTable notification_methods[] = {
1766 { GDBUS_METHOD("Release", NULL, NULL, session_release) },
1767 { GDBUS_METHOD("Update", GDBUS_ARGS({"settings", "a{sv}"}),
1768 NULL, session_update) },
1772 static int session_notify_add(const char *path)
1774 if (session_notify_path)
1777 if (!g_dbus_register_interface(connection, path,
1778 "net.connman.Notification",
1779 notification_methods, NULL, NULL,
1781 fprintf(stderr, "Error: Failed to register VPN Agent "
1786 session_notify_path = g_strdup(path);
1791 static void session_notify_remove(void)
1793 if (!session_notify_path)
1796 g_dbus_unregister_interface(connection, session_notify_path,
1797 "net.connman.Notification");
1799 g_free(session_notify_path);
1800 session_notify_path = NULL;
1803 static int session_connect_cb(DBusMessageIter *iter, int errnum,
1804 const char *error, void *user_data)
1807 fprintf(stderr, "Error: %s\n", error);
1811 return -EINPROGRESS;
1815 static int session_connect(void)
1817 return __connmanctl_dbus_method_call(connection, "net.connman",
1818 session_path, "net.connman.Session", "Connect",
1819 session_connect_cb, NULL, NULL, NULL);
1822 static int session_disconnect_cb(DBusMessageIter *iter, int errnum,
1823 const char *error, void *user_data)
1826 fprintf(stderr, "Error: %s\n", error);
1831 static int session_disconnect(void)
1833 return __connmanctl_dbus_method_call(connection, "net.connman",
1834 session_path, "net.connman.Session", "Disconnect",
1835 session_disconnect_cb, NULL, NULL, NULL);
1838 static int session_create_cb(DBusMessageIter *iter, int errnum,
1839 const char *error, void *user_data)
1841 gboolean connect = GPOINTER_TO_INT(user_data);
1845 fprintf(stderr, "Error creating session: %s", error);
1846 session_notify_remove();
1850 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH) {
1851 fprintf(stderr, "Error creating session: No session path\n");
1855 g_free(session_path);
1857 dbus_message_iter_get_basic(iter, &str);
1858 session_path = g_strdup(str);
1860 fprintf(stdout, "Session %s created\n", session_path);
1863 return session_connect();
1865 return -EINPROGRESS;
1868 static void session_config_append_array(DBusMessageIter *iter,
1871 struct config_append *append = user_data;
1872 char **opts = append->opts;
1878 while (opts[i] && strncmp(opts[i], "--", 2) != 0) {
1879 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
1887 static void session_create_append_dict(DBusMessageIter *iter, void *user_data)
1889 struct session_options *args_struct = user_data;
1890 int index = 0, res = 0;
1891 struct config_append append;
1894 dbus_bool_t source_ip_rule;
1896 while (index < args_struct->num && args_struct->args[index]) {
1897 append.opts = &args_struct->args[index];
1900 c = parse_args(args_struct->args[index], args_struct->options);
1904 __connmanctl_dbus_append_dict_string_array(iter, "AllowedBearers",
1905 session_config_append_array,
1909 if (! args_struct->args[index + 1]) {
1913 __connmanctl_dbus_append_dict_entry(iter, "ConnectionType",
1915 &args_struct->args[index + 1]);
1919 if (index + 1 < args_struct->num)
1920 ifname = args_struct->args[index + 1];
1923 __connmanctl_dbus_append_dict_entry(iter, "AllowedInterface",
1929 if (! args_struct->args[index + 1]) {
1933 switch (parse_boolean( args_struct->args[index + 1])) {
1935 source_ip_rule = TRUE;
1938 source_ip_rule = FALSE;
1944 __connmanctl_dbus_append_dict_entry(iter, "SourceIPRule",
1950 if (!args_struct->args[index + 1]) {
1954 __connmanctl_dbus_append_dict_entry(iter, "ContextIdentifier",
1956 &args_struct->args[index + 1]);
1963 if (res < 0 && res != -EINPROGRESS) {
1964 printf("Error '%s': %s\n", args_struct->args[index],
1969 index += append.values;
1973 static void session_create_append(DBusMessageIter *iter, void *user_data)
1975 struct session_options *args_struct = user_data;
1977 __connmanctl_dbus_append_dict(iter, session_create_append_dict,
1980 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
1981 &args_struct->notify_path);
1984 static int session_create(gboolean connect, char *args[], int num,
1985 struct connman_option *options)
1989 struct session_options args_struct;
1990 args_struct.args = args;
1991 args_struct.num = num;
1992 args_struct.options = options;
1994 notify_path = g_strdup_printf("/net/connman/connmanctl%d", getpid());
1995 session_notify_add(notify_path);
1996 args_struct.notify_path = notify_path;
1998 res = __connmanctl_dbus_method_call(connection, "net.connman", "/",
1999 "net.connman.Manager", "CreateSession",
2000 session_create_cb, GINT_TO_POINTER(connect),
2001 session_create_append, &args_struct);
2003 g_free(notify_path);
2005 if (res < 0 && res != -EINPROGRESS)
2006 session_notify_remove();
2011 static int session_destroy_cb(DBusMessageIter *iter, int errnum,
2012 const char *error, void *user_data)
2015 fprintf(stderr, "Error destroying session: %s", error);
2019 fprintf(stdout, "Session %s ended\n", session_path);
2021 g_free(session_path);
2022 session_path = NULL;
2023 session_connected = false;
2028 static void session_destroy_append(DBusMessageIter *iter, void *user_data)
2030 const char *path = user_data;
2032 dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
2035 static int session_destroy(void)
2037 return __connmanctl_dbus_method_call(connection, "net.connman", "/",
2038 "net.connman.Manager", "DestroySession",
2039 session_destroy_cb, NULL,
2040 session_destroy_append, session_path);
2043 static int session_config_return(DBusMessageIter *iter, int errnum,
2044 const char *error, void *user_data)
2046 char *property_name = user_data;
2049 fprintf(stderr, "Error setting session %s: %s\n",
2050 property_name, error);
2055 static int session_config(char *args[], int num,
2056 struct connman_option *options)
2058 int index = 0, res = 0;
2059 struct config_append append;
2062 dbus_bool_t source_ip_rule;
2064 while (index < num && args[index]) {
2065 append.opts = &args[index];
2068 c = parse_args(args[index], options);
2072 res = __connmanctl_dbus_session_change_array(connection,
2073 session_path, session_config_return,
2074 "AllowedBearers", "AllowedBearers",
2075 session_config_append_array, &append);
2078 if (!args[index + 1]) {
2083 res = __connmanctl_dbus_session_change(connection,
2084 session_path, session_config_return,
2085 "ConnectionType", "ConnectionType",
2086 DBUS_TYPE_STRING, &args[index + 1]);
2090 if (index + 1 < num)
2091 ifname = args[index + 1];
2095 res = __connmanctl_dbus_session_change(connection,
2096 session_path, session_config_return,
2097 "AllowedInterface", "AllowedInterface",
2098 DBUS_TYPE_STRING, &ifname);
2102 if (!args[index + 1]) {
2106 switch (parse_boolean(args[index + 1])) {
2108 source_ip_rule = TRUE;
2111 source_ip_rule = FALSE;
2118 res = __connmanctl_dbus_session_change(connection,
2119 session_path, session_config_return,
2120 "SourceIPRule", "SourceIPRule",
2121 DBUS_TYPE_BOOLEAN, &source_ip_rule);
2125 if (!args[index + 1]) {
2130 res = __connmanctl_dbus_session_change(connection,
2131 session_path, session_config_return,
2132 "ctxid", "ctxid", DBUS_TYPE_STRING,
2141 if (res < 0 && res != -EINPROGRESS) {
2142 printf("Error '%s': %s\n", args[index],
2147 index += append.values;
2153 static int cmd_session(char *args[], int num, struct connman_option *options)
2162 switch(parse_boolean(command)) {
2166 return session_destroy();
2171 return session_create(FALSE, &args[2], num - 2, options);
2174 if (!strcmp(command, "connect")) {
2176 return session_create(TRUE, &args[2], num - 2,
2179 return session_connect();
2181 } else if (!strcmp(command, "disconnect")) {
2183 if (!session_path) {
2184 fprintf(stdout, "Session does not exist\n");
2188 return session_disconnect();
2189 } else if (!strcmp(command, "config")) {
2190 if (!session_path) {
2191 fprintf(stdout, "Session does not exist\n");
2198 return session_config(&args[2], num - 2, options);
2206 static int cmd_exit(char *args[], int num, struct connman_option *options)
2211 static char *lookup_key_from_table(GHashTable *hash, const char *text,
2215 static GHashTableIter iter;
2216 gpointer key, value;
2219 g_hash_table_iter_init(&iter, hash);
2223 while (g_hash_table_iter_next(&iter, &key, &value))
2224 if (strncmp(text, key, len) == 0)
2230 static char *lookup_service_arg(const char *text, int state)
2232 if (__connmanctl_input_calc_level() > 1) {
2233 __connmanctl_input_lookup_end();
2237 return lookup_key_from_table(service_hash, text, state);
2240 static char *lookup_peer(const char *text, int state)
2242 static GHashTableIter iter;
2243 gpointer key, value;
2247 g_hash_table_iter_init(&iter, peer_hash);
2251 while (g_hash_table_iter_next(&iter, &key, &value)) {
2252 const char *peer = key;
2253 if (strncmp(text, peer, len) == 0)
2254 return strdup(peer);
2260 static char *lookup_peer_arg(const char *text, int state)
2262 if (__connmanctl_input_calc_level() > 1) {
2263 __connmanctl_input_lookup_end();
2267 return lookup_peer(text, state);
2270 static char *lookup_technology(const char *text, int state)
2273 static GHashTableIter iter;
2274 gpointer key, value;
2277 g_hash_table_iter_init(&iter, technology_hash);
2281 while (g_hash_table_iter_next(&iter, &key, &value)) {
2282 const char *technology = key;
2283 if (strncmp(text, technology, len) == 0)
2284 return strdup(technology);
2290 static char *lookup_technology_arg(const char *text, int state)
2292 if (__connmanctl_input_calc_level() > 1) {
2293 __connmanctl_input_lookup_end();
2297 return lookup_technology(text, state);
2300 static char *lookup_technology_offline(const char *text, int state)
2303 static bool end = false;
2306 if (__connmanctl_input_calc_level() > 1) {
2307 __connmanctl_input_lookup_end();
2319 str = lookup_technology(text, state);
2325 if (strncmp(text, "offline", len) == 0)
2326 return strdup("offline");
2331 static char *lookup_on_off(const char *text, int state)
2333 char *onoff[] = { "on", "off", NULL };
2344 while (onoff[idx]) {
2348 if (!strncmp(text, str, len))
2355 static char *lookup_tether(const char *text, int state)
2359 level = __connmanctl_input_calc_level();
2361 return lookup_technology(text, state);
2364 return lookup_on_off(text, state);
2366 __connmanctl_input_lookup_end();
2371 static char *lookup_agent(const char *text, int state)
2373 if (__connmanctl_input_calc_level() > 1) {
2374 __connmanctl_input_lookup_end();
2378 return lookup_on_off(text, state);
2381 static char *lookup_vpnconnection_arg(const char *text, int state)
2383 if (__connmanctl_input_calc_level() > 1) {
2384 __connmanctl_input_lookup_end();
2388 return lookup_key_from_table(vpnconnection_hash, text, state);
2391 static struct connman_option service_options[] = {
2392 {"properties", 'p', "[<service>] (obsolete)"},
2396 static struct connman_option config_options[] = {
2397 {"nameservers", 'n', "<dns1> [<dns2>] [<dns3>]"},
2398 {"timeservers", 't', "<ntp1> [<ntp2>] [...]"},
2399 {"domains", 'd', "<domain1> [<domain2>] [...]"},
2400 {"mdns", 'm', "yes|no"},
2401 {"ipv6", 'v', "off|auto [enable|disable|preferred]|\n"
2402 "\t\t\tmanual <address> <prefixlength> <gateway>"},
2403 {"proxy", 'x', "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
2404 "\t\t\t[exclude <exclude1> [<exclude2>] [...]]"},
2405 {"autoconnect", 'a', "yes|no"},
2406 {"ipv4", 'i', "off|dhcp|manual <address> <netmask> <gateway>"},
2407 {"remove", 'r', " Remove service"},
2411 static struct connman_option monitor_options[] = {
2412 {"services", 's', "[off] Monitor only services"},
2413 {"tech", 'c', "[off] Monitor only technologies"},
2414 {"manager", 'm', "[off] Monitor only manager interface"},
2415 {"vpnmanager", 'M', "[off] Monitor only VPN manager "
2417 {"vpnconnection", 'C', "[off] Monitor only VPN "
2422 static struct connman_option session_options[] = {
2423 {"bearers", 'b', "<technology1> [<technology2> [...]]"},
2424 {"type", 't', "local|internet|any"},
2425 {"ifname", 'i', "[<interface_name>]"},
2426 {"srciprule", 's', "yes|no"},
2427 {"ctxid", 'c', "<context_identifier>"},
2431 static char *lookup_options(struct connman_option *options, const char *text,
2443 while (options[idx].name) {
2444 str = options[idx].name;
2447 if (str && strncmp(text, str, len) == 0)
2454 static char *lookup_monitor(const char *text, int state)
2458 level = __connmanctl_input_calc_level();
2461 return lookup_options(monitor_options, text, state);
2464 return lookup_on_off(text, state);
2466 __connmanctl_input_lookup_end();
2470 static char *lookup_config(const char *text, int state)
2472 if (__connmanctl_input_calc_level() < 2)
2473 return lookup_key_from_table(service_hash, text, state);
2475 return lookup_options(config_options, text, state);
2478 static char *lookup_session(const char *text, int state)
2480 return lookup_options(session_options, text, state);
2483 static int peer_service_cb(DBusMessageIter *iter, int errnum,
2484 const char *error, void *user_data)
2486 bool registration = GPOINTER_TO_INT(user_data);
2489 fprintf(stderr, "Error %s peer service: %s\n",
2490 registration ? "registering" : "unregistering", error);
2492 fprintf(stdout, "Peer service %s\n",
2493 registration ? "registered" : "unregistered");
2498 struct _peer_service {
2499 unsigned char *bjr_query;
2501 unsigned char *bjr_response;
2502 int bjr_response_len;
2503 unsigned char *wfd_ies;
2510 static void append_dict_entry_fixed_array(DBusMessageIter *iter,
2511 const char *property, void *value, int length)
2513 DBusMessageIter dict_entry, variant, array;
2515 dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY,
2517 dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING,
2519 dbus_message_iter_open_container(&dict_entry, DBUS_TYPE_VARIANT,
2520 DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
2522 dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
2523 DBUS_TYPE_BYTE_AS_STRING, &array);
2524 dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
2526 dbus_message_iter_close_container(&variant, &array);
2527 dbus_message_iter_close_container(&dict_entry, &variant);
2528 dbus_message_iter_close_container(iter, &dict_entry);
2531 static void append_peer_service_dict(DBusMessageIter *iter, void *user_data)
2533 struct _peer_service *service = user_data;
2535 if (service->bjr_query && service->bjr_response) {
2536 append_dict_entry_fixed_array(iter, "BonjourQuery",
2537 &service->bjr_query, service->bjr_query_len);
2538 append_dict_entry_fixed_array(iter, "BonjourResponse",
2539 &service->bjr_response, service->bjr_response_len);
2540 } else if (service->upnp_service && service->version) {
2541 __connmanctl_dbus_append_dict_entry(iter, "UpnpVersion",
2542 DBUS_TYPE_INT32, &service->version);
2543 __connmanctl_dbus_append_dict_entry(iter, "UpnpService",
2544 DBUS_TYPE_STRING, &service->upnp_service);
2545 } else if (service->wfd_ies) {
2546 append_dict_entry_fixed_array(iter, "WiFiDisplayIEs",
2547 &service->wfd_ies, service->wfd_ies_len);
2551 static void peer_service_append(DBusMessageIter *iter, void *user_data)
2553 struct _peer_service *service = user_data;
2556 __connmanctl_dbus_append_dict(iter, append_peer_service_dict, service);
2558 if (service->master < 0)
2561 master = service->master == 1 ? TRUE : FALSE;
2562 dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &master);
2565 static struct _peer_service *fill_in_peer_service(unsigned char *bjr_query,
2566 int bjr_query_len, unsigned char *bjr_response,
2567 int bjr_response_len, char *upnp_service,
2568 int version, unsigned char *wfd_ies,
2571 struct _peer_service *service;
2573 service = dbus_malloc0(sizeof(*service));
2575 if (bjr_query_len && bjr_response_len) {
2576 service->bjr_query = dbus_malloc0(bjr_query_len);
2577 memcpy(service->bjr_query, bjr_query, bjr_query_len);
2578 service->bjr_query_len = bjr_query_len;
2580 service->bjr_response = dbus_malloc0(bjr_response_len);
2581 memcpy(service->bjr_response, bjr_response, bjr_response_len);
2582 service->bjr_response_len = bjr_response_len;
2583 } else if (upnp_service && version) {
2584 service->upnp_service = strdup(upnp_service);
2585 service->version = version;
2586 } else if (wfd_ies && wfd_ies_len) {
2587 service->wfd_ies = dbus_malloc0(wfd_ies_len);
2588 memcpy(service->wfd_ies, wfd_ies, wfd_ies_len);
2589 service->wfd_ies_len = wfd_ies_len;
2598 static void free_peer_service(struct _peer_service *service)
2600 dbus_free(service->bjr_query);
2601 dbus_free(service->bjr_response);
2602 dbus_free(service->wfd_ies);
2603 free(service->upnp_service);
2607 static int peer_service_register(unsigned char *bjr_query, int bjr_query_len,
2608 unsigned char *bjr_response, int bjr_response_len,
2609 char *upnp_service, int version,
2610 unsigned char *wfd_ies, int wfd_ies_len, int master)
2612 struct _peer_service *service;
2613 bool registration = true;
2616 service = fill_in_peer_service(bjr_query, bjr_query_len, bjr_response,
2617 bjr_response_len, upnp_service, version,
2618 wfd_ies, wfd_ies_len);
2622 service->master = master;
2624 ret = __connmanctl_dbus_method_call(connection, "net.connman", "/",
2625 "net.connman.Manager", "RegisterPeerService",
2626 peer_service_cb, GINT_TO_POINTER(registration),
2627 peer_service_append, service);
2629 free_peer_service(service);
2634 static int peer_service_unregister(unsigned char *bjr_query, int bjr_query_len,
2635 unsigned char *bjr_response, int bjr_response_len,
2636 char *upnp_service, int version,
2637 unsigned char *wfd_ies, int wfd_ies_len)
2639 struct _peer_service *service;
2640 bool registration = false;
2643 service = fill_in_peer_service(bjr_query, bjr_query_len, bjr_response,
2644 bjr_response_len, upnp_service, version,
2645 wfd_ies, wfd_ies_len);
2649 service->master = -1;
2651 ret = __connmanctl_dbus_method_call(connection, "net.connman", "/",
2652 "net.connman.Manager", "UnregisterPeerService",
2653 peer_service_cb, GINT_TO_POINTER(registration),
2654 peer_service_append, service);
2656 free_peer_service(service);
2661 static int parse_spec_array(char *command, unsigned char spec[1024])
2663 int length, pos, end;
2667 end = strlen(command);
2668 for (e = NULL, length = pos = 0; command[pos] != '\0'; length++) {
2672 b[0] = command[pos];
2673 b[1] = command[pos+1];
2675 spec[length] = strtol(b, &e, 16);
2676 if (e && *e != '\0')
2685 static int cmd_peer_service(char *args[], int num,
2686 struct connman_option *options)
2688 unsigned char bjr_query[1024] = {};
2689 unsigned char bjr_response[1024] = {};
2690 unsigned char wfd_ies[1024] = {};
2691 char *upnp_service = NULL;
2692 int bjr_query_len = 0, bjr_response_len = 0;
2693 int version = 0, master = 0, wfd_ies_len = 0;
2699 if (!strcmp(args[2], "wfd_ies")) {
2700 wfd_ies_len = parse_spec_array(args[3], wfd_ies);
2701 if (wfd_ies_len == -EINVAL)
2711 if (!strcmp(args[2], "bjr_query")) {
2712 if (strcmp(args[4], "bjr_response"))
2714 bjr_query_len = parse_spec_array(args[3], bjr_query);
2715 bjr_response_len = parse_spec_array(args[5], bjr_response);
2717 if (bjr_query_len == -EINVAL || bjr_response_len == -EINVAL)
2719 } else if (!strcmp(args[2], "upnp_service")) {
2722 if (strcmp(args[4], "upnp_version"))
2724 upnp_service = args[3];
2725 version = strtol(args[5], &e, 10);
2732 master = parse_boolean(args[6]);
2737 if (!strcmp(args[1], "register")) {
2738 return peer_service_register(bjr_query, bjr_query_len,
2739 bjr_response, bjr_response_len, upnp_service,
2740 version, wfd_ies, wfd_ies_len, master);
2741 } else if (!strcmp(args[1], "unregister")) {
2742 return peer_service_unregister(bjr_query, bjr_query_len,
2743 bjr_response, bjr_response_len, upnp_service,
2744 version, wfd_ies, wfd_ies_len);
2750 static const struct {
2752 const char *argument;
2753 struct connman_option *options;
2754 int (*func) (char *args[], int num, struct connman_option *options);
2756 __connmanctl_lookup_cb cb;
2758 { "state", NULL, NULL, cmd_state,
2759 "Shows if the system is online or offline", NULL },
2760 { "technologies", NULL, NULL, cmd_technologies,
2761 "Display technologies", NULL },
2762 { "clock", NULL, NULL, cmd_clock,
2763 "Get System Clock Properties", NULL },
2764 { "enable", "<technology>|offline", NULL, cmd_enable,
2765 "Enables given technology or offline mode",
2766 lookup_technology_offline },
2767 { "disable", "<technology>|offline", NULL, cmd_disable,
2768 "Disables given technology or offline mode",
2769 lookup_technology_offline },
2770 { "tether", "<technology> on|off\n"
2771 " wifi [on|off] <ssid> <passphrase> ",
2773 "Enable, disable tethering, set SSID and passphrase for wifi",
2775 { "tethering_clients", NULL, NULL, cmd_tethering_clients,
2776 "Display tethering clients", NULL },
2777 { "services", "[<service>]", service_options, cmd_services,
2778 "Display services", lookup_service_arg },
2779 { "peers", "[peer]", NULL, cmd_peers,
2780 "Display peers", lookup_peer_arg },
2781 { "scan", "<technology>", NULL, cmd_scan,
2782 "Scans for new services for given technology",
2783 lookup_technology_arg },
2784 { "connect", "<service/peer>", NULL, cmd_connect,
2785 "Connect a given service or peer", lookup_service_arg },
2786 { "disconnect", "<service/peer>", NULL, cmd_disconnect,
2787 "Disconnect a given service or peer", lookup_service_arg },
2788 { "move-before", "<service> <target service> ", NULL,
2789 cmd_service_move_before, "Move <service> before <target service>",
2790 lookup_service_arg },
2791 { "move-after", "<service> <target service> ", NULL,
2792 cmd_service_move_after, "Move <service> after <target service>",
2793 lookup_service_arg },
2794 { "config", "<service>", config_options, cmd_config,
2795 "Set service configuration options", lookup_config },
2796 { "monitor", "[off]", monitor_options, cmd_monitor,
2797 "Monitor signals from interfaces", lookup_monitor },
2798 { "agent", "on|off", NULL, cmd_agent,
2799 "Agent mode", lookup_agent },
2800 { "vpnconnections", "[<connection>]", NULL, cmd_vpnconnections,
2801 "Display VPN connections", lookup_vpnconnection_arg },
2802 { "vpnagent", "on|off", NULL, cmd_vpnagent,
2803 "VPN Agent mode", lookup_agent },
2804 { "session", "on|off|connect|disconnect|config", session_options,
2805 cmd_session, "Enable or disable a session", lookup_session },
2806 { "peer_service", "register|unregister <specs> <master>\n"
2807 "Where specs are:\n"
2808 "\tbjr_query <query> bjr_response <response>\n"
2809 "\tupnp_service <service> upnp_version <version>\n"
2810 "\twfd_ies <ies>\n", NULL,
2811 cmd_peer_service, "(Un)Register a Peer Service", NULL },
2812 { "help", NULL, NULL, cmd_help,
2813 "Show help", NULL },
2814 { "exit", NULL, NULL, cmd_exit,
2816 { "quit", NULL, NULL, cmd_exit,
2821 static int cmd_help(char *args[], int num, struct connman_option *options)
2823 bool interactive = __connmanctl_is_interactive();
2826 if (interactive == false)
2827 fprintf(stdout, "Usage: connmanctl [[command] [args]]\n");
2829 for (i = 0; cmd_table[i].cmd; i++) {
2830 const char *cmd = cmd_table[i].cmd;
2831 const char *argument = cmd_table[i].argument;
2832 const char *desc = cmd_table[i].desc;
2834 printf("%-16s%-22s%s\n", cmd? cmd: "",
2835 argument? argument: "",
2838 if (cmd_table[i].options) {
2839 for (j = 0; cmd_table[i].options[j].name;
2841 const char *options_desc =
2842 cmd_table[i].options[j].desc ?
2843 cmd_table[i].options[j].desc: "";
2845 printf(" --%-16s%s\n",
2846 cmd_table[i].options[j].name,
2852 if (interactive == false)
2853 fprintf(stdout, "\nNote: arguments and output are considered "
2854 "EXPERIMENTAL for now.\n");
2859 __connmanctl_lookup_cb __connmanctl_get_lookup_func(const char *text)
2861 int i, cmdlen, textlen;
2866 textlen = strlen(text);
2868 for (i = 0; cmd_table[i].cmd; i++) {
2869 cmdlen = strlen(cmd_table[i].cmd);
2871 if (textlen > cmdlen && text[cmdlen] != ' ')
2874 if (strncmp(cmd_table[i].cmd, text, cmdlen) == 0)
2875 return cmd_table[i].cb;
2881 int __connmanctl_commands(DBusConnection *dbus_conn, char *argv[], int argc)
2885 connection = dbus_conn;
2887 for (i = 0; cmd_table[i].cmd; i++) {
2888 if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
2889 cmd_table[i].func) {
2890 result = cmd_table[i].func(argv, argc,
2891 cmd_table[i].options);
2892 if (result < 0 && result != -EINPROGRESS)
2893 fprintf(stderr, "Error '%s': %s\n", argv[0],
2899 fprintf(stderr, "Error '%s': Unknown command\n", argv[0]);
2903 char *__connmanctl_lookup_command(const char *text, int state)
2913 while (cmd_table[i].cmd) {
2914 const char *command = cmd_table[i].cmd;
2918 if (strncmp(text, command, len) == 0)
2919 return strdup(command);
2925 static char *get_path(char *full_path)
2929 path = strrchr(full_path, '/');
2930 if (path && *path != '\0')
2938 static void add_service_id(const char *path)
2940 g_hash_table_replace(service_hash, g_strdup(path),
2941 GINT_TO_POINTER(TRUE));
2944 static void remove_service_id(const char *path)
2946 g_hash_table_remove(service_hash, path);
2949 static void services_added(DBusMessageIter *iter)
2951 DBusMessageIter array;
2954 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
2956 dbus_message_iter_recurse(iter, &array);
2957 if (dbus_message_iter_get_arg_type(&array) !=
2958 DBUS_TYPE_OBJECT_PATH)
2961 dbus_message_iter_get_basic(&array, &path);
2962 add_service_id(get_path(path));
2964 dbus_message_iter_next(iter);
2968 static void update_services(DBusMessageIter *iter)
2970 DBusMessageIter array;
2973 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2976 dbus_message_iter_recurse(iter, &array);
2977 services_added(&array);
2979 dbus_message_iter_next(iter);
2980 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
2983 dbus_message_iter_recurse(iter, &array);
2984 while (dbus_message_iter_get_arg_type(&array) ==
2985 DBUS_TYPE_OBJECT_PATH) {
2986 dbus_message_iter_get_basic(&array, &path);
2987 remove_service_id(get_path(path));
2989 dbus_message_iter_next(&array);
2993 static int populate_service_hash(DBusMessageIter *iter, int errnum,
2994 const char *error, void *user_data)
2997 fprintf(stderr, "Error getting services: %s", error);
3001 update_services(iter);
3005 static void add_vpnconnection_id(const char *path)
3007 g_hash_table_replace(vpnconnection_hash, g_strdup(path),
3008 GINT_TO_POINTER(TRUE));
3011 static void remove_vpnconnection_id(const char *path)
3013 g_hash_table_remove(vpnconnection_hash, path);
3016 static void vpnconnection_added(DBusMessageIter *iter)
3020 dbus_message_iter_get_basic(iter, &path);
3021 add_vpnconnection_id(get_path(path));
3024 static void vpnconnection_removed(DBusMessageIter *iter)
3028 dbus_message_iter_get_basic(iter, &path);
3029 remove_vpnconnection_id(get_path(path));
3032 static void add_vpnconnections(DBusMessageIter *iter)
3034 DBusMessageIter array;
3037 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
3039 dbus_message_iter_recurse(iter, &array);
3040 if (dbus_message_iter_get_arg_type(&array) !=
3041 DBUS_TYPE_OBJECT_PATH)
3044 dbus_message_iter_get_basic(&array, &path);
3045 add_vpnconnection_id(get_path(path));
3047 dbus_message_iter_next(iter);
3051 static int populate_vpnconnection_hash(DBusMessageIter *iter, int errnum,
3052 const char *error, void *user_data)
3054 DBusMessageIter array;
3057 fprintf(stderr, "Error getting VPN connections: %s", error);
3061 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
3064 dbus_message_iter_recurse(iter, &array);
3066 add_vpnconnections(&array);
3071 static void add_peer_id(const char *path)
3073 g_hash_table_replace(peer_hash, g_strdup(path), GINT_TO_POINTER(TRUE));
3076 static void remove_peer_id(const char *path)
3078 g_hash_table_remove(peer_hash, path);
3081 static void peers_added(DBusMessageIter *iter)
3083 DBusMessageIter array;
3086 while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
3088 dbus_message_iter_recurse(iter, &array);
3089 if (dbus_message_iter_get_arg_type(&array) !=
3090 DBUS_TYPE_OBJECT_PATH)
3093 dbus_message_iter_get_basic(&array, &path);
3094 add_peer_id(get_path(path));
3096 dbus_message_iter_next(iter);
3100 static void update_peers(DBusMessageIter *iter)
3102 DBusMessageIter array;
3105 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
3108 dbus_message_iter_recurse(iter, &array);
3109 peers_added(&array);
3111 dbus_message_iter_next(iter);
3112 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
3115 dbus_message_iter_recurse(iter, &array);
3116 while (dbus_message_iter_get_arg_type(&array) ==
3117 DBUS_TYPE_OBJECT_PATH) {
3118 dbus_message_iter_get_basic(&array, &path);
3119 remove_peer_id(get_path(path));
3121 dbus_message_iter_next(&array);
3125 static int populate_peer_hash(DBusMessageIter *iter, int errnum,
3126 const char *error, void *user_data)
3129 fprintf(stderr, "Error getting peers: %s", error);
3137 static void add_technology_id(const char *path)
3139 g_hash_table_replace(technology_hash, g_strdup(path),
3140 GINT_TO_POINTER(TRUE));
3143 static void remove_technology_id(const char *path)
3145 g_hash_table_remove(technology_hash, path);
3148 static void remove_technology(DBusMessageIter *iter)
3152 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
3155 dbus_message_iter_get_basic(iter, &path);
3156 remove_technology_id(get_path(path));
3159 static void add_technology(DBusMessageIter *iter)
3163 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
3166 dbus_message_iter_get_basic(iter, &path);
3167 add_technology_id(get_path(path));
3170 static void update_technologies(DBusMessageIter *iter)
3172 DBusMessageIter array;
3174 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
3177 dbus_message_iter_recurse(iter, &array);
3179 while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
3180 DBusMessageIter object_path;
3182 dbus_message_iter_recurse(&array, &object_path);
3184 add_technology(&object_path);
3186 dbus_message_iter_next(&array);
3190 static int populate_technology_hash(DBusMessageIter *iter, int errnum,
3191 const char *error, void *user_data)
3194 fprintf(stderr, "Error getting technologies: %s\n", error);
3198 update_technologies(iter);
3203 static DBusHandlerResult monitor_completions_changed(
3204 DBusConnection *connection,
3205 DBusMessage *message, void *user_data)
3207 bool *enabled = user_data;
3208 DBusMessageIter iter;
3209 DBusHandlerResult handled;
3212 handled = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3214 handled = DBUS_HANDLER_RESULT_HANDLED;
3216 if (dbus_message_is_signal(message, "net.connman.Manager",
3217 "ServicesChanged")) {
3218 dbus_message_iter_init(message, &iter);
3219 update_services(&iter);
3223 if (dbus_message_is_signal(message, "net.connman.vpn.Manager",
3224 "ConnectionAdded")) {
3225 dbus_message_iter_init(message, &iter);
3226 vpnconnection_added(&iter);
3230 if (dbus_message_is_signal(message, "net.connman.vpn.Manager",
3231 "ConnectionRemoved")) {
3232 dbus_message_iter_init(message, &iter);
3233 vpnconnection_removed(&iter);
3237 if (dbus_message_is_signal(message, "net.connman.Manager",
3239 dbus_message_iter_init(message, &iter);
3240 update_peers(&iter);
3244 if (dbus_message_is_signal(message, "net.connman.Manager",
3245 "TechnologyAdded")) {
3246 dbus_message_iter_init(message, &iter);
3247 add_technology(&iter);
3251 if (dbus_message_is_signal(message, "net.connman.Manager",
3252 "TechnologyRemoved")) {
3253 dbus_message_iter_init(message, &iter);
3254 remove_technology(&iter);
3258 if (!g_strcmp0(dbus_message_get_interface(message),
3259 "net.connman.Manager"))
3262 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
3265 void __connmanctl_monitor_completions(DBusConnection *dbus_conn)
3267 bool *manager_enabled = NULL;
3271 for (i = 0; monitor[i].interface; i++) {
3272 if (!strcmp(monitor[i].interface, "Manager")) {
3273 manager_enabled = &monitor[i].enabled;
3279 g_hash_table_destroy(service_hash);
3280 g_hash_table_destroy(vpnconnection_hash);
3281 g_hash_table_destroy(technology_hash);
3283 dbus_bus_remove_match(connection,
3284 "type='signal',interface='net.connman.Manager'", NULL);
3285 dbus_bus_remove_match(connection,
3286 "type='signal',interface='net.connman.vpn.Manager'",
3288 dbus_connection_remove_filter(connection,
3289 monitor_completions_changed,
3294 connection = dbus_conn;
3296 service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
3299 vpnconnection_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
3302 peer_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
3305 technology_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
3308 __connmanctl_dbus_method_call(connection,
3309 CONNMAN_SERVICE, CONNMAN_PATH,
3310 "net.connman.Manager", "GetServices",
3311 populate_service_hash, NULL, NULL, NULL);
3313 __connmanctl_dbus_method_call(connection,
3314 VPN_SERVICE, CONNMAN_PATH,
3315 "net.connman.vpn.Manager", "GetConnections",
3316 populate_vpnconnection_hash, NULL, NULL, NULL);
3318 __connmanctl_dbus_method_call(connection,
3319 CONNMAN_SERVICE, CONNMAN_PATH,
3320 "net.connman.Manager", "GetPeers",
3321 populate_peer_hash, NULL, NULL, NULL);
3323 __connmanctl_dbus_method_call(connection,
3324 CONNMAN_SERVICE, CONNMAN_PATH,
3325 "net.connman.Manager", "GetTechnologies",
3326 populate_technology_hash, NULL, NULL, NULL);
3328 dbus_connection_add_filter(connection,
3329 monitor_completions_changed, manager_enabled,
3332 dbus_error_init(&err);
3333 dbus_bus_add_match(connection,
3334 "type='signal',interface='net.connman.Manager'", &err);
3336 if (dbus_error_is_set(&err)) {
3337 fprintf(stderr, "Error: %s\n", err.message);
3341 dbus_bus_add_match(connection,
3342 "type='signal',interface='net.connman.vpn.Manager'",
3345 if (dbus_error_is_set(&err))
3346 fprintf(stderr, "Error: %s\n", err.message);