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