search.c revision 124317
1193326Sed/* 2193326Sed * search.c 3193326Sed * 4193326Sed * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5193326Sed * All rights reserved. 6193326Sed * 7193326Sed * Redistribution and use in source and binary forms, with or without 8193326Sed * modification, are permitted provided that the following conditions 9193326Sed * are met: 10193326Sed * 1. Redistributions of source code must retain the above copyright 11193326Sed * notice, this list of conditions and the following disclaimer. 12193326Sed * 2. Redistributions in binary form must reproduce the above copyright 13193326Sed * notice, this list of conditions and the following disclaimer in the 14193326Sed * documentation and/or other materials provided with the distribution. 15193326Sed * 16193326Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17219077Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18193326Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19193326Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20219077Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21239462Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22193326Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23193326Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24193326Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25193326Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26193326Sed * SUCH DAMAGE. 27193326Sed * 28218893Sdim * $Id: search.c,v 1.2 2003/09/08 17:35:15 max Exp $ 29193326Sed * $FreeBSD: head/usr.sbin/bluetooth/sdpcontrol/search.c 124317 2004-01-09 22:44:28Z emax $ 30193326Sed */ 31193326Sed 32193326Sed#include <bluetooth.h> 33276479Sdim#include <ctype.h> 34198092Srdivacky#include <sdp.h> 35193326Sed#include <stdio.h> 36193326Sed#include <stdlib.h> 37239462Sdim#include "sdpcontrol.h" 38239462Sdim 39193326Sed/* List of the attributes we are looking for */ 40193326Sedstatic uint32_t attrs[] = 41193326Sed{ 42193326Sed SDP_ATTR_RANGE( SDP_ATTR_SERVICE_RECORD_HANDLE, 43193326Sed SDP_ATTR_SERVICE_RECORD_HANDLE), 44193326Sed SDP_ATTR_RANGE( SDP_ATTR_SERVICE_CLASS_ID_LIST, 45193326Sed SDP_ATTR_SERVICE_CLASS_ID_LIST), 46218893Sdim SDP_ATTR_RANGE( SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, 47218893Sdim SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST), 48193326Sed SDP_ATTR_RANGE( SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, 49198092Srdivacky SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST) 50193326Sed}; 51193326Sed#define attrs_len (sizeof(attrs)/sizeof(attrs[0])) 52193326Sed 53219077Sdim/* Buffer for the attributes */ 54193326Sed#define NRECS 25 /* request this much records from the SDP server */ 55193326Sed#define BSIZE 256 /* one attribute buffer size */ 56193326Sedstatic uint8_t buffer[NRECS * attrs_len][BSIZE]; 57193326Sed 58193326Sed/* SDP attributes */ 59218893Sdimstatic sdp_attr_t values[NRECS * attrs_len]; 60249423Sdim#define values_len (sizeof(values)/sizeof(values[0])) 61249423Sdim 62193326Sed/* 63198092Srdivacky * Print Service Class ID List 64276479Sdim * 65276479Sdim * The ServiceClassIDList attribute consists of a data element sequence in 66193326Sed * which each data element is a UUID representing the service classes that 67193326Sed * a given service record conforms to. The UUIDs are listed in order from 68193326Sed * the most specific class to the most general class. The ServiceClassIDList 69280031Sdim * must contain at least one service class UUID. 70249423Sdim */ 71193326Sed 72193326Sedstatic void 73193326Sedprint_service_class_id_list(uint8_t const *start, uint8_t const *end) 74193326Sed{ 75218893Sdim uint32_t type, len, value; 76219077Sdim 77219077Sdim if (end - start < 2) { 78219077Sdim fprintf(stderr, "Invalid Service Class ID List. " \ 79219077Sdim "Too short, len=%d\n", end - start); 80276479Sdim return; 81276479Sdim } 82219077Sdim 83219077Sdim SDP_GET8(type, start); 84219077Sdim switch (type) { 85280031Sdim case SDP_DATA_SEQ8: 86219077Sdim SDP_GET8(len, start); 87219077Sdim break; 88219077Sdim 89219077Sdim case SDP_DATA_SEQ16: 90219077Sdim SDP_GET16(len, start); 91219077Sdim break; 92218893Sdim 93218893Sdim case SDP_DATA_SEQ32: 94193326Sed SDP_GET32(len, start); 95193326Sed break; 96193326Sed 97219077Sdim default: 98218893Sdim fprintf(stderr, "Invalid Service Class ID List. " \ 99193326Sed "Not a sequence, type=%#x\n", type); 100193326Sed return; 101198092Srdivacky /* NOT REACHED */ 102198092Srdivacky } 103218893Sdim 104198092Srdivacky while (start < end) { 105198092Srdivacky SDP_GET8(type, start); 106276479Sdim switch (type) { 107219077Sdim case SDP_DATA_UUID16: 108198092Srdivacky SDP_GET16(value, start); 109198092Srdivacky fprintf(stdout, "\t%s (%#4.4x)\n", 110198092Srdivacky sdp_uuid2desc(value), value); 111198092Srdivacky break; 112218893Sdim 113218893Sdim case SDP_DATA_UUID32: 114193326Sed SDP_GET32(value, start); 115239462Sdim fprintf(stdout, "\t%#8.8x\n", value); 116239462Sdim break; 117239462Sdim 118193326Sed case SDP_DATA_UUID128: { 119193326Sed int128_t uuid; 120193326Sed 121280031Sdim SDP_GET128(&uuid, start); 122280031Sdim fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", 123280031Sdim *(uint32_t *)&uuid.b[0], 124280031Sdim *(uint16_t *)&uuid.b[4], 125280031Sdim *(uint16_t *)&uuid.b[6], 126280031Sdim *(uint16_t *)&uuid.b[8], 127280031Sdim *(uint16_t *)&uuid.b[10], 128280031Sdim *(uint32_t *)&uuid.b[12]); 129280031Sdim } break; 130280031Sdim 131219077Sdim default: 132276479Sdim fprintf(stderr, "Invalid Service Class ID List. " \ 133219077Sdim "Not a UUID, type=%#x\n", type); 134219077Sdim return; 135219077Sdim /* NOT REACHED */ 136219077Sdim } 137219077Sdim } 138219077Sdim} /* print_service_class_id_list */ 139280031Sdim 140280031Sdim/* 141280031Sdim * Print Protocol Descriptor List 142280031Sdim * 143280031Sdim * If the ProtocolDescriptorList describes a single stack, it takes the form 144280031Sdim * of a data element sequence in which each element of the sequence is a 145219077Sdim * protocol descriptor. Each protocol descriptor is, in turn, a data element 146219077Sdim * sequence whose first element is a UUID identifying the protocol and whose 147219077Sdim * successive elements are protocol-specific parameters. The protocol 148219077Sdim * descriptors are listed in order from the lowest layer protocol to the 149219077Sdim * highest layer protocol used to gain access to the service. If it is possible 150219077Sdim * for more than one kind of protocol stack to be used to gain access to the 151219077Sdim * service, the ProtocolDescriptorList takes the form of a data element 152219077Sdim * alternative where each member is a data element sequence as described above. 153234353Sdim */ 154219077Sdim 155219077Sdimstatic void 156280031Sdimprint_protocol_descriptor(uint8_t const *start, uint8_t const *end) 157219077Sdim{ 158280031Sdim union { 159219077Sdim uint8_t uint8; 160219077Sdim uint16_t uint16; 161276479Sdim uint32_t uint32; 162219077Sdim uint64_t uint64; 163219077Sdim int128_t int128; 164280031Sdim } value; 165219077Sdim uint32_t type, len, param; 166280031Sdim 167219077Sdim /* Get Protocol UUID */ 168219077Sdim SDP_GET8(type, start); 169276479Sdim switch (type) { 170219077Sdim case SDP_DATA_UUID16: 171219077Sdim SDP_GET16(value.uint16, start); 172280031Sdim fprintf(stdout, "\t%s (%#4.4x)\n", sdp_uuid2desc(value.uint16), 173280031Sdim value.uint16); 174280031Sdim break; 175280031Sdim 176219077Sdim case SDP_DATA_UUID32: 177280031Sdim SDP_GET32(value.uint32, start); 178280031Sdim fprintf(stdout, "\t%#8.8x\n", value.uint32); 179280031Sdim break; 180193326Sed 181193326Sed case SDP_DATA_UUID128: 182193326Sed SDP_GET128(&value.int128, start); 183193326Sed fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", 184193326Sed *(uint32_t *)&value.int128.b[0], 185193326Sed *(uint16_t *)&value.int128.b[4], 186193326Sed *(uint16_t *)&value.int128.b[6], 187193326Sed *(uint16_t *)&value.int128.b[8], 188193326Sed *(uint16_t *)&value.int128.b[10], 189219077Sdim *(uint32_t *)&value.int128.b[12]); 190193326Sed break; 191193326Sed 192193326Sed default: 193280031Sdim fprintf(stderr, "Invalid Protocol Descriptor. " \ 194280031Sdim "Not a UUID, type=%#x\n", type); 195280031Sdim return; 196280031Sdim /* NOT REACHED */ 197280031Sdim } 198280031Sdim 199280031Sdim /* Protocol specific parameters */ 200280031Sdim for (param = 1; start < end; param ++) { 201280031Sdim fprintf(stdout, "\t\tProtocol specific parameter #%d: ", param); 202193326Sed 203193326Sed SDP_GET8(type, start); 204193326Sed switch (type) { 205193326Sed case SDP_DATA_NIL: 206193326Sed fprintf(stdout, "nil\n"); 207234353Sdim break; 208193326Sed 209193326Sed case SDP_DATA_UINT8: 210224145Sdim case SDP_DATA_INT8: 211224145Sdim case SDP_DATA_BOOL: 212224145Sdim SDP_GET8(value.uint8, start); 213224145Sdim fprintf(stdout, "u/int8/bool %u\n", value.uint8); 214224145Sdim break; 215224145Sdim 216224145Sdim case SDP_DATA_UINT16: 217224145Sdim case SDP_DATA_INT16: 218224145Sdim case SDP_DATA_UUID16: 219224145Sdim SDP_GET16(value.uint16, start); 220224145Sdim fprintf(stdout, "u/int/uuid16 %u\n", value.uint16); 221280031Sdim break; 222224145Sdim 223280031Sdim case SDP_DATA_UINT32: 224224145Sdim case SDP_DATA_INT32: 225224145Sdim case SDP_DATA_UUID32: 226224145Sdim SDP_GET32(value.uint32, start); 227224145Sdim fprintf(stdout, "u/int/uuid32 %u\n", value.uint32); 228234353Sdim break; 229234353Sdim 230224145Sdim case SDP_DATA_UINT64: 231224145Sdim case SDP_DATA_INT64: 232218893Sdim SDP_GET64(value.uint64, start); 233218893Sdim fprintf(stdout, "u/int64 %llu\n", value.uint64); 234218893Sdim break; 235218893Sdim 236218893Sdim case SDP_DATA_UINT128: 237218893Sdim case SDP_DATA_INT128: 238219077Sdim case SDP_DATA_UUID128: 239218893Sdim SDP_GET128(&value.int128, start); 240280031Sdim fprintf(stdout, "u/int/uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", 241218893Sdim *(uint32_t *)&value.int128.b[0], 242218893Sdim *(uint16_t *)&value.int128.b[4], 243218893Sdim *(uint16_t *)&value.int128.b[6], 244218893Sdim *(uint16_t *)&value.int128.b[8], 245218893Sdim *(uint16_t *)&value.int128.b[10], 246218893Sdim *(uint32_t *)&value.int128.b[12]); 247218893Sdim break; 248234353Sdim 249218893Sdim case SDP_DATA_STR8: 250218893Sdim case SDP_DATA_URL8: 251193326Sed SDP_GET8(len, start); 252193326Sed fprintf(stdout, "%*.*s\n", len, len, (char *) start); 253198092Srdivacky start += len; 254226633Sdim break; 255193326Sed 256193326Sed case SDP_DATA_STR16: 257193326Sed case SDP_DATA_URL16: 258193326Sed SDP_GET16(len, start); 259193326Sed fprintf(stdout, "%*.*s\n", len, len, (char *) start); 260193326Sed start += len; 261193326Sed break; 262193326Sed 263193326Sed case SDP_DATA_STR32: 264193326Sed case SDP_DATA_URL32: 265234353Sdim SDP_GET32(len, start); 266234353Sdim fprintf(stdout, "%*.*s\n", len, len, (char *) start); 267234353Sdim start += len; 268219077Sdim break; 269193326Sed 270193326Sed case SDP_DATA_SEQ8: 271219077Sdim case SDP_DATA_ALT8: 272219077Sdim SDP_GET8(len, start); 273219077Sdim for (; len > 0; start ++, len --) 274219077Sdim fprintf(stdout, "%#2.2x ", *start); 275193326Sed fprintf(stdout, "\n"); 276193326Sed break; 277193326Sed 278280031Sdim case SDP_DATA_SEQ16: 279280031Sdim case SDP_DATA_ALT16: 280280031Sdim SDP_GET16(len, start); 281280031Sdim for (; len > 0; start ++, len --) 282193326Sed fprintf(stdout, "%#2.2x ", *start); 283193326Sed fprintf(stdout, "\n"); 284193326Sed break; 285193326Sed 286193326Sed case SDP_DATA_SEQ32: 287218893Sdim case SDP_DATA_ALT32: 288193326Sed SDP_GET32(len, start); 289193326Sed for (; len > 0; start ++, len --) 290198092Srdivacky fprintf(stdout, "%#2.2x ", *start); 291198092Srdivacky fprintf(stdout, "\n"); 292198092Srdivacky break; 293208600Srdivacky 294198092Srdivacky default: 295198092Srdivacky fprintf(stderr, "Invalid Protocol Descriptor. " \ 296198092Srdivacky "Unknown data type: %#02x\n", type); 297198092Srdivacky return; 298198092Srdivacky /* NOT REACHED */ 299208600Srdivacky } 300208600Srdivacky } 301198092Srdivacky} /* print_protocol_descriptor */ 302198092Srdivacky 303198092Srdivackystatic void 304198092Srdivackyprint_protocol_descriptor_list(uint8_t const *start, uint8_t const *end) 305198092Srdivacky{ 306198092Srdivacky uint32_t type, len; 307198092Srdivacky 308249423Sdim if (end - start < 2) { 309249423Sdim fprintf(stderr, "Invalid Protocol Descriptor List. " \ 310198092Srdivacky "Too short, len=%d\n", end - start); 311198092Srdivacky return; 312249423Sdim } 313198092Srdivacky 314193326Sed SDP_GET8(type, start); 315193326Sed switch (type) { 316193326Sed case SDP_DATA_SEQ8: 317193326Sed SDP_GET8(len, start); 318193326Sed break; 319193326Sed 320193326Sed case SDP_DATA_SEQ16: 321296417Sdim SDP_GET16(len, start); 322195341Sed break; 323193326Sed 324219077Sdim case SDP_DATA_SEQ32: 325296417Sdim SDP_GET32(len, start); 326296417Sdim break; 327296417Sdim 328296417Sdim default: 329296417Sdim fprintf(stderr, "Invalid Protocol Descriptor List. " \ 330219077Sdim "Not a sequence, type=%#x\n", type); 331219077Sdim return; 332219077Sdim /* NOT REACHED */ 333219077Sdim } 334219077Sdim 335219077Sdim while (start < end) { 336219077Sdim SDP_GET8(type, start); 337219077Sdim switch (type) { 338219077Sdim case SDP_DATA_SEQ8: 339219077Sdim SDP_GET8(len, start); 340219077Sdim break; 341219077Sdim 342219077Sdim case SDP_DATA_SEQ16: 343219077Sdim SDP_GET16(len, start); 344219077Sdim break; 345280031Sdim 346219077Sdim case SDP_DATA_SEQ32: 347219077Sdim SDP_GET32(len, start); 348219077Sdim break; 349219077Sdim 350219077Sdim default: 351219077Sdim fprintf(stderr, "Invalid Protocol Descriptor List. " \ 352219077Sdim "Not a sequence, type=%#x\n", type); 353219077Sdim return; 354219077Sdim /* NOT REACHED */ 355219077Sdim } 356219077Sdim 357219077Sdim print_protocol_descriptor(start, start + len); 358219077Sdim start += len; 359219077Sdim } 360219077Sdim} /* print_protocol_descriptor_list */ 361219077Sdim 362219077Sdim/* 363219077Sdim * Print Bluetooth Profile Descriptor List 364219077Sdim * 365219077Sdim * The BluetoothProfileDescriptorList attribute consists of a data element 366219077Sdim * sequence in which each element is a profile descriptor that contains 367219077Sdim * information about a Bluetooth profile to which the service represented by 368219077Sdim * this service record conforms. Each profile descriptor is a data element 369219077Sdim * sequence whose first element is the UUID assigned to the profile and whose 370219077Sdim * second element is a 16-bit profile version number. Each version of a profile 371219077Sdim * is assigned a 16-bit unsigned integer profile version number, which consists 372219077Sdim * of two 8-bit fields. The higher-order 8 bits contain the major version 373219077Sdim * number field and the lower-order 8 bits contain the minor version number 374219077Sdim * field. 375219077Sdim */ 376219077Sdim 377219077Sdimstatic void 378219077Sdimprint_bluetooth_profile_descriptor_list(uint8_t const *start, uint8_t const *end) 379219077Sdim{ 380219077Sdim uint32_t type, len, value; 381219077Sdim 382219077Sdim if (end - start < 2) { 383219077Sdim fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \ 384219077Sdim "Too short, len=%d\n", end - start); 385219077Sdim return; 386219077Sdim } 387219077Sdim 388219077Sdim SDP_GET8(type, start); 389219077Sdim switch (type) { 390219077Sdim case SDP_DATA_SEQ8: 391219077Sdim SDP_GET8(len, start); 392219077Sdim break; 393219077Sdim 394219077Sdim case SDP_DATA_SEQ16: 395219077Sdim SDP_GET16(len, start); 396219077Sdim break; 397219077Sdim 398219077Sdim case SDP_DATA_SEQ32: 399219077Sdim SDP_GET32(len, start); 400219077Sdim break; 401219077Sdim 402219077Sdim default: 403219077Sdim fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \ 404219077Sdim "Not a sequence, type=%#x\n", type); 405219077Sdim return; 406219077Sdim /* NOT REACHED */ 407219077Sdim } 408219077Sdim 409219077Sdim while (start < end) { 410219077Sdim SDP_GET8(type, start); 411280031Sdim switch (type) { 412219077Sdim case SDP_DATA_SEQ8: 413219077Sdim SDP_GET8(len, start); 414219077Sdim break; 415219077Sdim 416219077Sdim case SDP_DATA_SEQ16: 417219077Sdim SDP_GET16(len, start); 418219077Sdim break; 419219077Sdim 420219077Sdim case SDP_DATA_SEQ32: 421219077Sdim SDP_GET32(len, start); 422219077Sdim break; 423219077Sdim 424219077Sdim default: 425234353Sdim fprintf(stderr, "Invalid Bluetooth Profile " \ 426234353Sdim "Descriptor List. " \ 427219077Sdim "Not a sequence, type=%#x\n", type); 428219077Sdim return; 429219077Sdim /* NOT REACHED */ 430219077Sdim } 431219077Sdim 432219077Sdim /* Get UUID */ 433219077Sdim SDP_GET8(type, start); 434219077Sdim switch (type) { 435219077Sdim case SDP_DATA_UUID16: 436219077Sdim SDP_GET16(value, start); 437219077Sdim fprintf(stdout, "\t%s (%#4.4x) ", 438219077Sdim sdp_uuid2desc(value), value); 439221345Sdim break; 440221345Sdim 441221345Sdim case SDP_DATA_UUID32: 442221345Sdim SDP_GET32(value, start); 443288943Sdim fprintf(stdout, "\t%#8.8x ", value); 444288943Sdim break; 445288943Sdim 446221345Sdim case SDP_DATA_UUID128: { 447221345Sdim int128_t uuid; 448288943Sdim 449288943Sdim SDP_GET128(&uuid, start); 450288943Sdim fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x ", 451221345Sdim *(uint32_t *)&uuid.b[0], 452288943Sdim *(uint16_t *)&uuid.b[4], 453288943Sdim *(uint16_t *)&uuid.b[6], 454221345Sdim *(uint16_t *)&uuid.b[8], 455288943Sdim *(uint16_t *)&uuid.b[10], 456221345Sdim *(uint32_t *)&uuid.b[12]); 457221345Sdim } break; 458221345Sdim 459221345Sdim default: 460221345Sdim fprintf(stderr, "Invalid Bluetooth Profile " \ 461221345Sdim "Descriptor List. " \ 462221345Sdim "Not a UUID, type=%#x\n", type); 463221345Sdim return; 464221345Sdim /* NOT REACHED */ 465221345Sdim } 466221345Sdim 467221345Sdim /* Get version */ 468221345Sdim SDP_GET8(type, start); 469221345Sdim if (type != SDP_DATA_UINT16) { 470221345Sdim fprintf(stderr, "Invalid Bluetooth Profile " \ 471221345Sdim "Descriptor List. " \ 472221345Sdim "Invalid version type=%#x\n", type); 473221345Sdim return; 474221345Sdim } 475221345Sdim 476221345Sdim SDP_GET16(value, start); 477221345Sdim fprintf(stdout, "ver. %d.%d\n", 478221345Sdim (value >> 8) & 0xff, value & 0xff); 479221345Sdim } 480221345Sdim} /* print_bluetooth_profile_descriptor_list */ 481221345Sdim 482221345Sdim/* Perform SDP search command */ 483221345Sdimstatic int 484276479Sdimdo_sdp_search(void *xs, int argc, char **argv) 485221345Sdim{ 486221345Sdim char *ep = NULL; 487221345Sdim int32_t n, type, value; 488221345Sdim uint16_t service; 489221345Sdim 490221345Sdim /* Parse command line arguments */ 491221345Sdim switch (argc) { 492221345Sdim case 1: 493221345Sdim n = strtoul(argv[0], &ep, 16); 494221345Sdim if (*ep != 0) { 495221345Sdim switch (tolower(argv[0][0])) { 496221345Sdim case 'c': /* CIP/CTP */ 497221345Sdim switch (tolower(argv[0][1])) { 498276479Sdim case 'i': 499276479Sdim service = SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS; 500221345Sdim break; 501221345Sdim 502221345Sdim case 't': 503221345Sdim service = SDP_SERVICE_CLASS_CORDLESS_TELEPHONY; 504221345Sdim break; 505221345Sdim 506221345Sdim default: 507221345Sdim return (USAGE); 508221345Sdim /* NOT REACHED */ 509221345Sdim } 510221345Sdim break; 511221345Sdim 512221345Sdim case 'd': /* DialUp Networking */ 513221345Sdim service = SDP_SERVICE_CLASS_DIALUP_NETWORKING; 514221345Sdim break; 515221345Sdim 516221345Sdim case 'f': /* Fax/OBEX File Transfer */ 517221345Sdim switch (tolower(argv[0][1])) { 518221345Sdim case 'a': 519221345Sdim service = SDP_SERVICE_CLASS_FAX; 520221345Sdim break; 521221345Sdim 522276479Sdim case 't': 523221345Sdim service = SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER; 524221345Sdim break; 525221345Sdim 526221345Sdim default: 527221345Sdim return (USAGE); 528221345Sdim /* NOT REACHED */ 529221345Sdim } 530221345Sdim break; 531221345Sdim 532221345Sdim case 'g': /* GN */ 533221345Sdim service = SDP_SERVICE_CLASS_GN; 534221345Sdim break; 535276479Sdim 536276479Sdim case 'h': /* Headset/HID */ 537221345Sdim switch (tolower(argv[0][1])) { 538221345Sdim case 'i': 539221345Sdim service = SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE; 540221345Sdim break; 541221345Sdim 542221345Sdim case 's': 543221345Sdim service = SDP_SERVICE_CLASS_HEADSET; 544221345Sdim break; 545221345Sdim 546221345Sdim default: 547221345Sdim return (USAGE); 548221345Sdim /* NOT REACHED */ 549221345Sdim } 550221345Sdim break; 551221345Sdim 552221345Sdim case 'l': /* LAN Access Using PPP */ 553221345Sdim service = SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP; 554221345Sdim break; 555221345Sdim 556221345Sdim case 'n': /* NAP */ 557221345Sdim service = SDP_SERVICE_CLASS_NAP; 558221345Sdim break; 559221345Sdim 560221345Sdim case 'o': /* OBEX Object Push */ 561221345Sdim service = SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH; 562221345Sdim break; 563221345Sdim 564221345Sdim case 's': /* Serial Port */ 565221345Sdim service = SDP_SERVICE_CLASS_SERIAL_PORT; 566221345Sdim break; 567221345Sdim 568221345Sdim default: 569221345Sdim return (USAGE); 570221345Sdim /* NOT REACHED */ 571221345Sdim } 572221345Sdim } else 573221345Sdim service = (uint16_t) n; 574221345Sdim break; 575221345Sdim 576221345Sdim default: 577221345Sdim return (USAGE); 578221345Sdim } 579221345Sdim 580221345Sdim if (service < SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER) 581221345Sdim return (USAGE); 582221345Sdim 583221345Sdim /* Initialize attribute values array */ 584221345Sdim for (n = 0; n < values_len; n ++) { 585221345Sdim values[n].flags = SDP_ATTR_INVALID; 586221345Sdim values[n].attr = 0; 587221345Sdim values[n].vlen = BSIZE; 588221345Sdim values[n].value = buffer[n]; 589221345Sdim } 590221345Sdim 591221345Sdim /* Do SDP Service Search Attribute Request */ 592221345Sdim n = sdp_search(xs, 1, &service, attrs_len, attrs, values_len, values); 593221345Sdim if (n != 0) 594221345Sdim return (ERROR); 595221345Sdim 596221345Sdim /* Print attributes values */ 597280031Sdim for (n = 0; n < values_len; n ++) { 598280031Sdim if (values[n].flags != SDP_ATTR_OK) 599280031Sdim break; 600280031Sdim 601280031Sdim switch (values[n].attr) { 602280031Sdim case SDP_ATTR_SERVICE_RECORD_HANDLE: 603280031Sdim fprintf(stdout, "\n"); 604280031Sdim if (values[n].vlen == 5) { 605280031Sdim SDP_GET8(type, values[n].value); 606280031Sdim if (type == SDP_DATA_UINT32) { 607280031Sdim SDP_GET32(value, values[n].value); 608221345Sdim fprintf(stdout, "Record Handle: " \ 609221345Sdim "%#8.8x\n", value); 610221345Sdim } else 611221345Sdim fprintf(stderr, "Invalid type=%#x " \ 612221345Sdim "Record Handle " \ 613221345Sdim "attribute!\n", type); 614221345Sdim } else 615221345Sdim fprintf(stderr, "Invalid size=%d for Record " \ 616226633Sdim "Handle attribute\n", 617221345Sdim values[n].vlen); 618221345Sdim break; 619221345Sdim 620261991Sdim case SDP_ATTR_SERVICE_CLASS_ID_LIST: 621221345Sdim fprintf(stdout, "Service Class ID List:\n"); 622221345Sdim print_service_class_id_list(values[n].value, 623221345Sdim values[n].value + values[n].vlen); 624221345Sdim break; 625221345Sdim 626221345Sdim case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST: 627221345Sdim fprintf(stdout, "Protocol Descriptor List:\n"); 628221345Sdim print_protocol_descriptor_list(values[n].value, 629221345Sdim values[n].value + values[n].vlen); 630221345Sdim break; 631221345Sdim 632221345Sdim case SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST: 633221345Sdim fprintf(stdout, "Bluetooth Profile Descriptor List:\n"); 634221345Sdim print_bluetooth_profile_descriptor_list(values[n].value, 635221345Sdim values[n].value + values[n].vlen); 636221345Sdim break; 637221345Sdim 638221345Sdim default: 639280031Sdim fprintf(stderr, "Unexpected attribute ID=%#4.4x\n", 640221345Sdim values[n].attr); 641221345Sdim break; 642221345Sdim } 643221345Sdim } 644221345Sdim 645221345Sdim return (OK); 646221345Sdim} /* do_sdp_search */ 647221345Sdim 648221345Sdim/* Perform SDP browse command */ 649221345Sdimstatic int 650221345Sdimdo_sdp_browse(void *xs, int argc, char **argv) 651221345Sdim{ 652221345Sdim#undef _STR 653221345Sdim#undef STR 654276479Sdim#define _STR(x) #x 655221345Sdim#define STR(x) _STR(x) 656221345Sdim 657221345Sdim static char const * const av[] = { 658221345Sdim STR(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP), 659221345Sdim NULL 660221345Sdim }; 661221345Sdim 662221345Sdim switch (argc) { 663221345Sdim case 0: 664221345Sdim argc = 1; 665221345Sdim argv = (char **) av; 666221345Sdim /* FALL THROUGH */ 667221345Sdim case 1: 668221345Sdim return (do_sdp_search(xs, argc, argv)); 669221345Sdim } 670221345Sdim 671221345Sdim return (USAGE); 672221345Sdim} /* do_sdp_browse */ 673221345Sdim 674221345Sdim/* List of SDP commands */ 675221345Sdimstruct sdp_command sdp_commands[] = { 676221345Sdim{ 677221345Sdim"Browse [<Group>]", 678221345Sdim"Browse for services. The <Group> parameter is a 16-bit UUID of the group\n" \ 679221345Sdim"to browse. If omitted <Group> is set to Public Browse Group.\n\n" \ 680221345Sdim"\t<Group> - xxxx; 16-bit UUID of the group to browse\n", 681221345Sdimdo_sdp_browse 682221345Sdim}, 683221345Sdim{ 684221345Sdim"Search <Service>", 685"Search for the <Service>. The <Service> parameter is a 16-bit UUID of the\n" \ 686"service to search for. For some services it is possible to use service name\n"\ 687"instead of service UUID\n\n" \ 688"\t<Service> - xxxx; 16-bit UUID of the service to search for\n\n" \ 689"\tKnown service names\n" \ 690"\t===================\n" \ 691"\tCIP - Common ISDN Access\n" \ 692"\tCTP - Cordless Telephony\n" \ 693"\tDUN - DialUp Networking\n" \ 694"\tFAX - Fax\n" \ 695"\tFTRN - OBEX File Transfer\n" \ 696"\tGN - GN\n" \ 697"\tHID - Human Interface Device\n" \ 698"\tHSET - Headset\n" \ 699"\tLAN - LAN Access Using PPP\n" \ 700"\tNAP - Network Access Point\n" \ 701"\tOPUSH - OBEX Object Push\n" \ 702"\tSP - Serial Port\n", 703do_sdp_search 704}, 705{ NULL, NULL, NULL } 706}; 707 708