1 /** @file
2 * @brief Service Discovery Protocol handling.
3 */
4
5 /*
6 * Copyright (c) 2016 Intel Corporation
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 */
10
11 #include <errno.h>
12 #include <sys/types.h>
13 #include <zephyr/sys/byteorder.h>
14 #include <zephyr/sys/__assert.h>
15
16 #include <zephyr/bluetooth/buf.h>
17 #include <zephyr/bluetooth/classic/sdp.h>
18
19 #include "common/bt_str.h"
20 #include "common/assert.h"
21
22 #include "host/hci_core.h"
23 #include "host/conn_internal.h"
24 #include "l2cap_br_internal.h"
25 #include "sdp_internal.h"
26
27 #define LOG_LEVEL CONFIG_BT_SDP_LOG_LEVEL
28 #include <zephyr/logging/log.h>
29 LOG_MODULE_REGISTER(bt_sdp);
30
31 #define SDP_PSM 0x0001
32
33 #define SDP_CHAN(_ch) CONTAINER_OF(_ch, struct bt_sdp, chan.chan)
34
35 #define SDP_DATA_MTU 200
36
37 #define SDP_MTU (SDP_DATA_MTU + sizeof(struct bt_sdp_hdr))
38
39 #define MAX_NUM_ATT_ID_FILTER 10
40
41 #define SDP_SERVICE_HANDLE_BASE 0x10000
42
43 #define SDP_DATA_ELEM_NEST_LEVEL_MAX 5
44
45 /* Size of Cont state length */
46 #define SDP_CONT_STATE_LEN_SIZE 1
47
48 /* 1 byte for the no. of services searched till this response */
49 /* 2 bytes for the total no. of matching records */
50 #define SDP_SS_CONT_STATE_SIZE 3
51
52 /* 1 byte for the no. of attributes searched till this response */
53 #define SDP_SA_CONT_STATE_SIZE 1
54
55 /* 1 byte for the no. of services searched till this response */
56 /* 1 byte for the no. of attributes searched till this response */
57 #define SDP_SSA_CONT_STATE_SIZE 2
58
59 #define SDP_INVALID 0xff
60
61 /* SDP record handle size */
62 #define SDP_RECORD_HANDLE_SIZE 4
63
64 struct bt_sdp {
65 struct bt_l2cap_br_chan chan;
66 struct k_fifo partial_resp_queue;
67 /* TODO: Allow more than one pending request */
68 };
69
70 static struct bt_sdp_record *db;
71 static uint8_t num_services;
72
73 static struct bt_sdp bt_sdp_pool[CONFIG_BT_MAX_CONN];
74
75 /* Pool for outgoing SDP packets */
76 NET_BUF_POOL_FIXED_DEFINE(sdp_pool, CONFIG_BT_MAX_CONN, BT_L2CAP_BUF_SIZE(SDP_MTU),
77 CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
78
79 #define SDP_CLIENT_CHAN(_ch) CONTAINER_OF(_ch, struct bt_sdp_client, chan.chan)
80
81 #define SDP_CLIENT_MTU 64
82
83 struct bt_sdp_client {
84 struct bt_l2cap_br_chan chan;
85 /* list of waiting to be resolved UUID params */
86 sys_slist_t reqs;
87 /* required SDP transaction ID */
88 uint16_t tid;
89 /* UUID params holder being now resolved */
90 const struct bt_sdp_discover_params *param;
91 /* PDU continuation state object */
92 struct bt_sdp_pdu_cstate cstate;
93 /* buffer for collecting record data */
94 struct net_buf *rec_buf;
95 };
96
97 static struct bt_sdp_client bt_sdp_client_pool[CONFIG_BT_MAX_CONN];
98
99 enum {
100 BT_SDP_ITER_STOP,
101 BT_SDP_ITER_CONTINUE,
102 };
103
104 struct search_state {
105 uint16_t att_list_size;
106 uint8_t current_svc;
107 uint8_t last_att;
108 bool pkt_full;
109 };
110
111 struct select_attrs_data {
112 struct bt_sdp_record *rec;
113 struct net_buf *rsp_buf;
114 struct bt_sdp *sdp;
115 struct bt_sdp_data_elem_seq *seq;
116 struct search_state *state;
117 uint32_t *filter;
118 uint16_t max_att_len;
119 uint16_t att_list_len;
120 uint8_t cont_state_size;
121 size_t num_filters;
122 bool new_service;
123 };
124
125 /* @typedef bt_sdp_attr_func_t
126 * @brief SDP attribute iterator callback.
127 *
128 * @param attr Attribute found.
129 * @param att_idx Index of the found attribute in the attribute database.
130 * @param user_data Data given.
131 *
132 * @return BT_SDP_ITER_CONTINUE if should continue to the next attribute
133 * or BT_SDP_ITER_STOP to stop.
134 */
135 typedef uint8_t (*bt_sdp_attr_func_t)(struct bt_sdp_attribute *attr,
136 uint8_t att_idx, void *user_data);
137
138 /* @typedef bt_sdp_svc_func_t
139 * @brief SDP service record iterator callback.
140 *
141 * @param rec Service record found.
142 * @param user_data Data given.
143 *
144 * @return BT_SDP_ITER_CONTINUE if should continue to the next service record
145 * or BT_SDP_ITER_STOP to stop.
146 */
147 typedef uint8_t (*bt_sdp_svc_func_t)(struct bt_sdp_record *rec,
148 void *user_data);
149
150 /* @brief Callback for SDP connection
151 *
152 * Gets called when an SDP connection is established
153 *
154 * @param chan L2CAP channel
155 *
156 * @return None
157 */
bt_sdp_connected(struct bt_l2cap_chan * chan)158 static void bt_sdp_connected(struct bt_l2cap_chan *chan)
159 {
160 struct bt_l2cap_br_chan *ch = CONTAINER_OF(chan,
161 struct bt_l2cap_br_chan,
162 chan);
163
164 struct bt_sdp *sdp = CONTAINER_OF(ch, struct bt_sdp, chan);
165
166 LOG_DBG("chan %p cid 0x%04x", ch, ch->tx.cid);
167
168 k_fifo_init(&sdp->partial_resp_queue);
169 }
170
171 /** @brief Callback for SDP disconnection
172 *
173 * Gets called when an SDP connection is terminated
174 *
175 * @param chan L2CAP channel
176 *
177 * @return None
178 */
bt_sdp_disconnected(struct bt_l2cap_chan * chan)179 static void bt_sdp_disconnected(struct bt_l2cap_chan *chan)
180 {
181 struct bt_l2cap_br_chan *ch = CONTAINER_OF(chan,
182 struct bt_l2cap_br_chan,
183 chan);
184
185 struct bt_sdp *sdp = CONTAINER_OF(ch, struct bt_sdp, chan);
186
187 LOG_DBG("chan %p cid 0x%04x", ch, ch->tx.cid);
188
189 (void)memset(sdp, 0, sizeof(*sdp));
190 }
191
192 /* @brief Creates an SDP PDU
193 *
194 * Creates an empty SDP PDU and returns the buffer
195 *
196 * @param None
197 *
198 * @return Pointer to the net_buf buffer
199 */
bt_sdp_create_pdu(void)200 static struct net_buf *bt_sdp_create_pdu(void)
201 {
202 return bt_l2cap_create_pdu(&sdp_pool, sizeof(struct bt_sdp_hdr));
203 }
204
205 /* @brief Sends out an SDP PDU
206 *
207 * Sends out an SDP PDU after adding the relevant header
208 *
209 * @param chan L2CAP channel
210 * @param buf Buffer to be sent out
211 * @param op Opcode to be used in the packet header
212 * @param tid Transaction ID to be used in the packet header
213 *
214 * @return None
215 */
bt_sdp_send(struct bt_l2cap_chan * chan,struct net_buf * buf,uint8_t op,uint16_t tid)216 static int bt_sdp_send(struct bt_l2cap_chan *chan, struct net_buf *buf,
217 uint8_t op, uint16_t tid)
218 {
219 struct bt_sdp_hdr *hdr;
220 uint16_t param_len = buf->len;
221 int err;
222
223 hdr = net_buf_push(buf, sizeof(struct bt_sdp_hdr));
224 hdr->op_code = op;
225 hdr->tid = sys_cpu_to_be16(tid);
226 hdr->param_len = sys_cpu_to_be16(param_len);
227
228 err = bt_l2cap_chan_send(chan, buf);
229 if (err < 0) {
230 net_buf_unref(buf);
231 }
232
233 return err;
234 }
235
236 /* @brief Sends an error response PDU
237 *
238 * Creates and sends an error response PDU
239 *
240 * @param chan L2CAP channel
241 * @param err Error code to be sent in the packet
242 * @param tid Transaction ID to be used in the packet header
243 *
244 * @return None
245 */
send_err_rsp(struct bt_l2cap_chan * chan,uint16_t err,uint16_t tid)246 static void send_err_rsp(struct bt_l2cap_chan *chan, uint16_t err,
247 uint16_t tid)
248 {
249 struct net_buf *buf;
250
251 LOG_DBG("tid %u, error %u", tid, err);
252
253 buf = bt_sdp_create_pdu();
254
255 net_buf_add_be16(buf, err);
256
257 bt_sdp_send(chan, buf, BT_SDP_ERROR_RSP, tid);
258 }
259
260 /* @brief Parses data elements from a net_buf
261 *
262 * Parses the first data element from a buffer and splits it into type, size,
263 * data. Used for parsing incoming requests. Net buf is advanced to the data
264 * part of the element.
265 *
266 * @param buf Buffer to be advanced
267 * @param data_elem Pointer to the parsed data element structure
268 *
269 * @return 0 for success, or relevant error code
270 */
parse_data_elem(struct net_buf * buf,struct bt_sdp_data_elem * data_elem)271 static uint16_t parse_data_elem(struct net_buf *buf,
272 struct bt_sdp_data_elem *data_elem)
273 {
274 uint8_t size_field_len = 0U; /* Space used to accommodate the size */
275
276 if (buf->len < 1) {
277 LOG_WRN("Malformed packet");
278 return BT_SDP_INVALID_SYNTAX;
279 }
280
281 data_elem->type = net_buf_pull_u8(buf);
282
283 switch (data_elem->type & BT_SDP_TYPE_DESC_MASK) {
284 case BT_SDP_UINT8:
285 case BT_SDP_INT8:
286 case BT_SDP_UUID_UNSPEC:
287 case BT_SDP_BOOL:
288 data_elem->data_size = BIT(data_elem->type &
289 BT_SDP_SIZE_DESC_MASK);
290 break;
291 case BT_SDP_TEXT_STR_UNSPEC:
292 case BT_SDP_SEQ_UNSPEC:
293 case BT_SDP_ALT_UNSPEC:
294 case BT_SDP_URL_STR_UNSPEC:
295 size_field_len = BIT((data_elem->type & BT_SDP_SIZE_DESC_MASK) -
296 BT_SDP_SIZE_INDEX_OFFSET);
297 if (buf->len < size_field_len) {
298 LOG_WRN("Malformed packet");
299 return BT_SDP_INVALID_SYNTAX;
300 }
301 switch (size_field_len) {
302 case 1:
303 data_elem->data_size = net_buf_pull_u8(buf);
304 break;
305 case 2:
306 data_elem->data_size = net_buf_pull_be16(buf);
307 break;
308 case 4:
309 data_elem->data_size = net_buf_pull_be32(buf);
310 break;
311 default:
312 LOG_WRN("Invalid size in remote request");
313 return BT_SDP_INVALID_SYNTAX;
314 }
315 break;
316 default:
317 LOG_WRN("Invalid type in remote request");
318 return BT_SDP_INVALID_SYNTAX;
319 }
320
321 if (buf->len < data_elem->data_size) {
322 LOG_WRN("Malformed packet");
323 return BT_SDP_INVALID_SYNTAX;
324 }
325
326 data_elem->total_size = data_elem->data_size + size_field_len + 1;
327 data_elem->data = buf->data;
328
329 return 0;
330 }
331
332 /* @brief Searches for an UUID within an attribute
333 *
334 * Searches for an UUID within an attribute. If the attribute has data element
335 * sequences, it recursively searches within them as well. On finding a match
336 * with the UUID, it sets the found flag.
337 *
338 * @param elem Attribute to be used as the search space (haystack)
339 * @param uuid UUID to be looked for (needle)
340 * @param found Flag set to true if the UUID is found (to be returned)
341 * @param nest_level Used to limit the extent of recursion into nested data
342 * elements, to avoid potential stack overflows
343 *
344 * @return Size of the last data element that has been searched
345 * (used in recursion)
346 */
search_uuid(struct bt_sdp_data_elem * elem,struct bt_uuid * uuid,bool * found,uint8_t nest_level)347 static uint32_t search_uuid(struct bt_sdp_data_elem *elem, struct bt_uuid *uuid,
348 bool *found, uint8_t nest_level)
349 {
350 const uint8_t *cur_elem;
351 uint32_t seq_size, size;
352 union {
353 struct bt_uuid uuid;
354 struct bt_uuid_16 u16;
355 struct bt_uuid_32 u32;
356 struct bt_uuid_128 u128;
357 } u;
358
359 if (*found) {
360 return 0;
361 }
362
363 /* Limit recursion depth to avoid stack overflows */
364 if (nest_level == SDP_DATA_ELEM_NEST_LEVEL_MAX) {
365 return 0;
366 }
367
368 seq_size = elem->data_size;
369 cur_elem = elem->data;
370
371 if ((elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_UUID_UNSPEC) {
372 if (seq_size == 2U) {
373 u.uuid.type = BT_UUID_TYPE_16;
374 u.u16.val = *((uint16_t *)cur_elem);
375 if (!bt_uuid_cmp(&u.uuid, uuid)) {
376 *found = true;
377 }
378 } else if (seq_size == 4U) {
379 u.uuid.type = BT_UUID_TYPE_32;
380 u.u32.val = *((uint32_t *)cur_elem);
381 if (!bt_uuid_cmp(&u.uuid, uuid)) {
382 *found = true;
383 }
384 } else if (seq_size == 16U) {
385 u.uuid.type = BT_UUID_TYPE_128;
386 memcpy(u.u128.val, cur_elem, seq_size);
387 if (!bt_uuid_cmp(&u.uuid, uuid)) {
388 *found = true;
389 }
390 } else {
391 LOG_WRN("Invalid UUID size in local database");
392 BT_ASSERT(0);
393 }
394 }
395
396 if ((elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_SEQ_UNSPEC ||
397 (elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_ALT_UNSPEC) {
398 do {
399 /* Recursively parse data elements */
400 size = search_uuid((struct bt_sdp_data_elem *)cur_elem,
401 uuid, found, nest_level + 1);
402 if (*found) {
403 return 0;
404 }
405 cur_elem += sizeof(struct bt_sdp_data_elem);
406 seq_size -= size;
407 } while (seq_size);
408 }
409
410 return elem->total_size;
411 }
412
413 /* @brief SDP service record iterator.
414 *
415 * Iterate over service records from a starting point.
416 *
417 * @param func Callback function.
418 * @param user_data Data to pass to the callback.
419 *
420 * @return Pointer to the record where the iterator stopped, or NULL if all
421 * records are covered
422 */
bt_sdp_foreach_svc(bt_sdp_svc_func_t func,void * user_data)423 static struct bt_sdp_record *bt_sdp_foreach_svc(bt_sdp_svc_func_t func,
424 void *user_data)
425 {
426 struct bt_sdp_record *rec = db;
427
428 while (rec) {
429 if (func(rec, user_data) == BT_SDP_ITER_STOP) {
430 break;
431 }
432
433 rec = rec->next;
434 }
435 return rec;
436 }
437
438 /* @brief Inserts a service record into a record pointer list
439 *
440 * Inserts a service record into a record pointer list
441 *
442 * @param rec The current service record.
443 * @param user_data Pointer to the destination record list.
444 *
445 * @return BT_SDP_ITER_CONTINUE to move on to the next record.
446 */
insert_record(struct bt_sdp_record * rec,void * user_data)447 static uint8_t insert_record(struct bt_sdp_record *rec, void *user_data)
448 {
449 struct bt_sdp_record **rec_list = user_data;
450
451 rec_list[rec->index] = rec;
452
453 return BT_SDP_ITER_CONTINUE;
454 }
455
456 /* @brief Looks for matching UUIDs in a list of service records
457 *
458 * Parses out a sequence of UUIDs from an input buffer, and checks if a record
459 * in the list contains all the UUIDs. If it doesn't, the record is removed
460 * from the list, so the list contains only the records which has all the
461 * input UUIDs in them.
462 *
463 * @param buf Incoming buffer containing all the UUIDs to be matched
464 * @param matching_recs List of service records to use for storing matching
465 * records
466 *
467 * @return 0 for success, or relevant error code
468 */
find_services(struct net_buf * buf,struct bt_sdp_record ** matching_recs)469 static uint16_t find_services(struct net_buf *buf,
470 struct bt_sdp_record **matching_recs)
471 {
472 struct bt_sdp_data_elem data_elem;
473 struct bt_sdp_record *record;
474 uint32_t uuid_list_size;
475 uint16_t res;
476 uint8_t att_idx, rec_idx = 0U;
477 bool found;
478 union {
479 struct bt_uuid uuid;
480 struct bt_uuid_16 u16;
481 struct bt_uuid_32 u32;
482 struct bt_uuid_128 u128;
483 } u;
484
485 res = parse_data_elem(buf, &data_elem);
486 if (res) {
487 return res;
488 }
489
490 if (((data_elem.type & BT_SDP_TYPE_DESC_MASK) != BT_SDP_SEQ_UNSPEC) &&
491 ((data_elem.type & BT_SDP_TYPE_DESC_MASK) != BT_SDP_ALT_UNSPEC)) {
492 LOG_WRN("Invalid type %x in service search pattern", data_elem.type);
493 return BT_SDP_INVALID_SYNTAX;
494 }
495
496 uuid_list_size = data_elem.data_size;
497
498 bt_sdp_foreach_svc(insert_record, matching_recs);
499
500 /* Go over the sequence of UUIDs, and match one UUID at a time */
501 while (uuid_list_size) {
502 res = parse_data_elem(buf, &data_elem);
503 if (res) {
504 return res;
505 }
506
507 if ((data_elem.type & BT_SDP_TYPE_DESC_MASK) !=
508 BT_SDP_UUID_UNSPEC) {
509 LOG_WRN("Invalid type %u in service search pattern", data_elem.type);
510 return BT_SDP_INVALID_SYNTAX;
511 }
512
513 if (buf->len < data_elem.data_size) {
514 LOG_WRN("Malformed packet");
515 return BT_SDP_INVALID_SYNTAX;
516 }
517
518 if (data_elem.data_size == 2U) {
519 u.uuid.type = BT_UUID_TYPE_16;
520 u.u16.val = net_buf_pull_be16(buf);
521 } else if (data_elem.data_size == 4U) {
522 u.uuid.type = BT_UUID_TYPE_32;
523 u.u32.val = net_buf_pull_be32(buf);
524 } else if (data_elem.data_size == 16U) {
525 u.uuid.type = BT_UUID_TYPE_128;
526 sys_memcpy_swap(u.u128.val, buf->data,
527 data_elem.data_size);
528 net_buf_pull(buf, data_elem.data_size);
529 } else {
530 LOG_WRN("Invalid UUID len %u in service search pattern",
531 data_elem.data_size);
532 net_buf_pull(buf, data_elem.data_size);
533 }
534
535 uuid_list_size -= data_elem.total_size;
536
537 /* Go over the list of services, and look for a service which
538 * doesn't have this UUID
539 */
540 for (rec_idx = 0U; rec_idx < num_services; rec_idx++) {
541 record = matching_recs[rec_idx];
542
543 if (!record) {
544 continue;
545 }
546
547 found = false;
548
549 /* Search for the UUID in all the attrs of the svc */
550 for (att_idx = 0U; att_idx < record->attr_count;
551 att_idx++) {
552 search_uuid(&record->attrs[att_idx].val,
553 &u.uuid, &found, 1);
554 if (found) {
555 break;
556 }
557 }
558
559 /* Remove the record from the list if it doesn't have
560 * the UUID
561 */
562 if (!found) {
563 matching_recs[rec_idx] = NULL;
564 }
565 }
566 }
567
568 return 0;
569 }
570
571 /* @brief Handler for Service Search Request
572 *
573 * Parses, processes and responds to a Service Search Request
574 *
575 * @param sdp Pointer to the SDP structure
576 * @param buf Request net buf
577 * @param tid Transaction ID
578 *
579 * @return 0 for success, or relevant error code
580 */
sdp_svc_search_req(struct bt_sdp * sdp,struct net_buf * buf,uint16_t tid)581 static uint16_t sdp_svc_search_req(struct bt_sdp *sdp, struct net_buf *buf,
582 uint16_t tid)
583 {
584 struct bt_sdp_svc_rsp *rsp;
585 struct net_buf *resp_buf;
586 struct bt_sdp_record *record;
587 struct bt_sdp_record *matching_recs[BT_SDP_MAX_SERVICES];
588 uint16_t max_rec_count, total_recs = 0U, current_recs = 0U, res;
589 uint8_t cont_state_size, cont_state = 0U, idx = 0U, count = 0U;
590 bool pkt_full = false;
591
592 res = find_services(buf, matching_recs);
593 if (res) {
594 /* Error in parsing */
595 return res;
596 }
597
598 if (buf->len < 3) {
599 LOG_WRN("Malformed packet");
600 return BT_SDP_INVALID_SYNTAX;
601 }
602
603 max_rec_count = net_buf_pull_be16(buf);
604 cont_state_size = net_buf_pull_u8(buf);
605
606 /* Zero out the matching services beyond max_rec_count */
607 for (idx = 0U; idx < num_services; idx++) {
608 if (count == max_rec_count) {
609 matching_recs[idx] = NULL;
610 continue;
611 }
612
613 if (matching_recs[idx]) {
614 count++;
615 }
616 }
617
618 /* We send out only SDP_SS_CONT_STATE_SIZE bytes continuation state in
619 * responses, so expect only SDP_SS_CONT_STATE_SIZE bytes in requests
620 */
621 if (cont_state_size) {
622 if (cont_state_size != SDP_SS_CONT_STATE_SIZE) {
623 LOG_WRN("Invalid cont state size %u", cont_state_size);
624 return BT_SDP_INVALID_CSTATE;
625 }
626
627 if (buf->len < cont_state_size) {
628 LOG_WRN("Malformed packet");
629 return BT_SDP_INVALID_SYNTAX;
630 }
631
632 cont_state = net_buf_pull_u8(buf);
633 /* We include total_recs in the continuation state. We calculate
634 * it once and preserve it across all the partial responses
635 */
636 total_recs = net_buf_pull_be16(buf);
637 }
638
639 LOG_DBG("max_rec_count %u, cont_state %u", max_rec_count, cont_state);
640
641 resp_buf = bt_sdp_create_pdu();
642 rsp = net_buf_add(resp_buf, sizeof(*rsp));
643
644 for (; cont_state < num_services; cont_state++) {
645 record = matching_recs[cont_state];
646
647 if (!record) {
648 continue;
649 }
650
651 /* Calculate total recs only if it is first packet */
652 if (!cont_state_size) {
653 total_recs++;
654 }
655
656 if (pkt_full) {
657 continue;
658 }
659
660 /* 4 bytes per Service Record Handle */
661 /* 4 bytes for ContinuationState */
662 if ((MIN(SDP_MTU, sdp->chan.tx.mtu) - resp_buf->len) <
663 (4 + 4 + sizeof(struct bt_sdp_hdr))) {
664 pkt_full = true;
665 }
666
667 if (pkt_full) {
668 /* Packet exhausted: Add continuation state and break */
669 LOG_DBG("Packet full, num_services_covered %u", cont_state);
670 net_buf_add_u8(resp_buf, SDP_SS_CONT_STATE_SIZE);
671 net_buf_add_u8(resp_buf, cont_state);
672
673 /* If it is the first packet of a partial response,
674 * continue dry-running to calculate total_recs.
675 * Else break
676 */
677 if (cont_state_size) {
678 break;
679 }
680
681 continue;
682 }
683
684 /* Add the service record handle to the packet */
685 net_buf_add_be32(resp_buf, record->handle);
686 current_recs++;
687 }
688
689 /* Add 0 continuation state if packet is exhausted */
690 if (!pkt_full) {
691 net_buf_add_u8(resp_buf, 0);
692 } else {
693 net_buf_add_be16(resp_buf, total_recs);
694 }
695
696 rsp->total_recs = sys_cpu_to_be16(total_recs);
697 rsp->current_recs = sys_cpu_to_be16(current_recs);
698
699 LOG_DBG("Sending response, len %u", resp_buf->len);
700 bt_sdp_send(&sdp->chan.chan, resp_buf, BT_SDP_SVC_SEARCH_RSP, tid);
701
702 return 0;
703 }
704
705 /* @brief Copies an attribute into an outgoing buffer
706 *
707 * Copies an attribute into a buffer. Recursively calls itself for complex
708 * attributes.
709 *
710 * @param elem Attribute to be copied to the buffer
711 * @param buf Buffer where the attribute is to be copied
712 *
713 * @return Size of the last data element that has been searched
714 * (used in recursion)
715 */
copy_attribute(struct bt_sdp_data_elem * elem,struct net_buf * buf,uint8_t nest_level)716 static uint32_t copy_attribute(struct bt_sdp_data_elem *elem,
717 struct net_buf *buf, uint8_t nest_level)
718 {
719 const uint8_t *cur_elem;
720 uint32_t size, seq_size, total_size;
721
722 /* Limit recursion depth to avoid stack overflows */
723 if (nest_level == SDP_DATA_ELEM_NEST_LEVEL_MAX) {
724 return 0;
725 }
726
727 seq_size = elem->data_size;
728 total_size = elem->total_size;
729 cur_elem = elem->data;
730
731 /* Copy the header */
732 net_buf_add_u8(buf, elem->type);
733
734 switch (total_size - (seq_size + 1U)) {
735 case 1:
736 net_buf_add_u8(buf, elem->data_size);
737 break;
738 case 2:
739 net_buf_add_be16(buf, elem->data_size);
740 break;
741 case 4:
742 net_buf_add_be32(buf, elem->data_size);
743 break;
744 }
745
746 /* Recursively parse (till the last element is not another data element)
747 * and then fill the elements
748 */
749 if ((elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_SEQ_UNSPEC ||
750 (elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_ALT_UNSPEC) {
751 do {
752 size = copy_attribute((struct bt_sdp_data_elem *)
753 cur_elem, buf, nest_level + 1);
754 cur_elem += sizeof(struct bt_sdp_data_elem);
755 seq_size -= size;
756 } while (seq_size);
757 } else if ((elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_UINT8 ||
758 (elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_INT8 ||
759 (elem->type & BT_SDP_TYPE_DESC_MASK) == BT_SDP_UUID_UNSPEC) {
760 if (seq_size == 1U) {
761 net_buf_add_u8(buf, *((uint8_t *)elem->data));
762 } else if (seq_size == 2U) {
763 net_buf_add_be16(buf, *((uint16_t *)elem->data));
764 } else if (seq_size == 4U) {
765 net_buf_add_be32(buf, *((uint32_t *)elem->data));
766 } else {
767 /* TODO: Convert 32bit and 128bit values to big-endian*/
768 net_buf_add_mem(buf, elem->data, seq_size);
769 }
770 } else {
771 net_buf_add_mem(buf, elem->data, seq_size);
772 }
773
774 return total_size;
775 }
776
777 /* @brief SDP attribute iterator.
778 *
779 * Iterate over attributes of a service record from a starting index.
780 *
781 * @param record Service record whose attributes are to be iterated over.
782 * @param idx Index in the attribute list from where to start.
783 * @param func Callback function.
784 * @param user_data Data to pass to the callback.
785 *
786 * @return Index of the attribute where the iterator stopped
787 */
bt_sdp_foreach_attr(struct bt_sdp_record * record,uint8_t idx,bt_sdp_attr_func_t func,void * user_data)788 static uint8_t bt_sdp_foreach_attr(struct bt_sdp_record *record, uint8_t idx,
789 bt_sdp_attr_func_t func, void *user_data)
790 {
791 for (; idx < record->attr_count; idx++) {
792 if (func(&record->attrs[idx], idx, user_data) ==
793 BT_SDP_ITER_STOP) {
794 break;
795 }
796 }
797
798 return idx;
799 }
800
801 /* @brief Check if an attribute matches a range, and include it in the response
802 *
803 * Checks if an attribute matches a given attribute ID or range, and if so,
804 * includes it in the response packet
805 *
806 * @param attr The current attribute
807 * @param att_idx Index of the current attribute in the database
808 * @param user_data Pointer to the structure containing response packet, byte
809 * count, states, etc
810 *
811 * @return BT_SDP_ITER_CONTINUE if should continue to the next attribute
812 * or BT_SDP_ITER_STOP to stop.
813 */
select_attrs(struct bt_sdp_attribute * attr,uint8_t att_idx,void * user_data)814 static uint8_t select_attrs(struct bt_sdp_attribute *attr, uint8_t att_idx,
815 void *user_data)
816 {
817 struct select_attrs_data *sad = user_data;
818 uint16_t att_id_lower, att_id_upper, att_id_cur, space;
819 uint32_t attr_size, seq_size;
820 size_t idx_filter;
821
822 for (idx_filter = 0U; idx_filter < sad->num_filters; idx_filter++) {
823
824 att_id_lower = (sad->filter[idx_filter] >> 16);
825 att_id_upper = (sad->filter[idx_filter]);
826 att_id_cur = attr->id;
827
828 /* Check for range values */
829 if (att_id_lower != 0xffff &&
830 (!IN_RANGE(att_id_cur, att_id_lower, att_id_upper))) {
831 continue;
832 }
833
834 /* Check for match values */
835 if (att_id_lower == 0xffff && att_id_cur != att_id_upper) {
836 continue;
837 }
838
839 /* Attribute ID matches */
840
841 /* 3 bytes for Attribute ID */
842 attr_size = 3 + attr->val.total_size;
843
844 /* If this is the first attribute of the service, then we need
845 * to account for the space required to add the per-service
846 * data element sequence header as well.
847 */
848 if ((sad->state->current_svc != sad->rec->index) &&
849 sad->new_service) {
850 /* 3 bytes for Per-Service Data Elem Seq declaration */
851 seq_size = attr_size + 3;
852 } else {
853 seq_size = attr_size;
854 }
855
856 if (sad->rsp_buf) {
857 space = MIN(SDP_MTU, sad->sdp->chan.tx.mtu) -
858 sad->rsp_buf->len - sizeof(struct bt_sdp_hdr);
859
860 if ((!sad->state->pkt_full) &&
861 ((seq_size > sad->max_att_len) ||
862 (space < seq_size + sad->cont_state_size))) {
863 /* Packet exhausted */
864 sad->state->pkt_full = true;
865 }
866 }
867
868 /* Keep filling data only if packet is not exhausted */
869 if (!sad->state->pkt_full && sad->rsp_buf) {
870 /* Add Per-Service Data Element Seq declaration once
871 * only when we are starting from the first attribute
872 */
873 if (!sad->seq &&
874 (sad->state->current_svc != sad->rec->index)) {
875 sad->seq = net_buf_add(sad->rsp_buf,
876 sizeof(*sad->seq));
877 sad->seq->type = BT_SDP_SEQ16;
878 sad->seq->size = 0U;
879 }
880
881 /* Add attribute ID */
882 net_buf_add_u8(sad->rsp_buf, BT_SDP_UINT16);
883 net_buf_add_be16(sad->rsp_buf, att_id_cur);
884
885 /* Add attribute value */
886 copy_attribute(&attr->val, sad->rsp_buf, 1);
887
888 sad->max_att_len -= seq_size;
889 sad->att_list_len += seq_size;
890 sad->state->last_att = att_idx;
891 sad->state->current_svc = sad->rec->index;
892 }
893
894 if (sad->seq) {
895 /* Keep adding the sequence size if this packet contains
896 * the Per-Service Data Element Seq declaration header
897 */
898 sad->seq->size += attr_size;
899 sad->state->att_list_size += seq_size;
900 } else {
901 /* Keep adding the total attr lists size if:
902 * It's a dry-run, calculating the total attr lists size
903 */
904 sad->state->att_list_size += seq_size;
905 }
906
907 sad->new_service = false;
908 break;
909 }
910
911 /* End the search if:
912 * 1. We have exhausted the packet
913 * AND
914 * 2. This packet doesn't contain the service element declaration header
915 * AND
916 * 3. This is not a dry-run (then we look for other attrs that match)
917 */
918 if (sad->state->pkt_full && !sad->seq && sad->rsp_buf) {
919 return BT_SDP_ITER_STOP;
920 }
921
922 return BT_SDP_ITER_CONTINUE;
923 }
924
925 /* @brief Creates attribute list in the given buffer
926 *
927 * Populates the attribute list of a service record in the buffer. To be used
928 * for responding to Service Attribute and Service Search Attribute requests
929 *
930 * @param sdp Pointer to the SDP structure
931 * @param record Service record whose attributes are to be included in the
932 * response
933 * @param filter Attribute values/ranges to be used as a filter
934 * @param num_filters Number of elements in the attribute filter
935 * @param max_att_len Maximum size of attributes to be included in the response
936 * @param cont_state_size No. of additional continuation state bytes to keep
937 * space for in the packet. This will vary based on the type of the request
938 * @param next_att Starting position of the search in the service's attr list
939 * @param state State of the overall search
940 * @param rsp_buf Response buffer which is filled in
941 *
942 * @return len Length of the attribute list created
943 */
create_attr_list(struct bt_sdp * sdp,struct bt_sdp_record * record,uint32_t * filter,size_t num_filters,uint16_t max_att_len,uint8_t cont_state_size,uint8_t next_att,struct search_state * state,struct net_buf * rsp_buf)944 static uint16_t create_attr_list(struct bt_sdp *sdp, struct bt_sdp_record *record,
945 uint32_t *filter, size_t num_filters,
946 uint16_t max_att_len, uint8_t cont_state_size,
947 uint8_t next_att, struct search_state *state,
948 struct net_buf *rsp_buf)
949 {
950 struct select_attrs_data sad;
951 uint8_t idx_att;
952
953 sad.num_filters = num_filters;
954 sad.rec = record;
955 sad.rsp_buf = rsp_buf;
956 sad.sdp = sdp;
957 sad.max_att_len = max_att_len;
958 sad.cont_state_size = cont_state_size;
959 sad.seq = NULL;
960 sad.filter = filter;
961 sad.state = state;
962 sad.att_list_len = 0U;
963 sad.new_service = true;
964
965 idx_att = bt_sdp_foreach_attr(sad.rec, next_att, select_attrs, &sad);
966
967 if (sad.seq) {
968 sad.seq->size = sys_cpu_to_be16(sad.seq->size);
969 }
970
971 return sad.att_list_len;
972 }
973
974 /* @brief Extracts the attribute search list from a buffer
975 *
976 * Parses a buffer to extract the attribute search list (list of attribute IDs
977 * and ranges) which are to be used to filter attributes.
978 *
979 * @param buf Buffer to be parsed for extracting the attribute search list
980 * @param filter Empty list of 4byte filters that are filled in. For attribute
981 * IDs, the lower 2 bytes contain the ID and the upper 2 bytes are set to
982 * 0xFFFF. For attribute ranges, the lower 2bytes indicate the start ID and
983 * the upper 2bytes indicate the end ID
984 * @param max_filters Max element slots of filter to be filled in
985 * @param num_filters No. of filter elements filled in (to be returned)
986 *
987 * @return 0 for success, or relevant error code
988 */
get_att_search_list(struct net_buf * buf,uint32_t * filter,size_t max_filters,size_t * num_filters)989 static uint16_t get_att_search_list(struct net_buf *buf, uint32_t *filter,
990 size_t max_filters, size_t *num_filters)
991 {
992 struct bt_sdp_data_elem data_elem;
993 uint16_t res;
994 uint32_t size;
995
996 *num_filters = 0U;
997 res = parse_data_elem(buf, &data_elem);
998 if (res) {
999 return res;
1000 }
1001
1002 size = data_elem.data_size;
1003
1004 while (size) {
1005 if (*num_filters >= max_filters) {
1006 LOG_WRN("Exceeded maximum array length %u of %p", max_filters, filter);
1007 return 0;
1008 }
1009
1010 res = parse_data_elem(buf, &data_elem);
1011 if (res) {
1012 return res;
1013 }
1014
1015 if ((data_elem.type & BT_SDP_TYPE_DESC_MASK) != BT_SDP_UINT8) {
1016 LOG_WRN("Invalid type %u in attribute ID list", data_elem.type);
1017 return BT_SDP_INVALID_SYNTAX;
1018 }
1019
1020 if (buf->len < data_elem.data_size) {
1021 LOG_WRN("Malformed packet");
1022 return BT_SDP_INVALID_SYNTAX;
1023 }
1024
1025 /* This is an attribute ID */
1026 if (data_elem.data_size == 2U) {
1027 filter[(*num_filters)++] = 0xffff0000 |
1028 net_buf_pull_be16(buf);
1029 }
1030
1031 /* This is an attribute ID range */
1032 if (data_elem.data_size == 4U) {
1033 filter[(*num_filters)++] = net_buf_pull_be32(buf);
1034 }
1035
1036 size -= data_elem.total_size;
1037 }
1038
1039 return 0;
1040 }
1041
1042 /* @brief Check if a given handle matches that of the current service
1043 *
1044 * Checks if a given handle matches that of the current service
1045 *
1046 * @param rec The current service record
1047 * @param user_data Pointer to the service record handle to be matched
1048 *
1049 * @return BT_SDP_ITER_CONTINUE if should continue to the next record
1050 * or BT_SDP_ITER_STOP to stop.
1051 */
find_handle(struct bt_sdp_record * rec,void * user_data)1052 static uint8_t find_handle(struct bt_sdp_record *rec, void *user_data)
1053 {
1054 uint32_t *svc_rec_hdl = user_data;
1055
1056 if (rec->handle == *svc_rec_hdl) {
1057 return BT_SDP_ITER_STOP;
1058 }
1059
1060 return BT_SDP_ITER_CONTINUE;
1061 }
1062
1063 /* @brief Handler for Service Attribute Request
1064 *
1065 * Parses, processes and responds to a Service Attribute Request
1066 *
1067 * @param sdp Pointer to the SDP structure
1068 * @param buf Request buffer
1069 * @param tid Transaction ID
1070 *
1071 * @return 0 for success, or relevant error code
1072 */
sdp_svc_att_req(struct bt_sdp * sdp,struct net_buf * buf,uint16_t tid)1073 static uint16_t sdp_svc_att_req(struct bt_sdp *sdp, struct net_buf *buf,
1074 uint16_t tid)
1075 {
1076 uint32_t filter[MAX_NUM_ATT_ID_FILTER];
1077 struct search_state state = {
1078 .current_svc = SDP_INVALID,
1079 .last_att = SDP_INVALID,
1080 .pkt_full = false
1081 };
1082 struct bt_sdp_record *record;
1083 struct bt_sdp_att_rsp *rsp;
1084 struct net_buf *rsp_buf;
1085 uint32_t svc_rec_hdl;
1086 uint16_t max_att_len, res, att_list_len;
1087 size_t num_filters;
1088 uint8_t cont_state_size, next_att = 0U;
1089
1090 if (buf->len < 6) {
1091 LOG_WRN("Malformed packet");
1092 return BT_SDP_INVALID_SYNTAX;
1093 }
1094
1095 svc_rec_hdl = net_buf_pull_be32(buf);
1096 max_att_len = net_buf_pull_be16(buf);
1097
1098 /* Set up the filters */
1099 res = get_att_search_list(buf, filter, ARRAY_SIZE(filter), &num_filters);
1100 if (res) {
1101 /* Error in parsing */
1102 return res;
1103 }
1104
1105 if (buf->len < 1) {
1106 LOG_WRN("Malformed packet");
1107 return BT_SDP_INVALID_SYNTAX;
1108 }
1109
1110 cont_state_size = net_buf_pull_u8(buf);
1111
1112 /* We only send out 1 byte continuation state in responses,
1113 * so expect only 1 byte in requests
1114 */
1115 if (cont_state_size) {
1116 if (cont_state_size != SDP_SA_CONT_STATE_SIZE) {
1117 LOG_WRN("Invalid cont state size %u", cont_state_size);
1118 return BT_SDP_INVALID_CSTATE;
1119 }
1120
1121 if (buf->len < cont_state_size) {
1122 LOG_WRN("Malformed packet");
1123 return BT_SDP_INVALID_SYNTAX;
1124 }
1125
1126 state.last_att = net_buf_pull_u8(buf) + 1;
1127 next_att = state.last_att;
1128 }
1129
1130 LOG_DBG("svc_rec_hdl %u, max_att_len 0x%04x, cont_state %u", svc_rec_hdl, max_att_len,
1131 next_att);
1132
1133 /* Find the service */
1134 record = bt_sdp_foreach_svc(find_handle, &svc_rec_hdl);
1135
1136 if (!record) {
1137 LOG_WRN("Handle %u not found", svc_rec_hdl);
1138 return BT_SDP_INVALID_RECORD_HANDLE;
1139 }
1140
1141 /* For partial responses, restore the search state */
1142 if (cont_state_size) {
1143 state.current_svc = record->index;
1144 }
1145
1146 rsp_buf = bt_sdp_create_pdu();
1147 rsp = net_buf_add(rsp_buf, sizeof(*rsp));
1148
1149 /* cont_state_size should include 1 byte header */
1150 att_list_len = create_attr_list(sdp, record, filter, num_filters,
1151 max_att_len, SDP_SA_CONT_STATE_SIZE + 1,
1152 next_att, &state, rsp_buf);
1153
1154 if (!att_list_len) {
1155 /* For empty responses, add an empty data element sequence */
1156 net_buf_add_u8(rsp_buf, BT_SDP_SEQ8);
1157 net_buf_add_u8(rsp_buf, 0);
1158 att_list_len = 2U;
1159 }
1160
1161 /* Add continuation state */
1162 if (state.pkt_full) {
1163 LOG_DBG("Packet full, state.last_att %u", state.last_att);
1164 net_buf_add_u8(rsp_buf, 1);
1165 net_buf_add_u8(rsp_buf, state.last_att);
1166 } else {
1167 net_buf_add_u8(rsp_buf, 0);
1168 }
1169
1170 rsp->att_list_len = sys_cpu_to_be16(att_list_len);
1171
1172 LOG_DBG("Sending response, len %u", rsp_buf->len);
1173 bt_sdp_send(&sdp->chan.chan, rsp_buf, BT_SDP_SVC_ATTR_RSP, tid);
1174
1175 return 0;
1176 }
1177
1178 /* @brief Handler for Service Search Attribute Request
1179 *
1180 * Parses, processes and responds to a Service Search Attribute Request
1181 *
1182 * @param sdp Pointer to the SDP structure
1183 * @param buf Request buffer
1184 * @param tid Transaction ID
1185 *
1186 * @return 0 for success, or relevant error code
1187 */
sdp_svc_search_att_req(struct bt_sdp * sdp,struct net_buf * buf,uint16_t tid)1188 static uint16_t sdp_svc_search_att_req(struct bt_sdp *sdp, struct net_buf *buf,
1189 uint16_t tid)
1190 {
1191 uint32_t filter[MAX_NUM_ATT_ID_FILTER];
1192 struct bt_sdp_record *matching_recs[BT_SDP_MAX_SERVICES];
1193 struct search_state state = {
1194 .att_list_size = 0,
1195 .current_svc = SDP_INVALID,
1196 .last_att = SDP_INVALID,
1197 .pkt_full = false
1198 };
1199 struct net_buf *rsp_buf, *rsp_buf_cpy;
1200 struct bt_sdp_record *record;
1201 struct bt_sdp_att_rsp *rsp;
1202 struct bt_sdp_data_elem_seq *seq = NULL;
1203 uint16_t max_att_len, res, att_list_len = 0U;
1204 size_t num_filters;
1205 uint8_t cont_state_size, next_svc = 0U, next_att = 0U;
1206 bool dry_run = false;
1207
1208 res = find_services(buf, matching_recs);
1209 if (res) {
1210 return res;
1211 }
1212
1213 if (buf->len < 2) {
1214 LOG_WRN("Malformed packet");
1215 return BT_SDP_INVALID_SYNTAX;
1216 }
1217
1218 max_att_len = net_buf_pull_be16(buf);
1219
1220 /* Set up the filters */
1221 res = get_att_search_list(buf, filter, ARRAY_SIZE(filter), &num_filters);
1222
1223 if (res) {
1224 /* Error in parsing */
1225 return res;
1226 }
1227
1228 if (buf->len < 1) {
1229 LOG_WRN("Malformed packet");
1230 return BT_SDP_INVALID_SYNTAX;
1231 }
1232
1233 cont_state_size = net_buf_pull_u8(buf);
1234
1235 /* We only send out 2 bytes continuation state in responses,
1236 * so expect only 2 bytes in requests
1237 */
1238 if (cont_state_size) {
1239 if (cont_state_size != SDP_SSA_CONT_STATE_SIZE) {
1240 LOG_WRN("Invalid cont state size %u", cont_state_size);
1241 return BT_SDP_INVALID_CSTATE;
1242 }
1243
1244 if (buf->len < cont_state_size) {
1245 LOG_WRN("Malformed packet");
1246 return BT_SDP_INVALID_SYNTAX;
1247 }
1248
1249 state.current_svc = net_buf_pull_u8(buf);
1250 state.last_att = net_buf_pull_u8(buf) + 1;
1251 next_svc = state.current_svc;
1252 next_att = state.last_att;
1253 }
1254
1255 LOG_DBG("max_att_len 0x%04x, state.current_svc %u, state.last_att %u", max_att_len,
1256 state.current_svc, state.last_att);
1257
1258 rsp_buf = bt_sdp_create_pdu();
1259
1260 rsp = net_buf_add(rsp_buf, sizeof(*rsp));
1261
1262 /* Add headers only if this is not a partial response */
1263 if (!cont_state_size) {
1264 seq = net_buf_add(rsp_buf, sizeof(*seq));
1265 seq->type = BT_SDP_SEQ16;
1266 seq->size = 0U;
1267
1268 /* 3 bytes for Outer Data Element Sequence declaration */
1269 att_list_len = 3U;
1270 }
1271
1272 rsp_buf_cpy = rsp_buf;
1273
1274 for (; next_svc < num_services; next_svc++) {
1275 record = matching_recs[next_svc];
1276
1277 if (!record) {
1278 continue;
1279 }
1280
1281 att_list_len += create_attr_list(sdp, record, filter,
1282 num_filters, max_att_len,
1283 SDP_SSA_CONT_STATE_SIZE + 1,
1284 next_att, &state, rsp_buf_cpy);
1285
1286 /* Check if packet is full and not dry run */
1287 if (state.pkt_full && !dry_run) {
1288 LOG_DBG("Packet full, state.last_att %u", state.last_att);
1289 dry_run = true;
1290
1291 /* Add continuation state */
1292 net_buf_add_u8(rsp_buf, 2);
1293 net_buf_add_u8(rsp_buf, state.current_svc);
1294 net_buf_add_u8(rsp_buf, state.last_att);
1295
1296 /* Break if it's not a partial response, else dry-run
1297 * Dry run: Look for other services that match
1298 */
1299 if (cont_state_size) {
1300 break;
1301 }
1302
1303 rsp_buf_cpy = NULL;
1304 }
1305
1306 next_att = 0U;
1307 }
1308
1309 if (!dry_run) {
1310 if (!att_list_len) {
1311 /* For empty responses, add an empty data elem seq */
1312 net_buf_add_u8(rsp_buf, BT_SDP_SEQ8);
1313 net_buf_add_u8(rsp_buf, 0);
1314 att_list_len = 2U;
1315 }
1316 /* Search exhausted */
1317 net_buf_add_u8(rsp_buf, 0);
1318 }
1319
1320 rsp->att_list_len = sys_cpu_to_be16(att_list_len);
1321 if (seq) {
1322 seq->size = sys_cpu_to_be16(state.att_list_size);
1323 }
1324
1325 LOG_DBG("Sending response, len %u", rsp_buf->len);
1326 bt_sdp_send(&sdp->chan.chan, rsp_buf, BT_SDP_SVC_SEARCH_ATTR_RSP,
1327 tid);
1328
1329 return 0;
1330 }
1331
1332 static const struct {
1333 uint8_t op_code;
1334 uint16_t (*func)(struct bt_sdp *sdp, struct net_buf *buf, uint16_t tid);
1335 } handlers[] = {
1336 { BT_SDP_SVC_SEARCH_REQ, sdp_svc_search_req },
1337 { BT_SDP_SVC_ATTR_REQ, sdp_svc_att_req },
1338 { BT_SDP_SVC_SEARCH_ATTR_REQ, sdp_svc_search_att_req },
1339 };
1340
1341 /* @brief Callback for SDP data receive
1342 *
1343 * Gets called when an SDP PDU is received. Calls the corresponding handler
1344 * based on the op code of the PDU.
1345 *
1346 * @param chan L2CAP channel
1347 * @param buf Received PDU
1348 *
1349 * @return None
1350 */
bt_sdp_recv(struct bt_l2cap_chan * chan,struct net_buf * buf)1351 static int bt_sdp_recv(struct bt_l2cap_chan *chan, struct net_buf *buf)
1352 {
1353 struct bt_l2cap_br_chan *ch = CONTAINER_OF(chan,
1354 struct bt_l2cap_br_chan, chan);
1355 struct bt_sdp *sdp = CONTAINER_OF(ch, struct bt_sdp, chan);
1356 struct bt_sdp_hdr *hdr;
1357 uint16_t err = BT_SDP_INVALID_SYNTAX;
1358 size_t i;
1359
1360 LOG_DBG("chan %p, ch %p, cid 0x%04x", chan, ch, ch->tx.cid);
1361
1362 BT_ASSERT(sdp);
1363
1364 if (buf->len < sizeof(*hdr)) {
1365 LOG_ERR("Too small SDP PDU received");
1366 return 0;
1367 }
1368
1369 hdr = net_buf_pull_mem(buf, sizeof(*hdr));
1370 LOG_DBG("Received SDP code 0x%02x len %u", hdr->op_code, buf->len);
1371
1372 if (sys_cpu_to_be16(hdr->param_len) != buf->len) {
1373 err = BT_SDP_INVALID_PDU_SIZE;
1374 } else {
1375 for (i = 0; i < ARRAY_SIZE(handlers); i++) {
1376 if (hdr->op_code != handlers[i].op_code) {
1377 continue;
1378 }
1379
1380 err = handlers[i].func(sdp, buf, sys_be16_to_cpu(hdr->tid));
1381 break;
1382 }
1383 }
1384
1385 if (err) {
1386 LOG_WRN("SDP error 0x%02x", err);
1387 send_err_rsp(chan, err, sys_be16_to_cpu(hdr->tid));
1388 }
1389
1390 return 0;
1391 }
1392
1393 /* @brief Callback for SDP connection accept
1394 *
1395 * Gets called when an incoming SDP connection needs to be authorized.
1396 * Registers the L2CAP callbacks and allocates an SDP context to the connection
1397 *
1398 * @param conn BT connection object
1399 * @param chan L2CAP channel structure (to be returned)
1400 *
1401 * @return 0 for success, or relevant error code
1402 */
bt_sdp_accept(struct bt_conn * conn,struct bt_l2cap_server * server,struct bt_l2cap_chan ** chan)1403 static int bt_sdp_accept(struct bt_conn *conn, struct bt_l2cap_server *server,
1404 struct bt_l2cap_chan **chan)
1405 {
1406 static const struct bt_l2cap_chan_ops ops = {
1407 .connected = bt_sdp_connected,
1408 .disconnected = bt_sdp_disconnected,
1409 .recv = bt_sdp_recv,
1410 };
1411 int i;
1412
1413 LOG_DBG("conn %p", conn);
1414
1415 for (i = 0; i < ARRAY_SIZE(bt_sdp_pool); i++) {
1416 struct bt_sdp *sdp = &bt_sdp_pool[i];
1417
1418 if (sdp->chan.chan.conn) {
1419 continue;
1420 }
1421
1422 sdp->chan.chan.ops = &ops;
1423 sdp->chan.rx.mtu = SDP_MTU;
1424
1425 *chan = &sdp->chan.chan;
1426
1427 return 0;
1428 }
1429
1430 LOG_ERR("No available SDP context for conn %p", conn);
1431
1432 return -ENOMEM;
1433 }
1434
bt_sdp_init(void)1435 void bt_sdp_init(void)
1436 {
1437 static struct bt_l2cap_server server = {
1438 .psm = SDP_PSM,
1439 .accept = bt_sdp_accept,
1440 .sec_level = BT_SECURITY_L0,
1441 };
1442 int res;
1443
1444 res = bt_l2cap_br_server_register(&server);
1445 if (res) {
1446 LOG_ERR("L2CAP server registration failed with error %d", res);
1447 }
1448 }
1449
bt_sdp_register_service(struct bt_sdp_record * service)1450 int bt_sdp_register_service(struct bt_sdp_record *service)
1451 {
1452 uint32_t handle = SDP_SERVICE_HANDLE_BASE;
1453
1454 if (!service) {
1455 LOG_ERR("No service record specified");
1456 return 0;
1457 }
1458
1459 if (num_services == BT_SDP_MAX_SERVICES) {
1460 LOG_ERR("Reached max allowed registrations");
1461 return -ENOMEM;
1462 }
1463
1464 if (db) {
1465 handle = db->handle + 1;
1466 }
1467
1468 service->next = db;
1469 service->index = num_services++;
1470 service->handle = handle;
1471 *((uint32_t *)(service->attrs[0].val.data)) = handle;
1472 db = service;
1473
1474 LOG_DBG("Service registered at %u", handle);
1475
1476 return 0;
1477 }
1478
1479 #define GET_PARAM(__node) \
1480 CONTAINER_OF(__node, struct bt_sdp_discover_params, _node)
1481
1482 /* ServiceSearch PDU, ref to BT Core 5.4, Vol 3, part B, 4.5.1 */
sdp_client_ss_search(struct bt_sdp_client * session,const struct bt_sdp_discover_params * param)1483 static int sdp_client_ss_search(struct bt_sdp_client *session,
1484 const struct bt_sdp_discover_params *param)
1485 {
1486 struct net_buf *buf;
1487
1488 buf = bt_sdp_create_pdu();
1489
1490 /* BT_SDP_SEQ8 means length of sequence is on additional next byte */
1491 net_buf_add_u8(buf, BT_SDP_SEQ8);
1492
1493 switch (param->uuid->type) {
1494 case BT_UUID_TYPE_16:
1495 /* Seq length */
1496 net_buf_add_u8(buf, 0x03);
1497 /* Seq type */
1498 net_buf_add_u8(buf, BT_SDP_UUID16);
1499 /* Seq value */
1500 net_buf_add_be16(buf, BT_UUID_16(param->uuid)->val);
1501 break;
1502 case BT_UUID_TYPE_32:
1503 net_buf_add_u8(buf, 0x05);
1504 net_buf_add_u8(buf, BT_SDP_UUID32);
1505 net_buf_add_be32(buf, BT_UUID_32(param->uuid)->val);
1506 break;
1507 case BT_UUID_TYPE_128:
1508 net_buf_add_u8(buf, 0x11);
1509 net_buf_add_u8(buf, BT_SDP_UUID128);
1510 net_buf_add_mem(buf, BT_UUID_128(param->uuid)->val,
1511 ARRAY_SIZE(BT_UUID_128(param->uuid)->val));
1512 break;
1513 default:
1514 LOG_ERR("Unknown UUID type %u", param->uuid->type);
1515 return -EINVAL;
1516 }
1517
1518 /* Set maximum number of service record handles */
1519 net_buf_add_be16(buf, net_buf_tailroom(session->rec_buf) / SDP_RECORD_HANDLE_SIZE);
1520 /*
1521 * Update and validate PDU ContinuationState. Initial SSA Request has
1522 * zero length continuation state since no interaction has place with
1523 * server so far, otherwise use the original state taken from remote's
1524 * last response PDU that is cached by SDP client context.
1525 */
1526 if (session->cstate.length == 0U) {
1527 net_buf_add_u8(buf, 0x00);
1528 } else {
1529 net_buf_add_u8(buf, session->cstate.length);
1530 net_buf_add_mem(buf, session->cstate.data, session->cstate.length);
1531 }
1532
1533 /* Update context param to the one being resolving now */
1534 session->param = param;
1535 session->tid++;
1536
1537 return bt_sdp_send(&session->chan.chan, buf, BT_SDP_SVC_SEARCH_REQ, session->tid);
1538 }
1539
1540 /* ServiceAttribute PDU, ref to BT Core 5.4, Vol 3, part B, 4.6.1 */
sdp_client_sa_search(struct bt_sdp_client * session,const struct bt_sdp_discover_params * param)1541 static int sdp_client_sa_search(struct bt_sdp_client *session,
1542 const struct bt_sdp_discover_params *param)
1543 {
1544 struct net_buf *buf;
1545
1546 buf = bt_sdp_create_pdu();
1547
1548 /* Add service record handle */
1549 net_buf_add_be32(buf, param->handle);
1550
1551 /* Set attribute max bytes count to be returned from server */
1552 net_buf_add_be16(buf, net_buf_tailroom(session->rec_buf));
1553 /*
1554 * Sequence definition where data is sequence of elements and where
1555 * additional next byte points the size of elements within
1556 */
1557 net_buf_add_u8(buf, BT_SDP_SEQ8);
1558 net_buf_add_u8(buf, 0x05);
1559 /* Data element definition for two following 16bits range elements */
1560 net_buf_add_u8(buf, BT_SDP_UINT32);
1561 /* Get all attributes. It enables filter out wanted only attributes */
1562 net_buf_add_be16(buf, 0x0000);
1563 net_buf_add_be16(buf, 0xffff);
1564
1565 /*
1566 * Update and validate PDU ContinuationState. Initial SSA Request has
1567 * zero length continuation state since no interaction has place with
1568 * server so far, otherwise use the original state taken from remote's
1569 * last response PDU that is cached by SDP client context.
1570 */
1571 if (session->cstate.length == 0U) {
1572 net_buf_add_u8(buf, 0x00);
1573 } else {
1574 net_buf_add_u8(buf, session->cstate.length);
1575 net_buf_add_mem(buf, session->cstate.data, session->cstate.length);
1576 }
1577
1578 /* Update context param to the one being resolving now */
1579 session->param = param;
1580 session->tid++;
1581
1582 return bt_sdp_send(&session->chan.chan, buf, BT_SDP_SVC_ATTR_REQ, session->tid);
1583 }
1584
1585 /* ServiceSearchAttribute PDU, ref to BT Core 4.2, Vol 3, part B, 4.7.1 */
sdp_client_ssa_search(struct bt_sdp_client * session,const struct bt_sdp_discover_params * param)1586 static int sdp_client_ssa_search(struct bt_sdp_client *session,
1587 const struct bt_sdp_discover_params *param)
1588 {
1589 struct net_buf *buf;
1590
1591 buf = bt_sdp_create_pdu();
1592
1593 /* BT_SDP_SEQ8 means length of sequence is on additional next byte */
1594 net_buf_add_u8(buf, BT_SDP_SEQ8);
1595
1596 switch (param->uuid->type) {
1597 case BT_UUID_TYPE_16:
1598 /* Seq length */
1599 net_buf_add_u8(buf, 0x03);
1600 /* Seq type */
1601 net_buf_add_u8(buf, BT_SDP_UUID16);
1602 /* Seq value */
1603 net_buf_add_be16(buf, BT_UUID_16(param->uuid)->val);
1604 break;
1605 case BT_UUID_TYPE_32:
1606 net_buf_add_u8(buf, 0x05);
1607 net_buf_add_u8(buf, BT_SDP_UUID32);
1608 net_buf_add_be32(buf, BT_UUID_32(param->uuid)->val);
1609 break;
1610 case BT_UUID_TYPE_128:
1611 net_buf_add_u8(buf, 0x11);
1612 net_buf_add_u8(buf, BT_SDP_UUID128);
1613 net_buf_add_mem(buf, BT_UUID_128(param->uuid)->val,
1614 ARRAY_SIZE(BT_UUID_128(param->uuid)->val));
1615 break;
1616 default:
1617 LOG_ERR("Unknown UUID type %u", param->uuid->type);
1618 return -EINVAL;
1619 }
1620
1621 /* Set attribute max bytes count to be returned from server */
1622 net_buf_add_be16(buf, net_buf_tailroom(session->rec_buf));
1623 /*
1624 * Sequence definition where data is sequence of elements and where
1625 * additional next byte points the size of elements within
1626 */
1627 net_buf_add_u8(buf, BT_SDP_SEQ8);
1628 net_buf_add_u8(buf, 0x05);
1629 /* Data element definition for two following 16bits range elements */
1630 net_buf_add_u8(buf, BT_SDP_UINT32);
1631 /* Get all attributes. It enables filter out wanted only attributes */
1632 net_buf_add_be16(buf, 0x0000);
1633 net_buf_add_be16(buf, 0xffff);
1634
1635 /*
1636 * Update and validate PDU ContinuationState. Initial SSA Request has
1637 * zero length continuation state since no interaction has place with
1638 * server so far, otherwise use the original state taken from remote's
1639 * last response PDU that is cached by SDP client context.
1640 */
1641 if (session->cstate.length == 0U) {
1642 net_buf_add_u8(buf, 0x00);
1643 } else {
1644 net_buf_add_u8(buf, session->cstate.length);
1645 net_buf_add_mem(buf, session->cstate.data,
1646 session->cstate.length);
1647 }
1648
1649 /* Update context param to the one being resolving now */
1650 session->param = param;
1651 session->tid++;
1652
1653 return bt_sdp_send(&session->chan.chan, buf, BT_SDP_SVC_SEARCH_ATTR_REQ,
1654 session->tid);
1655 }
1656
1657 static void sdp_client_params_iterator(struct bt_sdp_client *session);
1658
sdp_client_discover(struct bt_sdp_client * session)1659 static int sdp_client_discover(struct bt_sdp_client *session)
1660 {
1661 const struct bt_sdp_discover_params *param;
1662 int err;
1663
1664 /*
1665 * Select proper user params, if session->param is invalid it means
1666 * getting new UUID from top of to be resolved params list. Otherwise
1667 * the context is in a middle of partial SDP PDU responses and cached
1668 * value from context can be used.
1669 */
1670 if (!session->param) {
1671 param = GET_PARAM(sys_slist_peek_head(&session->reqs));
1672 } else {
1673 param = session->param;
1674 }
1675
1676 if (!param) {
1677 struct bt_l2cap_chan *chan = &session->chan.chan;
1678
1679 LOG_WRN("No more request, disconnect channel");
1680 /* No UUID items, disconnect channel */
1681 return bt_l2cap_chan_disconnect(chan);
1682 }
1683
1684 switch (param->type) {
1685 case BT_SDP_DISCOVER_SERVICE_SEARCH:
1686 err = sdp_client_ss_search(session, param);
1687 break;
1688 case BT_SDP_DISCOVER_SERVICE_ATTR:
1689 err = sdp_client_sa_search(session, param);
1690 break;
1691 case BT_SDP_DISCOVER_SERVICE_SEARCH_ATTR:
1692 err = sdp_client_ssa_search(session, param);
1693 break;
1694 default:
1695 err = -EINVAL;
1696 break;
1697 }
1698
1699 if (err) {
1700 /* Get next UUID and start resolving it */
1701 sdp_client_params_iterator(session);
1702 }
1703
1704 return 0;
1705 }
1706
sdp_client_params_iterator(struct bt_sdp_client * session)1707 static void sdp_client_params_iterator(struct bt_sdp_client *session)
1708 {
1709 struct bt_l2cap_chan *chan = &session->chan.chan;
1710 struct bt_sdp_discover_params *param, *tmp;
1711
1712 SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&session->reqs, param, tmp, _node) {
1713 if (param != session->param) {
1714 continue;
1715 }
1716
1717 LOG_DBG("");
1718
1719 /* Remove already checked UUID node */
1720 sys_slist_remove(&session->reqs, NULL, ¶m->_node);
1721 /* Invalidate cached param in context */
1722 session->param = NULL;
1723 /* Reset continuation state in current context */
1724 (void)memset(&session->cstate, 0, sizeof(session->cstate));
1725
1726 /* Check if there's valid next UUID */
1727 if (!sys_slist_is_empty(&session->reqs)) {
1728 sdp_client_discover(session);
1729 return;
1730 }
1731
1732 /* No UUID items, disconnect channel */
1733 bt_l2cap_chan_disconnect(chan);
1734 break;
1735 }
1736 }
1737
sdp_client_get_total(struct bt_sdp_client * session,struct net_buf * buf,uint16_t * total)1738 static uint16_t sdp_client_get_total(struct bt_sdp_client *session,
1739 struct net_buf *buf, uint16_t *total)
1740 {
1741 uint16_t pulled;
1742 uint8_t seq;
1743
1744 /*
1745 * Pull value of total octets of all attributes available to be
1746 * collected when response gets completed for given UUID. Such info can
1747 * be get from the very first response frame after initial SSA request
1748 * was sent. For subsequent calls related to the same SSA request input
1749 * buf and in/out function parameters stays neutral.
1750 */
1751 if (session->cstate.length == 0U) {
1752 seq = net_buf_pull_u8(buf);
1753 pulled = 1U;
1754 switch (seq) {
1755 case BT_SDP_SEQ8:
1756 *total = net_buf_pull_u8(buf);
1757 pulled += 1U;
1758 break;
1759 case BT_SDP_SEQ16:
1760 *total = net_buf_pull_be16(buf);
1761 pulled += 2U;
1762 break;
1763 case BT_SDP_SEQ32:
1764 *total = net_buf_pull_be32(buf);
1765 pulled += 4U;
1766 break;
1767 default:
1768 LOG_WRN("Sequence type 0x%02x not handled", seq);
1769 *total = 0U;
1770 break;
1771 }
1772
1773 LOG_DBG("Total %u octets of all attributes", *total);
1774 } else {
1775 pulled = 0U;
1776 *total = 0U;
1777 }
1778
1779 return pulled;
1780 }
1781
get_ss_record_len(struct net_buf * buf)1782 static uint16_t get_ss_record_len(struct net_buf *buf)
1783 {
1784 if (buf->len >= SDP_RECORD_HANDLE_SIZE) {
1785 return SDP_RECORD_HANDLE_SIZE;
1786 }
1787
1788 LOG_WRN("Invalid service record handle length");
1789 return 0;
1790 }
1791
get_ssa_record_len(struct net_buf * buf)1792 static uint16_t get_ssa_record_len(struct net_buf *buf)
1793 {
1794 uint16_t len;
1795 uint8_t seq;
1796
1797 seq = net_buf_pull_u8(buf);
1798
1799 switch (seq) {
1800 case BT_SDP_SEQ8:
1801 len = net_buf_pull_u8(buf);
1802 break;
1803 case BT_SDP_SEQ16:
1804 len = net_buf_pull_be16(buf);
1805 break;
1806 case BT_SDP_SEQ32:
1807 len = net_buf_pull_be32(buf);
1808 break;
1809 default:
1810 LOG_WRN("Sequence type 0x%02x not handled", seq);
1811 len = 0U;
1812 break;
1813 }
1814
1815 return len;
1816 }
1817
get_record_len(struct bt_sdp_client * session)1818 static uint16_t get_record_len(struct bt_sdp_client *session)
1819 {
1820 struct net_buf *buf;
1821 uint16_t len;
1822
1823 buf = session->rec_buf;
1824
1825 if (!session->param) {
1826 return buf->len;
1827 }
1828
1829 switch (session->param->type) {
1830 case BT_SDP_DISCOVER_SERVICE_SEARCH:
1831 len = get_ss_record_len(buf);
1832 break;
1833 case BT_SDP_DISCOVER_SERVICE_SEARCH_ATTR:
1834 len = get_ssa_record_len(buf);
1835 break;
1836 case BT_SDP_DISCOVER_SERVICE_ATTR:
1837 default:
1838 len = buf->len;
1839 break;
1840 }
1841
1842 LOG_DBG("Record len %u", len);
1843
1844 return len;
1845 }
1846
1847 enum uuid_state {
1848 UUID_NOT_RESOLVED,
1849 UUID_RESOLVED,
1850 };
1851
sdp_client_notify_result(struct bt_sdp_client * session,enum uuid_state state)1852 static void sdp_client_notify_result(struct bt_sdp_client *session,
1853 enum uuid_state state)
1854 {
1855 struct bt_conn *conn = session->chan.chan.conn;
1856 struct bt_sdp_client_result result;
1857 uint16_t rec_len;
1858 uint8_t user_ret;
1859
1860 if (state == UUID_NOT_RESOLVED) {
1861 result.resp_buf = NULL;
1862 result.next_record_hint = false;
1863 session->param->func(conn, &result, session->param);
1864 return;
1865 }
1866
1867 while (session->rec_buf->len) {
1868 struct net_buf_simple_state buf_state;
1869
1870 rec_len = get_record_len(session);
1871 /* tell the user about multi record resolution */
1872 if (session->rec_buf->len > rec_len) {
1873 result.next_record_hint = true;
1874 } else {
1875 result.next_record_hint = false;
1876 }
1877
1878 /* save the original session buffer */
1879 net_buf_simple_save(&session->rec_buf->b, &buf_state);
1880 /* initialize internal result buffer instead of memcpy */
1881 result.resp_buf = session->rec_buf;
1882 /*
1883 * Set user internal result buffer length as same as record
1884 * length to fake user. User will see the individual record
1885 * length as rec_len instead of whole session rec_buf length.
1886 */
1887 result.resp_buf->len = rec_len;
1888
1889 user_ret = session->param->func(conn, &result, session->param);
1890
1891 /* restore original session buffer */
1892 net_buf_simple_restore(&session->rec_buf->b, &buf_state);
1893 /*
1894 * sync session buffer data length with next record chunk not
1895 * send to user so far
1896 */
1897 net_buf_pull(session->rec_buf, rec_len);
1898 if (user_ret == BT_SDP_DISCOVER_UUID_STOP) {
1899 break;
1900 }
1901 }
1902 }
1903
sdp_client_receive_ss(struct bt_sdp_client * session,struct net_buf * buf)1904 static int sdp_client_receive_ss(struct bt_sdp_client *session, struct net_buf *buf)
1905 {
1906 struct bt_sdp_pdu_cstate *cstate;
1907 uint16_t current_count;
1908 uint16_t total_count;
1909 uint32_t record_len;
1910 uint32_t received_count;
1911
1912 /* Check the buffer len for the total_count field */
1913 if (buf->len < sizeof(total_count)) {
1914 LOG_ERR("Invalid frame payload length");
1915 return 0;
1916 }
1917
1918 /* Get total service record count. */
1919 total_count = net_buf_pull_be16(buf);
1920
1921 /* Check the buffer len for the current_count field */
1922 if (buf->len < sizeof(current_count)) {
1923 LOG_ERR("Invalid frame payload length");
1924 return 0;
1925 }
1926
1927 /* Get current service record count. */
1928 current_count = net_buf_pull_be16(buf);
1929 /* Check valid of current service record count */
1930 if (current_count > total_count) {
1931 LOG_ERR("Invalid current service record count");
1932 return 0;
1933 }
1934
1935 received_count = session->rec_buf->len / SDP_RECORD_HANDLE_SIZE;
1936 if ((received_count + current_count) > total_count) {
1937 LOG_ERR("Excess data received");
1938 return 0;
1939 }
1940
1941 record_len = current_count * SDP_RECORD_HANDLE_SIZE;
1942 if (record_len >= buf->len) {
1943 LOG_ERR("Invalid packet");
1944 return 0;
1945 }
1946
1947 /* Get PDU continuation state */
1948 cstate = (struct bt_sdp_pdu_cstate *)(buf->data + record_len);
1949
1950 if (cstate->length > BT_SDP_MAX_PDU_CSTATE_LEN) {
1951 LOG_ERR("Invalid SDP PDU Continuation State length %u", cstate->length);
1952 return 0;
1953 }
1954
1955 if ((record_len + SDP_CONT_STATE_LEN_SIZE + cstate->length) > buf->len) {
1956 LOG_ERR("Invalid payload length");
1957 return 0;
1958 }
1959
1960 /*
1961 * No record found for given UUID. The check catches case when
1962 * current response frame has Continuation State shortest and
1963 * valid and this is the first response frame as well.
1964 */
1965 if (!current_count && cstate->length == 0U && session->cstate.length == 0U) {
1966 LOG_DBG("Service record handle 0x%x not found", session->param->handle);
1967 /* Call user UUID handler */
1968 sdp_client_notify_result(session, UUID_NOT_RESOLVED);
1969 net_buf_pull(buf, sizeof(cstate->length));
1970 goto iterate;
1971 }
1972
1973 if (record_len > net_buf_tailroom(session->rec_buf)) {
1974 LOG_WRN("Not enough room for getting records data");
1975 goto iterate;
1976 }
1977
1978 net_buf_add_mem(session->rec_buf, buf->data, record_len);
1979 net_buf_pull(buf, record_len);
1980
1981 /* check if current response says there's next portion to be fetched */
1982 if (cstate->length) {
1983 /* Cache original Continuation State in context */
1984 memcpy(&session->cstate, cstate, sizeof(struct bt_sdp_pdu_cstate));
1985
1986 net_buf_pull(buf, cstate->length + sizeof(cstate->length));
1987
1988 /* Request for next portion of attributes data */
1989 return sdp_client_discover(session);
1990 }
1991
1992 net_buf_pull(buf, sizeof(cstate->length));
1993
1994 LOG_DBG("UUID 0x%s resolved", bt_uuid_str(session->param->uuid));
1995 sdp_client_notify_result(session, UUID_RESOLVED);
1996 iterate:
1997 /* Get next UUID and start resolving it */
1998 sdp_client_params_iterator(session);
1999
2000 return 0;
2001 }
2002
sdp_client_receive_ssa_sa(struct bt_sdp_client * session,struct net_buf * buf)2003 static int sdp_client_receive_ssa_sa(struct bt_sdp_client *session, struct net_buf *buf)
2004 {
2005 struct bt_sdp_pdu_cstate *cstate;
2006 uint16_t frame_len;
2007 uint16_t total;
2008
2009 /* Check the buffer len for the frame_len field */
2010 if (buf->len < sizeof(frame_len)) {
2011 LOG_ERR("Invalid frame payload length");
2012 return 0;
2013 }
2014
2015 /* Get number of attributes in this frame. */
2016 frame_len = net_buf_pull_be16(buf);
2017 /* Check valid buf len for attribute list and cont state */
2018 if (buf->len < frame_len + SDP_CONT_STATE_LEN_SIZE) {
2019 LOG_ERR("Invalid frame payload length");
2020 return 0;
2021 }
2022 /* Check valid range of attributes length */
2023 if (frame_len < 2) {
2024 LOG_ERR("Invalid attributes data length");
2025 return 0;
2026 }
2027
2028 /* Get PDU continuation state */
2029 cstate = (struct bt_sdp_pdu_cstate *)(buf->data + frame_len);
2030
2031 if (cstate->length > BT_SDP_MAX_PDU_CSTATE_LEN) {
2032 LOG_ERR("Invalid SDP PDU Continuation State length %u", cstate->length);
2033 return 0;
2034 }
2035
2036 if ((frame_len + SDP_CONT_STATE_LEN_SIZE + cstate->length) > buf->len) {
2037 LOG_ERR("Invalid frame payload length");
2038 return 0;
2039 }
2040
2041 /*
2042 * No record found for given UUID. The check catches case when
2043 * current response frame has Continuation State shortest and
2044 * valid and this is the first response frame as well.
2045 */
2046 if (frame_len == 2U && cstate->length == 0U && session->cstate.length == 0U) {
2047 LOG_DBG("Record for UUID 0x%s not found", bt_uuid_str(session->param->uuid));
2048 /* Call user UUID handler */
2049 sdp_client_notify_result(session, UUID_NOT_RESOLVED);
2050 net_buf_pull(buf, frame_len + sizeof(cstate->length));
2051 goto iterate;
2052 }
2053
2054 /* Get total value of all attributes to be collected */
2055 frame_len -= sdp_client_get_total(session, buf, &total);
2056
2057 if (total > net_buf_tailroom(session->rec_buf)) {
2058 LOG_WRN("Not enough room for getting records data");
2059 goto iterate;
2060 }
2061
2062 net_buf_add_mem(session->rec_buf, buf->data, frame_len);
2063 net_buf_pull(buf, frame_len);
2064
2065 /* check if current response says there's next portion to be fetched */
2066 if (cstate->length) {
2067 /* Cache original Continuation State in context */
2068 memcpy(&session->cstate, cstate, sizeof(struct bt_sdp_pdu_cstate));
2069
2070 net_buf_pull(buf, cstate->length + sizeof(cstate->length));
2071
2072 /* Request for next portion of attributes data */
2073 return sdp_client_discover(session);
2074 }
2075
2076 net_buf_pull(buf, sizeof(cstate->length));
2077
2078 LOG_DBG("UUID 0x%s resolved", bt_uuid_str(session->param->uuid));
2079 sdp_client_notify_result(session, UUID_RESOLVED);
2080 iterate:
2081 /* Get next UUID and start resolving it */
2082 sdp_client_params_iterator(session);
2083
2084 return 0;
2085 }
2086
sdp_client_receive(struct bt_l2cap_chan * chan,struct net_buf * buf)2087 static int sdp_client_receive(struct bt_l2cap_chan *chan, struct net_buf *buf)
2088 {
2089 struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
2090 struct bt_sdp_hdr *hdr;
2091 uint16_t len, tid;
2092
2093 LOG_DBG("session %p buf %p", session, buf);
2094
2095 if (buf->len < sizeof(*hdr)) {
2096 LOG_ERR("Too small SDP PDU");
2097 return 0;
2098 }
2099
2100 hdr = net_buf_pull_mem(buf, sizeof(*hdr));
2101 len = sys_be16_to_cpu(hdr->param_len);
2102 tid = sys_be16_to_cpu(hdr->tid);
2103
2104 LOG_DBG("SDP PDU tid %u len %u", tid, len);
2105
2106 if (buf->len != len) {
2107 LOG_ERR("SDP PDU length mismatch (%u != %u)", buf->len, len);
2108 return 0;
2109 }
2110
2111 if (tid != session->tid) {
2112 LOG_ERR("Mismatch transaction ID value in SDP PDU");
2113 return 0;
2114 }
2115
2116 switch (hdr->op_code) {
2117 case BT_SDP_SVC_SEARCH_RSP:
2118 return sdp_client_receive_ss(session, buf);
2119 case BT_SDP_SVC_ATTR_RSP:
2120 __fallthrough;
2121 case BT_SDP_SVC_SEARCH_ATTR_RSP:
2122 return sdp_client_receive_ssa_sa(session, buf);
2123 case BT_SDP_ERROR_RSP:
2124 LOG_INF("Invalid SDP request");
2125 sdp_client_notify_result(session, UUID_NOT_RESOLVED);
2126 sdp_client_params_iterator(session);
2127 return 0;
2128 default:
2129 LOG_DBG("PDU 0x%0x response not handled", hdr->op_code);
2130 break;
2131 }
2132
2133 return 0;
2134 }
2135
sdp_client_chan_connect(struct bt_sdp_client * session)2136 static int sdp_client_chan_connect(struct bt_sdp_client *session)
2137 {
2138 return bt_l2cap_br_chan_connect(session->chan.chan.conn, &session->chan.chan, SDP_PSM);
2139 }
2140
sdp_client_alloc_buf(struct bt_l2cap_chan * chan)2141 static struct net_buf *sdp_client_alloc_buf(struct bt_l2cap_chan *chan)
2142 {
2143 struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
2144 struct net_buf *buf;
2145
2146 LOG_DBG("session %p chan %p", session, chan);
2147
2148 session->param = GET_PARAM(sys_slist_peek_head(&session->reqs));
2149
2150 buf = net_buf_alloc(session->param->pool, K_FOREVER);
2151 __ASSERT_NO_MSG(buf);
2152
2153 return buf;
2154 }
2155
sdp_client_connected(struct bt_l2cap_chan * chan)2156 static void sdp_client_connected(struct bt_l2cap_chan *chan)
2157 {
2158 struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
2159
2160 LOG_DBG("session %p chan %p connected", session, chan);
2161
2162 session->rec_buf = chan->ops->alloc_buf(chan);
2163 if (!session->rec_buf) {
2164 bt_l2cap_chan_disconnect(chan);
2165 return;
2166 }
2167
2168 sdp_client_discover(session);
2169 }
2170
sdp_client_disconnected(struct bt_l2cap_chan * chan)2171 static void sdp_client_disconnected(struct bt_l2cap_chan *chan)
2172 {
2173 struct bt_sdp_client *session = SDP_CLIENT_CHAN(chan);
2174
2175 LOG_DBG("session %p chan %p disconnected", session, chan);
2176
2177 if (session->rec_buf) {
2178 net_buf_unref(session->rec_buf);
2179 }
2180
2181 /*
2182 * Reset session excluding L2CAP channel member. Let's the channel
2183 * resets autonomous.
2184 */
2185 (void)memset(&session->reqs, 0,
2186 sizeof(*session) - sizeof(session->chan));
2187 }
2188
2189 static const struct bt_l2cap_chan_ops sdp_client_chan_ops = {
2190 .connected = sdp_client_connected,
2191 .disconnected = sdp_client_disconnected,
2192 .recv = sdp_client_receive,
2193 .alloc_buf = sdp_client_alloc_buf,
2194 };
2195
sdp_client_new_session(struct bt_conn * conn)2196 static struct bt_sdp_client *sdp_client_new_session(struct bt_conn *conn)
2197 {
2198 int i;
2199
2200 for (i = 0; i < ARRAY_SIZE(bt_sdp_client_pool); i++) {
2201 struct bt_sdp_client *session = &bt_sdp_client_pool[i];
2202 int err;
2203
2204 if (session->chan.chan.conn) {
2205 continue;
2206 }
2207
2208 sys_slist_init(&session->reqs);
2209
2210 session->chan.chan.ops = &sdp_client_chan_ops;
2211 session->chan.chan.conn = conn;
2212 session->chan.rx.mtu = SDP_CLIENT_MTU;
2213
2214 err = sdp_client_chan_connect(session);
2215 if (err) {
2216 (void)memset(session, 0, sizeof(*session));
2217 LOG_ERR("Cannot connect %d", err);
2218 return NULL;
2219 }
2220
2221 return session;
2222 }
2223
2224 LOG_ERR("No available SDP client context");
2225
2226 return NULL;
2227 }
2228
sdp_client_get_session(struct bt_conn * conn)2229 static struct bt_sdp_client *sdp_client_get_session(struct bt_conn *conn)
2230 {
2231 int i;
2232
2233 for (i = 0; i < ARRAY_SIZE(bt_sdp_client_pool); i++) {
2234 if (bt_sdp_client_pool[i].chan.chan.conn == conn) {
2235 return &bt_sdp_client_pool[i];
2236 }
2237 }
2238
2239 /*
2240 * Try to allocate session context since not found in pool and attempt
2241 * connect to remote SDP endpoint.
2242 */
2243 return sdp_client_new_session(conn);
2244 }
2245
bt_sdp_discover(struct bt_conn * conn,const struct bt_sdp_discover_params * params)2246 int bt_sdp_discover(struct bt_conn *conn,
2247 const struct bt_sdp_discover_params *params)
2248 {
2249 struct bt_sdp_client *session;
2250
2251 if (!params || !params->uuid || !params->func || !params->pool) {
2252 LOG_WRN("Invalid user params");
2253 return -EINVAL;
2254 }
2255
2256 session = sdp_client_get_session(conn);
2257 if (!session) {
2258 return -ENOMEM;
2259 }
2260
2261 sys_slist_append(&session->reqs, (sys_snode_t *)¶ms->_node);
2262
2263 return 0;
2264 }
2265
2266 /* Helper getting length of data determined by DTD for integers */
sdp_get_int_len(const uint8_t * data,size_t len)2267 static inline ssize_t sdp_get_int_len(const uint8_t *data, size_t len)
2268 {
2269 BT_ASSERT(data);
2270
2271 switch (data[0]) {
2272 case BT_SDP_DATA_NIL:
2273 return 1;
2274 case BT_SDP_BOOL:
2275 case BT_SDP_INT8:
2276 case BT_SDP_UINT8:
2277 if (len < 2) {
2278 break;
2279 }
2280
2281 return 2;
2282 case BT_SDP_INT16:
2283 case BT_SDP_UINT16:
2284 if (len < 3) {
2285 break;
2286 }
2287
2288 return 3;
2289 case BT_SDP_INT32:
2290 case BT_SDP_UINT32:
2291 if (len < 5) {
2292 break;
2293 }
2294
2295 return 5;
2296 case BT_SDP_INT64:
2297 case BT_SDP_UINT64:
2298 if (len < 9) {
2299 break;
2300 }
2301
2302 return 9;
2303 case BT_SDP_INT128:
2304 case BT_SDP_UINT128:
2305 default:
2306 LOG_ERR("Invalid/unhandled DTD 0x%02x", data[0]);
2307 return -EINVAL;
2308 }
2309
2310 LOG_ERR("Too short buffer length %zu", len);
2311 return -EMSGSIZE;
2312 }
2313
2314 /* Helper getting length of data determined by DTD for UUID */
sdp_get_uuid_len(const uint8_t * data,size_t len)2315 static inline ssize_t sdp_get_uuid_len(const uint8_t *data, size_t len)
2316 {
2317 BT_ASSERT(data);
2318
2319 switch (data[0]) {
2320 case BT_SDP_UUID16:
2321 if (len < 3) {
2322 break;
2323 }
2324
2325 return 3;
2326 case BT_SDP_UUID32:
2327 if (len < 5) {
2328 break;
2329 }
2330
2331 return 5;
2332 case BT_SDP_UUID128:
2333 default:
2334 LOG_ERR("Invalid/unhandled DTD 0x%02x", data[0]);
2335 return -EINVAL;
2336 }
2337
2338 LOG_ERR("Too short buffer length %zu", len);
2339 return -EMSGSIZE;
2340 }
2341
2342 /* Helper getting length of data determined by DTD for strings */
sdp_get_str_len(const uint8_t * data,size_t len)2343 static inline ssize_t sdp_get_str_len(const uint8_t *data, size_t len)
2344 {
2345 const uint8_t *pnext;
2346
2347 BT_ASSERT(data);
2348
2349 /* validate len for pnext safe use to read next 8bit value */
2350 if (len < 2) {
2351 goto err;
2352 }
2353
2354 pnext = data + sizeof(uint8_t);
2355
2356 switch (data[0]) {
2357 case BT_SDP_TEXT_STR8:
2358 case BT_SDP_URL_STR8:
2359 if (len < (2 + pnext[0])) {
2360 break;
2361 }
2362
2363 return 2 + pnext[0];
2364 case BT_SDP_TEXT_STR16:
2365 case BT_SDP_URL_STR16:
2366 /* validate len for pnext safe use to read 16bit value */
2367 if (len < 3) {
2368 break;
2369 }
2370
2371 if (len < (3 + sys_get_be16(pnext))) {
2372 break;
2373 }
2374
2375 return 3 + sys_get_be16(pnext);
2376 case BT_SDP_TEXT_STR32:
2377 case BT_SDP_URL_STR32:
2378 default:
2379 LOG_ERR("Invalid/unhandled DTD 0x%02x", data[0]);
2380 return -EINVAL;
2381 }
2382 err:
2383 LOG_ERR("Too short buffer length %zu", len);
2384 return -EMSGSIZE;
2385 }
2386
2387 /* Helper getting length of data determined by DTD for sequences */
sdp_get_seq_len(const uint8_t * data,size_t len)2388 static inline ssize_t sdp_get_seq_len(const uint8_t *data, size_t len)
2389 {
2390 const uint8_t *pnext;
2391
2392 BT_ASSERT(data);
2393
2394 /* validate len for pnext safe use to read 8bit bit value */
2395 if (len < 2) {
2396 goto err;
2397 }
2398
2399 pnext = data + sizeof(uint8_t);
2400
2401 switch (data[0]) {
2402 case BT_SDP_SEQ8:
2403 case BT_SDP_ALT8:
2404 if (len < (2 + pnext[0])) {
2405 break;
2406 }
2407
2408 return 2 + pnext[0];
2409 case BT_SDP_SEQ16:
2410 case BT_SDP_ALT16:
2411 /* validate len for pnext safe use to read 16bit value */
2412 if (len < 3) {
2413 break;
2414 }
2415
2416 if (len < (3 + sys_get_be16(pnext))) {
2417 break;
2418 }
2419
2420 return 3 + sys_get_be16(pnext);
2421 case BT_SDP_SEQ32:
2422 case BT_SDP_ALT32:
2423 default:
2424 LOG_ERR("Invalid/unhandled DTD 0x%02x", data[0]);
2425 return -EINVAL;
2426 }
2427 err:
2428 LOG_ERR("Too short buffer length %zu", len);
2429 return -EMSGSIZE;
2430 }
2431
2432 /* Helper getting length of attribute value data */
sdp_get_attr_value_len(const uint8_t * data,size_t len)2433 static ssize_t sdp_get_attr_value_len(const uint8_t *data, size_t len)
2434 {
2435 BT_ASSERT(data);
2436
2437 LOG_DBG("Attr val DTD 0x%02x", data[0]);
2438
2439 if (len < 1) {
2440 goto err;
2441 }
2442
2443 switch (data[0]) {
2444 case BT_SDP_DATA_NIL:
2445 case BT_SDP_BOOL:
2446 case BT_SDP_UINT8:
2447 case BT_SDP_UINT16:
2448 case BT_SDP_UINT32:
2449 case BT_SDP_UINT64:
2450 case BT_SDP_UINT128:
2451 case BT_SDP_INT8:
2452 case BT_SDP_INT16:
2453 case BT_SDP_INT32:
2454 case BT_SDP_INT64:
2455 case BT_SDP_INT128:
2456 return sdp_get_int_len(data, len);
2457 case BT_SDP_UUID16:
2458 case BT_SDP_UUID32:
2459 case BT_SDP_UUID128:
2460 return sdp_get_uuid_len(data, len);
2461 case BT_SDP_TEXT_STR8:
2462 case BT_SDP_TEXT_STR16:
2463 case BT_SDP_TEXT_STR32:
2464 case BT_SDP_URL_STR8:
2465 case BT_SDP_URL_STR16:
2466 case BT_SDP_URL_STR32:
2467 return sdp_get_str_len(data, len);
2468 case BT_SDP_SEQ8:
2469 case BT_SDP_SEQ16:
2470 case BT_SDP_SEQ32:
2471 case BT_SDP_ALT8:
2472 case BT_SDP_ALT16:
2473 case BT_SDP_ALT32:
2474 return sdp_get_seq_len(data, len);
2475 default:
2476 LOG_ERR("Unknown DTD 0x%02x", data[0]);
2477 return -EINVAL;
2478 }
2479 err:
2480 LOG_ERR("Too short buffer length %zu", len);
2481 return -EMSGSIZE;
2482
2483 }
2484
2485 /* Type holding UUID item and related to it specific information. */
2486 struct bt_sdp_uuid_desc {
2487 union {
2488 struct bt_uuid uuid;
2489 struct bt_uuid_16 uuid16;
2490 struct bt_uuid_32 uuid32;
2491 };
2492 uint16_t attr_id;
2493 uint8_t *params;
2494 uint16_t params_len;
2495 };
2496
2497 /* Generic attribute item collector. */
2498 struct bt_sdp_attr_item {
2499 /* Attribute identifier. */
2500 uint16_t attr_id;
2501 /* Address of beginning attribute value taken from original buffer
2502 * holding response from server.
2503 */
2504 uint8_t *val;
2505 /* Says about the length of attribute value. */
2506 uint16_t len;
2507 };
2508
bt_sdp_get_attr(const struct net_buf * buf,struct bt_sdp_attr_item * attr,uint16_t attr_id)2509 static int bt_sdp_get_attr(const struct net_buf *buf,
2510 struct bt_sdp_attr_item *attr, uint16_t attr_id)
2511 {
2512 uint8_t *data;
2513 uint16_t id;
2514
2515 data = buf->data;
2516 while (data - buf->data < buf->len) {
2517 ssize_t dlen;
2518
2519 /* data need to point to attribute id descriptor field (DTD)*/
2520 if (data[0] != BT_SDP_UINT16) {
2521 LOG_ERR("Invalid descriptor 0x%02x", data[0]);
2522 return -EINVAL;
2523 }
2524
2525 data += sizeof(uint8_t);
2526 if ((data + sizeof(id) - buf->data) > buf->len) {
2527 return -EINVAL;
2528 }
2529 id = sys_get_be16(data);
2530 LOG_DBG("Attribute ID 0x%04x", id);
2531 data += sizeof(uint16_t);
2532
2533 dlen = sdp_get_attr_value_len(data,
2534 buf->len - (data - buf->data));
2535 if (dlen < 0) {
2536 LOG_ERR("Invalid attribute value data");
2537 return -EINVAL;
2538 }
2539
2540 if (id == attr_id) {
2541 LOG_DBG("Attribute ID 0x%04x Value found", id);
2542 /*
2543 * Initialize attribute value buffer data using selected
2544 * data slice from original buffer.
2545 */
2546 attr->val = data;
2547 attr->len = dlen;
2548 attr->attr_id = id;
2549 return 0;
2550 }
2551
2552 data += dlen;
2553 }
2554
2555 return -ENOENT;
2556 }
2557
2558 /* reads SEQ item length, moves input buffer data reader forward */
sdp_get_seq_len_item(uint8_t ** data,size_t len)2559 static ssize_t sdp_get_seq_len_item(uint8_t **data, size_t len)
2560 {
2561 const uint8_t *pnext;
2562
2563 BT_ASSERT(data);
2564 BT_ASSERT(*data);
2565
2566 /* validate len for pnext safe use to read 8bit bit value */
2567 if (len < 2) {
2568 goto err;
2569 }
2570
2571 pnext = *data + sizeof(uint8_t);
2572
2573 switch (*data[0]) {
2574 case BT_SDP_SEQ8:
2575 if (len < (2 + pnext[0])) {
2576 break;
2577 }
2578
2579 *data += 2;
2580 return pnext[0];
2581 case BT_SDP_SEQ16:
2582 /* validate len for pnext safe use to read 16bit value */
2583 if (len < 3) {
2584 break;
2585 }
2586
2587 if (len < (3 + sys_get_be16(pnext))) {
2588 break;
2589 }
2590
2591 *data += 3;
2592 return sys_get_be16(pnext);
2593 case BT_SDP_SEQ32:
2594 /* validate len for pnext safe use to read 32bit value */
2595 if (len < 5) {
2596 break;
2597 }
2598
2599 if (len < (5 + sys_get_be32(pnext))) {
2600 break;
2601 }
2602
2603 *data += 5;
2604 return sys_get_be32(pnext);
2605 default:
2606 LOG_ERR("Invalid/unhandled DTD 0x%02x", *data[0]);
2607 return -EINVAL;
2608 }
2609 err:
2610 LOG_ERR("Too short buffer length %zu", len);
2611 return -EMSGSIZE;
2612 }
2613
sdp_loop_seqs(uint8_t ** data,size_t len)2614 static int sdp_loop_seqs(uint8_t **data, size_t len)
2615 {
2616 ssize_t slen;
2617 ssize_t pre_slen;
2618 uint8_t *end;
2619
2620 if (len <= 0) {
2621 return -EMSGSIZE;
2622 }
2623
2624 pre_slen = -EINVAL;
2625 slen = -EINVAL;
2626 end = *data + len;
2627 /* loop all the SEQ */
2628 while (*data < end) {
2629 /* how long is current UUID's item data associated to */
2630 slen = sdp_get_seq_len_item(data, end - *data);
2631 if (slen < 0) {
2632 break;
2633 }
2634 pre_slen = slen;
2635 }
2636
2637 /* return the last seq len */
2638 if (pre_slen < 0) {
2639 return slen;
2640 }
2641
2642 return pre_slen;
2643 }
2644
sdp_get_uuid_data(const struct bt_sdp_attr_item * attr,struct bt_sdp_uuid_desc * pd,uint16_t proto_profile,uint8_t proto_profile_index)2645 static int sdp_get_uuid_data(const struct bt_sdp_attr_item *attr,
2646 struct bt_sdp_uuid_desc *pd,
2647 uint16_t proto_profile,
2648 uint8_t proto_profile_index)
2649 {
2650 /* get start address of attribute value */
2651 uint8_t *p = attr->val;
2652 ssize_t slen;
2653
2654 BT_ASSERT(p);
2655
2656 /* start reading stacked UUIDs in analyzed sequences tree */
2657 while (p - attr->val < attr->len) {
2658 size_t to_end, left = 0;
2659 uint8_t dtd;
2660
2661 /* to_end tells how far to the end of input buffer */
2662 to_end = attr->len - (p - attr->val);
2663 /* loop all the SEQ, get the last SEQ len */
2664 slen = sdp_loop_seqs(&p, to_end);
2665
2666 if (slen < 0) {
2667 return slen;
2668 }
2669
2670 /* left tells how far is to the end of current UUID */
2671 left = slen;
2672
2673 /* check if at least DTD + UUID16 can be read safely */
2674 if (left < (sizeof(dtd) + BT_UUID_SIZE_16)) {
2675 return -EMSGSIZE;
2676 }
2677
2678 /* check DTD and get stacked UUID value */
2679 dtd = p[0];
2680 p++;
2681 /* include last DTD in p[0] size itself updating left */
2682 left -= sizeof(dtd);
2683 switch (dtd) {
2684 case BT_SDP_UUID16:
2685 memcpy(&pd->uuid16,
2686 BT_UUID_DECLARE_16(sys_get_be16(p)),
2687 sizeof(struct bt_uuid_16));
2688 p += sizeof(uint16_t);
2689 left -= sizeof(uint16_t);
2690 break;
2691 case BT_SDP_UUID32:
2692 /* check if valid UUID32 can be read safely */
2693 if (left < BT_UUID_SIZE_32) {
2694 return -EMSGSIZE;
2695 }
2696
2697 memcpy(&pd->uuid32,
2698 BT_UUID_DECLARE_32(sys_get_be32(p)),
2699 sizeof(struct bt_uuid_32));
2700 p += sizeof(BT_UUID_SIZE_32);
2701 left -= sizeof(BT_UUID_SIZE_32);
2702 break;
2703 default:
2704 LOG_ERR("Invalid/unhandled DTD 0x%02x\n", dtd);
2705 return -EINVAL;
2706 }
2707
2708 /*
2709 * Check if current UUID value matches input one given by user.
2710 * If found save it's location and length and return.
2711 */
2712 if ((proto_profile == BT_UUID_16(&pd->uuid)->val) ||
2713 (proto_profile == BT_UUID_32(&pd->uuid)->val)) {
2714 pd->params = p;
2715 pd->params_len = left;
2716
2717 LOG_DBG("UUID 0x%s found", bt_uuid_str(&pd->uuid));
2718 if (proto_profile_index > 0U) {
2719 proto_profile_index--;
2720 p += left;
2721 continue;
2722 } else {
2723 return 0;
2724 }
2725 }
2726
2727 /* skip left octets to point beginning of next UUID in tree */
2728 p += left;
2729 }
2730
2731 LOG_DBG("Value 0x%04x index %d not found", proto_profile, proto_profile_index);
2732 return -ENOENT;
2733 }
2734
2735 /*
2736 * Helper extracting specific parameters associated with UUID node given in
2737 * protocol descriptor list or profile descriptor list.
2738 */
sdp_get_param_item(struct bt_sdp_uuid_desc * pd_item,uint16_t * param)2739 static int sdp_get_param_item(struct bt_sdp_uuid_desc *pd_item, uint16_t *param)
2740 {
2741 const uint8_t *p = pd_item->params;
2742 bool len_err = false;
2743
2744 BT_ASSERT(p);
2745
2746 LOG_DBG("Getting UUID's 0x%s params", bt_uuid_str(&pd_item->uuid));
2747
2748 switch (p[0]) {
2749 case BT_SDP_UINT8:
2750 /* check if 8bits value can be read safely */
2751 if (pd_item->params_len < 2) {
2752 len_err = true;
2753 break;
2754 }
2755 *param = (++p)[0];
2756 p += sizeof(uint8_t);
2757 break;
2758 case BT_SDP_UINT16:
2759 /* check if 16bits value can be read safely */
2760 if (pd_item->params_len < 3) {
2761 len_err = true;
2762 break;
2763 }
2764 *param = sys_get_be16(++p);
2765 p += sizeof(uint16_t);
2766 break;
2767 case BT_SDP_UINT32:
2768 /* check if 32bits value can be read safely */
2769 if (pd_item->params_len < 5) {
2770 len_err = true;
2771 break;
2772 }
2773 *param = sys_get_be32(++p);
2774 p += sizeof(uint32_t);
2775 break;
2776 default:
2777 LOG_ERR("Invalid/unhandled DTD 0x%02x\n", p[0]);
2778 return -EINVAL;
2779 }
2780 /*
2781 * Check if no more data than already read is associated with UUID. In
2782 * valid case after getting parameter we should reach data buf end.
2783 */
2784 if (p - pd_item->params != pd_item->params_len || len_err) {
2785 LOG_DBG("Invalid param buffer length");
2786 return -EMSGSIZE;
2787 }
2788
2789 return 0;
2790 }
2791
bt_sdp_get_proto_param(const struct net_buf * buf,enum bt_sdp_proto proto,uint16_t * param)2792 int bt_sdp_get_proto_param(const struct net_buf *buf, enum bt_sdp_proto proto,
2793 uint16_t *param)
2794 {
2795 struct bt_sdp_attr_item attr;
2796 struct bt_sdp_uuid_desc pd;
2797 int res;
2798
2799 if (proto != BT_SDP_PROTO_RFCOMM && proto != BT_SDP_PROTO_L2CAP) {
2800 LOG_ERR("Invalid protocol specifier");
2801 return -EINVAL;
2802 }
2803
2804 res = bt_sdp_get_attr(buf, &attr, BT_SDP_ATTR_PROTO_DESC_LIST);
2805 if (res < 0) {
2806 LOG_WRN("Attribute 0x%04x not found, err %d", BT_SDP_ATTR_PROTO_DESC_LIST, res);
2807 return res;
2808 }
2809
2810 res = sdp_get_uuid_data(&attr, &pd, proto, 0U);
2811 if (res < 0) {
2812 LOG_WRN("Protocol specifier 0x%04x not found, err %d", proto, res);
2813 return res;
2814 }
2815
2816 return sdp_get_param_item(&pd, param);
2817 }
2818
bt_sdp_get_addl_proto_param(const struct net_buf * buf,enum bt_sdp_proto proto,uint8_t param_index,uint16_t * param)2819 int bt_sdp_get_addl_proto_param(const struct net_buf *buf, enum bt_sdp_proto proto,
2820 uint8_t param_index, uint16_t *param)
2821 {
2822 struct bt_sdp_attr_item attr;
2823 struct bt_sdp_uuid_desc pd;
2824 int res;
2825
2826 if (proto != BT_SDP_PROTO_RFCOMM && proto != BT_SDP_PROTO_L2CAP) {
2827 LOG_ERR("Invalid protocol specifier");
2828 return -EINVAL;
2829 }
2830
2831 res = bt_sdp_get_attr(buf, &attr, BT_SDP_ATTR_ADD_PROTO_DESC_LIST);
2832 if (res < 0) {
2833 LOG_WRN("Attribute 0x%04x not found, err %d", BT_SDP_ATTR_PROTO_DESC_LIST, res);
2834 return res;
2835 }
2836
2837 res = sdp_get_uuid_data(&attr, &pd, proto, param_index);
2838 if (res < 0) {
2839 LOG_WRN("Protocol specifier 0x%04x not found, err %d", proto, res);
2840 return res;
2841 }
2842
2843 return sdp_get_param_item(&pd, param);
2844 }
2845
bt_sdp_get_profile_version(const struct net_buf * buf,uint16_t profile,uint16_t * version)2846 int bt_sdp_get_profile_version(const struct net_buf *buf, uint16_t profile,
2847 uint16_t *version)
2848 {
2849 struct bt_sdp_attr_item attr;
2850 struct bt_sdp_uuid_desc pd;
2851 int res;
2852
2853 res = bt_sdp_get_attr(buf, &attr, BT_SDP_ATTR_PROFILE_DESC_LIST);
2854 if (res < 0) {
2855 LOG_WRN("Attribute 0x%04x not found, err %d", BT_SDP_ATTR_PROFILE_DESC_LIST, res);
2856 return res;
2857 }
2858
2859 res = sdp_get_uuid_data(&attr, &pd, profile, 0U);
2860 if (res < 0) {
2861 LOG_WRN("Profile 0x%04x not found, err %d", profile, res);
2862 return res;
2863 }
2864
2865 return sdp_get_param_item(&pd, version);
2866 }
2867
bt_sdp_get_features(const struct net_buf * buf,uint16_t * features)2868 int bt_sdp_get_features(const struct net_buf *buf, uint16_t *features)
2869 {
2870 struct bt_sdp_attr_item attr;
2871 const uint8_t *p;
2872 int res;
2873
2874 res = bt_sdp_get_attr(buf, &attr, BT_SDP_ATTR_SUPPORTED_FEATURES);
2875 if (res < 0) {
2876 LOG_WRN("Attribute 0x%04x not found, err %d", BT_SDP_ATTR_SUPPORTED_FEATURES, res);
2877 return res;
2878 }
2879
2880 p = attr.val;
2881 BT_ASSERT(p);
2882
2883 if (p[0] != BT_SDP_UINT16) {
2884 LOG_ERR("Invalid DTD 0x%02x", p[0]);
2885 return -EINVAL;
2886 }
2887
2888 /* assert 16bit can be read safely */
2889 if (attr.len < 3) {
2890 LOG_ERR("Data length too short %u", attr.len);
2891 return -EMSGSIZE;
2892 }
2893
2894 *features = sys_get_be16(++p);
2895 p += sizeof(uint16_t);
2896
2897 if (p - attr.val != attr.len) {
2898 LOG_ERR("Invalid data length %u", attr.len);
2899 return -EMSGSIZE;
2900 }
2901
2902 return 0;
2903 }
2904