From b6e01800355a3dac272f835ca5d4ae618b7bdf8a Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 28 Mar 2011 15:24:12 +0300 Subject: [PATCH] P2P: Add more WPS attributes into Listen state Probe Response Configure more WPS attributes in the P2P module and use them when generating WSC IE for Probe Response frames in Listen state. --- src/p2p/p2p.c | 81 ++++++++++++++++++++++++++++++++- src/p2p/p2p.h | 24 ++++++++-- src/p2p/p2p_build.c | 50 +++++++++++++------- wpa_supplicant/p2p_supplicant.c | 22 +++++++++ 4 files changed, 156 insertions(+), 21 deletions(-) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index fa56d6203..454645162 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -1621,7 +1621,6 @@ struct wpabuf * p2p_build_probe_resp_ies(struct p2p_data *p2p) if (buf == NULL) return NULL; - /* TODO: add more info into WPS IE; maybe get from WPS module? */ p2p_build_wps_ie(p2p, buf, DEV_PW_DEFAULT, 1); /* P2P IE */ @@ -1954,6 +1953,14 @@ struct p2p_data * p2p_init(const struct p2p_config *cfg) os_memcpy(p2p->cfg, cfg, sizeof(*cfg)); if (cfg->dev_name) p2p->cfg->dev_name = os_strdup(cfg->dev_name); + if (cfg->manufacturer) + p2p->cfg->manufacturer = os_strdup(cfg->manufacturer); + if (cfg->model_name) + p2p->cfg->model_name = os_strdup(cfg->model_name); + if (cfg->model_number) + p2p->cfg->model_number = os_strdup(cfg->model_number); + if (cfg->serial_number) + p2p->cfg->serial_number = os_strdup(cfg->serial_number); p2p->min_disc_int = 1; p2p->max_disc_int = 3; @@ -1984,6 +1991,10 @@ void p2p_deinit(struct p2p_data *p2p) p2p_flush(p2p); p2p_free_req_dev_types(p2p); os_free(p2p->cfg->dev_name); + os_free(p2p->cfg->manufacturer); + os_free(p2p->cfg->model_name); + os_free(p2p->cfg->model_number); + os_free(p2p->cfg->serial_number); os_free(p2p->groups); wpabuf_free(p2p->sd_resp); os_free(p2p->after_scan_tx); @@ -2053,6 +2064,74 @@ int p2p_set_dev_name(struct p2p_data *p2p, const char *dev_name) } +int p2p_set_manufacturer(struct p2p_data *p2p, const char *manufacturer) +{ + os_free(p2p->cfg->manufacturer); + p2p->cfg->manufacturer = NULL; + if (manufacturer) { + p2p->cfg->manufacturer = os_strdup(manufacturer); + if (p2p->cfg->manufacturer == NULL) + return -1; + } + + return 0; +} + + +int p2p_set_model_name(struct p2p_data *p2p, const char *model_name) +{ + os_free(p2p->cfg->model_name); + p2p->cfg->model_name = NULL; + if (model_name) { + p2p->cfg->model_name = os_strdup(model_name); + if (p2p->cfg->model_name == NULL) + return -1; + } + + return 0; +} + + +int p2p_set_model_number(struct p2p_data *p2p, const char *model_number) +{ + os_free(p2p->cfg->model_number); + p2p->cfg->model_number = NULL; + if (model_number) { + p2p->cfg->model_number = os_strdup(model_number); + if (p2p->cfg->model_number == NULL) + return -1; + } + + return 0; +} + + +int p2p_set_serial_number(struct p2p_data *p2p, const char *serial_number) +{ + os_free(p2p->cfg->serial_number); + p2p->cfg->serial_number = NULL; + if (serial_number) { + p2p->cfg->serial_number = os_strdup(serial_number); + if (p2p->cfg->serial_number == NULL) + return -1; + } + + return 0; +} + + +void p2p_set_config_methods(struct p2p_data *p2p, u16 config_methods) +{ + p2p->cfg->config_methods = config_methods; +} + + +void p2p_set_uuid(struct p2p_data *p2p, const u8 *uuid) +{ + os_memcpy(p2p->cfg->uuid, uuid, 16); +} + + int p2p_set_pri_dev_type(struct p2p_data *p2p, const u8 *pri_dev_type) { os_memcpy(p2p->cfg->pri_dev_type, pri_dev_type, 8); diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index eb70dcfb1..a7d9839d8 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -251,6 +251,11 @@ struct p2p_config { */ u8 sec_dev_type[P2P_SEC_DEVICE_TYPES][8]; + /** + * num_sec_dev_types - Number of sec_dev_type entries + */ + size_t num_sec_dev_types; + /** * dev_addr - P2P Device Address */ @@ -261,10 +266,13 @@ struct p2p_config { */ char *dev_name; - /** - * num_sec_dev_types - Number of sec_dev_type entries - */ - size_t num_sec_dev_types; + char *manufacturer; + char *model_name; + char *model_number; + char *serial_number; + + u8 uuid[16]; + u16 config_methods; /** * concurrent_operations - Whether concurrent operations are supported @@ -700,6 +708,14 @@ int p2p_unauthorize(struct p2p_data *p2p, const u8 *addr); */ int p2p_set_dev_name(struct p2p_data *p2p, const char *dev_name); +int p2p_set_manufacturer(struct p2p_data *p2p, const char *manufacturer); +int p2p_set_model_name(struct p2p_data *p2p, const char *model_name); +int p2p_set_model_number(struct p2p_data *p2p, const char *model_number); +int p2p_set_serial_number(struct p2p_data *p2p, const char *serial_number); + +void p2p_set_config_methods(struct p2p_data *p2p, u16 config_methods); +void p2p_set_uuid(struct p2p_data *p2p, const u8 *uuid); + /** * p2p_set_pri_dev_type - Set primary device type * @p2p: P2P module context from p2p_init() diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c index bd263381b..42acc67bc 100644 --- a/src/p2p/p2p_build.c +++ b/src/p2p/p2p_build.c @@ -330,6 +330,30 @@ void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p) } +static void p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr, + const char *val) +{ + size_t len; + + wpabuf_put_be16(buf, attr); + len = val ? os_strlen(val) : 0; +#ifndef CONFIG_WPS_STRICT + if (len == 0) { + /* + * Some deployed WPS implementations fail to parse zeor-length + * attributes. As a workaround, send a space character if the + * device attribute string is empty. + */ + wpabuf_put_be16(buf, 1); + wpabuf_put_u8(buf, ' '); + } +#endif /* CONFIG_WPS_STRICT */ + wpabuf_put_be16(buf, len); + if (val) + wpabuf_put_data(buf, val, len); +} + + void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, u16 pw_id, int all_attr) { @@ -355,34 +379,28 @@ void p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, u16 pw_id, wpabuf_put_be16(buf, pw_id); if (all_attr) { - size_t nlen; - wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE); wpabuf_put_be16(buf, 1); wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO); -#if 0 - /* FIX */ - wps_build_uuid_e(buf, reg->wps->uuid); - wps_build_manufacturer(dev, buf); - wps_build_model_name(dev, buf); - wps_build_model_number(dev, buf); - wps_build_serial_number(dev, buf); -#endif + wps_build_uuid_e(buf, p2p->cfg->uuid); + p2p_add_wps_string(buf, ATTR_MANUFACTURER, + p2p->cfg->manufacturer); + p2p_add_wps_string(buf, ATTR_MODEL_NAME, p2p->cfg->model_name); + p2p_add_wps_string(buf, ATTR_MODEL_NUMBER, + p2p->cfg->model_number); + p2p_add_wps_string(buf, ATTR_SERIAL_NUMBER, + p2p->cfg->serial_number); wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE); wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN); wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN); - wpabuf_put_be16(buf, ATTR_DEV_NAME); - nlen = p2p->cfg->dev_name ? os_strlen(p2p->cfg->dev_name) : 0; - wpabuf_put_be16(buf, nlen); - if (p2p->cfg->dev_name) - wpabuf_put_data(buf, p2p->cfg->dev_name, nlen); + p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name); wpabuf_put_be16(buf, ATTR_CONFIG_METHODS); wpabuf_put_be16(buf, 2); - wpabuf_put_be16(buf, 0); /* FIX: ? */ + wpabuf_put_be16(buf, p2p->cfg->config_methods); } wps_build_wfa_ext(buf, 0, NULL, 0); diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 9d4b23db8..cfa651001 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -2362,6 +2362,14 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN); os_memcpy(p2p.dev_addr, wpa_s->own_addr, ETH_ALEN); p2p.dev_name = wpa_s->conf->device_name; + p2p.manufacturer = wpa_s->conf->manufacturer; + p2p.model_name = wpa_s->conf->model_name; + p2p.model_number = wpa_s->conf->model_number; + p2p.serial_number = wpa_s->conf->serial_number; + if (wpa_s->wps) { + os_memcpy(p2p.uuid, wpa_s->wps->uuid, 16); + p2p.config_methods = wpa_s->wps->config_methods; + } if (wpa_s->conf->p2p_listen_reg_class && wpa_s->conf->p2p_listen_channel) { @@ -3891,6 +3899,20 @@ void wpas_p2p_update_config(struct wpa_supplicant *wpa_s) if (wpa_s->conf->changed_parameters & CFG_CHANGED_DEVICE_TYPE) p2p_set_pri_dev_type(p2p, wpa_s->conf->device_type); + if (wpa_s->wps && + (wpa_s->conf->changed_parameters & CFG_CHANGED_CONFIG_METHODS)) + p2p_set_config_methods(p2p, wpa_s->wps->config_methods); + + if (wpa_s->wps && (wpa_s->conf->changed_parameters & CFG_CHANGED_UUID)) + p2p_set_uuid(p2p, wpa_s->wps->uuid); + + if (wpa_s->conf->changed_parameters & CFG_CHANGED_WPS_STRING) { + p2p_set_manufacturer(p2p, wpa_s->conf->manufacturer); + p2p_set_model_name(p2p, wpa_s->conf->model_name); + p2p_set_model_number(p2p, wpa_s->conf->model_number); + p2p_set_serial_number(p2p, wpa_s->conf->serial_number); + } + if (wpa_s->conf->changed_parameters & CFG_CHANGED_SEC_DEVICE_TYPE) p2p_set_sec_dev_types(p2p, (void *) wpa_s->conf->sec_device_type,