WPS: Add support for adding WPS Vendor Extensions

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>
This commit is contained in:
Jean-Michel Bachot 2011-03-19 11:44:42 +02:00 committed by Jouni Malinen
parent f3cb52fb90
commit 4028a7fd43
6 changed files with 71 additions and 4 deletions

View file

@ -316,6 +316,7 @@ struct hostapd_bss_config {
char *model_description; char *model_description;
char *model_url; char *model_url;
char *upc; char *upc;
struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
#endif /* CONFIG_WPS */ #endif /* CONFIG_WPS */
#define P2P_ENABLED BIT(0) #define P2P_ENABLED BIT(0)

View 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, int hostapd_init_wps(struct hostapd_data *hapd,
struct hostapd_bss_config *conf) 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, os_memcpy(wps->dev.pri_dev_type, hapd->conf->device_type,
WPS_DEV_TYPE_LEN); 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.os_version = WPA_GET_BE32(hapd->conf->os_version);
wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ? wps->dev.rf_bands = hapd->iconf->hw_mode == HOSTAPD_MODE_IEEE80211A ?
WPS_RF_50GHZ : WPS_RF_24GHZ; /* FIX: dualband AP */ 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; hapd->wps->upc = hapd->conf->upc;
#endif /* CONFIG_WPS_UPNP */ #endif /* CONFIG_WPS_UPNP */
hostapd_wps_set_vendor_ext(hapd, hapd->wps);
if (hapd->conf->wps_state) if (hapd->conf->wps_state)
wps_registrar_update_ie(hapd->wps->registrar); wps_registrar_update_ie(hapd->wps->registrar);
else else

View file

@ -64,6 +64,8 @@ struct wps_credential {
#define WPS_DEV_TYPE_LEN 8 #define WPS_DEV_TYPE_LEN 8
#define WPS_DEV_TYPE_BUFSIZE 21 #define WPS_DEV_TYPE_BUFSIZE 21
#define WPS_SEC_DEV_TYPE_MAX_LEN 128 #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 * struct wps_device_data - WPS Device Data
@ -93,6 +95,7 @@ struct wps_device_data {
u8 num_sec_dev_types; u8 num_sec_dev_types;
u32 os_version; u32 os_version;
u8 rf_bands; u8 rf_bands;
struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
int p2p; int p2p;
}; };

View 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, static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str,
size_t str_len) size_t str_len)
{ {

View 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, void wps_device_data_dup(struct wps_device_data *dst,
const struct wps_device_data *src); const struct wps_device_data *src);
void wps_device_data_free(struct wps_device_data *dev); 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 */ #endif /* WPS_DEV_ATTR_H */

View file

@ -1113,14 +1113,23 @@ static int wps_set_ie(struct wps_registrar *reg)
struct wpabuf *probe; struct wpabuf *probe;
const u8 *auth_macs; const u8 *auth_macs;
size_t count; size_t count;
size_t vendor_len = 0;
int i;
if (reg->set_ie_cb == NULL) if (reg->set_ie_cb == NULL)
return 0; 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) if (beacon == NULL)
return -1; return -1;
probe = wpabuf_alloc(500); probe = wpabuf_alloc(500 + vendor_len);
if (probe == NULL) { if (probe == NULL) {
wpabuf_free(beacon); wpabuf_free(beacon);
return -1; 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_reg_config_methods(reg, beacon) ||
wps_build_sel_pbc_reg_uuid_e(reg, beacon) || wps_build_sel_pbc_reg_uuid_e(reg, beacon) ||
(reg->dualband && wps_build_rf_bands(&reg->wps->dev, 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(beacon);
wpabuf_free(probe); wpabuf_free(probe);
return -1; 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_device_attrs(&reg->wps->dev, probe) ||
wps_build_probe_config_methods(reg, probe) || wps_build_probe_config_methods(reg, probe) ||
wps_build_rf_bands(&reg->wps->dev, 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(beacon);
wpabuf_free(probe); wpabuf_free(probe);
return -1; return -1;