Coverage Report

Created: 2025-08-26 06:04

/src/hostap/src/p2p/p2p_sd.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Wi-Fi Direct - P2P service discovery
3
 * Copyright (c) 2009, 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/gas.h"
14
#include "p2p_i.h"
15
#include "p2p.h"
16
17
18
#ifdef CONFIG_WIFI_DISPLAY
19
static int wfd_wsd_supported(struct wpabuf *wfd)
20
0
{
21
0
  const u8 *pos, *end;
22
0
  u8 subelem;
23
0
  u16 len;
24
25
0
  if (wfd == NULL)
26
0
    return 0;
27
28
0
  pos = wpabuf_head(wfd);
29
0
  end = pos + wpabuf_len(wfd);
30
31
0
  while (end - pos >= 3) {
32
0
    subelem = *pos++;
33
0
    len = WPA_GET_BE16(pos);
34
0
    pos += 2;
35
0
    if (len > end - pos)
36
0
      break;
37
38
0
    if (subelem == WFD_SUBELEM_DEVICE_INFO && len >= 6) {
39
0
      u16 info = WPA_GET_BE16(pos);
40
0
      return !!(info & 0x0040);
41
0
    }
42
43
0
    pos += len;
44
0
  }
45
46
0
  return 0;
47
0
}
48
#endif /* CONFIG_WIFI_DISPLAY */
49
50
struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p,
51
           struct p2p_device *dev)
52
0
{
53
0
  struct p2p_sd_query *q;
54
0
  int wsd = 0;
55
0
  int count = 0;
56
57
0
  if (!(dev->info.dev_capab & P2P_DEV_CAPAB_SERVICE_DISCOVERY))
58
0
    return NULL; /* peer does not support SD */
59
0
#ifdef CONFIG_WIFI_DISPLAY
60
0
  if (wfd_wsd_supported(dev->info.wfd_subelems))
61
0
    wsd = 1;
62
0
#endif /* CONFIG_WIFI_DISPLAY */
63
64
0
  for (q = p2p->sd_queries; q; q = q->next) {
65
    /* Use WSD only if the peer indicates support or it */
66
0
    if (q->wsd && !wsd)
67
0
      continue;
68
    /* if the query is a broadcast query */
69
0
    if (q->for_all_peers) {
70
      /*
71
       * check if there are any broadcast queries pending for
72
       * this device
73
       */
74
0
      if (dev->sd_pending_bcast_queries <= 0)
75
0
        return NULL;
76
      /* query number that needs to be send to the device */
77
0
      if (count == dev->sd_pending_bcast_queries - 1)
78
0
        goto found;
79
0
      count++;
80
0
    }
81
0
    if (!q->for_all_peers &&
82
0
        ether_addr_equal(q->peer, dev->info.p2p_device_addr))
83
0
      goto found;
84
0
  }
85
86
0
  return NULL;
87
88
0
found:
89
0
  if (dev->sd_reqs > 100) {
90
0
    p2p_dbg(p2p, "Too many SD request attempts to " MACSTR
91
0
      " - skip remaining queries",
92
0
      MAC2STR(dev->info.p2p_device_addr));
93
0
    return NULL;
94
0
  }
95
0
  return q;
96
0
}
97
98
99
static void p2p_decrease_sd_bc_queries(struct p2p_data *p2p, int query_number)
100
0
{
101
0
  struct p2p_device *dev;
102
103
0
  p2p->num_p2p_sd_queries--;
104
0
  dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
105
0
    if (query_number <= dev->sd_pending_bcast_queries - 1) {
106
      /*
107
       * Query not yet sent to the device and it is to be
108
       * removed, so update the pending count.
109
      */
110
0
      dev->sd_pending_bcast_queries--;
111
0
    }
112
0
  }
113
0
}
114
115
116
static int p2p_unlink_sd_query(struct p2p_data *p2p,
117
             struct p2p_sd_query *query)
118
0
{
119
0
  struct p2p_sd_query *q, *prev;
120
0
  int query_number = 0;
121
122
0
  q = p2p->sd_queries;
123
0
  prev = NULL;
124
0
  while (q) {
125
0
    if (q == query) {
126
      /* If the query is a broadcast query, decrease one from
127
       * all the devices */
128
0
      if (query->for_all_peers)
129
0
        p2p_decrease_sd_bc_queries(p2p, query_number);
130
0
      if (prev)
131
0
        prev->next = q->next;
132
0
      else
133
0
        p2p->sd_queries = q->next;
134
0
      if (p2p->sd_query == query)
135
0
        p2p->sd_query = NULL;
136
0
      return 1;
137
0
    }
138
0
    if (q->for_all_peers)
139
0
      query_number++;
140
0
    prev = q;
141
0
    q = q->next;
142
0
  }
143
0
  return 0;
144
0
}
145
146
147
static void p2p_free_sd_query(struct p2p_sd_query *q)
148
0
{
149
0
  if (q == NULL)
150
0
    return;
151
0
  wpabuf_free(q->tlvs);
152
0
  os_free(q);
153
0
}
154
155
156
void p2p_free_sd_queries(struct p2p_data *p2p)
157
6.52k
{
158
6.52k
  struct p2p_sd_query *q, *prev;
159
6.52k
  q = p2p->sd_queries;
160
6.52k
  p2p->sd_queries = NULL;
161
6.52k
  while (q) {
162
0
    prev = q;
163
0
    q = q->next;
164
0
    p2p_free_sd_query(prev);
165
0
  }
166
6.52k
  p2p->num_p2p_sd_queries = 0;
167
6.52k
}
168
169
170
static struct wpabuf * p2p_build_sd_query(u16 update_indic,
171
            struct wpabuf *tlvs)
172
0
{
173
0
  struct wpabuf *buf;
174
0
  u8 *len_pos;
175
176
0
  buf = gas_anqp_build_initial_req(0, 100 + wpabuf_len(tlvs));
177
0
  if (buf == NULL)
178
0
    return NULL;
179
180
  /* ANQP Query Request Frame */
181
0
  len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
182
0
  wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
183
0
  wpabuf_put_le16(buf, update_indic); /* Service Update Indicator */
184
0
  wpabuf_put_buf(buf, tlvs);
185
0
  gas_anqp_set_element_len(buf, len_pos);
186
187
0
  gas_anqp_set_len(buf);
188
189
0
  return buf;
190
0
}
191
192
193
static void p2p_send_gas_comeback_req(struct p2p_data *p2p, const u8 *dst,
194
              u8 dialog_token, int freq)
195
0
{
196
0
  struct wpabuf *req;
197
198
0
  req = gas_build_comeback_req(dialog_token);
199
0
  if (req == NULL)
200
0
    return;
201
202
0
  p2p->pending_action_state = P2P_NO_PENDING_ACTION;
203
0
  if (p2p_send_action(p2p, freq, dst, p2p->cfg->dev_addr, dst,
204
0
          wpabuf_head(req), wpabuf_len(req), 200) < 0)
205
0
    p2p_dbg(p2p, "Failed to send Action frame");
206
207
0
  wpabuf_free(req);
208
0
}
209
210
211
static struct wpabuf * p2p_build_sd_response(u8 dialog_token, u16 status_code,
212
               u16 comeback_delay,
213
               u16 update_indic,
214
               const struct wpabuf *tlvs)
215
0
{
216
0
  struct wpabuf *buf;
217
0
  u8 *len_pos;
218
219
0
  buf = gas_anqp_build_initial_resp(dialog_token, status_code,
220
0
            comeback_delay,
221
0
            100 + (tlvs ? wpabuf_len(tlvs) : 0));
222
0
  if (buf == NULL)
223
0
    return NULL;
224
225
0
  if (tlvs) {
226
    /* ANQP Query Response Frame */
227
0
    len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
228
0
    wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
229
     /* Service Update Indicator */
230
0
    wpabuf_put_le16(buf, update_indic);
231
0
    wpabuf_put_buf(buf, tlvs);
232
0
    gas_anqp_set_element_len(buf, len_pos);
233
0
  }
234
235
0
  gas_anqp_set_len(buf);
236
237
0
  return buf;
238
0
}
239
240
241
static struct wpabuf * p2p_build_gas_comeback_resp(u8 dialog_token,
242
               u16 status_code,
243
               u16 update_indic,
244
               const u8 *data, size_t len,
245
               u8 frag_id, u8 more,
246
               u16 total_len)
247
0
{
248
0
  struct wpabuf *buf;
249
250
0
  buf = gas_anqp_build_comeback_resp(dialog_token, status_code, frag_id,
251
0
             more, 0, 100 + len);
252
0
  if (buf == NULL)
253
0
    return NULL;
254
255
0
  if (frag_id == 0) {
256
    /* ANQP Query Response Frame */
257
0
    wpabuf_put_le16(buf, ANQP_VENDOR_SPECIFIC); /* Info ID */
258
0
    wpabuf_put_le16(buf, 3 + 1 + 2 + total_len);
259
0
    wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
260
    /* Service Update Indicator */
261
0
    wpabuf_put_le16(buf, update_indic);
262
0
  }
263
264
0
  wpabuf_put_data(buf, data, len);
265
0
  gas_anqp_set_len(buf);
266
267
0
  return buf;
268
0
}
269
270
271
int p2p_start_sd(struct p2p_data *p2p, struct p2p_device *dev)
272
0
{
273
0
  struct wpabuf *req;
274
0
  int ret = 0;
275
0
  struct p2p_sd_query *query;
276
0
  int freq;
277
0
  unsigned int wait_time;
278
279
0
  freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq;
280
0
  if (freq <= 0) {
281
0
    p2p_dbg(p2p, "No Listen/Operating frequency known for the peer "
282
0
      MACSTR " to send SD Request",
283
0
      MAC2STR(dev->info.p2p_device_addr));
284
0
    return -1;
285
0
  }
286
287
0
  query = p2p_pending_sd_req(p2p, dev);
288
0
  if (query == NULL)
289
0
    return -1;
290
0
  if (p2p->state == P2P_SEARCH &&
291
0
      ether_addr_equal(p2p->sd_query_no_ack, dev->info.p2p_device_addr)) {
292
0
    p2p_dbg(p2p, "Do not start Service Discovery with " MACSTR
293
0
      " due to it being the first no-ACK peer in this search iteration",
294
0
      MAC2STR(dev->info.p2p_device_addr));
295
0
    return -2;
296
0
  }
297
298
0
  p2p_dbg(p2p, "Start Service Discovery with " MACSTR,
299
0
    MAC2STR(dev->info.p2p_device_addr));
300
301
0
  req = p2p_build_sd_query(p2p->srv_update_indic, query->tlvs);
302
0
  if (req == NULL)
303
0
    return -1;
304
305
0
  dev->sd_reqs++;
306
0
  p2p->sd_peer = dev;
307
0
  p2p->sd_query = query;
308
0
  p2p->pending_action_state = P2P_PENDING_SD;
309
310
0
  wait_time = 5000;
311
0
  if (p2p->cfg->max_listen && wait_time > p2p->cfg->max_listen)
312
0
    wait_time = p2p->cfg->max_listen;
313
0
  if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr,
314
0
          p2p->cfg->dev_addr, dev->info.p2p_device_addr,
315
0
          wpabuf_head(req), wpabuf_len(req), wait_time) < 0) {
316
0
    p2p_dbg(p2p, "Failed to send Action frame");
317
0
    ret = -1;
318
0
  }
319
320
0
  wpabuf_free(req);
321
322
0
  return ret;
323
0
}
324
325
326
void p2p_rx_gas_initial_req(struct p2p_data *p2p, const u8 *sa,
327
          const u8 *data, size_t len, int rx_freq)
328
1
{
329
1
  const u8 *pos = data;
330
1
  const u8 *end = data + len;
331
1
  const u8 *next;
332
1
  u8 dialog_token;
333
1
  u16 slen;
334
1
  int freq;
335
1
  u16 update_indic;
336
337
338
1
  if (p2p->cfg->sd_request == NULL)
339
1
    return;
340
341
0
  if (rx_freq > 0)
342
0
    freq = rx_freq;
343
0
  else
344
0
    freq = p2p_channel_to_freq(p2p->cfg->reg_class,
345
0
             p2p->cfg->channel);
346
0
  if (freq < 0)
347
0
    return;
348
349
0
  if (len < 1 + 2)
350
0
    return;
351
352
0
  dialog_token = *pos++;
353
0
  p2p_dbg(p2p, "GAS Initial Request from " MACSTR
354
0
    " (dialog token %u, freq %d)",
355
0
    MAC2STR(sa), dialog_token, rx_freq);
356
357
0
  if (*pos != WLAN_EID_ADV_PROTO) {
358
0
    p2p_dbg(p2p, "Unexpected IE in GAS Initial Request: %u", *pos);
359
0
    return;
360
0
  }
361
0
  pos++;
362
363
0
  slen = *pos++;
364
0
  if (slen > end - pos || slen < 2) {
365
0
    p2p_dbg(p2p, "Invalid IE in GAS Initial Request");
366
0
    return;
367
0
  }
368
0
  next = pos + slen;
369
0
  pos++; /* skip QueryRespLenLimit and PAME-BI */
370
371
0
  if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
372
0
    p2p_dbg(p2p, "Unsupported GAS advertisement protocol id %u",
373
0
      *pos);
374
0
    return;
375
0
  }
376
377
0
  pos = next;
378
  /* Query Request */
379
0
  if (end - pos < 2)
380
0
    return;
381
0
  slen = WPA_GET_LE16(pos);
382
0
  pos += 2;
383
0
  if (slen > end - pos)
384
0
    return;
385
0
  end = pos + slen;
386
387
  /* ANQP Query Request */
388
0
  if (end - pos < 4)
389
0
    return;
390
0
  if (WPA_GET_LE16(pos) != ANQP_VENDOR_SPECIFIC) {
391
0
    p2p_dbg(p2p, "Unsupported ANQP Info ID %u", WPA_GET_LE16(pos));
392
0
    return;
393
0
  }
394
0
  pos += 2;
395
396
0
  slen = WPA_GET_LE16(pos);
397
0
  pos += 2;
398
0
  if (slen > end - pos || slen < 3 + 1) {
399
0
    p2p_dbg(p2p, "Invalid ANQP Query Request length");
400
0
    return;
401
0
  }
402
403
0
  if (WPA_GET_BE32(pos) != P2P_IE_VENDOR_TYPE) {
404
0
    p2p_dbg(p2p, "Unsupported ANQP vendor OUI-type %08x",
405
0
      WPA_GET_BE32(pos));
406
0
    return;
407
0
  }
408
0
  pos += 4;
409
410
0
  if (end - pos < 2)
411
0
    return;
412
0
  update_indic = WPA_GET_LE16(pos);
413
0
  p2p_dbg(p2p, "Service Update Indicator: %u", update_indic);
414
0
  pos += 2;
415
416
0
  p2p->cfg->sd_request(p2p->cfg->cb_ctx, freq, sa, dialog_token,
417
0
           update_indic, pos, end - pos);
418
  /* the response will be indicated with a call to p2p_sd_response() */
419
0
}
420
421
422
void p2p_sd_response(struct p2p_data *p2p, int freq, const u8 *dst,
423
         u8 dialog_token, const struct wpabuf *resp_tlvs)
424
0
{
425
0
  struct wpabuf *resp;
426
0
  size_t max_len;
427
0
  unsigned int wait_time = 200;
428
429
  /*
430
   * In the 60 GHz, we have a smaller maximum frame length for management
431
   * frames.
432
   */
433
0
  max_len = (freq > 56160) ? 928 : 1400;
434
435
  /* TODO: fix the length limit to match with the maximum frame length */
436
0
  if (wpabuf_len(resp_tlvs) > max_len) {
437
0
    p2p_dbg(p2p, "SD response long enough to require fragmentation");
438
0
    if (p2p->sd_resp) {
439
      /*
440
       * TODO: Could consider storing the fragmented response
441
       * separately for each peer to avoid having to drop old
442
       * one if there is more than one pending SD query.
443
       * Though, that would eat more memory, so there are
444
       * also benefits to just using a single buffer.
445
       */
446
0
      p2p_dbg(p2p, "Drop previous SD response");
447
0
      wpabuf_free(p2p->sd_resp);
448
0
    }
449
0
    p2p->sd_resp = wpabuf_dup(resp_tlvs);
450
0
    if (p2p->sd_resp == NULL) {
451
0
      p2p_err(p2p, "Failed to allocate SD response fragmentation area");
452
0
      return;
453
0
    }
454
0
    os_memcpy(p2p->sd_resp_addr, dst, ETH_ALEN);
455
0
    p2p->sd_resp_dialog_token = dialog_token;
456
0
    p2p->sd_resp_pos = 0;
457
0
    p2p->sd_frag_id = 0;
458
0
    resp = p2p_build_sd_response(dialog_token, WLAN_STATUS_SUCCESS,
459
0
               1, p2p->srv_update_indic, NULL);
460
0
  } else {
461
0
    p2p_dbg(p2p, "SD response fits in initial response");
462
0
    wait_time = 0; /* no more SD frames in the sequence */
463
0
    resp = p2p_build_sd_response(dialog_token,
464
0
               WLAN_STATUS_SUCCESS, 0,
465
0
               p2p->srv_update_indic, resp_tlvs);
466
0
  }
467
0
  if (resp == NULL)
468
0
    return;
469
470
0
  p2p->pending_action_state = P2P_NO_PENDING_ACTION;
471
0
  if (p2p_send_action(p2p, freq, dst, p2p->cfg->dev_addr,
472
0
          p2p->cfg->dev_addr,
473
0
          wpabuf_head(resp), wpabuf_len(resp), wait_time) < 0)
474
0
    p2p_dbg(p2p, "Failed to send Action frame");
475
476
0
  wpabuf_free(resp);
477
0
}
478
479
480
void p2p_rx_gas_initial_resp(struct p2p_data *p2p, const u8 *sa,
481
           const u8 *data, size_t len, int rx_freq)
482
2
{
483
2
  const u8 *pos = data;
484
2
  const u8 *end = data + len;
485
2
  const u8 *next;
486
2
  u8 dialog_token;
487
2
  u16 status_code;
488
2
  u16 comeback_delay;
489
2
  u16 slen;
490
2
  u16 update_indic;
491
492
2
  if ((p2p->state != P2P_SD_DURING_FIND && p2p->state != P2P_SEARCH) ||
493
2
      !p2p->sd_peer ||
494
2
      !ether_addr_equal(sa, p2p->sd_peer->info.p2p_device_addr)) {
495
2
    p2p_dbg(p2p, "Ignore unexpected GAS Initial Response from "
496
2
      MACSTR, MAC2STR(sa));
497
2
    return;
498
2
  }
499
0
  if (p2p->state == P2P_SEARCH) {
500
    /* It is possible for the TX status and RX response events to be
501
     * reordered, so assume the request was ACKed if a response is
502
     * received. */
503
0
    p2p_dbg(p2p,
504
0
      "GAS Initial Request had not yet received TX status - process the response anyway");
505
0
    p2p_sd_query_cb(p2p, 1);
506
0
  }
507
0
  p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
508
0
  p2p_clear_timeout(p2p);
509
510
0
  p2p_dbg(p2p, "Received GAS Initial Response from " MACSTR " (len=%d)",
511
0
    MAC2STR(sa), (int) len);
512
513
0
  if (len < 5 + 2) {
514
0
    p2p_dbg(p2p, "Too short GAS Initial Response frame");
515
0
    return;
516
0
  }
517
518
0
  dialog_token = *pos++;
519
  /* TODO: check dialog_token match */
520
0
  status_code = WPA_GET_LE16(pos);
521
0
  pos += 2;
522
0
  comeback_delay = WPA_GET_LE16(pos);
523
0
  pos += 2;
524
0
  p2p_dbg(p2p, "dialog_token=%u status_code=%u comeback_delay=%u",
525
0
    dialog_token, status_code, comeback_delay);
526
0
  if (status_code) {
527
0
    p2p_dbg(p2p, "Service Discovery failed: status code %u",
528
0
      status_code);
529
0
    return;
530
0
  }
531
532
0
  if (*pos != WLAN_EID_ADV_PROTO) {
533
0
    p2p_dbg(p2p, "Unexpected IE in GAS Initial Response: %u", *pos);
534
0
    return;
535
0
  }
536
0
  pos++;
537
538
0
  slen = *pos++;
539
0
  if (slen > end - pos || slen < 2) {
540
0
    p2p_dbg(p2p, "Invalid IE in GAS Initial Response");
541
0
    return;
542
0
  }
543
0
  next = pos + slen;
544
0
  pos++; /* skip QueryRespLenLimit and PAME-BI */
545
546
0
  if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
547
0
    p2p_dbg(p2p, "Unsupported GAS advertisement protocol id %u",
548
0
      *pos);
549
0
    return;
550
0
  }
551
552
0
  pos = next;
553
  /* Query Response */
554
0
  if (end - pos < 2) {
555
0
    p2p_dbg(p2p, "Too short Query Response");
556
0
    return;
557
0
  }
558
0
  slen = WPA_GET_LE16(pos);
559
0
  pos += 2;
560
0
  p2p_dbg(p2p, "Query Response Length: %d", slen);
561
0
  if (slen > end - pos) {
562
0
    p2p_dbg(p2p, "Not enough Query Response data");
563
0
    return;
564
0
  }
565
0
  end = pos + slen;
566
567
0
  if (comeback_delay) {
568
0
    p2p_dbg(p2p, "Fragmented response - request fragments");
569
0
    if (p2p->sd_rx_resp) {
570
0
      p2p_dbg(p2p, "Drop old SD reassembly buffer");
571
0
      wpabuf_free(p2p->sd_rx_resp);
572
0
      p2p->sd_rx_resp = NULL;
573
0
    }
574
0
    p2p_send_gas_comeback_req(p2p, sa, dialog_token, rx_freq);
575
0
    return;
576
0
  }
577
578
  /* ANQP Query Response */
579
0
  if (end - pos < 4)
580
0
    return;
581
0
  if (WPA_GET_LE16(pos) != ANQP_VENDOR_SPECIFIC) {
582
0
    p2p_dbg(p2p, "Unsupported ANQP Info ID %u", WPA_GET_LE16(pos));
583
0
    return;
584
0
  }
585
0
  pos += 2;
586
587
0
  slen = WPA_GET_LE16(pos);
588
0
  pos += 2;
589
0
  if (slen > end - pos || slen < 3 + 1) {
590
0
    p2p_dbg(p2p, "Invalid ANQP Query Response length");
591
0
    return;
592
0
  }
593
594
0
  if (WPA_GET_BE32(pos) != P2P_IE_VENDOR_TYPE) {
595
0
    p2p_dbg(p2p, "Unsupported ANQP vendor OUI-type %08x",
596
0
      WPA_GET_BE32(pos));
597
0
    return;
598
0
  }
599
0
  pos += 4;
600
601
0
  if (end - pos < 2)
602
0
    return;
603
0
  update_indic = WPA_GET_LE16(pos);
604
0
  p2p_dbg(p2p, "Service Update Indicator: %u", update_indic);
605
0
  pos += 2;
606
607
0
  p2p->sd_peer = NULL;
608
609
0
  if (p2p->sd_query) {
610
0
    if (!p2p->sd_query->for_all_peers) {
611
0
      struct p2p_sd_query *q;
612
0
      p2p_dbg(p2p, "Remove completed SD query %p",
613
0
        p2p->sd_query);
614
0
      q = p2p->sd_query;
615
0
      p2p_unlink_sd_query(p2p, p2p->sd_query);
616
0
      p2p_free_sd_query(q);
617
0
    }
618
0
    p2p->sd_query = NULL;
619
0
  }
620
621
0
  if (p2p->cfg->sd_response)
622
0
    p2p->cfg->sd_response(p2p->cfg->cb_ctx, sa, update_indic,
623
0
              pos, end - pos);
624
0
  p2p_continue_find(p2p);
625
0
}
626
627
628
void p2p_rx_gas_comeback_req(struct p2p_data *p2p, const u8 *sa,
629
           const u8 *data, size_t len, int rx_freq)
630
33
{
631
33
  struct wpabuf *resp;
632
33
  u8 dialog_token;
633
33
  size_t frag_len, max_len;
634
33
  int more = 0;
635
33
  unsigned int wait_time = 200;
636
637
33
  wpa_hexdump(MSG_DEBUG, "P2P: RX GAS Comeback Request", data, len);
638
33
  if (len < 1)
639
2
    return;
640
31
  dialog_token = *data;
641
31
  p2p_dbg(p2p, "Dialog Token: %u", dialog_token);
642
31
  if (dialog_token != p2p->sd_resp_dialog_token) {
643
24
    p2p_dbg(p2p, "No pending SD response fragment for dialog token %u",
644
24
      dialog_token);
645
24
    return;
646
24
  }
647
648
7
  if (p2p->sd_resp == NULL) {
649
7
    p2p_dbg(p2p, "No pending SD response fragment available");
650
7
    return;
651
7
  }
652
0
  if (!ether_addr_equal(sa, p2p->sd_resp_addr)) {
653
0
    p2p_dbg(p2p, "No pending SD response fragment for " MACSTR,
654
0
      MAC2STR(sa));
655
0
    return;
656
0
  }
657
658
  /*
659
   * In the 60 GHz, we have a smaller maximum frame length for management
660
   * frames.
661
   */
662
0
  max_len = (rx_freq > 56160) ? 928 : 1400;
663
0
  frag_len = wpabuf_len(p2p->sd_resp) - p2p->sd_resp_pos;
664
0
  if (frag_len > max_len) {
665
0
    frag_len = max_len;
666
0
    more = 1;
667
0
  }
668
0
  resp = p2p_build_gas_comeback_resp(dialog_token, WLAN_STATUS_SUCCESS,
669
0
             p2p->srv_update_indic,
670
0
             wpabuf_head_u8(p2p->sd_resp) +
671
0
             p2p->sd_resp_pos, frag_len,
672
0
             p2p->sd_frag_id, more,
673
0
             wpabuf_len(p2p->sd_resp));
674
0
  if (resp == NULL)
675
0
    return;
676
0
  p2p_dbg(p2p, "Send GAS Comeback Response (frag_id %d more=%d frag_len=%d)",
677
0
    p2p->sd_frag_id, more, (int) frag_len);
678
0
  p2p->sd_frag_id++;
679
0
  p2p->sd_resp_pos += frag_len;
680
681
0
  if (more) {
682
0
    p2p_dbg(p2p, "%d more bytes remain to be sent",
683
0
      (int) (wpabuf_len(p2p->sd_resp) - p2p->sd_resp_pos));
684
0
  } else {
685
0
    p2p_dbg(p2p, "All fragments of SD response sent");
686
0
    wpabuf_free(p2p->sd_resp);
687
0
    p2p->sd_resp = NULL;
688
0
    wait_time = 0; /* no more SD frames in the sequence */
689
0
  }
690
691
0
  p2p->pending_action_state = P2P_NO_PENDING_ACTION;
692
0
  if (p2p_send_action(p2p, rx_freq, sa, p2p->cfg->dev_addr,
693
0
          p2p->cfg->dev_addr,
694
0
          wpabuf_head(resp), wpabuf_len(resp), wait_time) < 0)
695
0
    p2p_dbg(p2p, "Failed to send Action frame");
696
697
0
  wpabuf_free(resp);
698
0
}
699
700
701
void p2p_rx_gas_comeback_resp(struct p2p_data *p2p, const u8 *sa,
702
            const u8 *data, size_t len, int rx_freq)
703
1
{
704
1
  const u8 *pos = data;
705
1
  const u8 *end = data + len;
706
1
  const u8 *next;
707
1
  u8 dialog_token;
708
1
  u16 status_code;
709
1
  u8 frag_id;
710
1
  u8 more_frags;
711
1
  u16 comeback_delay;
712
1
  u16 slen;
713
714
1
  wpa_hexdump(MSG_DEBUG, "P2P: RX GAS Comeback Response", data, len);
715
716
1
  if (p2p->state != P2P_SD_DURING_FIND || p2p->sd_peer == NULL ||
717
1
      !ether_addr_equal(sa, p2p->sd_peer->info.p2p_device_addr)) {
718
1
    p2p_dbg(p2p, "Ignore unexpected GAS Comeback Response from "
719
1
      MACSTR, MAC2STR(sa));
720
1
    return;
721
1
  }
722
0
  p2p->cfg->send_action_done(p2p->cfg->cb_ctx);
723
0
  p2p_clear_timeout(p2p);
724
725
0
  p2p_dbg(p2p, "Received GAS Comeback Response from " MACSTR " (len=%d)",
726
0
    MAC2STR(sa), (int) len);
727
728
0
  if (len < 6 + 2) {
729
0
    p2p_dbg(p2p, "Too short GAS Comeback Response frame");
730
0
    return;
731
0
  }
732
733
0
  dialog_token = *pos++;
734
  /* TODO: check dialog_token match */
735
0
  status_code = WPA_GET_LE16(pos);
736
0
  pos += 2;
737
0
  frag_id = *pos & 0x7f;
738
0
  more_frags = (*pos & 0x80) >> 7;
739
0
  pos++;
740
0
  comeback_delay = WPA_GET_LE16(pos);
741
0
  pos += 2;
742
0
  p2p_dbg(p2p, "dialog_token=%u status_code=%u frag_id=%d more_frags=%d "
743
0
    "comeback_delay=%u",
744
0
    dialog_token, status_code, frag_id, more_frags,
745
0
    comeback_delay);
746
  /* TODO: check frag_id match */
747
0
  if (status_code) {
748
0
    p2p_dbg(p2p, "Service Discovery failed: status code %u",
749
0
      status_code);
750
0
    return;
751
0
  }
752
753
0
  if (*pos != WLAN_EID_ADV_PROTO) {
754
0
    p2p_dbg(p2p, "Unexpected IE in GAS Comeback Response: %u",
755
0
      *pos);
756
0
    return;
757
0
  }
758
0
  pos++;
759
760
0
  slen = *pos++;
761
0
  if (slen > end - pos || slen < 2) {
762
0
    p2p_dbg(p2p, "Invalid IE in GAS Comeback Response");
763
0
    return;
764
0
  }
765
0
  next = pos + slen;
766
0
  pos++; /* skip QueryRespLenLimit and PAME-BI */
767
768
0
  if (*pos != ACCESS_NETWORK_QUERY_PROTOCOL) {
769
0
    p2p_dbg(p2p, "Unsupported GAS advertisement protocol id %u",
770
0
      *pos);
771
0
    return;
772
0
  }
773
774
0
  pos = next;
775
  /* Query Response */
776
0
  if (end - pos < 2) {
777
0
    p2p_dbg(p2p, "Too short Query Response");
778
0
    return;
779
0
  }
780
0
  slen = WPA_GET_LE16(pos);
781
0
  pos += 2;
782
0
  p2p_dbg(p2p, "Query Response Length: %d", slen);
783
0
  if (slen > end - pos) {
784
0
    p2p_dbg(p2p, "Not enough Query Response data");
785
0
    return;
786
0
  }
787
0
  if (slen == 0) {
788
0
    p2p_dbg(p2p, "No Query Response data");
789
0
    return;
790
0
  }
791
0
  end = pos + slen;
792
793
0
  if (p2p->sd_rx_resp) {
794
     /*
795
      * ANQP header is only included in the first fragment; rest of
796
      * the fragments start with continue TLVs.
797
      */
798
0
    goto skip_nqp_header;
799
0
  }
800
801
  /* ANQP Query Response */
802
0
  if (end - pos < 4)
803
0
    return;
804
0
  if (WPA_GET_LE16(pos) != ANQP_VENDOR_SPECIFIC) {
805
0
    p2p_dbg(p2p, "Unsupported ANQP Info ID %u", WPA_GET_LE16(pos));
806
0
    return;
807
0
  }
808
0
  pos += 2;
809
810
0
  slen = WPA_GET_LE16(pos);
811
0
  pos += 2;
812
0
  p2p_dbg(p2p, "ANQP Query Response length: %u", slen);
813
0
  if (slen < 3 + 1) {
814
0
    p2p_dbg(p2p, "Invalid ANQP Query Response length");
815
0
    return;
816
0
  }
817
0
  if (end - pos < 4)
818
0
    return;
819
820
0
  if (WPA_GET_BE32(pos) != P2P_IE_VENDOR_TYPE) {
821
0
    p2p_dbg(p2p, "Unsupported ANQP vendor OUI-type %08x",
822
0
      WPA_GET_BE32(pos));
823
0
    return;
824
0
  }
825
0
  pos += 4;
826
827
0
  if (end - pos < 2)
828
0
    return;
829
0
  p2p->sd_rx_update_indic = WPA_GET_LE16(pos);
830
0
  p2p_dbg(p2p, "Service Update Indicator: %u", p2p->sd_rx_update_indic);
831
0
  pos += 2;
832
833
0
skip_nqp_header:
834
0
  if (wpabuf_resize(&p2p->sd_rx_resp, end - pos) < 0)
835
0
    return;
836
0
  wpabuf_put_data(p2p->sd_rx_resp, pos, end - pos);
837
0
  p2p_dbg(p2p, "Current SD reassembly buffer length: %u",
838
0
    (unsigned int) wpabuf_len(p2p->sd_rx_resp));
839
840
0
  if (more_frags) {
841
0
    p2p_dbg(p2p, "More fragments remains");
842
    /* TODO: what would be a good size limit? */
843
0
    if (wpabuf_len(p2p->sd_rx_resp) > 64000) {
844
0
      wpabuf_free(p2p->sd_rx_resp);
845
0
      p2p->sd_rx_resp = NULL;
846
0
      p2p_dbg(p2p, "Too long SD response - drop it");
847
0
      return;
848
0
    }
849
0
    p2p_send_gas_comeback_req(p2p, sa, dialog_token, rx_freq);
850
0
    return;
851
0
  }
852
853
0
  p2p->sd_peer = NULL;
854
855
0
  if (p2p->sd_query) {
856
0
    if (!p2p->sd_query->for_all_peers) {
857
0
      struct p2p_sd_query *q;
858
0
      p2p_dbg(p2p, "Remove completed SD query %p",
859
0
        p2p->sd_query);
860
0
      q = p2p->sd_query;
861
0
      p2p_unlink_sd_query(p2p, p2p->sd_query);
862
0
      p2p_free_sd_query(q);
863
0
    }
864
0
    p2p->sd_query = NULL;
865
0
  }
866
867
0
  if (p2p->cfg->sd_response)
868
0
    p2p->cfg->sd_response(p2p->cfg->cb_ctx, sa,
869
0
              p2p->sd_rx_update_indic,
870
0
              wpabuf_head(p2p->sd_rx_resp),
871
0
              wpabuf_len(p2p->sd_rx_resp));
872
0
  wpabuf_free(p2p->sd_rx_resp);
873
0
  p2p->sd_rx_resp = NULL;
874
875
0
  p2p_continue_find(p2p);
876
0
}
877
878
879
void * p2p_sd_request(struct p2p_data *p2p, const u8 *dst,
880
          const struct wpabuf *tlvs)
881
0
{
882
0
  struct p2p_sd_query *q;
883
884
0
  q = os_zalloc(sizeof(*q));
885
0
  if (q == NULL)
886
0
    return NULL;
887
888
0
  if (dst)
889
0
    os_memcpy(q->peer, dst, ETH_ALEN);
890
0
  else
891
0
    q->for_all_peers = 1;
892
893
0
  q->tlvs = wpabuf_dup(tlvs);
894
0
  if (q->tlvs == NULL) {
895
0
    p2p_free_sd_query(q);
896
0
    return NULL;
897
0
  }
898
899
0
  q->next = p2p->sd_queries;
900
0
  p2p->sd_queries = q;
901
0
  p2p_dbg(p2p, "Added SD Query %p", q);
902
903
0
  if (dst == NULL) {
904
0
    struct p2p_device *dev;
905
906
0
    p2p->num_p2p_sd_queries++;
907
908
    /* Update all the devices for the newly added broadcast query */
909
0
    dl_list_for_each(dev, &p2p->devices, struct p2p_device, list) {
910
0
      if (dev->sd_pending_bcast_queries <= 0)
911
0
        dev->sd_pending_bcast_queries = 1;
912
0
      else
913
0
        dev->sd_pending_bcast_queries++;
914
0
    }
915
0
  }
916
917
0
  return q;
918
0
}
919
920
921
#ifdef CONFIG_WIFI_DISPLAY
922
void * p2p_sd_request_wfd(struct p2p_data *p2p, const u8 *dst,
923
        const struct wpabuf *tlvs)
924
0
{
925
0
  struct p2p_sd_query *q;
926
0
  q = p2p_sd_request(p2p, dst, tlvs);
927
0
  if (q)
928
0
    q->wsd = 1;
929
0
  return q;
930
0
}
931
#endif /* CONFIG_WIFI_DISPLAY */
932
933
934
void p2p_sd_service_update(struct p2p_data *p2p)
935
0
{
936
0
  p2p->srv_update_indic++;
937
0
}
938
939
940
int p2p_sd_cancel_request(struct p2p_data *p2p, void *req)
941
0
{
942
0
  if (p2p_unlink_sd_query(p2p, req)) {
943
0
    p2p_dbg(p2p, "Cancel pending SD query %p", req);
944
0
    p2p_free_sd_query(req);
945
0
    return 0;
946
0
  }
947
0
  return -1;
948
0
}