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