1 /* $NetBSD: print.c,v 1.2 2009/07/04 16:01:15 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.2 2009/07/04 16:01:15 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 *, int); 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_uint8x(sdp_data_t *); 77 static void print_uint16d(sdp_data_t *); 78 static void print_uint16x(sdp_data_t *); 79 static void print_uint32x(sdp_data_t *); 80 static void print_uint32d(sdp_data_t *); 81 static void print_uuid(sdp_data_t *); 82 static void print_uuid_list(sdp_data_t *); 83 static void print_string(sdp_data_t *); 84 static void print_url(sdp_data_t *); 85 static void print_profile_version(sdp_data_t *); 86 static void print_language_string(sdp_data_t *); 87 88 static void print_service_class_id_list(sdp_data_t *); 89 static void print_protocol_descriptor(sdp_data_t *); 90 static void print_protocol_descriptor_list(sdp_data_t *); 91 static void print_language_base_attribute_id_list(sdp_data_t *); 92 static void print_service_availability(sdp_data_t *); 93 static void print_bluetooth_profile_descriptor_list(sdp_data_t *); 94 static void print_additional_protocol_descriptor_lists(sdp_data_t *); 95 static void print_sds_version_number_list(sdp_data_t *); 96 static void print_ct_network(sdp_data_t *); 97 static void print_asrc_features(sdp_data_t *); 98 static void print_asink_features(sdp_data_t *); 99 static void print_avrcp_features(sdp_data_t *); 100 static void print_supported_data_stores(sdp_data_t *); 101 static void print_supported_formats(sdp_data_t *); 102 static void print_hid_version(sdp_data_t *); 103 static void print_hid_device_subclass(sdp_data_t *); 104 static void print_hid_descriptor_list(sdp_data_t *); 105 static void print_security_description(sdp_data_t *); 106 static void print_hf_features(sdp_data_t *); 107 static void print_hfag_network(sdp_data_t *); 108 static void print_hfag_features(sdp_data_t *); 109 static void print_net_access_type(sdp_data_t *); 110 static void print_pnp_source(sdp_data_t *); 111 112 static void print_rfcomm(sdp_data_t *); 113 static void print_bnep(sdp_data_t *); 114 static void print_avctp(sdp_data_t *); 115 static void print_avdtp(sdp_data_t *); 116 static void print_l2cap(sdp_data_t *); 117 118 attr_t protocol_list[] = { 119 { 0x0001, "SDP", NULL }, 120 { 0x0002, "UDP", NULL }, 121 { 0x0003, "RFCOMM", print_rfcomm }, 122 { 0x0004, "TCP", NULL }, 123 { 0x0005, "TCS_BIN", NULL }, 124 { 0x0006, "TCS_AT", NULL }, 125 { 0x0008, "OBEX", NULL }, 126 { 0x0009, "IP", NULL }, 127 { 0x000a, "FTP", NULL }, 128 { 0x000c, "HTTP", NULL }, 129 { 0x000e, "WSP", NULL }, 130 { 0x000f, "BNEP", print_bnep }, 131 { 0x0010, "UPNP", NULL }, 132 { 0x0011, "HIDP", NULL }, 133 { 0x0012, "HARDCOPY_CONTROL_CHANNEL", NULL }, 134 { 0x0014, "HARDCOPY_DATA_CHANNEL", NULL }, 135 { 0x0016, "HARDCOPY_NOTIFICATION", NULL }, 136 { 0x0017, "AVCTP", print_avctp }, 137 { 0x0019, "AVDTP", print_avdtp }, 138 { 0x001b, "CMTP", NULL }, 139 { 0x001d, "UDI_C_PLANE", NULL }, 140 { 0x0100, "L2CAP", print_l2cap }, 141 }; 142 143 attr_t universal_attrs[] = { 144 { 0x0000, "ServiceRecordHandle", print_uint32x }, 145 { 0x0001, "ServiceClassIDList", print_service_class_id_list }, 146 { 0x0002, "ServiceRecordState", print_uint32x }, 147 { 0x0003, "ServiceID", print_uuid }, 148 { 0x0004, "ProtocolDescriptorList", print_protocol_descriptor_list }, 149 { 0x0005, "BrowseGroupList", print_uuid_list }, 150 { 0x0006, "LanguageBaseAttributeIDList", print_language_base_attribute_id_list }, 151 { 0x0007, "ServiceInfoTimeToLive", print_uint32d }, 152 { 0x0008, "ServiceAvailability", print_service_availability }, 153 { 0x0009, "BluetoothProfileDescriptorList", print_bluetooth_profile_descriptor_list }, 154 { 0x000a, "DocumentationURL", print_url }, 155 { 0x000b, "ClientExecutableURL", print_url }, 156 { 0x000c, "IconURL", print_url }, 157 { 0x000d, "AdditionalProtocolDescriptorLists", print_additional_protocol_descriptor_lists }, 158 }; 159 160 attr_t language_attrs[] = { /* Language Attribute Offsets */ 161 { 0x0000, "ServiceName", print_language_string }, 162 { 0x0001, "ServiceDescription", print_language_string }, 163 { 0x0002, "ProviderName", print_language_string }, 164 }; 165 166 attr_t sds_attrs[] = { /* Service Discovery Server */ 167 { 0x0200, "VersionNumberList", print_sds_version_number_list }, 168 { 0x0201, "ServiceDatabaseState", print_uint32x }, 169 }; 170 171 attr_t bgd_attrs[] = { /* Browse Group Descriptor */ 172 { 0x0200, "GroupID", print_uuid }, 173 }; 174 175 attr_t ct_attrs[] = { /* Cordless Telephony */ 176 { 0x0301, "ExternalNetwork", print_ct_network }, 177 }; 178 179 attr_t asrc_attrs[] = { /* Audio Source */ 180 { 0x0311, "SupportedFeatures", print_asrc_features }, 181 }; 182 183 attr_t asink_attrs[] = { /* Audio Sink */ 184 { 0x0311, "SupportedFeatures", print_asink_features }, 185 }; 186 187 attr_t avrcp_attrs[] = { /* Audio Video Remote Control Profile */ 188 { 0x0311, "SupportedFeatures", print_avrcp_features }, 189 }; 190 191 attr_t lan_attrs[] = { /* LAN Access Using PPP */ 192 { 0x0200, "IPSubnet", print_string }, 193 }; 194 195 attr_t dun_attrs[] = { /* Dialup Networking */ 196 { 0x0305, "AudioFeedbackSupport", print_bool }, 197 }; 198 199 attr_t irmc_sync_attrs[] = { /* IrMC Sync */ 200 { 0x0301, "SupportedDataStoresList", print_supported_data_stores }, 201 }; 202 203 attr_t opush_attrs[] = { /* Object Push */ 204 { 0x0303, "SupportedFormatsList", print_supported_formats }, 205 }; 206 207 attr_t hset_attrs[] = { /* Headset */ 208 { 0x0302, "RemoteAudioVolumeControl", print_bool }, 209 }; 210 211 attr_t fax_attrs[] = { /* Fax */ 212 { 0x0302, "FAXClass1", print_bool }, 213 { 0x0303, "FAXClass2.0", print_bool }, 214 { 0x0304, "FAXClass2", print_bool }, 215 { 0x0305, "AudioFeedbackSupport", print_bool }, 216 }; 217 218 attr_t panu_attrs[] = { /* Personal Area Networking User */ 219 { 0x030a, "SecurityDescription", print_security_description }, 220 }; 221 222 attr_t nap_attrs[] = { /* Network Access Point */ 223 { 0x030a, "SecurityDescription", print_security_description }, 224 { 0x030b, "NetAccessType", print_net_access_type }, 225 { 0x030c, "MaxNetAccessRate", print_uint32d }, 226 { 0x030d, "IPv4Subnet", print_string }, 227 { 0x030e, "IPv6Subnet", print_string }, 228 }; 229 230 attr_t gn_attrs[] = { /* Group Network */ 231 { 0x030a, "SecurityDescription", print_security_description }, 232 { 0x030d, "IPv4Subnet", print_string }, 233 { 0x030e, "IPv6Subnet", print_string }, 234 }; 235 236 attr_t hf_attrs[] = { /* Handsfree */ 237 { 0x0311, "SupportedFeatures", print_hf_features }, 238 }; 239 240 attr_t hfag_attrs[] = { /* Handsfree Audio Gateway */ 241 { 0x0301, "Network", print_hfag_network }, 242 { 0x0311, "SupportedFeatures", print_hfag_features }, 243 }; 244 245 attr_t hid_attrs[] = { /* Human Interface Device */ 246 { 0x0200, "HIDDeviceReleaseNumber", print_hid_version }, 247 { 0x0201, "HIDParserVersion", print_hid_version }, 248 { 0x0202, "HIDDeviceSubClass", print_hid_device_subclass }, 249 { 0x0203, "HIDCountryCode", print_uint8x }, 250 { 0x0204, "HIDVirtualCable", print_bool }, 251 { 0x0205, "HIDReconnectInitiate", print_bool }, 252 { 0x0206, "HIDDescriptorList", print_hid_descriptor_list }, 253 { 0x0207, "HIDLANGIDBaseList", NULL }, 254 { 0x0208, "HIDSDPDisable", print_bool }, 255 { 0x0209, "HIDBatteryPower", print_bool }, 256 { 0x020a, "HIDRemoteWake", print_bool }, 257 { 0x020b, "HIDProfileVersion", print_profile_version }, 258 { 0x020c, "HIDSupervisionTimeout", print_uint16d }, 259 { 0x020d, "HIDNormallyConnectable", print_bool }, 260 { 0x020e, "HIDBootDevice", print_bool }, 261 }; 262 263 attr_t pnp_attrs[] = { /* Device ID */ 264 { 0x0200, "SpecificationID", print_profile_version }, 265 { 0x0201, "VendorID", print_uint16x }, 266 { 0x0202, "ProductID", print_uint16x }, 267 { 0x0203, "Version", print_hid_version }, 268 { 0x0204, "PrimaryRecord", print_bool }, 269 { 0x0205, "VendorIDSource", print_pnp_source }, 270 }; 271 272 #define A(a) a, __arraycount(a) 273 service_t service_list[] = { 274 { 0x1000, "Service Discovery Server", A(sds_attrs) }, 275 { 0x1001, "Browse Group Descriptor", A(bgd_attrs) }, 276 { 0x1002, "Public Browse Root", NULL, 0 }, 277 { 0x1101, "Serial Port", NULL, 0 }, 278 { 0x1102, "LAN Access Using PPP", A(lan_attrs) }, 279 { 0x1103, "Dialup Networking", A(dun_attrs) }, 280 { 0x1104, "IrMC Sync", A(irmc_sync_attrs) }, 281 { 0x1105, "Object Push", A(opush_attrs) }, 282 { 0x1106, "File Transfer", NULL, 0 }, 283 { 0x1107, "IrMC Sync Command", NULL, 0 }, 284 { 0x1108, "Headset", A(hset_attrs) }, 285 { 0x1109, "Cordless Telephony", A(ct_attrs) }, 286 { 0x110a, "Audio Source", A(asrc_attrs) }, 287 { 0x110b, "Audio Sink", A(asink_attrs) }, 288 { 0x110c, "A/V Remote Control Target", A(avrcp_attrs) }, 289 { 0x110d, "Advanced Audio Distribution", NULL, 0 }, 290 { 0x110e, "A/V Remote Control", A(avrcp_attrs) }, 291 { 0x110f, "Video Conferencing", NULL, 0 }, 292 { 0x1110, "Intercom", NULL, 0 }, 293 { 0x1111, "Fax", A(fax_attrs) }, 294 { 0x1112, "Headset Audio Gateway", NULL, 0 }, 295 { 0x1113, "WAP", NULL, 0 }, 296 { 0x1114, "WAP Client", NULL, 0 }, 297 { 0x1115, "Personal Area Networking User", A(panu_attrs) }, 298 { 0x1116, "Network Access Point", A(nap_attrs) }, 299 { 0x1117, "Group Network", A(gn_attrs) }, 300 { 0x1118, "Direct Printing", NULL, 0 }, 301 { 0x1119, "Reference Printing", NULL, 0 }, 302 { 0x111a, "Imaging", NULL, 0 }, 303 { 0x111b, "Imaging Responder", NULL, 0 }, 304 { 0x111c, "Imaging Automatic Archive", NULL, 0 }, 305 { 0x111d, "Imaging Referenced Objects", NULL, 0 }, 306 { 0x111e, "Handsfree", A(hf_attrs) }, 307 { 0x111f, "Handsfree Audio Gateway", A(hfag_attrs) }, 308 { 0x1120, "Direct Printing Reference Objects", NULL, 0 }, 309 { 0x1121, "Reflected User Interface", NULL, 0 }, 310 { 0x1122, "Basic Printing", NULL, 0 }, 311 { 0x1123, "Printing Status", NULL, 0 }, 312 { 0x1124, "Human Interface Device", A(hid_attrs) }, 313 { 0x1125, "Hardcopy Cable Replacement", NULL, 0 }, 314 { 0x1126, "Hardcopy Cable Replacement Print", NULL, 0 }, 315 { 0x1127, "Hardcopy Cable Replacement Scan", NULL, 0 }, 316 { 0x1128, "Common ISDN Access", NULL, 0 }, 317 { 0x1129, "Video Conferencing GW", NULL, 0 }, 318 { 0x112a, "UDI MT", NULL, 0 }, 319 { 0x112b, "UDI TA", NULL, 0 }, 320 { 0x112c, "Audio/Video", NULL, 0 }, 321 { 0x112d, "SIM Access", NULL, 0 }, 322 { 0x1200, "PNP Information", A(pnp_attrs) }, 323 { 0x1201, "Generic Networking", NULL, 0 }, 324 { 0x1202, "Generic File Transfer", NULL, 0 }, 325 { 0x1203, "Generic Audio", NULL, 0 }, 326 { 0x1204, "Generic Telephony", NULL, 0 }, 327 { 0x1205, "UPNP", NULL, 0 }, 328 { 0x1206, "UPNP IP", NULL, 0 }, 329 { 0x1300, "UPNP IP PAN", NULL, 0 }, 330 { 0x1301, "UPNP IP LAP", NULL, 0 }, 331 { 0x1302, "UPNP IP L2CAP", NULL, 0 }, 332 }; 333 #undef A 334 335 /* extracted Service Class ID List */ 336 #define MAX_SERVICES 16 337 static size_t nservices; 338 static uint16_t service_class[MAX_SERVICES]; 339 340 /* extracted Language Base Attribute ID List */ 341 #define MAX_LANGUAGES 16 342 static int nlanguages; 343 static language_t language[MAX_LANGUAGES]; 344 static int current; 345 346 static bool 347 sdp_get_uint8(sdp_data_t *d, uint8_t *vp) 348 { 349 uintmax_t v; 350 351 if (sdp_data_type(d) != SDP_DATA_UINT8 352 || !sdp_get_uint(d, &v)) 353 return false; 354 355 *vp = (uint8_t)v; 356 return true; 357 } 358 359 static bool 360 sdp_get_uint16(sdp_data_t *d, uint16_t *vp) 361 { 362 uintmax_t v; 363 364 if (sdp_data_type(d) != SDP_DATA_UINT16 365 || !sdp_get_uint(d, &v)) 366 return false; 367 368 *vp = (uint16_t)v; 369 return true; 370 } 371 372 static bool 373 sdp_get_uint32(sdp_data_t *d, uint32_t *vp) 374 { 375 uintmax_t v; 376 377 if (sdp_data_type(d) != SDP_DATA_UINT32 378 || !sdp_get_uint(d, &v)) 379 return false; 380 381 *vp = (uint32_t)v; 382 return true; 383 } 384 385 void 386 print_record(sdp_data_t *rec) 387 { 388 sdp_data_t value; 389 uint16_t id; 390 391 nservices = 0; 392 nlanguages = 0; 393 current = -1; 394 395 while (sdp_get_attr(rec, &id, &value)) { 396 if (Xflag) { 397 printf("AttributeID 0x%04x:\n", id); 398 print_hexdump(" ", value.next, value.end - value.next); 399 } else if (Rflag) { 400 printf("AttributeID 0x%04x:\n", id); 401 sdp_data_print(&value, 4); 402 } else if (print_universal_attribute(id, &value) 403 || print_language_attribute(id, &value) 404 || print_service_attribute(id, &value)) { 405 if (value.next != value.end) 406 printf(" [additional data ignored]\n"); 407 } else { 408 printf("AttributeID 0x%04x:\n", id); 409 sdp_data_print(&value, 4); 410 } 411 } 412 } 413 414 static const char * 415 string_uuid(uuid_t *uuid) 416 { 417 static char buf[64]; 418 const char *desc; 419 uuid_t u; 420 size_t i; 421 422 u = *uuid; 423 u.time_low = 0; 424 if (!uuid_equal(&u, &BLUETOOTH_BASE_UUID, NULL)) { 425 snprintf(buf, sizeof(buf), 426 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 427 uuid->time_low, uuid->time_mid, uuid->time_hi_and_version, 428 uuid->clock_seq_hi_and_reserved, uuid->clock_seq_low, 429 uuid->node[0], uuid->node[1], uuid->node[2], 430 uuid->node[3], uuid->node[4], uuid->node[5]); 431 432 return buf; 433 } 434 435 desc = NULL; 436 for (i = 0; i < __arraycount(service_list); i++) { 437 if (uuid->time_low == service_list[i].class) { 438 desc = service_list[i].desc; 439 break; 440 } 441 } 442 443 for (i = 0; i < __arraycount(protocol_list); i++) { 444 if (uuid->time_low == protocol_list[i].id) { 445 desc = protocol_list[i].desc; 446 break; 447 } 448 } 449 450 if (!Nflag && desc) { 451 snprintf(buf, sizeof(buf), "%s", desc); 452 return buf; 453 } 454 455 snprintf(buf, sizeof(buf), "%s%s(0x%*.*x)", 456 (desc == NULL ? "" : desc), 457 (desc == NULL ? "" : " "), 458 (uuid->time_low > UINT16_MAX ? 8 : 4), 459 (uuid->time_low > UINT16_MAX ? 8 : 4), 460 uuid->time_low); 461 462 return buf; 463 } 464 465 static const char * 466 string_vis(int style, const char *src, size_t len) 467 { 468 static char buf[50]; 469 char *dst = buf; 470 471 style |= VIS_NL; 472 while (len > 0 && (dst + 5) < (buf + sizeof(buf))) { 473 dst = vis(dst, src[0], style, (len > 1 ? src[1] : 0)); 474 src++; 475 len--; 476 } 477 478 return buf; 479 } 480 481 static void 482 print_hexdump(const char *title, const uint8_t *data, size_t len) 483 { 484 int n, i; 485 486 i = 0; 487 n = printf("%s", title); 488 489 while (len-- > 0) { 490 if (++i > 8) { 491 printf("\n%*s", n, ""); 492 i = 1; 493 } 494 495 printf(" 0x%02x", *data++); 496 } 497 498 printf("\n"); 499 } 500 501 static bool 502 print_attribute(uint16_t id, sdp_data_t *value, attr_t *attr, int count) 503 { 504 int i; 505 506 for (i = 0; i < count; i++) { 507 if (id == attr[i].id) { 508 printf("%s", attr[i].desc); 509 510 if (Nflag) { 511 printf(" ("); 512 513 if (current != -1) 514 printf("0x%04x + ", language[current].base); 515 516 printf("0x%04x)", id); 517 } 518 519 printf(": "); 520 521 if (attr[i].print == NULL) { 522 printf("\n"); 523 sdp_data_print(value, 4); 524 value->next = value->end; 525 } else { 526 (attr[i].print)(value); 527 } 528 529 return true; 530 } 531 } 532 533 return false; 534 } 535 536 static bool 537 print_universal_attribute(uint16_t id, sdp_data_t *value) 538 { 539 540 return print_attribute(id, value, 541 universal_attrs, __arraycount(universal_attrs)); 542 } 543 544 static bool 545 print_language_attribute(uint16_t id, sdp_data_t *value) 546 { 547 bool done = false; 548 549 for (current = 0; current < nlanguages && !done; current++) 550 done = print_attribute(id - language[current].base, value, 551 language_attrs, __arraycount(language_attrs)); 552 553 current = -1; 554 return done; 555 } 556 557 static bool 558 print_service_attribute(uint16_t id, sdp_data_t *value) 559 { 560 size_t i, j; 561 562 for (i = 0; i < nservices; i++) { 563 for (j = 0; j < __arraycount(service_list); j++) { 564 if (service_class[i] == service_list[j].class) 565 return print_attribute(id, value, 566 service_list[j].attrs, 567 service_list[j].nattr); 568 } 569 } 570 571 return false; 572 } 573 574 static void 575 print_bool(sdp_data_t *data) 576 { 577 bool v; 578 579 if (!sdp_get_bool(data, &v)) 580 return; 581 582 printf("%s\n", (v ? "true" : "false")); 583 } 584 585 static void 586 print_uint8x(sdp_data_t *data) 587 { 588 uint8_t v; 589 590 if (!sdp_get_uint8(data, &v)) 591 return; 592 593 printf("0x%02x\n", v); 594 } 595 596 static void 597 print_uint16d(sdp_data_t *data) 598 { 599 uint16_t v; 600 601 if (!sdp_get_uint16(data, &v)) 602 return; 603 604 printf("%d\n", v); 605 } 606 607 static void 608 print_uint16x(sdp_data_t *data) 609 { 610 uint16_t v; 611 612 if (!sdp_get_uint16(data, &v)) 613 return; 614 615 printf("0x%04x\n", v); 616 } 617 618 static void 619 print_uint32x(sdp_data_t *data) 620 { 621 uint32_t v; 622 623 if (!sdp_get_uint32(data, &v)) 624 return; 625 626 printf("0x%08x\n", v); 627 } 628 629 static void 630 print_uint32d(sdp_data_t *data) 631 { 632 uint32_t v; 633 634 if (!sdp_get_uint32(data, &v)) 635 return; 636 637 printf("%d\n", v); 638 } 639 640 static void 641 print_uuid(sdp_data_t *data) 642 { 643 uuid_t uuid; 644 645 if (!sdp_get_uuid(data, &uuid)) 646 return; 647 648 printf("%s\n", string_uuid(&uuid)); 649 } 650 651 static void 652 print_uuid_list(sdp_data_t *data) 653 { 654 sdp_data_t seq; 655 uuid_t uuid; 656 657 if (!sdp_get_seq(data, &seq)) 658 return; 659 660 printf("\n"); 661 while (sdp_get_uuid(&seq, &uuid)) 662 printf(" %s\n", string_uuid(&uuid)); 663 664 if (seq.next != seq.end) 665 printf(" [additional data]\n"); 666 } 667 668 static void 669 print_string(sdp_data_t *data) 670 { 671 char *str; 672 size_t len; 673 674 if (!sdp_get_str(data, &str, &len)) 675 return; 676 677 printf("\"%s\"\n", string_vis(VIS_CSTYLE, str, len)); 678 } 679 680 static void 681 print_url(sdp_data_t *data) 682 { 683 char *url; 684 size_t len; 685 686 if (!sdp_get_url(data, &url, &len)) 687 return; 688 689 printf("\"%s\"\n", string_vis(VIS_HTTPSTYLE, url, len)); 690 } 691 692 static void 693 print_profile_version(sdp_data_t *data) 694 { 695 uint16_t v; 696 697 if (!sdp_get_uint16(data, &v)) 698 return; 699 700 printf("v%d.%d\n", (v >> 8), (v & 0xff)); 701 } 702 703 /* 704 * This should only be called through print_language_attribute() which 705 * sets codeset of the string to be printed. 706 */ 707 static void 708 print_language_string(sdp_data_t *data) 709 { 710 char buf[50], *dst, *src; 711 iconv_t ih; 712 size_t n, srcleft, dstleft; 713 714 if (!sdp_get_str(data, &src, &srcleft)) 715 return; 716 717 dst = buf; 718 dstleft = sizeof(buf); 719 720 ih = iconv_open(nl_langinfo(CODESET), language[current].codeset); 721 if (ih == (iconv_t)-1) { 722 printf("Can't convert %s string\n", language[current].codeset); 723 return; 724 } 725 726 n = iconv(ih, (const char **)&src, &srcleft, &dst, &dstleft); 727 728 iconv_close(ih); 729 730 if (Nflag || n > 0) 731 printf("(%s) ", language[current].codeset); 732 733 printf("\"%.*s%s\n", (int)(sizeof(buf) - dstleft), buf, 734 (srcleft > 0 ? " ..." : "\"")); 735 } 736 737 static void 738 print_service_class_id_list(sdp_data_t *data) 739 { 740 sdp_data_t seq; 741 uuid_t uuid; 742 743 if (!sdp_get_seq(data, &seq)) 744 return; 745 746 printf("\n"); 747 while (sdp_get_uuid(&seq, &uuid)) { 748 printf(" %s\n", string_uuid(&uuid)); 749 750 if (nservices < MAX_SERVICES) { 751 service_class[nservices] = uuid.time_low; 752 uuid.time_low = 0; 753 if (uuid_equal(&uuid, &BLUETOOTH_BASE_UUID, NULL)) 754 nservices++; 755 } 756 } 757 758 if (seq.next != seq.end) 759 printf(" [additional data]\n"); 760 } 761 762 static void 763 print_protocol_descriptor(sdp_data_t *data) 764 { 765 uuid_t u0, uuid; 766 size_t i; 767 768 if (!sdp_get_uuid(data, &uuid)) 769 return; 770 771 u0 = uuid; 772 u0.time_low = 0; 773 if (uuid_equal(&u0, &BLUETOOTH_BASE_UUID, NULL)) { 774 for (i = 0; i < __arraycount(protocol_list); i++) { 775 if (uuid.time_low == protocol_list[i].id) { 776 printf(" %s", protocol_list[i].desc); 777 778 if (Nflag) 779 printf(" (0x%04x)", protocol_list[i].id); 780 781 if (protocol_list[i].print) 782 (protocol_list[i].print)(data); 783 784 if (data->next != data->end) 785 printf(" [additional data ignored]"); 786 787 printf("\n"); 788 return; 789 } 790 } 791 } 792 793 printf(" %s\n", string_uuid(&uuid)); 794 sdp_data_print(data, 4); 795 data->next = data->end; 796 } 797 798 static void 799 print_protocol_descriptor_list(sdp_data_t *data) 800 { 801 sdp_data_t seq, proto; 802 803 printf("\n"); 804 sdp_get_alt(data, data); /* strip [optional] alt header */ 805 806 while (sdp_get_seq(data, &seq)) 807 while (sdp_get_seq(&seq, &proto)) 808 print_protocol_descriptor(&proto); 809 } 810 811 static void 812 print_language_base_attribute_id_list(sdp_data_t *data) 813 { 814 sdp_data_t list; 815 uint16_t v; 816 const char *codeset; 817 char lang[2]; 818 819 if (!sdp_get_seq(data, &list)) 820 return; 821 822 printf("\n"); 823 while (list.next < list.end) { 824 /* 825 * ISO-639-1 natural language values are published at 826 * http://www.loc.gov/standards/iso639-2/php/code-list.php 827 */ 828 if (!sdp_get_uint16(&list, &v)) 829 break; 830 831 be16enc(lang, v); 832 if (!islower((int)lang[0]) || !islower((int)lang[1])) 833 break; 834 835 /* 836 * MIBenum values are published at 837 * http://www.iana.org/assignments/character-sets 838 */ 839 if (!sdp_get_uint16(&list, &v)) 840 break; 841 842 switch(v) { 843 case 3: codeset = "US-ASCII"; break; 844 case 4: codeset = "ISO-8859-1"; break; 845 case 5: codeset = "ISO-8859-2"; break; 846 case 106: codeset = "UTF-8"; break; 847 case 1013: codeset = "UTF-16BE"; break; 848 case 1014: codeset = "UTF-16LE"; break; 849 default: codeset = "Unknown"; break; 850 } 851 852 if (!sdp_get_uint16(&list, &v)) 853 break; 854 855 printf(" %.2s.%s base 0x%04x\n", lang, codeset, v); 856 857 if (nlanguages < MAX_LANGUAGES) { 858 language[nlanguages].base = v; 859 language[nlanguages].codeset = codeset; 860 nlanguages++; 861 } 862 } 863 864 if (list.next != list.end) 865 printf(" [additional data]\n"); 866 } 867 868 static void 869 print_service_availability(sdp_data_t *data) 870 { 871 uint8_t v; 872 873 if (!sdp_get_uint8(data, &v)) 874 return; 875 876 printf("%d/%d\n", v, UINT8_MAX); 877 } 878 879 static void 880 print_bluetooth_profile_descriptor_list(sdp_data_t *data) 881 { 882 sdp_data_t seq, profile; 883 uuid_t uuid; 884 uint16_t v; 885 886 if (!sdp_get_seq(data, &seq)) 887 return; 888 889 printf("\n"); 890 while (seq.next < seq.end) { 891 if (!sdp_get_seq(&seq, &profile) 892 || !sdp_get_uuid(&profile, &uuid) 893 || !sdp_get_uint16(&profile, &v)) 894 break; 895 896 printf(" %s, v%d.%d", string_uuid(&uuid), 897 (v >> 8), (v & 0xff)); 898 899 if (profile.next != profile.end) 900 printf(" [additional profile data]"); 901 902 printf("\n"); 903 } 904 905 if (seq.next != seq.end) 906 printf(" [additional data]\n"); 907 } 908 909 static void 910 print_additional_protocol_descriptor_lists(sdp_data_t *data) 911 { 912 sdp_data_t seq, stack, proto; 913 914 printf("\n"); 915 sdp_get_seq(data, &seq); 916 917 while (sdp_get_seq(&seq, &stack)) 918 while (sdp_get_seq(&stack, &proto)) 919 print_protocol_descriptor(&proto); 920 921 if (seq.next != seq.end) 922 printf(" [additional data]\n"); 923 } 924 925 static void 926 print_sds_version_number_list(sdp_data_t *data) 927 { 928 sdp_data_t list; 929 const char *sep; 930 uint16_t v; 931 932 if (!sdp_get_seq(data, &list)) 933 return; 934 935 sep = ""; 936 while (sdp_get_uint16(&list, &v)) { 937 printf("%sv%d.%d", sep, (v >> 8), (v & 0xff)); 938 sep = ", "; 939 } 940 941 if (list.next != list.end) 942 printf(" [additional data]"); 943 944 printf("\n"); 945 } 946 947 static void 948 print_ct_network(sdp_data_t *data) 949 { 950 uint8_t v; 951 952 if (!sdp_get_uint8(data, &v)) 953 return; 954 955 switch (v) { 956 case 0x01: printf("PSTN"); break; 957 case 0x02: printf("ISDN"); break; 958 case 0x03: printf("GSM"); break; 959 case 0x04: printf("CDMA"); break; 960 case 0x05: printf("Analogue Cellular"); break; 961 case 0x06: printf("Packet Switched"); break; 962 case 0x07: printf("Other"); break; 963 default: printf("0x%02x", v); break; 964 } 965 966 printf("\n"); 967 } 968 969 static void 970 print_asrc_features(sdp_data_t *data) 971 { 972 uint16_t v; 973 974 if (!sdp_get_uint16(data, &v)) 975 return; 976 977 if (Nflag) 978 printf("(0x%04x)", v); 979 980 printf("\n"); 981 if (v & (1<<0)) printf(" Player\n"); 982 if (v & (1<<1)) printf(" Microphone\n"); 983 if (v & (1<<2)) printf(" Tuner\n"); 984 if (v & (1<<3)) printf(" Mixer\n"); 985 } 986 987 static void 988 print_asink_features(sdp_data_t *data) 989 { 990 uint16_t v; 991 992 if (!sdp_get_uint16(data, &v)) 993 return; 994 995 if (Nflag) 996 printf("(0x%04x)", v); 997 998 printf("\n"); 999 if (v & (1<<0)) printf(" Headphone\n"); 1000 if (v & (1<<1)) printf(" Speaker\n"); 1001 if (v & (1<<2)) printf(" Recorder\n"); 1002 if (v & (1<<3)) printf(" Amplifier\n"); 1003 } 1004 1005 static void 1006 print_avrcp_features(sdp_data_t *data) 1007 { 1008 uint16_t v; 1009 1010 if (!sdp_get_uint16(data, &v)) 1011 return; 1012 1013 if (Nflag) 1014 printf("(0x%04x)", v); 1015 1016 printf("\n"); 1017 if (v & (1<<0)) printf(" Category 1\n"); 1018 if (v & (1<<1)) printf(" Category 2\n"); 1019 if (v & (1<<2)) printf(" Category 3\n"); 1020 if (v & (1<<3)) printf(" Category 4\n"); 1021 } 1022 1023 static void 1024 print_supported_data_stores(sdp_data_t *data) 1025 { 1026 sdp_data_t list; 1027 const char *sep; 1028 uint8_t v; 1029 1030 if (!sdp_get_seq(data, &list)) 1031 return; 1032 1033 sep = "\n "; 1034 while (sdp_get_uint8(&list, &v)) { 1035 printf(sep); 1036 sep = ", "; 1037 1038 switch(v) { 1039 case 0x01: printf("Phonebook"); break; 1040 case 0x03: printf("Calendar"); break; 1041 case 0x05: printf("Notes"); break; 1042 case 0x06: printf("Messages"); break; 1043 default: printf("0x%02x", v); break; 1044 } 1045 } 1046 1047 if (list.next != list.end) 1048 printf(" [additional data]"); 1049 1050 printf("\n"); 1051 } 1052 1053 static void 1054 print_supported_formats(sdp_data_t *data) 1055 { 1056 sdp_data_t list; 1057 const char *sep; 1058 uint8_t v; 1059 1060 if (!sdp_get_seq(data, &list)) 1061 return; 1062 1063 sep = "\n "; 1064 while (sdp_get_uint8(&list, &v)) { 1065 printf(sep); 1066 sep = ", "; 1067 1068 switch(v) { 1069 case 0x01: printf("vCard 2.1"); break; 1070 case 0x02: printf("vCard 3.0"); break; 1071 case 0x03: printf("vCal 1.0"); break; 1072 case 0x04: printf("iCal 2.0"); break; 1073 case 0x05: printf("vNote"); break; 1074 case 0x06: printf("vMessage"); break; 1075 case 0xff: printf("Any"); break; 1076 default: printf("0x%02x", v); break; 1077 } 1078 } 1079 1080 if (list.next != list.end) 1081 printf(" [additional data]"); 1082 1083 printf("\n"); 1084 } 1085 1086 static void 1087 print_hid_version(sdp_data_t *data) 1088 { 1089 uint16_t v; 1090 1091 if (!sdp_get_uint16(data, &v)) 1092 return; 1093 1094 printf("v%d.%d.%d\n", 1095 ((v & 0xff00) >> 8), ((v & 0x00f0) >> 4), (v & 0x000f)); 1096 } 1097 1098 static void 1099 print_hid_device_subclass(sdp_data_t *data) 1100 { 1101 uint8_t v; 1102 1103 if (!sdp_get_uint8(data, &v)) 1104 return; 1105 1106 switch ((v & 0x3c) >> 2) { 1107 case 1: printf("Joystick"); break; 1108 case 2: printf("Gamepad"); break; 1109 case 3: printf("Remote Control"); break; 1110 case 4: printf("Sensing Device"); break; 1111 case 5: printf("Digitiser Tablet"); break; 1112 case 6: printf("Card Reader"); break; 1113 default: printf("Peripheral"); break; 1114 } 1115 1116 if (v & 0x40) printf(" <Keyboard>"); 1117 if (v & 0x80) printf(" <Mouse>"); 1118 1119 printf("\n"); 1120 } 1121 1122 static void 1123 print_hid_descriptor_list(sdp_data_t *data) 1124 { 1125 sdp_data_t list, seq; 1126 uint8_t type; 1127 const char *name; 1128 char *str; 1129 size_t len; 1130 1131 1132 if (!sdp_get_seq(data, &list)) 1133 return; 1134 1135 printf("\n"); 1136 while (list.next < list.end) { 1137 if (!sdp_get_seq(&list, &seq) 1138 || !sdp_get_uint8(&seq, &type) 1139 || !sdp_get_str(&seq, &str, &len)) 1140 return; 1141 1142 switch (type) { 1143 case 0x22: name = "Report"; break; 1144 case 0x23: name = "Physical Descriptor"; break; 1145 default: name = ""; break; 1146 } 1147 1148 printf(" Type 0x%02x: %s\n", type, name); 1149 print_hexdump(" Data", (uint8_t *)str, len); 1150 1151 if (seq.next != seq.end) 1152 printf(" [additional data]\n"); 1153 } 1154 } 1155 1156 static void 1157 print_security_description(sdp_data_t *data) 1158 { 1159 uint16_t v; 1160 1161 if (!sdp_get_uint16(data, &v)) 1162 return; 1163 1164 switch (v) { 1165 case 0x0000: printf("None"); break; 1166 case 0x0001: printf("Service-level Security"); break; 1167 case 0x0002: printf("802.1x Security"); break; 1168 default: printf("0x%04x", v); break; 1169 } 1170 1171 printf("\n"); 1172 } 1173 1174 static void 1175 print_hf_features(sdp_data_t *data) 1176 { 1177 uint16_t v; 1178 1179 if (!sdp_get_uint16(data, &v)) 1180 return; 1181 1182 if (Nflag) 1183 printf("(0x%04x)", v); 1184 1185 printf("\n"); 1186 if (v & (1<<0)) printf(" Echo Cancellation/Noise Reduction\n"); 1187 if (v & (1<<1)) printf(" Call Waiting\n"); 1188 if (v & (1<<2)) printf(" Caller Line Identification\n"); 1189 if (v & (1<<3)) printf(" Voice Recognition\n"); 1190 if (v & (1<<4)) printf(" Volume Control\n"); 1191 } 1192 1193 static void 1194 print_hfag_network(sdp_data_t *data) 1195 { 1196 uint8_t v; 1197 1198 if (!sdp_get_uint8(data, &v)) 1199 return; 1200 1201 switch (v) { 1202 case 0x01: printf("Ability to reject a call"); break; 1203 case 0x02: printf("No ability to reject a call"); break; 1204 default: printf("0x%02x", v); break; 1205 } 1206 1207 printf("\n"); 1208 } 1209 1210 static void 1211 print_hfag_features(sdp_data_t *data) 1212 { 1213 uint16_t v; 1214 1215 if (!sdp_get_uint16(data, &v)) 1216 return; 1217 1218 if (Nflag) 1219 printf("(0x%04x)", v); 1220 1221 printf("\n"); 1222 if (v & (1<<0)) printf(" 3 Way Calling\n"); 1223 if (v & (1<<1)) printf(" Echo Cancellation/Noise Reduction\n"); 1224 if (v & (1<<2)) printf(" Voice Recognition\n"); 1225 if (v & (1<<3)) printf(" In-band Ring Tone\n"); 1226 if (v & (1<<4)) printf(" Voice Tags\n"); 1227 } 1228 1229 static void 1230 print_net_access_type(sdp_data_t *data) 1231 { 1232 uint16_t v; 1233 1234 if (!sdp_get_uint16(data, &v)) 1235 return; 1236 1237 switch(v) { 1238 case 0x0000: printf("PSTN"); break; 1239 case 0x0001: printf("ISDN"); break; 1240 case 0x0002: printf("DSL"); break; 1241 case 0x0003: printf("Cable Modem"); break; 1242 case 0x0004: printf("10Mb Ethernet"); break; 1243 case 0x0005: printf("100Mb Ethernet"); break; 1244 case 0x0006: printf("4Mb Token Ring"); break; 1245 case 0x0007: printf("16Mb Token Ring"); break; 1246 case 0x0008: printf("100Mb Token Ring"); break; 1247 case 0x0009: printf("FDDI"); break; 1248 case 0x000a: printf("GSM"); break; 1249 case 0x000b: printf("CDMA"); break; 1250 case 0x000c: printf("GPRS"); break; 1251 case 0x000d: printf("3G Cellular"); break; 1252 case 0xfffe: printf("other"); break; 1253 default: printf("0x%04x", v); break; 1254 } 1255 1256 printf("\n"); 1257 } 1258 1259 static void 1260 print_pnp_source(sdp_data_t *data) 1261 { 1262 uint16_t v; 1263 1264 if (!sdp_get_uint16(data, &v)) 1265 return; 1266 1267 switch (v) { 1268 case 0x0001: printf("Bluetooth SIG"); break; 1269 case 0x0002: printf("USB Implementers Forum"); break; 1270 default: printf("0x%04x", v); break; 1271 } 1272 1273 printf("\n"); 1274 } 1275 1276 static void 1277 print_rfcomm(sdp_data_t *data) 1278 { 1279 uint8_t v; 1280 1281 if (sdp_get_uint8(data, &v)) 1282 printf(" (channel %d)", v); 1283 } 1284 1285 static void 1286 print_bnep(sdp_data_t *data) 1287 { 1288 sdp_data_t seq; 1289 uint16_t v; 1290 const char *sep; 1291 1292 if (!sdp_get_uint16(data, &v) 1293 || !sdp_get_seq(data, &seq)) 1294 return; 1295 1296 printf(" (v%d.%d", (v >> 8), (v & 0xff)); 1297 sep = "; "; 1298 while (sdp_get_uint16(&seq, &v)) { 1299 printf(sep); 1300 sep = ", "; 1301 1302 switch (v) { 1303 case 0x0800: printf("IPv4"); break; 1304 case 0x0806: printf("ARP"); break; 1305 case 0x86dd: printf("IPv6"); break; 1306 default: printf("0x%04x", v); break; 1307 } 1308 } 1309 printf(")"); 1310 1311 if (seq.next != seq.end) 1312 printf(" [additional data]"); 1313 } 1314 1315 static void 1316 print_avctp(sdp_data_t *data) 1317 { 1318 uint16_t v; 1319 1320 if (sdp_get_uint16(data, &v)) 1321 printf(" (v%d.%d)", (v >> 8), (v & 0xff)); 1322 } 1323 1324 static void 1325 print_avdtp(sdp_data_t *data) 1326 { 1327 uint16_t v; 1328 1329 if (sdp_get_uint16(data, &v)) 1330 printf(" (v%d.%d)", (v >> 8), (v & 0xff)); 1331 } 1332 1333 static void 1334 print_l2cap(sdp_data_t *data) 1335 { 1336 uint16_t v; 1337 1338 if (sdp_get_uint16(data, &v)) 1339 printf(" (PSM 0x%04x)", v); 1340 } 1341