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