xref: /netbsd/lib/libbluetooth/bluetooth.c (revision a5c89047)
1 /*	$NetBSD: bluetooth.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $	*/
2 
3 /*
4  * bluetooth.c
5  *
6  * Copyright (c) 2001-2003 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.1 2006/06/19 15:44:36 gdamore Exp $
31  * $FreeBSD: src/lib/libbluetooth/bluetooth.c,v 1.2 2004/03/05 08:10:17 markm Exp $
32  */
33 
34 #include <sys/cdefs.h>
35 __RCSID("$NetBSD: bluetooth.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $");
36 
37 #include <bluetooth.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #define _PATH_BT_HOSTS		"/etc/bluetooth/hosts"
43 #define _PATH_BT_PROTOCOLS	"/etc/bluetooth/protocols"
44 #define MAXALIASES		 35
45 
46 static FILE		*hostf = NULL;
47 static int		 host_stayopen = 0;
48 static struct hostent	 host;
49 static bdaddr_t		 host_addr;
50 static char		*host_addr_ptrs[2];
51 static char		*host_aliases[MAXALIASES];
52 
53 static FILE		*protof = NULL;
54 static int		 proto_stayopen = 0;
55 static struct protoent	 proto;
56 static char		*proto_aliases[MAXALIASES];
57 
58 static char		 buf[BUFSIZ + 1];
59 
60 static int bt_hex_byte   (char const *str);
61 static int bt_hex_nibble (char nibble);
62 
63 struct hostent *
bt_gethostbyname(char const * name)64 bt_gethostbyname(char const *name)
65 {
66 	struct hostent	*p;
67 	char		**cp;
68 
69 	bt_sethostent(host_stayopen);
70 	while ((p = bt_gethostent()) != NULL) {
71 		if (strcasecmp(p->h_name, name) == 0)
72 			break;
73 		for (cp = p->h_aliases; *cp != 0; cp++)
74 			if (strcasecmp(*cp, name) == 0)
75 				goto found;
76 	}
77 found:
78 	bt_endhostent();
79 
80 	return (p);
81 }
82 
83 struct hostent *
bt_gethostbyaddr(char const * addr,socklen_t len,int type)84 bt_gethostbyaddr(char const *addr, socklen_t len, int type)
85 {
86 	struct hostent	*p;
87 
88 	if (type != AF_BLUETOOTH || len != sizeof(bdaddr_t)) {
89 		h_errno = NO_RECOVERY;
90 		return (NULL);
91 	}
92 
93 	bt_sethostent(host_stayopen);
94 	while ((p = bt_gethostent()) != NULL)
95 		if (p->h_addrtype == type && memcmp(p->h_addr, addr, len) == 0)
96 			break;
97 	bt_endhostent();
98 
99 	return (p);
100 }
101 
102 struct hostent *
bt_gethostent(void)103 bt_gethostent(void)
104 {
105 	char	*p, *cp, **q;
106 
107 	if (hostf == NULL)
108 		hostf = fopen(_PATH_BT_HOSTS, "r");
109 
110 	if (hostf == NULL) {
111 		h_errno = NETDB_INTERNAL;
112 		return (NULL);
113 	}
114 again:
115 	if ((p = fgets(buf, sizeof(buf), hostf)) == NULL) {
116 		h_errno = HOST_NOT_FOUND;
117 		return (NULL);
118 	}
119 	if (*p == '#')
120 		goto again;
121 	if ((cp = strpbrk(p, "#\n")) == NULL)
122 		goto again;
123 	*cp = 0;
124 	if ((cp = strpbrk(p, " \t")) == NULL)
125 		goto again;
126 	*cp++ = 0;
127 	if (bt_aton(p, &host_addr) == 0)
128 		goto again;
129 	host_addr_ptrs[0] = (char *) &host_addr;
130 	host_addr_ptrs[1] = NULL;
131 	host.h_addr_list = host_addr_ptrs;
132 	host.h_length = sizeof(host_addr);
133 	host.h_addrtype = AF_BLUETOOTH;
134 	while (*cp == ' ' || *cp == '\t')
135 		cp++;
136 	host.h_name = cp;
137 	q = host.h_aliases = host_aliases;
138 	if ((cp = strpbrk(cp, " \t")) != NULL)
139 		*cp++ = 0;
140 	while (cp != NULL && *cp != 0) {
141 		if (*cp == ' ' || *cp == '\t') {
142 			cp++;
143 			continue;
144 		}
145 		if (q < &host_aliases[MAXALIASES - 1])
146 			*q++ = cp;
147 		if ((cp = strpbrk(cp, " \t")) != NULL)
148 			*cp++ = 0;
149 	}
150 	*q = NULL;
151 	h_errno = NETDB_SUCCESS;
152 
153 	return (&host);
154 }
155 
156 void
bt_sethostent(int stayopen)157 bt_sethostent(int stayopen)
158 {
159 	if (hostf == NULL)
160 		hostf = fopen(_PATH_BT_HOSTS, "r");
161 	else
162 		rewind(hostf);
163 
164 	host_stayopen = stayopen;
165 }
166 
167 void
bt_endhostent(void)168 bt_endhostent(void)
169 {
170 	if (hostf != NULL && host_stayopen == 0) {
171 		(void) fclose(hostf);
172 		hostf = NULL;
173 	}
174 }
175 
176 struct protoent *
bt_getprotobyname(char const * name)177 bt_getprotobyname(char const *name)
178 {
179 	struct protoent	 *p;
180 	char		**cp;
181 
182 	bt_setprotoent(proto_stayopen);
183 	while ((p = bt_getprotoent()) != NULL) {
184 		if (strcmp(p->p_name, name) == 0)
185 			break;
186 		for (cp = p->p_aliases; *cp != 0; cp++)
187 			if (strcmp(*cp, name) == 0)
188 				goto found;
189 	}
190 found:
191 	bt_endprotoent();
192 
193 	return (p);
194 }
195 
196 struct protoent *
bt_getprotobynumber(int num)197 bt_getprotobynumber(int num)
198 {
199 	struct protoent	*p;
200 
201 	bt_setprotoent(proto_stayopen);
202 	while ((p = bt_getprotoent()) != NULL)
203 		if (p->p_proto == num)
204 			break;
205 	bt_endprotoent();
206 
207 	return (p);
208 }
209 
210 struct protoent *
bt_getprotoent(void)211 bt_getprotoent(void)
212 {
213 	char	*p, *cp, **q;
214 
215 	if (protof == NULL)
216 		protof = fopen(_PATH_BT_PROTOCOLS, "r");
217 
218 	if (protof == NULL)
219 		return (NULL);
220 again:
221 	if ((p = fgets(buf, sizeof(buf), protof)) == NULL)
222 		return (NULL);
223 	if (*p == '#')
224 		goto again;
225 	if ((cp = strpbrk(p, "#\n")) == NULL)
226 		goto again;
227 	*cp = '\0';
228 	proto.p_name = p;
229 	if ((cp = strpbrk(p, " \t")) == NULL)
230 		goto again;
231 	*cp++ = '\0';
232 	while (*cp == ' ' || *cp == '\t')
233 		cp++;
234 	if ((p = strpbrk(cp, " \t")) != NULL)
235 		*p++ = '\0';
236 	proto.p_proto = (int)strtol(cp, NULL, 0);
237 	q = proto.p_aliases = proto_aliases;
238 	if (p != NULL) {
239 		cp = p;
240 		while (cp != NULL && *cp != 0) {
241 			if (*cp == ' ' || *cp == '\t') {
242 				cp++;
243 				continue;
244 			}
245 			if (q < &proto_aliases[MAXALIASES - 1])
246 				*q++ = cp;
247 			if ((cp = strpbrk(cp, " \t")) != NULL)
248 				*cp++ = '\0';
249 		}
250 	}
251 	*q = NULL;
252 
253 	return (&proto);
254 }
255 
256 void
bt_setprotoent(int stayopen)257 bt_setprotoent(int stayopen)
258 {
259 	if (protof == NULL)
260 		protof = fopen(_PATH_BT_PROTOCOLS, "r");
261 	else
262 		rewind(protof);
263 
264 	proto_stayopen = stayopen;
265 }
266 
267 void
bt_endprotoent(void)268 bt_endprotoent(void)
269 {
270 	if (protof != NULL) {
271 		(void) fclose(protof);
272 		protof = NULL;
273 	}
274 }
275 
276 char const *
bt_ntoa(bdaddr_t const * ba,char * str)277 bt_ntoa(bdaddr_t const *ba, char *str)
278 {
279 	static char	buffer[24];
280 
281 	if (str == NULL)
282 		str = buffer;
283 
284 	sprintf(str, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
285 		ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
286 
287 	return (str);
288 }
289 
290 int
bt_aton(char const * str,bdaddr_t * ba)291 bt_aton(char const *str, bdaddr_t *ba)
292 {
293 	int	 i, b;
294 	char	*end = NULL;
295 
296 	memset(ba, 0, sizeof(*ba));
297 
298 	for (i = 5, end = strchr(str, ':');
299 	     i > 0 && *str != '\0' && end != NULL;
300 	     i --, str = end + 1, end = strchr(str, ':')) {
301 		switch (end - str) {
302 		case 1:
303 			b = bt_hex_nibble(str[0]);
304 			break;
305 
306 		case 2:
307 			b = bt_hex_byte(str);
308 			break;
309 
310 		default:
311 			b = -1;
312 			break;
313 		}
314 
315 		if (b < 0)
316 			return (0);
317 
318 		ba->b[i] = b;
319 	}
320 
321 	if (i != 0 || end != NULL || *str == 0)
322 		return (0);
323 
324 	switch (strlen(str)) {
325 	case 1:
326 		b = bt_hex_nibble(str[0]);
327 		break;
328 
329 	case 2:
330 		b = bt_hex_byte(str);
331 		break;
332 
333 	default:
334 		b = -1;
335 		break;
336 	}
337 
338 	if (b < 0)
339 		return (0);
340 
341 	ba->b[i] = b;
342 
343 	return (1);
344 }
345 
346 static int
bt_hex_byte(char const * str)347 bt_hex_byte(char const *str)
348 {
349 	int	n1, n2;
350 
351 	if ((n1 = bt_hex_nibble(str[0])) < 0)
352 		return (-1);
353 
354 	if ((n2 = bt_hex_nibble(str[1])) < 0)
355 		return (-1);
356 
357 	return ((((n1 & 0x0f) << 4) | (n2 & 0x0f)) & 0xff);
358 }
359 
360 static int
bt_hex_nibble(char nibble)361 bt_hex_nibble(char nibble)
362 {
363 	if ('0' <= nibble && nibble <= '9')
364 		return (nibble - '0');
365 
366 	if ('a' <= nibble && nibble <= 'f')
367 		return (nibble - 'a' + 0xa);
368 
369 	if ('A' <= nibble && nibble <= 'F')
370 		return (nibble - 'A' + 0xa);
371 
372 	return (-1);
373 }
374