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