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