Add WPS IE into (Re)Association Response frame if WPS is used
authorJouni Malinen <jouni.malinen@atheros.com>
Wed, 26 May 2010 15:46:08 +0000 (18:46 +0300)
committerJouni Malinen <j@w1.fi>
Wed, 26 May 2010 15:46:08 +0000 (18:46 +0300)
If the associating station indicates that it is intents to use WPS
by including WPS IE in (Re)Association Request frame, include WPS IE
in (Re)Association Response frame.

src/ap/ieee802_11.c
src/wps/wps.c
src/wps/wps.h
src/wps/wps_attr_build.c
src/wps/wps_i.h
src/wps/wps_registrar.c

index 2265623..4d7d885 100644 (file)
@@ -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)
index 780f9fa..619af15 100644 (file)
@@ -289,6 +289,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
  * @dev: Device attributes
index 350a640..1fd1e52 100644 (file)
@@ -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);
index bb21c40..9da556a 100644 (file)
@@ -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);
index e3a5141..50e66f6 100644 (file)
@@ -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);
index dc46fdc..0c3bc9c 100644 (file)
@@ -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(&reg->wps->dev, probe) ||
            wps_build_probe_config_methods(reg, probe) ||