xref: /netbsd/lib/libbluetooth/bluetooth.c (revision a5c89047)
1*a5c89047Sgdamore /*	$NetBSD: bluetooth.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $	*/
2*a5c89047Sgdamore 
3*a5c89047Sgdamore /*
4*a5c89047Sgdamore  * bluetooth.c
5*a5c89047Sgdamore  *
6*a5c89047Sgdamore  * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7*a5c89047Sgdamore  * All rights reserved.
8*a5c89047Sgdamore  *
9*a5c89047Sgdamore  * Redistribution and use in source and binary forms, with or without
10*a5c89047Sgdamore  * modification, are permitted provided that the following conditions
11*a5c89047Sgdamore  * are met:
12*a5c89047Sgdamore  * 1. Redistributions of source code must retain the above copyright
13*a5c89047Sgdamore  *    notice, this list of conditions and the following disclaimer.
14*a5c89047Sgdamore  * 2. Redistributions in binary form must reproduce the above copyright
15*a5c89047Sgdamore  *    notice, this list of conditions and the following disclaimer in the
16*a5c89047Sgdamore  *    documentation and/or other materials provided with the distribution.
17*a5c89047Sgdamore  *
18*a5c89047Sgdamore  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19*a5c89047Sgdamore  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*a5c89047Sgdamore  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*a5c89047Sgdamore  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22*a5c89047Sgdamore  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23*a5c89047Sgdamore  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24*a5c89047Sgdamore  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25*a5c89047Sgdamore  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26*a5c89047Sgdamore  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27*a5c89047Sgdamore  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28*a5c89047Sgdamore  * SUCH DAMAGE.
29*a5c89047Sgdamore  *
30*a5c89047Sgdamore  * $Id: bluetooth.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $
31*a5c89047Sgdamore  * $FreeBSD: src/lib/libbluetooth/bluetooth.c,v 1.2 2004/03/05 08:10:17 markm Exp $
32*a5c89047Sgdamore  */
33*a5c89047Sgdamore 
34*a5c89047Sgdamore #include <sys/cdefs.h>
35*a5c89047Sgdamore __RCSID("$NetBSD: bluetooth.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $");
36*a5c89047Sgdamore 
37*a5c89047Sgdamore #include <bluetooth.h>
38*a5c89047Sgdamore #include <stdio.h>
39*a5c89047Sgdamore #include <stdlib.h>
40*a5c89047Sgdamore #include <string.h>
41*a5c89047Sgdamore 
42*a5c89047Sgdamore #define _PATH_BT_HOSTS		"/etc/bluetooth/hosts"
43*a5c89047Sgdamore #define _PATH_BT_PROTOCOLS	"/etc/bluetooth/protocols"
44*a5c89047Sgdamore #define MAXALIASES		 35
45*a5c89047Sgdamore 
46*a5c89047Sgdamore static FILE		*hostf = NULL;
47*a5c89047Sgdamore static int		 host_stayopen = 0;
48*a5c89047Sgdamore static struct hostent	 host;
49*a5c89047Sgdamore static bdaddr_t		 host_addr;
50*a5c89047Sgdamore static char		*host_addr_ptrs[2];
51*a5c89047Sgdamore static char		*host_aliases[MAXALIASES];
52*a5c89047Sgdamore 
53*a5c89047Sgdamore static FILE		*protof = NULL;
54*a5c89047Sgdamore static int		 proto_stayopen = 0;
55*a5c89047Sgdamore static struct protoent	 proto;
56*a5c89047Sgdamore static char		*proto_aliases[MAXALIASES];
57*a5c89047Sgdamore 
58*a5c89047Sgdamore static char		 buf[BUFSIZ + 1];
59*a5c89047Sgdamore 
60*a5c89047Sgdamore static int bt_hex_byte   (char const *str);
61*a5c89047Sgdamore static int bt_hex_nibble (char nibble);
62*a5c89047Sgdamore 
63*a5c89047Sgdamore struct hostent *
bt_gethostbyname(char const * name)64*a5c89047Sgdamore bt_gethostbyname(char const *name)
65*a5c89047Sgdamore {
66*a5c89047Sgdamore 	struct hostent	*p;
67*a5c89047Sgdamore 	char		**cp;
68*a5c89047Sgdamore 
69*a5c89047Sgdamore 	bt_sethostent(host_stayopen);
70*a5c89047Sgdamore 	while ((p = bt_gethostent()) != NULL) {
71*a5c89047Sgdamore 		if (strcasecmp(p->h_name, name) == 0)
72*a5c89047Sgdamore 			break;
73*a5c89047Sgdamore 		for (cp = p->h_aliases; *cp != 0; cp++)
74*a5c89047Sgdamore 			if (strcasecmp(*cp, name) == 0)
75*a5c89047Sgdamore 				goto found;
76*a5c89047Sgdamore 	}
77*a5c89047Sgdamore found:
78*a5c89047Sgdamore 	bt_endhostent();
79*a5c89047Sgdamore 
80*a5c89047Sgdamore 	return (p);
81*a5c89047Sgdamore }
82*a5c89047Sgdamore 
83*a5c89047Sgdamore struct hostent *
bt_gethostbyaddr(char const * addr,socklen_t len,int type)84*a5c89047Sgdamore bt_gethostbyaddr(char const *addr, socklen_t len, int type)
85*a5c89047Sgdamore {
86*a5c89047Sgdamore 	struct hostent	*p;
87*a5c89047Sgdamore 
88*a5c89047Sgdamore 	if (type != AF_BLUETOOTH || len != sizeof(bdaddr_t)) {
89*a5c89047Sgdamore 		h_errno = NO_RECOVERY;
90*a5c89047Sgdamore 		return (NULL);
91*a5c89047Sgdamore 	}
92*a5c89047Sgdamore 
93*a5c89047Sgdamore 	bt_sethostent(host_stayopen);
94*a5c89047Sgdamore 	while ((p = bt_gethostent()) != NULL)
95*a5c89047Sgdamore 		if (p->h_addrtype == type && memcmp(p->h_addr, addr, len) == 0)
96*a5c89047Sgdamore 			break;
97*a5c89047Sgdamore 	bt_endhostent();
98*a5c89047Sgdamore 
99*a5c89047Sgdamore 	return (p);
100*a5c89047Sgdamore }
101*a5c89047Sgdamore 
102*a5c89047Sgdamore struct hostent *
bt_gethostent(void)103*a5c89047Sgdamore bt_gethostent(void)
104*a5c89047Sgdamore {
105*a5c89047Sgdamore 	char	*p, *cp, **q;
106*a5c89047Sgdamore 
107*a5c89047Sgdamore 	if (hostf == NULL)
108*a5c89047Sgdamore 		hostf = fopen(_PATH_BT_HOSTS, "r");
109*a5c89047Sgdamore 
110*a5c89047Sgdamore 	if (hostf == NULL) {
111*a5c89047Sgdamore 		h_errno = NETDB_INTERNAL;
112*a5c89047Sgdamore 		return (NULL);
113*a5c89047Sgdamore 	}
114*a5c89047Sgdamore again:
115*a5c89047Sgdamore 	if ((p = fgets(buf, sizeof(buf), hostf)) == NULL) {
116*a5c89047Sgdamore 		h_errno = HOST_NOT_FOUND;
117*a5c89047Sgdamore 		return (NULL);
118*a5c89047Sgdamore 	}
119*a5c89047Sgdamore 	if (*p == '#')
120*a5c89047Sgdamore 		goto again;
121*a5c89047Sgdamore 	if ((cp = strpbrk(p, "#\n")) == NULL)
122*a5c89047Sgdamore 		goto again;
123*a5c89047Sgdamore 	*cp = 0;
124*a5c89047Sgdamore 	if ((cp = strpbrk(p, " \t")) == NULL)
125*a5c89047Sgdamore 		goto again;
126*a5c89047Sgdamore 	*cp++ = 0;
127*a5c89047Sgdamore 	if (bt_aton(p, &host_addr) == 0)
128*a5c89047Sgdamore 		goto again;
129*a5c89047Sgdamore 	host_addr_ptrs[0] = (char *) &host_addr;
130*a5c89047Sgdamore 	host_addr_ptrs[1] = NULL;
131*a5c89047Sgdamore 	host.h_addr_list = host_addr_ptrs;
132*a5c89047Sgdamore 	host.h_length = sizeof(host_addr);
133*a5c89047Sgdamore 	host.h_addrtype = AF_BLUETOOTH;
134*a5c89047Sgdamore 	while (*cp == ' ' || *cp == '\t')
135*a5c89047Sgdamore 		cp++;
136*a5c89047Sgdamore 	host.h_name = cp;
137*a5c89047Sgdamore 	q = host.h_aliases = host_aliases;
138*a5c89047Sgdamore 	if ((cp = strpbrk(cp, " \t")) != NULL)
139*a5c89047Sgdamore 		*cp++ = 0;
140*a5c89047Sgdamore 	while (cp != NULL && *cp != 0) {
141*a5c89047Sgdamore 		if (*cp == ' ' || *cp == '\t') {
142*a5c89047Sgdamore 			cp++;
143*a5c89047Sgdamore 			continue;
144*a5c89047Sgdamore 		}
145*a5c89047Sgdamore 		if (q < &host_aliases[MAXALIASES - 1])
146*a5c89047Sgdamore 			*q++ = cp;
147*a5c89047Sgdamore 		if ((cp = strpbrk(cp, " \t")) != NULL)
148*a5c89047Sgdamore 			*cp++ = 0;
149*a5c89047Sgdamore 	}
150*a5c89047Sgdamore 	*q = NULL;
151*a5c89047Sgdamore 	h_errno = NETDB_SUCCESS;
152*a5c89047Sgdamore 
153*a5c89047Sgdamore 	return (&host);
154*a5c89047Sgdamore }
155*a5c89047Sgdamore 
156*a5c89047Sgdamore void
bt_sethostent(int stayopen)157*a5c89047Sgdamore bt_sethostent(int stayopen)
158*a5c89047Sgdamore {
159*a5c89047Sgdamore 	if (hostf == NULL)
160*a5c89047Sgdamore 		hostf = fopen(_PATH_BT_HOSTS, "r");
161*a5c89047Sgdamore 	else
162*a5c89047Sgdamore 		rewind(hostf);
163*a5c89047Sgdamore 
164*a5c89047Sgdamore 	host_stayopen = stayopen;
165*a5c89047Sgdamore }
166*a5c89047Sgdamore 
167*a5c89047Sgdamore void
bt_endhostent(void)168*a5c89047Sgdamore bt_endhostent(void)
169*a5c89047Sgdamore {
170*a5c89047Sgdamore 	if (hostf != NULL && host_stayopen == 0) {
171*a5c89047Sgdamore 		(void) fclose(hostf);
172*a5c89047Sgdamore 		hostf = NULL;
173*a5c89047Sgdamore 	}
174*a5c89047Sgdamore }
175*a5c89047Sgdamore 
176*a5c89047Sgdamore struct protoent *
bt_getprotobyname(char const * name)177*a5c89047Sgdamore bt_getprotobyname(char const *name)
178*a5c89047Sgdamore {
179*a5c89047Sgdamore 	struct protoent	 *p;
180*a5c89047Sgdamore 	char		**cp;
181*a5c89047Sgdamore 
182*a5c89047Sgdamore 	bt_setprotoent(proto_stayopen);
183*a5c89047Sgdamore 	while ((p = bt_getprotoent()) != NULL) {
184*a5c89047Sgdamore 		if (strcmp(p->p_name, name) == 0)
185*a5c89047Sgdamore 			break;
186*a5c89047Sgdamore 		for (cp = p->p_aliases; *cp != 0; cp++)
187*a5c89047Sgdamore 			if (strcmp(*cp, name) == 0)
188*a5c89047Sgdamore 				goto found;
189*a5c89047Sgdamore 	}
190*a5c89047Sgdamore found:
191*a5c89047Sgdamore 	bt_endprotoent();
192*a5c89047Sgdamore 
193*a5c89047Sgdamore 	return (p);
194*a5c89047Sgdamore }
195*a5c89047Sgdamore 
196*a5c89047Sgdamore struct protoent *
bt_getprotobynumber(int num)197*a5c89047Sgdamore bt_getprotobynumber(int num)
198*a5c89047Sgdamore {
199*a5c89047Sgdamore 	struct protoent	*p;
200*a5c89047Sgdamore 
201*a5c89047Sgdamore 	bt_setprotoent(proto_stayopen);
202*a5c89047Sgdamore 	while ((p = bt_getprotoent()) != NULL)
203*a5c89047Sgdamore 		if (p->p_proto == num)
204*a5c89047Sgdamore 			break;
205*a5c89047Sgdamore 	bt_endprotoent();
206*a5c89047Sgdamore 
207*a5c89047Sgdamore 	return (p);
208*a5c89047Sgdamore }
209*a5c89047Sgdamore 
210*a5c89047Sgdamore struct protoent *
bt_getprotoent(void)211*a5c89047Sgdamore bt_getprotoent(void)
212*a5c89047Sgdamore {
213*a5c89047Sgdamore 	char	*p, *cp, **q;
214*a5c89047Sgdamore 
215*a5c89047Sgdamore 	if (protof == NULL)
216*a5c89047Sgdamore 		protof = fopen(_PATH_BT_PROTOCOLS, "r");
217*a5c89047Sgdamore 
218*a5c89047Sgdamore 	if (protof == NULL)
219*a5c89047Sgdamore 		return (NULL);
220*a5c89047Sgdamore again:
221*a5c89047Sgdamore 	if ((p = fgets(buf, sizeof(buf), protof)) == NULL)
222*a5c89047Sgdamore 		return (NULL);
223*a5c89047Sgdamore 	if (*p == '#')
224*a5c89047Sgdamore 		goto again;
225*a5c89047Sgdamore 	if ((cp = strpbrk(p, "#\n")) == NULL)
226*a5c89047Sgdamore 		goto again;
227*a5c89047Sgdamore 	*cp = '\0';
228*a5c89047Sgdamore 	proto.p_name = p;
229*a5c89047Sgdamore 	if ((cp = strpbrk(p, " \t")) == NULL)
230*a5c89047Sgdamore 		goto again;
231*a5c89047Sgdamore 	*cp++ = '\0';
232*a5c89047Sgdamore 	while (*cp == ' ' || *cp == '\t')
233*a5c89047Sgdamore 		cp++;
234*a5c89047Sgdamore 	if ((p = strpbrk(cp, " \t")) != NULL)
235*a5c89047Sgdamore 		*p++ = '\0';
236*a5c89047Sgdamore 	proto.p_proto = (int)strtol(cp, NULL, 0);
237*a5c89047Sgdamore 	q = proto.p_aliases = proto_aliases;
238*a5c89047Sgdamore 	if (p != NULL) {
239*a5c89047Sgdamore 		cp = p;
240*a5c89047Sgdamore 		while (cp != NULL && *cp != 0) {
241*a5c89047Sgdamore 			if (*cp == ' ' || *cp == '\t') {
242*a5c89047Sgdamore 				cp++;
243*a5c89047Sgdamore 				continue;
244*a5c89047Sgdamore 			}
245*a5c89047Sgdamore 			if (q < &proto_aliases[MAXALIASES - 1])
246*a5c89047Sgdamore 				*q++ = cp;
247*a5c89047Sgdamore 			if ((cp = strpbrk(cp, " \t")) != NULL)
248*a5c89047Sgdamore 				*cp++ = '\0';
249*a5c89047Sgdamore 		}
250*a5c89047Sgdamore 	}
251*a5c89047Sgdamore 	*q = NULL;
252*a5c89047Sgdamore 
253*a5c89047Sgdamore 	return (&proto);
254*a5c89047Sgdamore }
255*a5c89047Sgdamore 
256*a5c89047Sgdamore void
bt_setprotoent(int stayopen)257*a5c89047Sgdamore bt_setprotoent(int stayopen)
258*a5c89047Sgdamore {
259*a5c89047Sgdamore 	if (protof == NULL)
260*a5c89047Sgdamore 		protof = fopen(_PATH_BT_PROTOCOLS, "r");
261*a5c89047Sgdamore 	else
262*a5c89047Sgdamore 		rewind(protof);
263*a5c89047Sgdamore 
264*a5c89047Sgdamore 	proto_stayopen = stayopen;
265*a5c89047Sgdamore }
266*a5c89047Sgdamore 
267*a5c89047Sgdamore void
bt_endprotoent(void)268*a5c89047Sgdamore bt_endprotoent(void)
269*a5c89047Sgdamore {
270*a5c89047Sgdamore 	if (protof != NULL) {
271*a5c89047Sgdamore 		(void) fclose(protof);
272*a5c89047Sgdamore 		protof = NULL;
273*a5c89047Sgdamore 	}
274*a5c89047Sgdamore }
275*a5c89047Sgdamore 
276*a5c89047Sgdamore char const *
bt_ntoa(bdaddr_t const * ba,char * str)277*a5c89047Sgdamore bt_ntoa(bdaddr_t const *ba, char *str)
278*a5c89047Sgdamore {
279*a5c89047Sgdamore 	static char	buffer[24];
280*a5c89047Sgdamore 
281*a5c89047Sgdamore 	if (str == NULL)
282*a5c89047Sgdamore 		str = buffer;
283*a5c89047Sgdamore 
284*a5c89047Sgdamore 	sprintf(str, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
285*a5c89047Sgdamore 		ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
286*a5c89047Sgdamore 
287*a5c89047Sgdamore 	return (str);
288*a5c89047Sgdamore }
289*a5c89047Sgdamore 
290*a5c89047Sgdamore int
bt_aton(char const * str,bdaddr_t * ba)291*a5c89047Sgdamore bt_aton(char const *str, bdaddr_t *ba)
292*a5c89047Sgdamore {
293*a5c89047Sgdamore 	int	 i, b;
294*a5c89047Sgdamore 	char	*end = NULL;
295*a5c89047Sgdamore 
296*a5c89047Sgdamore 	memset(ba, 0, sizeof(*ba));
297*a5c89047Sgdamore 
298*a5c89047Sgdamore 	for (i = 5, end = strchr(str, ':');
299*a5c89047Sgdamore 	     i > 0 && *str != '\0' && end != NULL;
300*a5c89047Sgdamore 	     i --, str = end + 1, end = strchr(str, ':')) {
301*a5c89047Sgdamore 		switch (end - str) {
302*a5c89047Sgdamore 		case 1:
303*a5c89047Sgdamore 			b = bt_hex_nibble(str[0]);
304*a5c89047Sgdamore 			break;
305*a5c89047Sgdamore 
306*a5c89047Sgdamore 		case 2:
307*a5c89047Sgdamore 			b = bt_hex_byte(str);
308*a5c89047Sgdamore 			break;
309*a5c89047Sgdamore 
310*a5c89047Sgdamore 		default:
311*a5c89047Sgdamore 			b = -1;
312*a5c89047Sgdamore 			break;
313*a5c89047Sgdamore 		}
314*a5c89047Sgdamore 
315*a5c89047Sgdamore 		if (b < 0)
316*a5c89047Sgdamore 			return (0);
317*a5c89047Sgdamore 
318*a5c89047Sgdamore 		ba->b[i] = b;
319*a5c89047Sgdamore 	}
320*a5c89047Sgdamore 
321*a5c89047Sgdamore 	if (i != 0 || end != NULL || *str == 0)
322*a5c89047Sgdamore 		return (0);
323*a5c89047Sgdamore 
324*a5c89047Sgdamore 	switch (strlen(str)) {
325*a5c89047Sgdamore 	case 1:
326*a5c89047Sgdamore 		b = bt_hex_nibble(str[0]);
327*a5c89047Sgdamore 		break;
328*a5c89047Sgdamore 
329*a5c89047Sgdamore 	case 2:
330*a5c89047Sgdamore 		b = bt_hex_byte(str);
331*a5c89047Sgdamore 		break;
332*a5c89047Sgdamore 
333*a5c89047Sgdamore 	default:
334*a5c89047Sgdamore 		b = -1;
335*a5c89047Sgdamore 		break;
336*a5c89047Sgdamore 	}
337*a5c89047Sgdamore 
338*a5c89047Sgdamore 	if (b < 0)
339*a5c89047Sgdamore 		return (0);
340*a5c89047Sgdamore 
341*a5c89047Sgdamore 	ba->b[i] = b;
342*a5c89047Sgdamore 
343*a5c89047Sgdamore 	return (1);
344*a5c89047Sgdamore }
345*a5c89047Sgdamore 
346*a5c89047Sgdamore static int
bt_hex_byte(char const * str)347*a5c89047Sgdamore bt_hex_byte(char const *str)
348*a5c89047Sgdamore {
349*a5c89047Sgdamore 	int	n1, n2;
350*a5c89047Sgdamore 
351*a5c89047Sgdamore 	if ((n1 = bt_hex_nibble(str[0])) < 0)
352*a5c89047Sgdamore 		return (-1);
353*a5c89047Sgdamore 
354*a5c89047Sgdamore 	if ((n2 = bt_hex_nibble(str[1])) < 0)
355*a5c89047Sgdamore 		return (-1);
356*a5c89047Sgdamore 
357*a5c89047Sgdamore 	return ((((n1 & 0x0f) << 4) | (n2 & 0x0f)) & 0xff);
358*a5c89047Sgdamore }
359*a5c89047Sgdamore 
360*a5c89047Sgdamore static int
bt_hex_nibble(char nibble)361*a5c89047Sgdamore bt_hex_nibble(char nibble)
362*a5c89047Sgdamore {
363*a5c89047Sgdamore 	if ('0' <= nibble && nibble <= '9')
364*a5c89047Sgdamore 		return (nibble - '0');
365*a5c89047Sgdamore 
366*a5c89047Sgdamore 	if ('a' <= nibble && nibble <= 'f')
367*a5c89047Sgdamore 		return (nibble - 'a' + 0xa);
368*a5c89047Sgdamore 
369*a5c89047Sgdamore 	if ('A' <= nibble && nibble <= 'F')
370*a5c89047Sgdamore 		return (nibble - 'A' + 0xa);
371*a5c89047Sgdamore 
372*a5c89047Sgdamore 	return (-1);
373*a5c89047Sgdamore }
374