From cea97a04f9527f026c3c3570f2c071c459513393 Mon Sep 17 00:00:00 2001 From: Paul Stewart Date: Mon, 11 Nov 2013 12:13:55 -0800 Subject: [PATCH] dbus_new: Add DBus TDLS methods Add DBus methods for TDLS operations similar to those available for the control interface. This includes Discover, Setup, and Teardown commands. While here, add a method to query the TDLS link status and add a DBus method for it. Tested with CONFIG_TDLS enabled, on a TDLS-enabled host and peer capable of TDLS: dbus-send --system --dest=fi.w1.wpa_supplicant1 --print-reply \ /fi/w1/wpa_supplicant1/Interfaces/0 \ fi.w1.wpa_supplicant1.Interface.TDLSStatus string: yields: string "peer does not exist" dbus-send --system --dest=fi.w1.wpa_supplicant1 --print-reply \ /fi/w1/wpa_supplicant1/Interfaces/0 \ fi.w1.wpa_supplicant1.Interface.TDLSDiscover string: yields no error dbus-send --system --dest=fi.w1.wpa_supplicant1 --print-reply \ /fi/w1/wpa_supplicant1/Interfaces/0 \ fi.w1.wpa_supplicant1.Interface.TDLSSetup string: yields no error dbus-send --system --dest=fi.w1.wpa_supplicant1 --print-reply \ /fi/w1/wpa_supplicant1/Interfaces/0 \ fi.w1.wpa_supplicant1.Interface.TDLSStatus string: yields: string "connected" after TDLS completes dbus-send --system --dest=fi.w1.wpa_supplicant1 --print-reply \ /fi/w1/wpa_supplicant1/Interfaces/0 \ fi.w1.wpa_supplicant1.Interface.TDLSTeardown string: yields no error dbus-send --system --dest=fi.w1.wpa_supplicant1 --print-reply \ /fi/w1/wpa_supplicant1/Interfaces/0 \ fi.w1.wpa_supplicant1.Interface.TDLSStatus string: yields: string "peer not connected" Signed-hostap: Paul Stewart --- src/rsn_supp/tdls.c | 22 ++++ src/rsn_supp/wpa.h | 1 + wpa_supplicant/dbus/dbus_new.c | 31 +++++ wpa_supplicant/dbus/dbus_new_handlers.c | 164 ++++++++++++++++++++++++ wpa_supplicant/dbus/dbus_new_handlers.h | 9 ++ 5 files changed, 227 insertions(+) diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c index e911ad0f4..616997f25 100644 --- a/src/rsn_supp/tdls.c +++ b/src/rsn_supp/tdls.c @@ -797,6 +797,28 @@ void wpa_tdls_disable_link(struct wpa_sm *sm, const u8 *addr) } +const char * wpa_tdls_get_link_status(struct wpa_sm *sm, const u8 *addr) +{ + struct wpa_tdls_peer *peer; + + if (sm->tdls_disabled || !sm->tdls_supported) + return "disabled"; + + for (peer = sm->tdls; peer; peer = peer->next) { + if (os_memcmp(peer->addr, addr, ETH_ALEN) == 0) + break; + } + + if (peer == NULL) + return "peer does not exist"; + + if (!peer->tpk_success) + return "peer not connected"; + + return "connected"; +} + + static int wpa_tdls_recv_teardown(struct wpa_sm *sm, const u8 *src_addr, const u8 *buf, size_t len) { diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 26e9c6ca0..db7f0db8c 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -380,6 +380,7 @@ void wpa_tdls_teardown_peers(struct wpa_sm *sm); void wpa_tdls_deinit(struct wpa_sm *sm); void wpa_tdls_enable(struct wpa_sm *sm, int enabled); void wpa_tdls_disable_link(struct wpa_sm *sm, const u8 *addr); +const char * wpa_tdls_get_link_status(struct wpa_sm *sm, const u8 *addr); int wpa_tdls_is_external_setup(struct wpa_sm *sm); int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf); diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c index f9521f6d7..9736e8f0a 100644 --- a/wpa_supplicant/dbus/dbus_new.c +++ b/wpa_supplicant/dbus/dbus_new.c @@ -2736,6 +2736,37 @@ static const struct wpa_dbus_method_desc wpas_dbus_interface_methods[] = { } }, #endif /* CONFIG_AUTOSCAN */ +#ifdef CONFIG_TDLS + { "TDLSDiscover", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_tdls_discover, + { + { "peer_address", "s", ARG_IN }, + END_ARGS + } + }, + { "TDLSSetup", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_tdls_setup, + { + { "peer_address", "s", ARG_IN }, + END_ARGS + } + }, + { "TDLSStatus", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_tdls_status, + { + { "peer_address", "s", ARG_IN }, + { "status", "s", ARG_OUT }, + END_ARGS + } + }, + { "TDLSTeardown", WPAS_DBUS_NEW_IFACE_INTERFACE, + (WPADBusMethodHandler) wpas_dbus_handler_tdls_teardown, + { + { "peer_address", "s", ARG_IN }, + END_ARGS + } + }, +#endif /* CONFIG_TDLS */ { NULL, NULL, NULL, { END_ARGS } } }; diff --git a/wpa_supplicant/dbus/dbus_new_handlers.c b/wpa_supplicant/dbus/dbus_new_handlers.c index 9f923e6b0..0a8052122 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.c +++ b/wpa_supplicant/dbus/dbus_new_handlers.c @@ -1997,6 +1997,170 @@ DBusMessage * wpas_dbus_handler_eap_logon(DBusMessage *message, } +#ifdef CONFIG_TDLS + +static DBusMessage * get_peer_hwaddr_helper(DBusMessage *message, + const char *func_name, + u8 *peer_address) +{ + const char *peer_string; + + if (!dbus_message_get_args(message, NULL, + DBUS_TYPE_STRING, &peer_string, + DBUS_TYPE_INVALID)) + return wpas_dbus_error_invalid_args(message, NULL); + + if (hwaddr_aton(peer_string, peer_address)) { + wpa_printf(MSG_DEBUG, "%s: invalid address '%s'", + func_name, peer_string); + return wpas_dbus_error_invalid_args( + message, "Invalid hardware address format"); + } + + return NULL; +} + + +/* + * wpas_dbus_handler_tdls_discover - Discover TDLS peer + * @message: Pointer to incoming dbus message + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: NULL indicating success or DBus error message on failure + * + * Handler function for "TDLSDiscover" method call of network interface. + */ +DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + u8 peer[ETH_ALEN]; + DBusMessage *error_reply; + int ret; + + error_reply = get_peer_hwaddr_helper(message, __func__, peer); + if (error_reply) + return error_reply; + + wpa_printf(MSG_DEBUG, "DBUS TDLS_DISCOVER " MACSTR, MAC2STR(peer)); + + if (wpa_tdls_is_external_setup(wpa_s->wpa)) + ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer); + else + ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer); + + if (ret) { + return wpas_dbus_error_unknown_error( + message, "error performing TDLS discovery"); + } + + return NULL; +} + + +/* + * wpas_dbus_handler_tdls_setup - Setup TDLS session + * @message: Pointer to incoming dbus message + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: NULL indicating success or DBus error message on failure + * + * Handler function for "TDLSSetup" method call of network interface. + */ +DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + u8 peer[ETH_ALEN]; + DBusMessage *error_reply; + int ret; + + error_reply = get_peer_hwaddr_helper(message, __func__, peer); + if (error_reply) + return error_reply; + + wpa_printf(MSG_DEBUG, "DBUS TDLS_SETUP " MACSTR, MAC2STR(peer)); + + wpa_tdls_remove(wpa_s->wpa, peer); + if (wpa_tdls_is_external_setup(wpa_s->wpa)) + ret = wpa_tdls_start(wpa_s->wpa, peer); + else + ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer); + + if (ret) { + return wpas_dbus_error_unknown_error( + message, "error performing TDLS setup"); + } + + return NULL; +} + + +/* + * wpas_dbus_handler_tdls_status - Return TDLS session status + * @message: Pointer to incoming dbus message + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: A string representing the state of the link to this TDLS peer + * + * Handler function for "TDLSStatus" method call of network interface. + */ +DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + u8 peer[ETH_ALEN]; + DBusMessage *reply; + const char *tdls_status; + + reply = get_peer_hwaddr_helper(message, __func__, peer); + if (reply) + return reply; + + wpa_printf(MSG_DEBUG, "DBUS TDLS_STATUS " MACSTR, MAC2STR(peer)); + + tdls_status = wpa_tdls_get_link_status(wpa_s->wpa, peer); + + reply = dbus_message_new_method_return(message); + dbus_message_append_args(reply, DBUS_TYPE_STRING, + &tdls_status, DBUS_TYPE_INVALID); + return reply; +} + + +/* + * wpas_dbus_handler_tdls_teardown - Teardown TDLS session + * @message: Pointer to incoming dbus message + * @wpa_s: wpa_supplicant structure for a network interface + * Returns: NULL indicating success or DBus error message on failure + * + * Handler function for "TDLSTeardown" method call of network interface. + */ +DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message, + struct wpa_supplicant *wpa_s) +{ + u8 peer[ETH_ALEN]; + DBusMessage *error_reply; + int ret; + + error_reply = get_peer_hwaddr_helper(message, __func__, peer); + if (error_reply) + return error_reply; + + wpa_printf(MSG_DEBUG, "DBUS TDLS_TEARDOWN " MACSTR, MAC2STR(peer)); + + if (wpa_tdls_is_external_setup(wpa_s->wpa)) + ret = wpa_tdls_teardown_link( + wpa_s->wpa, peer, + WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED); + else + ret = wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer); + + if (ret) { + return wpas_dbus_error_unknown_error( + message, "error performing TDLS teardown"); + } + + return NULL; +} + +#endif /* CONFIG_TDLS */ + + /** * wpas_dbus_getter_capabilities - Return interface capabilities * @iter: Pointer to incoming dbus message iter diff --git a/wpa_supplicant/dbus/dbus_new_handlers.h b/wpa_supplicant/dbus/dbus_new_handlers.h index fbc8358be..aa3316b7d 100644 --- a/wpa_supplicant/dbus/dbus_new_handlers.h +++ b/wpa_supplicant/dbus/dbus_new_handlers.h @@ -278,6 +278,15 @@ dbus_bool_t wpas_dbus_setter_process_credentials(DBusMessageIter *iter, DBusError *error, void *user_data); +DBusMessage * wpas_dbus_handler_tdls_discover(DBusMessage *message, + struct wpa_supplicant *wpa_s); +DBusMessage * wpas_dbus_handler_tdls_setup(DBusMessage *message, + struct wpa_supplicant *wpa_s); +DBusMessage * wpas_dbus_handler_tdls_status(DBusMessage *message, + struct wpa_supplicant *wpa_s); +DBusMessage * wpas_dbus_handler_tdls_teardown(DBusMessage *message, + struct wpa_supplicant *wpa_s); + DBusMessage * wpas_dbus_error_invalid_args(DBusMessage *message, const char *arg); DBusMessage * wpas_dbus_error_unknown_error(DBusMessage *message,