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