aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2014-08-12 14:34:30 -0400
committerJohannes Berg <johannes.berg@intel.com>2014-08-26 05:16:01 -0400
commit0e227084aee36b3ba27b4fc9cd9e425be6ce2ab8 (patch)
tree5a862e85d25ad5cf05e8f47800e20de792592e91
parentf41ef64853fb1e02728e56b2d0d55aef8ed12b26 (diff)
cfg80211: clarify BSS probe response vs. beacon data
There are a few possible cases of where BSS data came from: 1) only a beacon has been received 2) only a probe response has been received 3) the driver didn't report what it received (this happens when using cfg80211_inform_bss[_width]()) 4) both probe response and beacon data has been received Unfortunately, in the userspace API, a few things weren't there: a) there was no way to differentiate cases 1) and 4) above without comparing the data of the IEs b) the TSF was always from the last frame, instead of being exposed for beacon/probe response separately like IEs Fix this by i) exporting a new flag attribute that indicates whether or not probe response data has been received - this addresses (a) ii) exporting a BEACON_TSF attribute that holds the beacon's TSF if a beacon has been received iii) not exporting the beacon attributes in case (3) above as that would just lead userspace into thinking the data actually came from a beacon when that isn't clear To implement this, track inside the IEs struct whether or not it (definitely) came from a beacon. Reported-by: William Seto Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/cfg80211.h2
-rw-r--r--include/uapi/linux/nl80211.h16
-rw-r--r--net/wireless/nl80211.c16
-rw-r--r--net/wireless/scan.c6
4 files changed, 32 insertions, 8 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 7b8dac3efe8f..77b85a89abca 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1503,12 +1503,14 @@ enum cfg80211_signal_type {
1503 * @tsf: TSF contained in the frame that carried these IEs 1503 * @tsf: TSF contained in the frame that carried these IEs
1504 * @rcu_head: internal use, for freeing 1504 * @rcu_head: internal use, for freeing
1505 * @len: length of the IEs 1505 * @len: length of the IEs
1506 * @from_beacon: these IEs are known to come from a beacon
1506 * @data: IE data 1507 * @data: IE data
1507 */ 1508 */
1508struct cfg80211_bss_ies { 1509struct cfg80211_bss_ies {
1509 u64 tsf; 1510 u64 tsf;
1510 struct rcu_head rcu_head; 1511 struct rcu_head rcu_head;
1511 int len; 1512 int len;
1513 bool from_beacon;
1512 u8 data[]; 1514 u8 data[];
1513}; 1515};
1514 1516
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index f1db15b9c041..d097568da690 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -3055,14 +3055,20 @@ enum nl80211_bss_scan_width {
3055 * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets) 3055 * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets)
3056 * @NL80211_BSS_FREQUENCY: frequency in MHz (u32) 3056 * @NL80211_BSS_FREQUENCY: frequency in MHz (u32)
3057 * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64) 3057 * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64)
3058 * (if @NL80211_BSS_PRESP_DATA is present then this is known to be
3059 * from a probe response, otherwise it may be from the same beacon
3060 * that the NL80211_BSS_BEACON_TSF will be from)
3058 * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16) 3061 * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16)
3059 * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16) 3062 * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16)
3060 * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the 3063 * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the
3061 * raw information elements from the probe response/beacon (bin); 3064 * raw information elements from the probe response/beacon (bin);
3062 * if the %NL80211_BSS_BEACON_IES attribute is present, the IEs here are 3065 * if the %NL80211_BSS_BEACON_IES attribute is present and the data is
3063 * from a Probe Response frame; otherwise they are from a Beacon frame. 3066 * different then the IEs here are from a Probe Response frame; otherwise
3067 * they are from a Beacon frame.
3064 * However, if the driver does not indicate the source of the IEs, these 3068 * However, if the driver does not indicate the source of the IEs, these
3065 * IEs may be from either frame subtype. 3069 * IEs may be from either frame subtype.
3070 * If present, the @NL80211_BSS_PRESP_DATA attribute indicates that the
3071 * data here is known to be from a probe response, without any heuristics.
3066 * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon 3072 * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon
3067 * in mBm (100 * dBm) (s32) 3073 * in mBm (100 * dBm) (s32)
3068 * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon 3074 * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon
@@ -3074,6 +3080,10 @@ enum nl80211_bss_scan_width {
3074 * yet been received 3080 * yet been received
3075 * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel 3081 * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel
3076 * (u32, enum nl80211_bss_scan_width) 3082 * (u32, enum nl80211_bss_scan_width)
3083 * @NL80211_BSS_BEACON_TSF: TSF of the last received beacon (u64)
3084 * (not present if no beacon frame has been received yet)
3085 * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and
3086 * @NL80211_BSS_TSF is known to be from a probe response (flag attribute)
3077 * @__NL80211_BSS_AFTER_LAST: internal 3087 * @__NL80211_BSS_AFTER_LAST: internal
3078 * @NL80211_BSS_MAX: highest BSS attribute 3088 * @NL80211_BSS_MAX: highest BSS attribute
3079 */ 3089 */
@@ -3091,6 +3101,8 @@ enum nl80211_bss {
3091 NL80211_BSS_SEEN_MS_AGO, 3101 NL80211_BSS_SEEN_MS_AGO,
3092 NL80211_BSS_BEACON_IES, 3102 NL80211_BSS_BEACON_IES,
3093 NL80211_BSS_CHAN_WIDTH, 3103 NL80211_BSS_CHAN_WIDTH,
3104 NL80211_BSS_BEACON_TSF,
3105 NL80211_BSS_PRESP_DATA,
3094 3106
3095 /* keep last */ 3107 /* keep last */
3096 __NL80211_BSS_AFTER_LAST, 3108 __NL80211_BSS_AFTER_LAST,
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index df7b1332a1ec..3011401f52c0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -6033,7 +6033,6 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
6033 const struct cfg80211_bss_ies *ies; 6033 const struct cfg80211_bss_ies *ies;
6034 void *hdr; 6034 void *hdr;
6035 struct nlattr *bss; 6035 struct nlattr *bss;
6036 bool tsf = false;
6037 6036
6038 ASSERT_WDEV_LOCK(wdev); 6037 ASSERT_WDEV_LOCK(wdev);
6039 6038
@@ -6060,18 +6059,27 @@ static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
6060 goto nla_put_failure; 6059 goto nla_put_failure;
6061 6060
6062 rcu_read_lock(); 6061 rcu_read_lock();
6062 /* indicate whether we have probe response data or not */
6063 if (rcu_access_pointer(res->proberesp_ies) &&
6064 nla_put_flag(msg, NL80211_BSS_PRESP_DATA))
6065 goto fail_unlock_rcu;
6066
6067 /* this pointer prefers to be pointed to probe response data
6068 * but is always valid
6069 */
6063 ies = rcu_dereference(res->ies); 6070 ies = rcu_dereference(res->ies);
6064 if (ies) { 6071 if (ies) {
6065 if (nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf)) 6072 if (nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf))
6066 goto fail_unlock_rcu; 6073 goto fail_unlock_rcu;
6067 tsf = true;
6068 if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS, 6074 if (ies->len && nla_put(msg, NL80211_BSS_INFORMATION_ELEMENTS,
6069 ies->len, ies->data)) 6075 ies->len, ies->data))
6070 goto fail_unlock_rcu; 6076 goto fail_unlock_rcu;
6071 } 6077 }
6078
6079 /* and this pointer is always (unless driver didn't know) beacon data */
6072 ies = rcu_dereference(res->beacon_ies); 6080 ies = rcu_dereference(res->beacon_ies);
6073 if (ies) { 6081 if (ies && ies->from_beacon) {
6074 if (!tsf && nla_put_u64(msg, NL80211_BSS_TSF, ies->tsf)) 6082 if (nla_put_u64(msg, NL80211_BSS_BEACON_TSF, ies->tsf))
6075 goto fail_unlock_rcu; 6083 goto fail_unlock_rcu;
6076 if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES, 6084 if (ies->len && nla_put(msg, NL80211_BSS_BEACON_IES,
6077 ies->len, ies->data)) 6085 ies->len, ies->data))
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 0798c62e6085..ad1a1a2808d3 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -918,11 +918,12 @@ cfg80211_inform_bss_width(struct wiphy *wiphy,
918 * override the IEs pointer should we have received an earlier 918 * override the IEs pointer should we have received an earlier
919 * indication of Probe Response data. 919 * indication of Probe Response data.
920 */ 920 */
921 ies = kmalloc(sizeof(*ies) + ielen, gfp); 921 ies = kzalloc(sizeof(*ies) + ielen, gfp);
922 if (!ies) 922 if (!ies)
923 return NULL; 923 return NULL;
924 ies->len = ielen; 924 ies->len = ielen;
925 ies->tsf = tsf; 925 ies->tsf = tsf;
926 ies->from_beacon = false;
926 memcpy(ies->data, ie, ielen); 927 memcpy(ies->data, ie, ielen);
927 928
928 rcu_assign_pointer(tmp.pub.beacon_ies, ies); 929 rcu_assign_pointer(tmp.pub.beacon_ies, ies);
@@ -982,11 +983,12 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy,
982 if (!channel) 983 if (!channel)
983 return NULL; 984 return NULL;
984 985
985 ies = kmalloc(sizeof(*ies) + ielen, gfp); 986 ies = kzalloc(sizeof(*ies) + ielen, gfp);
986 if (!ies) 987 if (!ies)
987 return NULL; 988 return NULL;
988 ies->len = ielen; 989 ies->len = ielen;
989 ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp); 990 ies->tsf = le64_to_cpu(mgmt->u.probe_resp.timestamp);
991 ies->from_beacon = ieee80211_is_beacon(mgmt->frame_control);
990 memcpy(ies->data, mgmt->u.probe_resp.variable, ielen); 992 memcpy(ies->data, mgmt->u.probe_resp.variable, ielen);
991 993
992 if (ieee80211_is_probe_resp(mgmt->frame_control)) 994 if (ieee80211_is_probe_resp(mgmt->frame_control))