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