WPS vendor extension can be set in hapd->conf structure when AP( Group Owner) is configured after p2p groupd has been started. WPS vendor extension can also be updated through the hostapd_update_wps function call in wps_hostapd.c. Number of WPS Vendor Extension is currenlty limited to 1 (defined with WPS_MAX_VENDOR_EXTENSIONS_IN_BEACON macro. Signed-off-by: Johannes Berg --- src/ap/ap_config.h | 2 ++ src/ap/wps_hostapd.c | 35 +++++++++++++++++++++++++++++++++++ src/wps/wps.h | 3 +++ src/wps/wps_dev_attr.c | 19 +++++++++++++++++++ src/wps/wps_dev_attr.h | 1 + src/wps/wps_registrar.c | 3 ++- 6 files changed, 62 insertions(+), 1 deletions(-) diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 0a929d6..2ee2c4d 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -18,6 +18,7 @@ #include "common/defs.h" #include "ip_addr.h" #include "common/wpa_common.h" +#include "wps/wps.h" #define MAX_STA_COUNT 2007 #define MAX_VLAN_ID 4094 @@ -315,6 +316,7 @@ struct hostapd_bss_config { char *model_description; char *model_url; char *upc; + struct wpabuf *wps_vendor_ext[MAX_WPS_BEACON_VENDOR_EXTENSIONS]; #endif /* CONFIG_WPS */ #define P2P_ENABLED BIT(0) diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index b5cd5a8..51cd69a 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -648,6 +648,7 @@ int hostapd_init_wps(struct hostapd_data *hapd, { struct wps_context *wps; struct wps_registrar_config cfg; + int i; if (conf->wps_state == 0) { hostapd_wps_clear_ies(hapd); @@ -721,6 +722,24 @@ int hostapd_init_wps(struct hostapd_data *hapd, os_free(wps); return -1; } + + for (i = 0; i < MAX_WPS_BEACON_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]); + 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 */ @@ -879,6 +898,8 @@ void hostapd_deinit_wps(struct hostapd_data *hapd) void hostapd_update_wps(struct hostapd_data *hapd) { + int i; + if (hapd->wps == NULL) return; @@ -890,6 +911,20 @@ void hostapd_update_wps(struct hostapd_data *hapd) hapd->wps->upc = hapd->conf->upc; #endif /* CONFIG_WPS_UPNP */ + for (i = 0; i < MAX_WPS_BEACON_VENDOR_EXTENSIONS; i++) { + wpabuf_free(hapd->wps->dev.vendor_ext[i]); + hapd->wps->dev.vendor_ext[i] = NULL; + if (hapd->conf->wps_vendor_ext[i] == NULL) + continue; + hapd->wps->dev.vendor_ext[i] = + wpabuf_dup(hapd->conf->wps_vendor_ext[i]); + if (hapd->wps->dev.vendor_ext[i] == NULL) { + while (--i >= 0) + wpabuf_free(hapd->wps->dev.vendor_ext[i]); + return; + } + } + if (hapd->conf->wps_state) wps_registrar_update_ie(hapd->wps->registrar); else diff --git a/src/wps/wps.h b/src/wps/wps.h index a8c6ffe..8629c59 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -72,6 +72,8 @@ struct wps_credential { #define WPS_MAX_VENDOR_EXTENSIONS_SIZE 1024 /* maximum number of parsed WPS vendor extensions attributes */ #define MAX_WPS_PARSE_VENDOR_EXTENSIONS 10 +/* maximum number of beacon WPS Vendor extension attributes */ +#define MAX_WPS_BEACON_VENDOR_EXTENSIONS 10 /** * struct wps_device_data - WPS Device Data @@ -103,6 +105,7 @@ struct wps_device_data { u8 nb_req_dev_types; u32 os_version; u8 rf_bands; + struct wpabuf *vendor_ext[MAX_WPS_BEACON_VENDOR_EXTENSIONS]; int p2p; }; diff --git a/src/wps/wps_dev_attr.c b/src/wps/wps_dev_attr.c index f1d21d7..1586175 100644 --- a/src/wps/wps_dev_attr.c +++ b/src/wps/wps_dev_attr.c @@ -216,6 +216,25 @@ int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg) return 0; } +int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg) +{ + int i; + + /* build the WPS vendor extensions */ + for (i = 0; i < MAX_WPS_BEACON_VENDOR_EXTENSIONS; i++) { + if (dev->vendor_ext[i] == NULL) + continue; + wpa_hexdump_ascii(MSG_DEBUG, "WPS: Vendor Extension " + "in beacon", + 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) diff --git a/src/wps/wps_dev_attr.h b/src/wps/wps_dev_attr.h index db4cb15..de1787d 100644 --- a/src/wps/wps_dev_attr.h +++ b/src/wps/wps_dev_attr.h @@ -37,5 +37,6 @@ 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_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg); #endif /* WPS_DEV_ATTR_H */ diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index e2681f7..ab389dd 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -1113,7 +1113,8 @@ static int wps_set_ie(struct wps_registrar *reg) wps_build_device_attrs(®->wps->dev, probe) || wps_build_probe_config_methods(reg, probe) || wps_build_rf_bands(®->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(®->wps->dev, beacon)) { wpabuf_free(beacon); wpabuf_free(probe); return -1; -- 1.7.2.3