5 * Copyright (C) 2013 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
28 #include <sys/types.h>
38 #include "dbus_helpers.h"
41 static bool agent_registered = false;
42 static DBusMessage *agent_message = NULL;
49 #define AGENT_INTERFACE "net.connman.Agent"
51 static void request_input_ssid_return(char *input);
52 static void request_input_passphrase_return(char *input);
53 static void request_input_string_return(char *input);
55 static int confirm_input(char *input)
62 for (i = 0; input[i] != '\0'; i++)
63 if (isspace(input[i]) == 0)
66 if (strcasecmp(&input[i], "yes") == 0 ||
67 strcasecmp(&input[i], "y") == 0)
70 if (strcasecmp(&input[i], "no") == 0 ||
71 strcasecmp(&input[i], "n") == 0)
77 static char *strip_path(char *path)
79 char *name = strrchr(path, '/');
88 static char *agent_path(void)
90 static char *path = NULL;
93 path = g_strdup_printf("/net/connman/connmanctl%d", getpid());
98 static void pending_message_remove()
100 if (agent_message != NULL) {
101 dbus_message_unref(agent_message);
102 agent_message = NULL;
105 if (agent_reply.reply != NULL) {
106 dbus_message_unref(agent_reply.reply);
107 agent_reply.reply = NULL;
111 static void pending_command_complete(char *message)
113 __connmanctl_save_rl();
115 fprintf(stdout, "%s", message);
117 __connmanctl_redraw_rl();
119 if (__connmanctl_is_interactive() == true)
120 __connmanctl_command_mode();
122 __connmanctl_agent_mode("", NULL);
125 static DBusMessage *agent_release(DBusConnection *connection,
126 DBusMessage *message, void *user_data)
128 g_dbus_unregister_interface(connection, agent_path(), AGENT_INTERFACE);
129 agent_registered = false;
131 pending_message_remove();
132 pending_command_complete("Agent unregistered by ConnMan\n");
134 if (__connmanctl_is_interactive() == false)
137 return dbus_message_new_method_return(message);
140 static DBusMessage *agent_cancel(DBusConnection *connection,
141 DBusMessage *message, void *user_data)
143 pending_message_remove();
144 pending_command_complete("Agent request cancelled by ConnMan\n");
146 return dbus_message_new_method_return(message);
149 static DBusConnection *agent_connection = NULL;
151 static void request_browser_return(char *input)
153 switch (confirm_input(input)) {
155 g_dbus_send_reply(agent_connection, agent_message,
159 g_dbus_send_error(agent_connection, agent_message,
160 "net.connman.Agent.Error.Canceled", NULL);
166 pending_message_remove();
167 pending_command_complete("");
170 static DBusMessage *agent_request_browser(DBusConnection *connection,
171 DBusMessage *message, void *user_data)
173 DBusMessageIter iter;
176 dbus_message_iter_init(message, &iter);
178 dbus_message_iter_get_basic(&iter, &service);
179 dbus_message_iter_next(&iter);
180 dbus_message_iter_get_basic(&iter, &url);
182 __connmanctl_save_rl();
183 fprintf(stdout, "Agent RequestBrowser %s\n", strip_path(service));
184 fprintf(stdout, " %s\n", url);
185 __connmanctl_redraw_rl();
187 agent_connection = connection;
188 agent_message = dbus_message_ref(message);
189 __connmanctl_agent_mode("Connected (yes/no)? ",
190 request_browser_return);
195 static void report_error_return(char *input)
197 switch (confirm_input(input)) {
199 g_dbus_send_error(agent_connection, agent_message,
200 "net.connman.Agent.Error.Retry", NULL);
203 g_dbus_send_reply(agent_connection, agent_message,
210 pending_message_remove();
211 pending_command_complete("");
214 static DBusMessage *agent_report_error(DBusConnection *connection,
215 DBusMessage *message, void *user_data)
217 DBusMessageIter iter;
218 char *path, *service, *error;
220 dbus_message_iter_init(message, &iter);
222 dbus_message_iter_get_basic(&iter, &path);
223 service = strip_path(path);
225 dbus_message_iter_next(&iter);
226 dbus_message_iter_get_basic(&iter, &error);
228 __connmanctl_save_rl();
229 fprintf(stdout, "Agent ReportError %s\n", service);
230 fprintf(stdout, " %s\n", error);
231 __connmanctl_redraw_rl();
233 agent_connection = connection;
234 agent_message = dbus_message_ref(message);
235 __connmanctl_agent_mode("Retry (yes/no)? ", report_error_return);
246 WISPR_PASSPHRASE = 5,
247 REQUEST_INPUT_MAX = 6,
251 const char *attribute;
254 connmanctl_input_func_t *func;
256 { "Name", false, "Hidden SSID name? ", request_input_ssid_return },
257 { "Identity", false, "EAP username? ", request_input_string_return },
258 { "Passphrase", false, "Passphrase? ",
259 request_input_passphrase_return },
260 { "WPS", false, "WPS PIN (empty line for pushbutton)? " ,
261 request_input_string_return },
262 { "Username", false, "WISPr username? ", request_input_string_return },
263 { "Password", false, "WISPr password? ", request_input_string_return },
267 static void request_input_next(void)
271 for (i = 0; agent_input[i].attribute != NULL; i++) {
272 if (agent_input[i].requested == true) {
273 if(agent_input[i].func != NULL)
274 __connmanctl_agent_mode(agent_input[i].prompt,
275 agent_input[i].func);
277 agent_input[i].requested = false;
282 dbus_message_iter_close_container(&agent_reply.iter,
285 g_dbus_send_message(agent_connection, agent_reply.reply);
286 agent_reply.reply = NULL;
288 pending_message_remove();
289 pending_command_complete("");
291 __connmanctl_redraw_rl();
294 static void request_input_append(const char *attribute, char *value)
296 __connmanctl_dbus_append_dict_entry(&agent_reply.dict, attribute,
297 DBUS_TYPE_STRING, &value);
300 static void request_input_ssid_return(char *input)
307 if (len > 0 && len <= 32) {
308 agent_input[SSID].requested = false;
309 request_input_append(agent_input[SSID].attribute, input);
311 request_input_next();
315 static void request_input_passphrase_return(char *input)
317 /* TBD passphrase length checking */
319 if (input != NULL && strlen(input) > 0) {
320 agent_input[PASSPHRASE].requested = false;
321 request_input_append(agent_input[PASSPHRASE].attribute, input);
323 agent_input[WPS].requested = false;
325 request_input_next();
329 static void request_input_string_return(char *input)
333 for (i = 0; agent_input[i].attribute != NULL; i++) {
334 if (agent_input[i].requested == true) {
335 request_input_append(agent_input[i].attribute, input);
336 agent_input[i].requested = false;
341 request_input_next();
344 static DBusMessage *agent_request_input(DBusConnection *connection,
345 DBusMessage *message, void *user_data)
347 DBusMessageIter iter, dict, entry, variant;
348 char *service, *str, *field;
349 DBusMessageIter dict_entry, field_entry, field_value;
350 char *argument, *value, *attr_type;
354 dbus_message_iter_init(message, &iter);
356 dbus_message_iter_get_basic(&iter, &str);
357 service = strip_path(str);
359 dbus_message_iter_next(&iter);
360 dbus_message_iter_recurse(&iter, &dict);
362 __connmanctl_save_rl();
363 fprintf(stdout, "Agent RequestInput %s\n", service);
364 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
365 fprintf(stdout, "\n");
367 dbus_message_iter_recurse(&iter, &dict);
369 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
371 dbus_message_iter_recurse(&dict, &entry);
373 dbus_message_iter_get_basic(&entry, &field);
375 dbus_message_iter_next(&entry);
377 dbus_message_iter_recurse(&entry, &variant);
378 dbus_message_iter_recurse(&variant, &dict_entry);
380 while (dbus_message_iter_get_arg_type(&dict_entry)
381 == DBUS_TYPE_DICT_ENTRY) {
382 dbus_message_iter_recurse(&dict_entry, &field_entry);
384 dbus_message_iter_get_basic(&field_entry, &argument);
386 dbus_message_iter_next(&field_entry);
388 dbus_message_iter_recurse(&field_entry, &field_value);
390 if (strcmp(argument, "Type") == 0) {
391 dbus_message_iter_get_basic(&field_value,
393 attr_type = g_strdup(value);
396 dbus_message_iter_next(&dict_entry);
399 for (i = 0; agent_input[i].attribute != NULL; i++) {
400 if (strcmp(field, agent_input[i].attribute) == 0) {
401 agent_input[i].requested = true;
409 dbus_message_iter_next(&dict);
412 agent_connection = connection;
413 agent_reply.reply = dbus_message_new_method_return(message);
414 dbus_message_iter_init_append(agent_reply.reply, &agent_reply.iter);
416 dbus_message_iter_open_container(&agent_reply.iter, DBUS_TYPE_ARRAY,
417 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
418 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
419 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &agent_reply.dict);
421 request_input_next();
426 static const GDBusMethodTable agent_methods[] = {
427 { GDBUS_METHOD("Release", NULL, NULL, agent_release) },
428 { GDBUS_METHOD("Cancel", NULL, NULL, agent_cancel) },
429 { GDBUS_ASYNC_METHOD("RequestBrowser",
430 GDBUS_ARGS({ "service", "o" },
432 NULL, agent_request_browser) },
433 { GDBUS_ASYNC_METHOD("ReportError",
434 GDBUS_ARGS({ "service", "o" },
436 NULL, agent_report_error) },
437 { GDBUS_ASYNC_METHOD("RequestInput",
438 GDBUS_ARGS({ "service", "o" },
439 { "fields", "a{sv}" }),
440 GDBUS_ARGS({ "fields", "a{sv}" }),
441 agent_request_input) },
445 static int agent_register_return(DBusMessageIter *iter, const char *error,
448 DBusConnection *connection = user_data;
451 g_dbus_unregister_interface(connection, agent_path(),
453 fprintf(stderr, "Error registering Agent: %s\n", error);
457 agent_registered = true;
458 fprintf(stdout, "Agent registered\n");
463 int __connmanctl_agent_register(DBusConnection *connection)
465 char *path = agent_path();
468 if (agent_registered == true) {
469 fprintf(stderr, "Agent already registered\n");
473 if (g_dbus_register_interface(connection, path,
474 AGENT_INTERFACE, agent_methods,
475 NULL, NULL, connection,
477 fprintf(stderr, "Error: Failed to register Agent callbacks\n");
481 result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
482 CONNMAN_PATH, "net.connman.Manager", "RegisterAgent",
483 agent_register_return, connection,
484 DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
486 if (result != -EINPROGRESS) {
487 g_dbus_unregister_interface(connection, agent_path(),
490 fprintf(stderr, "Error: Failed to register Agent\n");
496 static int agent_unregister_return(DBusMessageIter *iter, const char *error,
500 fprintf(stderr, "Error unregistering Agent: %s\n", error);
504 agent_registered = false;
505 fprintf(stdout, "Agent unregistered\n");
510 int __connmanctl_agent_unregister(DBusConnection *connection)
512 char *path = agent_path();
515 if (agent_registered == false) {
516 fprintf(stderr, "Agent not registered\n");
520 g_dbus_unregister_interface(connection, agent_path(), AGENT_INTERFACE);
522 result = __connmanctl_dbus_method_call(connection, CONNMAN_SERVICE,
523 CONNMAN_PATH, "net.connman.Manager", "UnregisterAgent",
524 agent_unregister_return, NULL,
525 DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
527 if (result != -EINPROGRESS)
528 fprintf(stderr, "Error: Failed to unregister Agent\n");