Commit 0903f899 authored by Avraham Stern's avatar Avraham Stern Committed by Johannes Berg
Browse files

wifi: ieee80211: add helper functions for detecting TM/FTM frames



Add helper functions for detection timing measurement
and fine timing measurement frames.

Signed-off-by: default avatarAvraham Stern <avraham.stern@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent c204d9df
Loading
Loading
Loading
Loading
+54 −0
Original line number Diff line number Diff line
@@ -1332,6 +1332,15 @@ struct ieee80211_mgmt {
					u8 action_code;
					u8 variable[];
				} __packed s1g;
				struct {
					u8 action_code;
					u8 dialog_token;
					u8 follow_up;
					u32 tod;
					u32 toa;
					u8 max_tod_error;
					u8 max_toa_error;
				} __packed wnm_timing_msr;
			} u;
		} __packed action;
	} u;
@@ -3522,6 +3531,17 @@ enum ieee80211_mesh_actioncode {
	WLAN_MESH_ACTION_TBTT_ADJUSTMENT_RESPONSE,
};

/* Unprotected WNM action codes */
enum ieee80211_unprotected_wnm_actioncode {
	WLAN_UNPROTECTED_WNM_ACTION_TIM = 0,
	WLAN_UNPROTECTED_WNM_ACTION_TIMING_MEASUREMENT_RESPONSE = 1,
};

/* Public action codes */
enum ieee80211_public_actioncode {
	WLAN_PUBLIC_ACTION_FTM_RESPONSE = 33,
};

/* Security key length */
enum ieee80211_key_len {
	WLAN_KEY_LEN_WEP40 = 5,
@@ -4311,6 +4331,40 @@ static inline bool ieee80211_action_contains_tpc(struct sk_buff *skb)
	return true;
}

static inline bool ieee80211_is_timing_measurement(struct sk_buff *skb)
{
	struct ieee80211_mgmt *mgmt = (void *)skb->data;

	if (skb->len < IEEE80211_MIN_ACTION_SIZE)
		return false;

	if (!ieee80211_is_action(mgmt->frame_control))
		return false;

	if (mgmt->u.action.category == WLAN_CATEGORY_WNM_UNPROTECTED &&
	    mgmt->u.action.u.wnm_timing_msr.action_code ==
		WLAN_UNPROTECTED_WNM_ACTION_TIMING_MEASUREMENT_RESPONSE &&
	    skb->len >= offsetofend(typeof(*mgmt), u.action.u.wnm_timing_msr))
		return true;

	return false;
}

static inline bool ieee80211_is_ftm(struct sk_buff *skb)
{
	struct ieee80211_mgmt *mgmt = (void *)skb->data;

	if (!ieee80211_is_public_action((void *)mgmt, skb->len))
		return false;

	if (mgmt->u.action.u.ftm.action_code ==
		WLAN_PUBLIC_ACTION_FTM_RESPONSE &&
	    skb->len >= offsetofend(typeof(*mgmt), u.action.u.ftm))
		return true;

	return false;
}

struct element {
	u8 id;
	u8 datalen;