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