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