CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
orangepi-xunlong

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

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