xref: /netbsd-src/lib/libbluetooth/bluetooth.c (revision e28af4372a4de55a5803174563489fa94dd811ea)
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