6 #include <linux/kernel.h>
7 #include <linux/slab.h>
8 #include <linux/module.h>
9 #include <linux/netdevice.h>
10 #include <linux/wireless.h>
21 #define IEEE80211_SCAN_RESULT_EXPIRE (30 * HZ)
27 #ifdef CONFIG_CFG80211_WEXT
53 #ifdef CONFIG_CFG80211_WEXT
55 memset(&wrqu, 0,
sizeof(wrqu));
85 cfg80211_lock_rdev(rdev);
87 cfg80211_unlock_rdev(rdev);
92 WARN_ON(request != wiphy_to_dev(request->
wiphy)->scan_req);
136 bool driver_initiated)
147 if (!driver_initiated) {
148 int err = rdev->
ops->sched_scan_stop(&rdev->wiphy, dev);
161 static void bss_release(
struct kref *ref)
166 if (bss->
pub.free_priv)
167 bss->
pub.free_priv(&bss->
pub);
181 unsigned long age_secs)
187 bss->
ts -= age_jiffies;
195 list_del_init(&bss->
list);
197 kref_put(&bss->
ref, bss_release);
204 bool expired =
false;
211 __cfg80211_unlink_bss(dev, bss);
221 while (len > 2 && ies[0] != eid) {
227 if (len < 2 + ies[1])
234 const u8 *ies,
int len)
246 if (end - pos <
sizeof(*ie))
250 ie_oui = ie->
oui[0] << 16 | ie->
oui[1] << 8 | ie->
oui[2];
251 if (ie_oui == oui && ie->
oui_type == oui_type)
260 static int cmp_ies(
u8 num,
u8 *ies1,
size_t len1,
u8 *ies2,
size_t len2)
275 if (ie1[1] != ie2[1])
276 return ie2[1] - ie1[1];
277 return memcmp(ie1 + 2, ie2 + 2, ie1[1]);
282 const u8 *
ssid,
size_t ssid_len)
286 if (bssid && !ether_addr_equal(a->
bssid, bssid))
297 if (ssidie[1] != ssid_len)
299 return memcmp(ssidie + 2, ssid, ssid_len) == 0;
325 const u8 *meshid,
size_t meshidlen,
338 if (ie[1] != meshidlen)
340 if (
memcmp(ie + 2, meshid, meshidlen))
356 return memcmp(ie + 2, meshcfg,
368 if (is_mesh_bss(a) && is_mesh_bss(b)) {
395 r = cmp_bss_core(a, b);
414 r = cmp_bss_core(a, b);
441 if (ie1[1] != ie2[1])
442 return ie2[1] - ie1[1];
445 for (i = 0; i < ie2[1]; i++)
455 const u8 *ssid,
size_t ssid_len,
456 u16 capa_mask,
u16 capa_val)
465 if ((bss->
pub.capability & capa_mask) != capa_val)
467 if (channel && bss->
pub.channel != channel)
473 if (is_bss(&bss->
pub, bssid, ssid, ssid_len)) {
489 const u8 *meshid,
size_t meshidlen,
498 if (channel && bss->
pub.channel != channel)
500 if (is_mesh(&bss->
pub, meshid, meshidlen, meshcfg)) {
527 cmp = cmp_bss(&bss->
pub, &tbss->
pub);
540 rb_link_node(&bss->
rbn, parent, p);
554 r = cmp_bss(&res->
pub, &bss->
pub);
577 r = cmp_hidden_bss(&res->
pub, &bss->
pub);
604 res->
pub.len_beacon_ies = hidden->
pub.len_beacon_ies;
606 res->
pub.len_beacon_ies);
620 kref_put(&res->
ref, bss_release);
628 found = rb_find_bss(dev, res);
631 found->
pub.beacon_interval = res->
pub.beacon_interval;
632 found->
pub.tsf = res->
pub.tsf;
633 found->
pub.signal = res->
pub.signal;
634 found->
pub.capability = res->
pub.capability;
638 if (res->
pub.proberesp_ies) {
639 size_t used = dev->wiphy.bss_priv_size +
sizeof(*res);
640 size_t ielen = res->
pub.len_proberesp_ies;
642 if (found->
pub.proberesp_ies &&
644 ksize(found) >= used + ielen) {
646 res->
pub.proberesp_ies, ielen);
647 found->
pub.len_proberesp_ies = ielen;
649 u8 *ies = found->
pub.proberesp_ies;
660 found->
pub.proberesp_ies = ies;
661 found->
pub.len_proberesp_ies = ielen;
666 found->
pub.information_elements =
667 found->
pub.proberesp_ies;
668 found->
pub.len_information_elements =
669 found->
pub.len_proberesp_ies;
671 if (res->
pub.beacon_ies) {
672 size_t used = dev->wiphy.bss_priv_size +
sizeof(*res);
673 size_t ielen = res->
pub.len_beacon_ies;
674 bool information_elements_is_beacon_ies =
675 (found->
pub.information_elements ==
676 found->
pub.beacon_ies);
678 if (found->
pub.beacon_ies &&
680 ksize(found) >= used + ielen) {
682 res->
pub.beacon_ies, ielen);
683 found->
pub.len_beacon_ies = ielen;
685 u8 *ies = found->
pub.beacon_ies;
696 found->
pub.beacon_ies = ies;
697 found->
pub.len_beacon_ies = ielen;
702 if (information_elements_is_beacon_ies) {
703 found->
pub.information_elements =
704 found->
pub.beacon_ies;
705 found->
pub.len_information_elements =
706 found->
pub.len_beacon_ies;
710 kref_put(&res->
ref, bss_release);
723 hidden = rb_find_hidden_bss(dev, res);
725 copy_hidden_ies(res, hidden);
729 rb_insert_bss(dev, res);
736 kref_get(&found->
ref);
756 (signal < 0 || signal > 100)))
759 res = kzalloc(
sizeof(*res) + privsz + ielen, gfp);
765 res->
pub.signal = signal;
780 res->
pub.beacon_ies = (
u8 *)res +
sizeof(*res) + privsz;
782 res->
pub.len_beacon_ies = ielen;
783 res->
pub.information_elements = res->
pub.beacon_ies;
784 res->
pub.len_information_elements = res->
pub.len_beacon_ies;
786 kref_init(&res->
ref);
788 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
808 u.probe_resp.variable);
818 (signal < 0 || signal > 100)))
826 res = kzalloc(
sizeof(*res) + privsz + ielen, gfp);
832 res->
pub.signal = signal;
841 res->
pub.proberesp_ies = (
u8 *) res +
sizeof(*res) + privsz;
842 memcpy(res->
pub.proberesp_ies, mgmt->
u.probe_resp.variable,
844 res->
pub.len_proberesp_ies = ielen;
845 res->
pub.information_elements = res->
pub.proberesp_ies;
846 res->
pub.len_information_elements = res->
pub.len_proberesp_ies;
848 res->
pub.beacon_ies = (
u8 *) res +
sizeof(*res) + privsz;
849 memcpy(res->
pub.beacon_ies, mgmt->
u.beacon.variable, ielen);
850 res->
pub.len_beacon_ies = ielen;
851 res->
pub.information_elements = res->
pub.beacon_ies;
852 res->
pub.len_information_elements = res->
pub.len_beacon_ies;
855 kref_init(&res->
ref);
857 res = cfg80211_bss_update(wiphy_to_dev(wiphy), res);
889 kref_put(&bss->
ref, bss_release);
904 if (!list_empty(&bss->
list)) {
905 __cfg80211_unlink_bss(dev, bss);
912 #ifdef CONFIG_CFG80211_WEXT
924 if (!netif_running(dev))
933 return PTR_ERR(rdev);
940 wiphy = &rdev->wiphy;
947 if (wiphy->
bands[band])
948 n_channels += wiphy->
bands[band]->n_channels;
951 creq = kzalloc(
sizeof(*creq) +
sizeof(
struct cfg80211_ssid) +
952 n_channels *
sizeof(
void *),
971 if (!wiphy->
bands[band])
974 for (j = 0; j < wiphy->
bands[band]->n_channels; j++) {
976 if (wiphy->
bands[band]->channels[j].flags &
986 int wiphy_freq = wiphy->
bands[band]->channels[
j].center_freq;
989 if (wext_freq == wiphy_freq)
990 goto wext_freq_found;
992 goto wext_freq_not_found;
998 wext_freq_not_found: ;
1025 if (wiphy->
bands[i])
1026 creq->
rates[
i] = (1 << wiphy->
bands[
i]->n_bitrates) - 1;
1029 err = rdev->
ops->scan(wiphy, creq);
1041 cfg80211_unlock_rdev(rdev);
1048 char **current_ev,
char *end_buf)
1065 next = pos + 2 + pos[1];
1067 next = next + 2 + next[1];
1069 memset(&iwe, 0,
sizeof(iwe));
1071 iwe.u.data.length = next -
pos;
1072 *current_ev = iwe_stream_add_point(info, *current_ev,
1073 end_buf, &iwe, pos);
1079 memset(&iwe, 0,
sizeof(iwe));
1081 iwe.u.data.length = end -
pos;
1082 *current_ev = iwe_stream_add_point(info, *current_ev,
1083 end_buf, &iwe, pos);
1087 static inline unsigned int elapsed_jiffies_msecs(
unsigned long start)
1104 u8 *ie = bss->
pub.information_elements;
1105 int rem = bss->
pub.len_information_elements,
i,
sig;
1106 bool ismesh =
false;
1108 memset(&iwe, 0,
sizeof(iwe));
1112 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1115 memset(&iwe, 0,
sizeof(iwe));
1119 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1122 memset(&iwe, 0,
sizeof(iwe));
1124 iwe.u.freq.m = bss->
pub.channel->center_freq;
1126 current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe,
1130 memset(&iwe, 0,
sizeof(iwe));
1137 sig = bss->
pub.signal / 100;
1138 iwe.u.qual.level =
sig;
1145 iwe.u.qual.qual = sig + 110;
1148 iwe.u.qual.level = bss->
pub.signal;
1150 iwe.u.qual.qual = bss->
pub.signal;
1156 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
1160 memset(&iwe, 0,
sizeof(iwe));
1166 iwe.u.data.length = 0;
1167 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1172 if (ie[1] > rem - 2)
1177 memset(&iwe, 0,
sizeof(iwe));
1179 iwe.u.data.length = ie[1];
1180 iwe.u.data.flags = 1;
1181 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1185 memset(&iwe, 0,
sizeof(iwe));
1187 iwe.u.data.length = ie[1];
1188 iwe.u.data.flags = 1;
1189 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1200 memset(&iwe, 0,
sizeof(iwe));
1202 sprintf(buf,
"Mesh Network Path Selection Protocol ID: "
1204 iwe.u.data.length =
strlen(buf);
1205 current_ev = iwe_stream_add_point(info, current_ev,
1208 sprintf(buf,
"Path Selection Metric ID: 0x%02X",
1210 iwe.u.data.length =
strlen(buf);
1211 current_ev = iwe_stream_add_point(info, current_ev,
1214 sprintf(buf,
"Congestion Control Mode ID: 0x%02X",
1216 iwe.u.data.length =
strlen(buf);
1217 current_ev = iwe_stream_add_point(info, current_ev,
1220 sprintf(buf,
"Synchronization ID: 0x%02X", cfg[3]);
1221 iwe.u.data.length =
strlen(buf);
1222 current_ev = iwe_stream_add_point(info, current_ev,
1225 sprintf(buf,
"Authentication ID: 0x%02X", cfg[4]);
1226 iwe.u.data.length =
strlen(buf);
1227 current_ev = iwe_stream_add_point(info, current_ev,
1230 sprintf(buf,
"Formation Info: 0x%02X", cfg[5]);
1231 iwe.u.data.length =
strlen(buf);
1232 current_ev = iwe_stream_add_point(info, current_ev,
1235 sprintf(buf,
"Capabilities: 0x%02X", cfg[6]);
1236 iwe.u.data.length =
strlen(buf);
1237 current_ev = iwe_stream_add_point(info, current_ev,
1245 p = current_ev + iwe_stream_lcp_len(info);
1247 memset(&iwe, 0,
sizeof(iwe));
1250 iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
1252 for (i = 0; i < ie[1]; i++) {
1253 iwe.u.bitrate.value =
1254 ((ie[i + 2] & 0x7f) * 500000);
1255 p = iwe_stream_add_value(info, current_ev, p,
1267 memset(&iwe, 0,
sizeof(iwe));
1275 current_ev = iwe_stream_add_event(info, current_ev, end_buf,
1281 memset(&iwe, 0,
sizeof(iwe));
1283 sprintf(buf,
"tsf=%016llx", (
unsigned long long)(bss->
pub.tsf));
1284 iwe.u.data.length =
strlen(buf);
1285 current_ev = iwe_stream_add_point(info, current_ev, end_buf,
1287 memset(&iwe, 0,
sizeof(iwe));
1289 sprintf(buf,
" Last beacon: %ums ago",
1290 elapsed_jiffies_msecs(bss->
ts));
1291 iwe.u.data.length =
strlen(buf);
1292 current_ev = iwe_stream_add_point(info, current_ev,
1293 end_buf, &iwe, buf);
1297 ieee80211_scan_add_ies(info, &bss->
pub, ¤t_ev, end_buf);
1305 char *buf,
size_t len)
1307 char *current_ev =
buf;
1308 char *end_buf = buf +
len;
1320 current_ev, end_buf);
1323 return current_ev -
buf;
1334 if (!netif_running(dev))
1340 return PTR_ERR(rdev);
1347 res = ieee80211_scan_results(rdev, info, extra, data->
length);
1355 cfg80211_unlock_rdev(rdev);