1330449Seadler/*- 2121054Semax * search.c 3121054Semax * 4330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 5330449Seadler * 6121054Semax * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> 7121054Semax * All rights reserved. 8121054Semax * 9121054Semax * Redistribution and use in source and binary forms, with or without 10121054Semax * modification, are permitted provided that the following conditions 11121054Semax * are met: 12121054Semax * 1. Redistributions of source code must retain the above copyright 13121054Semax * notice, this list of conditions and the following disclaimer. 14121054Semax * 2. Redistributions in binary form must reproduce the above copyright 15121054Semax * notice, this list of conditions and the following disclaimer in the 16121054Semax * documentation and/or other materials provided with the distribution. 17121054Semax * 18121054Semax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19121054Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20121054Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21121054Semax * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22121054Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23121054Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24121054Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25121054Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26121054Semax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27121054Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28121054Semax * SUCH DAMAGE. 29121054Semax * 30121054Semax * $Id: search.c,v 1.2 2003/09/08 17:35:15 max Exp $ 31121054Semax * $FreeBSD: stable/11/usr.sbin/bluetooth/sdpcontrol/search.c 330449 2018-03-05 07:26:05Z eadler $ 32121054Semax */ 33121054Semax 34146691Semax#include <netinet/in.h> 35281210Stakawata#define L2CAP_SOCKET_CHECKED 36121054Semax#include <bluetooth.h> 37121054Semax#include <ctype.h> 38121054Semax#include <sdp.h> 39121054Semax#include <stdio.h> 40121054Semax#include <stdlib.h> 41121054Semax#include "sdpcontrol.h" 42121054Semax 43121054Semax/* List of the attributes we are looking for */ 44124317Semaxstatic uint32_t attrs[] = 45121054Semax{ 46121054Semax SDP_ATTR_RANGE( SDP_ATTR_SERVICE_RECORD_HANDLE, 47121054Semax SDP_ATTR_SERVICE_RECORD_HANDLE), 48121054Semax SDP_ATTR_RANGE( SDP_ATTR_SERVICE_CLASS_ID_LIST, 49121054Semax SDP_ATTR_SERVICE_CLASS_ID_LIST), 50121054Semax SDP_ATTR_RANGE( SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, 51121054Semax SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST), 52121054Semax SDP_ATTR_RANGE( SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, 53121054Semax SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST) 54121054Semax}; 55121054Semax#define attrs_len (sizeof(attrs)/sizeof(attrs[0])) 56121054Semax 57121054Semax/* Buffer for the attributes */ 58121054Semax#define NRECS 25 /* request this much records from the SDP server */ 59121054Semax#define BSIZE 256 /* one attribute buffer size */ 60124317Semaxstatic uint8_t buffer[NRECS * attrs_len][BSIZE]; 61121054Semax 62121054Semax/* SDP attributes */ 63121054Semaxstatic sdp_attr_t values[NRECS * attrs_len]; 64121054Semax#define values_len (sizeof(values)/sizeof(values[0])) 65121054Semax 66121054Semax/* 67121054Semax * Print Service Class ID List 68121054Semax * 69121054Semax * The ServiceClassIDList attribute consists of a data element sequence in 70121054Semax * which each data element is a UUID representing the service classes that 71121054Semax * a given service record conforms to. The UUIDs are listed in order from 72121054Semax * the most specific class to the most general class. The ServiceClassIDList 73121054Semax * must contain at least one service class UUID. 74121054Semax */ 75121054Semax 76121054Semaxstatic void 77124317Semaxprint_service_class_id_list(uint8_t const *start, uint8_t const *end) 78121054Semax{ 79124317Semax uint32_t type, len, value; 80121054Semax 81121054Semax if (end - start < 2) { 82121054Semax fprintf(stderr, "Invalid Service Class ID List. " \ 83128076Semax "Too short, len=%zd\n", end - start); 84121054Semax return; 85121054Semax } 86121054Semax 87121054Semax SDP_GET8(type, start); 88121054Semax switch (type) { 89121054Semax case SDP_DATA_SEQ8: 90121054Semax SDP_GET8(len, start); 91121054Semax break; 92121054Semax 93121054Semax case SDP_DATA_SEQ16: 94121054Semax SDP_GET16(len, start); 95121054Semax break; 96121054Semax 97121054Semax case SDP_DATA_SEQ32: 98121054Semax SDP_GET32(len, start); 99121054Semax break; 100121054Semax 101121054Semax default: 102121054Semax fprintf(stderr, "Invalid Service Class ID List. " \ 103121054Semax "Not a sequence, type=%#x\n", type); 104121054Semax return; 105121054Semax /* NOT REACHED */ 106121054Semax } 107121054Semax 108289637Semax if (len > (end - start)) { 109289637Semax fprintf(stderr, "Invalid Service Class ID List. " \ 110289637Semax "Too long len=%d\n", len); 111289637Semax return; 112289637Semax } 113289637Semax 114121054Semax while (start < end) { 115121054Semax SDP_GET8(type, start); 116121054Semax switch (type) { 117121054Semax case SDP_DATA_UUID16: 118121054Semax SDP_GET16(value, start); 119121054Semax fprintf(stdout, "\t%s (%#4.4x)\n", 120121054Semax sdp_uuid2desc(value), value); 121121054Semax break; 122121054Semax 123121054Semax case SDP_DATA_UUID32: 124121054Semax SDP_GET32(value, start); 125121054Semax fprintf(stdout, "\t%#8.8x\n", value); 126121054Semax break; 127121054Semax 128121054Semax case SDP_DATA_UUID128: { 129121054Semax int128_t uuid; 130121054Semax 131146691Semax SDP_GET_UUID128(&uuid, start); 132121054Semax fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", 133146691Semax ntohl(*(uint32_t *)&uuid.b[0]), 134146691Semax ntohs(*(uint16_t *)&uuid.b[4]), 135146691Semax ntohs(*(uint16_t *)&uuid.b[6]), 136146691Semax ntohs(*(uint16_t *)&uuid.b[8]), 137146691Semax ntohs(*(uint16_t *)&uuid.b[10]), 138146691Semax ntohl(*(uint32_t *)&uuid.b[12])); 139121054Semax } break; 140121054Semax 141121054Semax default: 142121054Semax fprintf(stderr, "Invalid Service Class ID List. " \ 143121054Semax "Not a UUID, type=%#x\n", type); 144121054Semax return; 145121054Semax /* NOT REACHED */ 146121054Semax } 147121054Semax } 148121054Semax} /* print_service_class_id_list */ 149121054Semax 150121054Semax/* 151121054Semax * Print Protocol Descriptor List 152121054Semax * 153121054Semax * If the ProtocolDescriptorList describes a single stack, it takes the form 154121054Semax * of a data element sequence in which each element of the sequence is a 155121054Semax * protocol descriptor. Each protocol descriptor is, in turn, a data element 156121054Semax * sequence whose first element is a UUID identifying the protocol and whose 157121054Semax * successive elements are protocol-specific parameters. The protocol 158121054Semax * descriptors are listed in order from the lowest layer protocol to the 159121054Semax * highest layer protocol used to gain access to the service. If it is possible 160121054Semax * for more than one kind of protocol stack to be used to gain access to the 161121054Semax * service, the ProtocolDescriptorList takes the form of a data element 162121054Semax * alternative where each member is a data element sequence as described above. 163121054Semax */ 164121054Semax 165121054Semaxstatic void 166124317Semaxprint_protocol_descriptor(uint8_t const *start, uint8_t const *end) 167121054Semax{ 168121054Semax union { 169121054Semax uint8_t uint8; 170121054Semax uint16_t uint16; 171121054Semax uint32_t uint32; 172121054Semax uint64_t uint64; 173121054Semax int128_t int128; 174121054Semax } value; 175124317Semax uint32_t type, len, param; 176121054Semax 177121054Semax /* Get Protocol UUID */ 178121054Semax SDP_GET8(type, start); 179121054Semax switch (type) { 180121054Semax case SDP_DATA_UUID16: 181121054Semax SDP_GET16(value.uint16, start); 182121054Semax fprintf(stdout, "\t%s (%#4.4x)\n", sdp_uuid2desc(value.uint16), 183121054Semax value.uint16); 184121054Semax break; 185121054Semax 186121054Semax case SDP_DATA_UUID32: 187121054Semax SDP_GET32(value.uint32, start); 188121054Semax fprintf(stdout, "\t%#8.8x\n", value.uint32); 189121054Semax break; 190121054Semax 191121054Semax case SDP_DATA_UUID128: 192146691Semax SDP_GET_UUID128(&value.int128, start); 193121054Semax fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", 194146691Semax ntohl(*(uint32_t *)&value.int128.b[0]), 195146691Semax ntohs(*(uint16_t *)&value.int128.b[4]), 196146691Semax ntohs(*(uint16_t *)&value.int128.b[6]), 197146691Semax ntohs(*(uint16_t *)&value.int128.b[8]), 198146691Semax ntohs(*(uint16_t *)&value.int128.b[10]), 199146691Semax ntohl(*(uint32_t *)&value.int128.b[12])); 200121054Semax break; 201121054Semax 202121054Semax default: 203121054Semax fprintf(stderr, "Invalid Protocol Descriptor. " \ 204121054Semax "Not a UUID, type=%#x\n", type); 205121054Semax return; 206121054Semax /* NOT REACHED */ 207121054Semax } 208121054Semax 209121054Semax /* Protocol specific parameters */ 210121054Semax for (param = 1; start < end; param ++) { 211121054Semax fprintf(stdout, "\t\tProtocol specific parameter #%d: ", param); 212121054Semax 213121054Semax SDP_GET8(type, start); 214121054Semax switch (type) { 215121054Semax case SDP_DATA_NIL: 216121054Semax fprintf(stdout, "nil\n"); 217121054Semax break; 218121054Semax 219121054Semax case SDP_DATA_UINT8: 220121054Semax case SDP_DATA_INT8: 221121054Semax case SDP_DATA_BOOL: 222121054Semax SDP_GET8(value.uint8, start); 223121054Semax fprintf(stdout, "u/int8/bool %u\n", value.uint8); 224121054Semax break; 225121054Semax 226121054Semax case SDP_DATA_UINT16: 227121054Semax case SDP_DATA_INT16: 228121054Semax case SDP_DATA_UUID16: 229121054Semax SDP_GET16(value.uint16, start); 230121054Semax fprintf(stdout, "u/int/uuid16 %u\n", value.uint16); 231121054Semax break; 232121054Semax 233121054Semax case SDP_DATA_UINT32: 234121054Semax case SDP_DATA_INT32: 235121054Semax case SDP_DATA_UUID32: 236121054Semax SDP_GET32(value.uint32, start); 237121054Semax fprintf(stdout, "u/int/uuid32 %u\n", value.uint32); 238121054Semax break; 239121054Semax 240121054Semax case SDP_DATA_UINT64: 241121054Semax case SDP_DATA_INT64: 242121054Semax SDP_GET64(value.uint64, start); 243128076Semax fprintf(stdout, "u/int64 %ju\n", value.uint64); 244121054Semax break; 245121054Semax 246121054Semax case SDP_DATA_UINT128: 247121054Semax case SDP_DATA_INT128: 248121054Semax SDP_GET128(&value.int128, start); 249146691Semax fprintf(stdout, "u/int128 %#8.8x%8.8x%8.8x%8.8x\n", 250124317Semax *(uint32_t *)&value.int128.b[0], 251146691Semax *(uint32_t *)&value.int128.b[4], 252146691Semax *(uint32_t *)&value.int128.b[8], 253124317Semax *(uint32_t *)&value.int128.b[12]); 254121054Semax break; 255121054Semax 256146691Semax case SDP_DATA_UUID128: 257146691Semax SDP_GET_UUID128(&value.int128, start); 258146691Semax fprintf(stdout, "uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", 259146691Semax ntohl(*(uint32_t *)&value.int128.b[0]), 260146691Semax ntohs(*(uint16_t *)&value.int128.b[4]), 261146691Semax ntohs(*(uint16_t *)&value.int128.b[6]), 262146691Semax ntohs(*(uint16_t *)&value.int128.b[8]), 263146691Semax ntohs(*(uint16_t *)&value.int128.b[10]), 264146691Semax ntohl(*(uint32_t *)&value.int128.b[12])); 265146691Semax break; 266146691Semax 267121054Semax case SDP_DATA_STR8: 268121054Semax case SDP_DATA_URL8: 269121054Semax SDP_GET8(len, start); 270289637Semax for (; start < end && len > 0; start ++, len --) 271289637Semax fprintf(stdout, "%c", *start); 272289637Semax fprintf(stdout, "\n"); 273121054Semax break; 274121054Semax 275121054Semax case SDP_DATA_STR16: 276121054Semax case SDP_DATA_URL16: 277121054Semax SDP_GET16(len, start); 278289637Semax for (; start < end && len > 0; start ++, len --) 279289637Semax fprintf(stdout, "%c", *start); 280289637Semax fprintf(stdout, "\n"); 281121054Semax break; 282121054Semax 283121054Semax case SDP_DATA_STR32: 284121054Semax case SDP_DATA_URL32: 285121054Semax SDP_GET32(len, start); 286289637Semax for (; start < end && len > 0; start ++, len --) 287289637Semax fprintf(stdout, "%c", *start); 288289637Semax fprintf(stdout, "\n"); 289121054Semax break; 290121054Semax 291121054Semax case SDP_DATA_SEQ8: 292121054Semax case SDP_DATA_ALT8: 293121054Semax SDP_GET8(len, start); 294289637Semax for (; start < end && len > 0; start ++, len --) 295121054Semax fprintf(stdout, "%#2.2x ", *start); 296121054Semax fprintf(stdout, "\n"); 297121054Semax break; 298121054Semax 299121054Semax case SDP_DATA_SEQ16: 300121054Semax case SDP_DATA_ALT16: 301121054Semax SDP_GET16(len, start); 302289637Semax for (; start < end && len > 0; start ++, len --) 303121054Semax fprintf(stdout, "%#2.2x ", *start); 304121054Semax fprintf(stdout, "\n"); 305121054Semax break; 306121054Semax 307121054Semax case SDP_DATA_SEQ32: 308121054Semax case SDP_DATA_ALT32: 309121054Semax SDP_GET32(len, start); 310289637Semax for (; start < end && len > 0; start ++, len --) 311121054Semax fprintf(stdout, "%#2.2x ", *start); 312121054Semax fprintf(stdout, "\n"); 313121054Semax break; 314121054Semax 315121054Semax default: 316121054Semax fprintf(stderr, "Invalid Protocol Descriptor. " \ 317121054Semax "Unknown data type: %#02x\n", type); 318121054Semax return; 319121054Semax /* NOT REACHED */ 320121054Semax } 321121054Semax } 322121054Semax} /* print_protocol_descriptor */ 323121054Semax 324121054Semaxstatic void 325124317Semaxprint_protocol_descriptor_list(uint8_t const *start, uint8_t const *end) 326121054Semax{ 327124317Semax uint32_t type, len; 328121054Semax 329121054Semax if (end - start < 2) { 330121054Semax fprintf(stderr, "Invalid Protocol Descriptor List. " \ 331128076Semax "Too short, len=%zd\n", end - start); 332121054Semax return; 333121054Semax } 334121054Semax 335121054Semax SDP_GET8(type, start); 336121054Semax switch (type) { 337121054Semax case SDP_DATA_SEQ8: 338121054Semax SDP_GET8(len, start); 339121054Semax break; 340121054Semax 341121054Semax case SDP_DATA_SEQ16: 342121054Semax SDP_GET16(len, start); 343121054Semax break; 344121054Semax 345121054Semax case SDP_DATA_SEQ32: 346121054Semax SDP_GET32(len, start); 347121054Semax break; 348121054Semax 349121054Semax default: 350121054Semax fprintf(stderr, "Invalid Protocol Descriptor List. " \ 351121054Semax "Not a sequence, type=%#x\n", type); 352121054Semax return; 353121054Semax /* NOT REACHED */ 354121054Semax } 355121054Semax 356289637Semax if (len > (end - start)) { 357289637Semax fprintf(stderr, "Invalid Protocol Descriptor List. " \ 358289637Semax "Too long, len=%d\n", len); 359289637Semax return; 360289637Semax } 361289637Semax 362121054Semax while (start < end) { 363121054Semax SDP_GET8(type, start); 364121054Semax switch (type) { 365121054Semax case SDP_DATA_SEQ8: 366121054Semax SDP_GET8(len, start); 367121054Semax break; 368121054Semax 369121054Semax case SDP_DATA_SEQ16: 370121054Semax SDP_GET16(len, start); 371121054Semax break; 372121054Semax 373121054Semax case SDP_DATA_SEQ32: 374121054Semax SDP_GET32(len, start); 375121054Semax break; 376121054Semax 377121054Semax default: 378121054Semax fprintf(stderr, "Invalid Protocol Descriptor List. " \ 379121054Semax "Not a sequence, type=%#x\n", type); 380121054Semax return; 381121054Semax /* NOT REACHED */ 382121054Semax } 383121054Semax 384289637Semax if (len > (end - start)) { 385289637Semax fprintf(stderr, "Invalid Protocol Descriptor List. " \ 386289637Semax "Too long, len=%d\n", len); 387289637Semax return; 388289637Semax } 389289637Semax 390121054Semax print_protocol_descriptor(start, start + len); 391121054Semax start += len; 392121054Semax } 393121054Semax} /* print_protocol_descriptor_list */ 394121054Semax 395121054Semax/* 396121054Semax * Print Bluetooth Profile Descriptor List 397121054Semax * 398121054Semax * The BluetoothProfileDescriptorList attribute consists of a data element 399121054Semax * sequence in which each element is a profile descriptor that contains 400121054Semax * information about a Bluetooth profile to which the service represented by 401121054Semax * this service record conforms. Each profile descriptor is a data element 402121054Semax * sequence whose first element is the UUID assigned to the profile and whose 403121054Semax * second element is a 16-bit profile version number. Each version of a profile 404121054Semax * is assigned a 16-bit unsigned integer profile version number, which consists 405121054Semax * of two 8-bit fields. The higher-order 8 bits contain the major version 406121054Semax * number field and the lower-order 8 bits contain the minor version number 407121054Semax * field. 408121054Semax */ 409121054Semax 410121054Semaxstatic void 411124317Semaxprint_bluetooth_profile_descriptor_list(uint8_t const *start, uint8_t const *end) 412121054Semax{ 413124317Semax uint32_t type, len, value; 414121054Semax 415121054Semax if (end - start < 2) { 416121054Semax fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \ 417128076Semax "Too short, len=%zd\n", end - start); 418121054Semax return; 419121054Semax } 420121054Semax 421121054Semax SDP_GET8(type, start); 422121054Semax switch (type) { 423121054Semax case SDP_DATA_SEQ8: 424121054Semax SDP_GET8(len, start); 425121054Semax break; 426121054Semax 427121054Semax case SDP_DATA_SEQ16: 428121054Semax SDP_GET16(len, start); 429121054Semax break; 430121054Semax 431121054Semax case SDP_DATA_SEQ32: 432121054Semax SDP_GET32(len, start); 433121054Semax break; 434121054Semax 435121054Semax default: 436121054Semax fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \ 437121054Semax "Not a sequence, type=%#x\n", type); 438121054Semax return; 439121054Semax /* NOT REACHED */ 440121054Semax } 441121054Semax 442289637Semax if (len > (end - start)) { 443289637Semax fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \ 444289637Semax "Too long, len=%d\n", len); 445289637Semax return; 446289637Semax } 447289637Semax 448121054Semax while (start < end) { 449121054Semax SDP_GET8(type, start); 450121054Semax switch (type) { 451121054Semax case SDP_DATA_SEQ8: 452121054Semax SDP_GET8(len, start); 453121054Semax break; 454121054Semax 455121054Semax case SDP_DATA_SEQ16: 456121054Semax SDP_GET16(len, start); 457121054Semax break; 458121054Semax 459121054Semax case SDP_DATA_SEQ32: 460121054Semax SDP_GET32(len, start); 461121054Semax break; 462121054Semax 463121054Semax default: 464121054Semax fprintf(stderr, "Invalid Bluetooth Profile " \ 465121054Semax "Descriptor List. " \ 466121054Semax "Not a sequence, type=%#x\n", type); 467121054Semax return; 468121054Semax /* NOT REACHED */ 469121054Semax } 470121054Semax 471289637Semax if (len > (end - start)) { 472289637Semax fprintf(stderr, "Invalid Bluetooth Profile " \ 473289637Semax "Descriptor List. " \ 474289637Semax "Too long, len=%d\n", len); 475289637Semax return; 476289637Semax } 477289637Semax 478121054Semax /* Get UUID */ 479121054Semax SDP_GET8(type, start); 480121054Semax switch (type) { 481121054Semax case SDP_DATA_UUID16: 482121054Semax SDP_GET16(value, start); 483121054Semax fprintf(stdout, "\t%s (%#4.4x) ", 484121054Semax sdp_uuid2desc(value), value); 485121054Semax break; 486121054Semax 487121054Semax case SDP_DATA_UUID32: 488121054Semax SDP_GET32(value, start); 489121054Semax fprintf(stdout, "\t%#8.8x ", value); 490121054Semax break; 491121054Semax 492121054Semax case SDP_DATA_UUID128: { 493121054Semax int128_t uuid; 494121054Semax 495146691Semax SDP_GET_UUID128(&uuid, start); 496121054Semax fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x ", 497146691Semax ntohl(*(uint32_t *)&uuid.b[0]), 498146691Semax ntohs(*(uint16_t *)&uuid.b[4]), 499146691Semax ntohs(*(uint16_t *)&uuid.b[6]), 500146691Semax ntohs(*(uint16_t *)&uuid.b[8]), 501146691Semax ntohs(*(uint16_t *)&uuid.b[10]), 502146691Semax ntohl(*(uint32_t *)&uuid.b[12])); 503121054Semax } break; 504121054Semax 505121054Semax default: 506121054Semax fprintf(stderr, "Invalid Bluetooth Profile " \ 507121054Semax "Descriptor List. " \ 508121054Semax "Not a UUID, type=%#x\n", type); 509121054Semax return; 510121054Semax /* NOT REACHED */ 511121054Semax } 512121054Semax 513121054Semax /* Get version */ 514121054Semax SDP_GET8(type, start); 515121054Semax if (type != SDP_DATA_UINT16) { 516121054Semax fprintf(stderr, "Invalid Bluetooth Profile " \ 517121054Semax "Descriptor List. " \ 518121054Semax "Invalid version type=%#x\n", type); 519121054Semax return; 520121054Semax } 521121054Semax 522121054Semax SDP_GET16(value, start); 523121054Semax fprintf(stdout, "ver. %d.%d\n", 524121054Semax (value >> 8) & 0xff, value & 0xff); 525121054Semax } 526121054Semax} /* print_bluetooth_profile_descriptor_list */ 527121054Semax 528121054Semax/* Perform SDP search command */ 529121054Semaxstatic int 530121054Semaxdo_sdp_search(void *xs, int argc, char **argv) 531121054Semax{ 532121054Semax char *ep = NULL; 533121054Semax int32_t n, type, value; 534124317Semax uint16_t service; 535121054Semax 536121054Semax /* Parse command line arguments */ 537121054Semax switch (argc) { 538121054Semax case 1: 539121054Semax n = strtoul(argv[0], &ep, 16); 540121054Semax if (*ep != 0) { 541121054Semax switch (tolower(argv[0][0])) { 542121054Semax case 'c': /* CIP/CTP */ 543121054Semax switch (tolower(argv[0][1])) { 544121054Semax case 'i': 545121054Semax service = SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS; 546121054Semax break; 547121054Semax 548121054Semax case 't': 549121054Semax service = SDP_SERVICE_CLASS_CORDLESS_TELEPHONY; 550121054Semax break; 551121054Semax 552121054Semax default: 553121054Semax return (USAGE); 554121054Semax /* NOT REACHED */ 555121054Semax } 556121054Semax break; 557121054Semax 558121054Semax case 'd': /* DialUp Networking */ 559121054Semax service = SDP_SERVICE_CLASS_DIALUP_NETWORKING; 560121054Semax break; 561121054Semax 562121054Semax case 'f': /* Fax/OBEX File Transfer */ 563121054Semax switch (tolower(argv[0][1])) { 564121054Semax case 'a': 565121054Semax service = SDP_SERVICE_CLASS_FAX; 566121054Semax break; 567121054Semax 568121054Semax case 't': 569121054Semax service = SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER; 570121054Semax break; 571121054Semax 572121054Semax default: 573121054Semax return (USAGE); 574121054Semax /* NOT REACHED */ 575121054Semax } 576121054Semax break; 577121054Semax 578121054Semax case 'g': /* GN */ 579121054Semax service = SDP_SERVICE_CLASS_GN; 580121054Semax break; 581121054Semax 582121054Semax case 'h': /* Headset/HID */ 583121054Semax switch (tolower(argv[0][1])) { 584121054Semax case 'i': 585121054Semax service = SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE; 586121054Semax break; 587121054Semax 588121054Semax case 's': 589121054Semax service = SDP_SERVICE_CLASS_HEADSET; 590121054Semax break; 591121054Semax 592121054Semax default: 593121054Semax return (USAGE); 594121054Semax /* NOT REACHED */ 595121054Semax } 596121054Semax break; 597121054Semax 598121054Semax case 'l': /* LAN Access Using PPP */ 599121054Semax service = SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP; 600121054Semax break; 601121054Semax 602121054Semax case 'n': /* NAP */ 603121054Semax service = SDP_SERVICE_CLASS_NAP; 604121054Semax break; 605121054Semax 606121054Semax case 'o': /* OBEX Object Push */ 607121054Semax service = SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH; 608121054Semax break; 609121054Semax 610121054Semax case 's': /* Serial Port */ 611121054Semax service = SDP_SERVICE_CLASS_SERIAL_PORT; 612121054Semax break; 613121054Semax 614121054Semax default: 615121054Semax return (USAGE); 616121054Semax /* NOT REACHED */ 617121054Semax } 618121054Semax } else 619124317Semax service = (uint16_t) n; 620121054Semax break; 621121054Semax 622121054Semax default: 623121054Semax return (USAGE); 624121054Semax } 625121054Semax 626121054Semax /* Initialize attribute values array */ 627121054Semax for (n = 0; n < values_len; n ++) { 628121054Semax values[n].flags = SDP_ATTR_INVALID; 629121054Semax values[n].attr = 0; 630121054Semax values[n].vlen = BSIZE; 631121054Semax values[n].value = buffer[n]; 632121054Semax } 633121054Semax 634121054Semax /* Do SDP Service Search Attribute Request */ 635121054Semax n = sdp_search(xs, 1, &service, attrs_len, attrs, values_len, values); 636121054Semax if (n != 0) 637121054Semax return (ERROR); 638121054Semax 639121054Semax /* Print attributes values */ 640121054Semax for (n = 0; n < values_len; n ++) { 641121054Semax if (values[n].flags != SDP_ATTR_OK) 642121054Semax break; 643121054Semax 644121054Semax switch (values[n].attr) { 645121054Semax case SDP_ATTR_SERVICE_RECORD_HANDLE: 646121054Semax fprintf(stdout, "\n"); 647121054Semax if (values[n].vlen == 5) { 648121054Semax SDP_GET8(type, values[n].value); 649121054Semax if (type == SDP_DATA_UINT32) { 650121054Semax SDP_GET32(value, values[n].value); 651121054Semax fprintf(stdout, "Record Handle: " \ 652121054Semax "%#8.8x\n", value); 653121054Semax } else 654121054Semax fprintf(stderr, "Invalid type=%#x " \ 655121054Semax "Record Handle " \ 656121054Semax "attribute!\n", type); 657121054Semax } else 658121054Semax fprintf(stderr, "Invalid size=%d for Record " \ 659121054Semax "Handle attribute\n", 660121054Semax values[n].vlen); 661121054Semax break; 662121054Semax 663121054Semax case SDP_ATTR_SERVICE_CLASS_ID_LIST: 664121054Semax fprintf(stdout, "Service Class ID List:\n"); 665121054Semax print_service_class_id_list(values[n].value, 666121054Semax values[n].value + values[n].vlen); 667121054Semax break; 668121054Semax 669121054Semax case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST: 670121054Semax fprintf(stdout, "Protocol Descriptor List:\n"); 671121054Semax print_protocol_descriptor_list(values[n].value, 672121054Semax values[n].value + values[n].vlen); 673121054Semax break; 674121054Semax 675121054Semax case SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST: 676121054Semax fprintf(stdout, "Bluetooth Profile Descriptor List:\n"); 677121054Semax print_bluetooth_profile_descriptor_list(values[n].value, 678121054Semax values[n].value + values[n].vlen); 679121054Semax break; 680121054Semax 681121054Semax default: 682121054Semax fprintf(stderr, "Unexpected attribute ID=%#4.4x\n", 683121054Semax values[n].attr); 684121054Semax break; 685121054Semax } 686121054Semax } 687121054Semax 688121054Semax return (OK); 689121054Semax} /* do_sdp_search */ 690121054Semax 691121054Semax/* Perform SDP browse command */ 692121054Semaxstatic int 693121054Semaxdo_sdp_browse(void *xs, int argc, char **argv) 694121054Semax{ 695121054Semax#undef _STR 696121054Semax#undef STR 697121054Semax#define _STR(x) #x 698121054Semax#define STR(x) _STR(x) 699121054Semax 700121054Semax static char const * const av[] = { 701121054Semax STR(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP), 702121054Semax NULL 703121054Semax }; 704121054Semax 705121054Semax switch (argc) { 706121054Semax case 0: 707121054Semax argc = 1; 708121054Semax argv = (char **) av; 709121054Semax /* FALL THROUGH */ 710121054Semax case 1: 711121054Semax return (do_sdp_search(xs, argc, argv)); 712121054Semax } 713121054Semax 714121054Semax return (USAGE); 715121054Semax} /* do_sdp_browse */ 716121054Semax 717121054Semax/* List of SDP commands */ 718121054Semaxstruct sdp_command sdp_commands[] = { 719121054Semax{ 720121054Semax"Browse [<Group>]", 721121054Semax"Browse for services. The <Group> parameter is a 16-bit UUID of the group\n" \ 722121054Semax"to browse. If omitted <Group> is set to Public Browse Group.\n\n" \ 723121054Semax"\t<Group> - xxxx; 16-bit UUID of the group to browse\n", 724121054Semaxdo_sdp_browse 725121054Semax}, 726121054Semax{ 727121054Semax"Search <Service>", 728121054Semax"Search for the <Service>. The <Service> parameter is a 16-bit UUID of the\n" \ 729121054Semax"service to search for. For some services it is possible to use service name\n"\ 730121054Semax"instead of service UUID\n\n" \ 731121054Semax"\t<Service> - xxxx; 16-bit UUID of the service to search for\n\n" \ 732121054Semax"\tKnown service names\n" \ 733121054Semax"\t===================\n" \ 734121054Semax"\tCIP - Common ISDN Access\n" \ 735121054Semax"\tCTP - Cordless Telephony\n" \ 736121054Semax"\tDUN - DialUp Networking\n" \ 737121054Semax"\tFAX - Fax\n" \ 738121054Semax"\tFTRN - OBEX File Transfer\n" \ 739121054Semax"\tGN - GN\n" \ 740121054Semax"\tHID - Human Interface Device\n" \ 741121054Semax"\tHSET - Headset\n" \ 742121054Semax"\tLAN - LAN Access Using PPP\n" \ 743121054Semax"\tNAP - Network Access Point\n" \ 744121054Semax"\tOPUSH - OBEX Object Push\n" \ 745121054Semax"\tSP - Serial Port\n", 746121054Semaxdo_sdp_search 747121054Semax}, 748121054Semax{ NULL, NULL, NULL } 749121054Semax}; 750121054Semax 751