diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c index 22656237d..4d7d885eb 100644 --- a/src/ap/ieee802_11.c +++ b/src/ap/ieee802_11.c @@ -25,6 +25,7 @@ #include "common/wpa_ctrl.h" #include "radius/radius.h" #include "radius/radius_client.h" +#include "wps/wps.h" #include "hostapd.h" #include "beacon.h" #include "ieee802_11_auth.h" @@ -874,6 +875,17 @@ static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, if (sta->flags & WLAN_STA_WMM) p = hostapd_eid_wmm(hapd, p); +#ifdef CONFIG_WPS + if (sta->flags & WLAN_STA_WPS) { + struct wpabuf *wps = wps_build_assoc_resp_ie(); + if (wps) { + os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps)); + p += wpabuf_len(wps); + wpabuf_free(wps); + } + } +#endif /* CONFIG_WPS */ + send_len += p - reply->u.assoc_resp.variable; if (hapd->drv.send_mgmt_frame(hapd, reply, send_len) < 0) diff --git a/src/wps/wps.c b/src/wps/wps.c index 780f9fa39..619af158d 100644 --- a/src/wps/wps.c +++ b/src/wps/wps.c @@ -288,6 +288,39 @@ struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type) } +/** + * wps_build_assoc_resp_ie - Build WPS IE for (Re)Association Response + * Returns: WPS IE or %NULL on failure + * + * The caller is responsible for freeing the buffer. + */ +struct wpabuf * wps_build_assoc_resp_ie(void) +{ + struct wpabuf *ie; + u8 *len; + + wpa_printf(MSG_DEBUG, "WPS: Building WPS IE for (Re)Association " + "Response"); + ie = wpabuf_alloc(100); + if (ie == NULL) + return NULL; + + wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC); + len = wpabuf_put(ie, 1); + wpabuf_put_be32(ie, WPS_DEV_OUI_WFA); + + if (wps_build_version(ie) || + wps_build_resp_type(ie, WPS_RESP_AP)) { + wpabuf_free(ie); + return NULL; + } + + *len = wpabuf_len(ie) - 2; + + return ie; +} + + /** * wps_build_probe_req_ie - Build WPS IE for Probe Request * @pbc: Whether searching for PBC mode APs diff --git a/src/wps/wps.h b/src/wps/wps.h index 350a64062..1fd1e52bb 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -198,6 +198,7 @@ int wps_is_selected_pin_registrar(const struct wpabuf *msg); const u8 * wps_get_uuid_e(const struct wpabuf *msg); struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type); +struct wpabuf * wps_build_assoc_resp_ie(void); struct wpabuf * wps_build_probe_req_ie(int pbc, struct wps_device_data *dev, const u8 *uuid, enum wps_request_type req_type); diff --git a/src/wps/wps_attr_build.c b/src/wps/wps_attr_build.c index bb21c40f8..9da556add 100644 --- a/src/wps/wps_attr_build.c +++ b/src/wps/wps_attr_build.c @@ -74,6 +74,16 @@ int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type) } +int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type) +{ + wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", type); + wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE); + wpabuf_put_be16(msg, 1); + wpabuf_put_u8(msg, type); + return 0; +} + + int wps_build_config_methods(struct wpabuf *msg, u16 methods) { wpa_printf(MSG_DEBUG, "WPS: * Config Methods (%x)", methods); diff --git a/src/wps/wps_i.h b/src/wps/wps_i.h index e3a51412b..50e66f6c2 100644 --- a/src/wps/wps_i.h +++ b/src/wps/wps_i.h @@ -218,6 +218,7 @@ int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr); /* wps_attr_build.c */ int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg); int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type); +int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type); int wps_build_config_methods(struct wpabuf *msg, u16 methods); int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid); int wps_build_dev_password_id(struct wpabuf *msg, u16 id); diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index dc46fdce9..0c3bc9c48 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -426,17 +426,6 @@ static int wps_build_config_methods_r(struct wps_registrar *reg, } -static int wps_build_resp_type(struct wps_registrar *reg, struct wpabuf *msg) -{ - u8 resp = reg->wps->ap ? WPS_RESP_AP : WPS_RESP_REGISTRAR; - wpa_printf(MSG_DEBUG, "WPS: * Response Type (%d)", resp); - wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE); - wpabuf_put_be16(msg, 1); - wpabuf_put_u8(msg, resp); - return 0; -} - - /** * wps_registrar_init - Initialize WPS Registrar data * @wps: Pointer to longterm WPS context @@ -940,7 +929,8 @@ static int wps_set_ie(struct wps_registrar *reg) wps_build_selected_registrar(reg, probe) || wps_build_sel_reg_dev_password_id(reg, probe) || wps_build_sel_reg_config_methods(reg, probe) || - wps_build_resp_type(reg, probe) || + wps_build_resp_type(probe, reg->wps->ap ? WPS_RESP_AP : + WPS_RESP_REGISTRAR) || wps_build_uuid_e(probe, reg->wps->uuid) || wps_build_device_attrs(®->wps->dev, probe) || wps_build_probe_config_methods(reg, probe) ||