xref: /freebsd-src/lib/libbluetooth/bluetooth.c (revision 42b388439bd3795e09258c57a74ce9eec3651c7b)
10986ab12SMaksim Yevmenkin /*
20986ab12SMaksim Yevmenkin  * bluetooth.c
3baeef614SMaksim Yevmenkin  */
4baeef614SMaksim Yevmenkin 
5baeef614SMaksim Yevmenkin /*-
6*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
75e53a4f9SPedro F. Giffuni  *
8baeef614SMaksim Yevmenkin  * Copyright (c) 2001-2009 Maksim Yevmenkin <m_evmenkin@yahoo.com>
90986ab12SMaksim Yevmenkin  * All rights reserved.
100986ab12SMaksim Yevmenkin  *
110986ab12SMaksim Yevmenkin  * Redistribution and use in source and binary forms, with or without
120986ab12SMaksim Yevmenkin  * modification, are permitted provided that the following conditions
130986ab12SMaksim Yevmenkin  * are met:
140986ab12SMaksim Yevmenkin  * 1. Redistributions of source code must retain the above copyright
150986ab12SMaksim Yevmenkin  *    notice, this list of conditions and the following disclaimer.
160986ab12SMaksim Yevmenkin  * 2. Redistributions in binary form must reproduce the above copyright
170986ab12SMaksim Yevmenkin  *    notice, this list of conditions and the following disclaimer in the
180986ab12SMaksim Yevmenkin  *    documentation and/or other materials provided with the distribution.
190986ab12SMaksim Yevmenkin  *
200986ab12SMaksim Yevmenkin  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
210986ab12SMaksim Yevmenkin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
220986ab12SMaksim Yevmenkin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
230986ab12SMaksim Yevmenkin  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
240986ab12SMaksim Yevmenkin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
250986ab12SMaksim Yevmenkin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
260986ab12SMaksim Yevmenkin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
270986ab12SMaksim Yevmenkin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
280986ab12SMaksim Yevmenkin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
290986ab12SMaksim Yevmenkin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
300986ab12SMaksim Yevmenkin  * SUCH DAMAGE.
310986ab12SMaksim Yevmenkin  *
320986ab12SMaksim Yevmenkin  * $Id: bluetooth.c,v 1.3 2003/05/20 23:04:30 max Exp $
330986ab12SMaksim Yevmenkin  */
348d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED
350986ab12SMaksim Yevmenkin #include <bluetooth.h>
360986ab12SMaksim Yevmenkin #include <stdio.h>
370986ab12SMaksim Yevmenkin #include <stdlib.h>
380986ab12SMaksim Yevmenkin #include <string.h>
390986ab12SMaksim Yevmenkin 
400986ab12SMaksim Yevmenkin #define _PATH_BT_HOSTS		"/etc/bluetooth/hosts"
410986ab12SMaksim Yevmenkin #define _PATH_BT_PROTOCOLS	"/etc/bluetooth/protocols"
420986ab12SMaksim Yevmenkin #define MAXALIASES		 35
430986ab12SMaksim Yevmenkin 
440986ab12SMaksim Yevmenkin static FILE		*hostf = NULL;
450986ab12SMaksim Yevmenkin static int		 host_stayopen = 0;
460986ab12SMaksim Yevmenkin static struct hostent	 host;
470986ab12SMaksim Yevmenkin static bdaddr_t		 host_addr;
480986ab12SMaksim Yevmenkin static char		*host_addr_ptrs[2];
490986ab12SMaksim Yevmenkin static char		*host_aliases[MAXALIASES];
500986ab12SMaksim Yevmenkin 
510986ab12SMaksim Yevmenkin static FILE		*protof = NULL;
520986ab12SMaksim Yevmenkin static int		 proto_stayopen = 0;
530986ab12SMaksim Yevmenkin static struct protoent	 proto;
540986ab12SMaksim Yevmenkin static char		*proto_aliases[MAXALIASES];
550986ab12SMaksim Yevmenkin 
560986ab12SMaksim Yevmenkin static char		 buf[BUFSIZ + 1];
570986ab12SMaksim Yevmenkin 
580986ab12SMaksim Yevmenkin static int bt_hex_byte   (char const *str);
590986ab12SMaksim Yevmenkin static int bt_hex_nibble (char nibble);
600986ab12SMaksim Yevmenkin 
610986ab12SMaksim Yevmenkin struct hostent *
bt_gethostbyname(char const * name)620986ab12SMaksim Yevmenkin bt_gethostbyname(char const *name)
630986ab12SMaksim Yevmenkin {
640986ab12SMaksim Yevmenkin 	struct hostent	*p;
650986ab12SMaksim Yevmenkin 	char		**cp;
660986ab12SMaksim Yevmenkin 
670986ab12SMaksim Yevmenkin 	bt_sethostent(host_stayopen);
680986ab12SMaksim Yevmenkin 	while ((p = bt_gethostent()) != NULL) {
690986ab12SMaksim Yevmenkin 		if (strcasecmp(p->h_name, name) == 0)
700986ab12SMaksim Yevmenkin 			break;
715eadfbfcSPedro F. Giffuni 		for (cp = p->h_aliases; *cp != NULL; cp++)
720986ab12SMaksim Yevmenkin 			if (strcasecmp(*cp, name) == 0)
730986ab12SMaksim Yevmenkin 				goto found;
740986ab12SMaksim Yevmenkin 	}
750986ab12SMaksim Yevmenkin found:
760986ab12SMaksim Yevmenkin 	bt_endhostent();
770986ab12SMaksim Yevmenkin 
780986ab12SMaksim Yevmenkin 	return (p);
790986ab12SMaksim Yevmenkin }
800986ab12SMaksim Yevmenkin 
810986ab12SMaksim Yevmenkin struct hostent *
bt_gethostbyaddr(char const * addr,int len,int type)820986ab12SMaksim Yevmenkin bt_gethostbyaddr(char const *addr, int len, int type)
830986ab12SMaksim Yevmenkin {
840986ab12SMaksim Yevmenkin 	struct hostent	*p;
850986ab12SMaksim Yevmenkin 
860986ab12SMaksim Yevmenkin 	if (type != AF_BLUETOOTH || len != sizeof(bdaddr_t)) {
870986ab12SMaksim Yevmenkin 		h_errno = NO_RECOVERY;
880986ab12SMaksim Yevmenkin 		return (NULL);
890986ab12SMaksim Yevmenkin 	}
900986ab12SMaksim Yevmenkin 
910986ab12SMaksim Yevmenkin 	bt_sethostent(host_stayopen);
920986ab12SMaksim Yevmenkin 	while ((p = bt_gethostent()) != NULL)
930986ab12SMaksim Yevmenkin 		if (p->h_addrtype == type && bcmp(p->h_addr, addr, len) == 0)
940986ab12SMaksim Yevmenkin 			break;
950986ab12SMaksim Yevmenkin 	bt_endhostent();
960986ab12SMaksim Yevmenkin 
970986ab12SMaksim Yevmenkin 	return (p);
980986ab12SMaksim Yevmenkin }
990986ab12SMaksim Yevmenkin 
1000986ab12SMaksim Yevmenkin struct hostent *
bt_gethostent(void)1010986ab12SMaksim Yevmenkin bt_gethostent(void)
1020986ab12SMaksim Yevmenkin {
1030986ab12SMaksim Yevmenkin 	char	*p, *cp, **q;
1040986ab12SMaksim Yevmenkin 
1050986ab12SMaksim Yevmenkin 	if (hostf == NULL)
1060986ab12SMaksim Yevmenkin 		hostf = fopen(_PATH_BT_HOSTS, "r");
1070986ab12SMaksim Yevmenkin 
1080986ab12SMaksim Yevmenkin 	if (hostf == NULL) {
1090986ab12SMaksim Yevmenkin 		h_errno = NETDB_INTERNAL;
1100986ab12SMaksim Yevmenkin 		return (NULL);
1110986ab12SMaksim Yevmenkin 	}
1120986ab12SMaksim Yevmenkin again:
1130986ab12SMaksim Yevmenkin 	if ((p = fgets(buf, sizeof(buf), hostf)) == NULL) {
1140986ab12SMaksim Yevmenkin 		h_errno = HOST_NOT_FOUND;
1150986ab12SMaksim Yevmenkin 		return (NULL);
1160986ab12SMaksim Yevmenkin 	}
1170986ab12SMaksim Yevmenkin 	if (*p == '#')
1180986ab12SMaksim Yevmenkin 		goto again;
1190986ab12SMaksim Yevmenkin 	if ((cp = strpbrk(p, "#\n")) == NULL)
1200986ab12SMaksim Yevmenkin 		goto again;
1210986ab12SMaksim Yevmenkin 	*cp = 0;
1220986ab12SMaksim Yevmenkin 	if ((cp = strpbrk(p, " \t")) == NULL)
1230986ab12SMaksim Yevmenkin 		goto again;
1240986ab12SMaksim Yevmenkin 	*cp++ = 0;
1250986ab12SMaksim Yevmenkin 	if (bt_aton(p, &host_addr) == 0)
1260986ab12SMaksim Yevmenkin 		goto again;
1270986ab12SMaksim Yevmenkin 	host_addr_ptrs[0] = (char *) &host_addr;
1280986ab12SMaksim Yevmenkin 	host_addr_ptrs[1] = NULL;
1290986ab12SMaksim Yevmenkin 	host.h_addr_list = host_addr_ptrs;
1300986ab12SMaksim Yevmenkin 	host.h_length = sizeof(host_addr);
1310986ab12SMaksim Yevmenkin 	host.h_addrtype = AF_BLUETOOTH;
1320986ab12SMaksim Yevmenkin 	while (*cp == ' ' || *cp == '\t')
1330986ab12SMaksim Yevmenkin 		cp++;
1340986ab12SMaksim Yevmenkin 	host.h_name = cp;
1350986ab12SMaksim Yevmenkin 	q = host.h_aliases = host_aliases;
1360986ab12SMaksim Yevmenkin 	if ((cp = strpbrk(cp, " \t")) != NULL)
1370986ab12SMaksim Yevmenkin 		*cp++ = 0;
1380986ab12SMaksim Yevmenkin 	while (cp != NULL && *cp != 0) {
1390986ab12SMaksim Yevmenkin 		if (*cp == ' ' || *cp == '\t') {
1400986ab12SMaksim Yevmenkin 			cp++;
1410986ab12SMaksim Yevmenkin 			continue;
1420986ab12SMaksim Yevmenkin 		}
1430986ab12SMaksim Yevmenkin 		if (q < &host_aliases[MAXALIASES - 1])
1440986ab12SMaksim Yevmenkin 			*q++ = cp;
1450986ab12SMaksim Yevmenkin 		if ((cp = strpbrk(cp, " \t")) != NULL)
1460986ab12SMaksim Yevmenkin 			*cp++ = 0;
1470986ab12SMaksim Yevmenkin 	}
1480986ab12SMaksim Yevmenkin 	*q = NULL;
1490986ab12SMaksim Yevmenkin 	h_errno = NETDB_SUCCESS;
1500986ab12SMaksim Yevmenkin 
1510986ab12SMaksim Yevmenkin 	return (&host);
1520986ab12SMaksim Yevmenkin }
1530986ab12SMaksim Yevmenkin 
1540986ab12SMaksim Yevmenkin void
bt_sethostent(int stayopen)1550986ab12SMaksim Yevmenkin bt_sethostent(int stayopen)
1560986ab12SMaksim Yevmenkin {
1570986ab12SMaksim Yevmenkin 	if (hostf == NULL)
1580986ab12SMaksim Yevmenkin 		hostf = fopen(_PATH_BT_HOSTS, "r");
1590986ab12SMaksim Yevmenkin 	else
1600986ab12SMaksim Yevmenkin 		rewind(hostf);
1610986ab12SMaksim Yevmenkin 
1620986ab12SMaksim Yevmenkin 	host_stayopen = stayopen;
1630986ab12SMaksim Yevmenkin }
1640986ab12SMaksim Yevmenkin 
1650986ab12SMaksim Yevmenkin void
bt_endhostent(void)1660986ab12SMaksim Yevmenkin bt_endhostent(void)
1670986ab12SMaksim Yevmenkin {
1680986ab12SMaksim Yevmenkin 	if (hostf != NULL && host_stayopen == 0) {
1690986ab12SMaksim Yevmenkin 		(void) fclose(hostf);
1700986ab12SMaksim Yevmenkin 		hostf = NULL;
1710986ab12SMaksim Yevmenkin 	}
1720986ab12SMaksim Yevmenkin }
1730986ab12SMaksim Yevmenkin 
1740986ab12SMaksim Yevmenkin struct protoent *
bt_getprotobyname(char const * name)1750986ab12SMaksim Yevmenkin bt_getprotobyname(char const *name)
1760986ab12SMaksim Yevmenkin {
1770986ab12SMaksim Yevmenkin 	struct protoent	 *p;
1780986ab12SMaksim Yevmenkin 	char		**cp;
1790986ab12SMaksim Yevmenkin 
1800986ab12SMaksim Yevmenkin 	bt_setprotoent(proto_stayopen);
1810986ab12SMaksim Yevmenkin 	while ((p = bt_getprotoent()) != NULL) {
1820986ab12SMaksim Yevmenkin 		if (strcmp(p->p_name, name) == 0)
1830986ab12SMaksim Yevmenkin 			break;
1845eadfbfcSPedro F. Giffuni 		for (cp = p->p_aliases; *cp != NULL; cp++)
1850986ab12SMaksim Yevmenkin 			if (strcmp(*cp, name) == 0)
1860986ab12SMaksim Yevmenkin 				goto found;
1870986ab12SMaksim Yevmenkin 	}
1880986ab12SMaksim Yevmenkin found:
1890986ab12SMaksim Yevmenkin 	bt_endprotoent();
1900986ab12SMaksim Yevmenkin 
1910986ab12SMaksim Yevmenkin 	return (p);
1920986ab12SMaksim Yevmenkin }
1930986ab12SMaksim Yevmenkin 
1940986ab12SMaksim Yevmenkin struct protoent *
bt_getprotobynumber(int proto)1950986ab12SMaksim Yevmenkin bt_getprotobynumber(int proto)
1960986ab12SMaksim Yevmenkin {
1970986ab12SMaksim Yevmenkin 	struct protoent	*p;
1980986ab12SMaksim Yevmenkin 
1990986ab12SMaksim Yevmenkin 	bt_setprotoent(proto_stayopen);
2000986ab12SMaksim Yevmenkin 	while ((p = bt_getprotoent()) != NULL)
2010986ab12SMaksim Yevmenkin 		if (p->p_proto == proto)
2020986ab12SMaksim Yevmenkin 			break;
2030986ab12SMaksim Yevmenkin 	bt_endprotoent();
2040986ab12SMaksim Yevmenkin 
2050986ab12SMaksim Yevmenkin 	return (p);
2060986ab12SMaksim Yevmenkin }
2070986ab12SMaksim Yevmenkin 
2080986ab12SMaksim Yevmenkin struct protoent *
bt_getprotoent(void)2090986ab12SMaksim Yevmenkin bt_getprotoent(void)
2100986ab12SMaksim Yevmenkin {
2110986ab12SMaksim Yevmenkin 	char	*p, *cp, **q;
2120986ab12SMaksim Yevmenkin 
2130986ab12SMaksim Yevmenkin 	if (protof == NULL)
2140986ab12SMaksim Yevmenkin 		protof = fopen(_PATH_BT_PROTOCOLS, "r");
2150986ab12SMaksim Yevmenkin 
2160986ab12SMaksim Yevmenkin 	if (protof == NULL)
2170986ab12SMaksim Yevmenkin 		return (NULL);
2180986ab12SMaksim Yevmenkin again:
2190986ab12SMaksim Yevmenkin 	if ((p = fgets(buf, sizeof(buf), protof)) == NULL)
2200986ab12SMaksim Yevmenkin 		return (NULL);
2210986ab12SMaksim Yevmenkin 	if (*p == '#')
2220986ab12SMaksim Yevmenkin 		goto again;
2230986ab12SMaksim Yevmenkin 	if ((cp = strpbrk(p, "#\n")) == NULL)
2240986ab12SMaksim Yevmenkin 		goto again;
2250986ab12SMaksim Yevmenkin 	*cp = '\0';
2260986ab12SMaksim Yevmenkin 	proto.p_name = p;
2270986ab12SMaksim Yevmenkin 	if ((cp = strpbrk(p, " \t")) == NULL)
2280986ab12SMaksim Yevmenkin 		goto again;
2290986ab12SMaksim Yevmenkin 	*cp++ = '\0';
2300986ab12SMaksim Yevmenkin 	while (*cp == ' ' || *cp == '\t')
2310986ab12SMaksim Yevmenkin 		cp++;
2320986ab12SMaksim Yevmenkin 	if ((p = strpbrk(cp, " \t")) != NULL)
2330986ab12SMaksim Yevmenkin 		*p++ = '\0';
2340986ab12SMaksim Yevmenkin 	proto.p_proto = atoi(cp);
2350986ab12SMaksim Yevmenkin 	q = proto.p_aliases = proto_aliases;
2360986ab12SMaksim Yevmenkin 	if (p != NULL) {
2370986ab12SMaksim Yevmenkin 		cp = p;
2380986ab12SMaksim Yevmenkin 		while (cp != NULL && *cp != 0) {
2390986ab12SMaksim Yevmenkin 			if (*cp == ' ' || *cp == '\t') {
2400986ab12SMaksim Yevmenkin 				cp++;
2410986ab12SMaksim Yevmenkin 				continue;
2420986ab12SMaksim Yevmenkin 			}
2430986ab12SMaksim Yevmenkin 			if (q < &proto_aliases[MAXALIASES - 1])
2440986ab12SMaksim Yevmenkin 				*q++ = cp;
2450986ab12SMaksim Yevmenkin 			if ((cp = strpbrk(cp, " \t")) != NULL)
2460986ab12SMaksim Yevmenkin 				*cp++ = '\0';
2470986ab12SMaksim Yevmenkin 		}
2480986ab12SMaksim Yevmenkin 	}
2490986ab12SMaksim Yevmenkin 	*q = NULL;
2500986ab12SMaksim Yevmenkin 
2510986ab12SMaksim Yevmenkin 	return (&proto);
2520986ab12SMaksim Yevmenkin }
2530986ab12SMaksim Yevmenkin 
2540986ab12SMaksim Yevmenkin void
bt_setprotoent(int stayopen)2550986ab12SMaksim Yevmenkin bt_setprotoent(int stayopen)
2560986ab12SMaksim Yevmenkin {
2570986ab12SMaksim Yevmenkin 	if (protof == NULL)
2580986ab12SMaksim Yevmenkin 		protof = fopen(_PATH_BT_PROTOCOLS, "r");
2590986ab12SMaksim Yevmenkin 	else
2600986ab12SMaksim Yevmenkin 		rewind(protof);
2610986ab12SMaksim Yevmenkin 
2620986ab12SMaksim Yevmenkin 	proto_stayopen = stayopen;
2630986ab12SMaksim Yevmenkin }
2640986ab12SMaksim Yevmenkin 
2650986ab12SMaksim Yevmenkin void
bt_endprotoent(void)2660986ab12SMaksim Yevmenkin bt_endprotoent(void)
2670986ab12SMaksim Yevmenkin {
2680986ab12SMaksim Yevmenkin 	if (protof != NULL) {
2690986ab12SMaksim Yevmenkin 		(void) fclose(protof);
2700986ab12SMaksim Yevmenkin 		protof = NULL;
2710986ab12SMaksim Yevmenkin 	}
2720986ab12SMaksim Yevmenkin }
2730986ab12SMaksim Yevmenkin 
2740986ab12SMaksim Yevmenkin char const *
bt_ntoa(bdaddr_t const * ba,char * str)2750986ab12SMaksim Yevmenkin bt_ntoa(bdaddr_t const *ba, char *str)
2760986ab12SMaksim Yevmenkin {
2770986ab12SMaksim Yevmenkin 	static char	buffer[24];
2780986ab12SMaksim Yevmenkin 
2790986ab12SMaksim Yevmenkin 	if (str == NULL)
2800986ab12SMaksim Yevmenkin 		str = buffer;
2810986ab12SMaksim Yevmenkin 
2820986ab12SMaksim Yevmenkin 	sprintf(str, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
2830986ab12SMaksim Yevmenkin 		ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
2840986ab12SMaksim Yevmenkin 
2850986ab12SMaksim Yevmenkin 	return (str);
2860986ab12SMaksim Yevmenkin }
2870986ab12SMaksim Yevmenkin 
2880986ab12SMaksim Yevmenkin int
bt_aton(char const * str,bdaddr_t * ba)2890986ab12SMaksim Yevmenkin bt_aton(char const *str, bdaddr_t *ba)
2900986ab12SMaksim Yevmenkin {
2910986ab12SMaksim Yevmenkin 	int	 i, b;
2920986ab12SMaksim Yevmenkin 	char	*end = NULL;
2930986ab12SMaksim Yevmenkin 
2940986ab12SMaksim Yevmenkin 	memset(ba, 0, sizeof(*ba));
2950986ab12SMaksim Yevmenkin 
2960986ab12SMaksim Yevmenkin 	for (i = 5, end = strchr(str, ':');
29716fc3635SMark Murray 	     i > 0 && *str != '\0' && end != NULL;
2980986ab12SMaksim Yevmenkin 	     i --, str = end + 1, end = strchr(str, ':')) {
2990986ab12SMaksim Yevmenkin 		switch (end - str) {
3000986ab12SMaksim Yevmenkin 		case 1:
3010986ab12SMaksim Yevmenkin 			b = bt_hex_nibble(str[0]);
3020986ab12SMaksim Yevmenkin 			break;
3030986ab12SMaksim Yevmenkin 
3040986ab12SMaksim Yevmenkin 		case 2:
3050986ab12SMaksim Yevmenkin 			b = bt_hex_byte(str);
3060986ab12SMaksim Yevmenkin 			break;
3070986ab12SMaksim Yevmenkin 
3080986ab12SMaksim Yevmenkin 		default:
3090986ab12SMaksim Yevmenkin 			b = -1;
3100986ab12SMaksim Yevmenkin 			break;
3110986ab12SMaksim Yevmenkin 		}
3120986ab12SMaksim Yevmenkin 
3130986ab12SMaksim Yevmenkin 		if (b < 0)
3140986ab12SMaksim Yevmenkin 			return (0);
3150986ab12SMaksim Yevmenkin 
3160986ab12SMaksim Yevmenkin 		ba->b[i] = b;
3170986ab12SMaksim Yevmenkin 	}
3180986ab12SMaksim Yevmenkin 
3190986ab12SMaksim Yevmenkin 	if (i != 0 || end != NULL || *str == 0)
3200986ab12SMaksim Yevmenkin 		return (0);
3210986ab12SMaksim Yevmenkin 
3220986ab12SMaksim Yevmenkin 	switch (strlen(str)) {
3230986ab12SMaksim Yevmenkin 	case 1:
3240986ab12SMaksim Yevmenkin 		b = bt_hex_nibble(str[0]);
3250986ab12SMaksim Yevmenkin 		break;
3260986ab12SMaksim Yevmenkin 
3270986ab12SMaksim Yevmenkin 	case 2:
3280986ab12SMaksim Yevmenkin 		b = bt_hex_byte(str);
3290986ab12SMaksim Yevmenkin 		break;
3300986ab12SMaksim Yevmenkin 
3310986ab12SMaksim Yevmenkin 	default:
3320986ab12SMaksim Yevmenkin 		b = -1;
3330986ab12SMaksim Yevmenkin 		break;
3340986ab12SMaksim Yevmenkin 	}
3350986ab12SMaksim Yevmenkin 
3360986ab12SMaksim Yevmenkin 	if (b < 0)
3370986ab12SMaksim Yevmenkin 		return (0);
3380986ab12SMaksim Yevmenkin 
3390986ab12SMaksim Yevmenkin 	ba->b[i] = b;
3400986ab12SMaksim Yevmenkin 
3410986ab12SMaksim Yevmenkin 	return (1);
3420986ab12SMaksim Yevmenkin }
3430986ab12SMaksim Yevmenkin 
3440986ab12SMaksim Yevmenkin static int
bt_hex_byte(char const * str)3450986ab12SMaksim Yevmenkin bt_hex_byte(char const *str)
3460986ab12SMaksim Yevmenkin {
3470986ab12SMaksim Yevmenkin 	int	n1, n2;
3480986ab12SMaksim Yevmenkin 
3490986ab12SMaksim Yevmenkin 	if ((n1 = bt_hex_nibble(str[0])) < 0)
3500986ab12SMaksim Yevmenkin 		return (-1);
3510986ab12SMaksim Yevmenkin 
3520986ab12SMaksim Yevmenkin 	if ((n2 = bt_hex_nibble(str[1])) < 0)
3530986ab12SMaksim Yevmenkin 		return (-1);
3540986ab12SMaksim Yevmenkin 
3550986ab12SMaksim Yevmenkin 	return ((((n1 & 0x0f) << 4) | (n2 & 0x0f)) & 0xff);
3560986ab12SMaksim Yevmenkin }
3570986ab12SMaksim Yevmenkin 
3580986ab12SMaksim Yevmenkin static int
bt_hex_nibble(char nibble)3590986ab12SMaksim Yevmenkin bt_hex_nibble(char nibble)
3600986ab12SMaksim Yevmenkin {
3610986ab12SMaksim Yevmenkin 	if ('0' <= nibble && nibble <= '9')
3620986ab12SMaksim Yevmenkin 		return (nibble - '0');
3630986ab12SMaksim Yevmenkin 
3640986ab12SMaksim Yevmenkin 	if ('a' <= nibble && nibble <= 'f')
3650986ab12SMaksim Yevmenkin 		return (nibble - 'a' + 0xa);
3660986ab12SMaksim Yevmenkin 
3670986ab12SMaksim Yevmenkin 	if ('A' <= nibble && nibble <= 'F')
3680986ab12SMaksim Yevmenkin 		return (nibble - 'A' + 0xa);
3690986ab12SMaksim Yevmenkin 
3700986ab12SMaksim Yevmenkin 	return (-1);
3710986ab12SMaksim Yevmenkin }
3720986ab12SMaksim Yevmenkin 
373