2 * hostapd / Neighboring APs DB
3 * Copyright(c) 2013 - 2016 Intel Mobile Communications GmbH.
4 * Copyright(c) 2011 - 2016 Intel Corporation. All rights reserved.
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
10 #include "utils/includes.h"
12 #include "utils/common.h"
14 #include "ieee802_11.h"
15 #include "neighbor_db.h"
18 struct hostapd_neighbor_entry *
19 hostapd_neighbor_get(struct hostapd_data *hapd, const u8 *bssid,
20 const struct wpa_ssid_value *ssid)
22 struct hostapd_neighbor_entry *nr;
24 dl_list_for_each(nr, &hapd->nr_db, struct hostapd_neighbor_entry,
26 if (os_memcmp(bssid, nr->bssid, ETH_ALEN) == 0 &&
28 (ssid->ssid_len == nr->ssid.ssid_len &&
29 os_memcmp(ssid->ssid, nr->ssid.ssid,
30 ssid->ssid_len) == 0)))
37 static void hostapd_neighbor_clear_entry(struct hostapd_neighbor_entry *nr)
43 wpabuf_free(nr->civic);
45 os_memset(nr->bssid, 0, sizeof(nr->bssid));
46 os_memset(&nr->ssid, 0, sizeof(nr->ssid));
51 static struct hostapd_neighbor_entry *
52 hostapd_neighbor_add(struct hostapd_data *hapd)
54 struct hostapd_neighbor_entry *nr;
56 nr = os_zalloc(sizeof(struct hostapd_neighbor_entry));
60 dl_list_add(&hapd->nr_db, &nr->list);
66 int hostapd_neighbor_set(struct hostapd_data *hapd, const u8 *bssid,
67 const struct wpa_ssid_value *ssid,
68 const struct wpabuf *nr, const struct wpabuf *lci,
69 const struct wpabuf *civic, int stationary)
71 struct hostapd_neighbor_entry *entry;
73 entry = hostapd_neighbor_get(hapd, bssid, ssid);
75 entry = hostapd_neighbor_add(hapd);
79 hostapd_neighbor_clear_entry(entry);
81 os_memcpy(entry->bssid, bssid, ETH_ALEN);
82 os_memcpy(&entry->ssid, ssid, sizeof(entry->ssid));
84 entry->nr = wpabuf_dup(nr);
88 if (lci && wpabuf_len(lci)) {
89 entry->lci = wpabuf_dup(lci);
90 if (!entry->lci || os_get_time(&entry->lci_date))
94 if (civic && wpabuf_len(civic)) {
95 entry->civic = wpabuf_dup(civic);
100 entry->stationary = stationary;
105 hostapd_neighbor_remove(hapd, bssid, ssid);
110 int hostapd_neighbor_remove(struct hostapd_data *hapd, const u8 *bssid,
111 const struct wpa_ssid_value *ssid)
113 struct hostapd_neighbor_entry *nr;
115 nr = hostapd_neighbor_get(hapd, bssid, ssid);
119 hostapd_neighbor_clear_entry(nr);
120 dl_list_del(&nr->list);
127 void hostapd_free_neighbor_db(struct hostapd_data *hapd)
129 struct hostapd_neighbor_entry *nr, *prev;
131 dl_list_for_each_safe(nr, prev, &hapd->nr_db,
132 struct hostapd_neighbor_entry, list) {
133 hostapd_neighbor_clear_entry(nr);
134 dl_list_del(&nr->list);
141 static enum nr_chan_width hostapd_get_nr_chan_width(struct hostapd_data *hapd,
142 int ht, int vht, int he)
144 u8 oper_chwidth = hostapd_get_oper_chwidth(hapd->iconf);
146 if (!ht && !vht && !he)
147 return NR_CHAN_WIDTH_20;
148 if (!hapd->iconf->secondary_channel)
149 return NR_CHAN_WIDTH_20;
150 if ((!vht && !he) || oper_chwidth == CHANWIDTH_USE_HT)
151 return NR_CHAN_WIDTH_40;
152 if (oper_chwidth == CHANWIDTH_80MHZ)
153 return NR_CHAN_WIDTH_80;
154 if (oper_chwidth == CHANWIDTH_160MHZ)
155 return NR_CHAN_WIDTH_160;
156 if (oper_chwidth == CHANWIDTH_80P80MHZ)
157 return NR_CHAN_WIDTH_80P80;
158 return NR_CHAN_WIDTH_20;
160 #endif /* NEED_AP_MLME */
163 void hostapd_neighbor_set_own_report(struct hostapd_data *hapd)
166 u16 capab = hostapd_own_capab_info(hapd);
167 int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n;
168 int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac;
169 int he = hapd->iconf->ieee80211ax;
170 struct wpa_ssid_value ssid;
171 u8 channel, op_class;
172 u8 center_freq1_idx = 0, center_freq2_idx = 0;
173 enum nr_chan_width width;
177 if (!(hapd->conf->radio_measurements[0] &
178 WLAN_RRM_CAPS_NEIGHBOR_REPORT))
181 bssid_info = 3; /* AP is reachable */
182 bssid_info |= NEI_REP_BSSID_INFO_SECURITY; /* "same as the AP" */
183 bssid_info |= NEI_REP_BSSID_INFO_KEY_SCOPE; /* "same as the AP" */
185 if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT)
186 bssid_info |= NEI_REP_BSSID_INFO_SPECTRUM_MGMT;
188 bssid_info |= NEI_REP_BSSID_INFO_RM; /* RRM is supported */
190 if (hapd->conf->wmm_enabled) {
191 bssid_info |= NEI_REP_BSSID_INFO_QOS;
193 if (hapd->conf->wmm_uapsd &&
194 (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD))
195 bssid_info |= NEI_REP_BSSID_INFO_APSD;
199 bssid_info |= NEI_REP_BSSID_INFO_HT |
200 NEI_REP_BSSID_INFO_DELAYED_BA;
202 /* VHT bit added in IEEE P802.11-REVmc/D4.3 */
204 bssid_info |= NEI_REP_BSSID_INFO_VHT;
207 /* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */
209 if (ieee80211_freq_to_channel_ext(hapd->iface->freq,
210 hapd->iconf->secondary_channel,
211 hostapd_get_oper_chwidth(hapd->iconf),
212 &op_class, &channel) ==
215 width = hostapd_get_nr_chan_width(hapd, ht, vht, he);
217 center_freq1_idx = hostapd_get_oper_centr_freq_seg0_idx(
219 if (width == NR_CHAN_WIDTH_80P80)
221 hostapd_get_oper_centr_freq_seg1_idx(
224 ieee80211_freq_to_chan(hapd->iface->freq +
225 10 * hapd->iconf->secondary_channel,
229 ssid.ssid_len = hapd->conf->ssid.ssid_len;
230 os_memcpy(ssid.ssid, hapd->conf->ssid.ssid, ssid.ssid_len);
233 * Neighbor Report element size = BSSID + BSSID info + op_class + chan +
234 * phy type + wide bandwidth channel subelement.
236 nr = wpabuf_alloc(ETH_ALEN + 4 + 1 + 1 + 1 + 5);
240 wpabuf_put_data(nr, hapd->own_addr, ETH_ALEN);
241 wpabuf_put_le32(nr, bssid_info);
242 wpabuf_put_u8(nr, op_class);
243 wpabuf_put_u8(nr, channel);
244 wpabuf_put_u8(nr, ieee80211_get_phy_type(hapd->iface->freq, ht, vht));
247 * Wide Bandwidth Channel subelement may be needed to allow the
248 * receiving STA to send packets to the AP. See IEEE P802.11-REVmc/D5.0
251 wpabuf_put_u8(nr, WNM_NEIGHBOR_WIDE_BW_CHAN);
252 wpabuf_put_u8(nr, 3);
253 wpabuf_put_u8(nr, width);
254 wpabuf_put_u8(nr, center_freq1_idx);
255 wpabuf_put_u8(nr, center_freq2_idx);
257 hostapd_neighbor_set(hapd, hapd->own_addr, &ssid, nr, hapd->iconf->lci,
258 hapd->iconf->civic, hapd->iconf->stationary_ap);
261 #endif /* NEED_AP_MLME */