Coverage Report

Created: 2026-03-19 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/hostap/src/p2p/p2p_parse.c
Line
Count
Source
1
/*
2
 * P2P - IE parser
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 "wps/wps_i.h"
15
#include "p2p_i.h"
16
17
18
void p2p_copy_filter_devname(char *dst, size_t dst_len,
19
           const void *src, size_t src_len)
20
1.79k
{
21
1.79k
  size_t i;
22
23
1.79k
  if (src_len >= dst_len)
24
0
    src_len = dst_len - 1;
25
1.79k
  os_memcpy(dst, src, src_len);
26
1.79k
  dst[src_len] = '\0';
27
14.1k
  for (i = 0; i < src_len; i++) {
28
13.0k
    if (dst[i] == '\0')
29
659
      break;
30
12.3k
    if (is_ctrl_char(dst[i]))
31
2.56k
      dst[i] = '_';
32
12.3k
  }
33
1.79k
}
34
35
36
static int p2p_parse_attribute(u8 id, const u8 *data, u16 len,
37
             struct p2p_message *msg)
38
20.5k
{
39
20.5k
  const u8 *pos;
40
20.5k
  u16 nlen;
41
20.5k
  char devtype[WPS_DEV_TYPE_BUFSIZE];
42
43
20.5k
  switch (id) {
44
481
  case P2P_ATTR_CAPABILITY:
45
481
    if (len < 2) {
46
14
      wpa_printf(MSG_DEBUG, "P2P: Too short Capability "
47
14
           "attribute (length %d)", len);
48
14
      return -1;
49
14
    }
50
467
    msg->capability = data;
51
467
    wpa_printf(MSG_DEBUG, "P2P: * Device Capability %02x "
52
467
         "Group Capability %02x",
53
467
         data[0], data[1]);
54
467
    break;
55
3.50k
  case P2P_ATTR_DEVICE_ID:
56
3.50k
    if (len < ETH_ALEN) {
57
15
      wpa_printf(MSG_DEBUG, "P2P: Too short Device ID "
58
15
           "attribute (length %d)", len);
59
15
      return -1;
60
15
    }
61
3.48k
    msg->device_id = data;
62
3.48k
    wpa_printf(MSG_DEBUG, "P2P: * Device ID " MACSTR,
63
3.48k
         MAC2STR(msg->device_id));
64
3.48k
    break;
65
251
  case P2P_ATTR_GROUP_OWNER_INTENT:
66
251
    if (len < 1) {
67
9
      wpa_printf(MSG_DEBUG, "P2P: Too short GO Intent "
68
9
           "attribute (length %d)", len);
69
9
      return -1;
70
9
    }
71
242
    msg->go_intent = data;
72
242
    wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u "
73
242
         "Tie breaker %u", data[0] >> 1, data[0] & 0x01);
74
242
    break;
75
867
  case P2P_ATTR_STATUS:
76
867
    if (len < 1) {
77
78
      wpa_printf(MSG_DEBUG, "P2P: Too short Status "
78
78
           "attribute (length %d)", len);
79
78
      return -1;
80
78
    }
81
789
    msg->status = data;
82
789
    wpa_printf(MSG_DEBUG, "P2P: * Status: %d", data[0]);
83
789
    break;
84
1.78k
  case P2P_ATTR_LISTEN_CHANNEL:
85
1.78k
    if (len == 0) {
86
196
      wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: Ignore "
87
196
           "null channel");
88
196
      break;
89
196
    }
90
1.58k
    if (len < 5) {
91
12
      wpa_printf(MSG_DEBUG, "P2P: Too short Listen Channel "
92
12
           "attribute (length %d)", len);
93
12
      return -1;
94
12
    }
95
1.57k
    msg->listen_channel = data;
96
1.57k
    if (has_ctrl_char(data, 2)) {
97
620
      wpa_printf(MSG_DEBUG,
98
620
           "P2P: * Listen Channel: Country(binary) %02x %02x (0x%02x) Regulatory Class %d Channel Number %d",
99
620
           data[0], data[1], data[2], data[3], data[4]);
100
620
      break;
101
620
    }
102
953
    wpa_printf(MSG_DEBUG, "P2P: * Listen Channel: "
103
953
         "Country %c%c(0x%02x) Regulatory "
104
953
         "Class %d Channel Number %d", data[0], data[1],
105
953
         data[2], data[3], data[4]);
106
953
    break;
107
1.23k
  case P2P_ATTR_OPERATING_CHANNEL:
108
1.23k
    if (len == 0) {
109
242
      wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: "
110
242
           "Ignore null channel");
111
242
      break;
112
242
    }
113
992
    if (len < 5) {
114
10
      wpa_printf(MSG_DEBUG, "P2P: Too short Operating "
115
10
           "Channel attribute (length %d)", len);
116
10
      return -1;
117
10
    }
118
982
    msg->operating_channel = data;
119
982
    if (has_ctrl_char(data, 2)) {
120
552
      wpa_printf(MSG_DEBUG,
121
552
           "P2P: * Operating Channel: Country(binary) %02x %02x (0x%02x) Regulatory Class %d Channel Number %d",
122
552
           data[0], data[1], data[2], data[3], data[4]);
123
552
      break;
124
552
    }
125
430
    wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: "
126
430
         "Country %c%c(0x%02x) Regulatory "
127
430
         "Class %d Channel Number %d", data[0], data[1],
128
430
         data[2], data[3], data[4]);
129
430
    break;
130
1.19k
  case P2P_ATTR_CHANNEL_LIST:
131
1.19k
    if (len < 3) {
132
8
      wpa_printf(MSG_DEBUG, "P2P: Too short Channel List "
133
8
           "attribute (length %d)", len);
134
8
      return -1;
135
8
    }
136
1.18k
    msg->channel_list = data;
137
1.18k
    msg->channel_list_len = len;
138
1.18k
    if (has_ctrl_char(data, 2)) {
139
769
      wpa_printf(MSG_DEBUG,
140
769
           "P2P: * Channel List: Country String (binary) %02x %02x (0x%02x)",
141
769
           data[0], data[1], data[2]);
142
769
    } else {
143
415
      wpa_printf(MSG_DEBUG,
144
415
           "P2P: * Channel List: Country String '%c%c(0x%02x)'",
145
415
           data[0], data[1], data[2]);
146
415
    }
147
1.18k
    wpa_hexdump(MSG_MSGDUMP, "P2P: Channel List",
148
1.18k
          msg->channel_list, msg->channel_list_len);
149
1.18k
    break;
150
551
  case P2P_ATTR_GROUP_INFO:
151
551
    msg->group_info = data;
152
551
    msg->group_info_len = len;
153
551
    wpa_printf(MSG_DEBUG, "P2P: * Group Info");
154
551
    break;
155
1.83k
  case P2P_ATTR_DEVICE_INFO:
156
1.83k
    if (len < ETH_ALEN + 2 + 8 + 1) {
157
18
      wpa_printf(MSG_DEBUG, "P2P: Too short Device Info "
158
18
           "attribute (length %d)", len);
159
18
      return -1;
160
18
    }
161
1.81k
    msg->p2p_device_info = data;
162
1.81k
    msg->p2p_device_info_len = len;
163
1.81k
    pos = data;
164
1.81k
    msg->p2p_device_addr = pos;
165
1.81k
    pos += ETH_ALEN;
166
1.81k
    msg->config_methods = WPA_GET_BE16(pos);
167
1.81k
    pos += 2;
168
1.81k
    msg->pri_dev_type = pos;
169
1.81k
    pos += 8;
170
1.81k
    msg->num_sec_dev_types = *pos++;
171
1.81k
    if (msg->num_sec_dev_types * 8 > data + len - pos) {
172
36
      wpa_printf(MSG_DEBUG, "P2P: Device Info underflow");
173
36
      return -1;
174
36
    }
175
1.77k
    pos += msg->num_sec_dev_types * 8;
176
1.77k
    if (data + len - pos < 4) {
177
10
      wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name "
178
10
           "length %d", (int) (data + len - pos));
179
10
      return -1;
180
10
    }
181
1.76k
    if (WPA_GET_BE16(pos) != ATTR_DEV_NAME) {
182
66
      wpa_hexdump(MSG_DEBUG, "P2P: Unexpected Device Name "
183
66
            "header", pos, 4);
184
66
      return -1;
185
66
    }
186
1.70k
    pos += 2;
187
1.70k
    nlen = WPA_GET_BE16(pos);
188
1.70k
    pos += 2;
189
1.70k
    if (nlen > data + len - pos || nlen > WPS_DEV_NAME_MAX_LEN) {
190
46
      wpa_printf(MSG_DEBUG, "P2P: Invalid Device Name "
191
46
           "length %u (buf len %d)", nlen,
192
46
           (int) (data + len - pos));
193
46
      return -1;
194
46
    }
195
1.65k
    p2p_copy_filter_devname(msg->device_name,
196
1.65k
          sizeof(msg->device_name), pos, nlen);
197
1.65k
    wpa_printf(MSG_DEBUG, "P2P: * Device Info: addr " MACSTR
198
1.65k
         " primary device type %s device name '%s' "
199
1.65k
         "config methods 0x%x",
200
1.65k
         MAC2STR(msg->p2p_device_addr),
201
1.65k
         wps_dev_type_bin2str(msg->pri_dev_type, devtype,
202
1.65k
            sizeof(devtype)),
203
1.65k
         msg->device_name, msg->config_methods);
204
1.65k
    break;
205
236
  case P2P_ATTR_CONFIGURATION_TIMEOUT:
206
236
    if (len < 2) {
207
8
      wpa_printf(MSG_DEBUG, "P2P: Too short Configuration "
208
8
           "Timeout attribute (length %d)", len);
209
8
      return -1;
210
8
    }
211
228
    msg->config_timeout = data;
212
228
    wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout");
213
228
    break;
214
326
  case P2P_ATTR_INTENDED_INTERFACE_ADDR:
215
326
    if (len < ETH_ALEN) {
216
10
      wpa_printf(MSG_DEBUG, "P2P: Too short Intended P2P "
217
10
           "Interface Address attribute (length %d)",
218
10
           len);
219
10
      return -1;
220
10
    }
221
316
    msg->intended_addr = data;
222
316
    wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address: "
223
316
         MACSTR, MAC2STR(msg->intended_addr));
224
316
    break;
225
243
  case P2P_ATTR_GROUP_BSSID:
226
243
    if (len < ETH_ALEN) {
227
17
      wpa_printf(MSG_DEBUG, "P2P: Too short P2P Group BSSID "
228
17
           "attribute (length %d)", len);
229
17
      return -1;
230
17
    }
231
226
    msg->group_bssid = data;
232
226
    wpa_printf(MSG_DEBUG, "P2P: * P2P Group BSSID: " MACSTR,
233
226
         MAC2STR(msg->group_bssid));
234
226
    break;
235
960
  case P2P_ATTR_GROUP_ID:
236
960
    if (len < ETH_ALEN || len > ETH_ALEN + SSID_MAX_LEN) {
237
46
      wpa_printf(MSG_DEBUG, "P2P: Invalid P2P Group ID "
238
46
           "attribute length %d", len);
239
46
      return -1;
240
46
    }
241
914
    msg->group_id = data;
242
914
    msg->group_id_len = len;
243
914
    wpa_printf(MSG_DEBUG, "P2P: * P2P Group ID: Device Address "
244
914
         MACSTR, MAC2STR(msg->group_id));
245
914
    wpa_hexdump_ascii(MSG_DEBUG, "P2P: * P2P Group ID: SSID",
246
914
          msg->group_id + ETH_ALEN,
247
914
          msg->group_id_len - ETH_ALEN);
248
914
    break;
249
240
  case P2P_ATTR_INVITATION_FLAGS:
250
240
    if (len < 1) {
251
9
      wpa_printf(MSG_DEBUG, "P2P: Too short Invitation "
252
9
           "Flag attribute (length %d)", len);
253
9
      return -1;
254
9
    }
255
231
    msg->invitation_flags = data;
256
231
    wpa_printf(MSG_DEBUG, "P2P: * Invitation Flags: bitmap 0x%x",
257
231
         data[0]);
258
231
    break;
259
247
  case P2P_ATTR_MANAGEABILITY:
260
247
    if (len < 1) {
261
6
      wpa_printf(MSG_DEBUG, "P2P: Too short Manageability "
262
6
           "attribute (length %d)", len);
263
6
      return -1;
264
6
    }
265
241
    msg->manageability = data;
266
241
    wpa_printf(MSG_DEBUG, "P2P: * Manageability: bitmap 0x%x",
267
241
         data[0]);
268
241
    break;
269
287
  case P2P_ATTR_NOTICE_OF_ABSENCE:
270
287
    if (len < 2) {
271
8
      wpa_printf(MSG_DEBUG, "P2P: Too short Notice of "
272
8
           "Absence attribute (length %d)", len);
273
8
      return -1;
274
8
    }
275
279
    msg->noa = data;
276
279
    msg->noa_len = len;
277
279
    wpa_printf(MSG_DEBUG, "P2P: * Notice of Absence");
278
279
    break;
279
227
  case P2P_ATTR_EXT_LISTEN_TIMING:
280
227
    if (len < 4) {
281
11
      wpa_printf(MSG_DEBUG, "P2P: Too short Extended Listen "
282
11
           "Timing attribute (length %d)", len);
283
11
      return -1;
284
11
    }
285
216
    msg->ext_listen_timing = data;
286
216
    wpa_printf(MSG_DEBUG, "P2P: * Extended Listen Timing "
287
216
         "(period %u msec  interval %u msec)",
288
216
         WPA_GET_LE16(msg->ext_listen_timing),
289
216
         WPA_GET_LE16(msg->ext_listen_timing + 2));
290
216
    break;
291
222
  case P2P_ATTR_MINOR_REASON_CODE:
292
222
    if (len < 1) {
293
8
      wpa_printf(MSG_DEBUG, "P2P: Too short Minor Reason "
294
8
           "Code attribute (length %d)", len);
295
8
      return -1;
296
8
    }
297
214
    msg->minor_reason_code = data;
298
214
    wpa_printf(MSG_DEBUG, "P2P: * Minor Reason Code: %u",
299
214
         *msg->minor_reason_code);
300
214
    break;
301
215
  case P2P_ATTR_OOB_GO_NEG_CHANNEL:
302
215
    if (len < 6) {
303
12
      wpa_printf(MSG_DEBUG, "P2P: Too short OOB GO Neg "
304
12
           "Channel attribute (length %d)", len);
305
12
      return -1;
306
12
    }
307
203
    msg->oob_go_neg_channel = data;
308
203
    wpa_printf(MSG_DEBUG, "P2P: * OOB GO Neg Channel: "
309
203
         "Country %c%c(0x%02x) Operating Class %d "
310
203
         "Channel Number %d Role %d",
311
203
         data[0], data[1], data[2], data[3], data[4],
312
203
         data[5]);
313
203
    break;
314
220
  case P2P_ATTR_SERVICE_HASH:
315
220
    if (len < P2PS_HASH_LEN) {
316
9
      wpa_printf(MSG_DEBUG,
317
9
           "P2P: Too short Service Hash (length %u)",
318
9
           len);
319
9
      return -1;
320
9
    }
321
211
    msg->service_hash_count = len / P2PS_HASH_LEN;
322
211
    msg->service_hash = data;
323
211
    wpa_hexdump(MSG_DEBUG, "P2P: * Service Hash(s)", data, len);
324
211
    break;
325
202
  case P2P_ATTR_SESSION_INFORMATION_DATA:
326
202
    msg->session_info = data;
327
202
    msg->session_info_len = len;
328
202
    wpa_printf(MSG_DEBUG, "P2P: * Service Instance: %u bytes - %p",
329
202
         len, data);
330
202
    break;
331
420
  case P2P_ATTR_CONNECTION_CAPABILITY:
332
420
    if (len < 1) {
333
8
      wpa_printf(MSG_DEBUG,
334
8
           "P2P: Too short Connection Capability (length %u)",
335
8
           len);
336
8
      return -1;
337
8
    }
338
412
    msg->conn_cap = data;
339
412
    wpa_printf(MSG_DEBUG, "P2P: * Connection Capability: 0x%x",
340
412
         *msg->conn_cap);
341
412
    break;
342
411
  case P2P_ATTR_ADVERTISEMENT_ID:
343
411
    if (len < 10) {
344
15
      wpa_printf(MSG_DEBUG,
345
15
           "P2P: Too short Advertisement ID (length %u)",
346
15
           len);
347
15
      return -1;
348
15
    }
349
396
    msg->adv_id = data;
350
396
    msg->adv_mac = &data[sizeof(u32)];
351
396
    wpa_printf(MSG_DEBUG, "P2P: * Advertisement ID %x",
352
396
         WPA_GET_LE32(data));
353
396
    break;
354
662
  case P2P_ATTR_ADVERTISED_SERVICE:
355
662
    if (len < 8) {
356
6
      wpa_printf(MSG_DEBUG,
357
6
           "P2P: Too short Service Instance (length %u)",
358
6
           len);
359
6
      return -1;
360
6
    }
361
656
    msg->adv_service_instance = data;
362
656
    msg->adv_service_instance_len = len;
363
656
    if (len <= 255 + 8) {
364
454
      char str[256];
365
454
      u8 namelen;
366
367
454
      namelen = data[6];
368
454
      if (namelen > len - 7)
369
224
        break;
370
230
      os_memcpy(str, &data[7], namelen);
371
230
      str[namelen] = '\0';
372
230
      wpa_printf(MSG_DEBUG, "P2P: * Service Instance: %x-%s",
373
230
           WPA_GET_LE32(data), str);
374
230
    } else {
375
202
      wpa_printf(MSG_DEBUG, "P2P: * Service Instance: %p",
376
202
           data);
377
202
    }
378
432
    break;
379
432
  case P2P_ATTR_SESSION_ID:
380
421
    if (len < sizeof(u32) + ETH_ALEN) {
381
14
      wpa_printf(MSG_DEBUG,
382
14
           "P2P: Too short Session ID Info (length %u)",
383
14
           len);
384
14
      return -1;
385
14
    }
386
407
    msg->session_id = data;
387
407
    msg->session_mac = &data[sizeof(u32)];
388
407
    wpa_printf(MSG_DEBUG, "P2P: * Session ID: %x " MACSTR,
389
407
         WPA_GET_LE32(data), MAC2STR(msg->session_mac));
390
407
    break;
391
410
  case P2P_ATTR_FEATURE_CAPABILITY:
392
410
    if (!len) {
393
6
      wpa_printf(MSG_DEBUG,
394
6
           "P2P: Too short Feature Capability (length %u)",
395
6
           len);
396
6
      return -1;
397
6
    }
398
404
    msg->feature_cap = data;
399
404
    msg->feature_cap_len = len;
400
404
    wpa_printf(MSG_DEBUG, "P2P: * Feature Cap (length=%u)", len);
401
404
    break;
402
787
  case P2P_ATTR_PERSISTENT_GROUP:
403
787
  {
404
787
    if (len < ETH_ALEN || len > ETH_ALEN + SSID_MAX_LEN) {
405
46
      wpa_printf(MSG_DEBUG,
406
46
           "P2P: Invalid Persistent Group Info (length %u)",
407
46
           len);
408
46
      return -1;
409
46
    }
410
411
741
    msg->persistent_dev = data;
412
741
    msg->persistent_ssid_len = len - ETH_ALEN;
413
741
    msg->persistent_ssid = &data[ETH_ALEN];
414
741
    wpa_printf(MSG_DEBUG, "P2P: * Persistent Group: " MACSTR " %s",
415
741
         MAC2STR(msg->persistent_dev),
416
741
         wpa_ssid_txt(msg->persistent_ssid,
417
741
          msg->persistent_ssid_len));
418
741
    break;
419
787
  }
420
331
  case P2P_ATTR_CAPABILITY_EXTENSION:
421
331
    if (len < 2) {
422
10
      wpa_printf(MSG_DEBUG, "P2P: Too short PCEA (length %d)",
423
10
           len);
424
10
      return -1;
425
10
    }
426
321
    msg->pcea_info = data;
427
321
    msg->pcea_info_len = len;
428
321
    wpa_printf(MSG_DEBUG, "P2P: * PCEA (length=%u)", len);
429
321
    break;
430
540
  case P2P_ATTR_PAIRING_AND_BOOTSTRAPPING:
431
540
    if (len < 1) {
432
6
      wpa_printf(MSG_DEBUG, "P2P: Too short PBMA (length %d)",
433
6
           len);
434
6
      return -1;
435
6
    }
436
534
    msg->pbma_info = data;
437
534
    msg->pbma_info_len = len;
438
534
    wpa_printf(MSG_DEBUG, "P2P: * PBMA (length=%u)", len);
439
534
    break;
440
230
  case P2P_ATTR_ACTION_FRAME_WRAPPER:
441
230
    if (len < 2) {
442
10
      wpa_printf(MSG_DEBUG,
443
10
           "P2P: Too short Action Frame Wrapper attribute (length %d)",
444
10
           len);
445
10
      return -1;
446
10
    }
447
220
    msg->action_frame_wrapper = data;
448
220
    msg->action_frame_wrapper_len = len;
449
220
    wpa_printf(MSG_DEBUG, "P2P: * Action frame wrapper (length=%u)",
450
220
         len);
451
220
    break;
452
294
  case P2P_ATTR_DEVICE_IDENTITY_RESOLUTION:
453
294
    if (len < 1) {
454
8
      wpa_printf(MSG_DEBUG, "P2P: Too short DIRA (length %d)",
455
8
           len);
456
8
      return -1;
457
8
    }
458
286
    msg->dira = data;
459
286
    msg->dira_len = len;
460
286
    wpa_printf(MSG_DEBUG, "P2P: * DIRA (length=%u)", len);
461
286
    break;
462
230
  case P2P_ATTR_WLAN_AP_INFORMATION:
463
    /* One or more AP Info fields (each being 12 octets) is required
464
     * to be included. */
465
230
    if (len < 12) {
466
16
      wpa_printf(MSG_DEBUG,
467
16
           "P2P: Too short WLAN AP info (length %d)",
468
16
           len);
469
16
      return -1;
470
16
    }
471
214
    msg->wlan_ap_info = data;
472
214
    msg->wlan_ap_info_len = len;
473
214
    break;
474
448
  default:
475
448
    wpa_printf(MSG_DEBUG, "P2P: Skipped unknown attribute %d "
476
448
         "(length %d)", id, len);
477
448
    break;
478
20.5k
  }
479
480
19.8k
  return 0;
481
20.5k
}
482
483
484
/**
485
 * p2p_parse_p2p_ie - Parse P2P IE
486
 * @buf: Concatenated P2P IE(s) payload
487
 * @msg: Buffer for returning parsed attributes
488
 * Returns: 0 on success, -1 on failure
489
 *
490
 * Note: Caller is responsible for clearing the msg data structure before
491
 * calling this function.
492
 */
493
int p2p_parse_p2p_ie(const struct wpabuf *buf, struct p2p_message *msg)
494
6.73k
{
495
6.73k
  const u8 *pos = wpabuf_head_u8(buf);
496
6.73k
  const u8 *end = pos + wpabuf_len(buf);
497
498
6.73k
  wpa_printf(MSG_DEBUG, "P2P: Parsing P2P IE");
499
500
26.6k
  while (pos < end) {
501
20.9k
    u16 attr_len;
502
20.9k
    u8 id;
503
504
20.9k
    if (end - pos < 3) {
505
152
      wpa_printf(MSG_DEBUG, "P2P: Invalid P2P attribute");
506
152
      return -1;
507
152
    }
508
20.8k
    id = *pos++;
509
20.8k
    attr_len = WPA_GET_LE16(pos);
510
20.8k
    pos += 2;
511
20.8k
    wpa_printf(MSG_DEBUG, "P2P: Attribute %d length %u",
512
20.8k
         id, attr_len);
513
20.8k
    if (attr_len > end - pos) {
514
308
      wpa_printf(MSG_DEBUG, "P2P: Attribute underflow "
515
308
           "(len=%u left=%d)",
516
308
           attr_len, (int) (end - pos));
517
308
      wpa_hexdump(MSG_MSGDUMP, "P2P: Data", pos, end - pos);
518
308
      return -1;
519
308
    }
520
20.5k
    if (p2p_parse_attribute(id, pos, attr_len, msg))
521
611
      return -1;
522
19.8k
    pos += attr_len;
523
19.8k
  }
524
525
5.66k
  return 0;
526
6.73k
}
527
528
529
static int p2p_parse_wps_ie(const struct wpabuf *buf, struct p2p_message *msg)
530
4.24k
{
531
4.24k
  struct wps_parse_attr attr;
532
4.24k
  int i;
533
534
4.24k
  wpa_printf(MSG_DEBUG, "P2P: Parsing WPS IE");
535
4.24k
  if (wps_parse_msg(buf, &attr))
536
1.59k
    return -1;
537
2.64k
  if (attr.dev_name && attr.dev_name_len < sizeof(msg->device_name) &&
538
66
      !msg->device_name[0])
539
66
    os_memcpy(msg->device_name, attr.dev_name, attr.dev_name_len);
540
2.64k
  if (attr.config_methods) {
541
282
    msg->wps_config_methods =
542
282
      WPA_GET_BE16(attr.config_methods);
543
282
    wpa_printf(MSG_DEBUG, "P2P: Config Methods (WPS): 0x%x",
544
282
         msg->wps_config_methods);
545
282
  }
546
2.64k
  if (attr.dev_password_id) {
547
24
    msg->dev_password_id = WPA_GET_BE16(attr.dev_password_id);
548
24
    wpa_printf(MSG_DEBUG, "P2P: Device Password ID: %d",
549
24
         msg->dev_password_id);
550
24
    msg->dev_password_id_present = 1;
551
24
  }
552
2.64k
  if (attr.primary_dev_type) {
553
40
    char devtype[WPS_DEV_TYPE_BUFSIZE];
554
40
    msg->wps_pri_dev_type = attr.primary_dev_type;
555
40
    wpa_printf(MSG_DEBUG, "P2P: Primary Device Type (WPS): %s",
556
40
         wps_dev_type_bin2str(msg->wps_pri_dev_type, devtype,
557
40
            sizeof(devtype)));
558
40
  }
559
2.64k
  if (attr.sec_dev_type_list) {
560
44
    msg->wps_sec_dev_type_list = attr.sec_dev_type_list;
561
44
    msg->wps_sec_dev_type_list_len = attr.sec_dev_type_list_len;
562
44
  }
563
564
29.0k
  for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
565
26.4k
    msg->wps_vendor_ext[i] = attr.vendor_ext[i];
566
26.4k
    msg->wps_vendor_ext_len[i] = attr.vendor_ext_len[i];
567
26.4k
  }
568
569
2.64k
  msg->manufacturer = attr.manufacturer;
570
2.64k
  msg->manufacturer_len = attr.manufacturer_len;
571
2.64k
  msg->model_name = attr.model_name;
572
2.64k
  msg->model_name_len = attr.model_name_len;
573
2.64k
  msg->model_number = attr.model_number;
574
2.64k
  msg->model_number_len = attr.model_number_len;
575
2.64k
  msg->serial_number = attr.serial_number;
576
2.64k
  msg->serial_number_len = attr.serial_number_len;
577
578
2.64k
  msg->oob_dev_password = attr.oob_dev_password;
579
2.64k
  msg->oob_dev_password_len = attr.oob_dev_password_len;
580
581
2.64k
  return 0;
582
4.24k
}
583
584
585
/**
586
 * p2p_parse_ies - Parse P2P message IEs (both WPS and P2P IE)
587
 * @data: IEs from the message
588
 * @len: Length of data buffer in octets
589
 * @msg: Buffer for returning parsed attributes
590
 * Returns: 0 on success, -1 on failure
591
 *
592
 * Note: Caller is responsible for clearing the msg data structure before
593
 * calling this function.
594
 *
595
 * Note: Caller must free temporary memory allocations by calling
596
 * p2p_parse_free() when the parsed data is not needed anymore.
597
 */
598
int p2p_parse_ies(const u8 *data, size_t len, struct p2p_message *msg)
599
16.0k
{
600
16.0k
  struct ieee802_11_elems elems;
601
602
16.0k
  if (ieee802_11_parse_elems(data, len, &elems, 0) == ParseFailed)
603
2.09k
    return -1;
604
605
13.9k
  if (elems.ds_params)
606
629
    msg->ds_params = elems.ds_params;
607
13.9k
  if (elems.ssid)
608
3.94k
    msg->ssid = elems.ssid - 2;
609
610
13.9k
  msg->wps_attributes = ieee802_11_vendor_ie_concat(data, len,
611
13.9k
                WPS_DEV_OUI_WFA);
612
13.9k
  if (msg->wps_attributes &&
613
4.24k
      p2p_parse_wps_ie(msg->wps_attributes, msg)) {
614
1.59k
    p2p_parse_free(msg);
615
1.59k
    return -1;
616
1.59k
  }
617
618
12.3k
  msg->p2p_attributes = ieee802_11_vendor_ie_concat(data, len,
619
12.3k
                P2P_IE_VENDOR_TYPE);
620
12.3k
  if (msg->p2p_attributes &&
621
6.21k
      p2p_parse_p2p_ie(msg->p2p_attributes, msg)) {
622
953
    wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data");
623
953
    if (msg->p2p_attributes)
624
953
      wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data",
625
953
          msg->p2p_attributes);
626
953
    p2p_parse_free(msg);
627
953
    return -1;
628
953
  }
629
630
11.4k
  msg->p2p2_attributes = ieee802_11_vendor_ie_concat(data, len,
631
11.4k
                 P2P2_IE_VENDOR_TYPE);
632
11.4k
  if (msg->p2p2_attributes &&
633
525
      p2p_parse_p2p_ie(msg->p2p2_attributes, msg)) {
634
118
    wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P2 IE data");
635
118
    if (msg->p2p2_attributes)
636
118
      wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P2 IE data",
637
118
          msg->p2p2_attributes);
638
118
    p2p_parse_free(msg);
639
118
    return -1;
640
118
  }
641
642
11.3k
#ifdef CONFIG_WIFI_DISPLAY
643
11.3k
  if (elems.wfd) {
644
737
    msg->wfd_subelems = ieee802_11_vendor_ie_concat(
645
737
      data, len, WFD_IE_VENDOR_TYPE);
646
737
  }
647
11.3k
#endif /* CONFIG_WIFI_DISPLAY */
648
649
11.3k
  msg->pref_freq_list = elems.pref_freq_list;
650
11.3k
  msg->pref_freq_list_len = elems.pref_freq_list_len;
651
652
11.3k
  return 0;
653
11.4k
}
654
655
656
/**
657
 * p2p_parse - Parse a P2P Action frame contents
658
 * @data: Action frame payload after Category and Code fields
659
 * @len: Length of data buffer in octets
660
 * @msg: Buffer for returning parsed attributes
661
 * Returns: 0 on success, -1 on failure
662
 *
663
 * Note: Caller must free temporary memory allocations by calling
664
 * p2p_parse_free() when the parsed data is not needed anymore.
665
 */
666
int p2p_parse(const u8 *data, size_t len, struct p2p_message *msg)
667
2.48k
{
668
2.48k
  os_memset(msg, 0, sizeof(*msg));
669
2.48k
  wpa_printf(MSG_DEBUG, "P2P: Parsing the received message");
670
2.48k
  if (len < 1) {
671
6
    wpa_printf(MSG_DEBUG, "P2P: No Dialog Token in the message");
672
6
    return -1;
673
6
  }
674
2.47k
  msg->dialog_token = data[0];
675
2.47k
  wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", msg->dialog_token);
676
677
2.47k
  return p2p_parse_ies(data + 1, len - 1, msg);
678
2.48k
}
679
680
681
int p2p_parse_ies_separate(const u8 *wsc, size_t wsc_len, const u8 *p2p,
682
         size_t p2p_len, struct p2p_message *msg)
683
0
{
684
0
  os_memset(msg, 0, sizeof(*msg));
685
686
0
  msg->wps_attributes = wpabuf_alloc_copy(wsc, wsc_len);
687
0
  if (msg->wps_attributes &&
688
0
      p2p_parse_wps_ie(msg->wps_attributes, msg)) {
689
0
    p2p_parse_free(msg);
690
0
    return -1;
691
0
  }
692
693
0
  msg->p2p_attributes = wpabuf_alloc_copy(p2p, p2p_len);
694
0
  if (msg->p2p_attributes &&
695
0
      p2p_parse_p2p_ie(msg->p2p_attributes, msg)) {
696
0
    wpa_printf(MSG_DEBUG, "P2P: Failed to parse P2P IE data");
697
0
    if (msg->p2p_attributes)
698
0
      wpa_hexdump_buf(MSG_MSGDUMP, "P2P: P2P IE data",
699
0
          msg->p2p_attributes);
700
0
    p2p_parse_free(msg);
701
0
    return -1;
702
0
  }
703
704
0
  return 0;
705
0
}
706
707
708
/**
709
 * p2p_parse_free - Free temporary data from P2P parsing
710
 * @msg: Parsed attributes
711
 */
712
void p2p_parse_free(struct p2p_message *msg)
713
18.2k
{
714
18.2k
  wpabuf_free(msg->p2p_attributes);
715
18.2k
  msg->p2p_attributes = NULL;
716
18.2k
  wpabuf_free(msg->p2p2_attributes);
717
18.2k
  msg->p2p2_attributes = NULL;
718
18.2k
  wpabuf_free(msg->wps_attributes);
719
18.2k
  msg->wps_attributes = NULL;
720
18.2k
#ifdef CONFIG_WIFI_DISPLAY
721
18.2k
  wpabuf_free(msg->wfd_subelems);
722
18.2k
  msg->wfd_subelems = NULL;
723
18.2k
#endif /* CONFIG_WIFI_DISPLAY */
724
18.2k
}
725
726
727
int p2p_group_info_parse(const u8 *gi, size_t gi_len,
728
       struct p2p_group_info *info)
729
137
{
730
137
  const u8 *g, *gend;
731
732
137
  os_memset(info, 0, sizeof(*info));
733
137
  if (gi == NULL)
734
0
    return 0;
735
736
137
  g = gi;
737
137
  gend = gi + gi_len;
738
310
  while (g < gend) {
739
242
    struct p2p_client_info *cli;
740
242
    const u8 *cend;
741
242
    u16 count;
742
242
    u8 len;
743
744
242
    cli = &info->client[info->num_clients];
745
242
    len = *g++;
746
242
    if (len > gend - g || len < 2 * ETH_ALEN + 1 + 2 + 8 + 1)
747
22
      return -1; /* invalid data */
748
220
    cend = g + len;
749
    /* g at start of P2P Client Info Descriptor */
750
220
    cli->p2p_device_addr = g;
751
220
    g += ETH_ALEN;
752
220
    cli->p2p_interface_addr = g;
753
220
    g += ETH_ALEN;
754
220
    cli->dev_capab = *g++;
755
756
220
    cli->config_methods = WPA_GET_BE16(g);
757
220
    g += 2;
758
220
    cli->pri_dev_type = g;
759
220
    g += 8;
760
761
    /* g at Number of Secondary Device Types */
762
220
    len = *g++;
763
220
    if (8 * len > cend - g)
764
18
      return -1; /* invalid data */
765
202
    cli->num_sec_dev_types = len;
766
202
    cli->sec_dev_types = g;
767
202
    g += 8 * len;
768
769
    /* g at Device Name in WPS TLV format */
770
202
    if (cend - g < 2 + 2)
771
3
      return -1; /* invalid data */
772
199
    if (WPA_GET_BE16(g) != ATTR_DEV_NAME)
773
21
      return -1; /* invalid Device Name TLV */
774
178
    g += 2;
775
178
    count = WPA_GET_BE16(g);
776
178
    g += 2;
777
178
    if (count > cend - g)
778
5
      return -1; /* invalid Device Name TLV */
779
173
    if (count >= WPS_DEV_NAME_MAX_LEN)
780
6
      count = WPS_DEV_NAME_MAX_LEN;
781
173
    cli->dev_name = (const char *) g;
782
173
    cli->dev_name_len = count;
783
784
173
    g = cend;
785
786
173
    info->num_clients++;
787
173
    if (info->num_clients == P2P_MAX_GROUP_ENTRIES)
788
0
      return -1;
789
173
  }
790
791
68
  return 0;
792
137
}
793
794
795
static int p2p_group_info_text(const u8 *gi, size_t gi_len, char *buf,
796
             char *end)
797
0
{
798
0
  char *pos = buf;
799
0
  int ret;
800
0
  struct p2p_group_info info;
801
0
  unsigned int i;
802
803
0
  if (p2p_group_info_parse(gi, gi_len, &info) < 0)
804
0
    return 0;
805
806
0
  for (i = 0; i < info.num_clients; i++) {
807
0
    struct p2p_client_info *cli;
808
0
    char name[WPS_DEV_NAME_MAX_LEN + 1];
809
0
    char devtype[WPS_DEV_TYPE_BUFSIZE];
810
0
    u8 s;
811
0
    int count;
812
813
0
    cli = &info.client[i];
814
0
    ret = os_snprintf(pos, end - pos, "p2p_group_client: "
815
0
          "dev=" MACSTR " iface=" MACSTR,
816
0
          MAC2STR(cli->p2p_device_addr),
817
0
          MAC2STR(cli->p2p_interface_addr));
818
0
    if (os_snprintf_error(end - pos, ret))
819
0
      return pos - buf;
820
0
    pos += ret;
821
822
0
    ret = os_snprintf(pos, end - pos,
823
0
          " dev_capab=0x%x config_methods=0x%x "
824
0
          "dev_type=%s",
825
0
          cli->dev_capab, cli->config_methods,
826
0
          wps_dev_type_bin2str(cli->pri_dev_type,
827
0
                   devtype,
828
0
                   sizeof(devtype)));
829
0
    if (os_snprintf_error(end - pos, ret))
830
0
      return pos - buf;
831
0
    pos += ret;
832
833
0
    for (s = 0; s < cli->num_sec_dev_types; s++) {
834
0
      ret = os_snprintf(pos, end - pos, " dev_type=%s",
835
0
            wps_dev_type_bin2str(
836
0
              &cli->sec_dev_types[s * 8],
837
0
              devtype, sizeof(devtype)));
838
0
      if (os_snprintf_error(end - pos, ret))
839
0
        return pos - buf;
840
0
      pos += ret;
841
0
    }
842
843
0
    os_memcpy(name, cli->dev_name, cli->dev_name_len);
844
0
    name[cli->dev_name_len] = '\0';
845
0
    count = (int) cli->dev_name_len - 1;
846
0
    while (count >= 0) {
847
0
      if (is_ctrl_char(name[count]))
848
0
        name[count] = '_';
849
0
      count--;
850
0
    }
851
852
0
    ret = os_snprintf(pos, end - pos, " dev_name='%s'\n", name);
853
0
    if (os_snprintf_error(end - pos, ret))
854
0
      return pos - buf;
855
0
    pos += ret;
856
0
  }
857
858
0
  return pos - buf;
859
0
}
860
861
862
/**
863
 * p2p_attr_text - Build text format description of P2P IE attributes
864
 * @data: P2P IE contents
865
 * @buf: Buffer for returning text
866
 * @end: Pointer to the end of the buf area
867
 * Returns: Number of octets written to the buffer or -1 on faikure
868
 *
869
 * This function can be used to parse P2P IE contents into text format
870
 * field=value lines.
871
 */
872
int p2p_attr_text(struct wpabuf *data, char *buf, char *end)
873
0
{
874
0
  struct p2p_message msg;
875
0
  char *pos = buf;
876
0
  int ret;
877
878
0
  os_memset(&msg, 0, sizeof(msg));
879
0
  if (p2p_parse_p2p_ie(data, &msg))
880
0
    return -1;
881
882
0
  if (msg.capability) {
883
0
    ret = os_snprintf(pos, end - pos,
884
0
          "p2p_dev_capab=0x%x\n"
885
0
          "p2p_group_capab=0x%x\n",
886
0
          msg.capability[0], msg.capability[1]);
887
0
    if (os_snprintf_error(end - pos, ret))
888
0
      return pos - buf;
889
0
    pos += ret;
890
0
  }
891
892
0
  if (msg.pri_dev_type) {
893
0
    char devtype[WPS_DEV_TYPE_BUFSIZE];
894
0
    ret = os_snprintf(pos, end - pos,
895
0
          "p2p_primary_device_type=%s\n",
896
0
          wps_dev_type_bin2str(msg.pri_dev_type,
897
0
                   devtype,
898
0
                   sizeof(devtype)));
899
0
    if (os_snprintf_error(end - pos, ret))
900
0
      return pos - buf;
901
0
    pos += ret;
902
0
  }
903
904
0
  ret = os_snprintf(pos, end - pos, "p2p_device_name=%s\n",
905
0
        msg.device_name);
906
0
  if (os_snprintf_error(end - pos, ret))
907
0
    return pos - buf;
908
0
  pos += ret;
909
910
0
  if (msg.p2p_device_addr) {
911
0
    ret = os_snprintf(pos, end - pos, "p2p_device_addr=" MACSTR
912
0
          "\n",
913
0
          MAC2STR(msg.p2p_device_addr));
914
0
    if (os_snprintf_error(end - pos, ret))
915
0
      return pos - buf;
916
0
    pos += ret;
917
0
  }
918
919
0
  ret = os_snprintf(pos, end - pos, "p2p_config_methods=0x%x\n",
920
0
        msg.config_methods);
921
0
  if (os_snprintf_error(end - pos, ret))
922
0
    return pos - buf;
923
0
  pos += ret;
924
925
0
  ret = p2p_group_info_text(msg.group_info, msg.group_info_len,
926
0
          pos, end);
927
0
  if (ret < 0)
928
0
    return pos - buf;
929
0
  pos += ret;
930
931
0
  return pos - buf;
932
0
}
933
934
935
int p2p_get_cross_connect_disallowed(const struct wpabuf *p2p_ie)
936
0
{
937
0
  struct p2p_message msg;
938
939
0
  os_memset(&msg, 0, sizeof(msg));
940
0
  if (p2p_parse_p2p_ie(p2p_ie, &msg))
941
0
    return 0;
942
943
0
  if (!msg.manageability)
944
0
    return 0;
945
946
0
  return !(msg.manageability[0] & P2P_MAN_CROSS_CONNECTION_PERMITTED);
947
0
}
948
949
950
u8 p2p_get_group_capab(const struct wpabuf *p2p_ie)
951
0
{
952
0
  struct p2p_message msg;
953
954
0
  os_memset(&msg, 0, sizeof(msg));
955
0
  if (p2p_parse_p2p_ie(p2p_ie, &msg))
956
0
    return 0;
957
958
0
  if (!msg.capability)
959
0
    return 0;
960
961
0
  return msg.capability[1];
962
0
}
963
964
965
const u8 * p2p_get_go_dev_addr(const struct wpabuf *p2p_ie)
966
0
{
967
0
  struct p2p_message msg;
968
969
0
  os_memset(&msg, 0, sizeof(msg));
970
0
  if (p2p_parse_p2p_ie(p2p_ie, &msg))
971
0
    return NULL;
972
973
0
  if (msg.p2p_device_addr)
974
0
    return msg.p2p_device_addr;
975
0
  if (msg.device_id)
976
0
    return msg.device_id;
977
978
0
  return NULL;
979
0
}