TDLS: Add peer as a STA during link setup
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. Extend sta_add() callback for adding/modifying a TDLS 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@wizery.com> Cc: Kalyan C Gaddam <chakkal@iit.edu>
This commit is contained in:
		
							parent
							
								
									979bcccf64
								
							
						
					
					
						commit
						45b722f150
					
				
					 6 changed files with 93 additions and 9 deletions
				
			
		|  | @ -794,6 +794,7 @@ struct hostapd_sta_add_params { | |||
| 	u16 listen_interval; | ||||
| 	const struct ieee80211_ht_capabilities *ht_capabilities; | ||||
| 	u32 flags; /* bitmask of WPA_STA_* flags */ | ||||
| 	int set; /* Set STA parameters instead of add */ | ||||
| }; | ||||
| 
 | ||||
| struct hostapd_freq_params { | ||||
|  | @ -878,6 +879,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 | ||||
|  | @ -1622,6 +1624,9 @@ struct wpa_driver_ops { | |||
| 	 * This function is used to add a station entry to the driver once the | ||||
| 	 * station has completed association. This is only used if the driver | ||||
| 	 * does not take care of association processing. | ||||
| 	 * | ||||
| 	 * With TDLS, this function is also used to add or set (params->set 1) | ||||
| 	 * TDLS peer entries. | ||||
| 	 */ | ||||
| 	int (*sta_add)(void *priv, struct hostapd_sta_add_params *params); | ||||
| 
 | ||||
|  | @ -2313,7 +2318,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. | ||||
|  | @ -2322,6 +2327,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); | ||||
| 
 | ||||
| 	/**
 | ||||
|  |  | |||
|  | @ -4409,6 +4409,8 @@ 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; | ||||
| } | ||||
|  | @ -4423,19 +4425,26 @@ static int wpa_driver_nl80211_sta_add(void *priv, | |||
| 	struct nl80211_sta_flag_update upd; | ||||
| 	int ret = -ENOBUFS; | ||||
| 
 | ||||
| 	if ((params->flags & WPA_STA_TDLS_PEER) && | ||||
| 	    !(drv->capa.flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT)) | ||||
| 		return -EOPNOTSUPP; | ||||
| 
 | ||||
| 	msg = nlmsg_alloc(); | ||||
| 	if (!msg) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	nl80211_cmd(drv, msg, 0, NL80211_CMD_NEW_STATION); | ||||
| 	nl80211_cmd(drv, msg, 0, params->set ? NL80211_CMD_SET_STATION : | ||||
| 		    NL80211_CMD_NEW_STATION); | ||||
| 
 | ||||
| 	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 (!params->set) { | ||||
| 		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), | ||||
|  | @ -4449,8 +4458,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)", params->set ? "SET" : "NEW", ret, | ||||
| 			   strerror(-ret)); | ||||
| 	if (ret == -EEXIST) | ||||
| 		ret = 0; | ||||
|  nla_put_failure: | ||||
|  | @ -5138,6 +5148,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; | ||||
| 
 | ||||
|  |  | |||
|  | @ -1624,8 +1624,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; | ||||
| 
 | ||||
|  | @ -1658,6 +1664,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); | ||||
| } | ||||
| 
 | ||||
|  | @ -2059,7 +2070,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; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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, | ||||
|  |  | |||
|  | @ -563,6 +563,27 @@ 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; | ||||
| 	params.set = !add; | ||||
| 
 | ||||
| 	return wpa_drv_sta_add(wpa_s, ¶ms); | ||||
| } | ||||
| 
 | ||||
| #endif /* CONFIG_TDLS */ | ||||
| 
 | ||||
| 
 | ||||
|  | @ -724,6 +745,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; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Arik Nemtsov
						Arik Nemtsov