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 44 static FILE *hostf = NULL; 45 static int host_stayopen = 0; 46 static struct hostent host; 47 static bdaddr_t host_addr; 48 static char *host_addr_ptrs[2]; 49 static char *host_aliases[MAXALIASES]; 50 51 static FILE *protof = NULL; 52 static int proto_stayopen = 0; 53 static struct protoent proto; 54 static char *proto_aliases[MAXALIASES]; 55 56 static char buf[BUFSIZ + 1]; 57 58 static int bt_hex_byte (char const *str); 59 static int bt_hex_nibble (char nibble); 60 61 struct hostent * 62 bt_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 } 75 found: 76 bt_endhostent(); 77 78 return (p); 79 } 80 81 struct hostent * 82 bt_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 100 struct hostent * 101 bt_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 } 112 again: 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 154 void 155 bt_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 165 void 166 bt_endhostent(void) 167 { 168 if (hostf != NULL && host_stayopen == 0) { 169 (void) fclose(hostf); 170 hostf = NULL; 171 } 172 } 173 174 struct protoent * 175 bt_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 } 188 found: 189 bt_endprotoent(); 190 191 return (p); 192 } 193 194 struct protoent * 195 bt_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 208 struct protoent * 209 bt_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); 218 again: 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 254 void 255 bt_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 265 void 266 bt_endprotoent(void) 267 { 268 if (protof != NULL) { 269 (void) fclose(protof); 270 protof = NULL; 271 } 272 } 273 274 char const * 275 bt_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 288 int 289 bt_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 344 static int 345 bt_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 358 static int 359 bt_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