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("");
292 static void request_input_append(const char *attribute, char *value)
294 __connmanctl_dbus_append_dict_entry(&agent_reply.dict, attribute,
295 DBUS_TYPE_STRING, &value);
298 static void request_input_ssid_return(char *input)
305 if (len > 0 && len <= 32) {
306 agent_input[SSID].requested = false;
307 request_input_append(agent_input[SSID].attribute, input);
309 request_input_next();
313 static void request_input_passphrase_return(char *input)
315 /* TBD passphrase length checking */
317 if (input != NULL && strlen(input) > 0) {
318 agent_input[PASSPHRASE].requested = false;
319 request_input_append(agent_input[PASSPHRASE].attribute, input);
321 agent_input[WPS].requested = false;
323 request_input_next();
327 static void request_input_string_return(char *input)
331 for (i = 0; agent_input[i].attribute != NULL; i++) {
332 if (agent_input[i].requested == true) {
333 request_input_append(agent_input[i].attribute, input);
334 agent_input[i].requested = false;
339 request_input_next();
342 static DBusMessage *agent_request_input(DBusConnection *connection,
343 DBusMessage *message, void *user_data)
345 DBusMessageIter iter, dict, entry, variant;
346 char *service, *str, *field;
347 DBusMessageIter dict_entry, field_entry, field_value;
348 char *argument, *value, *attr_type;
352 dbus_message_iter_init(message, &iter);
354 dbus_message_iter_get_basic(&iter, &str);
355 service = strip_path(str);
357 dbus_message_iter_next(&iter);
358 dbus_message_iter_recurse(&iter, &dict);
360 __connmanctl_save_rl();
361 fprintf(stdout, "Agent RequestInput %s\n", service);
362 __connmanctl_dbus_print(&dict, " ", " = ", "\n");
363 fprintf(stdout, "\n");
364 __connmanctl_redraw_rl();
366 dbus_message_iter_recurse(&iter, &dict);
368 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
370 dbus_message_iter_recurse(&dict, &entry);
372 dbus_message_iter_get_basic(&entry, &field);
374 dbus_message_iter_next(&entry);
376 dbus_message_iter_recurse(&entry, &variant);
377 dbus_message_iter_recurse(&variant, &dict_entry);
379 while (dbus_message_iter_get_arg_type(&dict_entry)
380 == DBUS_TYPE_DICT_ENTRY) {
381 dbus_message_iter_recurse(&dict_entry, &field_entry);
383 dbus_message_iter_get_basic(&field_entry, &argument);
385 dbus_message_iter_next(&field_entry);
387 dbus_message_iter_recurse(&field_entry, &field_value);
389 dbus_message_iter_get_basic(&field_value, &value);
391 if (strcmp(argument, "Type") == 0)
392 attr_type = g_strdup(value);
394 dbus_message_iter_next(&dict_entry);
397 for (i = 0; agent_input[i].attribute != NULL; i++) {
398 if (strcmp(field, agent_input[i].attribute) == 0) {
399 agent_input[i].requested = true;
407 dbus_message_iter_next(&dict);
410 agent_connection = connection;
411 agent_reply.reply = dbus_message_new_method_return(message);
412 dbus_message_iter_init_append(agent_reply.reply, &agent_reply.iter);
414 dbus_message_iter_open_container(&agent_reply.iter, DBUS_TYPE_ARRAY,
415 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
416 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_VARIANT_AS_STRING
417 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &agent_reply.dict);
419 request_input_next();
424 static const GDBusMethodTable agent_methods[] = {
425 { GDBUS_METHOD("Release", NULL, NULL, agent_release) },
426 { GDBUS_METHOD("Cancel", NULL, NULL, agent_cancel) },
427 { GDBUS_ASYNC_METHOD("RequestBrowser",
428 GDBUS_ARGS({ "service", "o" },
430 NULL, agent_request_browser) },
431 { GDBUS_ASYNC_METHOD("ReportError",
432 GDBUS_ARGS({ "service", "o" },
434 NULL, agent_report_error) },
435 { GDBUS_ASYNC_METHOD("RequestInput",
436 GDBUS_ARGS({ "service", "o" },
437 { "fields", "a{sv}" }),
438 GDBUS_ARGS({ "fields", "a{sv}" }),
439 agent_request_input) },
443 static int agent_register_return(DBusMessageIter *iter, const char *error,
446 DBusConnection *connection = user_data;
449 g_dbus_unregister_interface(connection, agent_path(),
451 fprintf(stderr, "Error registering Agent: %s\n", error);
455 agent_registered = true;
456 fprintf(stdout, "Agent registered\n");
461 int __connmanctl_agent_register(DBusConnection *connection)
463 char *path = agent_path();
466 if (agent_registered == true) {
467 fprintf(stderr, "Agent already registered\n");
471 if (g_dbus_register_interface(connection, path,
472 AGENT_INTERFACE, agent_methods,
473 NULL, NULL, connection,
475 fprintf(stderr, "Error: Failed to register Agent callbacks\n");
479 result = __connmanctl_dbus_method_call(connection, "/",
480 "net.connman.Manager", "RegisterAgent",
481 agent_register_return, connection,
482 DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
484 if (result != -EINPROGRESS) {
485 g_dbus_unregister_interface(connection, agent_path(),
488 fprintf(stderr, "Error: Failed to register Agent\n");
494 static int agent_unregister_return(DBusMessageIter *iter, const char *error,
498 fprintf(stderr, "Error unregistering Agent: %s\n", error);
502 agent_registered = false;
503 fprintf(stdout, "Agent unregistered\n");
508 int __connmanctl_agent_unregister(DBusConnection *connection)
510 char *path = agent_path();
513 if (agent_registered == false) {
514 fprintf(stderr, "Agent not registered\n");
518 g_dbus_unregister_interface(connection, agent_path(), AGENT_INTERFACE);
520 result = __connmanctl_dbus_method_call(connection, "/",
521 "net.connman.Manager", "UnregisterAgent",
522 agent_unregister_return, NULL,
523 DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
525 if (result != -EINPROGRESS)
526 fprintf(stderr, "Error: Failed to unregister Agent\n");