[PATCH 11/14] TDLS: add peer as a STA during link setup
Arik Nemtsov
arik
Mon Sep 26 03:55:32 PDT 2011
Before commencing setup, add a new STA entry to the driver representing
the peer. Later during setup, update the STA entry using information
received from the peer.
Define a new driver callback for adding/modifying a peer entry and
connect it to the TDLS state machine. Implement this callback for the
nl80211 driver and send peer information to kernel.
Mark TDLS peer entries with a new flag and translate it to a
corresponding nl80211 flag in the nl80211 driver.
In addition, correct TDLS related documentation in the wpa_driver_ops
structure.
Signed-off-by: Arik Nemtsov <arik at wizery.com>
Cc: Kalyan C Gaddam <chakkal at iit.edu>
---
src/drivers/driver.h | 26 +++++++++++++++++++-
src/drivers/driver_nl80211.c | 53 ++++++++++++++++++++++++++++++++++-------
src/rsn_supp/tdls.c | 23 ++++++++++++++++-
src/rsn_supp/wpa.h | 3 ++
src/rsn_supp/wpa_i.h | 12 +++++++++
wpa_supplicant/driver_i.h | 11 ++++++++
wpa_supplicant/wpas_glue.c | 21 ++++++++++++++++
7 files changed, 137 insertions(+), 12 deletions(-)
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 5d76ae8..935fcb9 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -816,6 +816,7 @@ struct wpa_bss_params {
#define WPA_STA_WMM BIT(1)
#define WPA_STA_SHORT_PREAMBLE BIT(2)
#define WPA_STA_MFP BIT(3)
+#define WPA_STA_TDLS_PEER BIT(4)
/**
* struct p2p_params - P2P parameters for driver-based P2P management
@@ -2348,6 +2349,19 @@ struct wpa_driver_ops {
const u8 *go_dev_addr, int persistent_group);
/**
+ * tdls_peer_addset - for adding/modifying TDLS peer stations
+ * @priv: private driver interface data
+ * @add: non-zero when adding a new TDLS peer
+ * @params: station parameters
+ * Returns: 0 on success, negative (<0) on failure
+ *
+ * This optional function can be used to to add TDLS peer
+ * entries to the driver, or modify their parameters.
+ */
+ int (*tdls_peer_addset)(void *priv, int add,
+ struct hostapd_sta_add_params *params);
+
+ /**
* send_tdls_mgmt - for sending TDLS management packets
* @priv: private driver interface data
* @dst: Destination (peer) MAC address
@@ -2356,7 +2370,7 @@ struct wpa_driver_ops {
* @status_code: Status Code or Reason Code to use (if needed)
* @buf: TDLS IEs to add to the message
* @len: Length of buf in octets
- * Returns: 0 on success, -1 on failure
+ * Returns: 0 on success, negative (<0) on failure
*
* This optional function can be used to send packet to driver which is
* responsible for receiving and sending all TDLS packets.
@@ -2365,6 +2379,16 @@ struct wpa_driver_ops {
u8 dialog_token, u16 status_code,
const u8 *buf, size_t len);
+ /**
+ * tdls_oper - ask the driver to perform high-level TDLS operations
+ * @priv: private driver interface data
+ * @oper: TDLS high-level operation. See %enum tdls_oper
+ * @peer: Destination (peer) MAC address
+ * Returns: 0 on success, negative (<0) on failure
+ *
+ * This optional function can be used to send high-level TDLS commands
+ * to the driver.
+ */
int (*tdls_oper)(void *priv, enum tdls_oper oper, const u8 *peer);
/**
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index cc10331..bbf5cde 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -4191,34 +4191,43 @@ static u32 sta_flags_nl80211(int flags)
f |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
if (flags & WPA_STA_MFP)
f |= BIT(NL80211_STA_FLAG_MFP);
+ if (flags & WPA_STA_TDLS_PEER)
+ f |= BIT(NL80211_STA_FLAG_TDLS_PEER);
return f;
}
-static int wpa_driver_nl80211_sta_add(void *priv,
- struct hostapd_sta_add_params *params)
+static int wpa_driver_nl80211_sta_addset(void *priv, int add,
+ struct hostapd_sta_add_params *params)
{
struct i802_bss *bss = priv;
struct wpa_driver_nl80211_data *drv = bss->drv;
struct nl_msg *msg;
struct nl80211_sta_flag_update upd;
+ int cmd;
int ret = -ENOBUFS;
msg = nlmsg_alloc();
if (!msg)
return -ENOMEM;
- genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
- 0, NL80211_CMD_NEW_STATION, 0);
+ if (add)
+ cmd = NL80211_CMD_NEW_STATION;
+ else
+ cmd = NL80211_CMD_SET_STATION;
+
+ genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0, cmd, 0);
NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(bss->ifname));
NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, params->addr);
- NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
NLA_PUT(msg, NL80211_ATTR_STA_SUPPORTED_RATES, params->supp_rates_len,
params->supp_rates);
- NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
- params->listen_interval);
+ if (add) {
+ NLA_PUT_U16(msg, NL80211_ATTR_STA_AID, params->aid);
+ NLA_PUT_U16(msg, NL80211_ATTR_STA_LISTEN_INTERVAL,
+ params->listen_interval);
+ }
if (params->ht_capabilities) {
NLA_PUT(msg, NL80211_ATTR_HT_CAPABILITY,
sizeof(*params->ht_capabilities),
@@ -4232,8 +4241,9 @@ static int wpa_driver_nl80211_sta_add(void *priv,
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
if (ret)
- wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_NEW_STATION "
- "result: %d (%s)", ret, strerror(-ret));
+ wpa_printf(MSG_DEBUG, "nl80211: NL80211_CMD_%s_STATION "
+ "result: %d (%s)", add ? "NEW" : "SET", ret,
+ strerror(-ret));
if (ret == -EEXIST)
ret = 0;
nla_put_failure:
@@ -4241,6 +4251,13 @@ static int wpa_driver_nl80211_sta_add(void *priv,
}
+static int wpa_driver_nl80211_sta_add(void *priv,
+ struct hostapd_sta_add_params *params)
+{
+ return wpa_driver_nl80211_sta_addset(priv, 1, params);
+}
+
+
static int wpa_driver_nl80211_sta_remove(void *priv, const u8 *addr)
{
struct i802_bss *bss = priv;
@@ -4907,6 +4924,9 @@ static int wpa_driver_nl80211_sta_set_flags(void *priv, const u8 *addr,
if (total_flags & WPA_STA_MFP)
NLA_PUT_FLAG(flags, NL80211_STA_FLAG_MFP);
+ if (total_flags & WPA_STA_TDLS_PEER)
+ NLA_PUT_FLAG(flags, NL80211_STA_FLAG_TDLS_PEER);
+
if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))
goto nla_put_failure;
@@ -7174,6 +7194,20 @@ static void nl80211_set_rekey_info(void *priv, const u8 *kek, const u8 *kck,
#ifdef CONFIG_TDLS
+
+static int nl80211_tdls_peer_addset(void *priv, int add,
+ struct hostapd_sta_add_params *params)
+{
+ struct i802_bss *bss = priv;
+ struct wpa_driver_nl80211_data *drv = bss->drv;
+
+ if (!(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT))
+ return -ENOTSUP;
+
+ return wpa_driver_nl80211_sta_addset(priv, add, params);
+}
+
+
static enum nl80211_tdls_operation nl80211_tdls_get_oper(enum tdls_oper oper)
{
switch (oper) {
@@ -7342,6 +7376,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
.flush_pmkid = nl80211_flush_pmkid,
.set_rekey_info = nl80211_set_rekey_info,
#ifdef CONFIG_TDLS
+ .tdls_peer_addset = nl80211_tdls_peer_addset,
.send_tdls_mgmt = nl80211_send_tdls_mgmt,
.tdls_oper = nl80211_tdls_oper,
#endif /* CONFIG_TDLS */
diff --git a/src/rsn_supp/tdls.c b/src/rsn_supp/tdls.c
index 1b80ac5..771f77c 100644
--- a/src/rsn_supp/tdls.c
+++ b/src/rsn_supp/tdls.c
@@ -1620,8 +1620,14 @@ skip_rsn:
wpa_tdls_generate_tpk(peer, sm->own_addr, sm->bssid);
skip_rsn_check:
+ /* add the peer to the driver as a "setup in progress" peer */
+ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0);
+
wpa_printf(MSG_DEBUG, "TDLS: Sending TDLS Setup Response / TPK M2");
- wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer);
+ if (wpa_tdls_send_tpk_m2(sm, src_addr, dtoken, lnkid, peer) < 0) {
+ wpa_tdls_disable_link(sm, peer->addr);
+ goto error;
+ }
return 0;
@@ -1654,6 +1660,11 @@ static void wpa_tdls_enable_link(struct wpa_sm *sm, struct wpa_tdls_peer *peer)
}
#endif /* CONFIG_TDLS_TESTING */
}
+
+ /* add supported rates and capabilities to the TDLS peer */
+ wpa_sm_tdls_peer_addset(sm, peer->addr, 0, peer->capability,
+ peer->supp_rates, peer->supp_rates_len);
+
wpa_sm_tdls_oper(sm, TDLS_ENABLE_LINK, peer->addr);
}
@@ -2075,7 +2086,15 @@ int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr)
peer->initiator = 1;
- return wpa_tdls_send_tpk_m1(sm, peer);
+ /* add the peer to the driver as a "setup in progress" peer */
+ wpa_sm_tdls_peer_addset(sm, peer->addr, 1, 0, NULL, 0);
+
+ if (wpa_tdls_send_tpk_m1(sm, peer) < 0) {
+ wpa_tdls_disable_link(sm, peer->addr);
+ return -1;
+ }
+
+ return 0;
}
diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h
index 492fd34..d4ae09c 100644
--- a/src/rsn_supp/wpa.h
+++ b/src/rsn_supp/wpa.h
@@ -62,6 +62,9 @@ struct wpa_sm_ctx {
u8 action_code, u8 dialog_token,
u16 status_code, const u8 *buf, size_t len);
int (*tdls_oper)(void *ctx, int oper, const u8 *peer);
+ int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add,
+ u16 capability, const u8 *supp_rates,
+ size_t supp_rates_len);
#endif /* CONFIG_TDLS */
void (*set_rekey_offload)(void *ctx, const u8 *kek, const u8 *kck,
const u8 *replay_ctr);
diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h
index 67c3390..39124c4 100644
--- a/src/rsn_supp/wpa_i.h
+++ b/src/rsn_supp/wpa_i.h
@@ -291,6 +291,18 @@ static inline int wpa_sm_tdls_oper(struct wpa_sm *sm, int oper,
return sm->ctx->tdls_oper(sm->ctx->ctx, oper, peer);
return -1;
}
+
+static inline int
+wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add,
+ u16 capability, const u8 *supp_rates,
+ size_t supp_rates_len)
+{
+ if (sm->ctx->tdls_peer_addset)
+ return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add,
+ capability, supp_rates,
+ supp_rates_len);
+ return -1;
+}
#endif /* CONFIG_TDLS */
void wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck,
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 79fdddd..9f1e7b0 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -700,6 +700,17 @@ static inline int wpa_drv_tdls_oper(struct wpa_supplicant *wpa_s,
return wpa_s->driver->tdls_oper(wpa_s->drv_priv, oper, peer);
}
+static inline int
+wpa_drv_tdls_peer_addset(struct wpa_supplicant *wpa_s, int add,
+ struct hostapd_sta_add_params *params)
+{
+ if (wpa_s->driver->tdls_peer_addset)
+ return wpa_s->driver->tdls_peer_addset(wpa_s->drv_priv, add,
+ params);
+ return -1;
+}
+
+
static inline void wpa_drv_set_rekey_info(struct wpa_supplicant *wpa_s,
const u8 *kek, const u8 *kck,
const u8 *replay_ctr)
diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c
index 7feeaeb..6a8d1f8 100644
--- a/wpa_supplicant/wpas_glue.c
+++ b/wpa_supplicant/wpas_glue.c
@@ -576,6 +576,26 @@ static int wpa_supplicant_tdls_oper(void *ctx, int oper, const u8 *peer)
return wpa_drv_tdls_oper(wpa_s, oper, peer);
}
+
+static int wpa_supplicant_tdls_peer_addset(void *ctx, const u8 *peer, int add,
+ u16 capability, const u8 *supp_rates,
+ size_t supp_rates_len)
+{
+ struct wpa_supplicant *wpa_s = ctx;
+ struct hostapd_sta_add_params params;
+
+ params.addr = peer;
+ params.aid = 1;
+ params.capability = capability;
+ params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED;
+ params.ht_capabilities = NULL;
+ params.listen_interval = 0;
+ params.supp_rates = supp_rates;
+ params.supp_rates_len = supp_rates_len;
+
+ return wpa_drv_tdls_peer_addset(wpa_s, add, ¶ms);
+}
+
#endif /* CONFIG_TDLS */
@@ -737,6 +757,7 @@ int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s)
ctx->tdls_get_capa = wpa_supplicant_tdls_get_capa;
ctx->send_tdls_mgmt = wpa_supplicant_send_tdls_mgmt;
ctx->tdls_oper = wpa_supplicant_tdls_oper;
+ ctx->tdls_peer_addset = wpa_supplicant_tdls_peer_addset;
#endif /* CONFIG_TDLS */
ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload;
--
1.7.4.1
More information about the Hostap
mailing list