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