xref: /freebsd/contrib/wpa/src/p2p/p2p_build.c (revision a9fcb51fbb8d2c5b47a35bcae5b4d5fb771c5985)
1 /*
2  * P2P - IE builder
3  * Copyright (c) 2009-2010, Atheros Communications
4  *
5  * This software may be distributed under the terms of the BSD license.
6  * See README for more details.
7  */
8 
9 #include "includes.h"
10 
11 #include "common.h"
12 #include "common/ieee802_11_defs.h"
13 #include "wps/wps_i.h"
14 #include "p2p_i.h"
15 
16 
17 void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token)
18 {
19 	wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC);
20 	wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
21 
22 	wpabuf_put_u8(buf, subtype); /* OUI Subtype */
23 	wpabuf_put_u8(buf, dialog_token);
24 	wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token);
25 }
26 
27 
28 void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype,
29 				   u8 dialog_token)
30 {
31 	wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
32 	wpabuf_put_u8(buf, WLAN_PA_VENDOR_SPECIFIC);
33 	wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
34 
35 	wpabuf_put_u8(buf, subtype); /* OUI Subtype */
36 	wpabuf_put_u8(buf, dialog_token);
37 	wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token);
38 }
39 
40 
41 u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf)
42 {
43 	u8 *len;
44 
45 	/* P2P IE header */
46 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
47 	len = wpabuf_put(buf, 1); /* IE length to be filled */
48 	wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
49 	wpa_printf(MSG_DEBUG, "P2P: * P2P IE header");
50 	return len;
51 }
52 
53 
54 void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len)
55 {
56 	/* Update P2P IE Length */
57 	*len = (u8 *) wpabuf_put(buf, 0) - len - 1;
58 }
59 
60 
61 void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab)
62 {
63 	/* P2P Capability */
64 	wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY);
65 	wpabuf_put_le16(buf, 2);
66 	wpabuf_put_u8(buf, dev_capab); /* Device Capabilities */
67 	wpabuf_put_u8(buf, group_capab); /* Group Capabilities */
68 	wpa_printf(MSG_DEBUG, "P2P: * Capability dev=%02x group=%02x",
69 		   dev_capab, group_capab);
70 }
71 
72 
73 void p2p_buf_add_go_intent(struct wpabuf *buf, u8 go_intent)
74 {
75 	/* Group Owner Intent */
76 	wpabuf_put_u8(buf, P2P_ATTR_GROUP_OWNER_INTENT);
77 	wpabuf_put_le16(buf, 1);
78 	wpabuf_put_u8(buf, go_intent);
79 	wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u Tie breaker %u",
80 		   go_intent >> 1, go_intent & 0x01);
81 }
82 
83 
84 void p2p_buf_add_listen_channel(struct wpabuf *buf, const char *country,
85 				u8 reg_class, u8 channel)
86 {
87 	/* Listen Channel */
88 	wpabuf_put_u8(buf, P2P_ATTR_LISTEN_CHANNEL);
89 	wpabuf_put_le16(buf, 5);
90 	wpabuf_put_data(buf, country, 3);
91 	wpabuf_put_u8(buf, reg_class); /* Regulatory Class */
92 	wpabuf_put_u8(buf, channel); /* Channel Number */
93 	wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Regulatory Class %u "
94 		   "Channel %u", reg_class, channel);
95 }
96 
97 
98 void p2p_buf_add_operating_channel(struct wpabuf *buf, const char *country,
99 				   u8 reg_class, u8 channel)
100 {
101 	/* Operating Channel */
102 	wpabuf_put_u8(buf, P2P_ATTR_OPERATING_CHANNEL);
103 	wpabuf_put_le16(buf, 5);
104 	wpabuf_put_data(buf, country, 3);
105 	wpabuf_put_u8(buf, reg_class); /* Regulatory Class */
106 	wpabuf_put_u8(buf, channel); /* Channel Number */
107 	wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: Regulatory Class %u "
108 		   "Channel %u", reg_class, channel);
109 }
110 
111 
112 void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country,
113 			      struct p2p_channels *chan)
114 {
115 	u8 *len;
116 	size_t i;
117 
118 	/* Channel List */
119 	wpabuf_put_u8(buf, P2P_ATTR_CHANNEL_LIST);
120 	len = wpabuf_put(buf, 2); /* IE length to be filled */
121 	wpabuf_put_data(buf, country, 3); /* Country String */
122 
123 	for (i = 0; i < chan->reg_classes; i++) {
124 		struct p2p_reg_class *c = &chan->reg_class[i];
125 		wpabuf_put_u8(buf, c->reg_class);
126 		wpabuf_put_u8(buf, c->channels);
127 		wpabuf_put_data(buf, c->channel, c->channels);
128 	}
129 
130 	/* Update attribute length */
131 	WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
132 	wpa_hexdump(MSG_DEBUG, "P2P: * Channel List",
133 		    len + 2, (u8 *) wpabuf_put(buf, 0) - len - 2);
134 }
135 
136 
137 void p2p_buf_add_status(struct wpabuf *buf, u8 status)
138 {
139 	/* Status */
140 	wpabuf_put_u8(buf, P2P_ATTR_STATUS);
141 	wpabuf_put_le16(buf, 1);
142 	wpabuf_put_u8(buf, status);
143 	wpa_printf(MSG_DEBUG, "P2P: * Status: %d", status);
144 }
145 
146 
147 void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p,
148 			     struct p2p_device *peer)
149 {
150 	u8 *len;
151 	u16 methods;
152 	size_t nlen, i;
153 
154 	/* P2P Device Info */
155 	wpabuf_put_u8(buf, P2P_ATTR_DEVICE_INFO);
156 	len = wpabuf_put(buf, 2); /* IE length to be filled */
157 
158 	/* P2P Device address */
159 	wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
160 
161 	/* Config Methods */
162 	methods = 0;
163 	if (peer && peer->wps_method != WPS_NOT_READY) {
164 		if (peer->wps_method == WPS_PBC)
165 			methods |= WPS_CONFIG_PUSHBUTTON;
166 		else if (peer->wps_method == WPS_PIN_DISPLAY ||
167 			 peer->wps_method == WPS_PIN_KEYPAD) {
168 			methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
169 			methods |= WPS_CONFIG_P2PS;
170 		}
171 	} else if (p2p->cfg->config_methods) {
172 		methods |= p2p->cfg->config_methods &
173 			(WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_DISPLAY |
174 			 WPS_CONFIG_KEYPAD | WPS_CONFIG_P2PS);
175 	} else {
176 		methods |= WPS_CONFIG_PUSHBUTTON;
177 		methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
178 		methods |= WPS_CONFIG_P2PS;
179 	}
180 	wpabuf_put_be16(buf, methods);
181 
182 	/* Primary Device Type */
183 	wpabuf_put_data(buf, p2p->cfg->pri_dev_type,
184 			sizeof(p2p->cfg->pri_dev_type));
185 
186 	/* Number of Secondary Device Types */
187 	wpabuf_put_u8(buf, p2p->cfg->num_sec_dev_types);
188 
189 	/* Secondary Device Type List */
190 	for (i = 0; i < p2p->cfg->num_sec_dev_types; i++)
191 		wpabuf_put_data(buf, p2p->cfg->sec_dev_type[i],
192 				WPS_DEV_TYPE_LEN);
193 
194 	/* Device Name */
195 	nlen = p2p->cfg->dev_name ? os_strlen(p2p->cfg->dev_name) : 0;
196 	wpabuf_put_be16(buf, ATTR_DEV_NAME);
197 	wpabuf_put_be16(buf, nlen);
198 	wpabuf_put_data(buf, p2p->cfg->dev_name, nlen);
199 
200 	/* Update attribute length */
201 	WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
202 	wpa_printf(MSG_DEBUG, "P2P: * Device Info");
203 }
204 
205 
206 void p2p_buf_add_device_id(struct wpabuf *buf, const u8 *dev_addr)
207 {
208 	/* P2P Device ID */
209 	wpabuf_put_u8(buf, P2P_ATTR_DEVICE_ID);
210 	wpabuf_put_le16(buf, ETH_ALEN);
211 	wpabuf_put_data(buf, dev_addr, ETH_ALEN);
212 	wpa_printf(MSG_DEBUG, "P2P: * Device ID: " MACSTR, MAC2STR(dev_addr));
213 }
214 
215 
216 void p2p_buf_add_config_timeout(struct wpabuf *buf, u8 go_timeout,
217 				u8 client_timeout)
218 {
219 	/* Configuration Timeout */
220 	wpabuf_put_u8(buf, P2P_ATTR_CONFIGURATION_TIMEOUT);
221 	wpabuf_put_le16(buf, 2);
222 	wpabuf_put_u8(buf, go_timeout);
223 	wpabuf_put_u8(buf, client_timeout);
224 	wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout: GO %d (*10ms)  "
225 		   "client %d (*10ms)", go_timeout, client_timeout);
226 }
227 
228 
229 void p2p_buf_add_intended_addr(struct wpabuf *buf, const u8 *interface_addr)
230 {
231 	/* Intended P2P Interface Address */
232 	wpabuf_put_u8(buf, P2P_ATTR_INTENDED_INTERFACE_ADDR);
233 	wpabuf_put_le16(buf, ETH_ALEN);
234 	wpabuf_put_data(buf, interface_addr, ETH_ALEN);
235 	wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address " MACSTR,
236 		   MAC2STR(interface_addr));
237 }
238 
239 
240 void p2p_buf_add_group_bssid(struct wpabuf *buf, const u8 *bssid)
241 {
242 	/* P2P Group BSSID */
243 	wpabuf_put_u8(buf, P2P_ATTR_GROUP_BSSID);
244 	wpabuf_put_le16(buf, ETH_ALEN);
245 	wpabuf_put_data(buf, bssid, ETH_ALEN);
246 	wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID " MACSTR,
247 		   MAC2STR(bssid));
248 }
249 
250 
251 void p2p_buf_add_group_id(struct wpabuf *buf, const u8 *dev_addr,
252 			  const u8 *ssid, size_t ssid_len)
253 {
254 	/* P2P Group ID */
255 	wpabuf_put_u8(buf, P2P_ATTR_GROUP_ID);
256 	wpabuf_put_le16(buf, ETH_ALEN + ssid_len);
257 	wpabuf_put_data(buf, dev_addr, ETH_ALEN);
258 	wpabuf_put_data(buf, ssid, ssid_len);
259 	wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID " MACSTR,
260 		   MAC2STR(dev_addr));
261 	wpa_hexdump_ascii(MSG_DEBUG, "P2P: P2P Group ID SSID", ssid, ssid_len);
262 }
263 
264 
265 void p2p_buf_add_invitation_flags(struct wpabuf *buf, u8 flags)
266 {
267 	/* Invitation Flags */
268 	wpabuf_put_u8(buf, P2P_ATTR_INVITATION_FLAGS);
269 	wpabuf_put_le16(buf, 1);
270 	wpabuf_put_u8(buf, flags);
271 	wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x", flags);
272 }
273 
274 
275 static void p2p_buf_add_noa_desc(struct wpabuf *buf, struct p2p_noa_desc *desc)
276 {
277 	if (desc == NULL)
278 		return;
279 
280 	wpabuf_put_u8(buf, desc->count_type);
281 	wpabuf_put_le32(buf, desc->duration);
282 	wpabuf_put_le32(buf, desc->interval);
283 	wpabuf_put_le32(buf, desc->start_time);
284 }
285 
286 
287 void p2p_buf_add_noa(struct wpabuf *buf, u8 noa_index, u8 opp_ps, u8 ctwindow,
288 		     struct p2p_noa_desc *desc1, struct p2p_noa_desc *desc2)
289 {
290 	/* Notice of Absence */
291 	wpabuf_put_u8(buf, P2P_ATTR_NOTICE_OF_ABSENCE);
292 	wpabuf_put_le16(buf, 2 + (desc1 ? 13 : 0) + (desc2 ? 13 : 0));
293 	wpabuf_put_u8(buf, noa_index);
294 	wpabuf_put_u8(buf, (opp_ps ? 0x80 : 0) | (ctwindow & 0x7f));
295 	p2p_buf_add_noa_desc(buf, desc1);
296 	p2p_buf_add_noa_desc(buf, desc2);
297 	wpa_printf(MSG_DEBUG, "P2P: * Notice of Absence");
298 }
299 
300 
301 void p2p_buf_add_ext_listen_timing(struct wpabuf *buf, u16 period,
302 				   u16 interval)
303 {
304 	/* Extended Listen Timing */
305 	wpabuf_put_u8(buf, P2P_ATTR_EXT_LISTEN_TIMING);
306 	wpabuf_put_le16(buf, 4);
307 	wpabuf_put_le16(buf, period);
308 	wpabuf_put_le16(buf, interval);
309 	wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing (period %u msec  "
310 		   "interval %u msec)", period, interval);
311 }
312 
313 
314 void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p)
315 {
316 	/* P2P Interface */
317 	wpabuf_put_u8(buf, P2P_ATTR_INTERFACE);
318 	wpabuf_put_le16(buf, ETH_ALEN + 1 + ETH_ALEN);
319 	/* P2P Device address */
320 	wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
321 	/*
322 	 * FIX: Fetch interface address list from driver. Do not include
323 	 * the P2P Device address if it is never used as interface address.
324 	 */
325 	/* P2P Interface Address Count */
326 	wpabuf_put_u8(buf, 1);
327 	wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
328 }
329 
330 
331 void p2p_buf_add_oob_go_neg_channel(struct wpabuf *buf, const char *country,
332 				    u8 oper_class, u8 channel,
333 				    enum p2p_role_indication role)
334 {
335 	/* OOB Group Owner Negotiation Channel */
336 	wpabuf_put_u8(buf, P2P_ATTR_OOB_GO_NEG_CHANNEL);
337 	wpabuf_put_le16(buf, 6);
338 	wpabuf_put_data(buf, country, 3);
339 	wpabuf_put_u8(buf, oper_class); /* Operating Class */
340 	wpabuf_put_u8(buf, channel); /* Channel Number */
341 	wpabuf_put_u8(buf, (u8) role); /* Role indication */
342 	wpa_printf(MSG_DEBUG, "P2P: * OOB GO Negotiation Channel: Operating "
343 		   "Class %u Channel %u Role %d",
344 		   oper_class, channel, role);
345 }
346 
347 
348 void p2p_buf_add_service_hash(struct wpabuf *buf, struct p2p_data *p2p)
349 {
350 	if (!p2p)
351 		return;
352 
353 	/* Service Hash */
354 	wpabuf_put_u8(buf, P2P_ATTR_SERVICE_HASH);
355 	wpabuf_put_le16(buf, p2p->p2ps_seek_count * P2PS_HASH_LEN);
356 	wpabuf_put_data(buf, p2p->query_hash,
357 			p2p->p2ps_seek_count * P2PS_HASH_LEN);
358 	wpa_hexdump(MSG_DEBUG, "P2P: * Service Hash",
359 		    p2p->query_hash, p2p->p2ps_seek_count * P2PS_HASH_LEN);
360 }
361 
362 
363 void p2p_buf_add_session_info(struct wpabuf *buf, const char *info)
364 {
365 	size_t info_len = 0;
366 
367 	if (info && info[0])
368 		info_len = os_strlen(info);
369 
370 	/* Session Information Data Info */
371 	wpabuf_put_u8(buf, P2P_ATTR_SESSION_INFORMATION_DATA);
372 	wpabuf_put_le16(buf, (u16) info_len);
373 
374 	if (info) {
375 		wpabuf_put_data(buf, info, info_len);
376 		wpa_printf(MSG_DEBUG, "P2P: * Session Info Data (%s)", info);
377 	}
378 }
379 
380 
381 void p2p_buf_add_connection_capability(struct wpabuf *buf, u8 connection_cap)
382 {
383 	/* Connection Capability Info */
384 	wpabuf_put_u8(buf, P2P_ATTR_CONNECTION_CAPABILITY);
385 	wpabuf_put_le16(buf, 1);
386 	wpabuf_put_u8(buf, connection_cap);
387 	wpa_printf(MSG_DEBUG, "P2P: * Connection Capability: 0x%x",
388 		   connection_cap);
389 }
390 
391 
392 void p2p_buf_add_advertisement_id(struct wpabuf *buf, u32 id, const u8 *mac)
393 {
394 	if (!buf || !mac)
395 		return;
396 
397 	/* Advertisement ID Info */
398 	wpabuf_put_u8(buf, P2P_ATTR_ADVERTISEMENT_ID);
399 	wpabuf_put_le16(buf, (u16) (sizeof(u32) + ETH_ALEN));
400 	wpabuf_put_le32(buf, id);
401 	wpabuf_put_data(buf, mac, ETH_ALEN);
402 	wpa_printf(MSG_DEBUG, "P2P: * Advertisement ID (%x) " MACSTR,
403 		   id, MAC2STR(mac));
404 }
405 
406 
407 void p2p_buf_add_service_instance(struct wpabuf *buf, struct p2p_data *p2p,
408 				  u8 hash_count, const u8 *hash,
409 				  struct p2ps_advertisement *adv_list)
410 {
411 	struct p2ps_advertisement *adv;
412 	struct wpabuf *tmp_buf;
413 	u8 *tag_len = NULL, *ie_len = NULL;
414 	size_t svc_len = 0, remaining = 0, total_len = 0;
415 
416 	if (!adv_list || !hash)
417 		return;
418 
419 	/* Allocate temp buffer, allowing for overflow of 1 instance */
420 	tmp_buf = wpabuf_alloc(MAX_SVC_ADV_IE_LEN + 256 + P2PS_HASH_LEN);
421 	if (!tmp_buf)
422 		return;
423 
424 	for (adv = adv_list; adv && total_len <= MAX_SVC_ADV_LEN;
425 	     adv = adv->next) {
426 		u8 count = hash_count;
427 		const u8 *test = hash;
428 
429 		while (count--) {
430 			/* Check for wildcard */
431 			if (os_memcmp(test, p2p->wild_card_hash,
432 				      P2PS_HASH_LEN) == 0) {
433 				total_len = MAX_SVC_ADV_LEN + 1;
434 				goto wild_hash;
435 			}
436 
437 			if (os_memcmp(test, adv->hash, P2PS_HASH_LEN) == 0)
438 				goto hash_match;
439 
440 			test += P2PS_HASH_LEN;
441 		}
442 
443 		/* No matches found - Skip this Adv Instance */
444 		continue;
445 
446 hash_match:
447 		if (!tag_len) {
448 			tag_len = p2p_buf_add_ie_hdr(tmp_buf);
449 			remaining = 255 - 4;
450 			if (!ie_len) {
451 				wpabuf_put_u8(tmp_buf,
452 					      P2P_ATTR_ADVERTISED_SERVICE);
453 				ie_len = wpabuf_put(tmp_buf, sizeof(u16));
454 				remaining -= (sizeof(u8) + sizeof(u16));
455 			}
456 		}
457 
458 		svc_len = os_strlen(adv->svc_name);
459 
460 		if (7 + svc_len + total_len > MAX_SVC_ADV_LEN) {
461 			/* Can't fit... return wildcard */
462 			total_len = MAX_SVC_ADV_LEN + 1;
463 			break;
464 		}
465 
466 		if (remaining <= (sizeof(adv->id) +
467 				  sizeof(adv->config_methods))) {
468 			size_t front = remaining;
469 			size_t back = (sizeof(adv->id) +
470 				       sizeof(adv->config_methods)) - front;
471 			u8 holder[sizeof(adv->id) +
472 				  sizeof(adv->config_methods)];
473 
474 			/* This works even if front or back == 0 */
475 			WPA_PUT_LE32(holder, adv->id);
476 			WPA_PUT_BE16(&holder[sizeof(adv->id)],
477 				     adv->config_methods);
478 			wpabuf_put_data(tmp_buf, holder, front);
479 			p2p_buf_update_ie_hdr(tmp_buf, tag_len);
480 			tag_len = p2p_buf_add_ie_hdr(tmp_buf);
481 			wpabuf_put_data(tmp_buf, &holder[front], back);
482 			remaining = 255 - (sizeof(adv->id) +
483 					   sizeof(adv->config_methods)) - back;
484 		} else {
485 			wpabuf_put_le32(tmp_buf, adv->id);
486 			wpabuf_put_be16(tmp_buf, adv->config_methods);
487 			remaining -= (sizeof(adv->id) +
488 				      sizeof(adv->config_methods));
489 		}
490 
491 		/* We are guaranteed at least one byte for svc_len */
492 		wpabuf_put_u8(tmp_buf, svc_len);
493 		remaining -= sizeof(u8);
494 
495 		if (remaining < svc_len) {
496 			size_t front = remaining;
497 			size_t back = svc_len - front;
498 
499 			wpabuf_put_data(tmp_buf, adv->svc_name, front);
500 			p2p_buf_update_ie_hdr(tmp_buf, tag_len);
501 			tag_len = p2p_buf_add_ie_hdr(tmp_buf);
502 
503 			/* In rare cases, we must split across 3 attributes */
504 			if (back > 255 - 4) {
505 				wpabuf_put_data(tmp_buf,
506 						&adv->svc_name[front], 255 - 4);
507 				back -= 255 - 4;
508 				front += 255 - 4;
509 				p2p_buf_update_ie_hdr(tmp_buf, tag_len);
510 				tag_len = p2p_buf_add_ie_hdr(tmp_buf);
511 			}
512 
513 			wpabuf_put_data(tmp_buf, &adv->svc_name[front], back);
514 			remaining = 255 - 4 - back;
515 		} else {
516 			wpabuf_put_data(tmp_buf, adv->svc_name, svc_len);
517 			remaining -= svc_len;
518 		}
519 
520 		/*           adv_id      config_methods     svc_string */
521 		total_len += sizeof(u32) + sizeof(u16) + sizeof(u8) + svc_len;
522 	}
523 
524 	if (tag_len)
525 		p2p_buf_update_ie_hdr(tmp_buf, tag_len);
526 
527 	if (ie_len)
528 		WPA_PUT_LE16(ie_len, (u16) total_len);
529 
530 wild_hash:
531 	/* If all fit, return matching instances, otherwise the wildcard */
532 	if (total_len <= MAX_SVC_ADV_LEN) {
533 		wpabuf_put_buf(buf, tmp_buf);
534 	} else {
535 		char *wild_card = P2PS_WILD_HASH_STR;
536 		u8 wild_len;
537 
538 		/* Insert wildcard instance */
539 		tag_len = p2p_buf_add_ie_hdr(buf);
540 		wpabuf_put_u8(buf, P2P_ATTR_ADVERTISED_SERVICE);
541 		ie_len = wpabuf_put(buf, sizeof(u16));
542 
543 		wild_len = (u8) os_strlen(wild_card);
544 		wpabuf_put_le32(buf, 0);
545 		wpabuf_put_be16(buf, 0);
546 		wpabuf_put_u8(buf, wild_len);
547 		wpabuf_put_data(buf, wild_card, wild_len);
548 
549 		WPA_PUT_LE16(ie_len, 4 + 2 + 1 + wild_len);
550 		p2p_buf_update_ie_hdr(buf, tag_len);
551 	}
552 
553 	wpabuf_free(tmp_buf);
554 }
555 
556 
557 void p2p_buf_add_session_id(struct wpabuf *buf, u32 id, const u8 *mac)
558 {
559 	if (!buf || !mac)
560 		return;
561 
562 	/* Session ID Info */
563 	wpabuf_put_u8(buf, P2P_ATTR_SESSION_ID);
564 	wpabuf_put_le16(buf, (u16) (sizeof(u32) + ETH_ALEN));
565 	wpabuf_put_le32(buf, id);
566 	wpabuf_put_data(buf, mac, ETH_ALEN);
567 	wpa_printf(MSG_DEBUG, "P2P: * Session ID Info (%x) " MACSTR,
568 		   id, MAC2STR(mac));
569 }
570 
571 
572 void p2p_buf_add_feature_capability(struct wpabuf *buf, u16 len, const u8 *mask)
573 {
574 	if (!buf || !len || !mask)
575 		return;
576 
577 	/* Feature Capability */
578 	wpabuf_put_u8(buf, P2P_ATTR_FEATURE_CAPABILITY);
579 	wpabuf_put_le16(buf, len);
580 	wpabuf_put_data(buf, mask, len);
581 	wpa_printf(MSG_DEBUG, "P2P: * Feature Capability (%d)", len);
582 }
583 
584 
585 void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr,
586 				       const u8 *ssid, size_t ssid_len)
587 {
588 	/* P2P Group ID */
589 	wpabuf_put_u8(buf, P2P_ATTR_PERSISTENT_GROUP);
590 	wpabuf_put_le16(buf, ETH_ALEN + ssid_len);
591 	wpabuf_put_data(buf, dev_addr, ETH_ALEN);
592 	wpabuf_put_data(buf, ssid, ssid_len);
593 	wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID " MACSTR,
594 		   MAC2STR(dev_addr));
595 }
596 
597 
598 static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
599 			      const char *val)
600 {
601 	size_t len;
602 
603 	len = val ? os_strlen(val) : 0;
604 	if (wpabuf_tailroom(buf) < 4 + len)
605 		return -1;
606 	wpabuf_put_be16(buf, attr);
607 #ifndef CONFIG_WPS_STRICT
608 	if (len == 0) {
609 		/*
610 		 * Some deployed WPS implementations fail to parse zeor-length
611 		 * attributes. As a workaround, send a space character if the
612 		 * device attribute string is empty.
613 		 */
614 		if (wpabuf_tailroom(buf) < 3)
615 			return -1;
616 		wpabuf_put_be16(buf, 1);
617 		wpabuf_put_u8(buf, ' ');
618 		return 0;
619 	}
620 #endif /* CONFIG_WPS_STRICT */
621 	wpabuf_put_be16(buf, len);
622 	if (val)
623 		wpabuf_put_data(buf, val, len);
624 	return 0;
625 }
626 
627 
628 int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
629 		     int all_attr)
630 {
631 	u8 *len;
632 	int i;
633 
634 	if (wpabuf_tailroom(buf) < 6)
635 		return -1;
636 	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
637 	len = wpabuf_put(buf, 1);
638 	wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
639 
640 	if (wps_build_version(buf) < 0)
641 		return -1;
642 
643 	if (all_attr) {
644 		if (wpabuf_tailroom(buf) < 5)
645 			return -1;
646 		wpabuf_put_be16(buf, ATTR_WPS_STATE);
647 		wpabuf_put_be16(buf, 1);
648 		wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED);
649 	}
650 
651 	if (pw_id >= 0) {
652 		if (wpabuf_tailroom(buf) < 6)
653 			return -1;
654 		/* Device Password ID */
655 		wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID);
656 		wpabuf_put_be16(buf, 2);
657 		wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d",
658 			   pw_id);
659 		wpabuf_put_be16(buf, pw_id);
660 	}
661 
662 	if (all_attr) {
663 		if (wpabuf_tailroom(buf) < 5)
664 			return -1;
665 		wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE);
666 		wpabuf_put_be16(buf, 1);
667 		wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO);
668 
669 		if (wps_build_uuid_e(buf, p2p->cfg->uuid) < 0 ||
670 		    p2p_add_wps_string(buf, ATTR_MANUFACTURER,
671 				       p2p->cfg->manufacturer) < 0 ||
672 		    p2p_add_wps_string(buf, ATTR_MODEL_NAME,
673 				       p2p->cfg->model_name) < 0 ||
674 		    p2p_add_wps_string(buf, ATTR_MODEL_NUMBER,
675 				       p2p->cfg->model_number) < 0 ||
676 		    p2p_add_wps_string(buf, ATTR_SERIAL_NUMBER,
677 				       p2p->cfg->serial_number) < 0)
678 			return -1;
679 
680 		if (wpabuf_tailroom(buf) < 4 + WPS_DEV_TYPE_LEN)
681 			return -1;
682 		wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE);
683 		wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN);
684 		wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN);
685 
686 		if (p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name)
687 		    < 0)
688 			return -1;
689 
690 		if (wpabuf_tailroom(buf) < 6)
691 			return -1;
692 		wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
693 		wpabuf_put_be16(buf, 2);
694 		wpabuf_put_be16(buf, p2p->cfg->config_methods);
695 	}
696 
697 	if (wps_build_wfa_ext(buf, 0, NULL, 0) < 0)
698 		return -1;
699 
700 	if (all_attr && p2p->cfg->num_sec_dev_types) {
701 		if (wpabuf_tailroom(buf) <
702 		    4 + WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types)
703 			return -1;
704 		wpabuf_put_be16(buf, ATTR_SECONDARY_DEV_TYPE_LIST);
705 		wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN *
706 				p2p->cfg->num_sec_dev_types);
707 		wpabuf_put_data(buf, p2p->cfg->sec_dev_type,
708 				WPS_DEV_TYPE_LEN *
709 				p2p->cfg->num_sec_dev_types);
710 	}
711 
712 	/* Add the WPS vendor extensions */
713 	for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
714 		if (p2p->wps_vendor_ext[i] == NULL)
715 			break;
716 		if (wpabuf_tailroom(buf) <
717 		    4 + wpabuf_len(p2p->wps_vendor_ext[i]))
718 			continue;
719 		wpabuf_put_be16(buf, ATTR_VENDOR_EXT);
720 		wpabuf_put_be16(buf, wpabuf_len(p2p->wps_vendor_ext[i]));
721 		wpabuf_put_buf(buf, p2p->wps_vendor_ext[i]);
722 	}
723 
724 	p2p_buf_update_ie_hdr(buf, len);
725 
726 	return 0;
727 }
728