1 /*        $NetBSD: bluetooth.c,v 1.2 2024/06/18 05:13:58 rillig 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.2 2024/06/18 05:13:58 rillig 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.2 2024/06/18 05:13:58 rillig 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           const char *end;
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