Coverage Report

Created: 2025-08-29 06:25

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