+ if (error)
+ fprintf(stderr, "Error %s: %s\n", method, error);
+ else
+ fprintf(stderr, "Success %s\n", method);
+
+ g_free(method);
+
+ return 0;
+}
+
+static void mesh_interface_add_append(DBusMessageIter *iter, void *user_data)
+{
+ struct mesh_if_prop *append = user_data;
+
+ /* Append Virtual Interface Name */
+ __connmanctl_dbus_append_dict_entry(iter, "Ifname",
+ DBUS_TYPE_STRING, &append->ifname);
+
+ /* Append Parent WiFi Interface Name */
+ __connmanctl_dbus_append_dict_entry(iter, "ParentIfname",
+ DBUS_TYPE_STRING, &append->parent_ifname);
+
+ /* Append Bridge Interface Name */
+ if (append->bridge_ifname)
+ __connmanctl_dbus_append_dict_entry(iter, "BridgeIfname",
+ DBUS_TYPE_STRING, &append->bridge_ifname);
+}
+
+static void mesh_interface_remove_append(DBusMessageIter *iter, void *user_data)
+{
+ struct mesh_if_prop *append = user_data;
+
+ /* Append Virtual Interface Name */
+ __connmanctl_dbus_append_dict_entry(iter, "Ifname",
+ DBUS_TYPE_STRING, &append->ifname);
+}
+
+static void mesh_create_network_append(DBusMessageIter *iter, void *user_data)
+{
+ struct mesh_create_network *append = user_data;
+
+ /* Append Mesh Network Name */
+ __connmanctl_dbus_append_dict_entry(iter, "Name",
+ DBUS_TYPE_STRING, &append->name);
+
+ /* Append Mesh Network Frequency */
+ __connmanctl_dbus_append_dict_entry(iter, "Frequency",
+ DBUS_TYPE_UINT16, &append->freq);
+
+ /* Append Mesh Network Security Type */
+ __connmanctl_dbus_append_dict_entry(iter, "Security",
+ DBUS_TYPE_STRING, &append->sec_type);
+}
+
+static void mesh_specific_scan_append(DBusMessageIter *iter, void *user_data)
+{
+ struct mesh_specific_scan_params *append = user_data;
+
+ /* Append Mesh Network Name */
+ __connmanctl_dbus_append_dict_entry(iter, "Name",
+ DBUS_TYPE_STRING, &append->name);
+
+ /* Append Mesh Network Frequency */
+ __connmanctl_dbus_append_dict_entry(iter, "Frequency",
+ DBUS_TYPE_UINT16, &append->freq);
+}
+
+static void mesh_set_gate_append(DBusMessageIter *iter, void *user_data)
+{
+ struct mesh_gate_params *append = user_data;
+
+ /* Append Gate Announce Protocol */
+ __connmanctl_dbus_append_dict_entry(iter, "GateAnnounce",
+ DBUS_TYPE_BOOLEAN, &append->gate_announce);
+
+ /* Append HWMP Root Mode */
+ __connmanctl_dbus_append_dict_entry(iter, "HWMPRootMode",
+ DBUS_TYPE_UINT16, &append->hwmp_rootmode);
+
+ /* Append STP */
+ __connmanctl_dbus_append_dict_entry(iter, "STP", DBUS_TYPE_UINT16,
+ &append->stp);
+}
+
+static void mesh_peer_append(DBusMessageIter *iter, void *user_data)
+{
+ char *peer_addr = user_data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &peer_addr);
+
+ g_free(peer_addr);
+}
+
+static int mesh_peers_list(DBusMessageIter *iter,
+ const char *error, void *user_data)
+{
+ if (!error) {
+ __connmanctl_mesh_peers_list(iter);
+ fprintf(stdout, "\n");
+ } else
+ fprintf(stderr, "Error: %s\n", error);
+
+ return 0;
+}
+
+static int connected_mesh_peers_list(DBusMessageIter *iter,
+ const char *error, void *user_data)
+{
+ if (!error) {
+ __connmanctl_mesh_connected_peers_list(iter);
+ fprintf(stdout, "\n");
+ } else
+ fprintf(stderr, "Error: %s\n", error);
+
+ return 0;
+}
+
+static int disconnected_mesh_peers_list(DBusMessageIter *iter,
+ const char *error, void *user_data)
+{
+ if (!error) {
+ __connmanctl_mesh_disconnected_peers_list(iter);
+ fprintf(stdout, "\n");
+ } else
+ fprintf(stderr, "Error: %s\n", error);
+
+ return 0;
+}
+
+static int mesh_connect_return(DBusMessageIter *iter, const char *error,
+ void *user_data)
+{
+ char *path = user_data;
+
+ if (!error) {
+ char *str = strrchr(path, '/');
+ str++;
+ fprintf(stdout, "Connected %s\n", str);
+ } else
+ fprintf(stderr, "Error %s: %s\n", path, error);
+
+ g_free(user_data);
+
+ return 0;
+}
+
+static int mesh_disconnect_return(DBusMessageIter *iter, const char *error,
+ void *user_data)
+{
+ char *path = user_data;
+
+ if (!error) {
+ char *str = strrchr(path, '/');
+ str++;
+ fprintf(stdout, "Disconnected %s\n", str);
+ } else
+ fprintf(stderr, "Error %s: %s\n", path, error);
+
+ g_free(user_data);
+
+ return 0;
+}
+
+static int mesh_remove_return(DBusMessageIter *iter, const char *error,
+ void *user_data)
+{
+ char *path = user_data;
+
+ if (!error) {
+ char *str = strrchr(path, '/');
+ str++;
+ fprintf(stdout, "Removed %s\n", str);
+ } else
+ fprintf(stderr, "Error %s: %s\n", path, error);
+
+ g_free(user_data);
+
+ return 0;
+}
+
+static int mesh_config_return(DBusMessageIter *iter, const char *error,
+ void *user_data)
+{
+ char *path = user_data;
+ char *str = strrchr(path, '/');
+ str++;
+
+ if (error)
+ fprintf(stderr, "Error %s: %s\n", path, error);
+ else
+ fprintf(stdout, "Success SetProperty %s\n", str);
+
+ g_free(user_data);
+
+ return 0;
+}
+
+static int cmd_mesh(char *args[], int num, struct connman_option *options)
+{
+ int result = 0;
+ int c;
+ char *path = NULL;
+ char *method = NULL;
+ char *mesh_peer_name = NULL;
+ char *mesh_peer_path = NULL;
+ char *property = NULL;
+ char *value = NULL;
+ struct mesh_if_prop *append;
+ struct mesh_create_network *network;
+ struct mesh_specific_scan_params *scan_params;
+ struct mesh_gate_params *gate_params;
+ char *mesh_peer_addr = NULL;
+
+ c = parse_args(args[1], options);
+
+ switch (c) {
+ case 'a':
+ if (num < 4 || num > 5) {
+ result = -EINVAL;
+ break;
+ }
+ path = g_strdup_printf("/net/connman/technology/mesh");
+
+ append = dbus_malloc0(sizeof(struct mesh_if_prop));
+ append->ifname = g_strdup(args[2]);
+ append->parent_ifname = g_strdup(args[3]);
+ if (num == 5)
+ append->bridge_ifname = g_strdup(args[4]);
+ method = g_strdup("MeshInterfaceAdd");
+ result = __connmanctl_dbus_mesh_dict(connection, path,
+ "net.connman.Technology", mesh_return, method,
+ "MeshInterfaceAdd", DBUS_TYPE_STRING,
+ mesh_interface_add_append, append);
+ g_free(append->ifname);
+ g_free(append->parent_ifname);
+ g_free(append->bridge_ifname);
+ g_free(append);
+ break;
+
+ case 'r':
+ if (num != 3) {
+ result = -EINVAL;
+ break;
+ }
+ path = g_strdup_printf("/net/connman/technology/mesh");
+
+ append = dbus_malloc0(sizeof(struct mesh_if_prop));
+ append->ifname = g_strdup(args[2]);
+ method = g_strdup("MeshInterfaceRemove");
+ result = __connmanctl_dbus_mesh_dict(connection, path,
+ "net.connman.Technology", mesh_return, method,
+ "MeshInterfaceRemove", DBUS_TYPE_STRING,
+ mesh_interface_remove_append, append);
+ g_free(append->ifname);
+ g_free(append);
+ break;
+
+ case 'p':
+ if (num > 3) {
+ result = -E2BIG;
+ break;
+ }
+
+ if (num == 3)
+ mesh_peer_name = args[2];
+
+ if (!mesh_peer_name) {
+ result = __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager", "GetMeshPeers",
+ mesh_peers_list, NULL, NULL, NULL);
+ break;
+ }
+
+ if (check_dbus_name(mesh_peer_name) == false) {
+ result = -EINVAL;
+ break;
+ }
+
+ mesh_peer_path = g_strdup_printf("/net/connman/mesh/%s",
+ mesh_peer_name);
+ result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+ mesh_peer_path, "net.connman.Mesh", "GetProperties",
+ object_properties, mesh_peer_path, NULL, NULL);
+ break;
+
+ case 'c':
+ if (num < 3) {
+ result = -EINVAL;
+ break;
+ }
+
+ if (num > 3) {
+ result = -E2BIG;
+ break;
+ }
+
+ mesh_peer_name = args[2];
+
+ if (check_dbus_name(mesh_peer_name) == false) {
+ result = -EINVAL;
+ break;
+ }
+
+ mesh_peer_path = g_strdup_printf("/net/connman/mesh/%s",
+ mesh_peer_name);
+ result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+ mesh_peer_path, "net.connman.Mesh", "Connect",
+ mesh_connect_return, mesh_peer_path, NULL, NULL);
+ break;
+
+ case 'd':
+ if (num < 3) {
+ result = -EINVAL;
+ break;
+ }
+
+ if (num > 3) {
+ result = -E2BIG;
+ break;
+ }
+
+ mesh_peer_name = args[2];
+
+ if (check_dbus_name(mesh_peer_name) == false) {
+ result = -EINVAL;
+ break;
+ }
+
+ mesh_peer_path = g_strdup_printf("/net/connman/mesh/%s",
+ mesh_peer_name);
+ result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+ mesh_peer_path, "net.connman.Mesh", "Disconnect",
+ mesh_disconnect_return, mesh_peer_path, NULL, NULL);
+ break;
+
+ case 'f':
+ if (num < 3) {
+ result = -EINVAL;
+ break;
+ }
+
+ if (num > 3) {
+ result = -E2BIG;
+ break;
+ }
+
+ mesh_peer_name = args[2];
+
+ if (check_dbus_name(mesh_peer_name) == false) {
+ result = -EINVAL;
+ break;
+ }
+
+ mesh_peer_path = g_strdup_printf("/net/connman/mesh/%s",
+ mesh_peer_name);
+ result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+ mesh_peer_path, "net.connman.Mesh", "Remove",
+ mesh_remove_return, mesh_peer_path, NULL, NULL);
+ break;
+
+ case 'C':
+ if (num > 2) {
+ result = -E2BIG;
+ break;
+ }
+
+ result = __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager", "GetConnectedMeshPeers",
+ connected_mesh_peers_list, NULL, NULL, NULL);
+ break;
+
+ case 'D':
+ if (num > 2) {
+ result = -E2BIG;
+ break;
+ }
+
+ result = __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager",
+ "GetDisconnectedMeshPeers",
+ disconnected_mesh_peers_list, NULL, NULL, NULL);
+ break;
+
+ case 'n':
+ if (num != 5) {
+ result = -EINVAL;
+ break;
+ }
+ path = g_strdup_printf("/net/connman/technology/mesh");
+
+ network = dbus_malloc0(sizeof(struct mesh_create_network));
+ network->name = g_strdup(args[2]);
+ network->freq = atoi(args[3]);
+ network->sec_type = g_strdup(args[4]);
+ method = g_strdup("MeshCreateNetwork");
+ result = __connmanctl_dbus_mesh_dict(connection, path,
+ "net.connman.Technology", mesh_return, method,
+ "MeshCreateNetwork", DBUS_TYPE_STRING,
+ mesh_create_network_append, network);
+ g_free(network->name);
+ g_free(network->sec_type);
+ g_free(network);
+ break;
+
+ case 'A':
+ if (num != 2) {
+ result = -EINVAL;
+ break;
+ }
+ path = g_strdup_printf("/net/connman/technology/mesh");
+
+ method = g_strdup("AbortScan");
+ result = __connmanctl_dbus_mesh_dict(connection, path,
+ "net.connman.Technology", mesh_return, method,
+ "AbortScan", DBUS_TYPE_STRING,
+ NULL, NULL);
+ break;
+
+ case 'S':
+ if (num != 4) {
+ result = -EINVAL;
+ break;
+ }
+ path = g_strdup_printf("/net/connman/technology/mesh");
+
+ scan_params = dbus_malloc0(sizeof(struct mesh_specific_scan_params));
+ scan_params->name = g_strdup(args[2]);
+ scan_params->freq = atoi(args[3]);
+ method = g_strdup("MeshSpecificScan");
+ result = __connmanctl_dbus_mesh_dict(connection, path,
+ "net.connman.Technology", mesh_return, method,
+ "MeshSpecificScan", DBUS_TYPE_STRING,
+ mesh_specific_scan_append, scan_params);
+ g_free(scan_params->name);
+ g_free(scan_params);
+ break;
+
+ case 'P':
+ if (num != 5) {
+ result = -EINVAL;
+ break;
+ }
+
+ mesh_peer_name = args[2];
+ property = args[3];
+ value = args[4];
+
+ if (check_dbus_name(mesh_peer_name) == false) {
+ result = -EINVAL;
+ break;
+ }
+
+ mesh_peer_path = g_strdup_printf("/net/connman/mesh/%s",
+ mesh_peer_name);
+
+ if (g_strcmp0(property, "Passphrase") == 0) {
+ result = __connmanctl_dbus_set_property(connection,
+ mesh_peer_path, "net.connman.Mesh",
+ mesh_config_return, mesh_peer_path, property,
+ DBUS_TYPE_STRING, &value);
+ } else {
+ printf("Invalid property %s\n", property);
+ result = -EINVAL;
+ }
+
+ break;
+
+ case 'G':
+ if (num != 5) {
+ result = -EINVAL;
+ break;
+ }
+
+ path = g_strdup_printf("/net/connman/technology/mesh");
+
+ gate_params = dbus_malloc0(sizeof(struct mesh_gate_params));
+ gate_params->gate_announce = atoi(args[2]);
+ gate_params->hwmp_rootmode = atoi(args[3]);
+ gate_params->stp = atoi(args[4]);
+
+ method = g_strdup("SetMeshGate");
+
+ result = __connmanctl_dbus_mesh_dict(connection, path,
+ "net.connman.Technology", mesh_return, method,
+ "SetMeshGate", DBUS_TYPE_STRING,
+ mesh_set_gate_append, gate_params);
+
+ break;
+
+ case 'z':
+ if (num != 3) {
+ result = -EINVAL;
+ break;
+ }
+
+ mesh_peer_addr = g_strdup(args[2]);
+ method = g_strdup("MeshAddPeer");
+
+ result = __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager", "MeshAddPeer",
+ mesh_return, method, mesh_peer_append,
+ mesh_peer_addr);
+
+ break;
+
+ case 'y':
+ if (num != 3) {
+ result = -EINVAL;
+ break;
+ }
+
+ mesh_peer_addr = g_strdup(args[2]);
+ method = g_strdup("MeshRemovePeer");
+
+ result = __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager", "MeshRemovePeer",
+ mesh_return, method, mesh_peer_append,
+ mesh_peer_addr);
+
+ break;
+
+ default:
+ result = -EINVAL;
+ break;
+ }
+
+ g_free(path);
+
+ if (result < 0) {
+ if (result != -EINPROGRESS)
+ printf("Error '%s': %s\n", args[1], strerror(-result));
+ }
+
+
+ return result;
+}
+#endif
+
+static int cmd_tether(char *args[], int num, struct connman_option *options)
+{
+ char *ssid, *passphrase;
+ int set_tethering;
+
+ if (num < 3)
+ return -EINVAL;
+
+ passphrase = args[num - 1];
+ ssid = args[num - 2];
+
+ set_tethering = parse_boolean(args[2]);
+
+ if (strcmp(args[1], "wifi") == 0) {
+
+ if (num > 5)
+ return -E2BIG;
+
+ if (num == 5 && set_tethering == -1)
+ return -EINVAL;
+
+ if (num == 4)
+ set_tethering = -1;
+
+ if (num > 3)
+ return tether_set_ssid(ssid, passphrase, set_tethering);
+ }
+
+ if (num > 3)
+ return -E2BIG;
+
+ if (set_tethering == -1)
+ return -EINVAL;
+
+ if (check_dbus_name(args[1]) == false)
+ return -EINVAL;
+
+ return tether_set(args[1], set_tethering);
+}
+
+static int cmd_tethering_clients(char *args[], int num, struct connman_option *options)
+{
+ if (num > 1)
+ return -E2BIG;
+
+ return __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager", "GetTetheringClients",
+ tethering_clients_list, NULL, NULL, NULL);
+}
+
+static int scan_return(DBusMessageIter *iter, int ernnum, const char *error,
+ void *user_data)
+{
+ char *path = user_data;
+
+ if (!error) {
+ char *str = strrchr(path, '/');
+ str++;
+ fprintf(stdout, "Scan completed for %s\n", str);
+ } else
+ fprintf(stderr, "Error %s: %s\n", path, error);
+
+ g_free(user_data);
+
+ return 0;
+}
+
+static int cmd_scan(char *args[], int num, struct connman_option *options)
+{
+ char *path;
+
+ if (num > 2)
+ return -E2BIG;
+
+ if (num < 2)
+ return -EINVAL;
+
+ if (check_dbus_name(args[1]) == false)
+ return -EINVAL;
+
+ path = g_strdup_printf("/net/connman/technology/%s", args[1]);
+ return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
+ "net.connman.Technology", "Scan",
+ scan_return, path, NULL, NULL);
+}
+
+static int connect_return(DBusMessageIter *iter, int errnum,
+ const char *error, void *user_data)
+{
+ char *path = user_data;
+
+ if (!error) {
+ char *str = strrchr(path, '/');
+ str++;
+ fprintf(stdout, "Connected %s\n", str);
+ } else
+ fprintf(stderr, "Error %s: %s\n", path, error);
+
+ g_free(user_data);
+
+ return 0;
+}
+
+static int cmd_connect(char *args[], int num, struct connman_option *options)
+{
+ const char *iface = "net.connman.Service";
+ char *path;
+
+ if (num > 2)
+ return -E2BIG;
+
+ if (num < 2)
+ return -EINVAL;
+
+ if (check_dbus_name(args[1]) == false)
+ return -EINVAL;
+
+ if (g_strstr_len(args[1], 5, "peer_") == args[1]) {
+ iface = "net.connman.Peer";
+ path = g_strdup_printf("/net/connman/peer/%s", args[1]);
+ } else
+ path = g_strdup_printf("/net/connman/service/%s", args[1]);
+
+ return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
+ iface, "Connect", connect_return, path, NULL, NULL);
+}
+
+static int disconnect_return(DBusMessageIter *iter, int errnum,
+ const char *error, void *user_data)
+{
+ char *path = user_data;
+
+ if (!error) {
+ char *str = strrchr(path, '/');
+ str++;
+ fprintf(stdout, "Disconnected %s\n", str);
+ } else
+ fprintf(stderr, "Error %s: %s\n", path, error);
+
+ g_free(user_data);
+
+ return 0;
+}
+
+static int cmd_disconnect(char *args[], int num, struct connman_option *options)
+{
+ const char *iface = "net.connman.Service";
+ char *path;
+
+ if (num > 2)
+ return -E2BIG;
+
+ if (num < 2)
+ return -EINVAL;
+
+ if (check_dbus_name(args[1]) == false)
+ return -EINVAL;
+
+ if (g_strstr_len(args[1], 5, "peer_") == args[1]) {
+ iface = "net.connman.Peer";
+ path = g_strdup_printf("/net/connman/peer/%s", args[1]);
+ } else
+ path = g_strdup_printf("/net/connman/service/%s", args[1]);
+
+ return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+ path, iface, "Disconnect",
+ disconnect_return, path, NULL, NULL);
+}
+
+struct move_service {
+ char *service;
+ char *target;
+};
+
+static int move_before_return(DBusMessageIter *iter, int errnum,
+ const char *error, void *user_data)
+{
+ struct move_service *services = user_data;
+ char *service;
+ char *target;
+
+ if (!error) {
+ service = strrchr(services->service, '/');
+ service++;
+ target = strrchr(services->target, '/');
+ target++;
+ fprintf(stdout, "Moved %s before %s\n", service, target);
+ } else
+ fprintf(stderr, "Error %s: %s\n", services->service, error);
+
+ g_free(services->service);
+ g_free(services->target);
+ g_free(user_data);
+
+ return 0;
+}
+
+static void move_before_append_args(DBusMessageIter *iter, void *user_data)
+{
+ char *path = user_data;
+
+ dbus_message_iter_append_basic(iter,
+ DBUS_TYPE_OBJECT_PATH, &path);
+}
+
+static int cmd_service_move_before(char *args[], int num,
+ struct connman_option *options)
+{
+ const char *iface = "net.connman.Service";
+ struct move_service *services;
+
+ if (num > 3)
+ return -E2BIG;
+
+ if (num < 3)
+ return -EINVAL;
+
+ if (check_dbus_name(args[1]) == false)
+ return -EINVAL;
+
+ services = g_new(struct move_service, 1);
+
+ services->service = g_strdup_printf("/net/connman/service/%s", args[1]);
+ services->target = g_strdup_printf("/net/connman/service/%s", args[2]);
+
+ return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+ services->service, iface, "MoveBefore",
+ move_before_return, services,
+ move_before_append_args,
+ services->target);
+}
+
+static int move_after_return(DBusMessageIter *iter, int errnum,
+ const char *error, void *user_data)
+{
+ struct move_service *services = user_data;
+ char *service;
+ char *target;
+
+ if (!error) {
+ service = strrchr(services->service, '/');
+ service++;
+ target = strrchr(services->target, '/');
+ target++;
+ fprintf(stdout, "Moved %s after %s\n", service, target);
+ } else
+ fprintf(stderr, "Error %s: %s\n", services->service, error);
+
+ g_free(services->service);
+ g_free(services->target);
+ g_free(user_data);
+
+ return 0;
+}
+
+static void move_after_append_args(DBusMessageIter *iter, void *user_data)
+{
+ char *path = user_data;
+
+ dbus_message_iter_append_basic(iter,
+ DBUS_TYPE_OBJECT_PATH, &path);
+}
+
+static int cmd_service_move_after(char *args[], int num,
+ struct connman_option *options)
+{
+ const char *iface = "net.connman.Service";
+ struct move_service *services;
+
+ if (num > 3)
+ return -E2BIG;
+
+ if (num < 3)
+ return -EINVAL;
+
+ if (check_dbus_name(args[1]) == false)
+ return -EINVAL;
+
+ services = g_new(struct move_service, 1);
+
+ services->service = g_strdup_printf("/net/connman/service/%s", args[1]);
+ services->target = g_strdup_printf("/net/connman/service/%s", args[2]);
+
+ return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+ services->service, iface, "MoveAfter",
+ move_after_return, services,
+ move_after_append_args,
+ services->target);
+}
+
+static int config_return(DBusMessageIter *iter, int errnum,
+ const char *error, void *user_data)
+{
+ char *service_name = user_data;
+
+ if (error)
+ fprintf(stderr, "Error %s: %s\n", service_name, error);
+
+ g_free(user_data);
+
+ return 0;
+}
+
+struct config_append {
+ char **opts;
+ int values;
+};
+
+struct session_options {
+ char **args;
+ int num;
+ char *notify_path;
+ struct connman_option *options;
+};
+
+static void config_append_ipv4(DBusMessageIter *iter,
+ void *user_data)
+{
+ struct config_append *append = user_data;
+ char **opts = append->opts;
+ int i = 0;
+
+ if (!opts)
+ return;
+
+ while (opts[i] && ipv4[i]) {
+ __connmanctl_dbus_append_dict_entry(iter, ipv4[i],
+ DBUS_TYPE_STRING, &opts[i]);
+ i++;
+ }
+
+ append->values = i;
+}
+
+static void config_append_ipv6(DBusMessageIter *iter, void *user_data)
+{
+ struct config_append *append = user_data;
+ char **opts = append->opts;
+
+ if (!opts)
+ return;
+
+ append->values = 1;
+
+ if (g_strcmp0(opts[0], "auto") == 0) {
+ char *str;
+
+ switch (parse_boolean(opts[1])) {
+ case 0:
+ append->values = 2;
+
+ str = "disabled";
+ __connmanctl_dbus_append_dict_entry(iter, "Privacy",
+ DBUS_TYPE_STRING, &str);
+ break;
+
+ case 1:
+ append->values = 2;
+
+ str = "enabled";
+ __connmanctl_dbus_append_dict_entry(iter, "Privacy",
+ DBUS_TYPE_STRING, &str);
+ break;
+
+ default:
+ if (opts[1]) {
+ append->values = 2;
+
+ if (g_strcmp0(opts[1], "prefered") != 0 &&
+ g_strcmp0(opts[1],
+ "preferred") != 0) {
+ fprintf(stderr, "Error %s: %s\n",
+ opts[1],
+ strerror(EINVAL));
+ return;
+ }
+
+ str = "prefered";
+ __connmanctl_dbus_append_dict_entry(iter,
+ "Privacy", DBUS_TYPE_STRING,
+ &str);
+ }
+ break;
+ }
+ } else if (g_strcmp0(opts[0], "manual") == 0) {
+ int i = 1;
+
+ while (opts[i] && ipv6[i]) {
+ if (i == 2) {
+ int value = atoi(opts[i]);
+ __connmanctl_dbus_append_dict_entry(iter,
+ ipv6[i], DBUS_TYPE_BYTE,
+ &value);
+ } else {
+ __connmanctl_dbus_append_dict_entry(iter,
+ ipv6[i], DBUS_TYPE_STRING,
+ &opts[i]);
+ }
+ i++;
+ }
+
+ append->values = i;
+
+ } else if (g_strcmp0(opts[0], "off") != 0) {
+ fprintf(stderr, "Error %s: %s\n", opts[0], strerror(EINVAL));
+
+ return;
+ }
+
+ __connmanctl_dbus_append_dict_entry(iter, "Method", DBUS_TYPE_STRING,
+ &opts[0]);
+}
+
+static void config_append_str(DBusMessageIter *iter, void *user_data)
+{
+ struct config_append *append = user_data;
+ char **opts = append->opts;
+ int i = 0;
+
+ if (!opts)
+ return;
+
+ while (opts[i]) {
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+ &opts[i]);
+ i++;
+ }
+
+ append->values = i;
+}
+
+static void append_servers(DBusMessageIter *iter, void *user_data)
+{
+ struct config_append *append = user_data;
+ char **opts = append->opts;
+ int i = 1;
+
+ if (!opts)
+ return;
+
+ while (opts[i] && g_strcmp0(opts[i], "--excludes") != 0) {
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+ &opts[i]);
+ i++;
+ }
+
+ append->values = i;
+}
+
+static void append_excludes(DBusMessageIter *iter, void *user_data)
+{
+ struct config_append *append = user_data;
+ char **opts = append->opts;
+ int i = append->values;
+
+ if (!opts || !opts[i] ||
+ g_strcmp0(opts[i], "--excludes") != 0)
+ return;
+
+ i++;
+ while (opts[i]) {
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+ &opts[i]);
+ i++;
+ }
+
+ append->values = i;
+}
+
+static void config_append_proxy(DBusMessageIter *iter, void *user_data)
+{
+ struct config_append *append = user_data;
+ char **opts = append->opts;
+
+ if (!opts)
+ return;
+
+ if (g_strcmp0(opts[0], "manual") == 0) {
+ __connmanctl_dbus_append_dict_string_array(iter, "Servers",
+ append_servers, append);
+
+ __connmanctl_dbus_append_dict_string_array(iter, "Excludes",
+ append_excludes, append);
+
+ } else if (g_strcmp0(opts[0], "auto") == 0) {
+ if (opts[1]) {
+ __connmanctl_dbus_append_dict_entry(iter, "URL",
+ DBUS_TYPE_STRING, &opts[1]);
+ append->values++;
+ }
+
+ } else if (g_strcmp0(opts[0], "direct") != 0)
+ return;
+
+ __connmanctl_dbus_append_dict_entry(iter, "Method",DBUS_TYPE_STRING,
+ &opts[0]);
+
+ append->values++;
+}
+
+static int cmd_config(char *args[], int num, struct connman_option *options)
+{
+ int result = 0, res = 0, index = 2, oldindex = 0;
+ int c;
+ char *service_name, *path;
+ char **opt_start;
+ dbus_bool_t val;
+ struct config_append append;
+
+ service_name = args[1];
+ if (!service_name)
+ return -EINVAL;
+
+ if (check_dbus_name(service_name) == false)
+ return -EINVAL;
+
+ while (index < num && args[index]) {
+ c = parse_args(args[index], options);
+ opt_start = &args[index + 1];
+ append.opts = opt_start;
+ append.values = 0;
+
+ res = 0;
+
+ oldindex = index;
+ path = g_strdup_printf("/net/connman/service/%s", service_name);
+
+ switch (c) {
+ case 'a':
+ switch (parse_boolean(*opt_start)) {
+ case 1:
+ val = TRUE;
+ break;
+ case 0:
+ val = FALSE;
+ break;
+ default:
+ res = -EINVAL;
+ break;
+ }
+
+ index++;
+
+ if (res == 0) {
+ res = __connmanctl_dbus_set_property(connection,
+ path, "net.connman.Service",
+ config_return,
+ g_strdup(service_name),
+ "AutoConnect",
+ DBUS_TYPE_BOOLEAN, &val);
+ }
+ break;
+ case 'i':
+ res = __connmanctl_dbus_set_property_dict(connection,
+ path, "net.connman.Service",
+ config_return, g_strdup(service_name),
+ "IPv4.Configuration", DBUS_TYPE_STRING,
+ config_append_ipv4, &append);
+ index += append.values;
+ break;
+
+ case 'v':
+ res = __connmanctl_dbus_set_property_dict(connection,
+ path, "net.connman.Service",
+ config_return, g_strdup(service_name),
+ "IPv6.Configuration", DBUS_TYPE_STRING,
+ config_append_ipv6, &append);
+ index += append.values;
+ break;
+
+ case 'n':
+ res = __connmanctl_dbus_set_property_array(connection,
+ path, "net.connman.Service",
+ config_return, g_strdup(service_name),
+ "Nameservers.Configuration",
+ DBUS_TYPE_STRING, config_append_str,
+ &append);
+ index += append.values;
+ break;
+
+ case 't':
+ res = __connmanctl_dbus_set_property_array(connection,
+ path, "net.connman.Service",
+ config_return, g_strdup(service_name),
+ "Timeservers.Configuration",
+ DBUS_TYPE_STRING, config_append_str,
+ &append);
+ index += append.values;
+ break;
+
+ case 'd':
+ res = __connmanctl_dbus_set_property_array(connection,
+ path, "net.connman.Service",
+ config_return, g_strdup(service_name),
+ "Domains.Configuration",
+ DBUS_TYPE_STRING, config_append_str,
+ &append);
+ index += append.values;
+ break;
+
+ case 'x':
+ res = __connmanctl_dbus_set_property_dict(connection,
+ path, "net.connman.Service",
+ config_return, g_strdup(service_name),
+ "Proxy.Configuration",
+ DBUS_TYPE_STRING, config_append_proxy,
+ &append);
+ index += append.values;
+ break;
+ case 'r':
+ res = __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, path,
+ "net.connman.Service", "Remove",
+ config_return, g_strdup(service_name),
+ NULL, NULL);
+ break;
+
+ case 'm':
+ switch (parse_boolean(*opt_start)) {
+ case 1:
+ val = TRUE;
+ break;
+ case 0:
+ val = FALSE;
+ break;
+ default:
+ res = -EINVAL;
+ break;
+ }
+ if (res == 0) {
+ res = __connmanctl_dbus_set_property(connection,
+ path, "net.connman.Service",
+ config_return,
+ g_strdup(service_name),
+ "mDNS.Configuration",
+ DBUS_TYPE_BOOLEAN, &val);
+ }
+ index++;
+ break;
+
+ default:
+ res = -EINVAL;
+ break;
+ }
+
+ g_free(path);
+
+ if (res < 0) {
+ if (res == -EINPROGRESS)
+ result = -EINPROGRESS;
+ else
+ printf("Error '%s': %s\n", args[oldindex],
+ strerror(-res));
+ } else
+ index += res;
+
+ index++;
+ }
+
+ return result;
+}
+
+static DBusHandlerResult monitor_changed(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ DBusMessageIter iter;
+ const char *interface, *path;
+
+ interface = dbus_message_get_interface(message);
+ if (!interface)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (strncmp(interface, "net.connman.", 12) != 0)
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ if (!strcmp(interface, "net.connman.Agent") ||
+ !strcmp(interface, "net.connman.vpn.Agent") ||
+ !strcmp(interface, "net.connman.Session") ||
+ !strcmp(interface, "net.connman.Notification"))
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+
+ interface = strrchr(interface, '.');
+ if (interface && *interface != '\0')
+ interface++;
+
+ path = strrchr(dbus_message_get_path(message), '/');
+ if (path && *path != '\0')
+ path++;
+
+ __connmanctl_save_rl();
+
+ if (dbus_message_is_signal(message, "net.connman.Manager",
+ "ServicesChanged")) {
+
+ fprintf(stdout, "%-12s %-20s = {\n", interface,
+ "ServicesChanged");
+ dbus_message_iter_init(message, &iter);
+ __connmanctl_services_list(&iter);
+ fprintf(stdout, "\n}\n");
+
+ __connmanctl_redraw_rl();
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ } else if (dbus_message_is_signal(message, "net.connman.Manager",
+ "PeersChanged")) {
+ fprintf(stdout, "%-12s %-20s = {\n", interface,
+ "PeersChanged");
+ dbus_message_iter_init(message, &iter);
+ __connmanctl_peers_list(&iter);
+ fprintf(stdout, "\n}\n");
+
+ __connmanctl_redraw_rl();
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ } else if (dbus_message_is_signal(message, "net.connman.vpn.Manager",
+ "ConnectionAdded") ||
+ dbus_message_is_signal(message,
+ "net.connman.vpn.Manager",
+ "ConnectionRemoved")) {
+ interface = "vpn.Manager";
+ path = dbus_message_get_member(message);
+
+ } else if (dbus_message_is_signal(message, "net.connman.Manager",
+ "TechnologyAdded") ||
+ dbus_message_is_signal(message, "net.connman.Manager",
+ "TechnologyRemoved"))
+ path = dbus_message_get_member(message);
+
+ fprintf(stdout, "%-12s %-20s ", interface, path);
+ dbus_message_iter_init(message, &iter);
+
+ __connmanctl_dbus_print(&iter, "", " = ", " = ");
+ fprintf(stdout, "\n");
+
+ __connmanctl_redraw_rl();
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static struct {
+ char *interface;
+ bool enabled;
+} monitor[] = {
+ { "Service", false },
+ { "Technology", false },
+ { "Manager", false },
+ { "vpn.Manager", false },
+ { "vpn.Connection", false },
+ { NULL, },
+};
+
+static void monitor_add(char *interface)
+{
+ bool add_filter = true, found = false;
+ int i;
+ char *rule;
+ DBusError err;
+
+ for (i = 0; monitor[i].interface; i++) {
+ if (monitor[i].enabled == true)
+ add_filter = false;
+
+ if (g_strcmp0(interface, monitor[i].interface) == 0) {
+ if (monitor[i].enabled == true)
+ return;
+
+ monitor[i].enabled = true;
+ found = true;
+ }
+ }
+
+ if (found == false)
+ return;
+
+ if (add_filter == true)
+ dbus_connection_add_filter(connection, monitor_changed,
+ NULL, NULL);
+
+ dbus_error_init(&err);
+ rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
+ interface);
+ dbus_bus_add_match(connection, rule, &err);
+ g_free(rule);
+
+ if (dbus_error_is_set(&err))
+ fprintf(stderr, "Error: %s\n", err.message);
+}
+
+static void monitor_del(char *interface)
+{
+ bool del_filter = true, found = false;
+ int i;
+ char *rule;
+
+
+ for (i = 0; monitor[i].interface; i++) {
+ if (g_strcmp0(interface, monitor[i].interface) == 0) {
+ if (monitor[i].enabled == false)
+ return;
+
+ monitor[i].enabled = false;
+ found = true;
+ }
+
+ if (monitor[i].enabled == true)
+ del_filter = false;
+ }
+
+ if (found == false)
+ return;
+
+ rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
+ interface);
+ dbus_bus_remove_match(connection, rule, NULL);
+ g_free(rule);
+
+ if (del_filter == true)
+ dbus_connection_remove_filter(connection, monitor_changed,
+ NULL);
+}
+
+static int cmd_monitor(char *args[], int num, struct connman_option *options)
+{
+ bool add = true;
+ int c;
+
+ if (num > 3)
+ return -E2BIG;
+
+ if (num == 3) {
+ switch (parse_boolean(args[2])) {
+ case 0:
+ add = false;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ c = parse_args(args[1], options);
+ switch (c) {
+ case -1:
+ monitor_add("Service");
+ monitor_add("Technology");
+ monitor_add("Manager");
+ monitor_add("vpn.Manager");
+ monitor_add("vpn.Connection");
+ break;
+
+ case 's':
+ if (add == true)
+ monitor_add("Service");
+ else
+ monitor_del("Service");
+ break;
+
+ case 'c':
+ if (add == true)
+ monitor_add("Technology");
+ else
+ monitor_del("Technology");
+ break;
+
+ case 'm':
+ if (add == true)
+ monitor_add("Manager");
+ else
+ monitor_del("Manager");
+ break;
+
+ case 'M':
+ if (add == true)
+ monitor_add("vpn.Manager");
+ else
+ monitor_del("vpn.Manager");
+ break;
+
+ case 'C':
+ if (add == true)
+ monitor_add("vpn.Connection");
+ else
+ monitor_del("vpn.Connection");
+ break;
+
+ default:
+ switch(parse_boolean(args[1])) {
+ case 0:
+ monitor_del("Service");
+ monitor_del("Technology");
+ monitor_del("Manager");
+ monitor_del("vpn.Manager");
+ monitor_del("vpn.Connection");
+ break;
+
+ case 1:
+ monitor_add("Service");
+ monitor_add("Technology");
+ monitor_add("Manager");
+ monitor_add("vpn.Manager");
+ monitor_add("vpn.Connection");
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ }
+
+ if (add == true)
+ return -EINPROGRESS;
+
+ return 0;
+}
+
+static int cmd_agent(char *args[], int num, struct connman_option *options)
+{
+ if (!__connmanctl_is_interactive()) {
+ fprintf(stderr, "Error: Not supported in non-interactive "
+ "mode\n");
+ return 0;
+ }
+
+ if (num > 2)
+ return -E2BIG;
+
+ if (num < 2)
+ return -EINVAL;
+
+ switch(parse_boolean(args[1])) {
+ case 0:
+ __connmanctl_agent_unregister(connection);
+ break;
+
+ case 1:
+ if (__connmanctl_agent_register(connection) == -EINPROGRESS)
+ return -EINPROGRESS;
+
+ break;
+
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+static int vpnconnections_properties(DBusMessageIter *iter, int errnum,
+ const char *error, void *user_data)
+{
+ char *path = user_data;
+ char *str;
+ DBusMessageIter dict;
+
+ if (!error) {
+ fprintf(stdout, "%s\n", path);
+
+ dbus_message_iter_recurse(iter, &dict);
+ __connmanctl_dbus_print(&dict, " ", " = ", "\n");
+
+ fprintf(stdout, "\n");
+
+ } else {
+ str = strrchr(path, '/');
+ if (str)
+ str++;
+ else
+ str = path;
+
+ fprintf(stderr, "Error %s: %s\n", str, error);
+ }
+
+ g_free(user_data);
+
+ return 0;
+}
+
+static int vpnconnections_list(DBusMessageIter *iter, int errnum,
+ const char *error, void *user_data)
+{
+ if (!error)
+ __connmanctl_vpnconnections_list(iter);
+ else
+ fprintf(stderr, "Error: %s\n", error);
+
+ return 0;
+}
+
+static int cmd_vpnconnections(char *args[], int num,
+ struct connman_option *options)
+{
+ char *vpnconnection_name, *path;
+
+ if (num > 2)
+ return -E2BIG;
+
+ vpnconnection_name = args[1];
+
+ if (!vpnconnection_name)
+ return __connmanctl_dbus_method_call(connection,
+ VPN_SERVICE, VPN_PATH,
+ "net.connman.vpn.Manager", "GetConnections",
+ vpnconnections_list, NULL,
+ NULL, NULL);
+
+ if (check_dbus_name(vpnconnection_name) == false)
+ return -EINVAL;
+
+ path = g_strdup_printf("/net/connman/vpn/connection/%s",
+ vpnconnection_name);
+ return __connmanctl_dbus_method_call(connection, VPN_SERVICE, path,
+ "net.connman.vpn.Connection", "GetProperties",
+ vpnconnections_properties, path, NULL, NULL);
+
+}
+
+static int cmd_vpnagent(char *args[], int num, struct connman_option *options)
+{
+ if (!__connmanctl_is_interactive()) {
+ fprintf(stderr, "Error: Not supported in non-interactive "
+ "mode\n");
+ return 0;
+ }
+
+ if (num > 2)
+ return -E2BIG;
+
+ if (num < 2)
+ return -EINVAL;
+
+ switch(parse_boolean(args[1])) {
+ case 0:
+ __connmanctl_vpn_agent_unregister(connection);
+ break;
+
+ case 1:
+ if (__connmanctl_vpn_agent_register(connection) ==
+ -EINPROGRESS)
+ return -EINPROGRESS;
+
+ break;
+
+ default:
+ return -EINVAL;
+ break;
+ }
+
+ return 0;
+}
+
+static DBusMessage *session_release(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ __connmanctl_save_rl();
+
+ fprintf(stdout, "Session %s released\n", session_path);
+
+ __connmanctl_redraw_rl();
+
+ g_free(session_path);
+ session_path = NULL;
+ session_connected = false;
+
+ return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
+}
+
+static DBusMessage *session_update(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ DBusMessageIter iter, dict;
+
+ __connmanctl_save_rl();
+
+ fprintf(stdout, "Session Update = {\n");
+
+ dbus_message_iter_init(message, &iter);
+ dbus_message_iter_recurse(&iter, &dict);
+
+ __connmanctl_dbus_print(&dict, "", " = ", "\n");
+ fprintf(stdout, "\n}\n");
+
+ dbus_message_iter_recurse(&iter, &dict);
+
+ while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
+ DBusMessageIter entry, variant;
+ char *field, *state;
+
+ dbus_message_iter_recurse(&dict, &entry);
+
+ dbus_message_iter_get_basic(&entry, &field);
+
+ if (dbus_message_iter_get_arg_type(&entry)
+ == DBUS_TYPE_STRING
+ && !strcmp(field, "State")) {
+
+ dbus_message_iter_next(&entry);
+ dbus_message_iter_recurse(&entry, &variant);
+ if (dbus_message_iter_get_arg_type(&variant)
+ != DBUS_TYPE_STRING)
+ break;
+
+ dbus_message_iter_get_basic(&variant, &state);
+
+ if (!session_connected && (!strcmp(state, "connected")
+ || !strcmp(state, "online"))) {
+
+ fprintf(stdout, "Session %s connected\n",
+ session_path);
+ session_connected = true;
+
+ break;
+ }
+
+ if (!strcmp(state, "disconnected") &&
+ session_connected) {
+
+ fprintf(stdout, "Session %s disconnected\n",
+ session_path);
+ session_connected = false;
+ }
+ break;
+ }
+
+ dbus_message_iter_next(&dict);
+ }
+
+ __connmanctl_redraw_rl();
+
+ return g_dbus_create_reply(message, DBUS_TYPE_INVALID);
+}
+
+static const GDBusMethodTable notification_methods[] = {
+ { GDBUS_METHOD("Release", NULL, NULL, session_release) },
+ { GDBUS_METHOD("Update", GDBUS_ARGS({"settings", "a{sv}"}),
+ NULL, session_update) },
+ { },
+};
+
+static int session_notify_add(const char *path)
+{
+ if (session_notify_path)
+ return 0;
+
+ if (!g_dbus_register_interface(connection, path,
+ "net.connman.Notification",
+ notification_methods, NULL, NULL,
+ NULL, NULL)) {
+ fprintf(stderr, "Error: Failed to register VPN Agent "
+ "callbacks\n");
+ return -EIO;
+ }
+
+ session_notify_path = g_strdup(path);
+
+ return 0;
+}
+
+static void session_notify_remove(void)
+{
+ if (!session_notify_path)
+ return;
+
+ g_dbus_unregister_interface(connection, session_notify_path,
+ "net.connman.Notification");
+
+ g_free(session_notify_path);
+ session_notify_path = NULL;
+}
+
+static int session_connect_cb(DBusMessageIter *iter, int errnum,
+ const char *error, void *user_data)
+{
+ if (error) {
+ fprintf(stderr, "Error: %s\n", error);
+ return 0;
+ }
+
+ return -EINPROGRESS;
+}
+
+
+static int session_connect(void)
+{
+ return __connmanctl_dbus_method_call(connection, "net.connman",
+ session_path, "net.connman.Session", "Connect",
+ session_connect_cb, NULL, NULL, NULL);
+}
+
+static int session_disconnect_cb(DBusMessageIter *iter, int errnum,
+ const char *error, void *user_data)
+{
+ if (error)
+ fprintf(stderr, "Error: %s\n", error);
+
+ return 0;
+}
+
+static int session_disconnect(void)
+{
+ return __connmanctl_dbus_method_call(connection, "net.connman",
+ session_path, "net.connman.Session", "Disconnect",
+ session_disconnect_cb, NULL, NULL, NULL);
+}
+
+static int session_create_cb(DBusMessageIter *iter, int errnum,
+ const char *error, void *user_data)
+{
+ gboolean connect = GPOINTER_TO_INT(user_data);
+ char *str;
+
+ if (error) {
+ fprintf(stderr, "Error creating session: %s", error);
+ session_notify_remove();
+ return 0;
+ }
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH) {
+ fprintf(stderr, "Error creating session: No session path\n");
+ return -EINVAL;
+ }
+
+ g_free(session_path);
+
+ dbus_message_iter_get_basic(iter, &str);
+ session_path = g_strdup(str);
+
+ fprintf(stdout, "Session %s created\n", session_path);
+
+ if (connect)
+ return session_connect();
+
+ return -EINPROGRESS;
+}
+
+static void session_config_append_array(DBusMessageIter *iter,
+ void *user_data)
+{
+ struct config_append *append = user_data;
+ char **opts = append->opts;
+ int i = 1;
+
+ if (!opts)
+ return;
+
+ while (opts[i] && strncmp(opts[i], "--", 2) != 0) {
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
+ &opts[i]);
+ i++;
+ }
+
+ append->values = i;
+}
+
+static void session_create_append_dict(DBusMessageIter *iter, void *user_data)
+{
+ struct session_options *args_struct = user_data;
+ int index = 0, res = 0;
+ struct config_append append;
+ char c;
+ char *ifname;
+ dbus_bool_t source_ip_rule;
+
+ while (index < args_struct->num && args_struct->args[index]) {
+ append.opts = &args_struct->args[index];
+ append.values = 0;
+
+ c = parse_args(args_struct->args[index], args_struct->options);
+
+ switch (c) {
+ case 'b':
+ __connmanctl_dbus_append_dict_string_array(iter, "AllowedBearers",
+ session_config_append_array,
+ &append);
+ break;
+ case 't':
+ if (! args_struct->args[index + 1]) {
+ res = -EINVAL;
+ break;
+ }
+ __connmanctl_dbus_append_dict_entry(iter, "ConnectionType",
+ DBUS_TYPE_STRING,
+ &args_struct->args[index + 1]);
+ append.values = 2;
+ break;
+ case 'i':
+ if (index + 1 < args_struct->num)
+ ifname = args_struct->args[index + 1];
+ else
+ ifname = "";
+ __connmanctl_dbus_append_dict_entry(iter, "AllowedInterface",
+ DBUS_TYPE_STRING,
+ &ifname);
+ append.values = 2;
+ break;
+ case 's':
+ if (! args_struct->args[index + 1]) {
+ res = -EINVAL;
+ break;
+ }
+ switch (parse_boolean( args_struct->args[index + 1])) {
+ case 1:
+ source_ip_rule = TRUE;
+ break;
+ case 0:
+ source_ip_rule = FALSE;
+ break;
+ default:
+ res = -EINVAL;
+ break;
+ }
+ __connmanctl_dbus_append_dict_entry(iter, "SourceIPRule",
+ DBUS_TYPE_BOOLEAN,
+ &source_ip_rule);
+ append.values = 2;
+ break;
+ case 'c':
+ if (!args_struct->args[index + 1]) {
+ res = -EINVAL;
+ break;
+ }
+ __connmanctl_dbus_append_dict_entry(iter, "ContextIdentifier",
+ DBUS_TYPE_STRING,
+ &args_struct->args[index + 1]);
+ append.values = 2;
+ break;
+ default:
+ res = -EINVAL;