Branch data Line data Source code
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 : 2 : void p2p_buf_add_action_hdr(struct wpabuf *buf, u8 subtype, u8 dialog_token)
18 : : {
19 : 2 : wpabuf_put_u8(buf, WLAN_ACTION_VENDOR_SPECIFIC);
20 : 2 : wpabuf_put_be24(buf, OUI_WFA);
21 : 2 : wpabuf_put_u8(buf, P2P_OUI_TYPE);
22 : :
23 : 2 : wpabuf_put_u8(buf, subtype); /* OUI Subtype */
24 : 2 : wpabuf_put_u8(buf, dialog_token);
25 : 2 : wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token);
26 : 2 : }
27 : :
28 : :
29 : 458 : void p2p_buf_add_public_action_hdr(struct wpabuf *buf, u8 subtype,
30 : : u8 dialog_token)
31 : : {
32 : 458 : wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
33 : 458 : wpabuf_put_u8(buf, WLAN_PA_VENDOR_SPECIFIC);
34 : 458 : wpabuf_put_be24(buf, OUI_WFA);
35 : 458 : wpabuf_put_u8(buf, P2P_OUI_TYPE);
36 : :
37 : 458 : wpabuf_put_u8(buf, subtype); /* OUI Subtype */
38 : 458 : wpabuf_put_u8(buf, dialog_token);
39 : 458 : wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token);
40 : 458 : }
41 : :
42 : :
43 : 4066 : u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf)
44 : : {
45 : : u8 *len;
46 : :
47 : : /* P2P IE header */
48 : 4066 : wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
49 : 4066 : len = wpabuf_put(buf, 1); /* IE length to be filled */
50 : 4066 : wpabuf_put_be24(buf, OUI_WFA);
51 : 4066 : wpabuf_put_u8(buf, P2P_OUI_TYPE);
52 : 4066 : wpa_printf(MSG_DEBUG, "P2P: * P2P IE header");
53 : 4066 : return len;
54 : : }
55 : :
56 : :
57 : 5544 : void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len)
58 : : {
59 : : /* Update P2P IE Length */
60 : 5544 : *len = (u8 *) wpabuf_put(buf, 0) - len - 1;
61 : 5544 : }
62 : :
63 : :
64 : 3698 : void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab)
65 : : {
66 : : /* P2P Capability */
67 : 3698 : wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY);
68 : 3698 : wpabuf_put_le16(buf, 2);
69 : 3698 : wpabuf_put_u8(buf, dev_capab); /* Device Capabilities */
70 : 3698 : wpabuf_put_u8(buf, group_capab); /* Group Capabilities */
71 : 3698 : wpa_printf(MSG_DEBUG, "P2P: * Capability dev=%02x group=%02x",
72 : : dev_capab, group_capab);
73 : 3698 : }
74 : :
75 : :
76 : 178 : void p2p_buf_add_go_intent(struct wpabuf *buf, u8 go_intent)
77 : : {
78 : : /* Group Owner Intent */
79 : 178 : wpabuf_put_u8(buf, P2P_ATTR_GROUP_OWNER_INTENT);
80 : 178 : wpabuf_put_le16(buf, 1);
81 : 178 : wpabuf_put_u8(buf, go_intent);
82 : 178 : wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u Tie breaker %u",
83 : : go_intent >> 1, go_intent & 0x01);
84 : 178 : }
85 : :
86 : :
87 : 1460 : void p2p_buf_add_listen_channel(struct wpabuf *buf, const char *country,
88 : : u8 reg_class, u8 channel)
89 : : {
90 : : /* Listen Channel */
91 : 1460 : wpabuf_put_u8(buf, P2P_ATTR_LISTEN_CHANNEL);
92 : 1460 : wpabuf_put_le16(buf, 5);
93 : 1460 : wpabuf_put_data(buf, country, 3);
94 : 1460 : wpabuf_put_u8(buf, reg_class); /* Regulatory Class */
95 : 1460 : wpabuf_put_u8(buf, channel); /* Channel Number */
96 : 1460 : wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Regulatory Class %u "
97 : : "Channel %u", reg_class, channel);
98 : 1460 : }
99 : :
100 : :
101 : 216 : void p2p_buf_add_operating_channel(struct wpabuf *buf, const char *country,
102 : : u8 reg_class, u8 channel)
103 : : {
104 : : /* Operating Channel */
105 : 216 : wpabuf_put_u8(buf, P2P_ATTR_OPERATING_CHANNEL);
106 : 216 : wpabuf_put_le16(buf, 5);
107 : 216 : wpabuf_put_data(buf, country, 3);
108 : 216 : wpabuf_put_u8(buf, reg_class); /* Regulatory Class */
109 : 216 : wpabuf_put_u8(buf, channel); /* Channel Number */
110 : 216 : wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: Regulatory Class %u "
111 : : "Channel %u", reg_class, channel);
112 : 216 : }
113 : :
114 : :
115 : 247 : void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country,
116 : : struct p2p_channels *chan)
117 : : {
118 : : u8 *len;
119 : : size_t i;
120 : :
121 : : /* Channel List */
122 : 247 : wpabuf_put_u8(buf, P2P_ATTR_CHANNEL_LIST);
123 : 247 : len = wpabuf_put(buf, 2); /* IE length to be filled */
124 : 247 : wpabuf_put_data(buf, country, 3); /* Country String */
125 : :
126 [ + + ]: 500 : for (i = 0; i < chan->reg_classes; i++) {
127 : 253 : struct p2p_reg_class *c = &chan->reg_class[i];
128 : 253 : wpabuf_put_u8(buf, c->reg_class);
129 : 253 : wpabuf_put_u8(buf, c->channels);
130 : 253 : wpabuf_put_data(buf, c->channel, c->channels);
131 : : }
132 : :
133 : : /* Update attribute length */
134 : 247 : WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
135 : 247 : wpa_hexdump(MSG_DEBUG, "P2P: * Channel List",
136 : 247 : len + 2, (u8 *) wpabuf_put(buf, 0) - len - 2);
137 : 247 : }
138 : :
139 : :
140 : 146 : void p2p_buf_add_status(struct wpabuf *buf, u8 status)
141 : : {
142 : : /* Status */
143 : 146 : wpabuf_put_u8(buf, P2P_ATTR_STATUS);
144 : 146 : wpabuf_put_le16(buf, 1);
145 : 146 : wpabuf_put_u8(buf, status);
146 : 146 : wpa_printf(MSG_DEBUG, "P2P: * Status: %d", status);
147 : 146 : }
148 : :
149 : :
150 : 2135 : void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p,
151 : : struct p2p_device *peer)
152 : : {
153 : : u8 *len;
154 : : u16 methods;
155 : : size_t nlen, i;
156 : :
157 : : /* P2P Device Info */
158 : 2135 : wpabuf_put_u8(buf, P2P_ATTR_DEVICE_INFO);
159 : 2135 : len = wpabuf_put(buf, 2); /* IE length to be filled */
160 : :
161 : : /* P2P Device address */
162 : 2135 : wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
163 : :
164 : : /* Config Methods */
165 : 2135 : methods = 0;
166 [ + + ][ + + ]: 2135 : if (peer && peer->wps_method != WPS_NOT_READY) {
167 [ + + ]: 322 : if (peer->wps_method == WPS_PBC)
168 : 22 : methods |= WPS_CONFIG_PUSHBUTTON;
169 [ + + ][ + + ]: 139 : else if (peer->wps_method == WPS_PIN_DISPLAY ||
170 : 88 : peer->wps_method == WPS_PIN_KEYPAD)
171 : 127 : methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
172 [ + - ]: 1974 : } else if (p2p->cfg->config_methods) {
173 : 1974 : methods |= p2p->cfg->config_methods &
174 : : (WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_DISPLAY |
175 : : WPS_CONFIG_KEYPAD);
176 : : } else {
177 : 0 : methods |= WPS_CONFIG_PUSHBUTTON;
178 : 0 : methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
179 : : }
180 : 2135 : wpabuf_put_be16(buf, methods);
181 : :
182 : : /* Primary Device Type */
183 : 2135 : wpabuf_put_data(buf, p2p->cfg->pri_dev_type,
184 : : sizeof(p2p->cfg->pri_dev_type));
185 : :
186 : : /* Number of Secondary Device Types */
187 : 2135 : wpabuf_put_u8(buf, p2p->cfg->num_sec_dev_types);
188 : :
189 : : /* Secondary Device Type List */
190 [ + + ]: 2169 : for (i = 0; i < p2p->cfg->num_sec_dev_types; i++)
191 : 34 : wpabuf_put_data(buf, p2p->cfg->sec_dev_type[i],
192 : : WPS_DEV_TYPE_LEN);
193 : :
194 : : /* Device Name */
195 [ + + ]: 2135 : nlen = p2p->cfg->dev_name ? os_strlen(p2p->cfg->dev_name) : 0;
196 : 2135 : wpabuf_put_be16(buf, ATTR_DEV_NAME);
197 : 2135 : wpabuf_put_be16(buf, nlen);
198 : 2135 : wpabuf_put_data(buf, p2p->cfg->dev_name, nlen);
199 : :
200 : : /* Update attribute length */
201 : 2135 : WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
202 : 2135 : wpa_printf(MSG_DEBUG, "P2P: * Device Info");
203 : 2135 : }
204 : :
205 : :
206 : 182 : void p2p_buf_add_device_id(struct wpabuf *buf, const u8 *dev_addr)
207 : : {
208 : : /* P2P Device ID */
209 : 182 : wpabuf_put_u8(buf, P2P_ATTR_DEVICE_ID);
210 : 182 : wpabuf_put_le16(buf, ETH_ALEN);
211 : 182 : wpabuf_put_data(buf, dev_addr, ETH_ALEN);
212 : 182 : wpa_printf(MSG_DEBUG, "P2P: * Device ID: " MACSTR, MAC2STR(dev_addr));
213 : 182 : }
214 : :
215 : :
216 : 217 : void p2p_buf_add_config_timeout(struct wpabuf *buf, u8 go_timeout,
217 : : u8 client_timeout)
218 : : {
219 : : /* Configuration Timeout */
220 : 217 : wpabuf_put_u8(buf, P2P_ATTR_CONFIGURATION_TIMEOUT);
221 : 217 : wpabuf_put_le16(buf, 2);
222 : 217 : wpabuf_put_u8(buf, go_timeout);
223 : 217 : wpabuf_put_u8(buf, client_timeout);
224 : 217 : wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout: GO %d (*10ms) "
225 : : "client %d (*10ms)", go_timeout, client_timeout);
226 : 217 : }
227 : :
228 : :
229 : 178 : void p2p_buf_add_intended_addr(struct wpabuf *buf, const u8 *interface_addr)
230 : : {
231 : : /* Intended P2P Interface Address */
232 : 178 : wpabuf_put_u8(buf, P2P_ATTR_INTENDED_INTERFACE_ADDR);
233 : 178 : wpabuf_put_le16(buf, ETH_ALEN);
234 : 178 : wpabuf_put_data(buf, interface_addr, ETH_ALEN);
235 : 178 : wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address " MACSTR,
236 : 1068 : MAC2STR(interface_addr));
237 : 178 : }
238 : :
239 : :
240 : 14 : void p2p_buf_add_group_bssid(struct wpabuf *buf, const u8 *bssid)
241 : : {
242 : : /* P2P Group BSSID */
243 : 14 : wpabuf_put_u8(buf, P2P_ATTR_GROUP_BSSID);
244 : 14 : wpabuf_put_le16(buf, ETH_ALEN);
245 : 14 : wpabuf_put_data(buf, bssid, ETH_ALEN);
246 : 14 : wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID " MACSTR,
247 : 84 : MAC2STR(bssid));
248 : 14 : }
249 : :
250 : :
251 : 94 : 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 : 94 : wpabuf_put_u8(buf, P2P_ATTR_GROUP_ID);
256 : 94 : wpabuf_put_le16(buf, ETH_ALEN + ssid_len);
257 : 94 : wpabuf_put_data(buf, dev_addr, ETH_ALEN);
258 : 94 : wpabuf_put_data(buf, ssid, ssid_len);
259 : 94 : wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID " MACSTR,
260 : 564 : MAC2STR(dev_addr));
261 : 94 : wpa_hexdump_ascii(MSG_DEBUG, "P2P: P2P Group ID SSID", ssid, ssid_len);
262 : 94 : }
263 : :
264 : :
265 : 14 : void p2p_buf_add_invitation_flags(struct wpabuf *buf, u8 flags)
266 : : {
267 : : /* Invitation Flags */
268 : 14 : wpabuf_put_u8(buf, P2P_ATTR_INVITATION_FLAGS);
269 : 14 : wpabuf_put_le16(buf, 1);
270 : 14 : wpabuf_put_u8(buf, flags);
271 : 14 : wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x", flags);
272 : 14 : }
273 : :
274 : :
275 : 4 : static void p2p_buf_add_noa_desc(struct wpabuf *buf, struct p2p_noa_desc *desc)
276 : : {
277 [ + + ]: 4 : if (desc == NULL)
278 : 4 : return;
279 : :
280 : 1 : wpabuf_put_u8(buf, desc->count_type);
281 : 1 : wpabuf_put_le32(buf, desc->duration);
282 : 1 : wpabuf_put_le32(buf, desc->interval);
283 : 1 : wpabuf_put_le32(buf, desc->start_time);
284 : : }
285 : :
286 : :
287 : 2 : 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 : 2 : wpabuf_put_u8(buf, P2P_ATTR_NOTICE_OF_ABSENCE);
292 [ + + ][ - + ]: 2 : wpabuf_put_le16(buf, 2 + (desc1 ? 13 : 0) + (desc2 ? 13 : 0));
293 : 2 : wpabuf_put_u8(buf, noa_index);
294 [ - + ]: 2 : wpabuf_put_u8(buf, (opp_ps ? 0x80 : 0) | (ctwindow & 0x7f));
295 : 2 : p2p_buf_add_noa_desc(buf, desc1);
296 : 2 : p2p_buf_add_noa_desc(buf, desc2);
297 : 2 : wpa_printf(MSG_DEBUG, "P2P: * Notice of Absence");
298 : 2 : }
299 : :
300 : :
301 : 0 : void p2p_buf_add_ext_listen_timing(struct wpabuf *buf, u16 period,
302 : : u16 interval)
303 : : {
304 : : /* Extended Listen Timing */
305 : 0 : wpabuf_put_u8(buf, P2P_ATTR_EXT_LISTEN_TIMING);
306 : 0 : wpabuf_put_le16(buf, 4);
307 : 0 : wpabuf_put_le16(buf, period);
308 : 0 : wpabuf_put_le16(buf, interval);
309 : 0 : wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing (period %u msec "
310 : : "interval %u msec)", period, interval);
311 : 0 : }
312 : :
313 : :
314 : 0 : void p2p_buf_add_p2p_interface(struct wpabuf *buf, struct p2p_data *p2p)
315 : : {
316 : : /* P2P Interface */
317 : 0 : wpabuf_put_u8(buf, P2P_ATTR_INTERFACE);
318 : 0 : wpabuf_put_le16(buf, ETH_ALEN + 1 + ETH_ALEN);
319 : : /* P2P Device address */
320 : 0 : 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 : 0 : wpabuf_put_u8(buf, 1);
327 : 0 : wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
328 : 0 : }
329 : :
330 : :
331 : 21 : 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 : 21 : wpabuf_put_u8(buf, P2P_ATTR_OOB_GO_NEG_CHANNEL);
337 : 21 : wpabuf_put_le16(buf, 6);
338 : 21 : wpabuf_put_data(buf, country, 3);
339 : 21 : wpabuf_put_u8(buf, oper_class); /* Operating Class */
340 : 21 : wpabuf_put_u8(buf, channel); /* Channel Number */
341 : 21 : wpabuf_put_u8(buf, (u8) role); /* Role indication */
342 : 21 : wpa_printf(MSG_DEBUG, "P2P: * OOB GO Negotiation Channel: Operating "
343 : : "Class %u Channel %u Role %d",
344 : : oper_class, channel, role);
345 : 21 : }
346 : :
347 : :
348 : 5540 : static int p2p_add_wps_string(struct wpabuf *buf, enum wps_attribute attr,
349 : : const char *val)
350 : : {
351 : : size_t len;
352 : :
353 [ + + ]: 5540 : len = val ? os_strlen(val) : 0;
354 [ - + ]: 5540 : if (wpabuf_tailroom(buf) < 4 + len)
355 : 0 : return -1;
356 : 5540 : wpabuf_put_be16(buf, attr);
357 : : #ifndef CONFIG_WPS_STRICT
358 [ + + ]: 5540 : if (len == 0) {
359 : : /*
360 : : * Some deployed WPS implementations fail to parse zeor-length
361 : : * attributes. As a workaround, send a space character if the
362 : : * device attribute string is empty.
363 : : */
364 [ - + ]: 4471 : if (wpabuf_tailroom(buf) < 3)
365 : 0 : return -1;
366 : 4471 : wpabuf_put_be16(buf, 1);
367 : 4471 : wpabuf_put_u8(buf, ' ');
368 : 4471 : return 0;
369 : : }
370 : : #endif /* CONFIG_WPS_STRICT */
371 : 1069 : wpabuf_put_be16(buf, len);
372 [ + - ]: 1069 : if (val)
373 : 1069 : wpabuf_put_data(buf, val, len);
374 : 5540 : return 0;
375 : : }
376 : :
377 : :
378 : 1288 : int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
379 : : int all_attr)
380 : : {
381 : : u8 *len;
382 : : int i;
383 : :
384 [ - + ]: 1288 : if (wpabuf_tailroom(buf) < 6)
385 : 0 : return -1;
386 : 1288 : wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
387 : 1288 : len = wpabuf_put(buf, 1);
388 : 1288 : wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
389 : :
390 [ - + ]: 1288 : if (wps_build_version(buf) < 0)
391 : 0 : return -1;
392 : :
393 [ + + ]: 1288 : if (all_attr) {
394 [ - + ]: 1108 : if (wpabuf_tailroom(buf) < 5)
395 : 0 : return -1;
396 : 1108 : wpabuf_put_be16(buf, ATTR_WPS_STATE);
397 : 1108 : wpabuf_put_be16(buf, 1);
398 : 1108 : wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED);
399 : : }
400 : :
401 [ + + ]: 1288 : if (pw_id >= 0) {
402 [ - + ]: 240 : if (wpabuf_tailroom(buf) < 6)
403 : 0 : return -1;
404 : : /* Device Password ID */
405 : 240 : wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID);
406 : 240 : wpabuf_put_be16(buf, 2);
407 : 240 : wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d",
408 : : pw_id);
409 : 240 : wpabuf_put_be16(buf, pw_id);
410 : : }
411 : :
412 [ + + ]: 1288 : if (all_attr) {
413 [ - + ]: 1108 : if (wpabuf_tailroom(buf) < 5)
414 : 0 : return -1;
415 : 1108 : wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE);
416 : 1108 : wpabuf_put_be16(buf, 1);
417 : 1108 : wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO);
418 : :
419 [ + - + - ]: 2216 : if (wps_build_uuid_e(buf, p2p->cfg->uuid) < 0 ||
420 : 1108 : p2p_add_wps_string(buf, ATTR_MANUFACTURER,
421 [ + - ]: 1108 : p2p->cfg->manufacturer) < 0 ||
422 : 1108 : p2p_add_wps_string(buf, ATTR_MODEL_NAME,
423 [ + - ]: 1108 : p2p->cfg->model_name) < 0 ||
424 : 1108 : p2p_add_wps_string(buf, ATTR_MODEL_NUMBER,
425 [ - + ]: 1108 : p2p->cfg->model_number) < 0 ||
426 : 1108 : p2p_add_wps_string(buf, ATTR_SERIAL_NUMBER,
427 : 1108 : p2p->cfg->serial_number) < 0)
428 : 0 : return -1;
429 : :
430 [ - + ]: 1108 : if (wpabuf_tailroom(buf) < 4 + WPS_DEV_TYPE_LEN)
431 : 0 : return -1;
432 : 1108 : wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE);
433 : 1108 : wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN);
434 : 1108 : wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN);
435 : :
436 [ - + ]: 1108 : if (p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name)
437 : : < 0)
438 : 0 : return -1;
439 : :
440 [ - + ]: 1108 : if (wpabuf_tailroom(buf) < 6)
441 : 0 : return -1;
442 : 1108 : wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
443 : 1108 : wpabuf_put_be16(buf, 2);
444 : 1108 : wpabuf_put_be16(buf, p2p->cfg->config_methods);
445 : : }
446 : :
447 [ - + ]: 1288 : if (wps_build_wfa_ext(buf, 0, NULL, 0) < 0)
448 : 0 : return -1;
449 : :
450 [ + + ][ + + ]: 1288 : if (all_attr && p2p->cfg->num_sec_dev_types) {
451 [ - + ]: 20 : if (wpabuf_tailroom(buf) <
452 : 20 : 4 + WPS_DEV_TYPE_LEN * p2p->cfg->num_sec_dev_types)
453 : 0 : return -1;
454 : 20 : wpabuf_put_be16(buf, ATTR_SECONDARY_DEV_TYPE_LIST);
455 : 20 : wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN *
456 : 20 : p2p->cfg->num_sec_dev_types);
457 : 20 : wpabuf_put_data(buf, p2p->cfg->sec_dev_type,
458 : : WPS_DEV_TYPE_LEN *
459 : 20 : p2p->cfg->num_sec_dev_types);
460 : : }
461 : :
462 : : /* Add the WPS vendor extensions */
463 [ + - ]: 1288 : for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
464 [ + - ]: 1288 : if (p2p->wps_vendor_ext[i] == NULL)
465 : 1288 : break;
466 [ # # ]: 0 : if (wpabuf_tailroom(buf) <
467 : 0 : 4 + wpabuf_len(p2p->wps_vendor_ext[i]))
468 : 0 : continue;
469 : 0 : wpabuf_put_be16(buf, ATTR_VENDOR_EXT);
470 : 0 : wpabuf_put_be16(buf, wpabuf_len(p2p->wps_vendor_ext[i]));
471 : 0 : wpabuf_put_buf(buf, p2p->wps_vendor_ext[i]);
472 : : }
473 : :
474 : 1288 : p2p_buf_update_ie_hdr(buf, len);
475 : :
476 : 1288 : return 0;
477 : : }
|