+ 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);