1/* $NetBSD: bluetooth.c$ */ 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$"); 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 46static FILE *hostf = NULL; 47static int host_stayopen = 0; 48static struct hostent host; 49static bdaddr_t host_addr; 50static char *host_addr_ptrs[2]; 51static char *host_aliases[MAXALIASES]; 52 53static FILE *protof = NULL; 54static int proto_stayopen = 0; 55static struct protoent proto; 56static char *proto_aliases[MAXALIASES]; 57 58static char buf[BUFSIZ + 1]; 59 60static int bt_hex_byte (char const *str); 61static int bt_hex_nibble (char nibble); 62 63struct hostent * 64bt_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 } 77found: 78 bt_endhostent(); 79 80 return (p); 81} 82 83struct hostent * 84bt_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 102struct hostent * 103bt_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 } 114again: 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 156void 157bt_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 167void 168bt_endhostent(void) 169{ 170 if (hostf != NULL && host_stayopen == 0) { 171 (void) fclose(hostf); 172 hostf = NULL; 173 } 174} 175 176struct protoent * 177bt_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 } 190found: 191 bt_endprotoent(); 192 193 return (p); 194} 195 196struct protoent * 197bt_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 210struct protoent * 211bt_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); 220again: 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 256void 257bt_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 267void 268bt_endprotoent(void) 269{ 270 if (protof != NULL) { 271 (void) fclose(protof); 272 protof = NULL; 273 } 274} 275 276char const * 277bt_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 290int 291bt_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 346static int 347bt_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 360static int 361bt_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