Coverage Report

Created: 2025-04-24 06:18

/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.64k
{
33
1.64k
  wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC);
34
1.64k
  wpabuf_put_u8(buf, WLAN_PA_VENDOR_SPECIFIC);
35
1.64k
  wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
36
37
1.64k
  wpabuf_put_u8(buf, subtype); /* OUI Subtype */
38
1.64k
  wpabuf_put_u8(buf, dialog_token);
39
1.64k
  wpa_printf(MSG_DEBUG, "P2P: * Dialog Token: %d", dialog_token);
40
1.64k
}
41
42
43
u8 * p2p_buf_add_ie_hdr(struct wpabuf *buf)
44
1.46k
{
45
1.46k
  u8 *len;
46
47
  /* P2P IE header */
48
1.46k
  wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
49
1.46k
  len = wpabuf_put(buf, 1); /* IE length to be filled */
50
1.46k
  wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
51
1.46k
  wpa_printf(MSG_DEBUG, "P2P: * P2P IE header");
52
1.46k
  return len;
53
1.46k
}
54
55
56
void p2p_buf_update_ie_hdr(struct wpabuf *buf, u8 *len)
57
2.21k
{
58
  /* Update P2P/P2P2 IE Length */
59
2.21k
  *len = (u8 *) wpabuf_put(buf, 0) - len - 1;
60
2.21k
}
61
62
63
u8 * p2p_buf_add_p2p2_ie_hdr(struct wpabuf *buf)
64
79
{
65
79
  u8 *len;
66
67
  /* P2P2 IE header */
68
79
  wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
69
79
  len = wpabuf_put(buf, 1); /* IE length to be filled */
70
79
  wpabuf_put_be32(buf, P2P2_IE_VENDOR_TYPE);
71
79
  wpa_printf(MSG_DEBUG, "P2P: * P2P2 IE header");
72
79
  return len;
73
79
}
74
75
76
void p2p_buf_add_capability(struct wpabuf *buf, u8 dev_capab, u8 group_capab)
77
59
{
78
  /* P2P Capability */
79
59
  wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY);
80
59
  wpabuf_put_le16(buf, 2);
81
59
  wpabuf_put_u8(buf, dev_capab); /* Device Capabilities */
82
59
  wpabuf_put_u8(buf, group_capab); /* Group Capabilities */
83
59
  wpa_printf(MSG_DEBUG, "P2P: * Capability dev=%02x group=%02x",
84
59
       dev_capab, group_capab);
85
59
}
86
87
88
void p2p_buf_add_go_intent(struct wpabuf *buf, u8 go_intent)
89
57
{
90
  /* Group Owner Intent */
91
57
  wpabuf_put_u8(buf, P2P_ATTR_GROUP_OWNER_INTENT);
92
57
  wpabuf_put_le16(buf, 1);
93
57
  wpabuf_put_u8(buf, go_intent);
94
57
  wpa_printf(MSG_DEBUG, "P2P: * GO Intent: Intent %u Tie breaker %u",
95
57
       go_intent >> 1, go_intent & 0x01);
96
57
}
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
57
{
116
  /* Operating Channel */
117
57
  wpabuf_put_u8(buf, P2P_ATTR_OPERATING_CHANNEL);
118
57
  wpabuf_put_le16(buf, 5);
119
57
  wpabuf_put_data(buf, country, 3);
120
57
  wpabuf_put_u8(buf, reg_class); /* Regulatory Class */
121
57
  wpabuf_put_u8(buf, channel); /* Channel Number */
122
57
  wpa_printf(MSG_DEBUG, "P2P: * Operating Channel: Regulatory Class %u "
123
57
       "Channel %u", reg_class, channel);
124
57
}
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
57
{
170
57
  u8 *len;
171
57
  size_t i;
172
173
  /* Channel List */
174
57
  wpabuf_put_u8(buf, P2P_ATTR_CHANNEL_LIST);
175
57
  len = wpabuf_put(buf, 2); /* IE length to be filled */
176
57
  wpabuf_put_data(buf, country, 3); /* Country String */
177
178
57
  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
57
  WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
190
57
  wpa_hexdump(MSG_DEBUG, "P2P: * Channel List",
191
57
        len + 2, (u8 *) wpabuf_put(buf, 0) - len - 2);
192
57
}
193
194
195
void p2p_buf_add_status(struct wpabuf *buf, u8 status)
196
1.59k
{
197
  /* Status */
198
1.59k
  wpabuf_put_u8(buf, P2P_ATTR_STATUS);
199
1.59k
  wpabuf_put_le16(buf, 1);
200
1.59k
  wpabuf_put_u8(buf, status);
201
1.59k
  wpa_printf(MSG_DEBUG, "P2P: * Status: %d", status);
202
1.59k
}
203
204
205
void p2p_buf_add_device_info(struct wpabuf *buf, struct p2p_data *p2p,
206
           struct p2p_device *peer)
207
59
{
208
59
  u8 *len;
209
59
  u16 methods;
210
59
  size_t nlen, i;
211
212
  /* P2P Device Info */
213
59
  wpabuf_put_u8(buf, P2P_ATTR_DEVICE_INFO);
214
59
  len = wpabuf_put(buf, 2); /* IE length to be filled */
215
216
  /* P2P Device address */
217
59
  wpabuf_put_data(buf, p2p->cfg->dev_addr, ETH_ALEN);
218
219
  /* Config Methods */
220
59
  methods = 0;
221
59
  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
59
  } 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
59
  } else {
234
59
    methods |= WPS_CONFIG_PUSHBUTTON;
235
59
    methods |= WPS_CONFIG_DISPLAY | WPS_CONFIG_KEYPAD;
236
59
    methods |= WPS_CONFIG_P2PS;
237
59
  }
238
59
  wpabuf_put_be16(buf, methods);
239
240
  /* Primary Device Type */
241
59
  wpabuf_put_data(buf, p2p->cfg->pri_dev_type,
242
59
      sizeof(p2p->cfg->pri_dev_type));
243
244
  /* Number of Secondary Device Types */
245
59
  wpabuf_put_u8(buf, p2p->cfg->num_sec_dev_types);
246
247
  /* Secondary Device Type List */
248
59
  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
59
  nlen = p2p->cfg->dev_name ? os_strlen(p2p->cfg->dev_name) : 0;
254
59
  wpabuf_put_be16(buf, ATTR_DEV_NAME);
255
59
  wpabuf_put_be16(buf, nlen);
256
59
  wpabuf_put_data(buf, p2p->cfg->dev_name, nlen);
257
258
  /* Update attribute length */
259
59
  WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
260
59
  wpa_printf(MSG_DEBUG, "P2P: * Device Info");
261
59
}
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
906
{
277
  /* Configuration Timeout */
278
906
  wpabuf_put_u8(buf, P2P_ATTR_CONFIGURATION_TIMEOUT);
279
906
  wpabuf_put_le16(buf, 2);
280
906
  wpabuf_put_u8(buf, go_timeout);
281
906
  wpabuf_put_u8(buf, client_timeout);
282
906
  wpa_printf(MSG_DEBUG, "P2P: * Configuration Timeout: GO %d (*10ms)  "
283
906
       "client %d (*10ms)", go_timeout, client_timeout);
284
906
}
285
286
287
void p2p_buf_add_intended_addr(struct wpabuf *buf, const u8 *interface_addr)
288
57
{
289
  /* Intended P2P Interface Address */
290
57
  wpabuf_put_u8(buf, P2P_ATTR_INTENDED_INTERFACE_ADDR);
291
57
  wpabuf_put_le16(buf, ETH_ALEN);
292
57
  wpabuf_put_data(buf, interface_addr, ETH_ALEN);
293
57
  wpa_printf(MSG_DEBUG, "P2P: * Intended P2P Interface Address " MACSTR,
294
57
       MAC2STR(interface_addr));
295
57
}
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
79
{
741
79
  u8 *len;
742
79
  u16 capability_info = 0;
743
744
  /* P2P Capability Extension */
745
79
  wpabuf_put_u8(buf, P2P_ATTR_CAPABILITY_EXTENSION);
746
  /* Length to be filled */
747
79
  len = wpabuf_put(buf, 2);
748
749
79
  if (!p2p->cfg->p2p_6ghz_disable)
750
79
    capability_info |= P2P_PCEA_6GHZ;
751
752
79
  if (p2p->cfg->reg_info)
753
0
    capability_info |= P2P_PCEA_REG_INFO;
754
755
79
  if (p2p->cfg->dfs_owner)
756
0
    capability_info |= P2P_PCEA_DFS_OWNER;
757
758
79
  if (p2p->cfg->chan_switch_req_enable)
759
0
    capability_info |= P2P_PCEA_CLI_REQ_CS;
760
761
79
  if (p2p->cfg->pairing_config.pairing_capable)
762
0
    capability_info |= P2P_PCEA_PAIRING_CAPABLE;
763
764
79
  if (p2p->cfg->pairing_config.enable_pairing_setup)
765
0
    capability_info |= P2P_PCEA_PAIRING_SETUP_ENABLED;
766
767
79
  if (p2p->cfg->pairing_config.enable_pairing_cache)
768
0
    capability_info |= P2P_PCEA_PMK_CACHING;
769
770
79
  if (p2p->cfg->pairing_config.pasn_type)
771
0
    capability_info |= P2P_PCEA_PASN_TYPE;
772
773
79
  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
79
  capability_info |= (2 - 1) & P2P_PCEA_LEN_MASK;
778
79
  wpabuf_put_le16(buf, capability_info);
779
780
79
  if (capability_info & P2P_PCEA_REG_INFO)
781
0
    wpabuf_put_u8(buf, p2p->cfg->reg_info);
782
783
79
  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
79
  WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
788
789
79
  wpa_printf(MSG_DEBUG, "P2P: * Capability Extension info=0x%x",
790
79
       capability_info);
791
79
}
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
79
{
797
79
  u8 *len;
798
799
  /* P2P Pairing and Bootstrapping methods */
800
79
  wpabuf_put_u8(buf, P2P_ATTR_PAIRING_AND_BOOTSTRAPPING);
801
  /* Length to be filled */
802
79
  len = wpabuf_put(buf, 2);
803
804
79
  if (cookie && cookie_len) {
805
64
    if (comeback_after)
806
64
      wpabuf_put_le16(buf, comeback_after);
807
64
    wpabuf_put_u8(buf, cookie_len);
808
64
    wpabuf_put_data(buf, cookie, cookie_len);
809
64
  }
810
79
  wpabuf_put_le16(buf, bootstrap);
811
812
  /* Update attribute length */
813
79
  WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
814
815
79
  wpa_printf(MSG_DEBUG, "P2P: * Bootstrapping method=0x%x",
816
79
       bootstrap);
817
79
}
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
10
{
849
10
  size_t len;
850
851
10
  len = val ? os_strlen(val) : 0;
852
10
  if (wpabuf_tailroom(buf) < 4 + len)
853
0
    return -1;
854
10
  wpabuf_put_be16(buf, attr);
855
10
#ifndef CONFIG_WPS_STRICT
856
10
  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
10
    if (wpabuf_tailroom(buf) < 3)
863
0
      return -1;
864
10
    wpabuf_put_be16(buf, 1);
865
10
    wpabuf_put_u8(buf, ' ');
866
10
    return 0;
867
10
  }
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
10
}
874
875
876
int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id,
877
         int all_attr)
878
30
{
879
30
  u8 *len;
880
30
  int i;
881
882
30
  if (wpabuf_tailroom(buf) < 6)
883
0
    return -1;
884
30
  wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
885
30
  len = wpabuf_put(buf, 1);
886
30
  wpabuf_put_be32(buf, WPS_DEV_OUI_WFA);
887
888
30
  if (wps_build_version(buf) < 0)
889
0
    return -1;
890
891
30
  if (all_attr) {
892
2
    if (wpabuf_tailroom(buf) < 5)
893
0
      return -1;
894
2
    wpabuf_put_be16(buf, ATTR_WPS_STATE);
895
2
    wpabuf_put_be16(buf, 1);
896
2
    wpabuf_put_u8(buf, WPS_STATE_NOT_CONFIGURED);
897
2
  }
898
899
30
  if (pw_id >= 0) {
900
28
    if (wpabuf_tailroom(buf) < 6)
901
0
      return -1;
902
    /* Device Password ID */
903
28
    wpabuf_put_be16(buf, ATTR_DEV_PASSWORD_ID);
904
28
    wpabuf_put_be16(buf, 2);
905
28
    wpa_printf(MSG_DEBUG, "P2P: WPS IE Device Password ID: %d",
906
28
         pw_id);
907
28
    wpabuf_put_be16(buf, pw_id);
908
28
  }
909
910
30
  if (all_attr) {
911
2
    if (wpabuf_tailroom(buf) < 5)
912
0
      return -1;
913
2
    wpabuf_put_be16(buf, ATTR_RESPONSE_TYPE);
914
2
    wpabuf_put_be16(buf, 1);
915
2
    wpabuf_put_u8(buf, WPS_RESP_ENROLLEE_INFO);
916
917
2
    if (wps_build_uuid_e(buf, p2p->cfg->uuid) < 0 ||
918
2
        p2p_add_wps_string(buf, ATTR_MANUFACTURER,
919
2
               p2p->cfg->manufacturer) < 0 ||
920
2
        p2p_add_wps_string(buf, ATTR_MODEL_NAME,
921
2
               p2p->cfg->model_name) < 0 ||
922
2
        p2p_add_wps_string(buf, ATTR_MODEL_NUMBER,
923
2
               p2p->cfg->model_number) < 0 ||
924
2
        p2p_add_wps_string(buf, ATTR_SERIAL_NUMBER,
925
2
               p2p->cfg->serial_number) < 0)
926
0
      return -1;
927
928
2
    if (wpabuf_tailroom(buf) < 4 + WPS_DEV_TYPE_LEN)
929
0
      return -1;
930
2
    wpabuf_put_be16(buf, ATTR_PRIMARY_DEV_TYPE);
931
2
    wpabuf_put_be16(buf, WPS_DEV_TYPE_LEN);
932
2
    wpabuf_put_data(buf, p2p->cfg->pri_dev_type, WPS_DEV_TYPE_LEN);
933
934
2
    if (p2p_add_wps_string(buf, ATTR_DEV_NAME, p2p->cfg->dev_name)
935
2
        < 0)
936
0
      return -1;
937
938
2
    if (wpabuf_tailroom(buf) < 6)
939
0
      return -1;
940
2
    wpabuf_put_be16(buf, ATTR_CONFIG_METHODS);
941
2
    wpabuf_put_be16(buf, 2);
942
2
    wpabuf_put_be16(buf, p2p->cfg->config_methods);
943
2
  }
944
945
30
  if (wps_build_wfa_ext(buf, 0, NULL, 0, 0) < 0)
946
0
    return -1;
947
948
30
  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
30
  for (i = 0; i < P2P_MAX_WPS_VENDOR_EXT; i++) {
962
30
    if (p2p->wps_vendor_ext[i] == NULL)
963
30
      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
30
  p2p_buf_update_ie_hdr(buf, len);
973
974
30
  return 0;
975
30
}
976
977
978
struct wpabuf * p2p_encaps_ie(const struct wpabuf *subelems, u32 ie_type)
979
57
{
980
57
  struct wpabuf *ie;
981
57
  const u8 *pos, *end;
982
57
  size_t len;
983
984
57
  if (!subelems)
985
0
    return NULL;
986
987
57
  len = wpabuf_len(subelems) + 1000;
988
989
57
  ie = wpabuf_alloc(len);
990
57
  if (!ie)
991
0
    return NULL;
992
993
57
  pos = wpabuf_head(subelems);
994
57
  end = pos + wpabuf_len(subelems);
995
996
114
  while (end > pos) {
997
57
    size_t frag_len = end - pos;
998
999
57
    if (frag_len > 251)
1000
0
      frag_len = 251;
1001
57
    wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
1002
57
    wpabuf_put_u8(ie, 4 + frag_len);
1003
57
    wpabuf_put_be32(ie, ie_type);
1004
57
    wpabuf_put_data(ie, pos, frag_len);
1005
57
    pos += frag_len;
1006
57
  }
1007
1008
57
  return ie;
1009
57
}