xref: /freebsd/usr.sbin/bluetooth/sdpcontrol/search.c (revision 43d33de948192c680cb4dccad6e88e568f9b1ea6)
10986ab12SMaksim Yevmenkin /*
20986ab12SMaksim Yevmenkin  * search.c
30986ab12SMaksim Yevmenkin  *
40986ab12SMaksim Yevmenkin  * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
50986ab12SMaksim Yevmenkin  * All rights reserved.
60986ab12SMaksim Yevmenkin  *
70986ab12SMaksim Yevmenkin  * Redistribution and use in source and binary forms, with or without
80986ab12SMaksim Yevmenkin  * modification, are permitted provided that the following conditions
90986ab12SMaksim Yevmenkin  * are met:
100986ab12SMaksim Yevmenkin  * 1. Redistributions of source code must retain the above copyright
110986ab12SMaksim Yevmenkin  *    notice, this list of conditions and the following disclaimer.
120986ab12SMaksim Yevmenkin  * 2. Redistributions in binary form must reproduce the above copyright
130986ab12SMaksim Yevmenkin  *    notice, this list of conditions and the following disclaimer in the
140986ab12SMaksim Yevmenkin  *    documentation and/or other materials provided with the distribution.
150986ab12SMaksim Yevmenkin  *
160986ab12SMaksim Yevmenkin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
170986ab12SMaksim Yevmenkin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
180986ab12SMaksim Yevmenkin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
190986ab12SMaksim Yevmenkin  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
200986ab12SMaksim Yevmenkin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
210986ab12SMaksim Yevmenkin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
220986ab12SMaksim Yevmenkin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
230986ab12SMaksim Yevmenkin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
240986ab12SMaksim Yevmenkin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
250986ab12SMaksim Yevmenkin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
260986ab12SMaksim Yevmenkin  * SUCH DAMAGE.
270986ab12SMaksim Yevmenkin  *
280986ab12SMaksim Yevmenkin  * $Id: search.c,v 1.2 2003/09/08 17:35:15 max Exp $
290986ab12SMaksim Yevmenkin  * $FreeBSD$
300986ab12SMaksim Yevmenkin  */
310986ab12SMaksim Yevmenkin 
3243d33de9SMaksim Yevmenkin #include <netinet/in.h>
330986ab12SMaksim Yevmenkin #include <bluetooth.h>
340986ab12SMaksim Yevmenkin #include <ctype.h>
350986ab12SMaksim Yevmenkin #include <sdp.h>
360986ab12SMaksim Yevmenkin #include <stdio.h>
370986ab12SMaksim Yevmenkin #include <stdlib.h>
380986ab12SMaksim Yevmenkin #include "sdpcontrol.h"
390986ab12SMaksim Yevmenkin 
400986ab12SMaksim Yevmenkin /* List of the attributes we are looking for */
41a4b187faSMaksim Yevmenkin static uint32_t	attrs[] =
420986ab12SMaksim Yevmenkin {
430986ab12SMaksim Yevmenkin 	SDP_ATTR_RANGE(	SDP_ATTR_SERVICE_RECORD_HANDLE,
440986ab12SMaksim Yevmenkin 			SDP_ATTR_SERVICE_RECORD_HANDLE),
450986ab12SMaksim Yevmenkin 	SDP_ATTR_RANGE(	SDP_ATTR_SERVICE_CLASS_ID_LIST,
460986ab12SMaksim Yevmenkin 			SDP_ATTR_SERVICE_CLASS_ID_LIST),
470986ab12SMaksim Yevmenkin 	SDP_ATTR_RANGE(	SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST,
480986ab12SMaksim Yevmenkin 			SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST),
490986ab12SMaksim Yevmenkin 	SDP_ATTR_RANGE(	SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST,
500986ab12SMaksim Yevmenkin 			SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST)
510986ab12SMaksim Yevmenkin };
520986ab12SMaksim Yevmenkin #define attrs_len	(sizeof(attrs)/sizeof(attrs[0]))
530986ab12SMaksim Yevmenkin 
540986ab12SMaksim Yevmenkin /* Buffer for the attributes */
550986ab12SMaksim Yevmenkin #define NRECS	25	/* request this much records from the SDP server */
560986ab12SMaksim Yevmenkin #define	BSIZE	256	/* one attribute buffer size */
57a4b187faSMaksim Yevmenkin static uint8_t		buffer[NRECS * attrs_len][BSIZE];
580986ab12SMaksim Yevmenkin 
590986ab12SMaksim Yevmenkin /* SDP attributes */
600986ab12SMaksim Yevmenkin static sdp_attr_t	values[NRECS * attrs_len];
610986ab12SMaksim Yevmenkin #define values_len	(sizeof(values)/sizeof(values[0]))
620986ab12SMaksim Yevmenkin 
630986ab12SMaksim Yevmenkin /*
640986ab12SMaksim Yevmenkin  * Print Service Class ID List
650986ab12SMaksim Yevmenkin  *
660986ab12SMaksim Yevmenkin  * The ServiceClassIDList attribute consists of a data element sequence in
670986ab12SMaksim Yevmenkin  * which each data element is a UUID representing the service classes that
680986ab12SMaksim Yevmenkin  * a given service record conforms to. The UUIDs are listed in order from
690986ab12SMaksim Yevmenkin  * the most specific class to the most general class. The ServiceClassIDList
700986ab12SMaksim Yevmenkin  * must contain at least one service class UUID.
710986ab12SMaksim Yevmenkin  */
720986ab12SMaksim Yevmenkin 
730986ab12SMaksim Yevmenkin static void
74a4b187faSMaksim Yevmenkin print_service_class_id_list(uint8_t const *start, uint8_t const *end)
750986ab12SMaksim Yevmenkin {
76a4b187faSMaksim Yevmenkin 	uint32_t	type, len, value;
770986ab12SMaksim Yevmenkin 
780986ab12SMaksim Yevmenkin 	if (end - start < 2) {
790986ab12SMaksim Yevmenkin 		fprintf(stderr, "Invalid Service Class ID List. " \
804ae439a3SMaksim Yevmenkin 				"Too short, len=%zd\n", end - start);
810986ab12SMaksim Yevmenkin 		return;
820986ab12SMaksim Yevmenkin 	}
830986ab12SMaksim Yevmenkin 
840986ab12SMaksim Yevmenkin 	SDP_GET8(type, start);
850986ab12SMaksim Yevmenkin 	switch (type) {
860986ab12SMaksim Yevmenkin 	case SDP_DATA_SEQ8:
870986ab12SMaksim Yevmenkin 		SDP_GET8(len, start);
880986ab12SMaksim Yevmenkin 		break;
890986ab12SMaksim Yevmenkin 
900986ab12SMaksim Yevmenkin 	case SDP_DATA_SEQ16:
910986ab12SMaksim Yevmenkin 		SDP_GET16(len, start);
920986ab12SMaksim Yevmenkin 		break;
930986ab12SMaksim Yevmenkin 
940986ab12SMaksim Yevmenkin 	case SDP_DATA_SEQ32:
950986ab12SMaksim Yevmenkin 		SDP_GET32(len, start);
960986ab12SMaksim Yevmenkin 		break;
970986ab12SMaksim Yevmenkin 
980986ab12SMaksim Yevmenkin 	default:
990986ab12SMaksim Yevmenkin 		fprintf(stderr, "Invalid Service Class ID List. " \
1000986ab12SMaksim Yevmenkin 				"Not a sequence, type=%#x\n", type);
1010986ab12SMaksim Yevmenkin 		return;
1020986ab12SMaksim Yevmenkin 		/* NOT REACHED */
1030986ab12SMaksim Yevmenkin 	}
1040986ab12SMaksim Yevmenkin 
1050986ab12SMaksim Yevmenkin 	while (start < end) {
1060986ab12SMaksim Yevmenkin 		SDP_GET8(type, start);
1070986ab12SMaksim Yevmenkin 		switch (type) {
1080986ab12SMaksim Yevmenkin 		case SDP_DATA_UUID16:
1090986ab12SMaksim Yevmenkin 			SDP_GET16(value, start);
1100986ab12SMaksim Yevmenkin 			fprintf(stdout, "\t%s (%#4.4x)\n",
1110986ab12SMaksim Yevmenkin 					sdp_uuid2desc(value), value);
1120986ab12SMaksim Yevmenkin 			break;
1130986ab12SMaksim Yevmenkin 
1140986ab12SMaksim Yevmenkin 		case SDP_DATA_UUID32:
1150986ab12SMaksim Yevmenkin 			SDP_GET32(value, start);
1160986ab12SMaksim Yevmenkin 			fprintf(stdout, "\t%#8.8x\n", value);
1170986ab12SMaksim Yevmenkin 			break;
1180986ab12SMaksim Yevmenkin 
1190986ab12SMaksim Yevmenkin 		case SDP_DATA_UUID128: {
1200986ab12SMaksim Yevmenkin 			int128_t	uuid;
1210986ab12SMaksim Yevmenkin 
12243d33de9SMaksim Yevmenkin 			SDP_GET_UUID128(&uuid, start);
1230986ab12SMaksim Yevmenkin 			fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n",
12443d33de9SMaksim Yevmenkin 					ntohl(*(uint32_t *)&uuid.b[0]),
12543d33de9SMaksim Yevmenkin 					ntohs(*(uint16_t *)&uuid.b[4]),
12643d33de9SMaksim Yevmenkin 					ntohs(*(uint16_t *)&uuid.b[6]),
12743d33de9SMaksim Yevmenkin 					ntohs(*(uint16_t *)&uuid.b[8]),
12843d33de9SMaksim Yevmenkin 					ntohs(*(uint16_t *)&uuid.b[10]),
12943d33de9SMaksim Yevmenkin 					ntohl(*(uint32_t *)&uuid.b[12]));
1300986ab12SMaksim Yevmenkin 			} break;
1310986ab12SMaksim Yevmenkin 
1320986ab12SMaksim Yevmenkin 		default:
1330986ab12SMaksim Yevmenkin 			fprintf(stderr, "Invalid Service Class ID List. " \
1340986ab12SMaksim Yevmenkin 					"Not a UUID, type=%#x\n", type);
1350986ab12SMaksim Yevmenkin 			return;
1360986ab12SMaksim Yevmenkin 			/* NOT REACHED */
1370986ab12SMaksim Yevmenkin 		}
1380986ab12SMaksim Yevmenkin 	}
1390986ab12SMaksim Yevmenkin } /* print_service_class_id_list */
1400986ab12SMaksim Yevmenkin 
1410986ab12SMaksim Yevmenkin /*
1420986ab12SMaksim Yevmenkin  * Print Protocol Descriptor List
1430986ab12SMaksim Yevmenkin  *
1440986ab12SMaksim Yevmenkin  * If the ProtocolDescriptorList describes a single stack, it takes the form
1450986ab12SMaksim Yevmenkin  * of a data element sequence in which each element of the sequence is a
1460986ab12SMaksim Yevmenkin  * protocol descriptor. Each protocol descriptor is, in turn, a data element
1470986ab12SMaksim Yevmenkin  * sequence whose first element is a UUID identifying the protocol and whose
1480986ab12SMaksim Yevmenkin  * successive elements are protocol-specific parameters. The protocol
1490986ab12SMaksim Yevmenkin  * descriptors are listed in order from the lowest layer protocol to the
1500986ab12SMaksim Yevmenkin  * highest layer protocol used to gain access to the service. If it is possible
1510986ab12SMaksim Yevmenkin  * for more than one kind of protocol stack to be used to gain access to the
1520986ab12SMaksim Yevmenkin  * service, the ProtocolDescriptorList takes the form of a data element
1530986ab12SMaksim Yevmenkin  * alternative where each member is a data element sequence as described above.
1540986ab12SMaksim Yevmenkin  */
1550986ab12SMaksim Yevmenkin 
1560986ab12SMaksim Yevmenkin static void
157a4b187faSMaksim Yevmenkin print_protocol_descriptor(uint8_t const *start, uint8_t const *end)
1580986ab12SMaksim Yevmenkin {
1590986ab12SMaksim Yevmenkin 	union {
1600986ab12SMaksim Yevmenkin 		uint8_t		uint8;
1610986ab12SMaksim Yevmenkin 		uint16_t	uint16;
1620986ab12SMaksim Yevmenkin 		uint32_t	uint32;
1630986ab12SMaksim Yevmenkin 		uint64_t	uint64;
1640986ab12SMaksim Yevmenkin 		int128_t	int128;
1650986ab12SMaksim Yevmenkin 	}			value;
166a4b187faSMaksim Yevmenkin 	uint32_t		type, len, param;
1670986ab12SMaksim Yevmenkin 
1680986ab12SMaksim Yevmenkin 	/* Get Protocol UUID */
1690986ab12SMaksim Yevmenkin 	SDP_GET8(type, start);
1700986ab12SMaksim Yevmenkin 	switch (type) {
1710986ab12SMaksim Yevmenkin 	case SDP_DATA_UUID16:
1720986ab12SMaksim Yevmenkin 		SDP_GET16(value.uint16, start);
1730986ab12SMaksim Yevmenkin 		fprintf(stdout, "\t%s (%#4.4x)\n", sdp_uuid2desc(value.uint16),
1740986ab12SMaksim Yevmenkin 				value.uint16);
1750986ab12SMaksim Yevmenkin 		break;
1760986ab12SMaksim Yevmenkin 
1770986ab12SMaksim Yevmenkin 	case SDP_DATA_UUID32:
1780986ab12SMaksim Yevmenkin 		SDP_GET32(value.uint32, start);
1790986ab12SMaksim Yevmenkin 		fprintf(stdout, "\t%#8.8x\n", value.uint32);
1800986ab12SMaksim Yevmenkin 		break;
1810986ab12SMaksim Yevmenkin 
1820986ab12SMaksim Yevmenkin 	case SDP_DATA_UUID128:
18343d33de9SMaksim Yevmenkin 		SDP_GET_UUID128(&value.int128, start);
1840986ab12SMaksim Yevmenkin 		fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n",
18543d33de9SMaksim Yevmenkin 				ntohl(*(uint32_t *)&value.int128.b[0]),
18643d33de9SMaksim Yevmenkin 				ntohs(*(uint16_t *)&value.int128.b[4]),
18743d33de9SMaksim Yevmenkin 				ntohs(*(uint16_t *)&value.int128.b[6]),
18843d33de9SMaksim Yevmenkin 				ntohs(*(uint16_t *)&value.int128.b[8]),
18943d33de9SMaksim Yevmenkin 				ntohs(*(uint16_t *)&value.int128.b[10]),
19043d33de9SMaksim Yevmenkin 				ntohl(*(uint32_t *)&value.int128.b[12]));
1910986ab12SMaksim Yevmenkin 		break;
1920986ab12SMaksim Yevmenkin 
1930986ab12SMaksim Yevmenkin 	default:
1940986ab12SMaksim Yevmenkin 		fprintf(stderr, "Invalid Protocol Descriptor. " \
1950986ab12SMaksim Yevmenkin 				"Not a UUID, type=%#x\n", type);
1960986ab12SMaksim Yevmenkin 		return;
1970986ab12SMaksim Yevmenkin 		/* NOT REACHED */
1980986ab12SMaksim Yevmenkin 	}
1990986ab12SMaksim Yevmenkin 
2000986ab12SMaksim Yevmenkin 	/* Protocol specific parameters */
2010986ab12SMaksim Yevmenkin 	for (param = 1; start < end; param ++) {
2020986ab12SMaksim Yevmenkin 		fprintf(stdout, "\t\tProtocol specific parameter #%d: ", param);
2030986ab12SMaksim Yevmenkin 
2040986ab12SMaksim Yevmenkin 		SDP_GET8(type, start);
2050986ab12SMaksim Yevmenkin 		switch (type) {
2060986ab12SMaksim Yevmenkin 		case SDP_DATA_NIL:
2070986ab12SMaksim Yevmenkin 			fprintf(stdout, "nil\n");
2080986ab12SMaksim Yevmenkin 			break;
2090986ab12SMaksim Yevmenkin 
2100986ab12SMaksim Yevmenkin 		case SDP_DATA_UINT8:
2110986ab12SMaksim Yevmenkin 		case SDP_DATA_INT8:
2120986ab12SMaksim Yevmenkin 		case SDP_DATA_BOOL:
2130986ab12SMaksim Yevmenkin 			SDP_GET8(value.uint8, start);
2140986ab12SMaksim Yevmenkin 			fprintf(stdout, "u/int8/bool %u\n", value.uint8);
2150986ab12SMaksim Yevmenkin 			break;
2160986ab12SMaksim Yevmenkin 
2170986ab12SMaksim Yevmenkin 		case SDP_DATA_UINT16:
2180986ab12SMaksim Yevmenkin 		case SDP_DATA_INT16:
2190986ab12SMaksim Yevmenkin 		case SDP_DATA_UUID16:
2200986ab12SMaksim Yevmenkin 			SDP_GET16(value.uint16, start);
2210986ab12SMaksim Yevmenkin 			fprintf(stdout, "u/int/uuid16 %u\n", value.uint16);
2220986ab12SMaksim Yevmenkin 			break;
2230986ab12SMaksim Yevmenkin 
2240986ab12SMaksim Yevmenkin 		case SDP_DATA_UINT32:
2250986ab12SMaksim Yevmenkin 		case SDP_DATA_INT32:
2260986ab12SMaksim Yevmenkin 		case SDP_DATA_UUID32:
2270986ab12SMaksim Yevmenkin 			SDP_GET32(value.uint32, start);
2280986ab12SMaksim Yevmenkin 			fprintf(stdout, "u/int/uuid32 %u\n", value.uint32);
2290986ab12SMaksim Yevmenkin 			break;
2300986ab12SMaksim Yevmenkin 
2310986ab12SMaksim Yevmenkin 		case SDP_DATA_UINT64:
2320986ab12SMaksim Yevmenkin 		case SDP_DATA_INT64:
2330986ab12SMaksim Yevmenkin 			SDP_GET64(value.uint64, start);
2344ae439a3SMaksim Yevmenkin 			fprintf(stdout, "u/int64 %ju\n", value.uint64);
2350986ab12SMaksim Yevmenkin 			break;
2360986ab12SMaksim Yevmenkin 
2370986ab12SMaksim Yevmenkin 		case SDP_DATA_UINT128:
2380986ab12SMaksim Yevmenkin 		case SDP_DATA_INT128:
2390986ab12SMaksim Yevmenkin 			SDP_GET128(&value.int128, start);
24043d33de9SMaksim Yevmenkin 			fprintf(stdout, "u/int128 %#8.8x%8.8x%8.8x%8.8x\n",
241a4b187faSMaksim Yevmenkin 				*(uint32_t *)&value.int128.b[0],
24243d33de9SMaksim Yevmenkin 				*(uint32_t *)&value.int128.b[4],
24343d33de9SMaksim Yevmenkin 				*(uint32_t *)&value.int128.b[8],
244a4b187faSMaksim Yevmenkin 				*(uint32_t *)&value.int128.b[12]);
2450986ab12SMaksim Yevmenkin 			break;
2460986ab12SMaksim Yevmenkin 
24743d33de9SMaksim Yevmenkin 		case SDP_DATA_UUID128:
24843d33de9SMaksim Yevmenkin 			SDP_GET_UUID128(&value.int128, start);
24943d33de9SMaksim Yevmenkin 			fprintf(stdout, "uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n",
25043d33de9SMaksim Yevmenkin 				ntohl(*(uint32_t *)&value.int128.b[0]),
25143d33de9SMaksim Yevmenkin 				ntohs(*(uint16_t *)&value.int128.b[4]),
25243d33de9SMaksim Yevmenkin 				ntohs(*(uint16_t *)&value.int128.b[6]),
25343d33de9SMaksim Yevmenkin 				ntohs(*(uint16_t *)&value.int128.b[8]),
25443d33de9SMaksim Yevmenkin 				ntohs(*(uint16_t *)&value.int128.b[10]),
25543d33de9SMaksim Yevmenkin 				ntohl(*(uint32_t *)&value.int128.b[12]));
25643d33de9SMaksim Yevmenkin 			break;
25743d33de9SMaksim Yevmenkin 
2580986ab12SMaksim Yevmenkin 		case SDP_DATA_STR8:
2590986ab12SMaksim Yevmenkin 		case SDP_DATA_URL8:
2600986ab12SMaksim Yevmenkin 			SDP_GET8(len, start);
2610986ab12SMaksim Yevmenkin 			fprintf(stdout, "%*.*s\n", len, len, (char *) start);
2620986ab12SMaksim Yevmenkin 			start += len;
2630986ab12SMaksim Yevmenkin 			break;
2640986ab12SMaksim Yevmenkin 
2650986ab12SMaksim Yevmenkin 		case SDP_DATA_STR16:
2660986ab12SMaksim Yevmenkin 		case SDP_DATA_URL16:
2670986ab12SMaksim Yevmenkin 			SDP_GET16(len, start);
2680986ab12SMaksim Yevmenkin 			fprintf(stdout, "%*.*s\n", len, len, (char *) start);
2690986ab12SMaksim Yevmenkin 			start += len;
2700986ab12SMaksim Yevmenkin 			break;
2710986ab12SMaksim Yevmenkin 
2720986ab12SMaksim Yevmenkin 		case SDP_DATA_STR32:
2730986ab12SMaksim Yevmenkin 		case SDP_DATA_URL32:
2740986ab12SMaksim Yevmenkin 			SDP_GET32(len, start);
2750986ab12SMaksim Yevmenkin 			fprintf(stdout, "%*.*s\n", len, len, (char *) start);
2760986ab12SMaksim Yevmenkin 			start += len;
2770986ab12SMaksim Yevmenkin 			break;
2780986ab12SMaksim Yevmenkin 
2790986ab12SMaksim Yevmenkin 		case SDP_DATA_SEQ8:
2800986ab12SMaksim Yevmenkin 		case SDP_DATA_ALT8:
2810986ab12SMaksim Yevmenkin 			SDP_GET8(len, start);
2820986ab12SMaksim Yevmenkin 			for (; len > 0; start ++, len --)
2830986ab12SMaksim Yevmenkin 				fprintf(stdout, "%#2.2x ", *start);
2840986ab12SMaksim Yevmenkin 			fprintf(stdout, "\n");
2850986ab12SMaksim Yevmenkin 			break;
2860986ab12SMaksim Yevmenkin 
2870986ab12SMaksim Yevmenkin 		case SDP_DATA_SEQ16:
2880986ab12SMaksim Yevmenkin 		case SDP_DATA_ALT16:
2890986ab12SMaksim Yevmenkin 			SDP_GET16(len, start);
2900986ab12SMaksim Yevmenkin 			for (; len > 0; start ++, len --)
2910986ab12SMaksim Yevmenkin 				fprintf(stdout, "%#2.2x ", *start);
2920986ab12SMaksim Yevmenkin 			fprintf(stdout, "\n");
2930986ab12SMaksim Yevmenkin 			break;
2940986ab12SMaksim Yevmenkin 
2950986ab12SMaksim Yevmenkin 		case SDP_DATA_SEQ32:
2960986ab12SMaksim Yevmenkin 		case SDP_DATA_ALT32:
2970986ab12SMaksim Yevmenkin 			SDP_GET32(len, start);
2980986ab12SMaksim Yevmenkin 			for (; len > 0; start ++, len --)
2990986ab12SMaksim Yevmenkin 				fprintf(stdout, "%#2.2x ", *start);
3000986ab12SMaksim Yevmenkin 			fprintf(stdout, "\n");
3010986ab12SMaksim Yevmenkin 			break;
3020986ab12SMaksim Yevmenkin 
3030986ab12SMaksim Yevmenkin 		default:
3040986ab12SMaksim Yevmenkin 			fprintf(stderr, "Invalid Protocol Descriptor. " \
3050986ab12SMaksim Yevmenkin 					"Unknown data type: %#02x\n", type);
3060986ab12SMaksim Yevmenkin 			return;
3070986ab12SMaksim Yevmenkin 			/* NOT REACHED */
3080986ab12SMaksim Yevmenkin 		}
3090986ab12SMaksim Yevmenkin 	}
3100986ab12SMaksim Yevmenkin } /* print_protocol_descriptor */
3110986ab12SMaksim Yevmenkin 
3120986ab12SMaksim Yevmenkin static void
313a4b187faSMaksim Yevmenkin print_protocol_descriptor_list(uint8_t const *start, uint8_t const *end)
3140986ab12SMaksim Yevmenkin {
315a4b187faSMaksim Yevmenkin 	uint32_t	type, len;
3160986ab12SMaksim Yevmenkin 
3170986ab12SMaksim Yevmenkin 	if (end - start < 2) {
3180986ab12SMaksim Yevmenkin 		fprintf(stderr, "Invalid Protocol Descriptor List. " \
3194ae439a3SMaksim Yevmenkin 				"Too short, len=%zd\n", end - start);
3200986ab12SMaksim Yevmenkin 		return;
3210986ab12SMaksim Yevmenkin 	}
3220986ab12SMaksim Yevmenkin 
3230986ab12SMaksim Yevmenkin 	SDP_GET8(type, start);
3240986ab12SMaksim Yevmenkin 	switch (type) {
3250986ab12SMaksim Yevmenkin 	case SDP_DATA_SEQ8:
3260986ab12SMaksim Yevmenkin 		SDP_GET8(len, start);
3270986ab12SMaksim Yevmenkin 		break;
3280986ab12SMaksim Yevmenkin 
3290986ab12SMaksim Yevmenkin 	case SDP_DATA_SEQ16:
3300986ab12SMaksim Yevmenkin 		SDP_GET16(len, start);
3310986ab12SMaksim Yevmenkin 		break;
3320986ab12SMaksim Yevmenkin 
3330986ab12SMaksim Yevmenkin 	case SDP_DATA_SEQ32:
3340986ab12SMaksim Yevmenkin 		SDP_GET32(len, start);
3350986ab12SMaksim Yevmenkin 		break;
3360986ab12SMaksim Yevmenkin 
3370986ab12SMaksim Yevmenkin 	default:
3380986ab12SMaksim Yevmenkin 		fprintf(stderr, "Invalid Protocol Descriptor List. " \
3390986ab12SMaksim Yevmenkin 				"Not a sequence, type=%#x\n", type);
3400986ab12SMaksim Yevmenkin 		return;
3410986ab12SMaksim Yevmenkin 		/* NOT REACHED */
3420986ab12SMaksim Yevmenkin 	}
3430986ab12SMaksim Yevmenkin 
3440986ab12SMaksim Yevmenkin 	while (start < end) {
3450986ab12SMaksim Yevmenkin 		SDP_GET8(type, start);
3460986ab12SMaksim Yevmenkin 		switch (type) {
3470986ab12SMaksim Yevmenkin 		case SDP_DATA_SEQ8:
3480986ab12SMaksim Yevmenkin 			SDP_GET8(len, start);
3490986ab12SMaksim Yevmenkin 			break;
3500986ab12SMaksim Yevmenkin 
3510986ab12SMaksim Yevmenkin 		case SDP_DATA_SEQ16:
3520986ab12SMaksim Yevmenkin 			SDP_GET16(len, start);
3530986ab12SMaksim Yevmenkin 			break;
3540986ab12SMaksim Yevmenkin 
3550986ab12SMaksim Yevmenkin 		case SDP_DATA_SEQ32:
3560986ab12SMaksim Yevmenkin 			SDP_GET32(len, start);
3570986ab12SMaksim Yevmenkin 			break;
3580986ab12SMaksim Yevmenkin 
3590986ab12SMaksim Yevmenkin 		default:
3600986ab12SMaksim Yevmenkin 			fprintf(stderr, "Invalid Protocol Descriptor List. " \
3610986ab12SMaksim Yevmenkin 					"Not a sequence, type=%#x\n", type);
3620986ab12SMaksim Yevmenkin 			return;
3630986ab12SMaksim Yevmenkin 			/* NOT REACHED */
3640986ab12SMaksim Yevmenkin 		}
3650986ab12SMaksim Yevmenkin 
3660986ab12SMaksim Yevmenkin 		print_protocol_descriptor(start, start + len);
3670986ab12SMaksim Yevmenkin 		start += len;
3680986ab12SMaksim Yevmenkin 	}
3690986ab12SMaksim Yevmenkin } /* print_protocol_descriptor_list */
3700986ab12SMaksim Yevmenkin 
3710986ab12SMaksim Yevmenkin /*
3720986ab12SMaksim Yevmenkin  * Print Bluetooth Profile Descriptor List
3730986ab12SMaksim Yevmenkin  *
3740986ab12SMaksim Yevmenkin  * The BluetoothProfileDescriptorList attribute consists of a data element
3750986ab12SMaksim Yevmenkin  * sequence in which each element is a profile descriptor that contains
3760986ab12SMaksim Yevmenkin  * information about a Bluetooth profile to which the service represented by
3770986ab12SMaksim Yevmenkin  * this service record conforms. Each profile descriptor is a data element
3780986ab12SMaksim Yevmenkin  * sequence whose first element is the UUID assigned to the profile and whose
3790986ab12SMaksim Yevmenkin  * second element is a 16-bit profile version number. Each version of a profile
3800986ab12SMaksim Yevmenkin  * is assigned a 16-bit unsigned integer profile version number, which consists
3810986ab12SMaksim Yevmenkin  * of two 8-bit fields. The higher-order 8 bits contain the major version
3820986ab12SMaksim Yevmenkin  * number field and the lower-order 8 bits contain the minor version number
3830986ab12SMaksim Yevmenkin  * field.
3840986ab12SMaksim Yevmenkin  */
3850986ab12SMaksim Yevmenkin 
3860986ab12SMaksim Yevmenkin static void
387a4b187faSMaksim Yevmenkin print_bluetooth_profile_descriptor_list(uint8_t const *start, uint8_t const *end)
3880986ab12SMaksim Yevmenkin {
389a4b187faSMaksim Yevmenkin 	uint32_t	type, len, value;
3900986ab12SMaksim Yevmenkin 
3910986ab12SMaksim Yevmenkin 	if (end - start < 2) {
3920986ab12SMaksim Yevmenkin 		fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \
3934ae439a3SMaksim Yevmenkin 				"Too short, len=%zd\n", end - start);
3940986ab12SMaksim Yevmenkin 		return;
3950986ab12SMaksim Yevmenkin 	}
3960986ab12SMaksim Yevmenkin 
3970986ab12SMaksim Yevmenkin 	SDP_GET8(type, start);
3980986ab12SMaksim Yevmenkin 	switch (type) {
3990986ab12SMaksim Yevmenkin 	case SDP_DATA_SEQ8:
4000986ab12SMaksim Yevmenkin 		SDP_GET8(len, start);
4010986ab12SMaksim Yevmenkin 		break;
4020986ab12SMaksim Yevmenkin 
4030986ab12SMaksim Yevmenkin 	case SDP_DATA_SEQ16:
4040986ab12SMaksim Yevmenkin 		SDP_GET16(len, start);
4050986ab12SMaksim Yevmenkin 		break;
4060986ab12SMaksim Yevmenkin 
4070986ab12SMaksim Yevmenkin 	case SDP_DATA_SEQ32:
4080986ab12SMaksim Yevmenkin 		SDP_GET32(len, start);
4090986ab12SMaksim Yevmenkin 		break;
4100986ab12SMaksim Yevmenkin 
4110986ab12SMaksim Yevmenkin 	default:
4120986ab12SMaksim Yevmenkin 		fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \
4130986ab12SMaksim Yevmenkin 				"Not a sequence, type=%#x\n", type);
4140986ab12SMaksim Yevmenkin 		return;
4150986ab12SMaksim Yevmenkin 		/* NOT REACHED */
4160986ab12SMaksim Yevmenkin 	}
4170986ab12SMaksim Yevmenkin 
4180986ab12SMaksim Yevmenkin 	while (start < end) {
4190986ab12SMaksim Yevmenkin 		SDP_GET8(type, start);
4200986ab12SMaksim Yevmenkin 		switch (type) {
4210986ab12SMaksim Yevmenkin 		case SDP_DATA_SEQ8:
4220986ab12SMaksim Yevmenkin 			SDP_GET8(len, start);
4230986ab12SMaksim Yevmenkin 			break;
4240986ab12SMaksim Yevmenkin 
4250986ab12SMaksim Yevmenkin 		case SDP_DATA_SEQ16:
4260986ab12SMaksim Yevmenkin 			SDP_GET16(len, start);
4270986ab12SMaksim Yevmenkin 			break;
4280986ab12SMaksim Yevmenkin 
4290986ab12SMaksim Yevmenkin 		case SDP_DATA_SEQ32:
4300986ab12SMaksim Yevmenkin 			SDP_GET32(len, start);
4310986ab12SMaksim Yevmenkin 			break;
4320986ab12SMaksim Yevmenkin 
4330986ab12SMaksim Yevmenkin 		default:
4340986ab12SMaksim Yevmenkin 			fprintf(stderr, "Invalid Bluetooth Profile " \
4350986ab12SMaksim Yevmenkin 					"Descriptor List. " \
4360986ab12SMaksim Yevmenkin 					"Not a sequence, type=%#x\n", type);
4370986ab12SMaksim Yevmenkin 			return;
4380986ab12SMaksim Yevmenkin 			/* NOT REACHED */
4390986ab12SMaksim Yevmenkin 		}
4400986ab12SMaksim Yevmenkin 
4410986ab12SMaksim Yevmenkin 		/* Get UUID */
4420986ab12SMaksim Yevmenkin 		SDP_GET8(type, start);
4430986ab12SMaksim Yevmenkin 		switch (type) {
4440986ab12SMaksim Yevmenkin 		case SDP_DATA_UUID16:
4450986ab12SMaksim Yevmenkin 			SDP_GET16(value, start);
4460986ab12SMaksim Yevmenkin 			fprintf(stdout, "\t%s (%#4.4x) ",
4470986ab12SMaksim Yevmenkin 					sdp_uuid2desc(value), value);
4480986ab12SMaksim Yevmenkin 			break;
4490986ab12SMaksim Yevmenkin 
4500986ab12SMaksim Yevmenkin 		case SDP_DATA_UUID32:
4510986ab12SMaksim Yevmenkin 			SDP_GET32(value, start);
4520986ab12SMaksim Yevmenkin 			fprintf(stdout, "\t%#8.8x ", value);
4530986ab12SMaksim Yevmenkin 			break;
4540986ab12SMaksim Yevmenkin 
4550986ab12SMaksim Yevmenkin 		case SDP_DATA_UUID128: {
4560986ab12SMaksim Yevmenkin 			int128_t	uuid;
4570986ab12SMaksim Yevmenkin 
45843d33de9SMaksim Yevmenkin 			SDP_GET_UUID128(&uuid, start);
4590986ab12SMaksim Yevmenkin 			fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x ",
46043d33de9SMaksim Yevmenkin 					ntohl(*(uint32_t *)&uuid.b[0]),
46143d33de9SMaksim Yevmenkin 					ntohs(*(uint16_t *)&uuid.b[4]),
46243d33de9SMaksim Yevmenkin 					ntohs(*(uint16_t *)&uuid.b[6]),
46343d33de9SMaksim Yevmenkin 					ntohs(*(uint16_t *)&uuid.b[8]),
46443d33de9SMaksim Yevmenkin 					ntohs(*(uint16_t *)&uuid.b[10]),
46543d33de9SMaksim Yevmenkin 					ntohl(*(uint32_t *)&uuid.b[12]));
4660986ab12SMaksim Yevmenkin 			} break;
4670986ab12SMaksim Yevmenkin 
4680986ab12SMaksim Yevmenkin 		default:
4690986ab12SMaksim Yevmenkin 			fprintf(stderr, "Invalid Bluetooth Profile " \
4700986ab12SMaksim Yevmenkin 					"Descriptor List. " \
4710986ab12SMaksim Yevmenkin 					"Not a UUID, type=%#x\n", type);
4720986ab12SMaksim Yevmenkin 			return;
4730986ab12SMaksim Yevmenkin 			/* NOT REACHED */
4740986ab12SMaksim Yevmenkin 		}
4750986ab12SMaksim Yevmenkin 
4760986ab12SMaksim Yevmenkin 		/* Get version */
4770986ab12SMaksim Yevmenkin 		SDP_GET8(type, start);
4780986ab12SMaksim Yevmenkin 		if (type != SDP_DATA_UINT16) {
4790986ab12SMaksim Yevmenkin 			fprintf(stderr, "Invalid Bluetooth Profile " \
4800986ab12SMaksim Yevmenkin 					"Descriptor List. " \
4810986ab12SMaksim Yevmenkin 					"Invalid version type=%#x\n", type);
4820986ab12SMaksim Yevmenkin 			return;
4830986ab12SMaksim Yevmenkin 		}
4840986ab12SMaksim Yevmenkin 
4850986ab12SMaksim Yevmenkin 		SDP_GET16(value, start);
4860986ab12SMaksim Yevmenkin 		fprintf(stdout, "ver. %d.%d\n",
4870986ab12SMaksim Yevmenkin 				(value >> 8) & 0xff, value & 0xff);
4880986ab12SMaksim Yevmenkin 	}
4890986ab12SMaksim Yevmenkin } /* print_bluetooth_profile_descriptor_list */
4900986ab12SMaksim Yevmenkin 
4910986ab12SMaksim Yevmenkin /* Perform SDP search command */
4920986ab12SMaksim Yevmenkin static int
4930986ab12SMaksim Yevmenkin do_sdp_search(void *xs, int argc, char **argv)
4940986ab12SMaksim Yevmenkin {
4950986ab12SMaksim Yevmenkin 	char		*ep = NULL;
4960986ab12SMaksim Yevmenkin 	int32_t		 n, type, value;
497a4b187faSMaksim Yevmenkin 	uint16_t	 service;
4980986ab12SMaksim Yevmenkin 
4990986ab12SMaksim Yevmenkin 	/* Parse command line arguments */
5000986ab12SMaksim Yevmenkin 	switch (argc) {
5010986ab12SMaksim Yevmenkin 	case 1:
5020986ab12SMaksim Yevmenkin 		n = strtoul(argv[0], &ep, 16);
5030986ab12SMaksim Yevmenkin 		if (*ep != 0) {
5040986ab12SMaksim Yevmenkin 			switch (tolower(argv[0][0])) {
5050986ab12SMaksim Yevmenkin 			case 'c': /* CIP/CTP */
5060986ab12SMaksim Yevmenkin 				switch (tolower(argv[0][1])) {
5070986ab12SMaksim Yevmenkin 				case 'i':
5080986ab12SMaksim Yevmenkin 					service = SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS;
5090986ab12SMaksim Yevmenkin 					break;
5100986ab12SMaksim Yevmenkin 
5110986ab12SMaksim Yevmenkin 				case 't':
5120986ab12SMaksim Yevmenkin 					service = SDP_SERVICE_CLASS_CORDLESS_TELEPHONY;
5130986ab12SMaksim Yevmenkin 					break;
5140986ab12SMaksim Yevmenkin 
5150986ab12SMaksim Yevmenkin 				default:
5160986ab12SMaksim Yevmenkin 					return (USAGE);
5170986ab12SMaksim Yevmenkin 					/* NOT REACHED */
5180986ab12SMaksim Yevmenkin 				}
5190986ab12SMaksim Yevmenkin 				break;
5200986ab12SMaksim Yevmenkin 
5210986ab12SMaksim Yevmenkin 			case 'd': /* DialUp Networking */
5220986ab12SMaksim Yevmenkin 				service = SDP_SERVICE_CLASS_DIALUP_NETWORKING;
5230986ab12SMaksim Yevmenkin 				break;
5240986ab12SMaksim Yevmenkin 
5250986ab12SMaksim Yevmenkin 			case 'f': /* Fax/OBEX File Transfer */
5260986ab12SMaksim Yevmenkin 				switch (tolower(argv[0][1])) {
5270986ab12SMaksim Yevmenkin 				case 'a':
5280986ab12SMaksim Yevmenkin 					service = SDP_SERVICE_CLASS_FAX;
5290986ab12SMaksim Yevmenkin 					break;
5300986ab12SMaksim Yevmenkin 
5310986ab12SMaksim Yevmenkin 				case 't':
5320986ab12SMaksim Yevmenkin 					service = SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER;
5330986ab12SMaksim Yevmenkin 					break;
5340986ab12SMaksim Yevmenkin 
5350986ab12SMaksim Yevmenkin 				default:
5360986ab12SMaksim Yevmenkin 					return (USAGE);
5370986ab12SMaksim Yevmenkin 					/* NOT REACHED */
5380986ab12SMaksim Yevmenkin 				}
5390986ab12SMaksim Yevmenkin 				break;
5400986ab12SMaksim Yevmenkin 
5410986ab12SMaksim Yevmenkin 			case 'g': /* GN */
5420986ab12SMaksim Yevmenkin 				service = SDP_SERVICE_CLASS_GN;
5430986ab12SMaksim Yevmenkin 				break;
5440986ab12SMaksim Yevmenkin 
5450986ab12SMaksim Yevmenkin 			case 'h': /* Headset/HID */
5460986ab12SMaksim Yevmenkin 				switch (tolower(argv[0][1])) {
5470986ab12SMaksim Yevmenkin 				case 'i':
5480986ab12SMaksim Yevmenkin 					service = SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE;
5490986ab12SMaksim Yevmenkin 					break;
5500986ab12SMaksim Yevmenkin 
5510986ab12SMaksim Yevmenkin 				case 's':
5520986ab12SMaksim Yevmenkin 					service = SDP_SERVICE_CLASS_HEADSET;
5530986ab12SMaksim Yevmenkin 					break;
5540986ab12SMaksim Yevmenkin 
5550986ab12SMaksim Yevmenkin 				default:
5560986ab12SMaksim Yevmenkin 					return (USAGE);
5570986ab12SMaksim Yevmenkin 					/* NOT REACHED */
5580986ab12SMaksim Yevmenkin 				}
5590986ab12SMaksim Yevmenkin 				break;
5600986ab12SMaksim Yevmenkin 
5610986ab12SMaksim Yevmenkin 			case 'l': /* LAN Access Using PPP */
5620986ab12SMaksim Yevmenkin 				service = SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP;
5630986ab12SMaksim Yevmenkin 				break;
5640986ab12SMaksim Yevmenkin 
5650986ab12SMaksim Yevmenkin 			case 'n': /* NAP */
5660986ab12SMaksim Yevmenkin 				service = SDP_SERVICE_CLASS_NAP;
5670986ab12SMaksim Yevmenkin 				break;
5680986ab12SMaksim Yevmenkin 
5690986ab12SMaksim Yevmenkin 			case 'o': /* OBEX Object Push */
5700986ab12SMaksim Yevmenkin 				service = SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH;
5710986ab12SMaksim Yevmenkin 				break;
5720986ab12SMaksim Yevmenkin 
5730986ab12SMaksim Yevmenkin 			case 's': /* Serial Port */
5740986ab12SMaksim Yevmenkin 				service = SDP_SERVICE_CLASS_SERIAL_PORT;
5750986ab12SMaksim Yevmenkin 				break;
5760986ab12SMaksim Yevmenkin 
5770986ab12SMaksim Yevmenkin 			default:
5780986ab12SMaksim Yevmenkin 				return (USAGE);
5790986ab12SMaksim Yevmenkin 				/* NOT REACHED */
5800986ab12SMaksim Yevmenkin 			}
5810986ab12SMaksim Yevmenkin 		} else
582a4b187faSMaksim Yevmenkin 			service = (uint16_t) n;
5830986ab12SMaksim Yevmenkin 		break;
5840986ab12SMaksim Yevmenkin 
5850986ab12SMaksim Yevmenkin 	default:
5860986ab12SMaksim Yevmenkin 		return (USAGE);
5870986ab12SMaksim Yevmenkin 	}
5880986ab12SMaksim Yevmenkin 
5890986ab12SMaksim Yevmenkin 	if (service < SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER)
5900986ab12SMaksim Yevmenkin 		return (USAGE);
5910986ab12SMaksim Yevmenkin 
5920986ab12SMaksim Yevmenkin 	/* Initialize attribute values array */
5930986ab12SMaksim Yevmenkin 	for (n = 0; n < values_len; n ++) {
5940986ab12SMaksim Yevmenkin 		values[n].flags = SDP_ATTR_INVALID;
5950986ab12SMaksim Yevmenkin 		values[n].attr = 0;
5960986ab12SMaksim Yevmenkin 		values[n].vlen = BSIZE;
5970986ab12SMaksim Yevmenkin 		values[n].value = buffer[n];
5980986ab12SMaksim Yevmenkin 	}
5990986ab12SMaksim Yevmenkin 
6000986ab12SMaksim Yevmenkin 	/* Do SDP Service Search Attribute Request */
6010986ab12SMaksim Yevmenkin 	n = sdp_search(xs, 1, &service, attrs_len, attrs, values_len, values);
6020986ab12SMaksim Yevmenkin 	if (n != 0)
6030986ab12SMaksim Yevmenkin 		return (ERROR);
6040986ab12SMaksim Yevmenkin 
6050986ab12SMaksim Yevmenkin 	/* Print attributes values */
6060986ab12SMaksim Yevmenkin 	for (n = 0; n < values_len; n ++) {
6070986ab12SMaksim Yevmenkin 		if (values[n].flags != SDP_ATTR_OK)
6080986ab12SMaksim Yevmenkin 			break;
6090986ab12SMaksim Yevmenkin 
6100986ab12SMaksim Yevmenkin 		switch (values[n].attr) {
6110986ab12SMaksim Yevmenkin 		case SDP_ATTR_SERVICE_RECORD_HANDLE:
6120986ab12SMaksim Yevmenkin 			fprintf(stdout, "\n");
6130986ab12SMaksim Yevmenkin 			if (values[n].vlen == 5) {
6140986ab12SMaksim Yevmenkin 				SDP_GET8(type, values[n].value);
6150986ab12SMaksim Yevmenkin 				if (type == SDP_DATA_UINT32) {
6160986ab12SMaksim Yevmenkin 					SDP_GET32(value, values[n].value);
6170986ab12SMaksim Yevmenkin 					fprintf(stdout, "Record Handle: " \
6180986ab12SMaksim Yevmenkin 							"%#8.8x\n", value);
6190986ab12SMaksim Yevmenkin 				} else
6200986ab12SMaksim Yevmenkin 					fprintf(stderr, "Invalid type=%#x " \
6210986ab12SMaksim Yevmenkin 							"Record Handle " \
6220986ab12SMaksim Yevmenkin 							"attribute!\n", type);
6230986ab12SMaksim Yevmenkin 			} else
6240986ab12SMaksim Yevmenkin 				fprintf(stderr, "Invalid size=%d for Record " \
6250986ab12SMaksim Yevmenkin 						"Handle attribute\n",
6260986ab12SMaksim Yevmenkin 						values[n].vlen);
6270986ab12SMaksim Yevmenkin 			break;
6280986ab12SMaksim Yevmenkin 
6290986ab12SMaksim Yevmenkin 		case SDP_ATTR_SERVICE_CLASS_ID_LIST:
6300986ab12SMaksim Yevmenkin 			fprintf(stdout, "Service Class ID List:\n");
6310986ab12SMaksim Yevmenkin 			print_service_class_id_list(values[n].value,
6320986ab12SMaksim Yevmenkin 					values[n].value + values[n].vlen);
6330986ab12SMaksim Yevmenkin 			break;
6340986ab12SMaksim Yevmenkin 
6350986ab12SMaksim Yevmenkin 		case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST:
6360986ab12SMaksim Yevmenkin 			fprintf(stdout, "Protocol Descriptor List:\n");
6370986ab12SMaksim Yevmenkin 			print_protocol_descriptor_list(values[n].value,
6380986ab12SMaksim Yevmenkin 					values[n].value + values[n].vlen);
6390986ab12SMaksim Yevmenkin 			break;
6400986ab12SMaksim Yevmenkin 
6410986ab12SMaksim Yevmenkin 		case SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST:
6420986ab12SMaksim Yevmenkin 			fprintf(stdout, "Bluetooth Profile Descriptor List:\n");
6430986ab12SMaksim Yevmenkin 			print_bluetooth_profile_descriptor_list(values[n].value,
6440986ab12SMaksim Yevmenkin 					values[n].value + values[n].vlen);
6450986ab12SMaksim Yevmenkin 			break;
6460986ab12SMaksim Yevmenkin 
6470986ab12SMaksim Yevmenkin 		default:
6480986ab12SMaksim Yevmenkin 			fprintf(stderr, "Unexpected attribute ID=%#4.4x\n",
6490986ab12SMaksim Yevmenkin 					values[n].attr);
6500986ab12SMaksim Yevmenkin 			break;
6510986ab12SMaksim Yevmenkin 		}
6520986ab12SMaksim Yevmenkin 	}
6530986ab12SMaksim Yevmenkin 
6540986ab12SMaksim Yevmenkin 	return (OK);
6550986ab12SMaksim Yevmenkin } /* do_sdp_search */
6560986ab12SMaksim Yevmenkin 
6570986ab12SMaksim Yevmenkin /* Perform SDP browse command */
6580986ab12SMaksim Yevmenkin static int
6590986ab12SMaksim Yevmenkin do_sdp_browse(void *xs, int argc, char **argv)
6600986ab12SMaksim Yevmenkin {
6610986ab12SMaksim Yevmenkin #undef	_STR
6620986ab12SMaksim Yevmenkin #undef	STR
6630986ab12SMaksim Yevmenkin #define	_STR(x)	#x
6640986ab12SMaksim Yevmenkin #define	STR(x)	_STR(x)
6650986ab12SMaksim Yevmenkin 
6660986ab12SMaksim Yevmenkin 	static char const * const	av[] = {
6670986ab12SMaksim Yevmenkin 		STR(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP),
6680986ab12SMaksim Yevmenkin 		NULL
6690986ab12SMaksim Yevmenkin 	};
6700986ab12SMaksim Yevmenkin 
6710986ab12SMaksim Yevmenkin 	switch (argc) {
6720986ab12SMaksim Yevmenkin 	case 0:
6730986ab12SMaksim Yevmenkin 		argc = 1;
6740986ab12SMaksim Yevmenkin 		argv = (char **) av;
6750986ab12SMaksim Yevmenkin 		/* FALL THROUGH */
6760986ab12SMaksim Yevmenkin 	case 1:
6770986ab12SMaksim Yevmenkin 		return (do_sdp_search(xs, argc, argv));
6780986ab12SMaksim Yevmenkin 	}
6790986ab12SMaksim Yevmenkin 
6800986ab12SMaksim Yevmenkin 	return (USAGE);
6810986ab12SMaksim Yevmenkin } /* do_sdp_browse */
6820986ab12SMaksim Yevmenkin 
6830986ab12SMaksim Yevmenkin /* List of SDP commands */
6840986ab12SMaksim Yevmenkin struct sdp_command	sdp_commands[] = {
6850986ab12SMaksim Yevmenkin {
6860986ab12SMaksim Yevmenkin "Browse [<Group>]",
6870986ab12SMaksim Yevmenkin "Browse for services. The <Group> parameter is a 16-bit UUID of the group\n" \
6880986ab12SMaksim Yevmenkin "to browse. If omitted <Group> is set to Public Browse Group.\n\n" \
6890986ab12SMaksim Yevmenkin "\t<Group> - xxxx; 16-bit UUID of the group to browse\n",
6900986ab12SMaksim Yevmenkin do_sdp_browse
6910986ab12SMaksim Yevmenkin },
6920986ab12SMaksim Yevmenkin {
6930986ab12SMaksim Yevmenkin "Search <Service>",
6940986ab12SMaksim Yevmenkin "Search for the <Service>. The <Service> parameter is a 16-bit UUID of the\n" \
6950986ab12SMaksim Yevmenkin "service to search for. For some services it is possible to use service name\n"\
6960986ab12SMaksim Yevmenkin "instead of service UUID\n\n" \
6970986ab12SMaksim Yevmenkin "\t<Service> - xxxx; 16-bit UUID of the service to search for\n\n" \
6980986ab12SMaksim Yevmenkin "\tKnown service names\n" \
6990986ab12SMaksim Yevmenkin "\t===================\n" \
7000986ab12SMaksim Yevmenkin "\tCIP   - Common ISDN Access\n" \
7010986ab12SMaksim Yevmenkin "\tCTP   - Cordless Telephony\n" \
7020986ab12SMaksim Yevmenkin "\tDUN   - DialUp Networking\n" \
7030986ab12SMaksim Yevmenkin "\tFAX   - Fax\n" \
7040986ab12SMaksim Yevmenkin "\tFTRN  - OBEX File Transfer\n" \
7050986ab12SMaksim Yevmenkin "\tGN    - GN\n" \
7060986ab12SMaksim Yevmenkin "\tHID   - Human Interface Device\n" \
7070986ab12SMaksim Yevmenkin "\tHSET  - Headset\n" \
7080986ab12SMaksim Yevmenkin "\tLAN   - LAN Access Using PPP\n" \
7090986ab12SMaksim Yevmenkin "\tNAP   - Network Access Point\n" \
7100986ab12SMaksim Yevmenkin "\tOPUSH - OBEX Object Push\n" \
7110986ab12SMaksim Yevmenkin "\tSP    - Serial Port\n",
7120986ab12SMaksim Yevmenkin do_sdp_search
7130986ab12SMaksim Yevmenkin },
7140986ab12SMaksim Yevmenkin { NULL, NULL, NULL }
7150986ab12SMaksim Yevmenkin };
7160986ab12SMaksim Yevmenkin 
717