*
* Connection Manager
*
- * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
+ * Copyright (C) 2012-2014 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#include <getopt.h>
#include <stdbool.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ctype.h>
#include <glib.h>
#include <gdbus.h>
#include "dbus_helpers.h"
#include "input.h"
#include "services.h"
+#if defined TIZEN_EXT_INS
+#include "ins.h"
+#endif
+#include "tethering.h"
+#include "peers.h"
#include "commands.h"
+#include "agent.h"
+#include "vpnconnections.h"
+#if defined TIZEN_EXT_WIFI_MESH
+#include "mesh.h"
+#endif
static DBusConnection *connection;
+static GHashTable *service_hash;
+static GHashTable *vpnconnection_hash;
+static GHashTable *peer_hash;
+static GHashTable *technology_hash;
+static char *session_notify_path;
+static char *session_path;
+static bool session_connected;
+
+struct connman_option {
+ const char *name;
+ const char val;
+ const char *desc;
+};
static char *ipv4[] = {
"Method",
NULL
};
-static int cmd_help(char *args[], int num, struct option *options);
+static int cmd_help(char *args[], int num, struct connman_option *options);
+
+static bool check_dbus_name(const char *name)
+{
+ /*
+ * Valid dbus chars should be [A-Z][a-z][0-9]_
+ * and should not start with number.
+ */
+ unsigned int i;
+
+ if (!name || name[0] == '\0')
+ return false;
+
+ for (i = 0; name[i] != '\0'; i++)
+ if (!((name[i] >= 'A' && name[i] <= 'Z') ||
+ (name[i] >= 'a' && name[i] <= 'z') ||
+ (name[i] >= '0' && name[i] <= '9') ||
+ name[i] == '_'))
+ return false;
+
+ return true;
+}
static int parse_boolean(char *arg)
{
- if (arg == NULL)
+ if (!arg)
return -1;
if (strcasecmp(arg, "no") == 0 ||
return -1;
}
-static int parse_args(char *arg, struct option *options)
+static int parse_args(char *arg, struct connman_option *options)
{
int i;
- if (arg == NULL)
+ if (!arg)
return -1;
- for (i = 0; options[i].name != NULL; i++) {
+ for (i = 0; options[i].name; i++) {
if (strcmp(options[i].name, arg) == 0 ||
(strncmp(arg, "--", 2) == 0 &&
strcmp(&arg[2], options[i].name) == 0))
return '?';
}
-static void enable_return(DBusMessageIter *iter, const char *error,
+static int enable_return(DBusMessageIter *iter, const char *error,
void *user_data)
{
char *tech = user_data;
char *str;
str = strrchr(tech, '/');
- if (str != NULL)
+ if (str)
str++;
else
str = tech;
- if (error == NULL) {
+ if (!error)
fprintf(stdout, "Enabled %s\n", str);
- } else
+ else
fprintf(stderr, "Error %s: %s\n", str, error);
g_free(user_data);
+
+ return 0;
}
-static int cmd_enable(char *args[], int num, struct option *options)
+static int cmd_enable(char *args[], int num, struct connman_option *options)
{
char *tech;
dbus_bool_t b = TRUE;
if (num < 2)
return -EINVAL;
- if (strcmp(args[1], "offlinemode") == 0) {
+ if (check_dbus_name(args[1]) == false)
+ return -EINVAL;
+
+ if (strcmp(args[1], "offline") == 0) {
tech = g_strdup(args[1]);
return __connmanctl_dbus_set_property(connection, "/",
"net.connman.Manager", enable_return, tech,
"Powered", DBUS_TYPE_BOOLEAN, &b);
}
-static void disable_return(DBusMessageIter *iter, const char *error,
+static int disable_return(DBusMessageIter *iter, const char *error,
void *user_data)
{
char *tech = user_data;
char *str;
str = strrchr(tech, '/');
- if (str != NULL)
+ if (str)
str++;
else
str = tech;
- if (error == NULL) {
+ if (!error)
fprintf(stdout, "Disabled %s\n", str);
- } else
+ else
fprintf(stderr, "Error %s: %s\n", str, error);
g_free(user_data);
+
+ return 0;
}
-static int cmd_disable(char *args[], int num, struct option *options)
+static int cmd_disable(char *args[], int num, struct connman_option *options)
{
char *tech;
dbus_bool_t b = FALSE;
if (num < 2)
return -EINVAL;
- if (strcmp(args[1], "offlinemode") == 0) {
+ if (check_dbus_name(args[1]) == false)
+ return -EINVAL;
+
+ if (strcmp(args[1], "offline") == 0) {
tech = g_strdup(args[1]);
return __connmanctl_dbus_set_property(connection, "/",
"net.connman.Manager", disable_return, tech,
"Powered", DBUS_TYPE_BOOLEAN, &b);
}
-static void state_print(DBusMessageIter *iter, const char *error,
+static int state_print(DBusMessageIter *iter, const char *error,
void *user_data)
{
DBusMessageIter entry;
- if (error != NULL) {
- fprintf(stderr, "Error: %s", error);
- return;
+ if (error) {
+ fprintf(stderr, "Error: %s\n", error);
+ return 0;
+ }
+
+ dbus_message_iter_recurse(iter, &entry);
+ __connmanctl_dbus_print(&entry, " ", " = ", "\n");
+ fprintf(stdout, "\n");
+
+ return 0;
+}
+
+static int cmd_state(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", "GetProperties",
+ state_print, NULL, NULL, NULL);
+}
+
+static int clock_print(DBusMessageIter *iter, const char *error,
+ void *user_data)
+{
+ DBusMessageIter entry;
+
+ if (error) {
+ fprintf(stderr, "Error: %s\n", error);
+ return 0;
}
dbus_message_iter_recurse(iter, &entry);
__connmanctl_dbus_print(&entry, " ", " = ", "\n");
fprintf(stdout, "\n");
+
+ return 0;
}
-static int cmd_state(char *args[], int num, struct option *options)
+static int cmd_clock(char *args[], int num, struct connman_option *options)
{
if (num > 1)
return -E2BIG;
- return __connmanctl_dbus_method_call(connection, "/",
- "net.connman.Manager", "GetProperties",
- state_print, NULL, DBUS_TYPE_INVALID);
+ return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+ CONNMAN_PATH, "net.connman.Clock", "GetProperties",
+ clock_print, NULL, NULL, NULL);
}
-static void services_list(DBusMessageIter *iter, const char *error,
+static int services_list(DBusMessageIter *iter, const char *error,
void *user_data)
{
- if (error == NULL) {
+ if (!error) {
__connmanctl_services_list(iter);
fprintf(stdout, "\n");
} else {
fprintf(stderr, "Error: %s\n", error);
}
+
+ return 0;
}
-static void services_properties(DBusMessageIter *iter, const char *error,
+#if defined TIZEN_EXT_INS
+static int ins_list(DBusMessageIter *iter, const char *error,
void *user_data)
{
+ char *filter = user_data;
+
+ if (!error) {
+ __connmanctl_ins_list(iter, filter);
+ fprintf(stdout, "\n");
+ } else {
+ fprintf(stderr, "Error: %s\n", error);
+ }
+
+ g_free(filter);
+
+ return 0;
+}
+#endif
+
+static int peers_list(DBusMessageIter *iter,
+ const char *error, void *user_data)
+{
+ if (!error) {
+ __connmanctl_peers_list(iter);
+ fprintf(stdout, "\n");
+ } else
+ fprintf(stderr, "Error: %s\n", error);
+
+ return 0;
+}
+
+static int tethering_clients_list(DBusMessageIter *iter,
+ const char *error, void *user_data)
+{
+ if (!error) {
+ __connmanctl_tethering_clients_list(iter);
+ fprintf(stdout, "\n");
+ } else
+ fprintf(stderr, "Error: %s\n", error);
+
+ return 0;
+}
+
+static int object_properties(DBusMessageIter *iter,
+ const char *error, void *user_data)
+{
char *path = user_data;
char *str;
DBusMessageIter dict;
- if (error == NULL) {
+ if (!error) {
fprintf(stdout, "%s\n", path);
dbus_message_iter_recurse(iter, &dict);
} else {
str = strrchr(path, '/');
- if (str != NULL)
+ if (str)
str++;
else
str = path;
}
g_free(user_data);
+
+ return 0;
}
-static int cmd_services(char *args[], int num, struct option *options)
+static int cmd_services(char *args[], int num, struct connman_option *options)
{
char *service_name = NULL;
char *path;
break;
}
- if (service_name == NULL) {
- return __connmanctl_dbus_method_call(connection, "/",
- "net.connman.Manager", "GetServices",
- services_list, NULL, DBUS_TYPE_INVALID);
+ if (!service_name) {
+ return __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager", "GetServices",
+ services_list, NULL, NULL, NULL);
}
+ if (check_dbus_name(service_name) == false)
+ return -EINVAL;
+
path = g_strdup_printf("/net/connman/service/%s", service_name);
- return __connmanctl_dbus_method_call(connection, path,
+ return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
"net.connman.Service", "GetProperties",
- services_properties, path, DBUS_TYPE_INVALID);
+ object_properties, path, NULL, NULL);
+}
+
+#if defined TIZEN_EXT_INS
+static int cmd_ins(char *args[], int num, struct connman_option *options)
+{
+ char *filter = NULL;
+
+ if (num > 2)
+ return -E2BIG;
+
+ if (num == 2)
+ filter = g_strdup(args[1]);
+
+ return __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager", "GetINS",
+ ins_list, filter, NULL, NULL);
+}
+#endif
+
+static int cmd_peers(char *args[], int num, struct connman_option *options)
+{
+ char *peer_name = NULL;
+ char *path;
+
+ if (num > 2)
+ return -E2BIG;
+
+ if (num == 2)
+ peer_name = args[1];
+
+ if (!peer_name) {
+ return __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager", "GetPeers",
+ peers_list, NULL, NULL, NULL);
+ }
+
+ if (check_dbus_name(peer_name) == false)
+ return -EINVAL;
+
+ path = g_strdup_printf("/net/connman/peer/%s", peer_name);
+ return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+ path, "net.connman.Peer", "GetProperties",
+ object_properties, path, NULL, NULL);
}
-static void technology_print(DBusMessageIter *iter, const char *error,
+static int technology_print(DBusMessageIter *iter, const char *error,
void *user_data)
{
DBusMessageIter array;
- if (error != NULL) {
+ if (error) {
fprintf(stderr, "Error: %s\n", error);
- return;
+ return 0;
}
dbus_message_iter_recurse(iter, &array);
dbus_message_iter_next(&array);
}
+
+ return 0;
}
-static int cmd_technologies(char *args[], int num, struct option *options)
+static int cmd_technologies(char *args[], int num,
+ struct connman_option *options)
{
if (num > 1)
return -E2BIG;
- return __connmanctl_dbus_method_call(connection, "/",
- "net.connman.Manager", "GetTechnologies",
- technology_print, NULL, DBUS_TYPE_INVALID);
+ return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
+ CONNMAN_PATH, "net.connman.Manager", "GetTechnologies",
+ technology_print, NULL, NULL, NULL);
}
struct tether_enable {
dbus_bool_t enable;
};
-static void tether_set_return(DBusMessageIter *iter, const char *error,
+static int tether_set_return(DBusMessageIter *iter, const char *error,
void *user_data)
{
struct tether_enable *tether = user_data;
char *str;
str = strrchr(tether->path, '/');
- if (str != NULL)
+ if (str)
str++;
else
str = tether->path;
- if (error == NULL) {
+ if (!error) {
fprintf(stdout, "%s tethering for %s\n",
- tether->enable == TRUE ? "Enabled": "Disabled",
+ tether->enable ? "Enabled" : "Disabled",
str);
} else
fprintf(stderr, "Error %s %s tethering: %s\n",
- tether->enable == TRUE ?
- "enabling": "disabling", str, error);
+ tether->enable ?
+ "enabling" : "disabling", str, error);
g_free(tether->path);
g_free(user_data);
+
+ return 0;
}
static int tether_set(char *technology, int set_tethering)
int set_tethering;
};
-static void tether_update(struct tether_properties *tether)
+static int tether_update(struct tether_properties *tether)
{
- printf("%d %d %d\n", tether->ssid_result, tether->passphrase_result,
- tether->set_tethering);
+ int ret;
- if (tether->ssid_result == 0 && tether->passphrase_result == 0)
- tether_set("wifi", tether->set_tethering);
+ if (tether->ssid_result == 0 && tether->passphrase_result == 0) {
+ ret = tether_set("wifi", tether->set_tethering);
+ g_free(tether);
+ return ret;
+ }
if (tether->ssid_result != -EINPROGRESS &&
- tether->passphrase_result != -EINPROGRESS)
+ tether->passphrase_result != -EINPROGRESS) {
g_free(tether);
+ return 0;
+ }
+
+ return -EINPROGRESS;
}
-static void tether_set_ssid_return(DBusMessageIter *iter, const char *error,
+static int tether_set_ssid_return(DBusMessageIter *iter, const char *error,
void *user_data)
{
struct tether_properties *tether = user_data;
- if (error == NULL) {
+ if (!error) {
fprintf(stdout, "Wifi SSID set\n");
tether->ssid_result = 0;
} else {
tether->ssid_result = -EINVAL;
}
- tether_update(tether);
+ return tether_update(tether);
}
-static void tether_set_passphrase_return(DBusMessageIter *iter,
+static int tether_set_passphrase_return(DBusMessageIter *iter,
const char *error, void *user_data)
{
struct tether_properties *tether = user_data;
- if (error == NULL) {
+ if (!error) {
fprintf(stdout, "Wifi passphrase set\n");
tether->passphrase_result = 0;
} else {
tether->passphrase_result = -EINVAL;
}
- tether_update(tether);
+ return tether_update(tether);
}
static int tether_set_ssid(char *ssid, char *passphrase, int set_tethering)
return -EINPROGRESS;
}
-static int cmd_tether(char *args[], int num, struct option *options)
+#if defined TIZEN_EXT_WIFI_MESH
+struct mesh_if_prop {
+ char *ifname;
+ char *parent_ifname;
+ char *bridge_ifname;
+};
+
+struct mesh_create_network {
+ char *name;
+ unsigned int freq;
+ char *sec_type;
+};
+
+struct mesh_specific_scan_params {
+ char *name;
+ unsigned int freq;
+};
+
+struct mesh_gate_params {
+ bool gate_announce;
+ int hwmp_rootmode;
+ int stp;
+};
+
+static int mesh_return(DBusMessageIter *iter, const char *error,
+ void *user_data)
{
- char *ssid, *passphrase;
- int set_tethering;
+ char *method = user_data;
- if (num < 3)
- return -EINVAL;
+ if (error)
+ fprintf(stderr, "Error %s: %s\n", method, error);
+ else
+ fprintf(stderr, "Success %s\n", method);
- passphrase = args[num - 1];
- ssid = args[num - 2];
+ g_free(method);
- set_tethering = parse_boolean(args[2]);
+ return 0;
+}
- if (strcmp(args[1], "wifi") == 0) {
+static void mesh_interface_add_append(DBusMessageIter *iter, void *user_data)
+{
+ struct mesh_if_prop *append = user_data;
- if (num > 5)
- return -E2BIG;
+ /* Append Virtual Interface Name */
+ __connmanctl_dbus_append_dict_entry(iter, "Ifname",
+ DBUS_TYPE_STRING, &append->ifname);
- if (num == 5 && set_tethering == -1)
- return -EINVAL;
+ /* Append Parent WiFi Interface Name */
+ __connmanctl_dbus_append_dict_entry(iter, "ParentIfname",
+ DBUS_TYPE_STRING, &append->parent_ifname);
- if (num == 4)
- set_tethering = -1;
+ /* Append Bridge Interface Name */
+ if (append->bridge_ifname)
+ __connmanctl_dbus_append_dict_entry(iter, "BridgeIfname",
+ DBUS_TYPE_STRING, &append->bridge_ifname);
+}
- if (num > 3)
- return tether_set_ssid(ssid, passphrase, set_tethering);
- }
+static void mesh_interface_remove_append(DBusMessageIter *iter, void *user_data)
+{
+ struct mesh_if_prop *append = user_data;
- if (num > 3)
- return -E2BIG;
+ /* Append Virtual Interface Name */
+ __connmanctl_dbus_append_dict_entry(iter, "Ifname",
+ DBUS_TYPE_STRING, &append->ifname);
+}
- if (set_tethering == -1)
- return -EINVAL;
+static void mesh_create_network_append(DBusMessageIter *iter, void *user_data)
+{
+ struct mesh_create_network *append = user_data;
- return tether_set(args[1], set_tethering);
+ /* 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 scan_return(DBusMessageIter *iter, const char *error,
- void *user_data)
+static void mesh_specific_scan_append(DBusMessageIter *iter, void *user_data)
{
- char *path = user_data;
+ struct mesh_specific_scan_params *append = user_data;
- if (error == NULL) {
- char *str = strrchr(path, '/');
- str++;
- fprintf(stdout, "Scan completed for %s\n", str);
- } else
- fprintf(stderr, "Error %s: %s", path, error);
+ /* Append Mesh Network Name */
+ __connmanctl_dbus_append_dict_entry(iter, "Name",
+ DBUS_TYPE_STRING, &append->name);
- g_free(user_data);
+ /* Append Mesh Network Frequency */
+ __connmanctl_dbus_append_dict_entry(iter, "Frequency",
+ DBUS_TYPE_UINT16, &append->freq);
}
-static int cmd_scan(char *args[], int num, struct option *options)
+static void mesh_set_gate_append(DBusMessageIter *iter, void *user_data)
{
- char *path;
+ struct mesh_gate_params *append = user_data;
- if (num > 2)
- return -E2BIG;
+ /* Append Gate Announce Protocol */
+ __connmanctl_dbus_append_dict_entry(iter, "GateAnnounce",
+ DBUS_TYPE_BOOLEAN, &append->gate_announce);
- if (num < 2)
- return -EINVAL;
+ /* Append HWMP Root Mode */
+ __connmanctl_dbus_append_dict_entry(iter, "HWMPRootMode",
+ DBUS_TYPE_UINT16, &append->hwmp_rootmode);
- path = g_strdup_printf("/net/connman/technology/%s", args[1]);
- return __connmanctl_dbus_method_call(connection, path,
- "net.connman.Technology", "Scan",
- scan_return, path, DBUS_TYPE_INVALID);
+ /* Append STP */
+ __connmanctl_dbus_append_dict_entry(iter, "STP", DBUS_TYPE_UINT16,
+ &append->stp);
}
-static void connect_return(DBusMessageIter *iter, const char *error,
- void *user_data)
+static void mesh_peer_append(DBusMessageIter *iter, void *user_data)
{
- char *path = user_data;
+ char *peer_addr = user_data;
- if (error == NULL) {
- char *str = strrchr(path, '/');
- str++;
- fprintf(stdout, "Connected %s\n", str);
+ 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: %s\n", path, error);
+ fprintf(stderr, "Error: %s\n", error);
- g_free(user_data);
+ return 0;
}
-static int cmd_connect(char *args[], int num, struct option *options)
+static int connected_mesh_peers_list(DBusMessageIter *iter,
+ const char *error, void *user_data)
{
- char *path;
+ if (!error) {
+ __connmanctl_mesh_connected_peers_list(iter);
+ fprintf(stdout, "\n");
+ } else
+ fprintf(stderr, "Error: %s\n", error);
- if (num > 2)
- return -E2BIG;
+ return 0;
+}
- if (num < 2)
- return -EINVAL;
+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);
- path = g_strdup_printf("/net/connman/service/%s", args[1]);
- return __connmanctl_dbus_method_call(connection, path,
- "net.connman.Service", "Connect",
- connect_return, path, DBUS_TYPE_INVALID);
+ return 0;
}
-static void disconnect_return(DBusMessageIter *iter, const char *error,
+static int mesh_connect_return(DBusMessageIter *iter, const char *error,
void *user_data)
{
char *path = user_data;
- if (error == NULL) {
+ if (!error) {
char *str = strrchr(path, '/');
str++;
- fprintf(stdout, "Disconnected %s\n", 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_disconnect(char *args[], int num, struct option *options)
+static int mesh_disconnect_return(DBusMessageIter *iter, const char *error,
+ void *user_data)
{
- char *path;
-
- if (num > 2)
- return -E2BIG;
+ char *path = user_data;
- if (num < 2)
- return -EINVAL;
+ if (!error) {
+ char *str = strrchr(path, '/');
+ str++;
+ fprintf(stdout, "Disconnected %s\n", str);
+ } else
+ fprintf(stderr, "Error %s: %s\n", path, error);
- path = g_strdup_printf("/net/connman/service/%s", args[1]);
- return __connmanctl_dbus_method_call(connection, path,
- "net.connman.Service", "Disconnect",
- disconnect_return, path, DBUS_TYPE_INVALID);
+ g_free(user_data);
return 0;
}
-static void config_return(DBusMessageIter *iter, const char *error,
+static int mesh_remove_return(DBusMessageIter *iter, const char *error,
void *user_data)
{
- char *service_name = user_data;
+ char *path = user_data;
- if (error != NULL)
- fprintf(stderr, "Error %s: %s\n", service_name, error);
+ 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);
-}
-struct config_append {
- char **opts;
- int values;
-};
+ return 0;
+}
-static void config_append_ipv4(DBusMessageIter *iter,
+static int mesh_config_return(DBusMessageIter *iter, const char *error,
void *user_data)
{
- struct config_append *append = user_data;
- char **opts = append->opts;
- int i = 0;
+ char *path = user_data;
+ char *str = strrchr(path, '/');
+ str++;
- if (opts == NULL)
- return;
+ if (error)
+ fprintf(stderr, "Error %s: %s\n", path, error);
+ else
+ fprintf(stdout, "Success SetProperty %s\n", str);
- while (opts[i] != NULL && ipv4[i] != NULL) {
- __connmanctl_dbus_append_dict_entry(iter, ipv4[i],
- DBUS_TYPE_STRING, &opts[i]);
- i++;
- }
+ g_free(user_data);
- append->values = i;
+ return 0;
}
-static void config_append_ipv6(DBusMessageIter *iter, void *user_data)
+static int cmd_mesh(char *args[], int num, struct connman_option *options)
{
- struct config_append *append = user_data;
- char **opts = append->opts;
+ 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;
- if (opts == NULL)
- return;
+ c = parse_args(args[1], options);
- append->values = 1;
+ 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;
- if (g_strcmp0(opts[0], "auto") == 0) {
+ 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, 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, 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, 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, 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, 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, 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;
+ 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, 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, 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, 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, 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, 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;
+ }
+
+ if (res < 0 && res != -EINPROGRESS) {
+ printf("Error '%s': %s\n", args_struct->args[index],
+ strerror(-res));
+ return;
+ }
+
+ index += append.values;
+ }
+}
+
+static void session_create_append(DBusMessageIter *iter, void *user_data)
+{
+ struct session_options *args_struct = user_data;
+
+ __connmanctl_dbus_append_dict(iter, session_create_append_dict,
+ args_struct);
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH,
+ &args_struct->notify_path);
+}
+
+static int session_create(gboolean connect, char *args[], int num,
+ struct connman_option *options)
+{
+ int res;
+ char *notify_path;
+ struct session_options args_struct;
+ args_struct.args = args;
+ args_struct.num = num;
+ args_struct.options = options;
+
+ notify_path = g_strdup_printf("/net/connman/connmanctl%d", getpid());
+ session_notify_add(notify_path);
+ args_struct.notify_path = notify_path;
+
+ res = __connmanctl_dbus_method_call(connection, "net.connman", "/",
+ "net.connman.Manager", "CreateSession",
+ session_create_cb, GINT_TO_POINTER(connect),
+ session_create_append, &args_struct);
+
+ g_free(notify_path);
+
+ if (res < 0 && res != -EINPROGRESS)
+ session_notify_remove();
+
+ return res;
+}
+
+static int session_destroy_cb(DBusMessageIter *iter, const char *error,
+ void *user_data)
+{
+ if (error) {
+ fprintf(stderr, "Error destroying session: %s", error);
+ return 0;
+ }
+
+ fprintf(stdout, "Session %s ended\n", session_path);
+
+ g_free(session_path);
+ session_path = NULL;
+ session_connected = false;
+
+ return 0;
+}
+
+static void session_destroy_append(DBusMessageIter *iter, void *user_data)
+{
+ const char *path = user_data;
+
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path);
+}
+
+static int session_destroy(void)
+{
+ return __connmanctl_dbus_method_call(connection, "net.connman", "/",
+ "net.connman.Manager", "DestroySession",
+ session_destroy_cb, NULL,
+ session_destroy_append, session_path);
+}
+
+static int session_config_return(DBusMessageIter *iter, const char *error,
+ void *user_data)
+{
+ char *property_name = user_data;
- str = "disabled";
- __connmanctl_dbus_append_dict_entry(iter, "Privacy",
- DBUS_TYPE_STRING, &str);
- break;
+ if (error)
+ fprintf(stderr, "Error setting session %s: %s\n",
+ property_name, error);
- case 1:
- append->values = 2;
+ return 0;
+}
- str = "enabled";
- __connmanctl_dbus_append_dict_entry(iter, "Privacy",
- DBUS_TYPE_STRING, &str);
- break;
+static int session_config(char *args[], int num,
+ struct connman_option *options)
+{
+ int index = 0, res = 0;
+ struct config_append append;
+ char c;
+ char *ifname;
+ dbus_bool_t source_ip_rule;
- default:
- if (opts[1] != NULL) {
- append->values = 2;
+ while (index < num && args[index]) {
+ append.opts = &args[index];
+ append.values = 0;
- if (g_strcmp0(opts[0], "prefered") != 0) {
- fprintf(stderr, "Error %s: %s\n",
- opts[1],
- strerror(-EINVAL));
- return;
- }
+ c = parse_args(args[index], options);
- str = "prefered";
- __connmanctl_dbus_append_dict_entry(iter,
- "Privacy", DBUS_TYPE_STRING,
- &str);
+ switch (c) {
+ case 'b':
+ res = __connmanctl_dbus_session_change_array(connection,
+ session_path, session_config_return,
+ "AllowedBearers", "AllowedBearers",
+ session_config_append_array, &append);
+ break;
+ case 't':
+ if (!args[index + 1]) {
+ res = -EINVAL;
+ break;
}
+
+ res = __connmanctl_dbus_session_change(connection,
+ session_path, session_config_return,
+ "ConnectionType", "ConnectionType",
+ DBUS_TYPE_STRING, &args[index + 1]);
+ append.values = 2;
break;
- }
- } else if (g_strcmp0(opts[0], "manual") == 0) {
- int i = 1;
+ case 'i':
+ if (index + 1 < num)
+ ifname = args[index + 1];
+ else
+ ifname = "";
- while (opts[i] != NULL && ipv6[i] != NULL) {
- 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]);
+ res = __connmanctl_dbus_session_change(connection,
+ session_path, session_config_return,
+ "AllowedInterface", "AllowedInterface",
+ DBUS_TYPE_STRING, &ifname);
+ append.values = 2;
+ break;
+ case 's':
+ if (!args[index + 1]) {
+ res = -EINVAL;
+ break;
+ }
+ switch (parse_boolean(args[index + 1])) {
+ case 1:
+ source_ip_rule = TRUE;
+ break;
+ case 0:
+ source_ip_rule = FALSE;
+ break;
+ default:
+ res = -EINVAL;
+ break;
}
- i++;
- }
- append->values = i;
+ res = __connmanctl_dbus_session_change(connection,
+ session_path, session_config_return,
+ "SourceIPRule", "SourceIPRule",
+ DBUS_TYPE_BOOLEAN, &source_ip_rule);
+ append.values = 2;
+ break;
+ case 'c':
+ if (!args[index + 1]) {
+ res = -EINVAL;
+ break;
+ }
- } else if (g_strcmp0(opts[0], "off") != 0) {
- fprintf(stderr, "Error %s: %s\n", opts[0], strerror(-EINVAL));
+ res = __connmanctl_dbus_session_change(connection,
+ session_path, session_config_return,
+ "ctxid", "ctxid", DBUS_TYPE_STRING,
+ &args[index + 1]);
+ append.values = 2;
+ break;
- return;
+ default:
+ res = -EINVAL;
+ }
+
+ if (res < 0 && res != -EINPROGRESS) {
+ printf("Error '%s': %s\n", args[index],
+ strerror(-res));
+ return 0;
+ }
+
+ index += append.values;
}
- __connmanctl_dbus_append_dict_entry(iter, "Method", DBUS_TYPE_STRING,
- &opts[0]);
+ return 0;
}
-static void config_append_str(DBusMessageIter *iter, void *user_data)
+static int cmd_session(char *args[], int num, struct connman_option *options)
{
- struct config_append *append = user_data;
- char **opts = append->opts;
- int i = 0;
+ char *command;
- if (opts == NULL)
- return;
+ if (num < 2)
+ return -EINVAL;
+
+ command = args[1];
+
+ switch(parse_boolean(command)) {
+ case 0:
+ if (!session_path)
+ return -EALREADY;
+ return session_destroy();
+
+ case 1:
+ if (session_path)
+ return -EALREADY;
+ return session_create(FALSE, &args[2], num - 2, options);
+
+ default:
+ if (!strcmp(command, "connect")) {
+ if (!session_path)
+ return session_create(TRUE, &args[2], num - 2,
+ options);
+
+ return session_connect();
+
+ } else if (!strcmp(command, "disconnect")) {
+
+ if (!session_path) {
+ fprintf(stdout, "Session does not exist\n");
+ return 0;
+ }
+
+ return session_disconnect();
+ } else if (!strcmp(command, "config")) {
+ if (!session_path) {
+ fprintf(stdout, "Session does not exist\n");
+ return 0;
+ }
+
+ if (num == 2)
+ return -EINVAL;
+
+ return session_config(&args[2], num - 2, options);
+ }
- while (opts[i] != NULL) {
- dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
- &opts[i]);
- i++;
}
- append->values = i;
+ return -EINVAL;
}
-static void append_servers(DBusMessageIter *iter, void *user_data)
+static int cmd_exit(char *args[], int num, struct connman_option *options)
{
- struct config_append *append = user_data;
- char **opts = append->opts;
- int i = 1;
+ return 1;
+}
- if (opts == NULL)
- return;
+static char *lookup_key_from_table(GHashTable *hash, const char *text,
+ int state)
+{
+ static int len = 0;
+ static GHashTableIter iter;
+ gpointer key, value;
- while (opts[i] != NULL && g_strcmp0(opts[i], "--excludes") != 0) {
- dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
- &opts[i]);
- i++;
+ if (state == 0) {
+ g_hash_table_iter_init(&iter, hash);
+ len = strlen(text);
}
- append->values = i;
+ while (g_hash_table_iter_next(&iter, &key, &value))
+ if (strncmp(text, key, len) == 0)
+ return strdup(key);
+
+ return NULL;
}
-static void append_excludes(DBusMessageIter *iter, void *user_data)
+static char *lookup_service_arg(const char *text, int state)
{
- struct config_append *append = user_data;
- char **opts = append->opts;
- int i = append->values;
+ if (__connmanctl_input_calc_level() > 1) {
+ __connmanctl_input_lookup_end();
+ return NULL;
+ }
- if (opts == NULL || opts[i] == NULL ||
- g_strcmp0(opts[i], "--excludes") != 0)
- return;
+ return lookup_key_from_table(service_hash, text, state);
+}
- i++;
- while (opts[i] != NULL) {
- dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING,
- &opts[i]);
- i++;
+static char *lookup_peer(const char *text, int state)
+{
+ static GHashTableIter iter;
+ gpointer key, value;
+ static int len = 0;
+
+ if (state == 0) {
+ g_hash_table_iter_init(&iter, peer_hash);
+ len = strlen(text);
}
- append->values = i;
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ const char *peer = key;
+ if (strncmp(text, peer, len) == 0)
+ return strdup(peer);
+ }
+
+ return NULL;
}
-static void config_append_proxy(DBusMessageIter *iter, void *user_data)
+static char *lookup_peer_arg(const char *text, int state)
{
- struct config_append *append = user_data;
- char **opts = append->opts;
+ if (__connmanctl_input_calc_level() > 1) {
+ __connmanctl_input_lookup_end();
+ return NULL;
+ }
- if (opts == NULL)
- return;
+ return lookup_peer(text, state);
+}
- if (g_strcmp0(opts[0], "manual") == 0) {
- __connmanctl_dbus_append_dict_string_array(iter, "Servers",
- append_servers, append);
+static char *lookup_technology(const char *text, int state)
+{
+ static int len = 0;
+ static GHashTableIter iter;
+ gpointer key, value;
- __connmanctl_dbus_append_dict_string_array(iter, "Excludes",
- append_excludes, append);
+ if (state == 0) {
+ g_hash_table_iter_init(&iter, technology_hash);
+ len = strlen(text);
+ }
- } else if (g_strcmp0(opts[0], "auto") == 0) {
- if (opts[1] != NULL) {
- __connmanctl_dbus_append_dict_entry(iter, "URL",
- DBUS_TYPE_STRING, &opts[1]);
- append->values++;
- }
+ while (g_hash_table_iter_next(&iter, &key, &value)) {
+ const char *technology = key;
+ if (strncmp(text, technology, len) == 0)
+ return strdup(technology);
+ }
- } else if (g_strcmp0(opts[0], "direct") != 0)
- return;
+ return NULL;
+}
- __connmanctl_dbus_append_dict_entry(iter, "Method",DBUS_TYPE_STRING,
- &opts[0]);
+static char *lookup_technology_arg(const char *text, int state)
+{
+ if (__connmanctl_input_calc_level() > 1) {
+ __connmanctl_input_lookup_end();
+ return NULL;
+ }
- append->values++;
+ return lookup_technology(text, state);
}
-static int cmd_config(char *args[], int num, struct option *options)
+static char *lookup_technology_offline(const char *text, int state)
{
- 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;
+ static int len = 0;
+ static bool end = false;
+ char *str;
- service_name = args[1];
- if (service_name == NULL)
- return -EINVAL;
+ if (__connmanctl_input_calc_level() > 1) {
+ __connmanctl_input_lookup_end();
+ return NULL;
+ }
- while (index < num && args[index] != NULL) {
- c = parse_args(args[index], options);
- opt_start = &args[index + 1];
- append.opts = opt_start;
- append.values = 0;
+ if (state == 0) {
+ len = strlen(text);
+ end = false;
+ }
- res = 0;
+ if (end)
+ return NULL;
- oldindex = index;
- path = g_strdup_printf("/net/connman/service/%s", service_name);
+ str = lookup_technology(text, state);
+ if (str)
+ return str;
- switch (c) {
- case 'a':
- switch (parse_boolean(*opt_start)) {
- case 1:
- val = TRUE;
- break;
- case 0:
- val = FALSE;
- break;
- default:
- res = -EINVAL;
- break;
- }
+ end = true;
- index++;
+ if (strncmp(text, "offline", len) == 0)
+ return strdup("offline");
- 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;
+ return NULL;
+}
- 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;
+static char *lookup_on_off(const char *text, int state)
+{
+ char *onoff[] = { "on", "off", NULL };
+ static int idx = 0;
+ static int len = 0;
- 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;
+ char *str;
+
+ if (!state) {
+ idx = 0;
+ len = strlen(text);
+ }
+
+ while (onoff[idx]) {
+ str = onoff[idx];
+ idx++;
+
+ if (!strncmp(text, str, len))
+ return strdup(str);
+ }
- 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;
+ return NULL;
+}
- 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;
+static char *lookup_tether(const char *text, int state)
+{
+ int level;
- 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,
- path, "net.connman.Service", "Remove",
- config_return, g_strdup(service_name),
- DBUS_TYPE_INVALID);
- break;
- default:
- res = -EINVAL;
- break;
- }
+ level = __connmanctl_input_calc_level();
+ if (level < 2)
+ return lookup_technology(text, state);
- g_free(path);
+ if (level == 2)
+ return lookup_on_off(text, state);
- if (res < 0) {
- if (res == -EINPROGRESS)
- result = -EINPROGRESS;
- else
- printf("Error '%s': %s\n", args[oldindex],
- strerror(-res));
- } else
- index += res;
+ __connmanctl_input_lookup_end();
- index++;
+ return NULL;
+}
+
+static char *lookup_agent(const char *text, int state)
+{
+ if (__connmanctl_input_calc_level() > 1) {
+ __connmanctl_input_lookup_end();
+ return NULL;
}
- return result;
+ return lookup_on_off(text, state);
}
-static DBusHandlerResult monitor_changed(DBusConnection *connection,
- DBusMessage *message, void *user_data)
+static char *lookup_vpnconnection_arg(const char *text, int state)
{
- DBusMessageIter iter;
- const char *interface, *path;
+ if (__connmanctl_input_calc_level() > 1) {
+ __connmanctl_input_lookup_end();
+ return NULL;
+ }
- interface = dbus_message_get_interface(message);
- if (strncmp(interface, "net.connman.", 12) != 0)
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ return lookup_key_from_table(vpnconnection_hash, text, state);
+}
- interface = strrchr(interface, '.');
- if (interface != NULL && *interface != '\0')
- interface++;
+static struct connman_option service_options[] = {
+ {"properties", 'p', "[<service>] (obsolete)"},
+ { NULL, }
+};
- path = strrchr(dbus_message_get_path(message), '/');
- if (path != NULL && *path != '\0')
- path++;
+#if defined TIZEN_EXT_INS
+static struct connman_option ins_options[] = {
+ {"all", 'a', ""},
+ {"filter-ssid", 's', "ssid"},
+ {"filter-name", 'n', "[<service_name>]"},
+ { NULL, }
+};
+#endif
- __connmanctl_save_rl();
+static struct connman_option config_options[] = {
+ {"nameservers", 'n', "<dns1> [<dns2>] [<dns3>]"},
+ {"timeservers", 't', "<ntp1> [<ntp2>] [...]"},
+ {"domains", 'd', "<domain1> [<domain2>] [...]"},
+ {"mdns", 'm', "yes|no"},
+ {"ipv6", 'v', "off|auto [enable|disable|preferred]|\n"
+ "\t\t\tmanual <address> <prefixlength> <gateway>"},
+ {"proxy", 'x', "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
+ "\t\t\t[exclude <exclude1> [<exclude2>] [...]]"},
+ {"autoconnect", 'a', "yes|no"},
+ {"ipv4", 'i', "off|dhcp|manual <address> <netmask> <gateway>"},
+ {"remove", 'r', " Remove service"},
+ { NULL, }
+};
- if (dbus_message_is_signal(message, "net.connman.Manager",
- "ServicesChanged") == TRUE) {
+static struct connman_option monitor_options[] = {
+ {"services", 's', "[off] Monitor only services"},
+ {"tech", 'c', "[off] Monitor only technologies"},
+ {"manager", 'm', "[off] Monitor only manager interface"},
+ {"vpnmanager", 'M', "[off] Monitor only VPN manager "
+ "interface"},
+ {"vpnconnection", 'C', "[off] Monitor only VPN "
+ "connections" },
+ { NULL, }
+};
- fprintf(stdout, "%-12s %-20s = {\n", interface,
- "ServicesChanged");
- dbus_message_iter_init(message, &iter);
- __connmanctl_services_list(&iter);
- fprintf(stdout, "\n}\n");
+static struct connman_option session_options[] = {
+ {"bearers", 'b', "<technology1> [<technology2> [...]]"},
+ {"type", 't', "local|internet|any"},
+ {"ifname", 'i', "[<interface_name>]"},
+ {"srciprule", 's', "yes|no"},
+ {"ctxid", 'c', "<context_identifier>"},
+ { NULL, }
+};
- __connmanctl_redraw_rl();
+#if defined TIZEN_EXT_WIFI_MESH
+static struct connman_option mesh_options[] = {
+ {"ifadd", 'a', "<ifname> <wifi_ifname>\n"
+ " [bridge_ifname] Add Virtual Mesh "
+ "interface"},
+ {"ifrmv", 'r', "<ifname> Remove Virtual Mesh "
+ "interface"},
+ {"peers", 'p', "[peer] Display Mesh peer "
+ "informations"},
+ {"connect", 'c', "<peer> Connect Mesh Peer"},
+ {"disconnect", 'd', "<peer> Disconnect Mesh Peer"},
+ {"remove", 'f', "<peer> Forget Mesh Peer"},
+ {"connected_peers", 'C', "[] Displays connected"
+ " Peer informations"},
+ {"disconnected_peers", 'D', "[] Displays "
+ "Disconnected Peer informations"},
+ {"create_network", 'n', "<name> <frequency> <sec_type> Create New Mesh "
+ "Network"},
+ {"abort_scan", 'A', " Abort ongoing mesh "
+ "scan"},
+ {"specific_scan", 'S', "<name> <frequency> Create New Mesh "
+ "Network"},
+ {"config", 'P', "<peer> Set Mesh Network "
+ "Configurations\n Passphrase <passphrase>"},
+ {"set_gate", 'G', "<gate_ann> <rootmode> <stp> Set Mesh Gate "
+ "Option"},
+ {"add_peer", 'z', "<addr> Add Mesh Peer"},
+ {"remove_peer", 'y', "<addr> Remove Mesh Peer"},
+ { NULL, }
+};
+#endif
+
+static char *lookup_options(struct connman_option *options, const char *text,
+ int state)
+{
+ static int idx = 0;
+ static int len = 0;
+ const char *str;
- return DBUS_HANDLER_RESULT_HANDLED;
+ if (state == 0) {
+ idx = 0;
+ len = strlen(text);
}
- if (dbus_message_is_signal(message, "net.connman.Manager",
- "TechnologyAdded") == TRUE)
- path = "TechnologyAdded";
+ while (options[idx].name) {
+ str = options[idx].name;
+ idx++;
- if (dbus_message_is_signal(message, "net.connman.Manager",
- "TechnologyRemoved") == TRUE)
- path = "TechnologyRemoved";
+ if (str && strncmp(text, str, len) == 0)
+ return strdup(str);
+ }
- fprintf(stdout, "%-12s %-20s ", interface, path);
- dbus_message_iter_init(message, &iter);
+ return NULL;
+}
- __connmanctl_dbus_print(&iter, "", " = ", " = ");
- fprintf(stdout, "\n");
+static char *lookup_monitor(const char *text, int state)
+{
+ int level;
- __connmanctl_redraw_rl();
+ level = __connmanctl_input_calc_level();
+
+ if (level < 2)
+ return lookup_options(monitor_options, text, state);
- return DBUS_HANDLER_RESULT_HANDLED;
+ if (level == 2)
+ return lookup_on_off(text, state);
+
+ __connmanctl_input_lookup_end();
+ return NULL;
}
-static bool monitor_s = false;
-static bool monitor_t = false;
-static bool monitor_m = false;
+static char *lookup_config(const char *text, int state)
+{
+ if (__connmanctl_input_calc_level() < 2)
+ return lookup_key_from_table(service_hash, text, state);
-static void monitor_add(char *interface)
+ return lookup_options(config_options, text, state);
+}
+
+static char *lookup_session(const char *text, int state)
{
- char *rule;
- DBusError err;
+ return lookup_options(session_options, text, state);
+}
- if (monitor_s == false && monitor_t == false && monitor_m == false)
- dbus_connection_add_filter(connection, monitor_changed,
- NULL, NULL);
+#if defined TIZEN_EXT_WIFI_MESH
+static char *lookup_mesh(const char *text, int state)
+{
+ return lookup_options(mesh_options, text, state);
+}
+#endif
- if (g_strcmp0(interface, "Service") == 0) {
- if (monitor_s == true)
- return;
- monitor_s = true;
- } else if (g_strcmp0(interface, "Technology") == 0) {
- if (monitor_t == true)
- return;
- monitor_t = true;
- } else if (g_strcmp0(interface, "Manager") == 0) {
- if (monitor_m == true)
- return;
- monitor_m = true;
- } else
- return;
+static int peer_service_cb(DBusMessageIter *iter, const char *error,
+ void *user_data)
+{
+ bool registration = GPOINTER_TO_INT(user_data);
- 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 (error)
+ fprintf(stderr, "Error %s peer service: %s\n",
+ registration ? "registering" : "unregistering", error);
+ else
+ fprintf(stdout, "Peer service %s\n",
+ registration ? "registered" : "unregistered");
- if (dbus_error_is_set(&err))
- fprintf(stderr, "Error: %s\n", err.message);
+ return 0;
}
-static void monitor_del(char *interface)
+struct _peer_service {
+ unsigned char *bjr_query;
+ int bjr_query_len;
+ unsigned char *bjr_response;
+ int bjr_response_len;
+ unsigned char *wfd_ies;
+ int wfd_ies_len;
+ char *upnp_service;
+ int version;
+ int master;
+};
+
+static void append_dict_entry_fixed_array(DBusMessageIter *iter,
+ const char *property, void *value, int length)
{
- char *rule;
+ DBusMessageIter dict_entry, variant, array;
+
+ dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY,
+ NULL, &dict_entry);
+ dbus_message_iter_append_basic(&dict_entry, DBUS_TYPE_STRING,
+ &property);
+ dbus_message_iter_open_container(&dict_entry, DBUS_TYPE_VARIANT,
+ DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING,
+ &variant);
+ dbus_message_iter_open_container(&variant, DBUS_TYPE_ARRAY,
+ DBUS_TYPE_BYTE_AS_STRING, &array);
+ dbus_message_iter_append_fixed_array(&array, DBUS_TYPE_BYTE,
+ value, length);
+ dbus_message_iter_close_container(&variant, &array);
+ dbus_message_iter_close_container(&dict_entry, &variant);
+ dbus_message_iter_close_container(iter, &dict_entry);
+}
- if (g_strcmp0(interface, "Service") == 0) {
- if (monitor_s == false)
- return;
- monitor_s = false;
- } else if (g_strcmp0(interface, "Technology") == 0) {
- if (monitor_t == false)
- return;
- monitor_t = false;
- } else if (g_strcmp0(interface, "Manager") == 0) {
- if (monitor_m == false)
- return;
- monitor_m = false;
- } else
- return;
+static void append_peer_service_dict(DBusMessageIter *iter, void *user_data)
+{
+ struct _peer_service *service = user_data;
+
+ if (service->bjr_query && service->bjr_response) {
+ append_dict_entry_fixed_array(iter, "BonjourQuery",
+ &service->bjr_query, service->bjr_query_len);
+ append_dict_entry_fixed_array(iter, "BonjourResponse",
+ &service->bjr_response, service->bjr_response_len);
+ } else if (service->upnp_service && service->version) {
+ __connmanctl_dbus_append_dict_entry(iter, "UpnpVersion",
+ DBUS_TYPE_INT32, &service->version);
+ __connmanctl_dbus_append_dict_entry(iter, "UpnpService",
+ DBUS_TYPE_STRING, &service->upnp_service);
+ } else if (service->wfd_ies) {
+ append_dict_entry_fixed_array(iter, "WiFiDisplayIEs",
+ &service->wfd_ies, service->wfd_ies_len);
+ }
+}
- rule = g_strdup_printf("type='signal',interface='net.connman.%s'",
- interface);
- dbus_bus_remove_match(connection, rule, NULL);
- g_free(rule);
+static void peer_service_append(DBusMessageIter *iter, void *user_data)
+{
+ struct _peer_service *service = user_data;
+ dbus_bool_t master;
- if (monitor_s == false && monitor_t == false && monitor_m == false)
- dbus_connection_remove_filter(connection, monitor_changed,
- NULL);
+ __connmanctl_dbus_append_dict(iter, append_peer_service_dict, service);
+
+ if (service->master < 0)
+ return;
+
+ master = service->master == 1 ? TRUE : FALSE;
+ dbus_message_iter_append_basic(iter, DBUS_TYPE_BOOLEAN, &master);
}
-static int cmd_monitor(char *args[], int num, struct option *options)
+static struct _peer_service *fill_in_peer_service(unsigned char *bjr_query,
+ int bjr_query_len, unsigned char *bjr_response,
+ int bjr_response_len, char *upnp_service,
+ int version, unsigned char *wfd_ies,
+ int wfd_ies_len)
{
- bool add = true;
- int c;
+ struct _peer_service *service;
- if (num > 3)
- return -E2BIG;
+ service = dbus_malloc0(sizeof(*service));
- if (num == 3) {
- switch (parse_boolean(args[2])) {
- case 0:
- add = false;
- break;
+#if defined TIZEN_EXT
+ if (!service)
+ return NULL;
+#endif
- default:
- break;
+ if (bjr_query_len && bjr_response_len) {
+ service->bjr_query = dbus_malloc0(bjr_query_len);
+#if defined TIZEN_EXT
+ if(!service->bjr_query) {
+ dbus_free(service);
+ return NULL;
+ }
+#endif
+ memcpy(service->bjr_query, bjr_query, bjr_query_len);
+ service->bjr_query_len = bjr_query_len;
+
+ service->bjr_response = dbus_malloc0(bjr_response_len);
+#if defined TIZEN_EXT
+ if(!service->bjr_response) {
+ dbus_free(service->bjr_query);
+ dbus_free(service);
+ return NULL;
}
+#endif
+ memcpy(service->bjr_response, bjr_response, bjr_response_len);
+ service->bjr_response_len = bjr_response_len;
+ } else if (upnp_service && version) {
+ service->upnp_service = strdup(upnp_service);
+ service->version = version;
+ } else if (wfd_ies && wfd_ies_len) {
+ service->wfd_ies = dbus_malloc0(wfd_ies_len);
+#if defined TIZEN_EXT
+ if (!service->wfd_ies) {
+ dbus_free(service);
+ return NULL;
+ }
+#endif
+ memcpy(service->wfd_ies, wfd_ies, wfd_ies_len);
+ service->wfd_ies_len = wfd_ies_len;
+ } else {
+ dbus_free(service);
+ service = NULL;
}
- c = parse_args(args[1], options);
- switch (c) {
- case -1:
- monitor_add("Service");
- monitor_add("Technology");
- monitor_add("Manager");
- break;
+ return service;
+}
- case 's':
- if (add == true)
- monitor_add("Service");
- else
- monitor_del("Service");
- break;
+static void free_peer_service(struct _peer_service *service)
+{
+ dbus_free(service->bjr_query);
+ dbus_free(service->bjr_response);
+ dbus_free(service->wfd_ies);
+ free(service->upnp_service);
+ dbus_free(service);
+}
- case 'c':
- if (add == true)
- monitor_add("Technology");
- else
- monitor_del("Technology");
- break;
+static int peer_service_register(unsigned char *bjr_query, int bjr_query_len,
+ unsigned char *bjr_response, int bjr_response_len,
+ char *upnp_service, int version,
+ unsigned char *wfd_ies, int wfd_ies_len, int master)
+{
+ struct _peer_service *service;
+ bool registration = true;
+ int ret;
+
+ service = fill_in_peer_service(bjr_query, bjr_query_len, bjr_response,
+ bjr_response_len, upnp_service, version,
+ wfd_ies, wfd_ies_len);
+ if (!service)
+ return -EINVAL;
- case 'm':
- if (add == true)
- monitor_add("Manager");
- else
- monitor_del("Manager");
- break;
+ service->master = master;
- default:
- switch(parse_boolean(args[1])) {
- case 0:
- monitor_del("Service");
- monitor_del("Technology");
- monitor_del("Manager");
- break;
+ ret = __connmanctl_dbus_method_call(connection, "net.connman", "/",
+ "net.connman.Manager", "RegisterPeerService",
+ peer_service_cb, GINT_TO_POINTER(registration),
+ peer_service_append, service);
- case 1:
- monitor_add("Service");
- monitor_add("Technology");
- monitor_add("Manager");
- break;
+ free_peer_service(service);
- default:
- return -EINVAL;
- }
- }
+ return ret;
+}
- if (add == true)
- return -EINPROGRESS;
+static int peer_service_unregister(unsigned char *bjr_query, int bjr_query_len,
+ unsigned char *bjr_response, int bjr_response_len,
+ char *upnp_service, int version,
+ unsigned char *wfd_ies, int wfd_ies_len)
+{
+ struct _peer_service *service;
+ bool registration = false;
+ int ret;
+
+ service = fill_in_peer_service(bjr_query, bjr_query_len, bjr_response,
+ bjr_response_len, upnp_service, version,
+ wfd_ies, wfd_ies_len);
+ if (!service)
+ return -EINVAL;
- return 0;
+ service->master = -1;
+
+ ret = __connmanctl_dbus_method_call(connection, "net.connman", "/",
+ "net.connman.Manager", "UnregisterPeerService",
+ peer_service_cb, GINT_TO_POINTER(registration),
+ peer_service_append, service);
+
+ free_peer_service(service);
+
+ return ret;
}
-static int cmd_exit(char *args[], int num, struct option *options)
+static int parse_spec_array(char *command, unsigned char spec[1024])
{
- return 1;
+ int length, pos, end;
+ char b[3] = {};
+ char *e;
+
+ end = strlen(command);
+ for (e = NULL, length = pos = 0; command[pos] != '\0'; length++) {
+ if (pos+2 > end)
+ return -EINVAL;
+
+ b[0] = command[pos];
+ b[1] = command[pos+1];
+
+ spec[length] = strtol(b, &e, 16);
+ if (e && *e != '\0')
+ return -EINVAL;
+
+ pos += 2;
+ }
+
+ return length;
}
-static struct option service_options[] = {
- {"properties", required_argument, 0, 'p'},
- { NULL, }
-};
+static int cmd_peer_service(char *args[], int num,
+ struct connman_option *options)
+{
+ unsigned char bjr_query[1024] = {};
+ unsigned char bjr_response[1024] = {};
+ unsigned char wfd_ies[1024] = {};
+ char *upnp_service = NULL;
+ int bjr_query_len = 0, bjr_response_len = 0;
+ int version = 0, master = 0, wfd_ies_len = 0;
+ int limit;
+
+ if (num < 4)
+ return -EINVAL;
-static const char *service_desc[] = {
- "[<service>] (obsolete)",
- NULL
-};
+ if (!strcmp(args[2], "wfd_ies")) {
+ wfd_ies_len = parse_spec_array(args[3], wfd_ies);
+ if (wfd_ies_len == -EINVAL)
+ return -EINVAL;
+ limit = 5;
+ goto master;
+ }
-static struct option config_options[] = {
- {"nameservers", required_argument, 0, 'n'},
- {"timeservers", required_argument, 0, 't'},
- {"domains", required_argument, 0, 'd'},
- {"ipv6", required_argument, 0, 'v'},
- {"proxy", required_argument, 0, 'x'},
- {"autoconnect", required_argument, 0, 'a'},
- {"ipv4", required_argument, 0, 'i'},
- {"remove", 0, 0, 'r'},
- { NULL, }
-};
+ if (num < 6)
+ return -EINVAL;
+
+ limit = 7;
+ if (!strcmp(args[2], "bjr_query")) {
+ if (strcmp(args[4], "bjr_response"))
+ return -EINVAL;
+ bjr_query_len = parse_spec_array(args[3], bjr_query);
+ bjr_response_len = parse_spec_array(args[5], bjr_response);
+
+ if (bjr_query_len == -EINVAL || bjr_response_len == -EINVAL)
+ return -EINVAL;
+ } else if (!strcmp(args[2], "upnp_service")) {
+ char *e = NULL;
+
+ if (strcmp(args[4], "upnp_version"))
+ return -EINVAL;
+ upnp_service = args[3];
+ version = strtol(args[5], &e, 10);
+ if (*e != '\0')
+ return -EINVAL;
+ }
-static const char *config_desc[] = {
- "<dns1> [<dns2>] [<dns3>]",
- "<ntp1> [<ntp2>] [...]",
- "<domain1> [<domain2>] [...]",
- "off|auto [enable|disable|prefered]|\n"
- "\t\t\tmanual <address> <prefixlength> <gateway>",
- "direct|auto <URL>|manual <URL1> [<URL2>] [...]\n"
- "\t\t\t[exclude <exclude1> [<exclude2>] [...]]",
- "yes|no",
- "off|dhcp|manual <address> <netmask> <gateway>",
- " Remove service",
- NULL
-};
+master:
+ if (num == limit) {
+ master = parse_boolean(args[6]);
+ if (master < 0)
+ return -EINVAL;
+ }
-static struct option monitor_options[] = {
- {"services", no_argument, 0, 's'},
- {"tech", no_argument, 0, 'c'},
- {"manager", no_argument, 0, 'm'},
- { NULL, }
-};
+ if (!strcmp(args[1], "register")) {
+ return peer_service_register(bjr_query, bjr_query_len,
+ bjr_response, bjr_response_len, upnp_service,
+ version, wfd_ies, wfd_ies_len, master);
+ } else if (!strcmp(args[1], "unregister")) {
+ return peer_service_unregister(bjr_query, bjr_query_len,
+ bjr_response, bjr_response_len, upnp_service,
+ version, wfd_ies, wfd_ies_len);
+ }
-static const char *monitor_desc[] = {
- "[off] Monitor only services",
- "[off] Monitor only technologies",
- "[off] Monitor only manager interface",
- NULL
-};
+ return -EINVAL;
+}
static const struct {
const char *cmd;
const char *argument;
- struct option *options;
- const char **options_desc;
- int (*func) (char *args[], int num, struct option *options);
+ struct connman_option *options;
+ int (*func) (char *args[], int num, struct connman_option *options);
const char *desc;
+ __connmanctl_lookup_cb cb;
} cmd_table[] = {
- { "enable", "<technology>|offline", NULL, NULL,
- cmd_enable, "Enables given technology or offline mode" },
- { "disable", "<technology>|offline", NULL, NULL,
- cmd_disable, "Disables given technology or offline mode"},
- { "state", NULL, NULL, NULL,
- cmd_state, "Shows if the system is online or offline" },
+ { "state", NULL, NULL, cmd_state,
+ "Shows if the system is online or offline", NULL },
+ { "technologies", NULL, NULL, cmd_technologies,
+ "Display technologies", NULL },
+ { "clock", NULL, NULL, cmd_clock,
+ "Get System Clock Properties", NULL },
+ { "enable", "<technology>|offline", NULL, cmd_enable,
+ "Enables given technology or offline mode",
+ lookup_technology_offline },
+ { "disable", "<technology>|offline", NULL, cmd_disable,
+ "Disables given technology or offline mode",
+ lookup_technology_offline },
+#if defined TIZEN_EXT_WIFI_MESH
+ { "mesh", "", mesh_options, cmd_mesh, "Mesh specific commands",
+ lookup_mesh },
+#endif
{ "tether", "<technology> on|off\n"
" wifi [on|off] <ssid> <passphrase> ",
- NULL, NULL,
- cmd_tether,
- "Enable, disable tethering, set SSID and passphrase for wifi" },
- { "services", "[<service>]", service_options, &service_desc[0],
- cmd_services, "Display services" },
- { "technologies", NULL, NULL, NULL,
- cmd_technologies, "Display technologies" },
- { "scan", "<technology>", NULL, NULL,
- cmd_scan, "Scans for new services for given technology" },
- { "connect", "<service>", NULL, NULL,
- cmd_connect, "Connect a given service" },
- { "disconnect", "<service>", NULL, NULL,
- cmd_disconnect, "Disconnect a given service" },
- { "config", "<service>", config_options, &config_desc[0],
- cmd_config, "Set service configuration options" },
- { "monitor", "[off]", monitor_options, &monitor_desc[0],
- cmd_monitor, "Monitor signals from interfaces" },
- { "help", NULL, NULL, NULL,
- cmd_help, "Show help" },
- { "exit", NULL, NULL, NULL,
- cmd_exit, "Exit" },
- { "quit", NULL, NULL, NULL,
- cmd_exit, "Quit" },
+ NULL, cmd_tether,
+ "Enable, disable tethering, set SSID and passphrase for wifi",
+ lookup_tether },
+ { "tethering_clients", NULL, NULL, cmd_tethering_clients,
+ "Display tethering clients", NULL },
+ { "services", "[<service>]", service_options, cmd_services,
+ "Display services", lookup_service_arg },
+#if defined TIZEN_EXT_INS
+ { "ins", NULL, ins_options, cmd_ins,
+ "Display intelligent network selection", NULL },
+#endif
+ { "peers", "[peer]", NULL, cmd_peers,
+ "Display peers", lookup_peer_arg },
+ { "scan", "<technology>", NULL, cmd_scan,
+ "Scans for new services for given technology",
+ lookup_technology_arg },
+ { "connect", "<service/peer>", NULL, cmd_connect,
+ "Connect a given service or peer", lookup_service_arg },
+ { "disconnect", "<service/peer>", NULL, cmd_disconnect,
+ "Disconnect a given service or peer", lookup_service_arg },
+ { "move-before", "<service> <target service> ", NULL,
+ cmd_service_move_before, "Move <service> before <target service>",
+ lookup_service_arg },
+ { "move-after", "<service> <target service> ", NULL,
+ cmd_service_move_after, "Move <service> after <target service>",
+ lookup_service_arg },
+ { "config", "<service>", config_options, cmd_config,
+ "Set service configuration options", lookup_config },
+ { "monitor", "[off]", monitor_options, cmd_monitor,
+ "Monitor signals from interfaces", lookup_monitor },
+ { "agent", "on|off", NULL, cmd_agent,
+ "Agent mode", lookup_agent },
+ { "vpnconnections", "[<connection>]", NULL, cmd_vpnconnections,
+ "Display VPN connections", lookup_vpnconnection_arg },
+ { "vpnagent", "on|off", NULL, cmd_vpnagent,
+ "VPN Agent mode", lookup_agent },
+ { "session", "on|off|connect|disconnect|config", session_options,
+ cmd_session, "Enable or disable a session", lookup_session },
+ { "peer_service", "register|unregister <specs> <master>\n"
+ "Where specs are:\n"
+ "\tbjr_query <query> bjr_response <response>\n"
+ "\tupnp_service <service> upnp_version <version>\n"
+ "\twfd_ies <ies>\n", NULL,
+ cmd_peer_service, "(Un)Register a Peer Service", NULL },
+ { "help", NULL, NULL, cmd_help,
+ "Show help", NULL },
+ { "exit", NULL, NULL, cmd_exit,
+ "Exit", NULL },
+ { "quit", NULL, NULL, cmd_exit,
+ "Quit", NULL },
{ NULL, },
};
-static int cmd_help(char *args[], int num, struct option *options)
+static int cmd_help(char *args[], int num, struct connman_option *options)
{
bool interactive = __connmanctl_is_interactive();
int i, j;
if (interactive == false)
fprintf(stdout, "Usage: connmanctl [[command] [args]]\n");
- for (i = 0; cmd_table[i].cmd != NULL; i++) {
+ for (i = 0; cmd_table[i].cmd; i++) {
const char *cmd = cmd_table[i].cmd;
const char *argument = cmd_table[i].argument;
const char *desc = cmd_table[i].desc;
- printf("%-12s%-22s%s\n", cmd != NULL? cmd: "",
- argument != NULL? argument: "",
- desc != NULL? desc: "");
+ printf("%-16s%-22s%s\n", cmd? cmd: "",
+ argument? argument: "",
+ desc? desc: "");
- if (cmd_table[i].options != NULL) {
- for (j = 0; cmd_table[i].options[j].name != NULL;
+ if (cmd_table[i].options) {
+ for (j = 0; cmd_table[i].options[j].name;
j++) {
const char *options_desc =
- cmd_table[i].options_desc != NULL ?
- cmd_table[i].options_desc[j]: "";
+ cmd_table[i].options[j].desc ?
+ cmd_table[i].options[j].desc: "";
- printf(" --%-12s%s\n",
+ printf(" --%-16s%s\n",
cmd_table[i].options[j].name,
options_desc);
}
return 0;
}
+__connmanctl_lookup_cb __connmanctl_get_lookup_func(const char *text)
+{
+ int i, cmdlen, textlen;
+
+ if (!text)
+ return NULL;
+
+ textlen = strlen(text);
+
+ for (i = 0; cmd_table[i].cmd; i++) {
+ cmdlen = strlen(cmd_table[i].cmd);
+
+ if (textlen > cmdlen && text[cmdlen] != ' ')
+ continue;
+
+ if (strncmp(cmd_table[i].cmd, text, cmdlen) == 0)
+ return cmd_table[i].cb;
+ }
+
+ return NULL;
+}
+
int __connmanctl_commands(DBusConnection *dbus_conn, char *argv[], int argc)
{
int i, result;
connection = dbus_conn;
- for (i = 0; cmd_table[i].cmd != NULL; i++) {
+ for (i = 0; cmd_table[i].cmd; i++) {
if (g_strcmp0(cmd_table[i].cmd, argv[0]) == 0 &&
- cmd_table[i].func != NULL) {
+ cmd_table[i].func) {
result = cmd_table[i].func(argv, argc,
cmd_table[i].options);
if (result < 0 && result != -EINPROGRESS)
len = strlen(text);
}
- while (cmd_table[i].cmd != NULL) {
+ while (cmd_table[i].cmd) {
const char *command = cmd_table[i].cmd;
i++;
return NULL;
}
+
+static char *get_path(char *full_path)
+{
+ char *path;
+
+ path = strrchr(full_path, '/');
+ if (path && *path != '\0')
+ path++;
+ else
+ path = full_path;
+
+ return path;
+}
+
+static void add_service_id(const char *path)
+{
+ g_hash_table_replace(service_hash, g_strdup(path),
+ GINT_TO_POINTER(TRUE));
+}
+
+static void remove_service_id(const char *path)
+{
+ g_hash_table_remove(service_hash, path);
+}
+
+static void services_added(DBusMessageIter *iter)
+{
+ DBusMessageIter array;
+ char *path = NULL;
+
+ while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
+
+ dbus_message_iter_recurse(iter, &array);
+ if (dbus_message_iter_get_arg_type(&array) !=
+ DBUS_TYPE_OBJECT_PATH)
+ return;
+
+ dbus_message_iter_get_basic(&array, &path);
+ add_service_id(get_path(path));
+
+ dbus_message_iter_next(iter);
+ }
+}
+
+static void update_services(DBusMessageIter *iter)
+{
+ DBusMessageIter array;
+ char *path;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+ return;
+
+ dbus_message_iter_recurse(iter, &array);
+ services_added(&array);
+
+ dbus_message_iter_next(iter);
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+ return;
+
+ dbus_message_iter_recurse(iter, &array);
+ while (dbus_message_iter_get_arg_type(&array) ==
+ DBUS_TYPE_OBJECT_PATH) {
+ dbus_message_iter_get_basic(&array, &path);
+ remove_service_id(get_path(path));
+
+ dbus_message_iter_next(&array);
+ }
+}
+
+static int populate_service_hash(DBusMessageIter *iter, const char *error,
+ void *user_data)
+{
+ if (error) {
+ fprintf(stderr, "Error getting services: %s", error);
+ return 0;
+ }
+
+ update_services(iter);
+ return 0;
+}
+
+static void add_vpnconnection_id(const char *path)
+{
+ g_hash_table_replace(vpnconnection_hash, g_strdup(path),
+ GINT_TO_POINTER(TRUE));
+}
+
+static void remove_vpnconnection_id(const char *path)
+{
+ g_hash_table_remove(vpnconnection_hash, path);
+}
+
+static void vpnconnection_added(DBusMessageIter *iter)
+{
+ char *path = NULL;
+
+ dbus_message_iter_get_basic(iter, &path);
+ add_vpnconnection_id(get_path(path));
+}
+
+static void vpnconnection_removed(DBusMessageIter *iter)
+{
+ char *path = NULL;
+
+ dbus_message_iter_get_basic(iter, &path);
+ remove_vpnconnection_id(get_path(path));
+}
+
+static void add_vpnconnections(DBusMessageIter *iter)
+{
+ DBusMessageIter array;
+ char *path = NULL;
+
+ while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
+
+ dbus_message_iter_recurse(iter, &array);
+ if (dbus_message_iter_get_arg_type(&array) !=
+ DBUS_TYPE_OBJECT_PATH)
+ return;
+
+ dbus_message_iter_get_basic(&array, &path);
+ add_vpnconnection_id(get_path(path));
+
+ dbus_message_iter_next(iter);
+ }
+}
+
+static int populate_vpnconnection_hash(DBusMessageIter *iter, const char *error,
+ void *user_data)
+{
+ DBusMessageIter array;
+
+ if (error) {
+ fprintf(stderr, "Error getting VPN connections: %s", error);
+ return 0;
+ }
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+ return 0;
+
+ dbus_message_iter_recurse(iter, &array);
+
+ add_vpnconnections(&array);
+
+ return 0;
+}
+
+static void add_peer_id(const char *path)
+{
+ g_hash_table_replace(peer_hash, g_strdup(path), GINT_TO_POINTER(TRUE));
+}
+
+static void remove_peer_id(const char *path)
+{
+ g_hash_table_remove(peer_hash, path);
+}
+
+static void peers_added(DBusMessageIter *iter)
+{
+ DBusMessageIter array;
+ char *path = NULL;
+
+ while (dbus_message_iter_get_arg_type(iter) == DBUS_TYPE_STRUCT) {
+
+ dbus_message_iter_recurse(iter, &array);
+ if (dbus_message_iter_get_arg_type(&array) !=
+ DBUS_TYPE_OBJECT_PATH)
+ return;
+
+ dbus_message_iter_get_basic(&array, &path);
+ add_peer_id(get_path(path));
+
+ dbus_message_iter_next(iter);
+ }
+}
+
+static void update_peers(DBusMessageIter *iter)
+{
+ DBusMessageIter array;
+ char *path;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+ return;
+
+ dbus_message_iter_recurse(iter, &array);
+ peers_added(&array);
+
+ dbus_message_iter_next(iter);
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+ return;
+
+ dbus_message_iter_recurse(iter, &array);
+ while (dbus_message_iter_get_arg_type(&array) ==
+ DBUS_TYPE_OBJECT_PATH) {
+ dbus_message_iter_get_basic(&array, &path);
+ remove_peer_id(get_path(path));
+
+ dbus_message_iter_next(&array);
+ }
+}
+
+static int populate_peer_hash(DBusMessageIter *iter,
+ const char *error, void *user_data)
+{
+ if (error) {
+ fprintf(stderr, "Error getting peers: %s", error);
+ return 0;
+ }
+
+ update_peers(iter);
+ return 0;
+}
+
+static void add_technology_id(const char *path)
+{
+ g_hash_table_replace(technology_hash, g_strdup(path),
+ GINT_TO_POINTER(TRUE));
+}
+
+static void remove_technology_id(const char *path)
+{
+ g_hash_table_remove(technology_hash, path);
+}
+
+static void remove_technology(DBusMessageIter *iter)
+{
+ char *path = NULL;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
+ return;
+
+ dbus_message_iter_get_basic(iter, &path);
+ remove_technology_id(get_path(path));
+}
+
+static void add_technology(DBusMessageIter *iter)
+{
+ char *path = NULL;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_OBJECT_PATH)
+ return;
+
+ dbus_message_iter_get_basic(iter, &path);
+ add_technology_id(get_path(path));
+}
+
+static void update_technologies(DBusMessageIter *iter)
+{
+ DBusMessageIter array;
+
+ if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
+ return;
+
+ dbus_message_iter_recurse(iter, &array);
+
+ while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_STRUCT) {
+ DBusMessageIter object_path;
+
+ dbus_message_iter_recurse(&array, &object_path);
+
+ add_technology(&object_path);
+
+ dbus_message_iter_next(&array);
+ }
+}
+
+static int populate_technology_hash(DBusMessageIter *iter, const char *error,
+ void *user_data)
+{
+ if (error) {
+ fprintf(stderr, "Error getting technologies: %s\n", error);
+ return 0;
+ }
+
+ update_technologies(iter);
+
+ return 0;
+}
+
+static DBusHandlerResult monitor_completions_changed(
+ DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ bool *enabled = user_data;
+ DBusMessageIter iter;
+ DBusHandlerResult handled;
+
+ if (*enabled)
+ handled = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+ else
+ handled = DBUS_HANDLER_RESULT_HANDLED;
+
+ if (dbus_message_is_signal(message, "net.connman.Manager",
+ "ServicesChanged")) {
+ dbus_message_iter_init(message, &iter);
+ update_services(&iter);
+ return handled;
+ }
+
+ if (dbus_message_is_signal(message, "net.connman.vpn.Manager",
+ "ConnectionAdded")) {
+ dbus_message_iter_init(message, &iter);
+ vpnconnection_added(&iter);
+ return handled;
+ }
+
+ if (dbus_message_is_signal(message, "net.connman.vpn.Manager",
+ "ConnectionRemoved")) {
+ dbus_message_iter_init(message, &iter);
+ vpnconnection_removed(&iter);
+ return handled;
+ }
+
+ if (dbus_message_is_signal(message, "net.connman.Manager",
+ "PeersChanged")) {
+ dbus_message_iter_init(message, &iter);
+ update_peers(&iter);
+ return handled;
+ }
+
+ if (dbus_message_is_signal(message, "net.connman.Manager",
+ "TechnologyAdded")) {
+ dbus_message_iter_init(message, &iter);
+ add_technology(&iter);
+ return handled;
+ }
+
+ if (dbus_message_is_signal(message, "net.connman.Manager",
+ "TechnologyRemoved")) {
+ dbus_message_iter_init(message, &iter);
+ remove_technology(&iter);
+ return handled;
+ }
+
+ if (!g_strcmp0(dbus_message_get_interface(message),
+ "net.connman.Manager"))
+ return handled;
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+void __connmanctl_monitor_completions(DBusConnection *dbus_conn)
+{
+ bool *manager_enabled = NULL;
+ DBusError err;
+ int i;
+
+ for (i = 0; monitor[i].interface; i++) {
+ if (!strcmp(monitor[i].interface, "Manager")) {
+ manager_enabled = &monitor[i].enabled;
+ break;
+ }
+ }
+
+ if (!dbus_conn) {
+ g_hash_table_destroy(service_hash);
+ g_hash_table_destroy(vpnconnection_hash);
+ g_hash_table_destroy(technology_hash);
+
+ dbus_bus_remove_match(connection,
+ "type='signal',interface='net.connman.Manager'", NULL);
+ dbus_bus_remove_match(connection,
+ "type='signal',interface='net.connman.vpn.Manager'",
+ NULL);
+ dbus_connection_remove_filter(connection,
+ monitor_completions_changed,
+ manager_enabled);
+ return;
+ }
+
+ connection = dbus_conn;
+
+ service_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ vpnconnection_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ peer_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ technology_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
+ g_free, NULL);
+
+ __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager", "GetServices",
+ populate_service_hash, NULL, NULL, NULL);
+
+ __connmanctl_dbus_method_call(connection,
+ VPN_SERVICE, CONNMAN_PATH,
+ "net.connman.vpn.Manager", "GetConnections",
+ populate_vpnconnection_hash, NULL, NULL, NULL);
+
+ __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager", "GetPeers",
+ populate_peer_hash, NULL, NULL, NULL);
+
+ __connmanctl_dbus_method_call(connection,
+ CONNMAN_SERVICE, CONNMAN_PATH,
+ "net.connman.Manager", "GetTechnologies",
+ populate_technology_hash, NULL, NULL, NULL);
+
+ dbus_connection_add_filter(connection,
+ monitor_completions_changed, manager_enabled,
+ NULL);
+
+ dbus_error_init(&err);
+ dbus_bus_add_match(connection,
+ "type='signal',interface='net.connman.Manager'", &err);
+
+ if (dbus_error_is_set(&err)) {
+ fprintf(stderr, "Error: %s\n", err.message);
+ return;
+ }
+
+ dbus_bus_add_match(connection,
+ "type='signal',interface='net.connman.vpn.Manager'",
+ &err);
+
+ if (dbus_error_is_set(&err))
+ fprintf(stderr, "Error: %s\n", err.message);
+}