static void p2p_buf_add_noa_desc(struct wpabuf *buf, struct p2p_noa_desc *desc) { if (desc == NULL) return; wpabuf_put_u8(buf, desc->count_type); wpabuf_put_le32(buf, desc->duration); wpabuf_put_le32(buf, desc->interval); wpabuf_put_le32(buf, desc->start_time); }
void p2p_buf_add_session_id(struct wpabuf *buf, u32 id, const u8 *mac) { if (!buf || !mac) return; /* Session ID Info */ wpabuf_put_u8(buf, P2P_ATTR_SESSION_ID); wpabuf_put_le16(buf, (u16) (sizeof(u32) + ETH_ALEN)); wpabuf_put_le32(buf, id); wpabuf_put_data(buf, mac, ETH_ALEN); wpa_printf(MSG_DEBUG, "P2P: * Session ID Info (%x) " MACSTR, id, MAC2STR(mac)); }
void p2p_buf_add_advertisement_id(struct wpabuf *buf, u32 id, const u8 *mac) { if (!buf || !mac) return; /* Advertisement ID Info */ wpabuf_put_u8(buf, P2P_ATTR_ADVERTISEMENT_ID); wpabuf_put_le16(buf, (u16) (sizeof(u32) + ETH_ALEN)); wpabuf_put_le32(buf, id); wpabuf_put_data(buf, mac, ETH_ALEN); wpa_printf(MSG_DEBUG, "P2P: * Advertisement ID (%x) " MACSTR, id, MAC2STR(mac)); }
void hostapd_neighbor_set_own_report(struct hostapd_data *hapd) { #ifdef NEED_AP_MLME u16 capab = hostapd_own_capab_info(hapd); int ht = hapd->iconf->ieee80211n && !hapd->conf->disable_11n; int vht = hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac; struct wpa_ssid_value ssid; u8 channel, op_class; u8 center_freq1_idx = 0, center_freq2_idx = 0; enum nr_chan_width width; u32 bssid_info; struct wpabuf *nr; if (!(hapd->conf->radio_measurements[0] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) return; bssid_info = 3; /* AP is reachable */ bssid_info |= NEI_REP_BSSID_INFO_SECURITY; /* "same as the AP" */ bssid_info |= NEI_REP_BSSID_INFO_KEY_SCOPE; /* "same as the AP" */ if (capab & WLAN_CAPABILITY_SPECTRUM_MGMT) bssid_info |= NEI_REP_BSSID_INFO_SPECTRUM_MGMT; bssid_info |= NEI_REP_BSSID_INFO_RM; /* RRM is supported */ if (hapd->conf->wmm_enabled) { bssid_info |= NEI_REP_BSSID_INFO_QOS; if (hapd->conf->wmm_uapsd && (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD)) bssid_info |= NEI_REP_BSSID_INFO_APSD; } if (ht) { bssid_info |= NEI_REP_BSSID_INFO_HT | NEI_REP_BSSID_INFO_DELAYED_BA; /* VHT bit added in IEEE P802.11-REVmc/D4.3 */ if (vht) bssid_info |= NEI_REP_BSSID_INFO_VHT; } /* TODO: Set NEI_REP_BSSID_INFO_MOBILITY_DOMAIN if MDE is set */ if (ieee80211_freq_to_channel_ext(hapd->iface->freq, hapd->iconf->secondary_channel, hapd->iconf->vht_oper_chwidth, &op_class, &channel) == NUM_HOSTAPD_MODES) return; width = hostapd_get_nr_chan_width(hapd, ht, vht); if (vht) { center_freq1_idx = hapd->iconf->vht_oper_centr_freq_seg0_idx; if (width == NR_CHAN_WIDTH_80P80) center_freq2_idx = hapd->iconf->vht_oper_centr_freq_seg1_idx; } else if (ht) { ieee80211_freq_to_chan(hapd->iface->freq + 10 * hapd->iconf->secondary_channel, ¢er_freq1_idx); } ssid.ssid_len = hapd->conf->ssid.ssid_len; os_memcpy(ssid.ssid, hapd->conf->ssid.ssid, ssid.ssid_len); /* * Neighbor Report element size = BSSID + BSSID info + op_class + chan + * phy type + wide bandwidth channel subelement. */ nr = wpabuf_alloc(ETH_ALEN + 4 + 1 + 1 + 1 + 5); if (!nr) return; wpabuf_put_data(nr, hapd->own_addr, ETH_ALEN); wpabuf_put_le32(nr, bssid_info); wpabuf_put_u8(nr, op_class); wpabuf_put_u8(nr, channel); wpabuf_put_u8(nr, ieee80211_get_phy_type(hapd->iface->freq, ht, vht)); /* * Wide Bandwidth Channel subelement may be needed to allow the * receiving STA to send packets to the AP. See IEEE P802.11-REVmc/D5.0 * Figure 9-301. */ wpabuf_put_u8(nr, WNM_NEIGHBOR_WIDE_BW_CHAN); wpabuf_put_u8(nr, 3); wpabuf_put_u8(nr, width); wpabuf_put_u8(nr, center_freq1_idx); wpabuf_put_u8(nr, center_freq2_idx); hostapd_neighbor_set(hapd, hapd->own_addr, &ssid, nr, hapd->iconf->lci, hapd->iconf->civic, hapd->iconf->stationary_ap); wpabuf_free(nr); #endif /* NEED_AP_MLME */ }
static int p2p_buf_add_service_info(struct wpabuf *buf, struct p2p_data *p2p, u32 adv_id, u16 config_methods, const char *svc_name, u8 **ie_len, u8 **pos, size_t *total_len, u8 *attr_len) { size_t svc_len; size_t remaining; size_t info_len; p2p_dbg(p2p, "Add service info for %s (adv_id=%u)", svc_name, adv_id); svc_len = os_strlen(svc_name); info_len = sizeof(adv_id) + sizeof(config_methods) + sizeof(u8) + svc_len; if (info_len + *total_len > MAX_SVC_ADV_LEN) { p2p_dbg(p2p, "Unsufficient buffer, failed to add advertised service info"); return -1; } if (svc_len > 255) { p2p_dbg(p2p, "Invalid service name length (%u bytes), failed to add advertised service info", (unsigned int) svc_len); return -1; } if (*ie_len) { int ie_data_len = (*pos - *ie_len) - 1; if (ie_data_len < 0 || ie_data_len > 255) { p2p_dbg(p2p, "Invalid IE length, failed to add advertised service info"); return -1; } remaining = 255 - ie_data_len; } else { /* * Adding new P2P IE header takes 6 extra bytes: * - 2 byte IE header (1 byte IE id and 1 byte length) * - 4 bytes of IE_VENDOR_TYPE are reduced from 255 below */ *ie_len = p2p_buf_add_ie_hdr(buf); remaining = 255 - 4; } if (remaining < sizeof(u32) + sizeof(u16) + sizeof(u8)) { /* * Split adv_id, config_methods, and svc_name_len between two * IEs. */ size_t front = remaining; size_t back = sizeof(u32) + sizeof(u16) + sizeof(u8) - front; u8 holder[sizeof(u32) + sizeof(u16) + sizeof(u8)]; WPA_PUT_LE32(holder, adv_id); WPA_PUT_BE16(&holder[sizeof(u32)], config_methods); holder[sizeof(u32) + sizeof(u16)] = svc_len; if (front) wpabuf_put_data(buf, holder, front); p2p_buf_update_ie_hdr(buf, *ie_len); *ie_len = p2p_buf_add_ie_hdr(buf); wpabuf_put_data(buf, &holder[front], back); remaining = 255 - 4 - (sizeof(u32) + sizeof(u16) + sizeof(u8)) - back; } else { wpabuf_put_le32(buf, adv_id); wpabuf_put_be16(buf, config_methods); wpabuf_put_u8(buf, svc_len); remaining -= sizeof(adv_id) + sizeof(config_methods) + sizeof(u8); } if (remaining < svc_len) { /* split svc_name between two or three IEs */ size_t front = remaining; size_t back = svc_len - front; if (front) wpabuf_put_data(buf, svc_name, front); p2p_buf_update_ie_hdr(buf, *ie_len); *ie_len = p2p_buf_add_ie_hdr(buf); /* In rare cases, we must split across 3 attributes */ if (back > 255 - 4) { wpabuf_put_data(buf, &svc_name[front], 255 - 4); back -= 255 - 4; front += 255 - 4; p2p_buf_update_ie_hdr(buf, *ie_len); *ie_len = p2p_buf_add_ie_hdr(buf); } wpabuf_put_data(buf, &svc_name[front], back); remaining = 255 - 4 - back; } else { wpabuf_put_data(buf, svc_name, svc_len); remaining -= svc_len; } p2p_buf_update_ie_hdr(buf, *ie_len); /* set *ie_len to NULL if a new IE has to be added on the next call */ if (!remaining) *ie_len = NULL; /* set *pos to point to the next byte to update */ *pos = wpabuf_put(buf, 0); *total_len += info_len; WPA_PUT_LE16(attr_len, (u16) *total_len); return 0; }