xref: /freebsd/lib/libbluetooth/bluetooth.c (revision 6be3386466ab79a84b48429ae66244f21526d3df)
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$
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 
45 static FILE		*hostf = NULL;
46 static int		 host_stayopen = 0;
47 static struct hostent	 host;
48 static bdaddr_t		 host_addr;
49 static char		*host_addr_ptrs[2];
50 static char		*host_aliases[MAXALIASES];
51 
52 static FILE		*protof = NULL;
53 static int		 proto_stayopen = 0;
54 static struct protoent	 proto;
55 static char		*proto_aliases[MAXALIASES];
56 
57 static char		 buf[BUFSIZ + 1];
58 
59 static int bt_hex_byte   (char const *str);
60 static int bt_hex_nibble (char nibble);
61 
62 struct hostent *
63 bt_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 	}
76 found:
77 	bt_endhostent();
78 
79 	return (p);
80 }
81 
82 struct hostent *
83 bt_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 
101 struct hostent *
102 bt_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 	}
113 again:
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 
155 void
156 bt_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 
166 void
167 bt_endhostent(void)
168 {
169 	if (hostf != NULL && host_stayopen == 0) {
170 		(void) fclose(hostf);
171 		hostf = NULL;
172 	}
173 }
174 
175 struct protoent *
176 bt_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 	}
189 found:
190 	bt_endprotoent();
191 
192 	return (p);
193 }
194 
195 struct protoent *
196 bt_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 
209 struct protoent *
210 bt_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);
219 again:
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 
255 void
256 bt_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 
266 void
267 bt_endprotoent(void)
268 {
269 	if (protof != NULL) {
270 		(void) fclose(protof);
271 		protof = NULL;
272 	}
273 }
274 
275 char const *
276 bt_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 
289 int
290 bt_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 
345 static int
346 bt_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 
359 static int
360 bt_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