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