device: Set disconnect timer to zero for fast disconnection
[platform/upstream/bluez.git] / monitor / sdp.c
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 /*
3  *
4  *  BlueZ - Bluetooth protocol stack for Linux
5  *
6  *  Copyright (C) 2011-2014  Intel Corporation
7  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
8  *
9  *
10  */
11
12 #ifdef HAVE_CONFIG_H
13 #include <config.h>
14 #endif
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <inttypes.h>
20
21 #include "lib/bluetooth.h"
22 #include "lib/uuid.h"
23
24 #include "src/shared/util.h"
25
26 #include "bt.h"
27 #include "packet.h"
28 #include "display.h"
29 #include "l2cap.h"
30 #include "sdp.h"
31
32 #define MAX_TID 16
33 #define MAX_CONT_SIZE 17
34
35 struct tid_data {
36         bool inuse;
37         uint16_t tid;
38         uint16_t channel;
39         uint8_t cont[MAX_CONT_SIZE];
40 };
41
42 static struct tid_data tid_list[MAX_TID];
43
44 static struct tid_data *get_tid(uint16_t tid, uint16_t channel)
45 {
46         int i, n = -1;
47
48         for (i = 0; i < MAX_TID; i++) {
49                 if (!tid_list[i].inuse) {
50                         if (n < 0)
51                                 n = i;
52                         continue;
53                 }
54
55                 if (tid_list[i].tid == tid && tid_list[i].channel == channel)
56                         return &tid_list[i];
57         }
58
59         if (n < 0)
60                 return NULL;
61
62         tid_list[n].inuse = true;
63         tid_list[n].tid = tid;
64         tid_list[n].channel = channel;
65
66         return &tid_list[n];
67 }
68
69 static void clear_tid(struct tid_data *tid)
70 {
71         if (tid)
72                 tid->inuse = false;
73 }
74
75 static void print_uint(uint8_t indent, const uint8_t *data, uint32_t size)
76 {
77         switch (size) {
78         case 1:
79                 print_field("%*c0x%2.2x", indent, ' ', data[0]);
80                 break;
81         case 2:
82                 print_field("%*c0x%4.4x", indent, ' ', get_be16(data));
83                 break;
84         case 4:
85                 print_field("%*c0x%8.8x", indent, ' ', get_be32(data));
86                 break;
87         case 8:
88                 print_field("%*c0x%16.16" PRIx64, indent, ' ', get_be64(data));
89                 break;
90         default:
91                 packet_hexdump(data, size);
92                 break;
93         }
94 }
95
96 static void print_sint(uint8_t indent, const uint8_t *data, uint32_t size)
97 {
98         packet_hexdump(data, size);
99 }
100
101 static void print_uuid(uint8_t indent, const uint8_t *data, uint32_t size)
102 {
103         switch (size) {
104         case 2:
105                 print_field("%*c%s (0x%4.4x)", indent, ' ',
106                         bt_uuid16_to_str(get_be16(data)), get_be16(data));
107                 break;
108         case 4:
109                 print_field("%*c%s (0x%8.8x)", indent, ' ',
110                         bt_uuid32_to_str(get_be32(data)), get_be32(data));
111                 break;
112         case 16:
113                 /* BASE_UUID = 00000000-0000-1000-8000-00805F9B34FB */
114                 print_field("%*c%8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.4x",
115                                 indent, ' ',
116                                 get_be32(data), get_be16(data + 4),
117                                 get_be16(data + 6), get_be16(data + 8),
118                                 get_be16(data + 10), get_be32(data + 12));
119                 if (get_be16(data + 4) == 0x0000 &&
120                                 get_be16(data + 6) == 0x1000 &&
121                                 get_be16(data + 8) == 0x8000 &&
122                                 get_be16(data + 10) == 0x0080 &&
123                                 get_be32(data + 12) == 0x5F9B34FB)
124                         print_field("%*c%s", indent, ' ',
125                                 bt_uuid32_to_str(get_be32(data)));
126                 break;
127         default:
128                 packet_hexdump(data, size);
129                 break;
130         }
131 }
132
133 static void print_string(uint8_t indent, const uint8_t *data, uint32_t size)
134 {
135         char *str = alloca(size + 1);
136
137         str[size] = '\0';
138         strncpy(str, (const char *) data, size);
139
140         print_field("%*c%s [len %d]", indent, ' ', str, size);
141 }
142
143 static void print_boolean(uint8_t indent, const uint8_t *data, uint32_t size)
144 {
145         print_field("%*c%s", indent, ' ', data[0] ? "true" : "false");
146 }
147
148 #define SIZES(args...) ((uint8_t[]) { args, 0xff } )
149
150 static struct {
151         uint8_t value;
152         uint8_t *sizes;
153         bool recurse;
154         const char *str;
155         void (*print) (uint8_t indent, const uint8_t *data, uint32_t size);
156 } type_table[] = {
157         { 0, SIZES(0),             false, "Nil"                 },
158         { 1, SIZES(0, 1, 2, 3, 4), false, "Unsigned Integer",   print_uint },
159         { 2, SIZES(0, 1, 2, 3, 4), false, "Signed Integer",     print_sint },
160         { 3, SIZES(1, 2, 4),       false, "UUID",               print_uuid },
161         { 4, SIZES(5, 6, 7),       false, "String",             print_string },
162         { 5, SIZES(0),             false, "Boolean",            print_boolean },
163         { 6, SIZES(5, 6, 7),       true,  "Sequence"            },
164         { 7, SIZES(5, 6, 7),       true,  "Alternative"         },
165         { 8, SIZES(5, 6, 7),       false, "URL",                print_string },
166         { }
167 };
168
169 static struct {
170         uint8_t index;
171         uint8_t bits;
172         uint8_t size;
173         const char *str;
174 } size_table[] = {
175         { 0,  0,  1, "1 byte"   },
176         { 1,  0,  2, "2 bytes"  },
177         { 2,  0,  4, "4 bytes"  },
178         { 3,  0,  8, "8 bytes"  },
179         { 4,  0, 16, "16 bytes" },
180         { 5,  8,  0, "8 bits"   },
181         { 6, 16,  0, "16 bits"  },
182         { 7, 32,  0, "32 bits"  },
183         { }
184 };
185
186 static bool valid_size(uint8_t size, uint8_t *sizes)
187 {
188         int i;
189
190         for (i = 0; sizes[i] != 0xff; i++) {
191                 if (sizes[i] == size)
192                         return true;
193         }
194
195         return false;
196 }
197
198 static uint8_t get_bits(const uint8_t *data, uint32_t size)
199 {
200         int i;
201
202         for (i = 0; size_table[i].str; i++) {
203                 if (size_table[i].index == (data[0] & 0x07))
204                         return size_table[i].bits;
205         }
206
207         return 0;
208 }
209
210 static uint32_t get_size(const uint8_t *data, uint32_t size)
211 {
212         int i;
213
214         for (i = 0; size_table[i].str; i++) {
215                 if (size_table[i].index == (data[0] & 0x07)) {
216                         switch (size_table[i].bits) {
217                         case 0:
218                                 if ((data[0] & 0xf8) == 0)
219                                         return 0;
220                                 else
221                                         return size_table[i].size;
222                         case 8:
223                                 return data[1];
224                         case 16:
225                                 return get_be16(data + 1);
226                         case 32:
227                                 return get_be32(data + 1);
228                         default:
229                                 return 0;
230                         }
231                 }
232         }
233
234         return 0;
235 }
236
237 static void decode_data_elements(uint32_t position, uint8_t indent,
238                                 const uint8_t *data, uint32_t size,
239                                 void (*print_func) (uint32_t, uint8_t, uint8_t,
240                                                 const uint8_t *, uint32_t))
241
242 {
243         uint32_t datalen, elemlen, extrabits;
244         int i;
245
246         if (!size)
247                 return;
248
249         extrabits = get_bits(data, size);
250
251         if (size < 1 + (extrabits / 8)) {
252                 print_text(COLOR_ERROR, "data element descriptor too short");
253                 packet_hexdump(data, size);
254                 return;
255         }
256
257         datalen = get_size(data, size);
258
259         if (size < 1 + (extrabits / 8) + datalen) {
260                 print_text(COLOR_ERROR, "data element size too short");
261                 packet_hexdump(data, size);
262                 return;
263         }
264
265         elemlen = 1 + (extrabits / 8) + datalen;
266
267         for (i = 0; type_table[i].str; i++) {
268                 uint8_t type = (data[0] & 0xf8) >> 3;
269
270                 if (type_table[i].value != type)
271                         continue;
272
273                 if (print_func) {
274                         print_func(position, indent, type,
275                                         data + 1 + (extrabits / 8), datalen);
276                         break;
277                 }
278
279                 print_field("%*c%s (%d) with %u byte%s [%u extra bits] len %u",
280                                         indent, ' ', type_table[i].str, type,
281                                         datalen, datalen == 1 ? "" : "s",
282                                         extrabits, elemlen);
283                 if (!valid_size(data[0] & 0x07, type_table[i].sizes)) {
284                         print_text(COLOR_ERROR, "invalid data element size");
285                         packet_hexdump(data + 1 + (extrabits / 8), datalen);
286                         break;
287                 }
288
289                 if (type_table[i].recurse)
290                         decode_data_elements(0, indent + 2,
291                                         data + 1 + (extrabits / 8), datalen,
292                                                                 print_func);
293                 else if (type_table[i].print)
294                         type_table[i].print(indent + 2,
295                                         data + 1 + (extrabits / 8), datalen);
296                 break;
297         }
298
299         data += elemlen;
300         size -= elemlen;
301
302         decode_data_elements(position + 1, indent, data, size, print_func);
303 }
304
305 static uint32_t get_bytes(const uint8_t *data, uint32_t size)
306 {
307         switch (data[0] & 0x07) {
308         case 5:
309                 return 2 + data[1];
310         case 6:
311                 return 3 + get_be16(data + 1);
312         case 7:
313                 return 5 + get_be32(data + 1);
314         }
315
316         return 0;
317 }
318
319 static struct {
320         uint16_t id;
321         const char *str;
322 } attribute_table[] = {
323         { 0x0000, "Service Record Handle"               },
324         { 0x0001, "Service Class ID List"               },
325         { 0x0002, "Service Record State"                },
326         { 0x0003, "Service ID"                          },
327         { 0x0004, "Protocol Descriptor List"            },
328         { 0x0005, "Browse Group List"                   },
329         { 0x0006, "Language Base Attribute ID List"     },
330         { 0x0007, "Service Info Time To Live"           },
331         { 0x0008, "Service Availability"                },
332         { 0x0009, "Bluetooth Profile Descriptor List"   },
333         { 0x000a, "Documentation URL"                   },
334         { 0x000b, "Client Executable URL"               },
335         { 0x000c, "Icon URL"                            },
336         { 0x000d, "Additional Protocol Descriptor List" },
337         { }
338 };
339
340 static void print_attr(uint32_t position, uint8_t indent, uint8_t type,
341                                         const uint8_t *data, uint32_t size)
342 {
343         int i;
344
345         if ((position % 2) == 0) {
346                 uint16_t id = get_be16(data);
347                 const char *str = "Unknown";
348
349                 for (i = 0; attribute_table[i].str; i++) {
350                         if (attribute_table[i].id == id)
351                                 str = attribute_table[i].str;
352                 }
353
354                 print_field("%*cAttribute: %s (0x%4.4x) [len %d]",
355                                                 indent, ' ', str, id, size);
356                 return;
357         }
358
359         for (i = 0; type_table[i].str; i++) {
360                 if (type_table[i].value != type)
361                         continue;
362
363                 if (type_table[i].recurse)
364                         decode_data_elements(0, indent + 2, data, size, NULL);
365                 else if (type_table[i].print)
366                         type_table[i].print(indent + 2, data, size);
367                 break;
368         }
369 }
370
371 static void print_attr_list(uint32_t position, uint8_t indent, uint8_t type,
372                                         const uint8_t *data, uint32_t size)
373 {
374         print_field("%*cAttribute list: [len %d] {position %d}",
375                                                 indent, ' ', size, position);
376
377         decode_data_elements(0, indent + 2, data, size, print_attr);
378 }
379
380 static void print_attr_lists(uint32_t position, uint8_t indent, uint8_t type,
381                                         const uint8_t *data, uint32_t size)
382 {
383         decode_data_elements(0, indent, data, size, print_attr_list);
384 }
385
386 static void print_continuation(const uint8_t *data, uint16_t size)
387 {
388         if (data[0] != size - 1) {
389                 print_text(COLOR_ERROR, "invalid continuation state");
390                 packet_hexdump(data, size);
391                 return;
392         }
393
394         print_field("Continuation state: %d", data[0]);
395         packet_hexdump(data + 1, size - 1);
396 }
397
398 static void store_continuation(struct tid_data *tid,
399                                         const uint8_t *data, uint16_t size)
400 {
401         if (size > MAX_CONT_SIZE) {
402                 print_text(COLOR_ERROR, "invalid continuation size");
403                 return;
404         }
405         memcpy(tid->cont, data, size);
406         print_continuation(data, size);
407 }
408
409 #define MAX_CONT 8
410
411 struct cont_data {
412         uint16_t channel;
413         uint8_t cont[17];
414         void *data;
415         uint32_t size;
416 };
417
418 static struct cont_data cont_list[MAX_CONT];
419
420 static void handle_continuation(struct tid_data *tid, bool nested,
421                         uint16_t bytes, const uint8_t *data, uint16_t size)
422 {
423         uint8_t *newdata;
424         int i, n = -1;
425
426         if (bytes + 1 > size) {
427                 print_text(COLOR_ERROR, "missing continuation state");
428                 return;
429         }
430
431         if (tid->cont[0] == 0x00 && data[bytes] == 0x00) {
432                 decode_data_elements(0, 2, data, bytes,
433                                 nested ? print_attr_lists : print_attr_list);
434
435                 print_continuation(data + bytes, size - bytes);
436                 return;
437         }
438
439         for (i = 0; i < MAX_CONT; i++) {
440                 if (cont_list[i].cont[0] == 0x00) {
441                         if (n < 0)
442                                 n = i;
443                         continue;
444                 }
445
446                 if (cont_list[i].channel != tid->channel)
447                         continue;
448
449                 if (cont_list[i].cont[0] != tid->cont[0])
450                         continue;
451
452                 if (!memcmp(cont_list[i].cont + 1,
453                                         tid->cont + 1, tid->cont[0])) {
454                         n = i;
455                         break;
456                 }
457         }
458
459         print_continuation(data + bytes, size - bytes);
460
461         if (n < 0)
462                 return;
463
464         newdata = realloc(cont_list[n].data, cont_list[n].size + bytes);
465         if (!newdata) {
466                 print_text(COLOR_ERROR, "failed buffer allocation");
467                 free(cont_list[n].data);
468                 cont_list[n].data = NULL;
469                 cont_list[n].size = 0;
470                 return;
471         }
472
473         cont_list[n].channel = tid->channel;
474         cont_list[n].data = newdata;
475
476         if (bytes > 0) {
477                 memcpy(cont_list[n].data + cont_list[n].size, data, bytes);
478                 cont_list[n].size += bytes;
479         }
480
481         if (data[bytes] == 0x00) {
482                 print_field("Combined attribute bytes: %d", cont_list[n].size);
483
484                 decode_data_elements(0, 2, cont_list[n].data, cont_list[n].size,
485                                 nested ? print_attr_lists : print_attr_list);
486
487                 free(cont_list[n].data);
488                 cont_list[n].data = NULL;
489                 cont_list[n].size = 0;
490 #ifdef TIZEN_FEATURE_BLUEZ_MODIFY
491                 cont_list[n].cont[0] = 0x00;
492 #endif
493         } else
494                 memcpy(cont_list[n].cont, data + bytes, data[bytes] + 1);
495 }
496
497 static uint16_t common_rsp(const struct l2cap_frame *frame,
498                                                 struct tid_data *tid)
499 {
500         uint16_t bytes;
501
502         if (frame->size < 2) {
503                 print_text(COLOR_ERROR, "invalid size");
504                 packet_hexdump(frame->data, frame->size);
505                 return 0;
506         }
507
508         bytes = get_be16(frame->data);
509         print_field("Attribute bytes: %d", bytes);
510
511         if (bytes > frame->size - 2) {
512                 print_text(COLOR_ERROR, "invalid attribute size");
513                 packet_hexdump(frame->data + 2, frame->size - 2);
514                 return 0;
515         }
516
517         return bytes;
518 }
519
520 static const char *error_str(uint16_t code)
521 {
522         switch (code) {
523         case 0x0001:
524                 return "Invalid Version";
525         case 0x0002:
526                 return "Invalid Record Handle";
527         case 0x0003:
528                 return "Invalid Syntax";
529         case 0x0004:
530                 return "Invalid PDU Size";
531         case 0x0005:
532                 return "Invalid Continuation State";
533         default:
534                 return "Unknown";
535         }
536 }
537
538 static void error_rsp(const struct l2cap_frame *frame, struct tid_data *tid)
539 {
540         uint16_t error;
541
542         clear_tid(tid);
543
544         if (frame->size < 2) {
545                 print_text(COLOR_ERROR, "invalid size");
546                 packet_hexdump(frame->data, frame->size);
547                 return;
548         }
549
550         error = get_be16(frame->data);
551
552         print_field("Error code: %s (0x%4.4x)", error_str(error), error);
553 }
554
555 static void service_req(const struct l2cap_frame *frame, struct tid_data *tid)
556 {
557         uint32_t search_bytes;
558
559         search_bytes = get_bytes(frame->data, frame->size);
560         print_field("Search pattern: [len %d]", search_bytes);
561
562         if (search_bytes + 2 > frame->size) {
563                 print_text(COLOR_ERROR, "invalid search list length");
564                 packet_hexdump(frame->data, frame->size);
565                 return;
566         }
567
568         decode_data_elements(0, 2, frame->data, search_bytes, NULL);
569
570         print_field("Max record count: %d",
571                                 get_be16(frame->data + search_bytes));
572
573         print_continuation(frame->data + search_bytes + 2,
574                                         frame->size - search_bytes - 2);
575 }
576
577 static void service_rsp(const struct l2cap_frame *frame, struct tid_data *tid)
578 {
579         uint16_t count;
580         int i;
581
582         clear_tid(tid);
583
584         if (frame->size < 4) {
585                 print_text(COLOR_ERROR, "invalid size");
586                 packet_hexdump(frame->data, frame->size);
587                 return;
588         }
589
590         count = get_be16(frame->data + 2);
591
592         print_field("Total record count: %d", get_be16(frame->data));
593         print_field("Current record count: %d", count);
594
595         for (i = 0; i < count; i++)
596                 print_field("Record handle: 0x%4.4x",
597                                 get_be32(frame->data + 4 + (i * 4)));
598
599         print_continuation(frame->data + 4 + (count * 4),
600                                         frame->size - 4 - (count * 4));
601 }
602
603 static void attr_req(const struct l2cap_frame *frame, struct tid_data *tid)
604 {
605         uint32_t attr_bytes;
606
607         if (frame->size < 6) {
608                 print_text(COLOR_ERROR, "invalid size");
609                 packet_hexdump(frame->data, frame->size);
610                 return;
611         }
612
613         print_field("Record handle: 0x%4.4x", get_be32(frame->data));
614         print_field("Max attribute bytes: %d", get_be16(frame->data + 4));
615
616         attr_bytes = get_bytes(frame->data + 6, frame->size - 6);
617         print_field("Attribute list: [len %d]", attr_bytes);
618
619         if (attr_bytes + 6 > frame->size) {
620                 print_text(COLOR_ERROR, "invalid attribute list length");
621                 packet_hexdump(frame->data, frame->size);
622                 return;
623         }
624
625         decode_data_elements(0, 2, frame->data + 6, attr_bytes, NULL);
626
627         store_continuation(tid, frame->data + 6 + attr_bytes,
628                                         frame->size - 6 - attr_bytes);
629 }
630
631 static void attr_rsp(const struct l2cap_frame *frame, struct tid_data *tid)
632 {
633         uint16_t bytes;
634
635         bytes = common_rsp(frame, tid);
636
637         handle_continuation(tid, false, bytes,
638                                         frame->data + 2, frame->size - 2);
639
640         clear_tid(tid);
641 }
642
643 static void search_attr_req(const struct l2cap_frame *frame,
644                                                 struct tid_data *tid)
645 {
646         uint32_t search_bytes, attr_bytes;
647
648         search_bytes = get_bytes(frame->data, frame->size);
649         print_field("Search pattern: [len %d]", search_bytes);
650
651         if (search_bytes + 2 > frame->size) {
652                 print_text(COLOR_ERROR, "invalid search list length");
653                 packet_hexdump(frame->data, frame->size);
654                 return;
655         }
656
657         decode_data_elements(0, 2, frame->data, search_bytes, NULL);
658
659         print_field("Max record count: %d",
660                                 get_be16(frame->data + search_bytes));
661
662         attr_bytes = get_bytes(frame->data + search_bytes + 2,
663                                 frame->size - search_bytes - 2);
664         print_field("Attribute list: [len %d]", attr_bytes);
665
666         decode_data_elements(0, 2, frame->data + search_bytes + 2,
667                                                 attr_bytes, NULL);
668
669         store_continuation(tid, frame->data + search_bytes + 2 + attr_bytes,
670                                 frame->size - search_bytes - 2 - attr_bytes);
671 }
672
673 static void search_attr_rsp(const struct l2cap_frame *frame,
674                                                 struct tid_data *tid)
675 {
676         uint16_t bytes;
677
678         bytes = common_rsp(frame, tid);
679
680         handle_continuation(tid, true, bytes, frame->data + 2, frame->size - 2);
681
682         clear_tid(tid);
683 }
684
685 struct sdp_data {
686         uint8_t pdu;
687         const char *str;
688         void (*func) (const struct l2cap_frame *frame, struct tid_data *tid);
689 };
690
691 static const struct sdp_data sdp_table[] = {
692         { 0x01, "Error Response",                       error_rsp       },
693         { 0x02, "Service Search Request",               service_req     },
694         { 0x03, "Service Search Response",              service_rsp     },
695         { 0x04, "Service Attribute Request",            attr_req        },
696         { 0x05, "Service Attribute Response",           attr_rsp        },
697         { 0x06, "Service Search Attribute Request",     search_attr_req },
698         { 0x07, "Service Search Attribute Response",    search_attr_rsp },
699         { }
700 };
701
702 void sdp_packet(const struct l2cap_frame *frame)
703 {
704         uint8_t pdu;
705         uint16_t tid, plen;
706         struct l2cap_frame sdp_frame;
707         struct tid_data *tid_info;
708         const struct sdp_data *sdp_data = NULL;
709         const char *pdu_color, *pdu_str;
710         int i;
711
712         l2cap_frame_pull(&sdp_frame, frame, 0);
713
714         if (!l2cap_frame_get_u8(&sdp_frame, &pdu) ||
715                                 !l2cap_frame_get_be16(&sdp_frame, &tid) ||
716                                 !l2cap_frame_get_be16(&sdp_frame, &plen)) {
717                 print_text(COLOR_ERROR, "frame too short");
718                 packet_hexdump(frame->data, frame->size);
719                 return;
720         }
721
722         if (sdp_frame.size != plen) {
723                 print_text(COLOR_ERROR, "invalid frame size");
724                 packet_hexdump(sdp_frame.data, sdp_frame.size);
725                 return;
726         }
727
728         for (i = 0; sdp_table[i].str; i++) {
729                 if (sdp_table[i].pdu == pdu) {
730                         sdp_data = &sdp_table[i];
731                         break;
732                 }
733         }
734
735         if (sdp_data) {
736                 if (sdp_data->func) {
737                         if (frame->in)
738                                 pdu_color = COLOR_MAGENTA;
739                         else
740                                 pdu_color = COLOR_BLUE;
741                 } else
742                         pdu_color = COLOR_WHITE_BG;
743                 pdu_str = sdp_data->str;
744         } else {
745                 pdu_color = COLOR_WHITE_BG;
746                 pdu_str = "Unknown";
747         }
748
749         print_indent(6, pdu_color, "SDP: ", pdu_str, COLOR_OFF,
750                                 " (0x%2.2x) tid %d len %d", pdu, tid, plen);
751
752         tid_info = get_tid(tid, frame->chan);
753
754         if (!sdp_data || !sdp_data->func || !tid_info) {
755                 packet_hexdump(sdp_frame.data, sdp_frame.size);
756                 return;
757         }
758
759         sdp_data->func(&sdp_frame, tid_info);
760 }