18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Wi-Fi Protected Setup - device attributes
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
5c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
78d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_i.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "wps_dev_attr.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg)
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WPS:  * Manufacturer");
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, ATTR_MANUFACTURER);
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = dev->manufacturer ? os_strlen(dev->manufacturer) : 0;
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_WPS_STRICT
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len == 0) {
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Some deployed WPS implementations fail to parse zero-length
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * attributes. As a workaround, send a space character if the
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * device attribute string is empty.
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be16(msg, 1);
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(msg, ' ');
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_STRICT */
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, len);
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(msg, dev->manufacturer, len);
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_model_name(struct wps_device_data *dev, struct wpabuf *msg)
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WPS:  * Model Name");
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, ATTR_MODEL_NAME);
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = dev->model_name ? os_strlen(dev->model_name) : 0;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_WPS_STRICT
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len == 0) {
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Some deployed WPS implementations fail to parse zero-length
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * attributes. As a workaround, send a space character if the
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * device attribute string is empty.
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be16(msg, 1);
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(msg, ' ');
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_STRICT */
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, len);
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(msg, dev->model_name, len);
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg)
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WPS:  * Model Number");
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, ATTR_MODEL_NUMBER);
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = dev->model_number ? os_strlen(dev->model_number) : 0;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_WPS_STRICT
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len == 0) {
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Some deployed WPS implementations fail to parse zero-length
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * attributes. As a workaround, send a space character if the
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * device attribute string is empty.
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be16(msg, 1);
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(msg, ' ');
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_STRICT */
828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, len);
838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(msg, dev->model_number, len);
848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
88cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidtint wps_build_serial_number(struct wps_device_data *dev, struct wpabuf *msg)
898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WPS:  * Serial Number");
928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, ATTR_SERIAL_NUMBER);
938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = dev->serial_number ? os_strlen(dev->serial_number) : 0;
948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_WPS_STRICT
958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len == 0) {
968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Some deployed WPS implementations fail to parse zero-length
988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * attributes. As a workaround, send a space character if the
998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * device attribute string is empty.
1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
1018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be16(msg, 1);
1028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(msg, ' ');
1038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_STRICT */
1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, len);
1078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(msg, dev->serial_number, len);
1088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_primary_dev_type(struct wps_device_data *dev, struct wpabuf *msg)
1138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WPS:  * Primary Device Type");
1158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, ATTR_PRIMARY_DEV_TYPE);
1168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN);
1178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(msg, dev->pri_dev_type, WPS_DEV_TYPE_LEN);
1188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_secondary_dev_type(struct wps_device_data *dev,
1238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  struct wpabuf *msg)
1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (!dev->num_sec_dev_types)
1268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WPS:  * Secondary Device Type");
1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, ATTR_SECONDARY_DEV_TYPE_LIST);
1308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN * dev->num_sec_dev_types);
1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(msg, dev->sec_dev_type,
1328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			WPS_DEV_TYPE_LEN * dev->num_sec_dev_types);
1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg,
1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   unsigned int num_req_dev_types,
1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			   const u8 *req_dev_types)
1418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	unsigned int i;
1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < num_req_dev_types; i++) {
1458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPS: * Requested Device Type",
1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    req_dev_types + i * WPS_DEV_TYPE_LEN,
1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    WPS_DEV_TYPE_LEN);
1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be16(msg, ATTR_REQUESTED_DEV_TYPE);
1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be16(msg, WPS_DEV_TYPE_LEN);
1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_data(msg, req_dev_types + i * WPS_DEV_TYPE_LEN,
1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				WPS_DEV_TYPE_LEN);
1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg)
1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	size_t len;
1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WPS:  * Device Name");
1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, ATTR_DEV_NAME);
1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	len = dev->device_name ? os_strlen(dev->device_name) : 0;
1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_WPS_STRICT
1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (len == 0) {
1668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		/*
1678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * Some deployed WPS implementations fail to parse zero-length
1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * attributes. As a workaround, send a space character if the
1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 * device attribute string is empty.
1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		 */
1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be16(msg, 1);
1728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_u8(msg, ' ');
1738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return 0;
1748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
1758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_WPS_STRICT */
1768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, len);
1778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_data(msg, dev->device_name, len);
1788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg)
1838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_build_manufacturer(dev, msg) ||
1858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wps_build_model_name(dev, msg) ||
1868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wps_build_model_number(dev, msg) ||
1878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wps_build_serial_number(dev, msg) ||
1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wps_build_primary_dev_type(dev, msg) ||
1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wps_build_dev_name(dev, msg))
1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg)
1968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
1978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WPS:  * OS Version");
1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, ATTR_OS_VERSION);
1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be16(msg, 4);
2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpabuf_put_be32(msg, 0x80000000 | dev->os_version);
2018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
20504949598a23f501be6eec21697465fd46a28840aDmitry Shmidtint wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg)
20604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{
20704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	if (dev->vendor_ext_m1 != NULL) {
20804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPS:  * Vendor Extension M1",
20904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			    wpabuf_head_u8(dev->vendor_ext_m1),
21004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt			    wpabuf_len(dev->vendor_ext_m1));
21104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
21204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext_m1));
21304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt		wpabuf_put_buf(msg, dev->vendor_ext_m1);
21404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	}
21504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt	return 0;
21604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt}
21704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
21804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt
219b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtint wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg,
220b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt		       u8 rf_band)
2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
222cf32e60fa7e0d33fe1551a6dba8dcbbec47ea50eDmitry Shmidt	return wps_build_rf_bands_attr(msg, rf_band ? rf_band : dev->rf_bands);
2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg)
2278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i;
2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < MAX_WPS_VENDOR_EXTENSIONS; i++) {
2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		if (dev->vendor_ext[i] == NULL)
2328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			continue;
2338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_hexdump(MSG_DEBUG, "WPS:  * Vendor Extension",
2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_head_u8(dev->vendor_ext[i]),
2358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			    wpabuf_len(dev->vendor_ext[i]));
2368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be16(msg, ATTR_VENDOR_EXT);
2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_be16(msg, wpabuf_len(dev->vendor_ext[i]));
2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpabuf_put_buf(msg, dev->vendor_ext[i]);
2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str,
2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    size_t str_len)
2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (str == NULL) {
2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: No Manufacturer received");
2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len);
2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev->manufacturer);
2564b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	dev->manufacturer = dup_binstr(str, str_len);
2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->manufacturer == NULL)
2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_process_model_name(struct wps_device_data *dev, const u8 *str,
2658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				  size_t str_len)
2668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (str == NULL) {
2688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: No Model Name received");
2698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len);
2738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev->model_name);
2754b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	dev->model_name = dup_binstr(str, str_len);
2768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->model_name == NULL)
2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_process_model_number(struct wps_device_data *dev, const u8 *str,
2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				    size_t str_len)
2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (str == NULL) {
2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: No Model Number received");
2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
2908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len);
2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev->model_number);
2944b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	dev->model_number = dup_binstr(str, str_len);
2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->model_number == NULL)
2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_process_serial_number(struct wps_device_data *dev,
3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     const u8 *str, size_t str_len)
3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (str == NULL) {
3068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: No Serial Number received");
3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len);
3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev->serial_number);
3134b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	dev->serial_number = dup_binstr(str, str_len);
3148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->serial_number == NULL)
3158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_process_dev_name(struct wps_device_data *dev, const u8 *str,
3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				size_t str_len)
3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (str == NULL) {
3258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: No Device Name received");
3268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len);
3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev->device_name);
3324b06059785b935dd1f4f09314e4e12c417d2c6a4Dmitry Shmidt	dev->device_name = dup_binstr(str, str_len);
3338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev->device_name == NULL)
3348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int wps_process_primary_dev_type(struct wps_device_data *dev,
3418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					const u8 *dev_type)
3428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG
3448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	char devtype[WPS_DEV_TYPE_BUFSIZE];
3458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */
3468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (dev_type == NULL) {
3488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: No Primary Device Type received");
3498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(dev->pri_dev_type, dev_type, WPS_DEV_TYPE_LEN);
3538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: %s",
3548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		   wps_dev_type_bin2str(dev->pri_dev_type, devtype,
3558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt					sizeof(devtype)));
3568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_process_device_attrs(struct wps_device_data *dev,
3628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			     struct wps_parse_attr *attr)
3638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (wps_process_manufacturer(dev, attr->manufacturer,
3658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     attr->manufacturer_len) ||
3668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wps_process_model_name(dev, attr->model_name,
3678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				   attr->model_name_len) ||
3688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wps_process_model_number(dev, attr->model_number,
3698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				     attr->model_number_len) ||
3708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wps_process_serial_number(dev, attr->serial_number,
3718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt				      attr->serial_number_len) ||
3728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wps_process_primary_dev_type(dev, attr->primary_dev_type) ||
3738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	    wps_process_dev_name(dev, attr->dev_name, attr->dev_name_len))
3748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_process_os_version(struct wps_device_data *dev, const u8 *ver)
3808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ver == NULL) {
3828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: No OS Version received");
3838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->os_version = WPA_GET_BE32(ver);
3878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WPS: OS Version %08x", dev->os_version);
3888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
3908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
3918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
3938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands)
3948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
3958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (bands == NULL) {
3968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		wpa_printf(MSG_DEBUG, "WPS: No RF Bands received");
3978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
3988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
3998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->rf_bands = *bands;
4018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	wpa_printf(MSG_DEBUG, "WPS: Enrollee RF Bands 0x%x", dev->rf_bands);
4028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
4048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
4058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
4078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid wps_device_data_free(struct wps_device_data *dev)
4088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
4098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev->device_name);
4108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->device_name = NULL;
4118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev->manufacturer);
4128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->manufacturer = NULL;
4138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev->model_name);
4148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->model_name = NULL;
4158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev->model_number);
4168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->model_number = NULL;
4178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_free(dev->serial_number);
4188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	dev->serial_number = NULL;
4198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
420