bss.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. /*
  2. * BSS table
  3. * Copyright (c) 2009-2010, Jouni Malinen <j@w1.fi>
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "utils/includes.h"
  9. #include "utils/common.h"
  10. #include "utils/eloop.h"
  11. #include "common/ieee802_11_defs.h"
  12. #include "drivers/driver.h"
  13. #include "wpa_supplicant_i.h"
  14. #include "config.h"
  15. #include "notify.h"
  16. #include "scan.h"
  17. #include "bss.h"
  18. /**
  19. * WPA_BSS_EXPIRATION_PERIOD - Period of expiration run in seconds
  20. */
  21. #define WPA_BSS_EXPIRATION_PERIOD 10
  22. #define WPA_BSS_FREQ_CHANGED_FLAG BIT(0)
  23. #define WPA_BSS_SIGNAL_CHANGED_FLAG BIT(1)
  24. #define WPA_BSS_PRIVACY_CHANGED_FLAG BIT(2)
  25. #define WPA_BSS_MODE_CHANGED_FLAG BIT(3)
  26. #define WPA_BSS_WPAIE_CHANGED_FLAG BIT(4)
  27. #define WPA_BSS_RSNIE_CHANGED_FLAG BIT(5)
  28. #define WPA_BSS_WPS_CHANGED_FLAG BIT(6)
  29. #define WPA_BSS_RATES_CHANGED_FLAG BIT(7)
  30. #define WPA_BSS_IES_CHANGED_FLAG BIT(8)
  31. static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
  32. const char *reason)
  33. {
  34. if (wpa_s->last_scan_res) {
  35. unsigned int i;
  36. for (i = 0; i < wpa_s->last_scan_res_used; i++) {
  37. if (wpa_s->last_scan_res[i] == bss) {
  38. os_memmove(&wpa_s->last_scan_res[i],
  39. &wpa_s->last_scan_res[i + 1],
  40. (wpa_s->last_scan_res_used - i - 1)
  41. * sizeof(struct wpa_bss *));
  42. wpa_s->last_scan_res_used--;
  43. break;
  44. }
  45. }
  46. }
  47. dl_list_del(&bss->list);
  48. dl_list_del(&bss->list_id);
  49. wpa_s->num_bss--;
  50. wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Remove id %u BSSID " MACSTR
  51. " SSID '%s' due to %s", bss->id, MAC2STR(bss->bssid),
  52. wpa_ssid_txt(bss->ssid, bss->ssid_len), reason);
  53. wpas_notify_bss_removed(wpa_s, bss->bssid, bss->id);
  54. #ifdef CONFIG_INTERWORKING
  55. wpabuf_free(bss->anqp_venue_name);
  56. wpabuf_free(bss->anqp_network_auth_type);
  57. wpabuf_free(bss->anqp_roaming_consortium);
  58. wpabuf_free(bss->anqp_ip_addr_type_availability);
  59. wpabuf_free(bss->anqp_nai_realm);
  60. wpabuf_free(bss->anqp_3gpp);
  61. wpabuf_free(bss->anqp_domain_name);
  62. #endif /* CONFIG_INTERWORKING */
  63. #ifdef CONFIG_HS20
  64. wpabuf_free(bss->hs20_operator_friendly_name);
  65. wpabuf_free(bss->hs20_wan_metrics);
  66. wpabuf_free(bss->hs20_connection_capability);
  67. wpabuf_free(bss->hs20_operating_class);
  68. #endif /* CONFIG_HS20 */
  69. os_free(bss);
  70. }
  71. struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid,
  72. const u8 *ssid, size_t ssid_len)
  73. {
  74. struct wpa_bss *bss;
  75. if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
  76. return NULL;
  77. dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
  78. if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 &&
  79. bss->ssid_len == ssid_len &&
  80. os_memcmp(bss->ssid, ssid, ssid_len) == 0)
  81. return bss;
  82. }
  83. return NULL;
  84. }
  85. static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src)
  86. {
  87. os_time_t usec;
  88. dst->flags = src->flags;
  89. os_memcpy(dst->bssid, src->bssid, ETH_ALEN);
  90. dst->freq = src->freq;
  91. dst->beacon_int = src->beacon_int;
  92. dst->caps = src->caps;
  93. dst->qual = src->qual;
  94. dst->noise = src->noise;
  95. dst->level = src->level;
  96. dst->tsf = src->tsf;
  97. os_get_time(&dst->last_update);
  98. dst->last_update.sec -= src->age / 1000;
  99. usec = (src->age % 1000) * 1000;
  100. if (dst->last_update.usec < usec) {
  101. dst->last_update.sec--;
  102. dst->last_update.usec += 1000000;
  103. }
  104. dst->last_update.usec -= usec;
  105. }
  106. static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
  107. {
  108. struct wpa_ssid *ssid;
  109. for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) {
  110. if (ssid->ssid == NULL || ssid->ssid_len == 0)
  111. continue;
  112. if (ssid->ssid_len == bss->ssid_len &&
  113. os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) == 0)
  114. return 1;
  115. }
  116. return 0;
  117. }
  118. static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss)
  119. {
  120. return bss == wpa_s->current_bss ||
  121. os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 ||
  122. os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0;
  123. }
  124. static int wpa_bss_remove_oldest_unknown(struct wpa_supplicant *wpa_s)
  125. {
  126. struct wpa_bss *bss;
  127. dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
  128. if (!wpa_bss_known(wpa_s, bss)) {
  129. wpa_bss_remove(wpa_s, bss, __func__);
  130. return 0;
  131. }
  132. }
  133. return -1;
  134. }
  135. static int wpa_bss_remove_oldest(struct wpa_supplicant *wpa_s)
  136. {
  137. struct wpa_bss *bss;
  138. /*
  139. * Remove the oldest entry that does not match with any configured
  140. * network.
  141. */
  142. if (wpa_bss_remove_oldest_unknown(wpa_s) == 0)
  143. return 0;
  144. /*
  145. * Remove the oldest entry that isn't currently in use.
  146. */
  147. dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
  148. if (!wpa_bss_in_use(wpa_s, bss)) {
  149. wpa_bss_remove(wpa_s, bss, __func__);
  150. return 0;
  151. }
  152. }
  153. return -1;
  154. }
  155. static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s,
  156. const u8 *ssid, size_t ssid_len,
  157. struct wpa_scan_res *res)
  158. {
  159. struct wpa_bss *bss;
  160. bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len);
  161. if (bss == NULL)
  162. return NULL;
  163. bss->id = wpa_s->bss_next_id++;
  164. bss->last_update_idx = wpa_s->bss_update_idx;
  165. wpa_bss_copy_res(bss, res);
  166. os_memcpy(bss->ssid, ssid, ssid_len);
  167. bss->ssid_len = ssid_len;
  168. bss->ie_len = res->ie_len;
  169. bss->beacon_ie_len = res->beacon_ie_len;
  170. os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
  171. dl_list_add_tail(&wpa_s->bss, &bss->list);
  172. dl_list_add_tail(&wpa_s->bss_id, &bss->list_id);
  173. wpa_s->num_bss++;
  174. wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR
  175. " SSID '%s'",
  176. bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len));
  177. wpas_notify_bss_added(wpa_s, bss->bssid, bss->id);
  178. if (wpa_s->num_bss > wpa_s->conf->bss_max_count &&
  179. wpa_bss_remove_oldest(wpa_s) != 0) {
  180. wpa_printf(MSG_ERROR, "Increasing the MAX BSS count to %d "
  181. "because all BSSes are in use. We should normally "
  182. "not get here!", (int) wpa_s->num_bss);
  183. wpa_s->conf->bss_max_count = wpa_s->num_bss;
  184. }
  185. return bss;
  186. }
  187. static int are_ies_equal(const struct wpa_bss *old,
  188. const struct wpa_scan_res *new, u32 ie)
  189. {
  190. const u8 *old_ie, *new_ie;
  191. struct wpabuf *old_ie_buff = NULL;
  192. struct wpabuf *new_ie_buff = NULL;
  193. int new_ie_len, old_ie_len, ret, is_multi;
  194. switch (ie) {
  195. case WPA_IE_VENDOR_TYPE:
  196. old_ie = wpa_bss_get_vendor_ie(old, ie);
  197. new_ie = wpa_scan_get_vendor_ie(new, ie);
  198. is_multi = 0;
  199. break;
  200. case WPS_IE_VENDOR_TYPE:
  201. old_ie_buff = wpa_bss_get_vendor_ie_multi(old, ie);
  202. new_ie_buff = wpa_scan_get_vendor_ie_multi(new, ie);
  203. is_multi = 1;
  204. break;
  205. case WLAN_EID_RSN:
  206. case WLAN_EID_SUPP_RATES:
  207. case WLAN_EID_EXT_SUPP_RATES:
  208. old_ie = wpa_bss_get_ie(old, ie);
  209. new_ie = wpa_scan_get_ie(new, ie);
  210. is_multi = 0;
  211. break;
  212. default:
  213. wpa_printf(MSG_DEBUG, "bss: %s: cannot compare IEs", __func__);
  214. return 0;
  215. }
  216. if (is_multi) {
  217. /* in case of multiple IEs stored in buffer */
  218. old_ie = old_ie_buff ? wpabuf_head_u8(old_ie_buff) : NULL;
  219. new_ie = new_ie_buff ? wpabuf_head_u8(new_ie_buff) : NULL;
  220. old_ie_len = old_ie_buff ? wpabuf_len(old_ie_buff) : 0;
  221. new_ie_len = new_ie_buff ? wpabuf_len(new_ie_buff) : 0;
  222. } else {
  223. /* in case of single IE */
  224. old_ie_len = old_ie ? old_ie[1] + 2 : 0;
  225. new_ie_len = new_ie ? new_ie[1] + 2 : 0;
  226. }
  227. if (!old_ie || !new_ie)
  228. ret = !old_ie && !new_ie;
  229. else
  230. ret = (old_ie_len == new_ie_len &&
  231. os_memcmp(old_ie, new_ie, old_ie_len) == 0);
  232. wpabuf_free(old_ie_buff);
  233. wpabuf_free(new_ie_buff);
  234. return ret;
  235. }
  236. static u32 wpa_bss_compare_res(const struct wpa_bss *old,
  237. const struct wpa_scan_res *new)
  238. {
  239. u32 changes = 0;
  240. int caps_diff = old->caps ^ new->caps;
  241. if (old->freq != new->freq)
  242. changes |= WPA_BSS_FREQ_CHANGED_FLAG;
  243. if (old->level != new->level)
  244. changes |= WPA_BSS_SIGNAL_CHANGED_FLAG;
  245. if (caps_diff & IEEE80211_CAP_PRIVACY)
  246. changes |= WPA_BSS_PRIVACY_CHANGED_FLAG;
  247. if (caps_diff & IEEE80211_CAP_IBSS)
  248. changes |= WPA_BSS_MODE_CHANGED_FLAG;
  249. if (old->ie_len == new->ie_len &&
  250. os_memcmp(old + 1, new + 1, old->ie_len) == 0)
  251. return changes;
  252. changes |= WPA_BSS_IES_CHANGED_FLAG;
  253. if (!are_ies_equal(old, new, WPA_IE_VENDOR_TYPE))
  254. changes |= WPA_BSS_WPAIE_CHANGED_FLAG;
  255. if (!are_ies_equal(old, new, WLAN_EID_RSN))
  256. changes |= WPA_BSS_RSNIE_CHANGED_FLAG;
  257. if (!are_ies_equal(old, new, WPS_IE_VENDOR_TYPE))
  258. changes |= WPA_BSS_WPS_CHANGED_FLAG;
  259. if (!are_ies_equal(old, new, WLAN_EID_SUPP_RATES) ||
  260. !are_ies_equal(old, new, WLAN_EID_EXT_SUPP_RATES))
  261. changes |= WPA_BSS_RATES_CHANGED_FLAG;
  262. return changes;
  263. }
  264. static void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes,
  265. const struct wpa_bss *bss)
  266. {
  267. if (changes & WPA_BSS_FREQ_CHANGED_FLAG)
  268. wpas_notify_bss_freq_changed(wpa_s, bss->id);
  269. if (changes & WPA_BSS_SIGNAL_CHANGED_FLAG)
  270. wpas_notify_bss_signal_changed(wpa_s, bss->id);
  271. if (changes & WPA_BSS_PRIVACY_CHANGED_FLAG)
  272. wpas_notify_bss_privacy_changed(wpa_s, bss->id);
  273. if (changes & WPA_BSS_MODE_CHANGED_FLAG)
  274. wpas_notify_bss_mode_changed(wpa_s, bss->id);
  275. if (changes & WPA_BSS_WPAIE_CHANGED_FLAG)
  276. wpas_notify_bss_wpaie_changed(wpa_s, bss->id);
  277. if (changes & WPA_BSS_RSNIE_CHANGED_FLAG)
  278. wpas_notify_bss_rsnie_changed(wpa_s, bss->id);
  279. if (changes & WPA_BSS_WPS_CHANGED_FLAG)
  280. wpas_notify_bss_wps_changed(wpa_s, bss->id);
  281. if (changes & WPA_BSS_IES_CHANGED_FLAG)
  282. wpas_notify_bss_ies_changed(wpa_s, bss->id);
  283. if (changes & WPA_BSS_RATES_CHANGED_FLAG)
  284. wpas_notify_bss_rates_changed(wpa_s, bss->id);
  285. }
  286. static void wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss,
  287. struct wpa_scan_res *res)
  288. {
  289. u32 changes;
  290. changes = wpa_bss_compare_res(bss, res);
  291. bss->scan_miss_count = 0;
  292. bss->last_update_idx = wpa_s->bss_update_idx;
  293. wpa_bss_copy_res(bss, res);
  294. /* Move the entry to the end of the list */
  295. dl_list_del(&bss->list);
  296. if (bss->ie_len + bss->beacon_ie_len >=
  297. res->ie_len + res->beacon_ie_len) {
  298. os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len);
  299. bss->ie_len = res->ie_len;
  300. bss->beacon_ie_len = res->beacon_ie_len;
  301. } else {
  302. struct wpa_bss *nbss;
  303. struct dl_list *prev = bss->list_id.prev;
  304. dl_list_del(&bss->list_id);
  305. nbss = os_realloc(bss, sizeof(*bss) + res->ie_len +
  306. res->beacon_ie_len);
  307. if (nbss) {
  308. if (wpa_s->current_bss == bss)
  309. wpa_s->current_bss = nbss;
  310. bss = nbss;
  311. os_memcpy(bss + 1, res + 1,
  312. res->ie_len + res->beacon_ie_len);
  313. bss->ie_len = res->ie_len;
  314. bss->beacon_ie_len = res->beacon_ie_len;
  315. }
  316. dl_list_add(prev, &bss->list_id);
  317. }
  318. dl_list_add_tail(&wpa_s->bss, &bss->list);
  319. notify_bss_changes(wpa_s, changes, bss);
  320. }
  321. void wpa_bss_update_start(struct wpa_supplicant *wpa_s)
  322. {
  323. wpa_s->bss_update_idx++;
  324. wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Start scan result update %u",
  325. wpa_s->bss_update_idx);
  326. wpa_s->last_scan_res_used = 0;
  327. }
  328. void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s,
  329. struct wpa_scan_res *res)
  330. {
  331. const u8 *ssid, *p2p;
  332. struct wpa_bss *bss;
  333. ssid = wpa_scan_get_ie(res, WLAN_EID_SSID);
  334. if (ssid == NULL) {
  335. wpa_dbg(wpa_s, MSG_DEBUG, "BSS: No SSID IE included for "
  336. MACSTR, MAC2STR(res->bssid));
  337. return;
  338. }
  339. if (ssid[1] > 32) {
  340. wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Too long SSID IE included for "
  341. MACSTR, MAC2STR(res->bssid));
  342. return;
  343. }
  344. p2p = wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE);
  345. #ifdef CONFIG_P2P
  346. if (p2p == NULL &&
  347. wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) {
  348. /*
  349. * If it's a P2P specific interface, then don't update
  350. * the scan result without a P2P IE.
  351. */
  352. wpa_printf(MSG_DEBUG, "BSS: No P2P IE - skipping BSS " MACSTR
  353. " update for P2P interface", MAC2STR(res->bssid));
  354. return;
  355. }
  356. #endif /* CONFIG_P2P */
  357. if (p2p && ssid[1] == P2P_WILDCARD_SSID_LEN &&
  358. os_memcmp(ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0)
  359. return; /* Skip P2P listen discovery results here */
  360. /* TODO: add option for ignoring BSSes we are not interested in
  361. * (to save memory) */
  362. bss = wpa_bss_get(wpa_s, res->bssid, ssid + 2, ssid[1]);
  363. if (bss == NULL)
  364. bss = wpa_bss_add(wpa_s, ssid + 2, ssid[1], res);
  365. else
  366. wpa_bss_update(wpa_s, bss, res);
  367. if (bss == NULL)
  368. return;
  369. if (wpa_s->last_scan_res_used >= wpa_s->last_scan_res_size) {
  370. struct wpa_bss **n;
  371. unsigned int siz;
  372. if (wpa_s->last_scan_res_size == 0)
  373. siz = 32;
  374. else
  375. siz = wpa_s->last_scan_res_size * 2;
  376. n = os_realloc_array(wpa_s->last_scan_res, siz,
  377. sizeof(struct wpa_bss *));
  378. if (n == NULL)
  379. return;
  380. wpa_s->last_scan_res = n;
  381. wpa_s->last_scan_res_size = siz;
  382. }
  383. wpa_s->last_scan_res[wpa_s->last_scan_res_used++] = bss;
  384. }
  385. static int wpa_bss_included_in_scan(const struct wpa_bss *bss,
  386. const struct scan_info *info)
  387. {
  388. int found;
  389. size_t i;
  390. if (info == NULL)
  391. return 1;
  392. if (info->num_freqs) {
  393. found = 0;
  394. for (i = 0; i < info->num_freqs; i++) {
  395. if (bss->freq == info->freqs[i]) {
  396. found = 1;
  397. break;
  398. }
  399. }
  400. if (!found)
  401. return 0;
  402. }
  403. if (info->num_ssids) {
  404. found = 0;
  405. for (i = 0; i < info->num_ssids; i++) {
  406. const struct wpa_driver_scan_ssid *s = &info->ssids[i];
  407. if ((s->ssid == NULL || s->ssid_len == 0) ||
  408. (s->ssid_len == bss->ssid_len &&
  409. os_memcmp(s->ssid, bss->ssid, bss->ssid_len) ==
  410. 0)) {
  411. found = 1;
  412. break;
  413. }
  414. }
  415. if (!found)
  416. return 0;
  417. }
  418. return 1;
  419. }
  420. void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info,
  421. int new_scan)
  422. {
  423. struct wpa_bss *bss, *n;
  424. wpa_s->last_scan_full = 0;
  425. os_get_time(&wpa_s->last_scan);
  426. if (!new_scan)
  427. return; /* do not expire entries without new scan */
  428. if (info && !info->aborted && !info->freqs) {
  429. size_t i;
  430. if (info->num_ssids == 0) {
  431. wpa_s->last_scan_full = 1;
  432. } else {
  433. for (i = 0; i < info->num_ssids; i++) {
  434. if (info->ssids[i].ssid == NULL ||
  435. info->ssids[i].ssid_len == 0) {
  436. wpa_s->last_scan_full = 1;
  437. break;
  438. }
  439. }
  440. }
  441. }
  442. dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
  443. if (wpa_bss_in_use(wpa_s, bss))
  444. continue;
  445. if (!wpa_bss_included_in_scan(bss, info))
  446. continue; /* expire only BSSes that were scanned */
  447. if (bss->last_update_idx < wpa_s->bss_update_idx)
  448. bss->scan_miss_count++;
  449. if (bss->scan_miss_count >=
  450. wpa_s->conf->bss_expiration_scan_count) {
  451. wpa_bss_remove(wpa_s, bss, "no match in scan");
  452. }
  453. }
  454. wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%u/%u "
  455. "last_scan_full=%d",
  456. wpa_s->last_scan_res_used, wpa_s->last_scan_res_size,
  457. wpa_s->last_scan_full);
  458. }
  459. void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age)
  460. {
  461. struct wpa_bss *bss, *n;
  462. struct os_time t;
  463. if (dl_list_empty(&wpa_s->bss))
  464. return;
  465. os_get_time(&t);
  466. t.sec -= age;
  467. dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
  468. if (wpa_bss_in_use(wpa_s, bss))
  469. continue;
  470. if (os_time_before(&bss->last_update, &t)) {
  471. wpa_bss_remove(wpa_s, bss, __func__);
  472. } else
  473. break;
  474. }
  475. }
  476. static void wpa_bss_timeout(void *eloop_ctx, void *timeout_ctx)
  477. {
  478. struct wpa_supplicant *wpa_s = eloop_ctx;
  479. wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age);
  480. eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD, 0,
  481. wpa_bss_timeout, wpa_s, NULL);
  482. }
  483. int wpa_bss_init(struct wpa_supplicant *wpa_s)
  484. {
  485. dl_list_init(&wpa_s->bss);
  486. dl_list_init(&wpa_s->bss_id);
  487. eloop_register_timeout(WPA_BSS_EXPIRATION_PERIOD, 0,
  488. wpa_bss_timeout, wpa_s, NULL);
  489. return 0;
  490. }
  491. void wpa_bss_flush(struct wpa_supplicant *wpa_s)
  492. {
  493. struct wpa_bss *bss, *n;
  494. if (wpa_s->bss.next == NULL)
  495. return; /* BSS table not yet initialized */
  496. dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) {
  497. if (wpa_bss_in_use(wpa_s, bss))
  498. continue;
  499. wpa_bss_remove(wpa_s, bss, __func__);
  500. }
  501. }
  502. void wpa_bss_deinit(struct wpa_supplicant *wpa_s)
  503. {
  504. eloop_cancel_timeout(wpa_bss_timeout, wpa_s, NULL);
  505. wpa_bss_flush(wpa_s);
  506. }
  507. struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s,
  508. const u8 *bssid)
  509. {
  510. struct wpa_bss *bss;
  511. if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid))
  512. return NULL;
  513. dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
  514. if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0)
  515. return bss;
  516. }
  517. return NULL;
  518. }
  519. #ifdef CONFIG_P2P
  520. struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s,
  521. const u8 *dev_addr)
  522. {
  523. struct wpa_bss *bss;
  524. dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) {
  525. u8 addr[ETH_ALEN];
  526. if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len,
  527. addr) == 0 &&
  528. os_memcmp(addr, dev_addr, ETH_ALEN) == 0)
  529. return bss;
  530. }
  531. return NULL;
  532. }
  533. #endif /* CONFIG_P2P */
  534. struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id)
  535. {
  536. struct wpa_bss *bss;
  537. dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) {
  538. if (bss->id == id)
  539. return bss;
  540. }
  541. return NULL;
  542. }
  543. const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie)
  544. {
  545. const u8 *end, *pos;
  546. pos = (const u8 *) (bss + 1);
  547. end = pos + bss->ie_len;
  548. while (pos + 1 < end) {
  549. if (pos + 2 + pos[1] > end)
  550. break;
  551. if (pos[0] == ie)
  552. return pos;
  553. pos += 2 + pos[1];
  554. }
  555. return NULL;
  556. }
  557. const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type)
  558. {
  559. const u8 *end, *pos;
  560. pos = (const u8 *) (bss + 1);
  561. end = pos + bss->ie_len;
  562. while (pos + 1 < end) {
  563. if (pos + 2 + pos[1] > end)
  564. break;
  565. if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
  566. vendor_type == WPA_GET_BE32(&pos[2]))
  567. return pos;
  568. pos += 2 + pos[1];
  569. }
  570. return NULL;
  571. }
  572. struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss,
  573. u32 vendor_type)
  574. {
  575. struct wpabuf *buf;
  576. const u8 *end, *pos;
  577. buf = wpabuf_alloc(bss->ie_len);
  578. if (buf == NULL)
  579. return NULL;
  580. pos = (const u8 *) (bss + 1);
  581. end = pos + bss->ie_len;
  582. while (pos + 1 < end) {
  583. if (pos + 2 + pos[1] > end)
  584. break;
  585. if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
  586. vendor_type == WPA_GET_BE32(&pos[2]))
  587. wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
  588. pos += 2 + pos[1];
  589. }
  590. if (wpabuf_len(buf) == 0) {
  591. wpabuf_free(buf);
  592. buf = NULL;
  593. }
  594. return buf;
  595. }
  596. int wpa_bss_get_max_rate(const struct wpa_bss *bss)
  597. {
  598. int rate = 0;
  599. const u8 *ie;
  600. int i;
  601. ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
  602. for (i = 0; ie && i < ie[1]; i++) {
  603. if ((ie[i + 2] & 0x7f) > rate)
  604. rate = ie[i + 2] & 0x7f;
  605. }
  606. ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
  607. for (i = 0; ie && i < ie[1]; i++) {
  608. if ((ie[i + 2] & 0x7f) > rate)
  609. rate = ie[i + 2] & 0x7f;
  610. }
  611. return rate;
  612. }
  613. int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates)
  614. {
  615. const u8 *ie, *ie2;
  616. int i, j;
  617. unsigned int len;
  618. u8 *r;
  619. ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES);
  620. ie2 = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES);
  621. len = (ie ? ie[1] : 0) + (ie2 ? ie2[1] : 0);
  622. r = os_malloc(len);
  623. if (!r)
  624. return -1;
  625. for (i = 0; ie && i < ie[1]; i++)
  626. r[i] = ie[i + 2] & 0x7f;
  627. for (j = 0; ie2 && j < ie2[1]; j++)
  628. r[i + j] = ie2[j + 2] & 0x7f;
  629. *rates = r;
  630. return len;
  631. }