1 /* 2 * bluetooth.c 3 */ 4 5 /*- 6 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 * $FreeBSD$ 34 */ 35 #define L2CAP_SOCKET_CHECKED 36 #include <bluetooth.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 41 #define _PATH_BT_HOSTS "/etc/bluetooth/hosts" 42 #define _PATH_BT_PROTOCOLS "/etc/bluetooth/protocols" 43 #define MAXALIASES 35 44 45 static FILE *hostf = NULL; 46 static int host_stayopen = 0; 47 static struct hostent host; 48 static bdaddr_t host_addr; 49 static char *host_addr_ptrs[2]; 50 static char *host_aliases[MAXALIASES]; 51 52 static FILE *protof = NULL; 53 static int proto_stayopen = 0; 54 static struct protoent proto; 55 static char *proto_aliases[MAXALIASES]; 56 57 static char buf[BUFSIZ + 1]; 58 59 static int bt_hex_byte (char const *str); 60 static int bt_hex_nibble (char nibble); 61 62 struct hostent * 63 bt_gethostbyname(char const *name) 64 { 65 struct hostent *p; 66 char **cp; 67 68 bt_sethostent(host_stayopen); 69 while ((p = bt_gethostent()) != NULL) { 70 if (strcasecmp(p->h_name, name) == 0) 71 break; 72 for (cp = p->h_aliases; *cp != NULL; cp++) 73 if (strcasecmp(*cp, name) == 0) 74 goto found; 75 } 76 found: 77 bt_endhostent(); 78 79 return (p); 80 } 81 82 struct hostent * 83 bt_gethostbyaddr(char const *addr, int len, int type) 84 { 85 struct hostent *p; 86 87 if (type != AF_BLUETOOTH || len != sizeof(bdaddr_t)) { 88 h_errno = NO_RECOVERY; 89 return (NULL); 90 } 91 92 bt_sethostent(host_stayopen); 93 while ((p = bt_gethostent()) != NULL) 94 if (p->h_addrtype == type && bcmp(p->h_addr, addr, len) == 0) 95 break; 96 bt_endhostent(); 97 98 return (p); 99 } 100 101 struct hostent * 102 bt_gethostent(void) 103 { 104 char *p, *cp, **q; 105 106 if (hostf == NULL) 107 hostf = fopen(_PATH_BT_HOSTS, "r"); 108 109 if (hostf == NULL) { 110 h_errno = NETDB_INTERNAL; 111 return (NULL); 112 } 113 again: 114 if ((p = fgets(buf, sizeof(buf), hostf)) == NULL) { 115 h_errno = HOST_NOT_FOUND; 116 return (NULL); 117 } 118 if (*p == '#') 119 goto again; 120 if ((cp = strpbrk(p, "#\n")) == NULL) 121 goto again; 122 *cp = 0; 123 if ((cp = strpbrk(p, " \t")) == NULL) 124 goto again; 125 *cp++ = 0; 126 if (bt_aton(p, &host_addr) == 0) 127 goto again; 128 host_addr_ptrs[0] = (char *) &host_addr; 129 host_addr_ptrs[1] = NULL; 130 host.h_addr_list = host_addr_ptrs; 131 host.h_length = sizeof(host_addr); 132 host.h_addrtype = AF_BLUETOOTH; 133 while (*cp == ' ' || *cp == '\t') 134 cp++; 135 host.h_name = cp; 136 q = host.h_aliases = host_aliases; 137 if ((cp = strpbrk(cp, " \t")) != NULL) 138 *cp++ = 0; 139 while (cp != NULL && *cp != 0) { 140 if (*cp == ' ' || *cp == '\t') { 141 cp++; 142 continue; 143 } 144 if (q < &host_aliases[MAXALIASES - 1]) 145 *q++ = cp; 146 if ((cp = strpbrk(cp, " \t")) != NULL) 147 *cp++ = 0; 148 } 149 *q = NULL; 150 h_errno = NETDB_SUCCESS; 151 152 return (&host); 153 } 154 155 void 156 bt_sethostent(int stayopen) 157 { 158 if (hostf == NULL) 159 hostf = fopen(_PATH_BT_HOSTS, "r"); 160 else 161 rewind(hostf); 162 163 host_stayopen = stayopen; 164 } 165 166 void 167 bt_endhostent(void) 168 { 169 if (hostf != NULL && host_stayopen == 0) { 170 (void) fclose(hostf); 171 hostf = NULL; 172 } 173 } 174 175 struct protoent * 176 bt_getprotobyname(char const *name) 177 { 178 struct protoent *p; 179 char **cp; 180 181 bt_setprotoent(proto_stayopen); 182 while ((p = bt_getprotoent()) != NULL) { 183 if (strcmp(p->p_name, name) == 0) 184 break; 185 for (cp = p->p_aliases; *cp != NULL; cp++) 186 if (strcmp(*cp, name) == 0) 187 goto found; 188 } 189 found: 190 bt_endprotoent(); 191 192 return (p); 193 } 194 195 struct protoent * 196 bt_getprotobynumber(int proto) 197 { 198 struct protoent *p; 199 200 bt_setprotoent(proto_stayopen); 201 while ((p = bt_getprotoent()) != NULL) 202 if (p->p_proto == proto) 203 break; 204 bt_endprotoent(); 205 206 return (p); 207 } 208 209 struct protoent * 210 bt_getprotoent(void) 211 { 212 char *p, *cp, **q; 213 214 if (protof == NULL) 215 protof = fopen(_PATH_BT_PROTOCOLS, "r"); 216 217 if (protof == NULL) 218 return (NULL); 219 again: 220 if ((p = fgets(buf, sizeof(buf), protof)) == NULL) 221 return (NULL); 222 if (*p == '#') 223 goto again; 224 if ((cp = strpbrk(p, "#\n")) == NULL) 225 goto again; 226 *cp = '\0'; 227 proto.p_name = p; 228 if ((cp = strpbrk(p, " \t")) == NULL) 229 goto again; 230 *cp++ = '\0'; 231 while (*cp == ' ' || *cp == '\t') 232 cp++; 233 if ((p = strpbrk(cp, " \t")) != NULL) 234 *p++ = '\0'; 235 proto.p_proto = atoi(cp); 236 q = proto.p_aliases = proto_aliases; 237 if (p != NULL) { 238 cp = p; 239 while (cp != NULL && *cp != 0) { 240 if (*cp == ' ' || *cp == '\t') { 241 cp++; 242 continue; 243 } 244 if (q < &proto_aliases[MAXALIASES - 1]) 245 *q++ = cp; 246 if ((cp = strpbrk(cp, " \t")) != NULL) 247 *cp++ = '\0'; 248 } 249 } 250 *q = NULL; 251 252 return (&proto); 253 } 254 255 void 256 bt_setprotoent(int stayopen) 257 { 258 if (protof == NULL) 259 protof = fopen(_PATH_BT_PROTOCOLS, "r"); 260 else 261 rewind(protof); 262 263 proto_stayopen = stayopen; 264 } 265 266 void 267 bt_endprotoent(void) 268 { 269 if (protof != NULL) { 270 (void) fclose(protof); 271 protof = NULL; 272 } 273 } 274 275 char const * 276 bt_ntoa(bdaddr_t const *ba, char *str) 277 { 278 static char buffer[24]; 279 280 if (str == NULL) 281 str = buffer; 282 283 sprintf(str, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x", 284 ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]); 285 286 return (str); 287 } 288 289 int 290 bt_aton(char const *str, bdaddr_t *ba) 291 { 292 int i, b; 293 char *end = NULL; 294 295 memset(ba, 0, sizeof(*ba)); 296 297 for (i = 5, end = strchr(str, ':'); 298 i > 0 && *str != '\0' && end != NULL; 299 i --, str = end + 1, end = strchr(str, ':')) { 300 switch (end - str) { 301 case 1: 302 b = bt_hex_nibble(str[0]); 303 break; 304 305 case 2: 306 b = bt_hex_byte(str); 307 break; 308 309 default: 310 b = -1; 311 break; 312 } 313 314 if (b < 0) 315 return (0); 316 317 ba->b[i] = b; 318 } 319 320 if (i != 0 || end != NULL || *str == 0) 321 return (0); 322 323 switch (strlen(str)) { 324 case 1: 325 b = bt_hex_nibble(str[0]); 326 break; 327 328 case 2: 329 b = bt_hex_byte(str); 330 break; 331 332 default: 333 b = -1; 334 break; 335 } 336 337 if (b < 0) 338 return (0); 339 340 ba->b[i] = b; 341 342 return (1); 343 } 344 345 static int 346 bt_hex_byte(char const *str) 347 { 348 int n1, n2; 349 350 if ((n1 = bt_hex_nibble(str[0])) < 0) 351 return (-1); 352 353 if ((n2 = bt_hex_nibble(str[1])) < 0) 354 return (-1); 355 356 return ((((n1 & 0x0f) << 4) | (n2 & 0x0f)) & 0xff); 357 } 358 359 static int 360 bt_hex_nibble(char nibble) 361 { 362 if ('0' <= nibble && nibble <= '9') 363 return (nibble - '0'); 364 365 if ('a' <= nibble && nibble <= 'f') 366 return (nibble - 'a' + 0xa); 367 368 if ('A' <= nibble && nibble <= 'F') 369 return (nibble - 'A' + 0xa); 370 371 return (-1); 372 } 373 374