sdp.c 17 KB

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