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