aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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))