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