sdp.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2001-2002 Ricky Yuen <ryuen@qualcomm.com>
  7. * Copyright (C) 2003-2011 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 <errno.h>
  17. #include <ctype.h>
  18. #include <unistd.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include "parser.h"
  22. #include "sdp.h"
  23. #define SDP_ERROR_RSP 0x01
  24. #define SDP_SERVICE_SEARCH_REQ 0x02
  25. #define SDP_SERVICE_SEARCH_RSP 0x03
  26. #define SDP_SERVICE_ATTR_REQ 0x04
  27. #define SDP_SERVICE_ATTR_RSP 0x05
  28. #define SDP_SERVICE_SEARCH_ATTR_REQ 0x06
  29. #define SDP_SERVICE_SEARCH_ATTR_RSP 0x07
  30. typedef struct {
  31. uint8_t pid;
  32. uint16_t tid;
  33. uint16_t len;
  34. } __attribute__ ((packed)) sdp_pdu_hdr;
  35. #define SDP_PDU_HDR_SIZE 5
  36. /* Data element type descriptor */
  37. #define SDP_DE_NULL 0
  38. #define SDP_DE_UINT 1
  39. #define SDP_DE_INT 2
  40. #define SDP_DE_UUID 3
  41. #define SDP_DE_STRING 4
  42. #define SDP_DE_BOOL 5
  43. #define SDP_DE_SEQ 6
  44. #define SDP_DE_ALT 7
  45. #define SDP_DE_URL 8
  46. /* Data element size index lookup table */
  47. typedef struct {
  48. int addl_bits;
  49. int num_bytes;
  50. } sdp_siz_idx_lookup_table_t;
  51. static sdp_siz_idx_lookup_table_t sdp_siz_idx_lookup_table[] = {
  52. { 0, 1 }, /* Size index = 0 */
  53. { 0, 2 }, /* 1 */
  54. { 0, 4 }, /* 2 */
  55. { 0, 8 }, /* 3 */
  56. { 0, 16 }, /* 4 */
  57. { 1, 1 }, /* 5 */
  58. { 1, 2 }, /* 6 */
  59. { 1, 4 }, /* 7 */
  60. };
  61. /* UUID name lookup table */
  62. typedef struct {
  63. int uuid;
  64. char* name;
  65. } sdp_uuid_nam_lookup_table_t;
  66. static sdp_uuid_nam_lookup_table_t sdp_uuid_nam_lookup_table[] = {
  67. { SDP_UUID_SDP, "SDP" },
  68. { SDP_UUID_UDP, "UDP" },
  69. { SDP_UUID_RFCOMM, "RFCOMM" },
  70. { SDP_UUID_TCP, "TCP" },
  71. { SDP_UUID_TCS_BIN, "TCS-BIN" },
  72. { SDP_UUID_TCS_AT, "TCS-AT" },
  73. { SDP_UUID_OBEX, "OBEX" },
  74. { SDP_UUID_IP, "IP" },
  75. { SDP_UUID_FTP, "FTP" },
  76. { SDP_UUID_HTTP, "HTTP" },
  77. { SDP_UUID_WSP, "WSP" },
  78. { SDP_UUID_L2CAP, "L2CAP" },
  79. { SDP_UUID_BNEP, "BNEP" }, /* PAN */
  80. { SDP_UUID_HIDP, "HIDP" }, /* HID */
  81. { SDP_UUID_AVCTP, "AVCTP" }, /* AVCTP */
  82. { SDP_UUID_AVDTP, "AVDTP" }, /* AVDTP */
  83. { SDP_UUID_CMTP, "CMTP" }, /* CIP */
  84. { SDP_UUID_UDI_C_PLANE, "UDI_C-Plane" }, /* UDI */
  85. { SDP_UUID_SERVICE_DISCOVERY_SERVER, "SDServer" },
  86. { SDP_UUID_BROWSE_GROUP_DESCRIPTOR, "BrwsGrpDesc" },
  87. { SDP_UUID_PUBLIC_BROWSE_GROUP, "PubBrwsGrp" },
  88. { SDP_UUID_SERIAL_PORT, "SP" },
  89. { SDP_UUID_LAN_ACCESS_PPP, "LAN" },
  90. { SDP_UUID_DIALUP_NETWORKING, "DUN" },
  91. { SDP_UUID_IR_MC_SYNC, "IRMCSync" },
  92. { SDP_UUID_OBEX_OBJECT_PUSH, "OBEXObjPush" },
  93. { SDP_UUID_OBEX_FILE_TRANSFER, "OBEXObjTrnsf" },
  94. { SDP_UUID_IR_MC_SYNC_COMMAND, "IRMCSyncCmd" },
  95. { SDP_UUID_HEADSET, "Headset" },
  96. { SDP_UUID_CORDLESS_TELEPHONY, "CordlessTel" },
  97. { SDP_UUID_AUDIO_SOURCE, "AudioSource" }, /* A2DP */
  98. { SDP_UUID_AUDIO_SINK, "AudioSink" }, /* A2DP */
  99. { SDP_UUID_AV_REMOTE_TARGET, "AVRemTarget" }, /* AVRCP */
  100. { SDP_UUID_ADVANCED_AUDIO, "AdvAudio" }, /* A2DP */
  101. { SDP_UUID_AV_REMOTE, "AVRemote" }, /* AVRCP */
  102. { SDP_UUID_AV_REMOTE_CONTROLLER, "AVRemCt" }, /* AVRCP */
  103. { SDP_UUID_INTERCOM, "Intercom" },
  104. { SDP_UUID_FAX, "Fax" },
  105. { SDP_UUID_HEADSET_AUDIO_GATEWAY, "Headset AG" },
  106. { SDP_UUID_WAP, "WAP" },
  107. { SDP_UUID_WAP_CLIENT, "WAP Client" },
  108. { SDP_UUID_PANU, "PANU" }, /* PAN */
  109. { SDP_UUID_NAP, "NAP" }, /* PAN */
  110. { SDP_UUID_GN, "GN" }, /* PAN */
  111. { SDP_UUID_DIRECT_PRINTING, "DirectPrint" }, /* BPP */
  112. { SDP_UUID_REFERENCE_PRINTING, "RefPrint" }, /* BPP */
  113. { SDP_UUID_IMAGING, "Imaging" }, /* BIP */
  114. { SDP_UUID_IMAGING_RESPONDER, "ImagingResp" }, /* BIP */
  115. { SDP_UUID_HANDSFREE, "Handsfree" },
  116. { SDP_UUID_HANDSFREE_AUDIO_GATEWAY, "Handsfree AG" },
  117. { SDP_UUID_DIRECT_PRINTING_REF_OBJS, "RefObjsPrint" }, /* BPP */
  118. { SDP_UUID_REFLECTED_UI, "ReflectedUI" }, /* BPP */
  119. { SDP_UUID_BASIC_PRINTING, "BasicPrint" }, /* BPP */
  120. { SDP_UUID_PRINTING_STATUS, "PrintStatus" }, /* BPP */
  121. { SDP_UUID_HUMAN_INTERFACE_DEVICE, "HID" }, /* HID */
  122. { SDP_UUID_HARDCOPY_CABLE_REPLACE, "HCRP" }, /* HCRP */
  123. { SDP_UUID_HCR_PRINT, "HCRPrint" }, /* HCRP */
  124. { SDP_UUID_HCR_SCAN, "HCRScan" }, /* HCRP */
  125. { SDP_UUID_COMMON_ISDN_ACCESS, "CIP" }, /* CIP */
  126. { SDP_UUID_UDI_MT, "UDI MT" }, /* UDI */
  127. { SDP_UUID_UDI_TA, "UDI TA" }, /* UDI */
  128. { SDP_UUID_AUDIO_VIDEO, "AudioVideo" }, /* VCP */
  129. { SDP_UUID_SIM_ACCESS, "SAP" }, /* SAP */
  130. { SDP_UUID_PHONEBOOK_ACCESS_PCE, "PBAP PCE" }, /* PBAP */
  131. { SDP_UUID_PHONEBOOK_ACCESS_PSE, "PBAP PSE" }, /* PBAP */
  132. { SDP_UUID_PHONEBOOK_ACCESS, "PBAP" }, /* PBAP */
  133. { SDP_UUID_PNP_INFORMATION, "PNPInfo" },
  134. { SDP_UUID_GENERIC_NETWORKING, "Networking" },
  135. { SDP_UUID_GENERIC_FILE_TRANSFER, "FileTrnsf" },
  136. { SDP_UUID_GENERIC_AUDIO, "Audio" },
  137. { SDP_UUID_GENERIC_TELEPHONY, "Telephony" },
  138. { SDP_UUID_UPNP_SERVICE, "UPNP" }, /* ESDP */
  139. { SDP_UUID_UPNP_IP_SERVICE, "UPNP IP" }, /* ESDP */
  140. { SDP_UUID_ESDP_UPNP_IP_PAN, "UPNP PAN" }, /* ESDP */
  141. { SDP_UUID_ESDP_UPNP_IP_LAP, "UPNP LAP" }, /* ESDP */
  142. { SDP_UUID_ESDP_UPNP_L2CAP, "UPNP L2CAP" }, /* ESDP */
  143. { SDP_UUID_VIDEO_SOURCE, "VideoSource" }, /* VDP */
  144. { SDP_UUID_VIDEO_SINK, "VideoSink" }, /* VDP */
  145. { SDP_UUID_VIDEO_DISTRIBUTION, "VideoDist" }, /* VDP */
  146. { SDP_UUID_APPLE_AGENT, "AppleAgent" },
  147. };
  148. #define SDP_UUID_NAM_LOOKUP_TABLE_SIZE \
  149. (sizeof(sdp_uuid_nam_lookup_table)/sizeof(sdp_uuid_nam_lookup_table_t))
  150. /* AttrID name lookup table */
  151. typedef struct {
  152. int attr_id;
  153. char* name;
  154. } sdp_attr_id_nam_lookup_table_t;
  155. static sdp_attr_id_nam_lookup_table_t sdp_attr_id_nam_lookup_table[] = {
  156. { SDP_ATTR_ID_SERVICE_RECORD_HANDLE, "SrvRecHndl" },
  157. { SDP_ATTR_ID_SERVICE_CLASS_ID_LIST, "SrvClassIDList" },
  158. { SDP_ATTR_ID_SERVICE_RECORD_STATE, "SrvRecState" },
  159. { SDP_ATTR_ID_SERVICE_SERVICE_ID, "SrvID" },
  160. { SDP_ATTR_ID_PROTOCOL_DESCRIPTOR_LIST, "ProtocolDescList" },
  161. { SDP_ATTR_ID_BROWSE_GROUP_LIST, "BrwGrpList" },
  162. { SDP_ATTR_ID_LANGUAGE_BASE_ATTRIBUTE_ID_LIST, "LangBaseAttrIDList" },
  163. { SDP_ATTR_ID_SERVICE_INFO_TIME_TO_LIVE, "SrvInfoTimeToLive" },
  164. { SDP_ATTR_ID_SERVICE_AVAILABILITY, "SrvAvail" },
  165. { SDP_ATTR_ID_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, "BTProfileDescList" },
  166. { SDP_ATTR_ID_DOCUMENTATION_URL, "DocURL" },
  167. { SDP_ATTR_ID_CLIENT_EXECUTABLE_URL, "ClientExeURL" },
  168. { SDP_ATTR_ID_ICON_URL, "IconURL" },
  169. { SDP_ATTR_ID_ADDITIONAL_PROTOCOL_DESC_LISTS, "AdditionalProtocolDescLists" },
  170. { SDP_ATTR_ID_SERVICE_NAME, "SrvName" },
  171. { SDP_ATTR_ID_SERVICE_DESCRIPTION, "SrvDesc" },
  172. { SDP_ATTR_ID_PROVIDER_NAME, "ProviderName" },
  173. { SDP_ATTR_ID_VERSION_NUMBER_LIST, "VersionNumList" },
  174. { SDP_ATTR_ID_GROUP_ID, "GrpID" },
  175. { SDP_ATTR_ID_SERVICE_DATABASE_STATE, "SrvDBState" },
  176. { SDP_ATTR_ID_SERVICE_VERSION, "SrvVersion" },
  177. { SDP_ATTR_ID_SECURITY_DESCRIPTION, "SecurityDescription"}, /* PAN */
  178. { SDP_ATTR_ID_SUPPORTED_DATA_STORES_LIST, "SuppDataStoresList" }, /* Synchronization */
  179. { SDP_ATTR_ID_SUPPORTED_FORMATS_LIST, "SuppFormatsList" }, /* OBEX Object Push */
  180. { SDP_ATTR_ID_NET_ACCESS_TYPE, "NetAccessType" }, /* PAN */
  181. { SDP_ATTR_ID_MAX_NET_ACCESS_RATE, "MaxNetAccessRate" }, /* PAN */
  182. { SDP_ATTR_ID_IPV4_SUBNET, "IPv4Subnet" }, /* PAN */
  183. { SDP_ATTR_ID_IPV6_SUBNET, "IPv6Subnet" }, /* PAN */
  184. { SDP_ATTR_ID_SUPPORTED_CAPABILITIES, "SuppCapabilities" }, /* Imaging */
  185. { SDP_ATTR_ID_SUPPORTED_FEATURES, "SuppFeatures" }, /* Imaging and Hansfree */
  186. { SDP_ATTR_ID_SUPPORTED_FUNCTIONS, "SuppFunctions" }, /* Imaging */
  187. { SDP_ATTR_ID_TOTAL_IMAGING_DATA_CAPACITY, "SuppTotalCapacity" }, /* Imaging */
  188. { SDP_ATTR_ID_SUPPORTED_REPOSITORIES, "SuppRepositories" }, /* PBAP */
  189. };
  190. #define SDP_ATTR_ID_NAM_LOOKUP_TABLE_SIZE \
  191. (sizeof(sdp_attr_id_nam_lookup_table)/sizeof(sdp_attr_id_nam_lookup_table_t))
  192. char* get_uuid_name(int uuid)
  193. {
  194. unsigned int i;
  195. for (i = 0; i < SDP_UUID_NAM_LOOKUP_TABLE_SIZE; i++) {
  196. if (sdp_uuid_nam_lookup_table[i].uuid == uuid)
  197. return sdp_uuid_nam_lookup_table[i].name;
  198. }
  199. return 0;
  200. }
  201. static inline char* get_attr_id_name(int attr_id)
  202. {
  203. unsigned int i;
  204. for (i = 0; i < SDP_ATTR_ID_NAM_LOOKUP_TABLE_SIZE; i++)
  205. if (sdp_attr_id_nam_lookup_table[i].attr_id == attr_id)
  206. return sdp_attr_id_nam_lookup_table[i].name;
  207. return 0;
  208. }
  209. static inline uint8_t parse_de_hdr(struct frame *frm, int *n)
  210. {
  211. uint8_t de_hdr = p_get_u8(frm);
  212. uint8_t de_type = de_hdr >> 3;
  213. uint8_t siz_idx = de_hdr & 0x07;
  214. /* Get the number of bytes */
  215. if (sdp_siz_idx_lookup_table[siz_idx].addl_bits) {
  216. switch(sdp_siz_idx_lookup_table[siz_idx].num_bytes) {
  217. case 1:
  218. *n = p_get_u8(frm); break;
  219. case 2:
  220. *n = p_get_u16(frm); break;
  221. case 4:
  222. *n = p_get_u32(frm); break;
  223. case 8:
  224. *n = p_get_u64(frm); break;
  225. }
  226. } else
  227. *n = sdp_siz_idx_lookup_table[siz_idx].num_bytes;
  228. return de_type;
  229. }
  230. static inline void print_int(uint8_t de_type, int level, int n, struct frame *frm, uint16_t *psm, uint8_t *channel)
  231. {
  232. uint64_t val, val2;
  233. switch(de_type) {
  234. case SDP_DE_UINT:
  235. printf(" uint");
  236. break;
  237. case SDP_DE_INT:
  238. printf(" int");
  239. break;
  240. case SDP_DE_BOOL:
  241. printf(" bool");
  242. break;
  243. }
  244. switch(n) {
  245. case 1: /* 8-bit */
  246. val = p_get_u8(frm);
  247. if (channel && de_type == SDP_DE_UINT)
  248. if (*channel == 0)
  249. *channel = val;
  250. break;
  251. case 2: /* 16-bit */
  252. val = p_get_u16(frm);
  253. if (psm && de_type == SDP_DE_UINT)
  254. if (*psm == 0)
  255. *psm = val;
  256. break;
  257. case 4: /* 32-bit */
  258. val = p_get_u32(frm);
  259. break;
  260. case 8: /* 64-bit */
  261. val = p_get_u64(frm);
  262. break;
  263. case 16:/* 128-bit */
  264. p_get_u128(frm, &val, &val2);
  265. printf(" 0x%jx", val2);
  266. if (val < 0x1000000000000000LL)
  267. printf("0");
  268. printf("%jx", val);
  269. return;
  270. default: /* syntax error */
  271. printf(" err");
  272. frm->ptr += n;
  273. frm->len -= n;
  274. return;
  275. }
  276. printf(" 0x%jx", val);
  277. }
  278. static inline void print_uuid(int n, struct frame *frm, uint16_t *psm, uint8_t *channel)
  279. {
  280. uint32_t uuid = 0;
  281. char* s;
  282. int i;
  283. switch(n) {
  284. case 2: /* 16-bit UUID */
  285. uuid = p_get_u16(frm);
  286. s = "uuid-16";
  287. break;
  288. case 4: /* 32_bit UUID */
  289. uuid = p_get_u32(frm);
  290. s = "uuid-32";
  291. break;
  292. case 16: /* 128-bit UUID */
  293. printf(" uuid-128 ");
  294. for (i = 0; i < 16; i++) {
  295. printf("%02x", ((unsigned char *) frm->ptr)[i]);
  296. if (i == 3 || i == 5 || i == 7 || i == 9)
  297. printf("-");
  298. }
  299. frm->ptr += 16;
  300. frm->len -= 16;
  301. return;
  302. default: /* syntax error */
  303. printf(" *err*");
  304. frm->ptr += n;
  305. frm->len -= n;
  306. return;
  307. }
  308. if (psm && *psm > 0 && *psm != 0xffff) {
  309. set_proto(frm->handle, *psm, 0, uuid);
  310. *psm = 0xffff;
  311. }
  312. if (channel && *channel > 0 && *channel != 0xff) {
  313. set_proto(frm->handle, *psm, *channel, uuid);
  314. *channel = 0xff;
  315. }
  316. printf(" %s 0x%04x", s, uuid);
  317. if ((s = get_uuid_name(uuid)))
  318. printf(" (%s)", s);
  319. }
  320. static inline void print_string(int n, struct frame *frm, const char *name)
  321. {
  322. int i, hex = 0;
  323. for (i = 0; i < n; i++) {
  324. if (i == (n - 1) && ((char *) frm->ptr)[i] == '\0')
  325. break;
  326. if (!isprint(((char *) frm->ptr)[i])) {
  327. hex = 1;
  328. break;
  329. }
  330. }
  331. printf(" %s", name);
  332. if (hex) {
  333. for (i = 0; i < n; i++)
  334. printf(" %02x", ((unsigned char *) frm->ptr)[i]);
  335. } else {
  336. printf(" \"");
  337. for (i = 0; i < n; i++)
  338. printf("%c", ((char *) frm->ptr)[i]);
  339. printf("\"");
  340. }
  341. frm->ptr += n;
  342. frm->len -= n;
  343. }
  344. static inline void print_de(int, struct frame *frm, int *split, uint16_t *psm, uint8_t *channel);
  345. static inline void print_des(uint8_t de_type, int level, int n, struct frame *frm, int *split, uint16_t *psm, uint8_t *channel)
  346. {
  347. int len = frm->len;
  348. while (len - (int) frm->len < n && (int) frm->len > 0)
  349. print_de(level, frm, split, psm, channel);
  350. }
  351. static inline void print_de(int level, struct frame *frm, int *split, uint16_t *psm, uint8_t *channel)
  352. {
  353. int n = 0;
  354. uint8_t de_type = parse_de_hdr(frm, &n);
  355. switch (de_type) {
  356. case SDP_DE_NULL:
  357. printf(" null");
  358. break;
  359. case SDP_DE_UINT:
  360. case SDP_DE_INT:
  361. case SDP_DE_BOOL:
  362. print_int(de_type, level, n, frm, psm, channel);
  363. break;
  364. case SDP_DE_UUID:
  365. if (split) {
  366. /* Split output by uuids.
  367. * Used for printing Protocol Desc List */
  368. if (*split) {
  369. printf("\n");
  370. p_indent(level, NULL);
  371. }
  372. ++*split;
  373. }
  374. print_uuid(n, frm, psm, channel);
  375. break;
  376. case SDP_DE_URL:
  377. case SDP_DE_STRING:
  378. print_string(n, frm, de_type == SDP_DE_URL? "url": "str");
  379. break;
  380. case SDP_DE_SEQ:
  381. printf(" <");
  382. print_des(de_type, level, n, frm, split, psm, channel);
  383. printf(" >");
  384. break;
  385. case SDP_DE_ALT:
  386. printf(" [");
  387. print_des(de_type, level, n, frm, split, psm, channel);
  388. printf(" ]");
  389. break;
  390. }
  391. }
  392. static inline void print_srv_srch_pat(int level, struct frame *frm)
  393. {
  394. int len, n1 = 0, n2 = 0;
  395. p_indent(level, frm);
  396. printf("pat");
  397. if (parse_de_hdr(frm, &n1) == SDP_DE_SEQ) {
  398. len = frm->len;
  399. while (len - (int) frm->len < n1 && (int) frm->len > 0) {
  400. if (parse_de_hdr(frm, &n2) == SDP_DE_UUID) {
  401. print_uuid(n2, frm, NULL, NULL);
  402. } else {
  403. printf("\nERROR: Unexpected syntax (UUID)\n");
  404. raw_dump(level, frm);
  405. }
  406. }
  407. printf("\n");
  408. } else {
  409. printf("\nERROR: Unexpected syntax (SEQ)\n");
  410. raw_dump(level, frm);
  411. }
  412. }
  413. static inline void print_attr_id_list(int level, struct frame *frm)
  414. {
  415. uint16_t attr_id;
  416. uint32_t attr_id_range;
  417. int len, n1 = 0, n2 = 0;
  418. p_indent(level, frm);
  419. printf("aid(s)");
  420. if (parse_de_hdr(frm, &n1) == SDP_DE_SEQ) {
  421. len = frm->len;
  422. while (len - (int) frm->len < n1 && (int) frm->len > 0) {
  423. /* Print AttributeID */
  424. if (parse_de_hdr(frm, &n2) == SDP_DE_UINT) {
  425. char *name;
  426. switch(n2) {
  427. case 2:
  428. attr_id = p_get_u16(frm);
  429. name = get_attr_id_name(attr_id);
  430. if (!name)
  431. name = "unknown";
  432. printf(" 0x%04x (%s)", attr_id, name);
  433. break;
  434. case 4:
  435. attr_id_range = p_get_u32(frm);
  436. printf(" 0x%04x - 0x%04x",
  437. (attr_id_range >> 16),
  438. (attr_id_range & 0xFFFF));
  439. break;
  440. }
  441. } else {
  442. printf("\nERROR: Unexpected syntax\n");
  443. raw_dump(level, frm);
  444. }
  445. }
  446. printf("\n");
  447. } else {
  448. printf("\nERROR: Unexpected syntax\n");
  449. raw_dump(level, frm);
  450. }
  451. }
  452. static inline void print_attr_list(int level, struct frame *frm)
  453. {
  454. uint16_t attr_id, psm;
  455. uint8_t channel;
  456. int len, split, n1 = 0, n2 = 0;
  457. if (parse_de_hdr(frm, &n1) == SDP_DE_SEQ) {
  458. len = frm->len;
  459. while (len - (int) frm->len < n1 && (int) frm->len > 0) {
  460. /* Print AttributeID */
  461. if (parse_de_hdr(frm, &n2) == SDP_DE_UINT && n2 == sizeof(attr_id)) {
  462. char *name;
  463. attr_id = p_get_u16(frm);
  464. p_indent(level, 0);
  465. name = get_attr_id_name(attr_id);
  466. if (!name)
  467. name = "unknown";
  468. printf("aid 0x%04x (%s)\n", attr_id, name);
  469. split = (attr_id != SDP_ATTR_ID_PROTOCOL_DESCRIPTOR_LIST);
  470. psm = 0;
  471. channel = 0;
  472. /* Print AttributeValue */
  473. p_indent(level + 1, 0);
  474. print_de(level + 1, frm, split ? NULL: &split,
  475. attr_id == SDP_ATTR_ID_PROTOCOL_DESCRIPTOR_LIST ? &psm : NULL,
  476. attr_id == SDP_ATTR_ID_PROTOCOL_DESCRIPTOR_LIST ? &channel : NULL);
  477. printf("\n");
  478. } else {
  479. printf("\nERROR: Unexpected syntax\n");
  480. raw_dump(level, frm);
  481. break;
  482. }
  483. }
  484. } else {
  485. printf("\nERROR: Unexpected syntax\n");
  486. raw_dump(level, frm);
  487. }
  488. }
  489. static inline void print_attr_lists(int level, struct frame *frm)
  490. {
  491. int n = 0, cnt = 0;
  492. int count = frm->len;
  493. if (parse_de_hdr(frm, &n) == SDP_DE_SEQ) {
  494. while (count - (int) frm->len < n && (int) frm->len > 0) {
  495. p_indent(level, 0);
  496. printf("record #%d\n", cnt++);
  497. print_attr_list(level + 2, frm);
  498. }
  499. } else {
  500. printf("\nERROR: Unexpected syntax\n");
  501. raw_dump(level, frm);
  502. }
  503. }
  504. static inline void print_cont_state(int level, unsigned char *buf)
  505. {
  506. uint8_t cont = buf[0];
  507. int i;
  508. p_indent(level, 0);
  509. printf("cont");
  510. for (i = 0; i < cont + 1; i++)
  511. printf(" %2.2X", buf[i]);
  512. printf("\n");
  513. }
  514. static char *pid2str(uint8_t pid)
  515. {
  516. switch (pid) {
  517. case SDP_ERROR_RSP:
  518. return "Error Rsp";
  519. case SDP_SERVICE_SEARCH_REQ:
  520. return "SS Req";
  521. case SDP_SERVICE_SEARCH_RSP:
  522. return "SS Rsp";
  523. case SDP_SERVICE_ATTR_REQ:
  524. return "SA Req";
  525. case SDP_SERVICE_ATTR_RSP:
  526. return "SA Rsp";
  527. case SDP_SERVICE_SEARCH_ATTR_REQ:
  528. return "SSA Req";
  529. case SDP_SERVICE_SEARCH_ATTR_RSP:
  530. return "SSA Rsp";
  531. default:
  532. return "Unknown";
  533. }
  534. }
  535. #define FRAME_TABLE_SIZE 10
  536. static struct frame frame_table[FRAME_TABLE_SIZE];
  537. static int frame_add(struct frame *frm, int count)
  538. {
  539. register struct frame *fr;
  540. register unsigned char *data;
  541. register int i, len = 0, pos = -1;
  542. for (i = 0; i < FRAME_TABLE_SIZE; i++) {
  543. if (frame_table[i].handle == frm->handle &&
  544. frame_table[i].cid == frm->cid) {
  545. pos = i;
  546. len = frame_table[i].data_len;
  547. break;
  548. }
  549. if (pos < 0 && !frame_table[i].handle)
  550. pos = i;
  551. }
  552. if (pos < 0 || count <= 0)
  553. return -EIO;
  554. data = malloc(len + count);
  555. if (!data)
  556. return -ENOMEM;
  557. fr = &frame_table[pos];
  558. if (len > 0) {
  559. memcpy(data, fr->data, len);
  560. memcpy(data + len, frm->ptr, count);
  561. } else
  562. memcpy(data, frm->ptr, count);
  563. if (fr->data)
  564. free(fr->data);
  565. fr->data = data;
  566. fr->data_len = len + count;
  567. fr->len = fr->data_len;
  568. fr->ptr = fr->data;
  569. fr->dev_id = frm->dev_id;
  570. fr->in = frm->in;
  571. fr->ts = frm->ts;
  572. fr->handle = frm->handle;
  573. fr->cid = frm->cid;
  574. fr->num = frm->num;
  575. fr->channel = frm->channel;
  576. fr->pppdump_fd = frm->pppdump_fd;
  577. fr->audio_fd = frm->audio_fd;
  578. return pos;
  579. }
  580. static struct frame *frame_get(struct frame *frm, int count)
  581. {
  582. register int pos;
  583. pos = frame_add(frm, count);
  584. if (pos < 0)
  585. return frm;
  586. frame_table[pos].handle = 0;
  587. return &frame_table[pos];
  588. }
  589. void sdp_dump(int level, struct frame *frm)
  590. {
  591. sdp_pdu_hdr *hdr = frm->ptr;
  592. uint16_t tid = ntohs(hdr->tid);
  593. uint16_t len = ntohs(hdr->len);
  594. uint16_t total, count;
  595. uint8_t cont;
  596. frm->ptr += SDP_PDU_HDR_SIZE;
  597. frm->len -= SDP_PDU_HDR_SIZE;
  598. p_indent(level, frm);
  599. printf("SDP %s: tid 0x%x len 0x%x\n", pid2str(hdr->pid), tid, len);
  600. switch (hdr->pid) {
  601. case SDP_ERROR_RSP:
  602. p_indent(level + 1, frm);
  603. printf("code 0x%x info ", p_get_u16(frm));
  604. if (frm->len > 0)
  605. hex_dump(0, frm, frm->len);
  606. else
  607. printf("none\n");
  608. break;
  609. case SDP_SERVICE_SEARCH_REQ:
  610. /* Parse ServiceSearchPattern */
  611. print_srv_srch_pat(level + 1, frm);
  612. /* Parse MaximumServiceRecordCount */
  613. p_indent(level + 1, frm);
  614. printf("max %d\n", p_get_u16(frm));
  615. /* Parse ContinuationState */
  616. print_cont_state(level + 1, frm->ptr);
  617. break;
  618. case SDP_SERVICE_SEARCH_RSP:
  619. /* Parse TotalServiceRecordCount */
  620. total = p_get_u16(frm);
  621. /* Parse CurrentServiceRecordCount */
  622. count = p_get_u16(frm);
  623. p_indent(level + 1, frm);
  624. if (count < total)
  625. printf("count %d of %d\n", count, total);
  626. else
  627. printf("count %d\n", count);
  628. /* Parse service record handle(s) */
  629. if (count > 0) {
  630. int i;
  631. p_indent(level + 1, frm);
  632. printf("handle%s", count > 1 ? "s" : "");
  633. for (i = 0; i < count; i++)
  634. printf(" 0x%x", p_get_u32(frm));
  635. printf("\n");
  636. }
  637. /* Parse ContinuationState */
  638. print_cont_state(level + 1, frm->ptr);
  639. break;
  640. case SDP_SERVICE_ATTR_REQ:
  641. /* Parse ServiceRecordHandle */
  642. p_indent(level + 1, frm);
  643. printf("handle 0x%x\n", p_get_u32(frm));
  644. /* Parse MaximumAttributeByteCount */
  645. p_indent(level + 1, frm);
  646. printf("max %d\n", p_get_u16(frm));
  647. /* Parse ServiceSearchPattern */
  648. print_attr_id_list(level + 1, frm);
  649. /* Parse ContinuationState */
  650. print_cont_state(level + 1, frm->ptr);
  651. break;
  652. case SDP_SERVICE_ATTR_RSP:
  653. /* Parse AttributeByteCount */
  654. count = p_get_u16(frm);
  655. p_indent(level + 1, frm);
  656. printf("count %d\n", count);
  657. /* Parse ContinuationState */
  658. cont = *(unsigned char *)(frm->ptr + count);
  659. if (cont == 0) {
  660. /* Parse AttributeList */
  661. print_attr_list(level + 1, frame_get(frm, count));
  662. } else
  663. frame_add(frm, count);
  664. print_cont_state(level + 1, frm->ptr + count);
  665. break;
  666. case SDP_SERVICE_SEARCH_ATTR_REQ:
  667. /* Parse ServiceSearchPattern */
  668. print_srv_srch_pat(level + 1, frm);
  669. /* Parse MaximumAttributeByteCount */
  670. p_indent(level + 1, frm);
  671. printf("max %d\n", p_get_u16(frm));
  672. /* Parse AttributeList */
  673. print_attr_id_list(level + 1, frm);
  674. /* Parse ContinuationState */
  675. print_cont_state(level + 1, frm->ptr);
  676. break;
  677. case SDP_SERVICE_SEARCH_ATTR_RSP:
  678. /* Parse AttributeByteCount */
  679. count = p_get_u16(frm);
  680. p_indent(level + 1, frm);
  681. printf("count %d\n", count);
  682. /* Parse ContinuationState */
  683. cont = *(unsigned char *)(frm->ptr + count);
  684. if (cont == 0) {
  685. /* Parse AttributeLists */
  686. print_attr_lists(level + 1, frame_get(frm, count));
  687. } else
  688. frame_add(frm, count);
  689. print_cont_state(level + 1, frm->ptr + count);
  690. break;
  691. default:
  692. raw_dump(level + 1, frm);
  693. break;
  694. }
  695. }