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