diff options
-rw-r--r-- | include/net/cfg80211.h | 2 | ||||
-rw-r--r-- | include/uapi/linux/nl80211.h | 16 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 16 | ||||
-rw-r--r-- | net/wireless/scan.c | 6 |
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 | */ |
1508 | struct cfg80211_bss_ies { | 1509 | struct 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)) |