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