summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/agent.c196
-rw-r--r--client/commands.c322
-rw-r--r--client/dbus_helpers.c5
3 files changed, 483 insertions, 40 deletions
diff --git a/client/agent.c b/client/agent.c
index baa0a87..d020889 100644
--- a/client/agent.c
+++ b/client/agent.c
@@ -368,6 +368,36 @@ static DBusMessage *agent_report_error(DBusConnection *connection,
return NULL;
}
+static DBusMessage *agent_report_peer_error(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct agent_data *request = user_data;
+ char *path, *peer, *error;
+ DBusMessageIter iter;
+
+ if (handle_message(message, request,
+ agent_report_peer_error) == false)
+ return NULL;
+
+ dbus_message_iter_init(message, &iter);
+
+ dbus_message_iter_get_basic(&iter, &path);
+ peer = strip_path(path);
+
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_get_basic(&iter, &error);
+
+ __connmanctl_save_rl();
+ fprintf(stdout, "Agent ReportPeerError %s\n", peer);
+ fprintf(stdout, " %s\n", error);
+ __connmanctl_redraw_rl();
+
+ request->message = dbus_message_ref(message);
+ __connmanctl_agent_mode("Retry (yes/no)? ",
+ report_error_return, request);
+ return NULL;
+}
+
static void request_input_next(struct agent_data *request)
{
int i;
@@ -462,37 +492,16 @@ static void request_input_string_return(char *input, void *user_data)
request_input_next(request);
}
-static DBusMessage *agent_request_input(DBusConnection *connection,
- DBusMessage *message, void *user_data)
+static void parse_agent_request(struct agent_data *request,
+ DBusMessageIter *iter)
{
- struct agent_data *request = user_data;
- DBusMessageIter iter, dict, entry, variant;
- char *service, *str, *field;
- DBusMessageIter dict_entry, field_entry, field_value;
- char *argument, *value, *attr_type = NULL;
-
+ DBusMessageIter dict, entry, variant, dict_entry;
+ DBusMessageIter field_entry, field_value;
+ char *field, *argument, *value;
+ char *attr_type = NULL;
int i;
- if (handle_message(message, request, agent_request_input) == false)
- return NULL;
-
- dbus_message_iter_init(message, &iter);
-
- dbus_message_iter_get_basic(&iter, &str);
- service = strip_path(str);
-
- dbus_message_iter_next(&iter);
- dbus_message_iter_recurse(&iter, &dict);
-
- __connmanctl_save_rl();
- if (strcmp(request->interface, AGENT_INTERFACE) == 0)
- fprintf(stdout, "Agent RequestInput %s\n", service);
- else
- fprintf(stdout, "VPN Agent RequestInput %s\n", service);
- __connmanctl_dbus_print(&dict, " ", " = ", "\n");
- fprintf(stdout, "\n");
-
- dbus_message_iter_recurse(&iter, &dict);
+ dbus_message_iter_recurse(iter, &dict);
while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
@@ -536,6 +545,128 @@ static DBusMessage *agent_request_input(DBusConnection *connection,
dbus_message_iter_next(&dict);
}
+}
+
+static DBusMessage *agent_request_input(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct agent_data *request = user_data;
+ DBusMessageIter iter, dict;
+ char *service, *str;
+
+ if (handle_message(message, request, agent_request_input) == false)
+ return NULL;
+
+ dbus_message_iter_init(message, &iter);
+
+ dbus_message_iter_get_basic(&iter, &str);
+ service = strip_path(str);
+
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_recurse(&iter, &dict);
+
+ __connmanctl_save_rl();
+ if (strcmp(request->interface, AGENT_INTERFACE) == 0)
+ fprintf(stdout, "Agent RequestInput %s\n", service);
+ else
+ fprintf(stdout, "VPN Agent RequestInput %s\n", service);
+ __connmanctl_dbus_print(&dict, " ", " = ", "\n");
+ fprintf(stdout, "\n");
+
+ parse_agent_request(request, &iter);
+
+ request->reply = dbus_message_new_method_return(message);
+ dbus_message_iter_init_append(request->reply, &request->iter);
+
+ dbus_message_iter_open_container(&request->iter, DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &request->dict);
+
+ request_input_next(request);
+
+ return NULL;
+}
+
+static void request_authorization_return(char *input, void *user_data)
+{
+ struct agent_data *request = user_data;
+
+ switch (confirm_input(input)) {
+ case 1:
+ request->reply = dbus_message_new_method_return(
+ request->message);
+ dbus_message_iter_init_append(request->reply, &request->iter);
+
+ dbus_message_iter_open_container(&request->iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_VARIANT_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &request->dict);
+ dbus_message_iter_close_container(&request->iter,
+ &request->dict);
+ g_dbus_send_message(agent_connection, request->reply);
+ request->reply = NULL;
+ break;
+ case 0:
+ g_dbus_send_error(agent_connection, request->message,
+ "net.connman.Agent.Error.Rejected", NULL);
+ break;
+ default:
+ g_dbus_send_error(agent_connection, request->message,
+ "net.connman.Agent.Error.Canceled", NULL);
+ break;
+ }
+
+ pending_message_remove(request);
+ pending_command_complete("");
+}
+
+static DBusMessage *
+agent_request_peer_authorization(DBusConnection *connection,
+ DBusMessage *message, void *user_data)
+{
+ struct agent_data *request = user_data;
+ DBusMessageIter iter, dict;
+ char *peer, *str;
+ bool input;
+ int i;
+
+ if (handle_message(message, request, agent_request_peer_authorization)
+ == false)
+ return NULL;
+
+ dbus_message_iter_init(message, &iter);
+
+ dbus_message_iter_get_basic(&iter, &str);
+ peer = strip_path(str);
+
+ dbus_message_iter_next(&iter);
+ dbus_message_iter_recurse(&iter, &dict);
+
+ __connmanctl_save_rl();
+ fprintf(stdout, "Agent RequestPeerAuthorization %s\n", peer);
+ __connmanctl_dbus_print(&dict, " ", " = ", "\n");
+ fprintf(stdout, "\n");
+
+ parse_agent_request(request, &iter);
+
+ for (input = false, i = 0; request->input[i].attribute; i++) {
+ if (request->input[i].requested == true) {
+ input = true;
+ break;
+ }
+ }
+
+ if (!input) {
+ request->message = dbus_message_ref(message);
+ __connmanctl_agent_mode("Accept connection (yes/no)? ",
+ request_authorization_return, request);
+ return NULL;
+ }
request->reply = dbus_message_new_method_return(message);
dbus_message_iter_init_append(request->reply, &request->iter);
@@ -562,11 +693,20 @@ static const GDBusMethodTable agent_methods[] = {
GDBUS_ARGS({ "service", "o" },
{ "error", "s" }),
NULL, agent_report_error) },
+ { GDBUS_ASYNC_METHOD("ReportPeerError",
+ GDBUS_ARGS({ "peer", "o" },
+ { "error", "s" }),
+ NULL, agent_report_peer_error) },
{ GDBUS_ASYNC_METHOD("RequestInput",
GDBUS_ARGS({ "service", "o" },
{ "fields", "a{sv}" }),
GDBUS_ARGS({ "fields", "a{sv}" }),
agent_request_input) },
+ { GDBUS_ASYNC_METHOD("RequestPeerAuthorization",
+ GDBUS_ARGS({ "peer", "o" },
+ { "fields", "a{sv}" }),
+ GDBUS_ARGS({ "fields", "a{sv}" }),
+ agent_request_peer_authorization) },
{ },
};
diff --git a/client/commands.c b/client/commands.c
index 9c01fd5..9208016 100644
--- a/client/commands.c
+++ b/client/commands.c
@@ -31,6 +31,7 @@
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
+#include <ctype.h>
#include <glib.h>
#include <gdbus.h>
@@ -660,6 +661,7 @@ static int connect_return(DBusMessageIter *iter, const char *error,
static int cmd_connect(char *args[], int num, struct connman_option *options)
{
+ const char *iface = "net.connman.Service";
char *path;
if (num > 2)
@@ -671,10 +673,14 @@ static int cmd_connect(char *args[], int num, struct connman_option *options)
if (check_dbus_name(args[1]) == false)
return -EINVAL;
- path = g_strdup_printf("/net/connman/service/%s", args[1]);
+ 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,
- "net.connman.Service", "Connect",
- connect_return, path, NULL, NULL);
+ iface, "Connect", connect_return, path, NULL, NULL);
}
static int disconnect_return(DBusMessageIter *iter, const char *error,
@@ -696,6 +702,7 @@ static int disconnect_return(DBusMessageIter *iter, const char *error,
static int cmd_disconnect(char *args[], int num, struct connman_option *options)
{
+ const char *iface = "net.connman.Service";
char *path;
if (num > 2)
@@ -707,10 +714,15 @@ static int cmd_disconnect(char *args[], int num, struct connman_option *options)
if (check_dbus_name(args[1]) == false)
return -EINVAL;
- path = g_strdup_printf("/net/connman/service/%s", args[1]);
- return __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, path,
- "net.connman.Service", "Disconnect",
- disconnect_return, path, NULL, NULL);
+ 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);
}
static int config_return(DBusMessageIter *iter, const char *error,
@@ -2085,6 +2097,273 @@ static char *lookup_session(const char *text, int state)
return lookup_options(session_options, text, state);
}
+static int peer_service_cb(DBusMessageIter *iter, const char *error,
+ void *user_data)
+{
+ bool registration = GPOINTER_TO_INT(user_data);
+
+ if (error)
+ fprintf(stderr, "Error %s peer service: %s\n",
+ registration ? "registering" : "unregistering", error);
+ else
+ fprintf(stdout, "Peer service %s\n",
+ registration ? "registered" : "unregistered");
+
+ return 0;
+}
+
+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)
+{
+ 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);
+}
+
+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);
+ }
+}
+
+static void peer_service_append(DBusMessageIter *iter, void *user_data)
+{
+ struct _peer_service *service = user_data;
+ dbus_bool_t master;
+
+ __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 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)
+{
+ struct _peer_service *service;
+
+ service = dbus_malloc0(sizeof(*service));
+
+ if (bjr_query_len && bjr_response_len) {
+ service->bjr_query = dbus_malloc0(bjr_query_len);
+ memcpy(service->bjr_query, bjr_query, bjr_query_len);
+ service->bjr_query_len = bjr_query_len;
+
+ service->bjr_response = dbus_malloc0(bjr_response_len);
+ 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);
+ memcpy(service->wfd_ies, wfd_ies, wfd_ies_len);
+ service->wfd_ies_len = wfd_ies_len;
+ } else {
+ dbus_free(service);
+ service = NULL;
+ }
+
+ return service;
+}
+
+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);
+}
+
+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;
+
+ service->master = master;
+
+ ret = __connmanctl_dbus_method_call(connection, "net.connman", "/",
+ "net.connman.Manager", "RegisterPeerService",
+ peer_service_cb, GINT_TO_POINTER(registration),
+ peer_service_append, service);
+
+ free_peer_service(service);
+
+ return ret;
+}
+
+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;
+
+ 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 parse_spec_array(char *command, unsigned char spec[1024])
+{
+ 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 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;
+
+ 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;
+ }
+
+ 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;
+ }
+
+master:
+ if (num == limit) {
+ master = parse_boolean(args[6]);
+ if (master < 0)
+ return -EINVAL;
+ }
+
+ 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);
+ }
+
+ return -EINVAL;
+}
+
static const struct {
const char *cmd;
const char *argument;
@@ -2115,10 +2394,10 @@ static const struct {
{ "scan", "<technology>", NULL, cmd_scan,
"Scans for new services for given technology",
lookup_technology_arg },
- { "connect", "<service>", NULL, cmd_connect,
- "Connect a given service", lookup_service_arg },
- { "disconnect", "<service>", NULL, cmd_disconnect,
- "Disconnect a given service", lookup_service_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 },
{ "config", "<service>", config_options, cmd_config,
"Set service configuration options", lookup_config },
{ "monitor", "[off]", monitor_options, cmd_monitor,
@@ -2131,6 +2410,12 @@ static const struct {
"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,
@@ -2315,6 +2600,11 @@ static void update_services(DBusMessageIter *iter)
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;
}
@@ -2376,6 +2666,11 @@ static void update_peers(DBusMessageIter *iter)
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;
}
@@ -2436,6 +2731,11 @@ static void update_technologies(DBusMessageIter *iter)
static int populate_technology_hash(DBusMessageIter *iter, const char *error,
void *user_data)
{
+ if (error) {
+ fprintf(stderr, "Error getting technologies: %s", error);
+ return 0;
+ }
+
update_technologies(iter);
return 0;
diff --git a/client/dbus_helpers.c b/client/dbus_helpers.c
index 826111f..d905746 100644
--- a/client/dbus_helpers.c
+++ b/client/dbus_helpers.c
@@ -27,7 +27,7 @@
#include "input.h"
#include "dbus_helpers.h"
-#define TIMEOUT 60000
+#define TIMEOUT 120000
void __connmanctl_dbus_print(DBusMessageIter *iter, const char *pre,
const char *dict, const char *sep)
@@ -213,6 +213,9 @@ static int append_variant(DBusMessageIter *iter, const char *property,
case DBUS_TYPE_STRING:
type_str = DBUS_TYPE_STRING_AS_STRING;
break;
+ case DBUS_TYPE_INT32:
+ type_str = DBUS_TYPE_INT32_AS_STRING;
+ break;
default:
return -EOPNOTSUPP;
}