* Process a beacon or probe response frame; create an * entry in the scan cache or update any previous entry. */
| 235 | * entry in the scan cache or update any previous entry. |
| 236 | */ |
| 237 | static int |
| 238 | sta_add(struct ieee80211_scan_state *ss, |
| 239 | struct ieee80211_channel *curchan, |
| 240 | const struct ieee80211_scanparams *sp, |
| 241 | const struct ieee80211_frame *wh, |
| 242 | int subtype, int rssi, int noise) |
| 243 | { |
| 244 | #define ISPROBE(_st) ((_st) == IEEE80211_FC0_SUBTYPE_PROBE_RESP) |
| 245 | #define PICK1ST(_ss) \ |
| 246 | ((ss->ss_flags & (IEEE80211_SCAN_PICK1ST | IEEE80211_SCAN_GOTPICK)) == \ |
| 247 | IEEE80211_SCAN_PICK1ST) |
| 248 | struct sta_table *st = ss->ss_priv; |
| 249 | const uint8_t *macaddr = wh->i_addr2; |
| 250 | struct ieee80211vap *vap = ss->ss_vap; |
| 251 | struct ieee80211com *ic = vap->iv_ic; |
| 252 | struct ieee80211_channel *c; |
| 253 | struct sta_entry *se; |
| 254 | struct ieee80211_scan_entry *ise; |
| 255 | int hash; |
| 256 | |
| 257 | hash = STA_HASH(macaddr); |
| 258 | |
| 259 | IEEE80211_SCAN_TABLE_LOCK(st); |
| 260 | LIST_FOREACH(se, &st->st_hash[hash], se_hash) |
| 261 | if (IEEE80211_ADDR_EQ(se->base.se_macaddr, macaddr)) |
| 262 | goto found; |
| 263 | se = (struct sta_entry *) IEEE80211_MALLOC(sizeof(struct sta_entry), |
| 264 | M_80211_SCAN, IEEE80211_M_NOWAIT | IEEE80211_M_ZERO); |
| 265 | if (se == NULL) { |
| 266 | IEEE80211_SCAN_TABLE_UNLOCK(st); |
| 267 | return 0; |
| 268 | } |
| 269 | se->se_scangen = st->st_scaniter-1; |
| 270 | se->se_avgrssi = IEEE80211_RSSI_DUMMY_MARKER; |
| 271 | IEEE80211_ADDR_COPY(se->base.se_macaddr, macaddr); |
| 272 | TAILQ_INSERT_TAIL(&st->st_entry, se, se_list); |
| 273 | LIST_INSERT_HEAD(&st->st_hash[hash], se, se_hash); |
| 274 | found: |
| 275 | ise = &se->base; |
| 276 | /* XXX ap beaconing multiple ssid w/ same bssid */ |
| 277 | if (sp->ssid[1] != 0 && |
| 278 | (ISPROBE(subtype) || ise->se_ssid[1] == 0)) |
| 279 | memcpy(ise->se_ssid, sp->ssid, 2+sp->ssid[1]); |
| 280 | KASSERT(sp->rates[1] <= IEEE80211_RATE_MAXSIZE, |
| 281 | ("rate set too large: %u", sp->rates[1])); |
| 282 | memcpy(ise->se_rates, sp->rates, 2+sp->rates[1]); |
| 283 | if (sp->xrates != NULL) { |
| 284 | /* XXX validate xrates[1] */ |
| 285 | KASSERT(sp->xrates[1] <= IEEE80211_RATE_MAXSIZE, |
| 286 | ("xrate set too large: %u", sp->xrates[1])); |
| 287 | memcpy(ise->se_xrates, sp->xrates, 2+sp->xrates[1]); |
| 288 | } else |
| 289 | ise->se_xrates[1] = 0; |
| 290 | IEEE80211_ADDR_COPY(ise->se_bssid, wh->i_addr3); |
| 291 | if ((sp->status & IEEE80211_BPARSE_OFFCHAN) == 0) { |
| 292 | /* |
| 293 | * Record rssi data using extended precision LPF filter. |
| 294 | * |
nothing calls this directly
no test coverage detected