diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 53a8687a9..89e02a59a 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -3762,6 +3762,9 @@ static int hostapd_config_fill(struct hostapd_config *conf, } else if (os_strcmp(buf, "server_id") == 0) { os_free(bss->server_id); bss->server_id = os_strdup(pos); + } else if (os_strcmp(buf, "wps_application_ext") == 0) { + wpabuf_free(bss->wps_application_ext); + bss->wps_application_ext = wpabuf_parse_bin(pos); #ifdef CONFIG_WPS_NFC } else if (os_strcmp(buf, "wps_nfc_dev_pw_id") == 0) { bss->wps_nfc_dev_pw_id = atoi(pos); diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index 263a04e8f..10a6291ff 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -2205,6 +2205,13 @@ own_ip_addr=127.0.0.1 #wps_nfc_dh_privkey: Hexdump of DH Private Key #wps_nfc_dev_pw: Hexdump of Device Password +# Application Extension attribute for Beacon and Probe Response frames +# This parameter can be used to add application extension into WPS IE. The +# contents of this parameter starts with 16-octet (32 hexdump characters) of +# UUID to identify the specific application and that is followed by the actual +# application specific data. +#wps_application_ext= + ##### Wi-Fi Direct (P2P) ###################################################### # Enable P2P Device management diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 945f05285..cc041441c 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -813,6 +813,7 @@ void hostapd_config_free_bss(struct hostapd_bss_config *conf) os_free(conf->upc); for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) wpabuf_free(conf->wps_vendor_ext[i]); + wpabuf_free(conf->wps_application_ext); wpabuf_free(conf->wps_nfc_dh_pubkey); wpabuf_free(conf->wps_nfc_dh_privkey); wpabuf_free(conf->wps_nfc_dev_pw); diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index a74eac083..1efdc2b43 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -498,6 +498,7 @@ struct hostapd_bss_config { char *model_url; char *upc; struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; + struct wpabuf *wps_application_ext; int wps_nfc_pw_from_config; int wps_nfc_dev_pw_id; struct wpabuf *wps_nfc_dh_pubkey; diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c index 175b9fc09..3ea2228a9 100644 --- a/src/ap/wps_hostapd.c +++ b/src/ap/wps_hostapd.c @@ -985,6 +985,21 @@ static int hostapd_wps_set_vendor_ext(struct hostapd_data *hapd, } +static int hostapd_wps_set_application_ext(struct hostapd_data *hapd, + struct wps_context *wps) +{ + wpabuf_free(wps->dev.application_ext); + + if (!hapd->conf->wps_application_ext) { + wps->dev.application_ext = NULL; + return 0; + } + + wps->dev.application_ext = wpabuf_dup(hapd->conf->wps_application_ext); + return wps->dev.application_ext ? 0 : -1; +} + + static void hostapd_free_wps(struct wps_context *wps) { int i; @@ -1074,7 +1089,8 @@ 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) + if (hostapd_wps_set_vendor_ext(hapd, wps) < 0 || + hostapd_wps_set_application_ext(hapd, wps) < 0) goto fail; wps->dev.os_version = WPA_GET_BE32(hapd->conf->os_version); @@ -1311,6 +1327,7 @@ void hostapd_update_wps(struct hostapd_data *hapd) #endif /* CONFIG_WPS_UPNP */ hostapd_wps_set_vendor_ext(hapd, hapd->wps); + hostapd_wps_set_application_ext(hapd, hapd->wps); if (hapd->conf->wps_state) wps_registrar_update_ie(hapd->wps->registrar); diff --git a/src/wps/wps.h b/src/wps/wps.h index 9963c4687..f42045e93 100644 --- a/src/wps/wps.h +++ b/src/wps/wps.h @@ -98,6 +98,7 @@ struct wps_device_data { u16 config_methods; struct wpabuf *vendor_ext_m1; struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; + struct wpabuf *application_ext; int p2p; u8 multi_ap_ext; diff --git a/src/wps/wps_dev_attr.c b/src/wps/wps_dev_attr.c index b209fea8a..c2e949cb6 100644 --- a/src/wps/wps_dev_attr.c +++ b/src/wps/wps_dev_attr.c @@ -242,6 +242,21 @@ int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg) } +int wps_build_application_ext(struct wps_device_data *dev, struct wpabuf *msg) +{ + if (!dev->application_ext) + return 0; + + wpa_hexdump_buf(MSG_DEBUG, "WPS: * Application Extension", + dev->application_ext); + wpabuf_put_be16(msg, ATTR_APPLICATION_EXT); + wpabuf_put_be16(msg, wpabuf_len(dev->application_ext)); + wpabuf_put_buf(msg, dev->application_ext); + + return 0; +} + + static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str, size_t str_len) { @@ -424,4 +439,6 @@ void wps_device_data_free(struct wps_device_data *dev) dev->model_number = NULL; os_free(dev->serial_number); dev->serial_number = NULL; + wpabuf_free(dev->application_ext); + dev->application_ext = NULL; } diff --git a/src/wps/wps_dev_attr.h b/src/wps/wps_dev_attr.h index a4b4173cd..81fdd5f4e 100644 --- a/src/wps/wps_dev_attr.h +++ b/src/wps/wps_dev_attr.h @@ -33,6 +33,7 @@ void wps_process_vendor_ext_m1(struct wps_device_data *dev, const u8 ext); int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands); void wps_device_data_free(struct wps_device_data *dev); int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_application_ext(struct wps_device_data *dev, struct wpabuf *msg); int wps_build_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg, unsigned int num_req_dev_types, const u8 *req_dev_types); diff --git a/src/wps/wps_registrar.c b/src/wps/wps_registrar.c index 671f5fed7..da81d1adc 100644 --- a/src/wps/wps_registrar.c +++ b/src/wps/wps_registrar.c @@ -1331,7 +1331,8 @@ static int wps_set_ie(struct wps_registrar *reg) wps_build_sel_pbc_reg_uuid_e(reg, beacon) || (reg->dualband && wps_build_rf_bands(®->wps->dev, beacon, 0)) || wps_build_wfa_ext(beacon, 0, auth_macs, count, 0) || - wps_build_vendor_ext(®->wps->dev, beacon)) { + wps_build_vendor_ext(®->wps->dev, beacon) || + wps_build_application_ext(®->wps->dev, beacon)) { wpabuf_free(beacon); wpabuf_free(probe); return -1; @@ -1361,7 +1362,8 @@ static int wps_set_ie(struct wps_registrar *reg) wps_build_probe_config_methods(reg, probe) || (reg->dualband && wps_build_rf_bands(®->wps->dev, probe, 0)) || wps_build_wfa_ext(probe, 0, auth_macs, count, 0) || - wps_build_vendor_ext(®->wps->dev, probe)) { + wps_build_vendor_ext(®->wps->dev, probe) || + wps_build_application_ext(®->wps->dev, probe)) { wpabuf_free(beacon); wpabuf_free(probe); return -1;