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 * 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 * 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 * 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 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 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 * 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 * 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 * 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 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 268 bt_endprotoent(void) 269 { 270 if (protof != NULL) { 271 (void) fclose(protof); 272 protof = NULL; 273 } 274 } 275 276 char const * 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 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 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 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