xref: /netbsd-src/usr.bin/sdpquery/print.c (revision ca453df649ce9db45b64d73678ba06cbccf9aa11)
1 /*	$NetBSD: print.c,v 1.16 2011/07/07 10:49:38 plunky Exp $	*/
2 
3 /*-
4  * Copyright (c) 2009 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Iain Hibbert.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include <sys/cdefs.h>
33 __RCSID("$NetBSD: print.c,v 1.16 2011/07/07 10:49:38 plunky Exp $");
34 
35 #include <ctype.h>
36 #include <iconv.h>
37 #include <langinfo.h>
38 #include <sdp.h>
39 #include <stdbool.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <uuid.h>
44 #include <vis.h>
45 
46 #include "sdpquery.h"
47 
48 typedef struct {
49 	uint16_t	id;
50 	const char *	desc;
51 	void		(*print)(sdp_data_t *);
52 } attr_t;
53 
54 typedef struct {
55 	uint16_t	class;
56 	const char *	desc;
57 	attr_t *	attrs;
58 	size_t		nattr;
59 } service_t;
60 
61 typedef struct {
62 	uint16_t	base;
63 	const char *	codeset;
64 } language_t;
65 
66 static const char *string_uuid(uuid_t *);
67 static const char *string_vis(int, const char *, size_t);
68 
69 static void print_hexdump(const char *, const uint8_t *, size_t);
70 static bool print_attribute(uint16_t, sdp_data_t *, attr_t *, size_t);
71 static bool print_universal_attribute(uint16_t, sdp_data_t *);
72 static bool print_language_attribute(uint16_t, sdp_data_t *);
73 static bool print_service_attribute(uint16_t, sdp_data_t *);
74 
75 static void print_bool(sdp_data_t *);
76 static void print_uint8d(sdp_data_t *);
77 static void print_uint8x(sdp_data_t *);
78 static void print_uint16d(sdp_data_t *);
79 static void print_uint16x(sdp_data_t *);
80 static void print_uint32d(sdp_data_t *);
81 static void print_uint32x(sdp_data_t *);
82 static void print_uuid(sdp_data_t *);
83 static void print_uuid_list(sdp_data_t *);
84 static void print_string(sdp_data_t *);
85 static void print_string_list(sdp_data_t *);
86 static void print_url(sdp_data_t *);
87 static void print_profile_version(sdp_data_t *);
88 static void print_language_string(sdp_data_t *);
89 
90 static void print_service_class_id_list(sdp_data_t *);
91 static void print_protocol_descriptor(sdp_data_t *);
92 static void print_protocol_descriptor_list(sdp_data_t *);
93 static void print_language_base_attribute_id_list(sdp_data_t *);
94 static void print_service_availability(sdp_data_t *);
95 static void print_bluetooth_profile_descriptor_list(sdp_data_t *);
96 static void print_additional_protocol_descriptor_lists(sdp_data_t *);
97 static void print_sds_version_number_list(sdp_data_t *);
98 static void print_ct_network(sdp_data_t *);
99 static void print_asrc_features(sdp_data_t *);
100 static void print_asink_features(sdp_data_t *);
101 static void print_avrcp_features(sdp_data_t *);
102 static void print_supported_data_stores(sdp_data_t *);
103 static void print_supported_formats(sdp_data_t *);
104 static void print_hid_version(sdp_data_t *);
105 static void print_hid_device_subclass(sdp_data_t *);
106 static void print_hid_descriptor_list(sdp_data_t *);
107 static void print_security_description(sdp_data_t *);
108 static void print_hf_features(sdp_data_t *);
109 static void print_hfag_network(sdp_data_t *);
110 static void print_hfag_features(sdp_data_t *);
111 static void print_net_access_type(sdp_data_t *);
112 static void print_pnp_source(sdp_data_t *);
113 static void print_mas_types(sdp_data_t *);
114 static void print_supported_repositories(sdp_data_t *);
115 static void print_character_repertoires(sdp_data_t *);
116 static void print_bip_capabilities(sdp_data_t *);
117 static void print_bip_features(sdp_data_t *);
118 static void print_bip_functions(sdp_data_t *);
119 static void print_bip_capacity(sdp_data_t *);
120 static void print_1284id(sdp_data_t *);
121 
122 static void print_rfcomm(sdp_data_t *);
123 static void print_bnep(sdp_data_t *);
124 static void print_avctp(sdp_data_t *);
125 static void print_avdtp(sdp_data_t *);
126 static void print_l2cap(sdp_data_t *);
127 
128 attr_t protocol_list[] = {
129 	{ 0x0001, "SDP",				NULL },
130 	{ 0x0002, "UDP",				NULL },
131 	{ 0x0003, "RFCOMM",				print_rfcomm },
132 	{ 0x0004, "TCP",				NULL },
133 	{ 0x0005, "TCS_BIN",				NULL },
134 	{ 0x0006, "TCS_AT",				NULL },
135 	{ 0x0008, "OBEX",				NULL },
136 	{ 0x0009, "IP",					NULL },
137 	{ 0x000a, "FTP",				NULL },
138 	{ 0x000c, "HTTP",				NULL },
139 	{ 0x000e, "WSP",				NULL },
140 	{ 0x000f, "BNEP",				print_bnep },
141 	{ 0x0010, "UPNP",				NULL },
142 	{ 0x0011, "HIDP",				NULL },
143 	{ 0x0012, "HARDCOPY_CONTROL_CHANNEL",		NULL },
144 	{ 0x0014, "HARDCOPY_DATA_CHANNEL",		NULL },
145 	{ 0x0016, "HARDCOPY_NOTIFICATION",		NULL },
146 	{ 0x0017, "AVCTP",				print_avctp },
147 	{ 0x0019, "AVDTP",				print_avdtp },
148 	{ 0x001b, "CMTP",				NULL },
149 	{ 0x001d, "UDI_C_PLANE",			NULL },
150 	{ 0x001e, "MCAP_CONTROL_CHANNEL",		NULL },
151 	{ 0x001f, "MCAP_DATA_CHANNEL",			NULL },
152 	{ 0x0100, "L2CAP",				print_l2cap },
153 };
154 
155 attr_t universal_attrs[] = {
156 	{ 0x0000, "ServiceRecordHandle",		print_uint32x },
157 	{ 0x0001, "ServiceClassIDList",			print_service_class_id_list },
158 	{ 0x0002, "ServiceRecordState",			print_uint32x },
159 	{ 0x0003, "ServiceID",				print_uuid },
160 	{ 0x0004, "ProtocolDescriptorList",		print_protocol_descriptor_list },
161 	{ 0x0005, "BrowseGroupList",			print_uuid_list },
162 	{ 0x0006, "LanguageBaseAttributeIDList",	print_language_base_attribute_id_list },
163 	{ 0x0007, "ServiceInfoTimeToLive",		print_uint32d },
164 	{ 0x0008, "ServiceAvailability",		print_service_availability },
165 	{ 0x0009, "BluetoothProfileDescriptorList",	print_bluetooth_profile_descriptor_list },
166 	{ 0x000a, "DocumentationURL",			print_url },
167 	{ 0x000b, "ClientExecutableURL",		print_url },
168 	{ 0x000c, "IconURL",				print_url },
169 	{ 0x000d, "AdditionalProtocolDescriptorLists",	print_additional_protocol_descriptor_lists },
170 };
171 
172 attr_t language_attrs[] = { /* Language Attribute Offsets */
173 	{ 0x0000, "ServiceName",			print_language_string },
174 	{ 0x0001, "ServiceDescription",			print_language_string },
175 	{ 0x0002, "ProviderName",			print_language_string },
176 };
177 
178 attr_t sds_attrs[] = {	/* Service Discovery Server */
179 	{ 0x0200, "VersionNumberList",			print_sds_version_number_list },
180 	{ 0x0201, "ServiceDatabaseState",		print_uint32x },
181 };
182 
183 attr_t bgd_attrs[] = {	/* Browse Group Descriptor */
184 	{ 0x0200, "GroupID",				print_uuid },
185 };
186 
187 attr_t ct_attrs[] = { /* Cordless Telephony */
188 	{ 0x0301, "ExternalNetwork",			print_ct_network },
189 };
190 
191 attr_t asrc_attrs[] = { /* Audio Source */
192 	{ 0x0311, "SupportedFeatures",			print_asrc_features },
193 };
194 
195 attr_t asink_attrs[] = { /* Audio Sink */
196 	{ 0x0311, "SupportedFeatures",			print_asink_features },
197 };
198 
199 attr_t avrcp_attrs[] = { /* Audio Video Remote Control Profile */
200 	{ 0x0311, "SupportedFeatures",			print_avrcp_features },
201 };
202 
203 attr_t lan_attrs[] = {	/* LAN Access Using PPP */
204 	{ 0x0200, "IPSubnet",				print_string },
205 };
206 
207 attr_t dun_attrs[] = {	/* Dialup Networking */
208 	{ 0x0305, "AudioFeedbackSupport",		print_bool },
209 };
210 
211 attr_t irmc_sync_attrs[] = { /* IrMC Sync */
212 	{ 0x0301, "SupportedDataStoresList",		print_supported_data_stores },
213 };
214 
215 attr_t opush_attrs[] = { /* Object Push */
216 	{ 0x0303, "SupportedFormatsList",		print_supported_formats },
217 };
218 
219 attr_t hset_attrs[] = {	/* Headset */
220 	{ 0x0302, "RemoteAudioVolumeControl",		print_bool },
221 };
222 
223 attr_t fax_attrs[] = {	/* Fax */
224 	{ 0x0302, "FAXClass1",				print_bool },
225 	{ 0x0303, "FAXClass2.0",			print_bool },
226 	{ 0x0304, "FAXClass2",				print_bool },
227 	{ 0x0305, "AudioFeedbackSupport",		print_bool },
228 };
229 
230 attr_t panu_attrs[] = {	/* Personal Area Networking User */
231 	{ 0x030a, "SecurityDescription",		print_security_description },
232 };
233 
234 attr_t nap_attrs[] = {	/* Network Access Point */
235 	{ 0x030a, "SecurityDescription",		print_security_description },
236 	{ 0x030b, "NetAccessType",			print_net_access_type },
237 	{ 0x030c, "MaxNetAccessRate",			print_uint32d },
238 	{ 0x030d, "IPv4Subnet",				print_string },
239 	{ 0x030e, "IPv6Subnet",				print_string },
240 };
241 
242 attr_t gn_attrs[] = {	/* Group Network */
243 	{ 0x030a, "SecurityDescription",		print_security_description },
244 	{ 0x030d, "IPv4Subnet",				print_string },
245 	{ 0x030e, "IPv6Subnet",				print_string },
246 };
247 
248 attr_t bp_attrs[] = {	/* Basic Printing */
249 	{ 0x0350, "DocumentFormatsSupported",		print_string_list },
250 	{ 0x0352, "CharacterRepertoiresSupported",	print_character_repertoires },
251 	{ 0x0354, "XHTML-PrintImageFormatsSupported",	print_string_list },
252 	{ 0x0356, "ColorSupported",			print_bool },
253 	{ 0x0358, "1284ID",				print_1284id },
254 	{ 0x035a, "PrinterName",			print_string },
255 	{ 0x035c, "PrinterLocation",			print_string },
256 	{ 0x035e, "DuplexSupported",			print_bool },
257 	{ 0x0360, "MediaTypesSupported",		print_string_list },
258 	{ 0x0362, "MaxMediaWidth",			print_uint16d },
259 	{ 0x0364, "MaxMediaLength",			print_uint16d },
260 	{ 0x0366, "EnhancedLayoutSupport",		print_bool },
261 	{ 0x0368, "RUIFormatsSupported",		print_string_list },
262 	{ 0x0370, "ReferencePrintingRUISupported",	print_bool },
263 	{ 0x0372, "DirectPrintingRUISupported",		print_bool },
264 	{ 0x0374, "ReferencePrintingTopURL",		print_url },
265 	{ 0x0376, "DirectPrintingTopURL",		print_url },
266 	{ 0x037a, "DeviceName",				print_string },
267 };
268 
269 attr_t bi_attrs[] = {	/* Basic Imaging */
270 	{ 0x0310, "SupportedCapabilities",		print_bip_capabilities },
271 	{ 0x0311, "SupportedFeatures",			print_bip_features },
272 	{ 0x0312, "SupportedFunctions",			print_bip_functions },
273 	{ 0x0313, "TotalImagingDataCapacity",		print_bip_capacity },
274 };
275 
276 attr_t hf_attrs[] = {	/* Handsfree */
277 	{ 0x0311, "SupportedFeatures",			print_hf_features },
278 };
279 
280 attr_t hfag_attrs[] = {	/* Handsfree Audio Gateway */
281 	{ 0x0301, "Network",				print_hfag_network },
282 	{ 0x0311, "SupportedFeatures",			print_hfag_features },
283 };
284 
285 attr_t rui_attrs[] = {	/* Reflected User Interface */
286 	{ 0x0368, "RUIFormatsSupported",		print_string_list },
287 	{ 0x0378, "PrinterAdminRUITopURL",		print_url },
288 };
289 
290 attr_t hid_attrs[] = {	/* Human Interface Device */
291 	{ 0x0200, "HIDDeviceReleaseNumber",		print_hid_version },
292 	{ 0x0201, "HIDParserVersion",			print_hid_version },
293 	{ 0x0202, "HIDDeviceSubClass",			print_hid_device_subclass },
294 	{ 0x0203, "HIDCountryCode",			print_uint8x },
295 	{ 0x0204, "HIDVirtualCable",			print_bool },
296 	{ 0x0205, "HIDReconnectInitiate",		print_bool },
297 	{ 0x0206, "HIDDescriptorList",			print_hid_descriptor_list },
298 	{ 0x0207, "HIDLANGIDBaseList",			NULL },
299 	{ 0x0208, "HIDSDPDisable",			print_bool },
300 	{ 0x0209, "HIDBatteryPower",			print_bool },
301 	{ 0x020a, "HIDRemoteWake",			print_bool },
302 	{ 0x020b, "HIDProfileVersion",			print_profile_version },
303 	{ 0x020c, "HIDSupervisionTimeout",		print_uint16d },
304 	{ 0x020d, "HIDNormallyConnectable",		print_bool },
305 	{ 0x020e, "HIDBootDevice",			print_bool },
306 };
307 
308 attr_t hcr_attrs[] = {	/* Hardcopy Cable Replacement */
309 	{ 0x0300, "1284ID",				print_1284id },
310 	{ 0x0302, "DeviceName",				print_string },
311 	{ 0x0304, "FriendlyName",			print_string },
312 	{ 0x0306, "DeviceLocation",			print_string },
313 };
314 
315 attr_t pnp_attrs[] = {	/* Device ID */
316 	{ 0x0200, "SpecificationID",			print_profile_version },
317 	{ 0x0201, "VendorID",				print_uint16x },
318 	{ 0x0202, "ProductID",				print_uint16x },
319 	{ 0x0203, "Version",				print_hid_version },
320 	{ 0x0204, "PrimaryRecord",			print_bool },
321 	{ 0x0205, "VendorIDSource",			print_pnp_source },
322 };
323 
324 attr_t mas_attrs[] = {	/* Message Access Server */
325 	{ 0x0315, "InstanceID",				print_uint8d },
326 	{ 0x0316, "SupportedMessageTypes",		print_mas_types },
327 };
328 
329 attr_t pse_attrs[] = {	/* Phonebook Access Server */
330 	{ 0x0314, "SupportedRepositories",		print_supported_repositories },
331 };
332 
333 #define A(a)	a, __arraycount(a)
334 service_t service_list[] = {
335 	{ 0x1000, "Service Discovery Server",		A(sds_attrs) },
336 	{ 0x1001, "Browse Group Descriptor",		A(bgd_attrs) },
337 	{ 0x1002, "Public Browse Root",			NULL, 0 },
338 	{ 0x1101, "Serial Port",			NULL, 0 },
339 	{ 0x1102, "LAN Access Using PPP",		A(lan_attrs) },
340 	{ 0x1103, "Dialup Networking",			A(dun_attrs) },
341 	{ 0x1104, "IrMC Sync",				A(irmc_sync_attrs) },
342 	{ 0x1105, "Object Push",			A(opush_attrs) },
343 	{ 0x1106, "File Transfer",			NULL, 0 },
344 	{ 0x1107, "IrMC Sync Command",			NULL, 0 },
345 	{ 0x1108, "Headset",				A(hset_attrs) },
346 	{ 0x1109, "Cordless Telephony",			A(ct_attrs) },
347 	{ 0x110a, "Audio Source",			A(asrc_attrs) },
348 	{ 0x110b, "Audio Sink",				A(asink_attrs) },
349 	{ 0x110c, "A/V Remote Control Target",		A(avrcp_attrs) },
350 	{ 0x110d, "Advanced Audio Distribution",	NULL, 0 },
351 	{ 0x110e, "A/V Remote Control",			A(avrcp_attrs) },
352 	{ 0x110f, "Video Conferencing",			NULL, 0 },
353 	{ 0x1110, "Intercom",				NULL, 0 },
354 	{ 0x1111, "Fax",				A(fax_attrs) },
355 	{ 0x1112, "Headset Audio Gateway",		NULL, 0 },
356 	{ 0x1113, "WAP",				NULL, 0 },
357 	{ 0x1114, "WAP Client",				NULL, 0 },
358 	{ 0x1115, "Personal Area Networking User",	A(panu_attrs) },
359 	{ 0x1116, "Network Access Point",		A(nap_attrs) },
360 	{ 0x1117, "Group Network",			A(gn_attrs) },
361 	{ 0x1118, "Direct Printing",			A(bp_attrs) },
362 	{ 0x1119, "Reference Printing",			A(bp_attrs) },
363 	{ 0x111a, "Imaging",				NULL, 0 },
364 	{ 0x111b, "Imaging Responder",			A(bi_attrs) },
365 	{ 0x111c, "Imaging Automatic Archive",		A(bi_attrs) },
366 	{ 0x111d, "Imaging Referenced Objects",		A(bi_attrs) },
367 	{ 0x111e, "Handsfree",				A(hf_attrs) },
368 	{ 0x111f, "Handsfree Audio Gateway",		A(hfag_attrs) },
369 	{ 0x1120, "Direct Printing Reference Objects",	NULL, 0 },
370 	{ 0x1121, "Reflected User Interface",		A(rui_attrs) },
371 	{ 0x1122, "Basic Printing",			NULL, 0 },
372 	{ 0x1123, "Printing Status",			A(bp_attrs) },
373 	{ 0x1124, "Human Interface Device",		A(hid_attrs) },
374 	{ 0x1125, "Hardcopy Cable Replacement",		NULL, 0 },
375 	{ 0x1126, "Hardcopy Cable Replacement Print",	A(hcr_attrs) },
376 	{ 0x1127, "Hardcopy Cable Replacement Scan",	A(hcr_attrs) },
377 	{ 0x1128, "Common ISDN Access",			NULL, 0 },
378 	{ 0x1129, "Video Conferencing GW",		NULL, 0 },
379 	{ 0x112a, "UDI MT",				NULL, 0 },
380 	{ 0x112b, "UDI TA",				NULL, 0 },
381 	{ 0x112c, "Audio/Video",			NULL, 0 },
382 	{ 0x112d, "SIM Access",				NULL, 0 },
383 	{ 0x112e, "Phonebook Access Client",		NULL, 0 },
384 	{ 0x112f, "Phonebook Access Server",		A(pse_attrs) },
385 	{ 0x1130, "Phonebook Access",			NULL, 0 },
386 	{ 0x1131, "Headset HS",				NULL, 0 },
387 	{ 0x1132, "Message Access Server",		A(mas_attrs) },
388 	{ 0x1133, "Message Notification Server",	NULL, 0 },
389 	{ 0x1134, "Message Access Profile",		NULL, 0 },
390 	{ 0x1200, "PNP Information",			A(pnp_attrs) },
391 	{ 0x1201, "Generic Networking",			NULL, 0 },
392 	{ 0x1202, "Generic File Transfer",		NULL, 0 },
393 	{ 0x1203, "Generic Audio",			NULL, 0 },
394 	{ 0x1204, "Generic Telephony",			NULL, 0 },
395 	{ 0x1205, "UPNP",				NULL, 0 },
396 	{ 0x1206, "UPNP IP",				NULL, 0 },
397 	{ 0x1300, "UPNP IP PAN",			NULL, 0 },
398 	{ 0x1301, "UPNP IP LAP",			NULL, 0 },
399 	{ 0x1302, "UPNP IP L2CAP",			NULL, 0 },
400 	{ 0x1303, "Video Source",			NULL, 0 },
401 	{ 0x1304, "Video Sink",				NULL, 0 },
402 	{ 0x1305, "Video Distribution",			NULL, 0 },
403 	{ 0x1400, "HDP",				NULL, 0 },
404 	{ 0x1401, "HDP Source",				NULL, 0 },
405 	{ 0x1402, "HDP Sink",				NULL, 0 },
406 };
407 #undef A
408 
409 /* extracted Service Class ID List */
410 #define MAX_SERVICES		16
411 static size_t nservices;
412 static uint16_t service_class[MAX_SERVICES];
413 
414 /* extracted Language Base Attribute ID List */
415 #define MAX_LANGUAGES		16
416 static int nlanguages;
417 static language_t language[MAX_LANGUAGES];
418 static int current;
419 
420 static bool
421 sdp_get_uint8(sdp_data_t *d, uint8_t *vp)
422 {
423 	uintmax_t v;
424 
425 	if (sdp_data_type(d) != SDP_DATA_UINT8
426 	    || !sdp_get_uint(d, &v))
427 		return false;
428 
429 	*vp = (uint8_t)v;
430 	return true;
431 }
432 
433 static bool
434 sdp_get_uint16(sdp_data_t *d, uint16_t *vp)
435 {
436 	uintmax_t v;
437 
438 	if (sdp_data_type(d) != SDP_DATA_UINT16
439 	    || !sdp_get_uint(d, &v))
440 		return false;
441 
442 	*vp = (uint16_t)v;
443 	return true;
444 }
445 
446 static bool
447 sdp_get_uint32(sdp_data_t *d, uint32_t *vp)
448 {
449 	uintmax_t v;
450 
451 	if (sdp_data_type(d) != SDP_DATA_UINT32
452 	    || !sdp_get_uint(d, &v))
453 		return false;
454 
455 	*vp = (uint32_t)v;
456 	return true;
457 }
458 
459 static bool
460 sdp_get_uint64(sdp_data_t *d, uint64_t *vp)
461 {
462 	uintmax_t v;
463 
464 	if (sdp_data_type(d) != SDP_DATA_UINT64
465 	    || !sdp_get_uint(d, &v))
466 		return false;
467 
468 	*vp = (uint64_t)v;
469 	return true;
470 }
471 
472 void
473 print_record(sdp_data_t *rec)
474 {
475 	sdp_data_t value;
476 	uint16_t id;
477 
478 	nservices = 0;
479 	nlanguages = 0;
480 	current = -1;
481 
482 	while (sdp_get_attr(rec, &id, &value)) {
483 		if (Xflag) {
484 			printf("AttributeID 0x%04x:\n", id);
485 			print_hexdump("     ", value.next,
486 			    (size_t)(value.end - value.next));
487 		} else if (Rflag) {
488 			printf("AttributeID 0x%04x:\n", id);
489 			sdp_data_print(&value, 4);
490 		} else if (print_universal_attribute(id, &value)
491 		    || print_language_attribute(id, &value)
492 		    || print_service_attribute(id, &value)) {
493 			if (value.next != value.end)
494 			    printf("    [additional data ignored]\n");
495 		} else {
496 			printf("AttributeID 0x%04x:\n", id);
497 			sdp_data_print(&value, 4);
498 		}
499 	}
500 }
501 
502 static const char *
503 string_uuid(uuid_t *uuid)
504 {
505 	static char buf[64];
506 	const char *desc;
507 	uuid_t u;
508 	size_t i;
509 
510 	u = *uuid;
511 	u.time_low = 0;
512 	if (!uuid_equal(&u, &BLUETOOTH_BASE_UUID, NULL)) {
513 		snprintf(buf, sizeof(buf),
514 		    "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
515 		    uuid->time_low, uuid->time_mid, uuid->time_hi_and_version,
516 		    uuid->clock_seq_hi_and_reserved, uuid->clock_seq_low,
517 		    uuid->node[0], uuid->node[1], uuid->node[2],
518 		    uuid->node[3], uuid->node[4], uuid->node[5]);
519 
520 		return buf;
521 	}
522 
523 	desc = NULL;
524 	for (i = 0; i < __arraycount(service_list); i++) {
525 		if (uuid->time_low == service_list[i].class) {
526 			desc = service_list[i].desc;
527 			break;
528 		}
529 	}
530 
531 	for (i = 0; i < __arraycount(protocol_list); i++) {
532 		if (uuid->time_low == protocol_list[i].id) {
533 			desc = protocol_list[i].desc;
534 			break;
535 		}
536 	}
537 
538 	if (!Nflag && desc) {
539 		snprintf(buf, sizeof(buf), "%s", desc);
540 		return buf;
541 	}
542 
543 	snprintf(buf, sizeof(buf), "%s%s(0x%*.*x)",
544 	    (desc == NULL ? "" : desc),
545 	    (desc == NULL ? "" : " "),
546 	    (uuid->time_low > UINT16_MAX ? 8 : 4),
547 	    (uuid->time_low > UINT16_MAX ? 8 : 4),
548 	    uuid->time_low);
549 
550 	return buf;
551 }
552 
553 static const char *
554 string_vis(int style, const char *src, size_t len)
555 {
556 	static char buf[50];
557 	char *dst = buf;
558 
559 	buf[0] = '\0';
560 	style |= VIS_NL;
561 	while (len > 0 && (dst + 5) < (buf + sizeof(buf))) {
562 		dst = vis(dst, src[0], style, (len > 1 ? src[1] : 0));
563 		src++;
564 		len--;
565 	}
566 
567 	return buf;
568 }
569 
570 static void
571 print_hexdump(const char *title, const uint8_t *data, size_t len)
572 {
573 	int n, i;
574 
575 	i = 0;
576 	n = printf("%s", title);
577 
578 	while (len-- > 0) {
579 		if (++i > 8) {
580 			printf("\n%*s", n, "");
581 			i = 1;
582 		}
583 
584 		printf(" 0x%02x", *data++);
585 	}
586 
587 	printf("\n");
588 }
589 
590 static bool
591 print_attribute(uint16_t id, sdp_data_t *value, attr_t *attr, size_t count)
592 {
593 	size_t i;
594 
595 	for (i = 0; i < count; i++) {
596 		if (id == attr[i].id) {
597 			printf("%s", attr[i].desc);
598 
599 			if (Nflag) {
600 				printf(" (");
601 
602 				if (current != -1)
603 					printf("0x%04x + ", language[current].base);
604 
605 				printf("0x%04x)", id);
606 			}
607 
608 			printf(": ");
609 
610 			if (attr[i].print == NULL) {
611 				printf("\n");
612 				sdp_data_print(value, 4);
613 				value->next = value->end;
614 			} else {
615 				(attr[i].print)(value);
616 			}
617 
618 			return true;
619 		}
620 	}
621 
622 	return false;
623 }
624 
625 static bool
626 print_universal_attribute(uint16_t id, sdp_data_t *value)
627 {
628 
629 	return print_attribute(id, value,
630 	    universal_attrs, __arraycount(universal_attrs));
631 }
632 
633 static bool
634 print_language_attribute(uint16_t id, sdp_data_t *value)
635 {
636 	bool done = false;
637 
638 	for (current = 0; current < nlanguages && !done; current++)
639 		done = print_attribute(id - language[current].base, value,
640 		    language_attrs, __arraycount(language_attrs));
641 
642 	current = -1;
643 	return done;
644 }
645 
646 static bool
647 print_service_attribute(uint16_t id, sdp_data_t *value)
648 {
649 	size_t i, j;
650 
651 	for (i = 0; i < nservices; i++) {
652 		for (j = 0; j < __arraycount(service_list); j++) {
653 			if (service_class[i] == service_list[j].class
654 			    && print_attribute(id, value,
655 			    service_list[j].attrs, service_list[j].nattr))
656 				return true;
657 		}
658 	}
659 
660 	return false;
661 }
662 
663 static void
664 print_bool(sdp_data_t *data)
665 {
666 	bool v;
667 
668 	if (!sdp_get_bool(data, &v))
669 		return;
670 
671 	printf("%s\n", (v ? "true" : "false"));
672 }
673 
674 static void
675 print_uint8d(sdp_data_t *data)
676 {
677 	uint8_t v;
678 
679 	if (!sdp_get_uint8(data, &v))
680 		return;
681 
682 	printf("%d\n", v);
683 }
684 
685 static void
686 print_uint8x(sdp_data_t *data)
687 {
688 	uint8_t v;
689 
690 	if (!sdp_get_uint8(data, &v))
691 		return;
692 
693 	printf("0x%02x\n", v);
694 }
695 
696 static void
697 print_uint16d(sdp_data_t *data)
698 {
699 	uint16_t v;
700 
701 	if (!sdp_get_uint16(data, &v))
702 		return;
703 
704 	printf("%d\n", v);
705 }
706 
707 static void
708 print_uint16x(sdp_data_t *data)
709 {
710 	uint16_t v;
711 
712 	if (!sdp_get_uint16(data, &v))
713 		return;
714 
715 	printf("0x%04x\n", v);
716 }
717 
718 static void
719 print_uint32x(sdp_data_t *data)
720 {
721 	uint32_t v;
722 
723 	if (!sdp_get_uint32(data, &v))
724 		return;
725 
726 	printf("0x%08x\n", v);
727 }
728 
729 static void
730 print_uint32d(sdp_data_t *data)
731 {
732 	uint32_t v;
733 
734 	if (!sdp_get_uint32(data, &v))
735 		return;
736 
737 	printf("%d\n", v);
738 }
739 
740 static void
741 print_uuid(sdp_data_t *data)
742 {
743 	uuid_t uuid;
744 
745 	if (!sdp_get_uuid(data, &uuid))
746 		return;
747 
748 	printf("%s\n", string_uuid(&uuid));
749 }
750 
751 static void
752 print_uuid_list(sdp_data_t *data)
753 {
754 	sdp_data_t seq;
755 	uuid_t uuid;
756 
757 	if (!sdp_get_seq(data, &seq))
758 		return;
759 
760 	printf("\n");
761 	while (sdp_get_uuid(&seq, &uuid))
762 		printf("    %s\n", string_uuid(&uuid));
763 
764 	if (seq.next != seq.end)
765 		printf("    [additional data]\n");
766 }
767 
768 static void
769 print_string(sdp_data_t *data)
770 {
771 	char *str;
772 	size_t len;
773 
774 	if (!sdp_get_str(data, &str, &len))
775 		return;
776 
777 	printf("\"%s\"\n", string_vis(VIS_CSTYLE, str, len));
778 }
779 
780 static void
781 print_string_list(sdp_data_t *data)
782 {
783 	char *str, *ep;
784 	size_t len, l;
785 
786 	if (!sdp_get_str(data, &str, &len))
787 		return;
788 
789 	printf("\n");
790 	while (len > 0) {
791 		ep = memchr(str, (int)',', len);
792 		if (ep == NULL) {
793 			l = len;
794 			len = 0;
795 		} else {
796 			l = (size_t)(ep - str);
797 			len -= l + 1;
798 			ep++;
799 		}
800 		printf("    %s\n", string_vis(VIS_CSTYLE, str, l));
801 		str = ep;
802 	}
803 }
804 
805 static void
806 print_url(sdp_data_t *data)
807 {
808 	char *url;
809 	size_t len;
810 
811 	if (!sdp_get_url(data, &url, &len))
812 		return;
813 
814 	printf("\"%s\"\n", string_vis(VIS_HTTPSTYLE, url, len));
815 }
816 
817 static void
818 print_profile_version(sdp_data_t *data)
819 {
820 	uint16_t v;
821 
822 	if (!sdp_get_uint16(data, &v))
823 		return;
824 
825 	printf("v%d.%d\n", (v >> 8), (v & 0xff));
826 }
827 
828 /*
829  * This should only be called through print_language_attribute() which
830  * sets codeset of the string to be printed.
831  */
832 static void
833 print_language_string(sdp_data_t *data)
834 {
835 	char buf[50], *dst, *src;
836 	iconv_t ih;
837 	size_t n, srcleft, dstleft;
838 
839 	if (!sdp_get_str(data, &src, &srcleft))
840 		return;
841 
842 	dst = buf;
843 	dstleft = sizeof(buf);
844 
845 	ih = iconv_open(nl_langinfo(CODESET), language[current].codeset);
846 	if (ih == (iconv_t)-1) {
847 		printf("Can't convert %s string\n", language[current].codeset);
848 		return;
849 	}
850 
851 	n = iconv(ih, (const char **)&src, &srcleft, &dst, &dstleft);
852 
853 	iconv_close(ih);
854 
855 	if (Nflag || n > 0)
856 		printf("(%s) ", language[current].codeset);
857 
858 	printf("\"%.*s%s\n", (int)(sizeof(buf) - dstleft), buf,
859 	    (srcleft > 0 ? " ..." : "\""));
860 }
861 
862 static void
863 print_service_class_id_list(sdp_data_t *data)
864 {
865 	sdp_data_t seq;
866 	uuid_t uuid;
867 
868 	if (!sdp_get_seq(data, &seq))
869 		return;
870 
871 	printf("\n");
872 	while (sdp_get_uuid(&seq, &uuid)) {
873 		printf("    %s\n", string_uuid(&uuid));
874 
875 		if (nservices < MAX_SERVICES) {
876 			service_class[nservices] = uuid.time_low;
877 			uuid.time_low = 0;
878 			if (uuid_equal(&uuid, &BLUETOOTH_BASE_UUID, NULL))
879 				nservices++;
880 		}
881 	}
882 
883 	if (seq.next != seq.end)
884 		printf("    [additional data]\n");
885 }
886 
887 static void
888 print_protocol_descriptor(sdp_data_t *data)
889 {
890 	uuid_t u0, uuid;
891 	size_t i;
892 
893 	if (!sdp_get_uuid(data, &uuid))
894 		return;
895 
896 	u0 = uuid;
897 	u0.time_low = 0;
898 	if (uuid_equal(&u0, &BLUETOOTH_BASE_UUID, NULL)) {
899 		for (i = 0; i < __arraycount(protocol_list); i++) {
900 			if (uuid.time_low == protocol_list[i].id) {
901 				printf("    %s", protocol_list[i].desc);
902 
903 				if (Nflag)
904 					printf(" (0x%04x)", protocol_list[i].id);
905 
906 				if (protocol_list[i].print)
907 					(protocol_list[i].print)(data);
908 
909 				if (data->next != data->end)
910 					printf(" [additional data ignored]");
911 
912 				printf("\n");
913 				return;
914 			}
915 		}
916 	}
917 
918 	printf("    %s\n", string_uuid(&uuid));
919 	sdp_data_print(data, 4);
920 	data->next = data->end;
921 }
922 
923 static void
924 print_protocol_descriptor_list(sdp_data_t *data)
925 {
926 	sdp_data_t seq, proto;
927 
928 	printf("\n");
929 	sdp_get_alt(data, data);	/* strip [optional] alt header */
930 
931 	while (sdp_get_seq(data, &seq))
932 		while (sdp_get_seq(&seq, &proto))
933 			print_protocol_descriptor(&proto);
934 }
935 
936 static void
937 print_language_base_attribute_id_list(sdp_data_t *data)
938 {
939 	sdp_data_t list;
940 	uint16_t v;
941 	const char *codeset;
942 	char lang[2];
943 
944 	if (!sdp_get_seq(data, &list))
945 		return;
946 
947 	printf("\n");
948 	while (list.next < list.end) {
949 		/*
950 		 * ISO-639-1 natural language values are published at
951 		 *	http://www.loc.gov/standards/iso639-2/php/code-list.php
952 		 */
953 		if (!sdp_get_uint16(&list, &v))
954 			break;
955 
956 		be16enc(lang, v);
957 		if (!islower((int)lang[0]) || !islower((int)lang[1]))
958 			break;
959 
960 		/*
961 		 * MIBenum values are published at
962 		 *	http://www.iana.org/assignments/character-sets
963 		 */
964 		if (!sdp_get_uint16(&list, &v))
965 			break;
966 
967 		switch(v) {
968 		case 3:		codeset = "US-ASCII";		break;
969 		case 4:		codeset = "ISO-8859-1";		break;
970 		case 5:		codeset = "ISO-8859-2";		break;
971 		case 106:	codeset = "UTF-8";		break;
972 		case 1013:	codeset = "UTF-16BE";		break;
973 		case 1014:	codeset = "UTF-16LE";		break;
974 		default:	codeset = "Unknown";		break;
975 		}
976 
977 		if (!sdp_get_uint16(&list, &v))
978 			break;
979 
980 		printf("    %.2s.%s base 0x%04x\n", lang, codeset, v);
981 
982 		if (nlanguages < MAX_LANGUAGES) {
983 			language[nlanguages].base = v;
984 			language[nlanguages].codeset = codeset;
985 			nlanguages++;
986 		}
987 	}
988 
989 	if (list.next != list.end)
990 		printf("    [additional data]\n");
991 }
992 
993 static void
994 print_service_availability(sdp_data_t *data)
995 {
996 	uint8_t v;
997 
998 	if (!sdp_get_uint8(data, &v))
999 		return;
1000 
1001 	printf("%d/%d\n", v, UINT8_MAX);
1002 }
1003 
1004 static void
1005 print_bluetooth_profile_descriptor_list(sdp_data_t *data)
1006 {
1007 	sdp_data_t seq, profile;
1008 	uuid_t uuid;
1009 	uint16_t v;
1010 
1011 	if (!sdp_get_seq(data, &seq))
1012 		return;
1013 
1014 	printf("\n");
1015 	while (seq.next < seq.end) {
1016 		if (!sdp_get_seq(&seq, &profile)
1017 		    || !sdp_get_uuid(&profile, &uuid)
1018 		    || !sdp_get_uint16(&profile, &v))
1019 			break;
1020 
1021 		printf("    %s, v%d.%d", string_uuid(&uuid),
1022 		    (v >> 8), (v & 0xff));
1023 
1024 		if (profile.next != profile.end)
1025 			printf(" [additional profile data]");
1026 
1027 		printf("\n");
1028 	}
1029 
1030 	if (seq.next != seq.end)
1031 		printf("    [additional data]\n");
1032 }
1033 
1034 static void
1035 print_additional_protocol_descriptor_lists(sdp_data_t *data)
1036 {
1037 	sdp_data_t seq, stack, proto;
1038 
1039 	printf("\n");
1040 	sdp_get_seq(data, &seq);
1041 
1042 	while (sdp_get_seq(&seq, &stack))
1043 		while (sdp_get_seq(&stack, &proto))
1044 			print_protocol_descriptor(&proto);
1045 
1046 	if (seq.next != seq.end)
1047 		printf("    [additional data]\n");
1048 }
1049 
1050 static void
1051 print_sds_version_number_list(sdp_data_t *data)
1052 {
1053 	sdp_data_t list;
1054 	const char *sep;
1055 	uint16_t v;
1056 
1057 	if (!sdp_get_seq(data, &list))
1058 		return;
1059 
1060 	sep = "";
1061 	while (sdp_get_uint16(&list, &v)) {
1062 		printf("%sv%d.%d", sep, (v >> 8), (v & 0xff));
1063 		sep = ", ";
1064 	}
1065 
1066 	if (list.next != list.end)
1067 		printf(" [additional data]");
1068 
1069 	printf("\n");
1070 }
1071 
1072 static void
1073 print_ct_network(sdp_data_t *data)
1074 {
1075 	uint8_t v;
1076 
1077 	if (!sdp_get_uint8(data, &v))
1078 		return;
1079 
1080 	switch (v) {
1081 	case 0x01:	printf("PSTN");			break;
1082 	case 0x02:	printf("ISDN");			break;
1083 	case 0x03:	printf("GSM");			break;
1084 	case 0x04:	printf("CDMA");			break;
1085 	case 0x05:	printf("Analogue Cellular");	break;
1086 	case 0x06:	printf("Packet Switched");	break;
1087 	case 0x07:	printf("Other");		break;
1088 	default:	printf("0x%02x", v);		break;
1089 	}
1090 
1091 	printf("\n");
1092 }
1093 
1094 static void
1095 print_asrc_features(sdp_data_t *data)
1096 {
1097 	uint16_t v;
1098 
1099 	if (!sdp_get_uint16(data, &v))
1100 		return;
1101 
1102 	if (Nflag)
1103 		printf("(0x%04x)", v);
1104 
1105 	printf("\n");
1106 	if (v & (1<<0))	printf("    Player\n");
1107 	if (v & (1<<1))	printf("    Microphone\n");
1108 	if (v & (1<<2))	printf("    Tuner\n");
1109 	if (v & (1<<3))	printf("    Mixer\n");
1110 }
1111 
1112 static void
1113 print_asink_features(sdp_data_t *data)
1114 {
1115 	uint16_t v;
1116 
1117 	if (!sdp_get_uint16(data, &v))
1118 		return;
1119 
1120 	if (Nflag)
1121 		printf("(0x%04x)", v);
1122 
1123 	printf("\n");
1124 	if (v & (1<<0))	printf("    Headphone\n");
1125 	if (v & (1<<1))	printf("    Speaker\n");
1126 	if (v & (1<<2))	printf("    Recorder\n");
1127 	if (v & (1<<3))	printf("    Amplifier\n");
1128 }
1129 
1130 static void
1131 print_avrcp_features(sdp_data_t *data)
1132 {
1133 	uint16_t v;
1134 
1135 	if (!sdp_get_uint16(data, &v))
1136 		return;
1137 
1138 	if (Nflag)
1139 		printf("(0x%04x)", v);
1140 
1141 	printf("\n");
1142 	if (v & (1<<0))	printf("    Category 1\n");
1143 	if (v & (1<<1))	printf("    Category 2\n");
1144 	if (v & (1<<2))	printf("    Category 3\n");
1145 	if (v & (1<<3))	printf("    Category 4\n");
1146 }
1147 
1148 static void
1149 print_supported_data_stores(sdp_data_t *data)
1150 {
1151 	sdp_data_t list;
1152 	const char *sep;
1153 	uint8_t v;
1154 
1155 	if (!sdp_get_seq(data, &list))
1156 		return;
1157 
1158 	sep = "\n    ";
1159 	while (sdp_get_uint8(&list, &v)) {
1160 		printf("%s", sep);
1161 		sep = ", ";
1162 
1163 		switch(v) {
1164 		case 0x01:	printf("Phonebook");	break;
1165 		case 0x03:	printf("Calendar");	break;
1166 		case 0x05:	printf("Notes");	break;
1167 		case 0x06:	printf("Messages");	break;
1168 		default:	printf("0x%02x", v);	break;
1169 		}
1170 	}
1171 
1172 	if (list.next != list.end)
1173 		printf("   [additional data]");
1174 
1175 	printf("\n");
1176 }
1177 
1178 static void
1179 print_supported_formats(sdp_data_t *data)
1180 {
1181 	sdp_data_t list;
1182 	const char *sep;
1183 	uint8_t v;
1184 
1185 	if (!sdp_get_seq(data, &list))
1186 		return;
1187 
1188 	sep = "\n    ";
1189 	while (sdp_get_uint8(&list, &v)) {
1190 		printf("%s", sep);
1191 		sep = ", ";
1192 
1193 		switch(v) {
1194 		case 0x01:	printf("vCard 2.1");	break;
1195 		case 0x02:	printf("vCard 3.0");	break;
1196 		case 0x03:	printf("vCal 1.0");	break;
1197 		case 0x04:	printf("iCal 2.0");	break;
1198 		case 0x05:	printf("vNote");	break;
1199 		case 0x06:	printf("vMessage");	break;
1200 		case 0xff:	printf("Any");		break;
1201 		default:	printf("0x%02x", v);	break;
1202 		}
1203 	}
1204 
1205 	if (list.next != list.end)
1206 		printf("   [additional data]");
1207 
1208 	printf("\n");
1209 }
1210 
1211 static void
1212 print_hid_version(sdp_data_t *data)
1213 {
1214 	uint16_t v;
1215 
1216 	if (!sdp_get_uint16(data, &v))
1217 		return;
1218 
1219 	printf("v%d.%d.%d\n",
1220 	    ((v & 0xff00) >> 8), ((v & 0x00f0) >> 4), (v & 0x000f));
1221 }
1222 
1223 static void
1224 print_hid_device_subclass(sdp_data_t *data)
1225 {
1226 	uint8_t v;
1227 
1228 	if (!sdp_get_uint8(data, &v))
1229 		return;
1230 
1231 	switch ((v & 0x3c) >> 2) {
1232 	case 1:		printf("Joystick");		break;
1233 	case 2:		printf("Gamepad");		break;
1234 	case 3:		printf("Remote Control");	break;
1235 	case 4:		printf("Sensing Device");	break;
1236 	case 5:		printf("Digitiser Tablet");	break;
1237 	case 6:		printf("Card Reader");		break;
1238 	default:	printf("Peripheral");		break;
1239 	}
1240 
1241 	if (v & 0x40)	printf(" <Keyboard>");
1242 	if (v & 0x80)	printf(" <Mouse>");
1243 
1244 	printf("\n");
1245 }
1246 
1247 static void
1248 print_hid_descriptor_list(sdp_data_t *data)
1249 {
1250 	sdp_data_t list, seq;
1251 	uint8_t type;
1252 	const char *name;
1253 	char *str;
1254 	size_t len;
1255 
1256 
1257 	if (!sdp_get_seq(data, &list))
1258 		return;
1259 
1260 	printf("\n");
1261 	while (list.next < list.end) {
1262 		if (!sdp_get_seq(&list, &seq)
1263 		    || !sdp_get_uint8(&seq, &type)
1264 		    || !sdp_get_str(&seq, &str, &len))
1265 			return;
1266 
1267 		switch (type) {
1268 		case 0x22:	name = "Report";		break;
1269 		case 0x23:	name = "Physical Descriptor";	break;
1270 		default:	name = "";			break;
1271 		}
1272 
1273 		printf("    Type 0x%02x: %s\n", type, name);
1274 		print_hexdump("    Data", (uint8_t *)str, len);
1275 
1276 		if (seq.next != seq.end)
1277 			printf("    [additional data]\n");
1278 	}
1279 }
1280 
1281 static void
1282 print_security_description(sdp_data_t *data)
1283 {
1284 	uint16_t v;
1285 
1286 	if (!sdp_get_uint16(data, &v))
1287 		return;
1288 
1289 	switch (v) {
1290 	case 0x0000:	printf("None");				break;
1291 	case 0x0001:	printf("Service-level Security");	break;
1292 	case 0x0002:	printf("802.1x Security");		break;
1293 	default:	printf("0x%04x", v);			break;
1294 	}
1295 
1296 	printf("\n");
1297 }
1298 
1299 static void
1300 print_hf_features(sdp_data_t *data)
1301 {
1302 	uint16_t v;
1303 
1304 	if (!sdp_get_uint16(data, &v))
1305 		return;
1306 
1307 	if (Nflag)
1308 		printf("(0x%04x)", v);
1309 
1310 	printf("\n");
1311 	if (v & (1<<0))	printf("    Echo Cancellation/Noise Reduction\n");
1312 	if (v & (1<<1))	printf("    Call Waiting\n");
1313 	if (v & (1<<2))	printf("    Caller Line Identification\n");
1314 	if (v & (1<<3))	printf("    Voice Recognition\n");
1315 	if (v & (1<<4))	printf("    Volume Control\n");
1316 }
1317 
1318 static void
1319 print_hfag_network(sdp_data_t *data)
1320 {
1321 	uint8_t v;
1322 
1323 	if (!sdp_get_uint8(data, &v))
1324 		return;
1325 
1326 	switch (v) {
1327 	case 0x01:	printf("Ability to reject a call");	break;
1328 	case 0x02:	printf("No ability to reject a call");	break;
1329 	default:	printf("0x%02x", v);			break;
1330 	}
1331 
1332 	printf("\n");
1333 }
1334 
1335 static void
1336 print_hfag_features(sdp_data_t *data)
1337 {
1338 	uint16_t v;
1339 
1340 	if (!sdp_get_uint16(data, &v))
1341 		return;
1342 
1343 	if (Nflag)
1344 		printf("(0x%04x)", v);
1345 
1346 	printf("\n");
1347 	if (v & (1<<0))	printf("    3 Way Calling\n");
1348 	if (v & (1<<1))	printf("    Echo Cancellation/Noise Reduction\n");
1349 	if (v & (1<<2))	printf("    Voice Recognition\n");
1350 	if (v & (1<<3))	printf("    In-band Ring Tone\n");
1351 	if (v & (1<<4))	printf("    Voice Tags\n");
1352 }
1353 
1354 static void
1355 print_net_access_type(sdp_data_t *data)
1356 {
1357 	uint16_t v;
1358 
1359 	if (!sdp_get_uint16(data, &v))
1360 		return;
1361 
1362 	switch(v) {
1363 	case 0x0000:	printf("PSTN");			break;
1364 	case 0x0001:	printf("ISDN");			break;
1365 	case 0x0002:	printf("DSL");			break;
1366 	case 0x0003:	printf("Cable Modem");		break;
1367 	case 0x0004:	printf("10Mb Ethernet");	break;
1368 	case 0x0005:	printf("100Mb Ethernet");	break;
1369 	case 0x0006:	printf("4Mb Token Ring");	break;
1370 	case 0x0007:	printf("16Mb Token Ring");	break;
1371 	case 0x0008:	printf("100Mb Token Ring");	break;
1372 	case 0x0009:	printf("FDDI");			break;
1373 	case 0x000a:	printf("GSM");			break;
1374 	case 0x000b:	printf("CDMA");			break;
1375 	case 0x000c:	printf("GPRS");			break;
1376 	case 0x000d:	printf("3G Cellular");		break;
1377 	case 0xfffe:	printf("other");		break;
1378 	default:	printf("0x%04x", v);		break;
1379 	}
1380 
1381 	printf("\n");
1382 }
1383 
1384 static void
1385 print_pnp_source(sdp_data_t *data)
1386 {
1387 	uint16_t v;
1388 
1389 	if (!sdp_get_uint16(data, &v))
1390 		return;
1391 
1392 	switch (v) {
1393 	case 0x0001:	printf("Bluetooth SIG");		break;
1394 	case 0x0002:	printf("USB Implementers Forum");	break;
1395 	default:	printf("0x%04x", v);			break;
1396 	}
1397 
1398 	printf("\n");
1399 }
1400 
1401 static void
1402 print_mas_types(sdp_data_t *data)
1403 {
1404 	uint8_t v;
1405 
1406 	if (!sdp_get_uint8(data, &v))
1407 		return;
1408 
1409 	if (Nflag)
1410 		printf("(0x%02x)", v);
1411 
1412 	printf("\n");
1413 	if (v & (1<<0))	printf("    EMAIL\n");
1414 	if (v & (1<<1))	printf("    SMS_GSM\n");
1415 	if (v & (1<<2))	printf("    SMS_CDMA\n");
1416 	if (v & (1<<3))	printf("    MMS\n");
1417 }
1418 
1419 static void
1420 print_supported_repositories(sdp_data_t *data)
1421 {
1422 	uint8_t v;
1423 
1424 	if (!sdp_get_uint8(data, &v))
1425 		return;
1426 
1427 	if (Nflag)
1428 		printf("(0x%02x)", v);
1429 
1430 	printf("\n");
1431 	if (v & (1<<0))	printf("    Local Phonebook\n");
1432 	if (v & (1<<1))	printf("    SIM Card\n");
1433 }
1434 
1435 static void
1436 print_character_repertoires(sdp_data_t *data)
1437 {
1438 	uintmax_t v;
1439 
1440 	/*
1441 	 * we have no uint128 type so use uintmax as only
1442 	 * only 17-bits are currently defined, and if the
1443 	 * value is out of bounds it will be printed anyway
1444 	 */
1445 	if (sdp_data_type(data) != SDP_DATA_UINT128
1446 	    || !sdp_get_uint(data, &v))
1447 		return;
1448 
1449 	if (Nflag)
1450 		printf("(0x%016jx)", v);
1451 
1452 	printf("\n");
1453 	if (v & (1<< 0)) printf("    ISO-8859-1\n");
1454 	if (v & (1<< 1)) printf("    ISO-8859-2\n");
1455 	if (v & (1<< 2)) printf("    ISO-8859-3\n");
1456 	if (v & (1<< 3)) printf("    ISO-8859-4\n");
1457 	if (v & (1<< 4)) printf("    ISO-8859-5\n");
1458 	if (v & (1<< 5)) printf("    ISO-8859-6\n");
1459 	if (v & (1<< 6)) printf("    ISO-8859-7\n");
1460 	if (v & (1<< 7)) printf("    ISO-8859-8\n");
1461 	if (v & (1<< 8)) printf("    ISO-8859-9\n");
1462 	if (v & (1<< 9)) printf("    ISO-8859-10\n");
1463 	if (v & (1<<10)) printf("    ISO-8859-13\n");
1464 	if (v & (1<<11)) printf("    ISO-8859-14\n");
1465 	if (v & (1<<12)) printf("    ISO-8859-15\n");
1466 	if (v & (1<<13)) printf("    GB18030\n");
1467 	if (v & (1<<14)) printf("    JIS X0208-1990, JIS X0201-1976\n");
1468 	if (v & (1<<15)) printf("    KSC 5601-1992\n");
1469 	if (v & (1<<16)) printf("    Big5\n");
1470 	if (v & (1<<17)) printf("    TIS-620\n");
1471 }
1472 
1473 static void
1474 print_bip_capabilities(sdp_data_t *data)
1475 {
1476 	uint8_t v;
1477 
1478 	if (!sdp_get_uint8(data, &v))
1479 		return;
1480 
1481 	if (Nflag)
1482 		printf("(0x%02x)", v);
1483 
1484 	printf("\n");
1485 	if (v & (1<< 0)) printf("    Generic imaging\n");
1486 	if (v & (1<< 1)) printf("    Capturing\n");
1487 	if (v & (1<< 2)) printf("    Printing\n");
1488 	if (v & (1<< 3)) printf("    Displaying\n");
1489 }
1490 
1491 static void
1492 print_bip_features(sdp_data_t *data)
1493 {
1494 	uint16_t v;
1495 
1496 	if (!sdp_get_uint16(data, &v))
1497 		return;
1498 
1499 	if (Nflag)
1500 		printf("(0x%04x)", v);
1501 
1502 	printf("\n");
1503 	if (v & (1<<0))	printf("    ImagePush\n");
1504 	if (v & (1<<1))	printf("    ImagePush-Store\n");
1505 	if (v & (1<<2))	printf("    ImagePush-Print\n");
1506 	if (v & (1<<3))	printf("    ImagePush-Display\n");
1507 	if (v & (1<<4))	printf("    ImagePull\n");
1508 	if (v & (1<<5))	printf("    AdvancedImagePrinting\n");
1509 	if (v & (1<<6))	printf("    AutomaticArchive\n");
1510 	if (v & (1<<7))	printf("    RemoteCamera\n");
1511 	if (v & (1<<8))	printf("    RemoteDisplay\n");
1512 }
1513 
1514 static void
1515 print_bip_functions(sdp_data_t *data)
1516 {
1517 	uint32_t v;
1518 
1519 	if (!sdp_get_uint32(data, &v))
1520 		return;
1521 
1522 	if (Nflag)
1523 		printf("(0x%08x)", v);
1524 
1525 	printf("\n");
1526 	if (v & (1<< 0)) printf("    GetCapabilities\n");
1527 	if (v & (1<< 1)) printf("    PutImage\n");
1528 	if (v & (1<< 2)) printf("    PutLinkedAttachment\n");
1529 	if (v & (1<< 3)) printf("    PutLinkedThumbnail\n");
1530 	if (v & (1<< 4)) printf("    RemoteDisplay\n");
1531 	if (v & (1<< 5)) printf("    GetImagesList\n");
1532 	if (v & (1<< 6)) printf("    GetImageProperties\n");
1533 	if (v & (1<< 7)) printf("    GetImage\n");
1534 	if (v & (1<< 8)) printf("    GetLinkedThumbnail\n");
1535 	if (v & (1<< 9)) printf("    GetLinkedAttachment\n");
1536 	if (v & (1<<10)) printf("    DeleteImage\n");
1537 	if (v & (1<<11)) printf("    StartPrint\n");
1538 	if (v & (1<<12)) printf("    GetPartialImage\n");
1539 	if (v & (1<<13)) printf("    StartArchive\n");
1540 	if (v & (1<<14)) printf("    GetMonitoringImage\n");
1541 	if (v & (1<<16)) printf("    GetStatus\n");
1542 }
1543 
1544 static void
1545 print_bip_capacity(sdp_data_t *data)
1546 {
1547 	char buf[9];
1548 	uint64_t v;
1549 
1550 	if (!sdp_get_uint64(data, &v))
1551 		return;
1552 
1553 	if (v > INT64_MAX) {
1554 		printf("more than ");
1555 		v = INT64_MAX;
1556 	}
1557 
1558 	(void)humanize_number(buf, sizeof(buf), (int64_t)v,
1559 	    "bytes", HN_AUTOSCALE, HN_NOSPACE);
1560 
1561 	printf("%s\n", buf);
1562 }
1563 
1564 static void
1565 print_1284id(sdp_data_t *data)
1566 {
1567 	char *str, *ep;
1568 	size_t len, l;
1569 
1570 	if (!sdp_get_str(data, &str, &len))
1571 		return;
1572 
1573 	if (len < 2 || len != be16dec(str)) {
1574 		printf("[invalid IEEE 1284 Device ID]\n");
1575 		return;
1576 	}
1577 
1578 	str += 2;
1579 	len -= 2;
1580 
1581 	printf("\n");
1582 	while (len > 0) {
1583 		ep = memchr(str, (int)';', len);
1584 		if (ep == NULL) {
1585 			printf("[invalid IEEE 1284 Device ID]\n");
1586 			return;
1587 		}
1588 
1589 		l = (size_t)(ep - str + 1);
1590 		printf("    %s\n", string_vis(VIS_CSTYLE, str, l));
1591 		str += l;
1592 		len -= l;
1593 	}
1594 }
1595 
1596 static void
1597 print_rfcomm(sdp_data_t *data)
1598 {
1599 	uint8_t v;
1600 
1601 	if (sdp_get_uint8(data, &v))
1602 		printf(" (channel %d)", v);
1603 }
1604 
1605 static void
1606 print_bnep(sdp_data_t *data)
1607 {
1608 	sdp_data_t seq;
1609 	uint16_t v;
1610 	const char *sep;
1611 
1612 	if (!sdp_get_uint16(data, &v)
1613 	    || !sdp_get_seq(data, &seq))
1614 		return;
1615 
1616 	printf(" (v%d.%d", (v >> 8), (v & 0xff));
1617 	sep = "; ";
1618 	while (sdp_get_uint16(&seq, &v)) {
1619 		printf("%s", sep);
1620 		sep = ", ";
1621 
1622 		switch (v) {
1623 		case 0x0800:	printf("IPv4");		break;
1624 		case 0x0806:	printf("ARP");		break;
1625 		case 0x8100:	printf("802.1Q");	break;
1626 		case 0x86dd:	printf("IPv6");		break;
1627 		default:	printf("0x%04x", v);	break;
1628 		}
1629 	}
1630 	printf(")");
1631 
1632 	if (seq.next != seq.end)
1633 		printf(" [additional data]");
1634 }
1635 
1636 static void
1637 print_avctp(sdp_data_t *data)
1638 {
1639 	uint16_t v;
1640 
1641 	if (sdp_get_uint16(data, &v))
1642 		printf(" (v%d.%d)", (v >> 8), (v & 0xff));
1643 }
1644 
1645 static void
1646 print_avdtp(sdp_data_t *data)
1647 {
1648 	uint16_t v;
1649 
1650 	if (sdp_get_uint16(data, &v))
1651 		printf(" (v%d.%d)", (v >> 8), (v & 0xff));
1652 }
1653 
1654 static void
1655 print_l2cap(sdp_data_t *data)
1656 {
1657 	uint16_t v;
1658 
1659 	if (sdp_get_uint16(data, &v))
1660 		printf(" (PSM 0x%04x)", v);
1661 }
1662