1121054Semax/* 2121054Semax * search.c 3121054Semax * 4121054Semax * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> 5121054Semax * All rights reserved. 6121054Semax * 7121054Semax * Redistribution and use in source and binary forms, with or without 8121054Semax * modification, are permitted provided that the following conditions 9121054Semax * are met: 10121054Semax * 1. Redistributions of source code must retain the above copyright 11121054Semax * notice, this list of conditions and the following disclaimer. 12121054Semax * 2. Redistributions in binary form must reproduce the above copyright 13121054Semax * notice, this list of conditions and the following disclaimer in the 14121054Semax * documentation and/or other materials provided with the distribution. 15121054Semax * 16121054Semax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17121054Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18121054Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19121054Semax * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20121054Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21121054Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22121054Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23121054Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24121054Semax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25121054Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26121054Semax * SUCH DAMAGE. 27121054Semax * 28121054Semax * $Id: search.c,v 1.2 2003/09/08 17:35:15 max Exp $ 29121054Semax * $FreeBSD$ 30121054Semax */ 31121054Semax 32146691Semax#include <netinet/in.h> 33121054Semax#include <bluetooth.h> 34121054Semax#include <ctype.h> 35121054Semax#include <sdp.h> 36121054Semax#include <stdio.h> 37121054Semax#include <stdlib.h> 38121054Semax#include "sdpcontrol.h" 39121054Semax 40121054Semax/* List of the attributes we are looking for */ 41124317Semaxstatic uint32_t attrs[] = 42121054Semax{ 43121054Semax SDP_ATTR_RANGE( SDP_ATTR_SERVICE_RECORD_HANDLE, 44121054Semax SDP_ATTR_SERVICE_RECORD_HANDLE), 45121054Semax SDP_ATTR_RANGE( SDP_ATTR_SERVICE_CLASS_ID_LIST, 46121054Semax SDP_ATTR_SERVICE_CLASS_ID_LIST), 47121054Semax SDP_ATTR_RANGE( SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, 48121054Semax SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST), 49121054Semax SDP_ATTR_RANGE( SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, 50121054Semax SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST) 51121054Semax}; 52121054Semax#define attrs_len (sizeof(attrs)/sizeof(attrs[0])) 53121054Semax 54121054Semax/* Buffer for the attributes */ 55121054Semax#define NRECS 25 /* request this much records from the SDP server */ 56121054Semax#define BSIZE 256 /* one attribute buffer size */ 57124317Semaxstatic uint8_t buffer[NRECS * attrs_len][BSIZE]; 58121054Semax 59121054Semax/* SDP attributes */ 60121054Semaxstatic sdp_attr_t values[NRECS * attrs_len]; 61121054Semax#define values_len (sizeof(values)/sizeof(values[0])) 62121054Semax 63121054Semax/* 64121054Semax * Print Service Class ID List 65121054Semax * 66121054Semax * The ServiceClassIDList attribute consists of a data element sequence in 67121054Semax * which each data element is a UUID representing the service classes that 68121054Semax * a given service record conforms to. The UUIDs are listed in order from 69121054Semax * the most specific class to the most general class. The ServiceClassIDList 70121054Semax * must contain at least one service class UUID. 71121054Semax */ 72121054Semax 73121054Semaxstatic void 74124317Semaxprint_service_class_id_list(uint8_t const *start, uint8_t const *end) 75121054Semax{ 76124317Semax uint32_t type, len, value; 77121054Semax 78121054Semax if (end - start < 2) { 79121054Semax fprintf(stderr, "Invalid Service Class ID List. " \ 80128076Semax "Too short, len=%zd\n", end - start); 81121054Semax return; 82121054Semax } 83121054Semax 84121054Semax SDP_GET8(type, start); 85121054Semax switch (type) { 86121054Semax case SDP_DATA_SEQ8: 87121054Semax SDP_GET8(len, start); 88121054Semax break; 89121054Semax 90121054Semax case SDP_DATA_SEQ16: 91121054Semax SDP_GET16(len, start); 92121054Semax break; 93121054Semax 94121054Semax case SDP_DATA_SEQ32: 95121054Semax SDP_GET32(len, start); 96121054Semax break; 97121054Semax 98121054Semax default: 99121054Semax fprintf(stderr, "Invalid Service Class ID List. " \ 100121054Semax "Not a sequence, type=%#x\n", type); 101121054Semax return; 102121054Semax /* NOT REACHED */ 103121054Semax } 104121054Semax 105290395Semax if (len > (end - start)) { 106290395Semax fprintf(stderr, "Invalid Service Class ID List. " \ 107290395Semax "Too long len=%d\n", len); 108290395Semax return; 109290395Semax } 110290395Semax 111121054Semax while (start < end) { 112121054Semax SDP_GET8(type, start); 113121054Semax switch (type) { 114121054Semax case SDP_DATA_UUID16: 115121054Semax SDP_GET16(value, start); 116121054Semax fprintf(stdout, "\t%s (%#4.4x)\n", 117121054Semax sdp_uuid2desc(value), value); 118121054Semax break; 119121054Semax 120121054Semax case SDP_DATA_UUID32: 121121054Semax SDP_GET32(value, start); 122121054Semax fprintf(stdout, "\t%#8.8x\n", value); 123121054Semax break; 124121054Semax 125121054Semax case SDP_DATA_UUID128: { 126121054Semax int128_t uuid; 127121054Semax 128146691Semax SDP_GET_UUID128(&uuid, start); 129121054Semax fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", 130146691Semax ntohl(*(uint32_t *)&uuid.b[0]), 131146691Semax ntohs(*(uint16_t *)&uuid.b[4]), 132146691Semax ntohs(*(uint16_t *)&uuid.b[6]), 133146691Semax ntohs(*(uint16_t *)&uuid.b[8]), 134146691Semax ntohs(*(uint16_t *)&uuid.b[10]), 135146691Semax ntohl(*(uint32_t *)&uuid.b[12])); 136121054Semax } break; 137121054Semax 138121054Semax default: 139121054Semax fprintf(stderr, "Invalid Service Class ID List. " \ 140121054Semax "Not a UUID, type=%#x\n", type); 141121054Semax return; 142121054Semax /* NOT REACHED */ 143121054Semax } 144121054Semax } 145121054Semax} /* print_service_class_id_list */ 146121054Semax 147121054Semax/* 148121054Semax * Print Protocol Descriptor List 149121054Semax * 150121054Semax * If the ProtocolDescriptorList describes a single stack, it takes the form 151121054Semax * of a data element sequence in which each element of the sequence is a 152121054Semax * protocol descriptor. Each protocol descriptor is, in turn, a data element 153121054Semax * sequence whose first element is a UUID identifying the protocol and whose 154121054Semax * successive elements are protocol-specific parameters. The protocol 155121054Semax * descriptors are listed in order from the lowest layer protocol to the 156121054Semax * highest layer protocol used to gain access to the service. If it is possible 157121054Semax * for more than one kind of protocol stack to be used to gain access to the 158121054Semax * service, the ProtocolDescriptorList takes the form of a data element 159121054Semax * alternative where each member is a data element sequence as described above. 160121054Semax */ 161121054Semax 162121054Semaxstatic void 163124317Semaxprint_protocol_descriptor(uint8_t const *start, uint8_t const *end) 164121054Semax{ 165121054Semax union { 166121054Semax uint8_t uint8; 167121054Semax uint16_t uint16; 168121054Semax uint32_t uint32; 169121054Semax uint64_t uint64; 170121054Semax int128_t int128; 171121054Semax } value; 172124317Semax uint32_t type, len, param; 173121054Semax 174121054Semax /* Get Protocol UUID */ 175121054Semax SDP_GET8(type, start); 176121054Semax switch (type) { 177121054Semax case SDP_DATA_UUID16: 178121054Semax SDP_GET16(value.uint16, start); 179121054Semax fprintf(stdout, "\t%s (%#4.4x)\n", sdp_uuid2desc(value.uint16), 180121054Semax value.uint16); 181121054Semax break; 182121054Semax 183121054Semax case SDP_DATA_UUID32: 184121054Semax SDP_GET32(value.uint32, start); 185121054Semax fprintf(stdout, "\t%#8.8x\n", value.uint32); 186121054Semax break; 187121054Semax 188121054Semax case SDP_DATA_UUID128: 189146691Semax SDP_GET_UUID128(&value.int128, start); 190121054Semax fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", 191146691Semax ntohl(*(uint32_t *)&value.int128.b[0]), 192146691Semax ntohs(*(uint16_t *)&value.int128.b[4]), 193146691Semax ntohs(*(uint16_t *)&value.int128.b[6]), 194146691Semax ntohs(*(uint16_t *)&value.int128.b[8]), 195146691Semax ntohs(*(uint16_t *)&value.int128.b[10]), 196146691Semax ntohl(*(uint32_t *)&value.int128.b[12])); 197121054Semax break; 198121054Semax 199121054Semax default: 200121054Semax fprintf(stderr, "Invalid Protocol Descriptor. " \ 201121054Semax "Not a UUID, type=%#x\n", type); 202121054Semax return; 203121054Semax /* NOT REACHED */ 204121054Semax } 205121054Semax 206121054Semax /* Protocol specific parameters */ 207121054Semax for (param = 1; start < end; param ++) { 208121054Semax fprintf(stdout, "\t\tProtocol specific parameter #%d: ", param); 209121054Semax 210121054Semax SDP_GET8(type, start); 211121054Semax switch (type) { 212121054Semax case SDP_DATA_NIL: 213121054Semax fprintf(stdout, "nil\n"); 214121054Semax break; 215121054Semax 216121054Semax case SDP_DATA_UINT8: 217121054Semax case SDP_DATA_INT8: 218121054Semax case SDP_DATA_BOOL: 219121054Semax SDP_GET8(value.uint8, start); 220121054Semax fprintf(stdout, "u/int8/bool %u\n", value.uint8); 221121054Semax break; 222121054Semax 223121054Semax case SDP_DATA_UINT16: 224121054Semax case SDP_DATA_INT16: 225121054Semax case SDP_DATA_UUID16: 226121054Semax SDP_GET16(value.uint16, start); 227121054Semax fprintf(stdout, "u/int/uuid16 %u\n", value.uint16); 228121054Semax break; 229121054Semax 230121054Semax case SDP_DATA_UINT32: 231121054Semax case SDP_DATA_INT32: 232121054Semax case SDP_DATA_UUID32: 233121054Semax SDP_GET32(value.uint32, start); 234121054Semax fprintf(stdout, "u/int/uuid32 %u\n", value.uint32); 235121054Semax break; 236121054Semax 237121054Semax case SDP_DATA_UINT64: 238121054Semax case SDP_DATA_INT64: 239121054Semax SDP_GET64(value.uint64, start); 240128076Semax fprintf(stdout, "u/int64 %ju\n", value.uint64); 241121054Semax break; 242121054Semax 243121054Semax case SDP_DATA_UINT128: 244121054Semax case SDP_DATA_INT128: 245121054Semax SDP_GET128(&value.int128, start); 246146691Semax fprintf(stdout, "u/int128 %#8.8x%8.8x%8.8x%8.8x\n", 247124317Semax *(uint32_t *)&value.int128.b[0], 248146691Semax *(uint32_t *)&value.int128.b[4], 249146691Semax *(uint32_t *)&value.int128.b[8], 250124317Semax *(uint32_t *)&value.int128.b[12]); 251121054Semax break; 252121054Semax 253146691Semax case SDP_DATA_UUID128: 254146691Semax SDP_GET_UUID128(&value.int128, start); 255146691Semax fprintf(stdout, "uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", 256146691Semax ntohl(*(uint32_t *)&value.int128.b[0]), 257146691Semax ntohs(*(uint16_t *)&value.int128.b[4]), 258146691Semax ntohs(*(uint16_t *)&value.int128.b[6]), 259146691Semax ntohs(*(uint16_t *)&value.int128.b[8]), 260146691Semax ntohs(*(uint16_t *)&value.int128.b[10]), 261146691Semax ntohl(*(uint32_t *)&value.int128.b[12])); 262146691Semax break; 263146691Semax 264121054Semax case SDP_DATA_STR8: 265121054Semax case SDP_DATA_URL8: 266121054Semax SDP_GET8(len, start); 267290395Semax for (; start < end && len > 0; start ++, len --) 268290395Semax fprintf(stdout, "%c", *start); 269290395Semax fprintf(stdout, "\n"); 270121054Semax break; 271121054Semax 272121054Semax case SDP_DATA_STR16: 273121054Semax case SDP_DATA_URL16: 274121054Semax SDP_GET16(len, start); 275290395Semax for (; start < end && len > 0; start ++, len --) 276290395Semax fprintf(stdout, "%c", *start); 277290395Semax fprintf(stdout, "\n"); 278121054Semax break; 279121054Semax 280121054Semax case SDP_DATA_STR32: 281121054Semax case SDP_DATA_URL32: 282121054Semax SDP_GET32(len, start); 283290395Semax for (; start < end && len > 0; start ++, len --) 284290395Semax fprintf(stdout, "%c", *start); 285290395Semax fprintf(stdout, "\n"); 286121054Semax break; 287121054Semax 288121054Semax case SDP_DATA_SEQ8: 289121054Semax case SDP_DATA_ALT8: 290121054Semax SDP_GET8(len, start); 291290395Semax for (; start < end && len > 0; start ++, len --) 292121054Semax fprintf(stdout, "%#2.2x ", *start); 293121054Semax fprintf(stdout, "\n"); 294121054Semax break; 295121054Semax 296121054Semax case SDP_DATA_SEQ16: 297121054Semax case SDP_DATA_ALT16: 298121054Semax SDP_GET16(len, start); 299290395Semax for (; start < end && len > 0; start ++, len --) 300121054Semax fprintf(stdout, "%#2.2x ", *start); 301121054Semax fprintf(stdout, "\n"); 302121054Semax break; 303121054Semax 304121054Semax case SDP_DATA_SEQ32: 305121054Semax case SDP_DATA_ALT32: 306121054Semax SDP_GET32(len, start); 307290395Semax for (; start < end && len > 0; start ++, len --) 308121054Semax fprintf(stdout, "%#2.2x ", *start); 309121054Semax fprintf(stdout, "\n"); 310121054Semax break; 311121054Semax 312121054Semax default: 313121054Semax fprintf(stderr, "Invalid Protocol Descriptor. " \ 314121054Semax "Unknown data type: %#02x\n", type); 315121054Semax return; 316121054Semax /* NOT REACHED */ 317121054Semax } 318121054Semax } 319121054Semax} /* print_protocol_descriptor */ 320121054Semax 321121054Semaxstatic void 322124317Semaxprint_protocol_descriptor_list(uint8_t const *start, uint8_t const *end) 323121054Semax{ 324124317Semax uint32_t type, len; 325121054Semax 326121054Semax if (end - start < 2) { 327121054Semax fprintf(stderr, "Invalid Protocol Descriptor List. " \ 328128076Semax "Too short, len=%zd\n", end - start); 329121054Semax return; 330121054Semax } 331121054Semax 332121054Semax SDP_GET8(type, start); 333121054Semax switch (type) { 334121054Semax case SDP_DATA_SEQ8: 335121054Semax SDP_GET8(len, start); 336121054Semax break; 337121054Semax 338121054Semax case SDP_DATA_SEQ16: 339121054Semax SDP_GET16(len, start); 340121054Semax break; 341121054Semax 342121054Semax case SDP_DATA_SEQ32: 343121054Semax SDP_GET32(len, start); 344121054Semax break; 345121054Semax 346121054Semax default: 347121054Semax fprintf(stderr, "Invalid Protocol Descriptor List. " \ 348121054Semax "Not a sequence, type=%#x\n", type); 349121054Semax return; 350121054Semax /* NOT REACHED */ 351121054Semax } 352121054Semax 353290395Semax if (len > (end - start)) { 354290395Semax fprintf(stderr, "Invalid Protocol Descriptor List. " \ 355290395Semax "Too long, len=%d\n", len); 356290395Semax return; 357290395Semax } 358290395Semax 359121054Semax while (start < end) { 360121054Semax SDP_GET8(type, start); 361121054Semax switch (type) { 362121054Semax case SDP_DATA_SEQ8: 363121054Semax SDP_GET8(len, start); 364121054Semax break; 365121054Semax 366121054Semax case SDP_DATA_SEQ16: 367121054Semax SDP_GET16(len, start); 368121054Semax break; 369121054Semax 370121054Semax case SDP_DATA_SEQ32: 371121054Semax SDP_GET32(len, start); 372121054Semax break; 373121054Semax 374121054Semax default: 375121054Semax fprintf(stderr, "Invalid Protocol Descriptor List. " \ 376121054Semax "Not a sequence, type=%#x\n", type); 377121054Semax return; 378121054Semax /* NOT REACHED */ 379121054Semax } 380121054Semax 381290395Semax if (len > (end - start)) { 382290395Semax fprintf(stderr, "Invalid Protocol Descriptor List. " \ 383290395Semax "Too long, len=%d\n", len); 384290395Semax return; 385290395Semax } 386290395Semax 387121054Semax print_protocol_descriptor(start, start + len); 388121054Semax start += len; 389121054Semax } 390121054Semax} /* print_protocol_descriptor_list */ 391121054Semax 392121054Semax/* 393121054Semax * Print Bluetooth Profile Descriptor List 394121054Semax * 395121054Semax * The BluetoothProfileDescriptorList attribute consists of a data element 396121054Semax * sequence in which each element is a profile descriptor that contains 397121054Semax * information about a Bluetooth profile to which the service represented by 398121054Semax * this service record conforms. Each profile descriptor is a data element 399121054Semax * sequence whose first element is the UUID assigned to the profile and whose 400121054Semax * second element is a 16-bit profile version number. Each version of a profile 401121054Semax * is assigned a 16-bit unsigned integer profile version number, which consists 402121054Semax * of two 8-bit fields. The higher-order 8 bits contain the major version 403121054Semax * number field and the lower-order 8 bits contain the minor version number 404121054Semax * field. 405121054Semax */ 406121054Semax 407121054Semaxstatic void 408124317Semaxprint_bluetooth_profile_descriptor_list(uint8_t const *start, uint8_t const *end) 409121054Semax{ 410124317Semax uint32_t type, len, value; 411121054Semax 412121054Semax if (end - start < 2) { 413121054Semax fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \ 414128076Semax "Too short, len=%zd\n", end - start); 415121054Semax return; 416121054Semax } 417121054Semax 418121054Semax SDP_GET8(type, start); 419121054Semax switch (type) { 420121054Semax case SDP_DATA_SEQ8: 421121054Semax SDP_GET8(len, start); 422121054Semax break; 423121054Semax 424121054Semax case SDP_DATA_SEQ16: 425121054Semax SDP_GET16(len, start); 426121054Semax break; 427121054Semax 428121054Semax case SDP_DATA_SEQ32: 429121054Semax SDP_GET32(len, start); 430121054Semax break; 431121054Semax 432121054Semax default: 433121054Semax fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \ 434121054Semax "Not a sequence, type=%#x\n", type); 435121054Semax return; 436121054Semax /* NOT REACHED */ 437121054Semax } 438121054Semax 439290395Semax if (len > (end - start)) { 440290395Semax fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \ 441290395Semax "Too long, len=%d\n", len); 442290395Semax return; 443290395Semax } 444290395Semax 445121054Semax while (start < end) { 446121054Semax SDP_GET8(type, start); 447121054Semax switch (type) { 448121054Semax case SDP_DATA_SEQ8: 449121054Semax SDP_GET8(len, start); 450121054Semax break; 451121054Semax 452121054Semax case SDP_DATA_SEQ16: 453121054Semax SDP_GET16(len, start); 454121054Semax break; 455121054Semax 456121054Semax case SDP_DATA_SEQ32: 457121054Semax SDP_GET32(len, start); 458121054Semax break; 459121054Semax 460121054Semax default: 461121054Semax fprintf(stderr, "Invalid Bluetooth Profile " \ 462121054Semax "Descriptor List. " \ 463121054Semax "Not a sequence, type=%#x\n", type); 464121054Semax return; 465121054Semax /* NOT REACHED */ 466121054Semax } 467121054Semax 468290395Semax if (len > (end - start)) { 469290395Semax fprintf(stderr, "Invalid Bluetooth Profile " \ 470290395Semax "Descriptor List. " \ 471290395Semax "Too long, len=%d\n", len); 472290395Semax return; 473290395Semax } 474290395Semax 475121054Semax /* Get UUID */ 476121054Semax SDP_GET8(type, start); 477121054Semax switch (type) { 478121054Semax case SDP_DATA_UUID16: 479121054Semax SDP_GET16(value, start); 480121054Semax fprintf(stdout, "\t%s (%#4.4x) ", 481121054Semax sdp_uuid2desc(value), value); 482121054Semax break; 483121054Semax 484121054Semax case SDP_DATA_UUID32: 485121054Semax SDP_GET32(value, start); 486121054Semax fprintf(stdout, "\t%#8.8x ", value); 487121054Semax break; 488121054Semax 489121054Semax case SDP_DATA_UUID128: { 490121054Semax int128_t uuid; 491121054Semax 492146691Semax SDP_GET_UUID128(&uuid, start); 493121054Semax fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x ", 494146691Semax ntohl(*(uint32_t *)&uuid.b[0]), 495146691Semax ntohs(*(uint16_t *)&uuid.b[4]), 496146691Semax ntohs(*(uint16_t *)&uuid.b[6]), 497146691Semax ntohs(*(uint16_t *)&uuid.b[8]), 498146691Semax ntohs(*(uint16_t *)&uuid.b[10]), 499146691Semax ntohl(*(uint32_t *)&uuid.b[12])); 500121054Semax } break; 501121054Semax 502121054Semax default: 503121054Semax fprintf(stderr, "Invalid Bluetooth Profile " \ 504121054Semax "Descriptor List. " \ 505121054Semax "Not a UUID, type=%#x\n", type); 506121054Semax return; 507121054Semax /* NOT REACHED */ 508121054Semax } 509121054Semax 510121054Semax /* Get version */ 511121054Semax SDP_GET8(type, start); 512121054Semax if (type != SDP_DATA_UINT16) { 513121054Semax fprintf(stderr, "Invalid Bluetooth Profile " \ 514121054Semax "Descriptor List. " \ 515121054Semax "Invalid version type=%#x\n", type); 516121054Semax return; 517121054Semax } 518121054Semax 519121054Semax SDP_GET16(value, start); 520121054Semax fprintf(stdout, "ver. %d.%d\n", 521121054Semax (value >> 8) & 0xff, value & 0xff); 522121054Semax } 523121054Semax} /* print_bluetooth_profile_descriptor_list */ 524121054Semax 525121054Semax/* Perform SDP search command */ 526121054Semaxstatic int 527121054Semaxdo_sdp_search(void *xs, int argc, char **argv) 528121054Semax{ 529121054Semax char *ep = NULL; 530121054Semax int32_t n, type, value; 531124317Semax uint16_t service; 532121054Semax 533121054Semax /* Parse command line arguments */ 534121054Semax switch (argc) { 535121054Semax case 1: 536121054Semax n = strtoul(argv[0], &ep, 16); 537121054Semax if (*ep != 0) { 538121054Semax switch (tolower(argv[0][0])) { 539121054Semax case 'c': /* CIP/CTP */ 540121054Semax switch (tolower(argv[0][1])) { 541121054Semax case 'i': 542121054Semax service = SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS; 543121054Semax break; 544121054Semax 545121054Semax case 't': 546121054Semax service = SDP_SERVICE_CLASS_CORDLESS_TELEPHONY; 547121054Semax break; 548121054Semax 549121054Semax default: 550121054Semax return (USAGE); 551121054Semax /* NOT REACHED */ 552121054Semax } 553121054Semax break; 554121054Semax 555121054Semax case 'd': /* DialUp Networking */ 556121054Semax service = SDP_SERVICE_CLASS_DIALUP_NETWORKING; 557121054Semax break; 558121054Semax 559121054Semax case 'f': /* Fax/OBEX File Transfer */ 560121054Semax switch (tolower(argv[0][1])) { 561121054Semax case 'a': 562121054Semax service = SDP_SERVICE_CLASS_FAX; 563121054Semax break; 564121054Semax 565121054Semax case 't': 566121054Semax service = SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER; 567121054Semax break; 568121054Semax 569121054Semax default: 570121054Semax return (USAGE); 571121054Semax /* NOT REACHED */ 572121054Semax } 573121054Semax break; 574121054Semax 575121054Semax case 'g': /* GN */ 576121054Semax service = SDP_SERVICE_CLASS_GN; 577121054Semax break; 578121054Semax 579121054Semax case 'h': /* Headset/HID */ 580121054Semax switch (tolower(argv[0][1])) { 581121054Semax case 'i': 582121054Semax service = SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE; 583121054Semax break; 584121054Semax 585121054Semax case 's': 586121054Semax service = SDP_SERVICE_CLASS_HEADSET; 587121054Semax break; 588121054Semax 589121054Semax default: 590121054Semax return (USAGE); 591121054Semax /* NOT REACHED */ 592121054Semax } 593121054Semax break; 594121054Semax 595121054Semax case 'l': /* LAN Access Using PPP */ 596121054Semax service = SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP; 597121054Semax break; 598121054Semax 599121054Semax case 'n': /* NAP */ 600121054Semax service = SDP_SERVICE_CLASS_NAP; 601121054Semax break; 602121054Semax 603121054Semax case 'o': /* OBEX Object Push */ 604121054Semax service = SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH; 605121054Semax break; 606121054Semax 607121054Semax case 's': /* Serial Port */ 608121054Semax service = SDP_SERVICE_CLASS_SERIAL_PORT; 609121054Semax break; 610121054Semax 611121054Semax default: 612121054Semax return (USAGE); 613121054Semax /* NOT REACHED */ 614121054Semax } 615121054Semax } else 616124317Semax service = (uint16_t) n; 617121054Semax break; 618121054Semax 619121054Semax default: 620121054Semax return (USAGE); 621121054Semax } 622121054Semax 623121054Semax /* Initialize attribute values array */ 624121054Semax for (n = 0; n < values_len; n ++) { 625121054Semax values[n].flags = SDP_ATTR_INVALID; 626121054Semax values[n].attr = 0; 627121054Semax values[n].vlen = BSIZE; 628121054Semax values[n].value = buffer[n]; 629121054Semax } 630121054Semax 631121054Semax /* Do SDP Service Search Attribute Request */ 632121054Semax n = sdp_search(xs, 1, &service, attrs_len, attrs, values_len, values); 633121054Semax if (n != 0) 634121054Semax return (ERROR); 635121054Semax 636121054Semax /* Print attributes values */ 637121054Semax for (n = 0; n < values_len; n ++) { 638121054Semax if (values[n].flags != SDP_ATTR_OK) 639121054Semax break; 640121054Semax 641121054Semax switch (values[n].attr) { 642121054Semax case SDP_ATTR_SERVICE_RECORD_HANDLE: 643121054Semax fprintf(stdout, "\n"); 644121054Semax if (values[n].vlen == 5) { 645121054Semax SDP_GET8(type, values[n].value); 646121054Semax if (type == SDP_DATA_UINT32) { 647121054Semax SDP_GET32(value, values[n].value); 648121054Semax fprintf(stdout, "Record Handle: " \ 649121054Semax "%#8.8x\n", value); 650121054Semax } else 651121054Semax fprintf(stderr, "Invalid type=%#x " \ 652121054Semax "Record Handle " \ 653121054Semax "attribute!\n", type); 654121054Semax } else 655121054Semax fprintf(stderr, "Invalid size=%d for Record " \ 656121054Semax "Handle attribute\n", 657121054Semax values[n].vlen); 658121054Semax break; 659121054Semax 660121054Semax case SDP_ATTR_SERVICE_CLASS_ID_LIST: 661121054Semax fprintf(stdout, "Service Class ID List:\n"); 662121054Semax print_service_class_id_list(values[n].value, 663121054Semax values[n].value + values[n].vlen); 664121054Semax break; 665121054Semax 666121054Semax case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST: 667121054Semax fprintf(stdout, "Protocol Descriptor List:\n"); 668121054Semax print_protocol_descriptor_list(values[n].value, 669121054Semax values[n].value + values[n].vlen); 670121054Semax break; 671121054Semax 672121054Semax case SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST: 673121054Semax fprintf(stdout, "Bluetooth Profile Descriptor List:\n"); 674121054Semax print_bluetooth_profile_descriptor_list(values[n].value, 675121054Semax values[n].value + values[n].vlen); 676121054Semax break; 677121054Semax 678121054Semax default: 679121054Semax fprintf(stderr, "Unexpected attribute ID=%#4.4x\n", 680121054Semax values[n].attr); 681121054Semax break; 682121054Semax } 683121054Semax } 684121054Semax 685121054Semax return (OK); 686121054Semax} /* do_sdp_search */ 687121054Semax 688121054Semax/* Perform SDP browse command */ 689121054Semaxstatic int 690121054Semaxdo_sdp_browse(void *xs, int argc, char **argv) 691121054Semax{ 692121054Semax#undef _STR 693121054Semax#undef STR 694121054Semax#define _STR(x) #x 695121054Semax#define STR(x) _STR(x) 696121054Semax 697121054Semax static char const * const av[] = { 698121054Semax STR(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP), 699121054Semax NULL 700121054Semax }; 701121054Semax 702121054Semax switch (argc) { 703121054Semax case 0: 704121054Semax argc = 1; 705121054Semax argv = (char **) av; 706121054Semax /* FALL THROUGH */ 707121054Semax case 1: 708121054Semax return (do_sdp_search(xs, argc, argv)); 709121054Semax } 710121054Semax 711121054Semax return (USAGE); 712121054Semax} /* do_sdp_browse */ 713121054Semax 714121054Semax/* List of SDP commands */ 715121054Semaxstruct sdp_command sdp_commands[] = { 716121054Semax{ 717121054Semax"Browse [<Group>]", 718121054Semax"Browse for services. The <Group> parameter is a 16-bit UUID of the group\n" \ 719121054Semax"to browse. If omitted <Group> is set to Public Browse Group.\n\n" \ 720121054Semax"\t<Group> - xxxx; 16-bit UUID of the group to browse\n", 721121054Semaxdo_sdp_browse 722121054Semax}, 723121054Semax{ 724121054Semax"Search <Service>", 725121054Semax"Search for the <Service>. The <Service> parameter is a 16-bit UUID of the\n" \ 726121054Semax"service to search for. For some services it is possible to use service name\n"\ 727121054Semax"instead of service UUID\n\n" \ 728121054Semax"\t<Service> - xxxx; 16-bit UUID of the service to search for\n\n" \ 729121054Semax"\tKnown service names\n" \ 730121054Semax"\t===================\n" \ 731121054Semax"\tCIP - Common ISDN Access\n" \ 732121054Semax"\tCTP - Cordless Telephony\n" \ 733121054Semax"\tDUN - DialUp Networking\n" \ 734121054Semax"\tFAX - Fax\n" \ 735121054Semax"\tFTRN - OBEX File Transfer\n" \ 736121054Semax"\tGN - GN\n" \ 737121054Semax"\tHID - Human Interface Device\n" \ 738121054Semax"\tHSET - Headset\n" \ 739121054Semax"\tLAN - LAN Access Using PPP\n" \ 740121054Semax"\tNAP - Network Access Point\n" \ 741121054Semax"\tOPUSH - OBEX Object Push\n" \ 742121054Semax"\tSP - Serial Port\n", 743121054Semaxdo_sdp_search 744121054Semax}, 745121054Semax{ NULL, NULL, NULL } 746121054Semax}; 747121054Semax 748