]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
WPS: Add support for adding WPS Vendor Extensions
authorJean-Michel Bachot <jean-michelx.bachot@linux.intel.com>
Sat, 19 Mar 2011 09:44:42 +0000 (11:44 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 19 Mar 2011 10:22:16 +0000 (12:22 +0200)
This adds the ability to add WPS vendor extensions to an AP (or GO).
They will be added to the WSC IE(s) in Beacon and Probe Response frames.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
src/ap/ap_config.h
src/ap/wps_hostapd.c
src/wps/wps.h
src/wps/wps_dev_attr.c
src/wps/wps_dev_attr.h
src/wps/wps_registrar.c

index fbe8734ffc9548e5f366027d86faa3e41948cff9..25720b84a3e884c146d67233117c454f8cc620a8 100644 (file)
@@ -316,6 +316,7 @@ struct hostapd_bss_config {
        char *model_description;
        char *model_url;
        char *upc;
+       struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
 #endif /* CONFIG_WPS */
 
 #define P2P_ENABLED BIT(0)
index 92a6dd4a61bd92a2d65e66bb29b3deba4481cbe6..fcbd89b9cff54ad33c28c19120caa51c1b1e65c2 100644 (file)
@@ -657,6 +657,31 @@ static int interface_count(struct hostapd_iface *iface)
 }
 
 
+static int hostapd_wps_set_vendor_ext(struct hostapd_data *hapd,
+                                     struct wps_context *wps)
+{
+       int i;
+
+       for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
+               wpabuf_free(wps->dev.vendor_ext[i]);
+               wps->dev.vendor_ext[i] = NULL;
+
+               if (hapd->conf->wps_vendor_ext[i] == NULL)
+                       continue;
+
+               wps->dev.vendor_ext[i] =
+                       wpabuf_dup(hapd->conf->wps_vendor_ext[i]);
+               if (wps->dev.vendor_ext[i] == NULL) {
+                       while (--i >= 0)
+                               wpabuf_free(wps->dev.vendor_ext[i]);
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+
 int hostapd_init_wps(struct hostapd_data *hapd,
                     struct hostapd_bss_config *conf)
 {
@@ -731,6 +756,11 @@ int hostapd_init_wps(struct hostapd_data *hapd,
        os_memcpy(wps->dev.pri_dev_type, hapd->conf->device_type,
                  WPS_DEV_TYPE_LEN);
 
+       if (hostapd_wps_set_vendor_ext(hapd, wps) < 0) {
+               os_free(wps);
+               return -1;
+       }
+
        wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version);
        wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
                WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */
@@ -900,6 +930,8 @@ void hostapd_update_wps(struct hostapd_data *hapd)
        hapd->wps->upc = hapd->conf->upc;
 #endif /* CONFIG_WPS_UPNP */
 
+       hostapd_wps_set_vendor_ext(hapd, hapd->wps);
+
        if (hapd->conf->wps_state)
                wps_registrar_update_ie(hapd->wps->registrar);
        else
index 60a33d5246a5d9f3b908db2d3c2b501e19e878ca..8b29982953ee6063c4f2a662b5f81d551ceb5d9e 100644 (file)
@@ -64,6 +64,8 @@ struct wps_credential {
 #define WPS_DEV_TYPE_LEN 8
 #define WPS_DEV_TYPE_BUFSIZE 21
 #define WPS_SEC_DEV_TYPE_MAX_LEN 128
+/* maximum number of advertised WPS vendor extension attributes */
+#define MAX_WPS_VENDOR_EXTENSIONS 10
 
 /**
  * struct wps_device_data - WPS Device Data
@@ -93,6 +95,7 @@ struct wps_device_data {
        u8 num_sec_dev_types;
        u32 os_version;
        u8 rf_bands;
+       struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
 
        int p2p;
 };
index 2304bc4e26c4f12d648c5b9d76ab0ba5749c0cea..7253d21ecd0c765a48d41636029a1056427a2596 100644 (file)
@@ -199,6 +199,25 @@ int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg)
 }
 
 
+int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg)
+{
+       int i;
+
+       for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
+               if (dev->vendor_ext[i] == NULL)
+                       continue;
+               wpa_hexdump(MSG_DEBUG, "WPS:  * Vendor Extension",
+                           wpabuf_head_u8(dev->vendor_ext[i]),
+                           wpabuf_len(dev->vendor_ext[i]));
+               wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
+               wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext[i]));
+               wpabuf_put_buf(msg, dev->vendor_ext[i]);
+       }
+
+       return 0;
+}
+
+
 static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str,
                                    size_t str_len)
 {
index 84a2cd288585272eea97cd7f2d9108bc96eb89a5..f17f62d647104b0b3e3ab4347a37a79a7ddd9bb5 100644 (file)
@@ -36,5 +36,6 @@ int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands);
 void wps_device_data_dup(struct wps_device_data *dst,
                         const struct wps_device_data *src);
 void wps_device_data_free(struct wps_device_data *dev);
+int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg);
 
 #endif /* WPS_DEV_ATTR_H */
index dbaf99357a881b38bd967f1f9ccce2cfeb28e414..65ff40dd610d15d3e724165fac82199c5314b2d2 100644 (file)
@@ -1113,14 +1113,23 @@ static int wps_set_ie(struct wps_registrar *reg)
        struct wpabuf *probe;
        const u8 *auth_macs;
        size_t count;
+       size_t vendor_len = 0;
+       int i;
 
        if (reg->set_ie_cb == NULL)
                return 0;
 
-       beacon = wpabuf_alloc(400);
+       for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
+               if (reg->wps->dev.vendor_ext[i]) {
+                       vendor_len += 2 + 2;
+                       vendor_len += wpabuf_len(reg->wps->dev.vendor_ext[i]);
+               }
+       }
+
+       beacon = wpabuf_alloc(400 + vendor_len);
        if (beacon == NULL)
                return -1;
-       probe = wpabuf_alloc(500);
+       probe = wpabuf_alloc(500 + vendor_len);
        if (probe == NULL) {
                wpabuf_free(beacon);
                return -1;
@@ -1138,7 +1147,8 @@ static int wps_set_ie(struct wps_registrar *reg)
            wps_build_sel_reg_config_methods(reg, beacon) ||
            wps_build_sel_pbc_reg_uuid_e(reg, beacon) ||
            (reg->dualband && wps_build_rf_bands(&reg->wps->dev, beacon)) ||
-           wps_build_wfa_ext(beacon, 0, auth_macs, count)) {
+           wps_build_wfa_ext(beacon, 0, auth_macs, count) ||
+           wps_build_vendor_ext(&reg->wps->dev, beacon)) {
                wpabuf_free(beacon);
                wpabuf_free(probe);
                return -1;
@@ -1167,7 +1177,8 @@ static int wps_set_ie(struct wps_registrar *reg)
            wps_build_device_attrs(&reg->wps->dev, probe) ||
            wps_build_probe_config_methods(reg, probe) ||
            wps_build_rf_bands(&reg->wps->dev, probe) ||
-           wps_build_wfa_ext(probe, 0, auth_macs, count)) {
+           wps_build_wfa_ext(probe, 0, auth_macs, count) ||
+           wps_build_vendor_ext(&reg->wps->dev, probe)) {
                wpabuf_free(beacon);
                wpabuf_free(probe);
                return -1;