xref: /dragonfly/lib/libbluetooth/bluetooth.c (revision a632cd2d33eae3cdf365948061576a303057c733)
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 <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 *
bt_gethostbyname(char const * name)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 != NULL; 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 *
bt_gethostbyaddr(void const * addr,socklen_t len,int type)81 bt_gethostbyaddr(void const *addr, socklen_t 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 && memcmp(p->h_addr, addr, len) == 0)
93                               break;
94           bt_endhostent();
95 
96           return (p);
97 }
98 
99 struct hostent *
bt_gethostent(void)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
bt_sethostent(int stayopen)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
bt_endhostent(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 *
bt_getprotobyname(char const * name)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 != NULL; 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 *
bt_getprotobynumber(int num)194 bt_getprotobynumber(int num)
195 {
196           struct protoent     *p;
197 
198           bt_setprotoent(proto_stayopen);
199           while ((p = bt_getprotoent()) != NULL)
200                     if (p->p_proto == num)
201                               break;
202           bt_endprotoent();
203 
204           return (p);
205 }
206 
207 struct protoent *
bt_getprotoent(void)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 = (int)strtol(cp, NULL, 0);
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
bt_setprotoent(int stayopen)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
bt_endprotoent(void)265 bt_endprotoent(void)
266 {
267           if (protof != NULL) {
268                     (void) fclose(protof);
269                     protof = NULL;
270           }
271 }
272 
273 char const *
bt_ntoa(bdaddr_t const * ba,char * str)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
bt_aton(char const * str,bdaddr_t * ba)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
bt_hex_byte(char const * str)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
bt_hex_nibble(char nibble)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