aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
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 /net/wireless
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>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c16
-rw-r--r--net/wireless/scan.c6
2 files changed, 16 insertions, 6 deletions
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))