Parcourir la source

Provide extra IEs for AP mode management frames with set_ap

Drivers that build Beacon, Probe Response, and (Re)Association
Response frames can use this information to and WPS and P2P IE
when needed.
Jouni Malinen il y a 13 ans
Parent
commit
fb91db5639
5 fichiers modifiés avec 114 ajouts et 43 suppressions
  1. 65 43
      src/ap/ap_drv_ops.c
  2. 7 0
      src/ap/ap_drv_ops.h
  3. 6 0
      src/ap/beacon.c
  4. 21 0
      src/drivers/driver.h
  5. 15 0
      src/drivers/driver_nl80211.c

+ 65 - 43
src/ap/ap_drv_ops.c

@@ -41,49 +41,47 @@ u32 hostapd_sta_flags_to_drv(u32 flags)
 }
 
 
-int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
+int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
+			       struct wpabuf **beacon,
+			       struct wpabuf **proberesp,
+			       struct wpabuf **assocresp)
 {
-	struct wpabuf *beacon, *proberesp, *assocresp = NULL;
-	int ret;
-
-	if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
-		return 0;
-
-	beacon = hapd->wps_beacon_ie;
-	proberesp = hapd->wps_probe_resp_ie;
+	*beacon = hapd->wps_beacon_ie;
+	*proberesp = hapd->wps_probe_resp_ie;
+	*assocresp = NULL;
 
 #ifdef CONFIG_P2P
 	if (hapd->wps_beacon_ie == NULL && hapd->p2p_beacon_ie == NULL)
-		beacon = NULL;
+		*beacon = NULL;
 	else {
-		beacon = wpabuf_alloc((hapd->wps_beacon_ie ?
-				       wpabuf_len(hapd->wps_beacon_ie) : 0) +
-				      (hapd->p2p_beacon_ie ?
-				       wpabuf_len(hapd->p2p_beacon_ie) : 0));
-		if (beacon == NULL)
+		*beacon = wpabuf_alloc((hapd->wps_beacon_ie ?
+					wpabuf_len(hapd->wps_beacon_ie) : 0) +
+				       (hapd->p2p_beacon_ie ?
+					wpabuf_len(hapd->p2p_beacon_ie) : 0));
+		if (*beacon == NULL)
 			return -1;
 		if (hapd->wps_beacon_ie)
-			wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
+			wpabuf_put_buf(*beacon, hapd->wps_beacon_ie);
 		if (hapd->p2p_beacon_ie)
-			wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
+			wpabuf_put_buf(*beacon, hapd->p2p_beacon_ie);
 	}
 
 	if (hapd->wps_probe_resp_ie == NULL && hapd->p2p_probe_resp_ie == NULL)
-		proberesp = NULL;
+		*proberesp = NULL;
 	else {
-		proberesp = wpabuf_alloc(
+		*proberesp = wpabuf_alloc(
 			(hapd->wps_probe_resp_ie ?
 			 wpabuf_len(hapd->wps_probe_resp_ie) : 0) +
 			(hapd->p2p_probe_resp_ie ?
 			 wpabuf_len(hapd->p2p_probe_resp_ie) : 0));
-		if (proberesp == NULL) {
-			wpabuf_free(beacon);
+		if (*proberesp == NULL) {
+			wpabuf_free(*beacon);
 			return -1;
 		}
 		if (hapd->wps_probe_resp_ie)
-			wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
+			wpabuf_put_buf(*proberesp, hapd->wps_probe_resp_ie);
 		if (hapd->p2p_probe_resp_ie)
-			wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
+			wpabuf_put_buf(*proberesp, hapd->p2p_probe_resp_ie);
 	}
 #endif /* CONFIG_P2P */
 
@@ -91,67 +89,91 @@ int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
 	if (hapd->conf->p2p & P2P_MANAGE) {
 		struct wpabuf *a;
 
-		a = wpabuf_alloc(100 + (beacon ? wpabuf_len(beacon) : 0));
+		a = wpabuf_alloc(100 + (*beacon ? wpabuf_len(*beacon) : 0));
 		if (a) {
 			u8 *start, *p;
-			if (beacon)
-				wpabuf_put_buf(a, beacon);
-			if (beacon != hapd->wps_beacon_ie)
-				wpabuf_free(beacon);
+			if (*beacon)
+				wpabuf_put_buf(a, *beacon);
+			if (*beacon != hapd->wps_beacon_ie)
+				wpabuf_free(*beacon);
 			start = wpabuf_put(a, 0);
 			p = hostapd_eid_p2p_manage(hapd, start);
 			wpabuf_put(a, p - start);
-			beacon = a;
+			*beacon = a;
 		}
 
-		a = wpabuf_alloc(100 + (proberesp ? wpabuf_len(proberesp) :
+		a = wpabuf_alloc(100 + (*proberesp ? wpabuf_len(*proberesp) :
 					0));
 		if (a) {
 			u8 *start, *p;
-			if (proberesp)
-				wpabuf_put_buf(a, proberesp);
-			if (proberesp != hapd->wps_probe_resp_ie)
-				wpabuf_free(proberesp);
+			if (*proberesp)
+				wpabuf_put_buf(a, *proberesp);
+			if (*proberesp != hapd->wps_probe_resp_ie)
+				wpabuf_free(*proberesp);
 			start = wpabuf_put(a, 0);
 			p = hostapd_eid_p2p_manage(hapd, start);
 			wpabuf_put(a, p - start);
-			proberesp = a;
+			*proberesp = a;
 		}
 	}
 #endif /* CONFIG_P2P_MANAGER */
 
 #ifdef CONFIG_WPS2
 	if (hapd->conf->wps_state)
-		assocresp = wps_build_assoc_resp_ie();
+		*assocresp = wps_build_assoc_resp_ie();
 #endif /* CONFIG_WPS2 */
 
 #ifdef CONFIG_P2P_MANAGER
 	if (hapd->conf->p2p & P2P_MANAGE) {
 		struct wpabuf *a;
-		a = wpabuf_alloc(100 + (assocresp ? wpabuf_len(assocresp) :
+		a = wpabuf_alloc(100 + (*assocresp ? wpabuf_len(*assocresp) :
 					0));
 		if (a) {
 			u8 *start, *p;
 			start = wpabuf_put(a, 0);
 			p = hostapd_eid_p2p_manage(hapd, start);
 			wpabuf_put(a, p - start);
-			if (assocresp) {
-				wpabuf_put_buf(a, assocresp);
-				wpabuf_free(assocresp);
+			if (*assocresp) {
+				wpabuf_put_buf(a, *assocresp);
+				wpabuf_free(*assocresp);
 			}
-			assocresp = a;
+			*assocresp = a;
 		}
 	}
 #endif /* CONFIG_P2P_MANAGER */
 
-	ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
-					  assocresp);
+	return 0;
+}
+
 
+void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
+			       struct wpabuf *proberesp,
+			       struct wpabuf *assocresp)
+{
 	if (beacon != hapd->wps_beacon_ie)
 		wpabuf_free(beacon);
 	if (proberesp != hapd->wps_probe_resp_ie)
 		wpabuf_free(proberesp);
 	wpabuf_free(assocresp);
+}
+
+
+int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
+{
+	struct wpabuf *beacon, *proberesp, *assocresp;
+	int ret;
+
+	if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
+		return 0;
+
+	if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
+	    0)
+		return -1;
+
+	ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
+					  assocresp);
+
+	hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
 
 	return ret;
 }

+ 7 - 0
src/ap/ap_drv_ops.h

@@ -21,6 +21,13 @@ struct wpa_driver_scan_params;
 struct ieee80211_ht_capabilities;
 
 u32 hostapd_sta_flags_to_drv(u32 flags);
+int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
+			       struct wpabuf **beacon,
+			       struct wpabuf **proberesp,
+			       struct wpabuf **assocresp);
+void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
+			       struct wpabuf *proberesp,
+			       struct wpabuf *assocresp);
 int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
 int hostapd_set_authorized(struct hostapd_data *hapd,
 			   struct sta_info *sta, int authorized);

+ 6 - 0
src/ap/beacon.c

@@ -399,6 +399,7 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
 	u16 capab_info;
 	size_t head_len, tail_len;
 	struct wpa_driver_ap_params params;
+	struct wpabuf *beacon, *proberesp, *assocresp;
 
 #ifdef CONFIG_P2P
 	if ((hapd->conf->p2p & (P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_ENABLED)
@@ -541,8 +542,13 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
 		params.hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
 		break;
 	}
+	hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp);
+	params.beacon_ies = beacon;
+	params.proberesp_ies = proberesp;
+	params.assocresp_ies = assocresp;
 	if (hostapd_drv_set_ap(hapd, &params))
 		wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
+	hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
 
 	os_free(tail);
 	os_free(head);

+ 21 - 0
src/drivers/driver.h

@@ -581,6 +581,27 @@ struct wpa_driver_ap_params {
 	 * privacy - Whether privacy is used in the BSS
 	 */
 	int privacy;
+
+	/**
+	 * beacon_ies - WPS/P2P IE(s) for Beacon frames
+	 *
+	 * This is used to add IEs like WPS IE and P2P IE by drivers that do not
+	 * use the full Beacon template.
+	 */
+	const struct wpabuf *beacon_ies;
+
+	/**
+	 * proberesp_ies - P2P/WPS IE(s) for Probe Response frames
+	 *
+	 * This is used to add IEs like WPS IE and P2P IE by drivers that
+	 * reply to Probe Request frames internally.
+	 */
+	const struct wpabuf *proberesp_ies;
+
+	/**
+	 * assocresp_ies - WPS IE(s) for (Re)Association Response frames
+	 */
+	const struct wpabuf *assocresp_ies;
 };
 
 /**

+ 15 - 0
src/drivers/driver_nl80211.c

@@ -3929,6 +3929,21 @@ static int wpa_driver_nl80211_set_ap(void *priv,
 		break;
 	}
 
+	if (params->beacon_ies) {
+		NLA_PUT(msg, NL80211_ATTR_IE, wpabuf_len(params->beacon_ies),
+			wpabuf_head(params->beacon_ies));
+	}
+	if (params->proberesp_ies) {
+		NLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,
+			wpabuf_len(params->proberesp_ies),
+			wpabuf_head(params->proberesp_ies));
+	}
+	if (params->assocresp_ies) {
+		NLA_PUT(msg, NL80211_ATTR_IE_ASSOC_RESP,
+			wpabuf_len(params->assocresp_ies),
+			wpabuf_head(params->assocresp_ies));
+	}
+
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	if (ret) {
 		wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",