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