aboutsummaryrefslogtreecommitdiffstats
path: root/wpa_supplicant
diff options
context:
space:
mode:
authorGanesh Prasadh <gprasadh@atheros.com>2010-10-07 07:26:56 (GMT)
committerJouni Malinen <j@w1.fi>2011-03-06 12:53:49 (GMT)
commit281ff0aa76d7b6cec0ecb0d9fa209c57c9066dd0 (patch)
treefe0081cd26e83edaf1074b945b235cae7e82f550 /wpa_supplicant
parent23ab8e863f5add2050cd71ec1205816152ae4f2f (diff)
downloadhostap-281ff0aa76d7b6cec0ecb0d9fa209c57c9066dd0.zip
hostap-281ff0aa76d7b6cec0ecb0d9fa209c57c9066dd0.tar.gz
hostap-281ff0aa76d7b6cec0ecb0d9fa209c57c9066dd0.tar.bz2
TDLS: Add initial support for TDLS (IEEE Std 802.11z-2010)
Diffstat (limited to 'wpa_supplicant')
-rw-r--r--wpa_supplicant/Makefile7
-rw-r--r--wpa_supplicant/ctrl_iface.c69
-rw-r--r--wpa_supplicant/driver_i.h20
-rw-r--r--wpa_supplicant/events.c25
-rw-r--r--wpa_supplicant/wpa_cli.c72
-rw-r--r--wpa_supplicant/wpa_supplicant.c9
-rw-r--r--wpa_supplicant/wpas_glue.c26
7 files changed, 228 insertions, 0 deletions
diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile
index cbcf30a..0098aae 100644
--- a/wpa_supplicant/Makefile
+++ b/wpa_supplicant/Makefile
@@ -142,6 +142,13 @@ NEED_SHA256=y
NEED_AES_OMAC1=y
endif
+ifdef CONFIG_TDLS
+CFLAGS += -DCONFIG_TDLS
+OBJS += ../src/rsn_supp/tdls.o
+NEED_SHA256=y
+NEED_AES_OMAC1=y
+endif
+
ifdef CONFIG_PEERKEY
CFLAGS += -DCONFIG_PEERKEY
endif
diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c
index 2fe12f0..f4b6442 100644
--- a/wpa_supplicant/ctrl_iface.c
+++ b/wpa_supplicant/ctrl_iface.c
@@ -181,6 +181,64 @@ static int wpa_supplicant_ctrl_iface_stkstart(
#endif /* CONFIG_PEERKEY */
+#ifdef CONFIG_TDLS
+
+static int wpa_supplicant_ctrl_iface_tdls_discover(
+ struct wpa_supplicant *wpa_s, char *addr)
+{
+ u8 peer[ETH_ALEN];
+
+ if (hwaddr_aton(addr, peer)) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
+ "address '%s'", addr);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
+ MAC2STR(peer));
+
+ return wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
+}
+
+
+static int wpa_supplicant_ctrl_iface_tdls_setup(
+ struct wpa_supplicant *wpa_s, char *addr)
+{
+ u8 peer[ETH_ALEN];
+
+ if (hwaddr_aton(addr, peer)) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP: invalid "
+ "address '%s'", addr);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_SETUP " MACSTR,
+ MAC2STR(peer));
+
+ return wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
+}
+
+
+static int wpa_supplicant_ctrl_iface_tdls_teardown(
+ struct wpa_supplicant *wpa_s, char *addr)
+{
+ u8 peer[ETH_ALEN];
+
+ if (hwaddr_aton(addr, peer)) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN: invalid "
+ "address '%s'", addr);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
+ MAC2STR(peer));
+
+ return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
+}
+
+#endif /* CONFIG_TDLS */
+
+
#ifdef CONFIG_IEEE80211R
static int wpa_supplicant_ctrl_iface_ft_ds(
struct wpa_supplicant *wpa_s, char *addr)
@@ -3118,6 +3176,17 @@ char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
} else if (os_strncmp(buf, "STA_AUTOCONNECT ", 16) == 0) {
if (wpa_supplicant_ctrl_iface_sta_autoconnect(wpa_s, buf + 16))
reply_len = -1;
+#ifdef CONFIG_TDLS
+ } else if (os_strncmp(buf, "TDLS_DISCOVER ", 14) == 0) {
+ if (wpa_supplicant_ctrl_iface_tdls_discover(wpa_s, buf + 14))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "TDLS_SETUP ", 11) == 0) {
+ if (wpa_supplicant_ctrl_iface_tdls_setup(wpa_s, buf + 11))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "TDLS_TEARDOWN ", 14) == 0) {
+ if (wpa_supplicant_ctrl_iface_tdls_teardown(wpa_s, buf + 14))
+ reply_len = -1;
+#endif /* CONFIG_TDLS */
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 5331765..682c56c 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -675,5 +675,25 @@ static inline int wpa_drv_p2p_invite(struct wpa_supplicant *wpa_s,
persistent_group);
}
+static inline int wpa_drv_send_tdls_mgmt(struct wpa_supplicant *wpa_s,
+ const u8 *dst, u8 action_code,
+ u8 dialog_token, u16 status_code,
+ const u8 *buf, size_t len)
+{
+ if (wpa_s->driver->send_tdls_mgmt) {
+ return wpa_s->driver->send_tdls_mgmt(wpa_s->drv_priv, dst,
+ action_code, dialog_token,
+ status_code, buf, len);
+ }
+ return -1;
+}
+
+static inline int wpa_drv_tdls_oper(struct wpa_supplicant *wpa_s,
+ enum tdls_oper oper, const u8 *peer)
+{
+ if (!wpa_s->driver->tdls_oper)
+ return -1;
+ return wpa_s->driver->tdls_oper(wpa_s->drv_priv, oper, peer);
+}
#endif /* DRIVER_I_H */
diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c
index 8c63563..5105955 100644
--- a/wpa_supplicant/events.c
+++ b/wpa_supplicant/events.c
@@ -1587,6 +1587,26 @@ wpa_supplicant_event_stkstart(struct wpa_supplicant *wpa_s,
#endif /* CONFIG_PEERKEY */
+#ifdef CONFIG_TDLS
+static void wpa_supplicant_event_tdls(struct wpa_supplicant *wpa_s,
+ union wpa_event_data *data)
+{
+ if (data == NULL)
+ return;
+ switch (data->tdls.oper) {
+ case TDLS_REQUEST_SETUP:
+ wpa_tdls_start(wpa_s->wpa, data->tdls.peer);
+ break;
+ case TDLS_REQUEST_TEARDOWN:
+ /* request from driver to add FTIE */
+ wpa_tdls_recv_teardown_notify(wpa_s->wpa, data->tdls.peer,
+ data->tdls.reason_code);
+ break;
+ }
+}
+#endif /* CONFIG_TDLS */
+
+
#ifdef CONFIG_IEEE80211R
static void
wpa_supplicant_event_ft_response(struct wpa_supplicant *wpa_s,
@@ -1818,6 +1838,11 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_supplicant_event_stkstart(wpa_s, data);
break;
#endif /* CONFIG_PEERKEY */
+#ifdef CONFIG_TDLS
+ case EVENT_TDLS:
+ wpa_supplicant_event_tdls(wpa_s, data);
+ break;
+#endif /* CONFIG_TDLS */
#ifdef CONFIG_IEEE80211R
case EVENT_FT_RESPONSE:
wpa_supplicant_event_ft_response(wpa_s, data);
diff --git a/wpa_supplicant/wpa_cli.c b/wpa_supplicant/wpa_cli.c
index d888a8e..4b9e930 100644
--- a/wpa_supplicant/wpa_cli.c
+++ b/wpa_supplicant/wpa_cli.c
@@ -2153,6 +2153,69 @@ static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
}
+static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char cmd[256];
+ int res;
+
+ if (argc != 1) {
+ printf("Invalid TDLS_DISCOVER command: needs one argument "
+ "(Peer STA MAC address)\n");
+ return -1;
+ }
+
+ res = os_snprintf(cmd, sizeof(cmd), "TDLS_DISCOVER %s", argv[0]);
+ if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ printf("Too long TDLS_DISCOVER command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char cmd[256];
+ int res;
+
+ if (argc != 1) {
+ printf("Invalid TDLS_SETUP command: needs one argument "
+ "(Peer STA MAC address)\n");
+ return -1;
+ }
+
+ res = os_snprintf(cmd, sizeof(cmd), "TDLS_SETUP %s", argv[0]);
+ if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ printf("Too long TDLS_SETUP command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
+static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
+ char *argv[])
+{
+ char cmd[256];
+ int res;
+
+ if (argc != 1) {
+ printf("Invalid TDLS_TEARDOWN command: needs one argument "
+ "(Peer STA MAC address)\n");
+ return -1;
+ }
+
+ res = os_snprintf(cmd, sizeof(cmd), "TDLS_TEARDOWN %s", argv[0]);
+ if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
+ printf("Too long TDLS_TEARDOWN command.\n");
+ return -1;
+ }
+ return wpa_ctrl_command(ctrl, cmd);
+}
+
+
enum wpa_cli_cmd_flags {
cli_cmd_flag_none = 0x00,
cli_cmd_flag_sensitive = 0x01
@@ -2450,6 +2513,15 @@ static struct wpa_cli_cmd wpa_cli_commands[] = {
#endif /* CONFIG_P2P */
{ "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, cli_cmd_flag_none,
"<0/1> = disable/enable automatic reconnection" },
+ { "tdls_discover", wpa_cli_cmd_tdls_discover,
+ cli_cmd_flag_none,
+ "<addr> = request TDLS discovery with <addr>" },
+ { "tdls_setup", wpa_cli_cmd_tdls_setup,
+ cli_cmd_flag_none,
+ "<addr> = request TDLS setup with <addr>" },
+ { "tdls_teardown", wpa_cli_cmd_tdls_teardown,
+ cli_cmd_flag_none,
+ "<addr> = tear down TDLS with <addr>" },
{ NULL, NULL, cli_cmd_flag_none, NULL }
};
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 6a1a7e3..3479879 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -402,6 +402,10 @@ static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s)
rsn_preauth_deinit(wpa_s->wpa);
+#ifdef CONFIG_TDLS
+ wpa_tdls_deinit(wpa_s->wpa);
+#endif /* CONFIG_TDLS */
+
pmksa_candidate_free(wpa_s->wpa);
wpa_sm_deinit(wpa_s->wpa);
wpa_s->wpa = NULL;
@@ -2136,6 +2140,11 @@ next_driver:
if (wpa_supplicant_driver_init(wpa_s) < 0)
return -1;
+#ifdef CONFIG_TDLS
+ if (wpa_tdls_init(wpa_s->wpa))
+ return -1;
+#endif /* CONFIG_TDLS */
+
if (wpa_s->conf->country[0] && wpa_s->conf->country[1] &&
wpa_drv_set_country(wpa_s, wpa_s->conf->country)) {
wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country");
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 5b7aebe..2662eec 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -535,6 +535,28 @@ static int wpa_supplicant_mark_authenticated(void *ctx, const u8 *target_ap)
#endif /* CONFIG_NO_WPA */
+#ifdef CONFIG_TDLS
+
+static int wpa_supplicant_send_tdls_mgmt(void *ctx, const u8 *dst,
+ u8 action_code, u8 dialog_token,
+ u16 status_code, const u8 *buf,
+ size_t len)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ return wpa_drv_send_tdls_mgmt(wpa_s, dst, action_code, dialog_token,
+ status_code, buf, len);
+}
+
+
+static int wpa_supplicant_tdls_oper(void *ctx, int oper, const u8 *peer)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ return wpa_drv_tdls_oper(wpa_s, oper, peer);
+}
+
+#endif /* CONFIG_TDLS */
+
+
#ifdef IEEE8021X_EAPOL
#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG)
static void wpa_supplicant_eap_param_needed(void *ctx, const char *field,
@@ -668,6 +690,10 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
ctx->send_ft_action = wpa_supplicant_send_ft_action;
ctx->mark_authenticated = wpa_supplicant_mark_authenticated;
#endif /* CONFIG_IEEE80211R */
+#ifdef CONFIG_TDLS
+ ctx->send_tdls_mgmt = wpa_supplicant_send_tdls_mgmt;
+ ctx->tdls_oper = wpa_supplicant_tdls_oper;
+#endif /* CONFIG_TDLS */
wpa_s->wpa = wpa_sm_init(ctx);
if (wpa_s->wpa == NULL) {