Home | History | Annotate | Line # | Download | only in sdpquery
command.c revision 1.3
      1 /*	$NetBSD: command.c,v 1.3 2009/12/05 16:54:13 plunky Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2009 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Iain Hibbert.
      9  *
     10  * Redistribution and use in source and binary forms, with or without
     11  * modification, are permitted provided that the following conditions
     12  * are met:
     13  * 1. Redistributions of source code must retain the above copyright
     14  *    notice, this list of conditions and the following disclaimer.
     15  * 2. Redistributions in binary form must reproduce the above copyright
     16  *    notice, this list of conditions and the following disclaimer in the
     17  *    documentation and/or other materials provided with the distribution.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __RCSID("$NetBSD: command.c,v 1.3 2009/12/05 16:54:13 plunky Exp $");
     34 
     35 #include <bluetooth.h>
     36 #include <err.h>
     37 #include <sdp.h>
     38 #include <stdlib.h>
     39 #include <string.h>
     40 
     41 #include "sdpquery.h"
     42 
     43 static sdp_session_t open_session(void);
     44 static void build_ssp(sdp_data_t *, int, const char **);
     45 
     46 static struct alias {
     47 	uint16_t	uuid;
     48 	const char *	name;
     49 	const char *	desc;
     50 } aliases[] = {
     51 	{ SDP_SERVICE_CLASS_ADVANCED_AUDIO_DISTRIBUTION,
     52 	  "A2DP",	"Advanced Audio Distribution Profile"		},
     53 	{ SDP_UUID_PROTOCOL_BNEP,
     54 	  "BNEP",	"Bluetooth Network Encapsulation Protocol"	},
     55 	{ SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS,
     56 	  "CIP",	"Common ISDN Access Service"			},
     57 	{ SDP_SERVICE_CLASS_CORDLESS_TELEPHONY,
     58 	  "CTP",	"Cordless Telephony Service"			},
     59 	{ SDP_SERVICE_CLASS_DIALUP_NETWORKING,
     60 	  "DUN",	"Dial Up Networking Service"			},
     61 	{ SDP_SERVICE_CLASS_FAX,
     62 	  "FAX",	"Fax Service"					},
     63 	{ SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER,
     64 	  "FTRN",	"File Transfer Service"				},
     65 	{ SDP_SERVICE_CLASS_GN,
     66 	  "GN",		"Group ad-hoc Network Service"			},
     67 	{ SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE,
     68 	  "HID",	"Human Interface Device Service"		},
     69 	{ SDP_SERVICE_CLASS_HANDSFREE,
     70 	  "HF",		"Handsfree Service"				},
     71 	{ SDP_SERVICE_CLASS_HEADSET,
     72 	  "HSET",	"Headset Service"				},
     73 	{ SDP_UUID_PROTOCOL_L2CAP,
     74 	  "L2CAP",	"Logical Link Control and Adapatation Protocol"	},
     75 	{ SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP,
     76 	  "LAN",	"Lan access using PPP Service"			},
     77 	{ SDP_SERVICE_CLASS_NAP,
     78 	  "NAP",	"Network Access Point Service"			},
     79 	{ SDP_UUID_PROTOCOL_OBEX,
     80 	  "OBEX",	"Object Exchange Protocol"			},
     81 	{ SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH,
     82 	  "OPUSH",	"Object Push Service"				},
     83 	{ SDP_SERVICE_CLASS_PANU,
     84 	  "PANU",	"Personal Area Networking User Service"		},
     85 	{ SDP_SERVICE_CLASS_PNP_INFORMATION,
     86 	  "PNP",	"PNP Information Service"			},
     87 	{ SDP_UUID_PROTOCOL_RFCOMM,
     88 	  "RFCOMM",	"RFCOMM Protocol"				},
     89 	{ SDP_UUID_PROTOCOL_SDP,
     90 	  "SDP",	"Service Discovery Protocol"			},
     91 	{ SDP_SERVICE_CLASS_SERIAL_PORT,
     92 	  "SP",		"Serial Port Service"				},
     93 	{ SDP_SERVICE_CLASS_IR_MC_SYNC,
     94 	  "SYNC",	"IrMC Sync Client Service"			},
     95 };
     96 
     97 int
     98 do_sdp_browse(int argc, const char **argv)
     99 {
    100 #define STR(x)	__STRING(x)
    101 	const char *av = STR(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
    102 #undef STR
    103 
    104 	if (argc > 1)
    105 		errx(EXIT_FAILURE, "Too many arguments");
    106 
    107 	if (argc == 0) {
    108 		argc = 1;
    109 		argv = &av;
    110 	}
    111 
    112 	return do_sdp_search(argc, argv);
    113 }
    114 
    115 int
    116 do_sdp_record(int argc, const char **argv)
    117 {
    118 	sdp_session_t	ss;
    119 	sdp_data_t	rsp;
    120 	char *		ep;
    121 	unsigned long	handle;
    122 	bool		rv;
    123 
    124 	if (argc == 0)
    125 		errx(EXIT_FAILURE, "Record handle required");
    126 
    127 	ss = open_session();
    128 
    129 	for (; argc-- > 0; argv++) {
    130 		handle = strtoul(*argv, &ep, 0);
    131 		if (*argv[0] == '\0' || *ep != '\0' || handle > UINT32_MAX)
    132 			errx(EXIT_FAILURE, "Invalid handle: %s\n", *argv);
    133 
    134 		rv = sdp_service_attribute(ss, (uint32_t)handle, NULL, &rsp);
    135 		if (!rv)
    136 			warn("%s", *argv);
    137 		else
    138 			print_record(&rsp);
    139 
    140 		if (argc > 0)
    141 			printf("\n\n");
    142 	}
    143 
    144 	sdp_close(ss);
    145 	return EXIT_SUCCESS;
    146 }
    147 
    148 int
    149 do_sdp_search(int argc, const char **argv)
    150 {
    151 	sdp_session_t	ss;
    152 	sdp_data_t	ssp, rec, rsp;
    153 	bool		rv;
    154 
    155 	if (argc < 1)
    156 		errx(EXIT_FAILURE, "UUID required");
    157 
    158 	if (argc > 12)
    159 		errx(EXIT_FAILURE, "Too many UUIDs");
    160 
    161 	build_ssp(&ssp, argc, argv);
    162 
    163 	ss = open_session();
    164 
    165 	rv = sdp_service_search_attribute(ss, &ssp, NULL, &rsp);
    166 	if (!rv)
    167 		err(EXIT_FAILURE, "sdp_service_search_attribute");
    168 
    169 	while (sdp_get_seq(&rsp, &rec)) {
    170 		if (!rv)
    171 			printf("\n\n");
    172 		else
    173 			rv = false;
    174 
    175 		print_record(&rec);
    176 	}
    177 
    178 	if (rsp.next != rsp.end) {
    179 		printf("\n\nAdditional Data:\n");
    180 		sdp_data_print(&rsp, 4);
    181 	}
    182 
    183 	sdp_close(ss);
    184 
    185 	return EXIT_SUCCESS;
    186 }
    187 
    188 static sdp_session_t
    189 open_session(void)
    190 {
    191 	sdp_session_t ss;
    192 
    193 	if (bdaddr_any(&remote_addr))
    194 		ss = sdp_open_local(control_socket);
    195 	else
    196 		ss = sdp_open(&local_addr, &remote_addr);
    197 
    198 	if (ss == NULL)
    199 		err(EXIT_FAILURE, "sdp_open");
    200 
    201 	return ss;
    202 }
    203 
    204 /*
    205  * build ServiceSearchPattern from arglist
    206  */
    207 static void
    208 build_ssp(sdp_data_t *ssp, int argc, const char **argv)
    209 {
    210 	static uint8_t	data[12 * sizeof(uuid_t)];
    211 	char *		ep;
    212 	uintmax_t	umax;
    213 	uuid_t		uuid;
    214 	uint32_t	status;
    215 	int		i;
    216 
    217 	ssp->next = data;
    218 	ssp->end = data + sizeof(data);
    219 
    220 	for (; argc-- > 0; argv++) {
    221 		uuid_from_string(*argv, &uuid, &status);
    222 		if (status != uuid_s_ok) {
    223 			umax = strtoumax(*argv, &ep, 0);
    224 			if (*argv[0] == '\0' || *ep != '\0') {
    225 				for (i = 0;; i++) {
    226 					if (i == __arraycount(aliases))
    227 						errx(EXIT_FAILURE,
    228 						    "%s: Bad UUID", *argv);
    229 
    230 					if (strcasecmp(aliases[i].name,
    231 					    *argv) == 0)
    232 						break;
    233 				}
    234 
    235 				umax = aliases[i].uuid;
    236 			} else if (umax > UINT32_MAX)
    237 				errx(EXIT_FAILURE, "%s: Bad UUID", *argv);
    238 
    239 			uuid = BLUETOOTH_BASE_UUID;
    240 			uuid.time_low = (uint32_t)umax;
    241 		}
    242 
    243 		sdp_put_uuid(ssp, &uuid);
    244 	}
    245 
    246 	ssp->end = ssp->next;
    247 	ssp->next = data;
    248 }
    249