| /* |
| * |
| * Connection Manager |
| * |
| * Copyright (C) 2013 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 |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| * |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #endif |
| |
| #include <stdio.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| #include <errno.h> |
| #include <stdbool.h> |
| #include <string.h> |
| #include <ctype.h> |
| |
| #include <gdbus.h> |
| |
| #include "input.h" |
| #include "dbus_helpers.h" |
| #include "agent.h" |
| |
| #define AGENT_INTERFACE "net.connman.Agent" |
| #define VPN_AGENT_INTERFACE "net.connman.vpn.Agent" |
| |
| static DBusConnection *agent_connection; |
| |
| struct agent_input_data { |
| const char *attribute; |
| bool requested; |
| char *prompt; |
| connmanctl_input_func_t func; |
| }; |
| |
| struct agent_data { |
| struct agent_input_data *input; |
| char *interface; |
| bool registered; |
| DBusMessage *message; |
| DBusMessage *reply; |
| DBusMessageIter iter; |
| DBusMessageIter dict; |
| GDBusMethodFunction pending_function; |
| }; |
| |
| static void request_input_ssid_return(char *input, void *user_data); |
| static void request_input_passphrase_return(char *input, void *user_data); |
| static void request_input_string_return(char *input, void *user_data); |
| |
| enum requestinput { |
| SSID = 0, |
| IDENTITY = 1, |
| PASSPHRASE = 2, |
| WPS = 3, |
| WISPR_USERNAME = 4, |
| WISPR_PASSPHRASE = 5, |
| REQUEST_INPUT_MAX = 6, |
| }; |
| |
| static struct agent_input_data agent_input_handler[] = { |
| { "Name", false, "Hidden SSID name? ", request_input_ssid_return }, |
| { "Identity", false, "EAP username? ", request_input_string_return }, |
| { "Passphrase", false, "Passphrase? ", |
| request_input_passphrase_return }, |
| { "WPS", false, "WPS PIN (empty line for pushbutton)? " , |
| request_input_string_return }, |
| { "Username", false, "WISPr username? ", request_input_string_return }, |
| { "Password", false, "WISPr password? ", request_input_string_return }, |
| { }, |
| }; |
| |
| static struct agent_data agent_request = { |
| agent_input_handler, |
| AGENT_INTERFACE, |
| }; |
| |
| static struct agent_input_data vpnagent_input_handler[] = { |
| { "OpenConnect.Cookie", false, "OpenConnect Cookie? ", |
| request_input_string_return }, |
| { "OpenConnect.ServerCert", false, |
| "OpenConnect server certificate hash? ", |
| request_input_string_return }, |
| { "OpenConnect.VPNHost", false, "OpenConnect VPN server? ", |
| request_input_string_return }, |
| { "Username", false, "VPN username? ", request_input_string_return }, |
| { "Password", false, "VPN password? ", request_input_string_return }, |
| { }, |
| }; |
| |
| static struct agent_data vpn_agent_request = { |
| vpnagent_input_handler, |
| VPN_AGENT_INTERFACE, |
| }; |
| |
| static int confirm_input(char *input) |
| { |
| int i; |
| |
| if (!input) |
| return -1; |
| |
| for (i = 0; input[i] != '\0'; i++) |
| if (isspace(input[i]) == 0) |
| break; |
| |
| if (strcasecmp(&input[i], "yes") == 0 || |
| strcasecmp(&input[i], "y") == 0) |
| return 1; |
| |
| if (strcasecmp(&input[i], "no") == 0 || |
| strcasecmp(&input[i], "n") == 0) |
| return 0; |
| |
| return -1; |
| } |
| |
| static char *strip_path(char *path) |
| { |
| char *name = strrchr(path, '/'); |
| if (name) |
| name++; |
| else |
| name = path; |
| |
| return name; |
| } |
| |
| static char *agent_path(void) |
| { |
| static char *path = NULL; |
| |
| if (!path) |
| path = g_strdup_printf("/net/connman/connmanctl%d", getpid()); |
| |
| return path; |
| } |
| |
| static void pending_message_remove(struct agent_data *request) |
| { |
| if (request->message) { |
| dbus_message_unref(request->message); |
| request->message = NULL; |
| } |
| |
| if (request->reply) { |
| dbus_message_unref(request->reply); |
| request->reply = NULL; |
| } |
| } |
| |
| static void pending_command_complete(char *message) |
| { |
| struct agent_data *next_request = NULL; |
| DBusMessage *pending_message; |
| GDBusMethodFunction pending_function; |
| |
| __connmanctl_save_rl(); |
| |
| fprintf(stdout, "%s", message); |
| |
| __connmanctl_redraw_rl(); |
| |
| if (__connmanctl_is_interactive() == true) |
| __connmanctl_command_mode(); |
| else |
| __connmanctl_agent_mode("", NULL, NULL); |
| |
| if (agent_request.message) |
| next_request = &agent_request; |
| else if (vpn_agent_request.message) |
| next_request = &vpn_agent_request; |
| |
| if (!next_request) |
| return; |
| |
| pending_message = next_request->message; |
| pending_function = next_request->pending_function; |
| next_request->pending_function = NULL; |
| |
| pending_function(agent_connection, next_request->message, |
| next_request); |
| |
| dbus_message_unref(pending_message); |
| } |
| |
| static bool handle_message(DBusMessage *message, struct agent_data *request, |
| GDBusMethodFunction function) |
| { |
| if (!agent_request.pending_function && |
| !vpn_agent_request.pending_function) |
| return true; |
| |
| request->message = dbus_message_ref(message); |
| request->pending_function = function; |
| |
| return false; |
| } |
| |
| static DBusMessage *agent_release(DBusConnection *connection, |
| DBusMessage *message, void *user_data) |
| { |
| struct agent_data *request = user_data; |
| |
| if (handle_message(message, request, agent_release) == false) |
| return NULL; |
| |
| g_dbus_unregister_interface(connection, agent_path(), |
| request->interface); |
| request->registered = false; |
| |
| pending_message_remove(request); |
| |
| if (strcmp(request->interface, AGENT_INTERFACE) == 0) |
| pending_command_complete("Agent unregistered by ConnMan\n"); |
| else |
| pending_command_complete("VPN Agent unregistered by ConnMan " |
| "VPNd\n"); |
| |
| if (__connmanctl_is_interactive() == false) |
| __connmanctl_quit(); |
| |
| return dbus_message_new_method_return(message); |
| } |
| |
| static DBusMessage *agent_cancel(DBusConnection *connection, |
| DBusMessage *message, void *user_data) |
| { |
| struct agent_data *request = user_data; |
| |
| if (handle_message(message, request, agent_cancel) == false) |
| return NULL; |
| |
| pending_message_remove(request); |
| |
| if (strcmp(request->interface, AGENT_INTERFACE) == 0) |
| pending_command_complete("Agent request cancelled by " |
| "ConnMan\n"); |
| else |
| pending_command_complete("VPN Agent request cancelled by " |
| "ConnMan VPNd\n"); |
| |
| return dbus_message_new_method_return(message); |
| } |
| |
| static void request_browser_return(char *input, void *user_data) |
| { |
| struct agent_data *request = user_data; |
| |
| switch (confirm_input(input)) { |
| case 1: |
| g_dbus_send_reply(agent_connection, request->message, |
| DBUS_TYPE_INVALID); |
| break; |
| case 0: |
| g_dbus_send_error(agent_connection, request->message, |
| "net.connman.Agent.Error.Canceled", NULL); |
| break; |
| default: |
| return; |
| } |
| |
| pending_message_remove(request); |
| pending_command_complete(""); |
| } |
| |
| static DBusMessage *agent_request_browser(DBusConnection *connection, |
| DBusMessage *message, void *user_data) |
| { |
| struct agent_data *request = user_data; |
| DBusMessageIter iter; |
| char *service, *url; |
| |
| if (handle_message(message, request, agent_request_browser) == false) |
| return NULL; |
| |
| dbus_message_iter_init(message, &iter); |
| |
| dbus_message_iter_get_basic(&iter, &service); |
| dbus_message_iter_next(&iter); |
| dbus_message_iter_get_basic(&iter, &url); |
| |
| __connmanctl_save_rl(); |
| fprintf(stdout, "Agent RequestBrowser %s\n", strip_path(service)); |
| fprintf(stdout, " %s\n", url); |
| __connmanctl_redraw_rl(); |
| |
| request->message = dbus_message_ref(message); |
| __connmanctl_agent_mode("Connected (yes/no)? ", |
| request_browser_return, request); |
| |
| return NULL; |
| } |
| |
| static void report_error_return(char *input, void *user_data) |
| { |
| struct agent_data *request = user_data; |
| |
| switch (confirm_input(input)) { |
| case 1: |
| if (strcmp(request->interface, AGENT_INTERFACE) == 0) |
| g_dbus_send_error(agent_connection, request->message, |
| "net.connman.Agent.Error.Retry", NULL); |
| else |
| g_dbus_send_error(agent_connection, request->message, |
| "net.connman.vpn.Agent.Error.Retry", |
| NULL); |
| break; |
| case 0: |
| g_dbus_send_reply(agent_connection, request->message, |
| DBUS_TYPE_INVALID); |
| break; |
| default: |
| return; |
| } |
| |
| pending_message_remove(request); |
| pending_command_complete(""); |
| } |
| |
| static DBusMessage *agent_report_error(DBusConnection *connection, |
| DBusMessage *message, void *user_data) |
| { |
| struct agent_data *request = user_data; |
| DBusMessageIter iter; |
| char *path, *service, *error; |
| |
| if (handle_message(message, request, agent_report_error) == false) |
| return NULL; |
| |
| dbus_message_iter_init(message, &iter); |
| |
| dbus_message_iter_get_basic(&iter, &path); |
| service = strip_path(path); |
| |
| dbus_message_iter_next(&iter); |
| dbus_message_iter_get_basic(&iter, &error); |
| |
| __connmanctl_save_rl(); |
| if (strcmp(request->interface, AGENT_INTERFACE) == 0) |
| fprintf(stdout, "Agent ReportError %s\n", service); |
| else |
| fprintf(stdout, "VPN Agent ReportError %s\n", service); |
| 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 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; |
| |
| for (i = 0; request->input[i].attribute; i++) { |
| if (request->input[i].requested == true) { |
| if (request->input[i].func) |
| __connmanctl_agent_mode(request->input[i].prompt, |
| request->input[i].func, |
| request); |
| else |
| request->input[i].requested = false; |
| return; |
| } |
| } |
| |
| dbus_message_iter_close_container(&request->iter, &request->dict); |
| |
| g_dbus_send_message(agent_connection, request->reply); |
| request->reply = NULL; |
| |
| pending_message_remove(request); |
| pending_command_complete(""); |
| |
| __connmanctl_redraw_rl(); |
| } |
| |
| static void request_input_append(struct agent_data *request, |
| const char *attribute, char *value) |
| { |
| __connmanctl_dbus_append_dict_entry(&request->dict, attribute, |
| DBUS_TYPE_STRING, &value); |
| } |
| |
| static void request_input_ssid_return(char *input, |
| void *user_data) |
| { |
| struct agent_data *request = user_data; |
| int len = 0; |
| |
| if (input) |
| len = strlen(input); |
| |
| if (len > 0 && len <= 32) { |
| request->input[SSID].requested = false; |
| request_input_append(request, request->input[SSID].attribute, |
| input); |
| |
| request_input_next(request); |
| } |
| } |
| |
| static void request_input_passphrase_return(char *input, void *user_data) |
| { |
| struct agent_data *request = user_data; |
| int len = 0; |
| |
| /* TBD passphrase length checking */ |
| |
| if (input) |
| len = strlen(input); |
| |
| if (len == 0 && request->input[WPS].requested == false) |
| return; |
| |
| request->input[PASSPHRASE].requested = false; |
| |
| if (len > 0) { |
| request_input_append(request, |
| request->input[PASSPHRASE].attribute, input); |
| |
| request->input[WPS].requested = false; |
| } |
| |
| request_input_next(request); |
| } |
| |
| static void request_input_string_return(char *input, void *user_data) |
| { |
| struct agent_data *request = user_data; |
| int i; |
| |
| for (i = 0; request->input[i].attribute; i++) { |
| if (request->input[i].requested == true) { |
| request_input_append(request, |
| request->input[i].attribute, input); |
| request->input[i].requested = false; |
| break; |
| } |
| } |
| |
| request_input_next(request); |
| } |
| |
| static void parse_agent_request(struct agent_data *request, |
| DBusMessageIter *iter) |
| { |
| DBusMessageIter dict, entry, variant, dict_entry; |
| DBusMessageIter field_entry, field_value; |
| char *field, *argument, *value; |
| char *attr_type = NULL; |
| int i; |
| |
| dbus_message_iter_recurse(iter, &dict); |
| |
| while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { |
| |
| dbus_message_iter_recurse(&dict, &entry); |
| |
| dbus_message_iter_get_basic(&entry, &field); |
| |
| dbus_message_iter_next(&entry); |
| |
| dbus_message_iter_recurse(&entry, &variant); |
| dbus_message_iter_recurse(&variant, &dict_entry); |
| |
| while (dbus_message_iter_get_arg_type(&dict_entry) |
| == DBUS_TYPE_DICT_ENTRY) { |
| dbus_message_iter_recurse(&dict_entry, &field_entry); |
| |
| dbus_message_iter_get_basic(&field_entry, &argument); |
| |
| dbus_message_iter_next(&field_entry); |
| |
| dbus_message_iter_recurse(&field_entry, &field_value); |
| |
| if (strcmp(argument, "Type") == 0) { |
| dbus_message_iter_get_basic(&field_value, |
| &value); |
| attr_type = g_strdup(value); |
| } |
| |
| dbus_message_iter_next(&dict_entry); |
| } |
| |
| for (i = 0; request->input[i].attribute; i++) { |
| if (strcmp(field, request->input[i].attribute) == 0) { |
| request->input[i].requested = true; |
| break; |
| } |
| } |
| |
| g_free(attr_type); |
| attr_type = NULL; |
| |
| 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); |
| |
| 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 const GDBusMethodTable agent_methods[] = { |
| { GDBUS_ASYNC_METHOD("Release", NULL, NULL, agent_release) }, |
| { GDBUS_ASYNC_METHOD("Cancel", NULL, NULL, agent_cancel) }, |
| { GDBUS_ASYNC_METHOD("RequestBrowser", |
| GDBUS_ARGS({ "service", "o" }, |
| { "url", "s" }), |
| NULL, agent_request_browser) }, |
| { GDBUS_ASYNC_METHOD("ReportError", |
| 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) }, |
| { }, |
| }; |
| |
| static int agent_register_return(DBusMessageIter *iter, const char *error, |
| void *user_data) |
| { |
| DBusConnection *connection = user_data; |
| |
| if (error) { |
| g_dbus_unregister_interface(connection, agent_path(), |
| AGENT_INTERFACE); |
| fprintf(stderr, "Error registering Agent: %s\n", error); |
| return 0; |
| } |
| |
| agent_request.registered = true; |
| fprintf(stdout, "Agent registered\n"); |
| |
| return -EINPROGRESS; |
| } |
| |
| static void append_path(DBusMessageIter *iter, void *user_data) |
| { |
| const char *path = user_data; |
| |
| dbus_message_iter_append_basic(iter, DBUS_TYPE_OBJECT_PATH, &path); |
| } |
| |
| int __connmanctl_agent_register(DBusConnection *connection) |
| { |
| char *path = agent_path(); |
| int result; |
| |
| if (agent_request.registered == true) { |
| fprintf(stderr, "Agent already registered\n"); |
| return -EALREADY; |
| } |
| |
| agent_connection = connection; |
| |
| if (!g_dbus_register_interface(connection, path, |
| AGENT_INTERFACE, agent_methods, |
| NULL, NULL, &agent_request, NULL)) { |
| fprintf(stderr, "Error: Failed to register Agent callbacks\n"); |
| return 0; |
| } |
| |
| result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, |
| CONNMAN_PATH, "net.connman.Manager", "RegisterAgent", |
| agent_register_return, connection, append_path, path); |
| |
| if (result != -EINPROGRESS) { |
| g_dbus_unregister_interface(connection, agent_path(), |
| AGENT_INTERFACE); |
| |
| fprintf(stderr, "Error: Failed to register Agent\n"); |
| } |
| |
| return result; |
| } |
| |
| static int agent_unregister_return(DBusMessageIter *iter, const char *error, |
| void *user_data) |
| { |
| if (error) { |
| fprintf(stderr, "Error unregistering Agent: %s\n", error); |
| return 0; |
| } |
| |
| agent_request.registered = false; |
| fprintf(stdout, "Agent unregistered\n"); |
| |
| return 0; |
| } |
| |
| int __connmanctl_agent_unregister(DBusConnection *connection) |
| { |
| char *path = agent_path(); |
| int result; |
| |
| if (agent_request.registered == false) { |
| fprintf(stderr, "Agent not registered\n"); |
| return -EALREADY; |
| } |
| |
| g_dbus_unregister_interface(connection, agent_path(), AGENT_INTERFACE); |
| |
| result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE, |
| CONNMAN_PATH, "net.connman.Manager", "UnregisterAgent", |
| agent_unregister_return, NULL, append_path, path); |
| |
| if (result != -EINPROGRESS) |
| fprintf(stderr, "Error: Failed to unregister Agent\n"); |
| |
| return result; |
| } |
| |
| static const GDBusMethodTable vpn_agent_methods[] = { |
| { GDBUS_ASYNC_METHOD("Release", NULL, NULL, agent_release) }, |
| { GDBUS_ASYNC_METHOD("Cancel", NULL, NULL, agent_cancel) }, |
| { GDBUS_ASYNC_METHOD("ReportError", |
| GDBUS_ARGS({ "service", "o" }, |
| { "error", "s" }), |
| NULL, agent_report_error) }, |
| { GDBUS_ASYNC_METHOD("RequestInput", |
| GDBUS_ARGS({ "service", "o" }, |
| { "fields", "a{sv}" }), |
| GDBUS_ARGS({ "fields", "a{sv}" }), |
| agent_request_input) }, |
| { }, |
| }; |
| |
| static int vpn_agent_register_return(DBusMessageIter *iter, const char *error, |
| void *user_data) |
| { |
| DBusConnection *connection = user_data; |
| |
| if (error) { |
| g_dbus_unregister_interface(connection, agent_path(), |
| VPN_AGENT_INTERFACE); |
| fprintf(stderr, "Error registering VPN Agent: %s\n", error); |
| return 0; |
| } |
| |
| vpn_agent_request.registered = true; |
| fprintf(stdout, "VPN Agent registered\n"); |
| |
| return -EINPROGRESS; |
| } |
| |
| int __connmanctl_vpn_agent_register(DBusConnection *connection) |
| { |
| char *path = agent_path(); |
| int result; |
| |
| if (vpn_agent_request.registered == true) { |
| fprintf(stderr, "VPN Agent already registered\n"); |
| return -EALREADY; |
| } |
| |
| agent_connection = connection; |
| |
| if (!g_dbus_register_interface(connection, path, |
| VPN_AGENT_INTERFACE, vpn_agent_methods, |
| NULL, NULL, &vpn_agent_request, NULL)) { |
| fprintf(stderr, "Error: Failed to register VPN Agent " |
| "callbacks\n"); |
| return 0; |
| } |
| |
| result = __connmanctl_dbus_method_call(connection, VPN_SERVICE, |
| VPN_PATH, "net.connman.vpn.Manager", "RegisterAgent", |
| vpn_agent_register_return, connection, append_path, |
| path); |
| |
| if (result != -EINPROGRESS) { |
| g_dbus_unregister_interface(connection, agent_path(), |
| VPN_AGENT_INTERFACE); |
| |
| fprintf(stderr, "Error: Failed to register VPN Agent\n"); |
| } |
| |
| return result; |
| } |
| |
| static int vpn_agent_unregister_return(DBusMessageIter *iter, |
| const char *error, void *user_data) |
| { |
| if (error) { |
| fprintf(stderr, "Error unregistering VPN Agent: %s\n", error); |
| return 0; |
| } |
| |
| vpn_agent_request.registered = false; |
| fprintf(stdout, "VPN Agent unregistered\n"); |
| |
| return 0; |
| } |
| |
| int __connmanctl_vpn_agent_unregister(DBusConnection *connection) |
| { |
| char *path = agent_path(); |
| int result; |
| |
| if (vpn_agent_request.registered == false) { |
| fprintf(stderr, "VPN Agent not registered\n"); |
| return -EALREADY; |
| } |
| |
| g_dbus_unregister_interface(connection, agent_path(), |
| VPN_AGENT_INTERFACE); |
| |
| result = __connmanctl_dbus_method_call(connection, VPN_SERVICE, |
| VPN_PATH, "net.connman.vpn.Manager", "UnregisterAgent", |
| vpn_agent_unregister_return, NULL, append_path, path); |
| |
| if (result != -EINPROGRESS) |
| fprintf(stderr, "Error: Failed to unregister VPN Agent\n"); |
| |
| return result; |
| } |