• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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