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>
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)
}
+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)
{
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 */
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
#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
u8 num_sec_dev_types;
u32 os_version;
u8 rf_bands;
+ struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS];
int p2p;
};
}
+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)
{
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 */
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;
wps_build_sel_reg_config_methods(reg, beacon) ||
wps_build_sel_pbc_reg_uuid_e(reg, beacon) ||
(reg->dualband && wps_build_rf_bands(®->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(®->wps->dev, beacon)) {
wpabuf_free(beacon);
wpabuf_free(probe);
return -1;
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, probe)) {
wpabuf_free(beacon);
wpabuf_free(probe);
return -1;