137f60ad1SHasso Tepper /* $NetBSD: bluetooth.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $ */
237f60ad1SHasso Tepper
337f60ad1SHasso Tepper /*
437f60ad1SHasso Tepper * bluetooth.c
537f60ad1SHasso Tepper *
637f60ad1SHasso Tepper * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
737f60ad1SHasso Tepper * All rights reserved.
837f60ad1SHasso Tepper *
937f60ad1SHasso Tepper * Redistribution and use in source and binary forms, with or without
1037f60ad1SHasso Tepper * modification, are permitted provided that the following conditions
1137f60ad1SHasso Tepper * are met:
1237f60ad1SHasso Tepper * 1. Redistributions of source code must retain the above copyright
1337f60ad1SHasso Tepper * notice, this list of conditions and the following disclaimer.
1437f60ad1SHasso Tepper * 2. Redistributions in binary form must reproduce the above copyright
1537f60ad1SHasso Tepper * notice, this list of conditions and the following disclaimer in the
1637f60ad1SHasso Tepper * documentation and/or other materials provided with the distribution.
1737f60ad1SHasso Tepper *
1837f60ad1SHasso Tepper * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1937f60ad1SHasso Tepper * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2037f60ad1SHasso Tepper * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2137f60ad1SHasso Tepper * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2237f60ad1SHasso Tepper * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2337f60ad1SHasso Tepper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2437f60ad1SHasso Tepper * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2537f60ad1SHasso Tepper * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2637f60ad1SHasso Tepper * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2737f60ad1SHasso Tepper * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2837f60ad1SHasso Tepper * SUCH DAMAGE.
2937f60ad1SHasso Tepper *
3037f60ad1SHasso Tepper * $Id: bluetooth.c,v 1.1 2006/06/19 15:44:36 gdamore Exp $
3137f60ad1SHasso Tepper * $FreeBSD: src/lib/libbluetooth/bluetooth.c,v 1.2 2004/03/05 08:10:17 markm Exp $
3237f60ad1SHasso Tepper */
3337f60ad1SHasso Tepper
3437f60ad1SHasso Tepper #include <bluetooth.h>
3537f60ad1SHasso Tepper #include <stdio.h>
3637f60ad1SHasso Tepper #include <stdlib.h>
3737f60ad1SHasso Tepper #include <string.h>
3837f60ad1SHasso Tepper
3937f60ad1SHasso Tepper #define _PATH_BT_HOSTS "/etc/bluetooth/hosts"
4037f60ad1SHasso Tepper #define _PATH_BT_PROTOCOLS "/etc/bluetooth/protocols"
4137f60ad1SHasso Tepper #define MAXALIASES 35
4237f60ad1SHasso Tepper
4337f60ad1SHasso Tepper static FILE *hostf = NULL;
4437f60ad1SHasso Tepper static int host_stayopen = 0;
4537f60ad1SHasso Tepper static struct hostent host;
4637f60ad1SHasso Tepper static bdaddr_t host_addr;
4737f60ad1SHasso Tepper static char *host_addr_ptrs[2];
4837f60ad1SHasso Tepper static char *host_aliases[MAXALIASES];
4937f60ad1SHasso Tepper
5037f60ad1SHasso Tepper static FILE *protof = NULL;
5137f60ad1SHasso Tepper static int proto_stayopen = 0;
5237f60ad1SHasso Tepper static struct protoent proto;
5337f60ad1SHasso Tepper static char *proto_aliases[MAXALIASES];
5437f60ad1SHasso Tepper
5537f60ad1SHasso Tepper static char buf[BUFSIZ + 1];
5637f60ad1SHasso Tepper
5737f60ad1SHasso Tepper static int bt_hex_byte (char const *str);
5837f60ad1SHasso Tepper static int bt_hex_nibble (char nibble);
5937f60ad1SHasso Tepper
6037f60ad1SHasso Tepper struct hostent *
bt_gethostbyname(char const * name)6137f60ad1SHasso Tepper bt_gethostbyname(char const *name)
6237f60ad1SHasso Tepper {
6337f60ad1SHasso Tepper struct hostent *p;
6437f60ad1SHasso Tepper char **cp;
6537f60ad1SHasso Tepper
6637f60ad1SHasso Tepper bt_sethostent(host_stayopen);
6737f60ad1SHasso Tepper while ((p = bt_gethostent()) != NULL) {
6837f60ad1SHasso Tepper if (strcasecmp(p->h_name, name) == 0)
6937f60ad1SHasso Tepper break;
70*678e8cc6SSascha Wildner for (cp = p->h_aliases; *cp != NULL; cp++)
7137f60ad1SHasso Tepper if (strcasecmp(*cp, name) == 0)
7237f60ad1SHasso Tepper goto found;
7337f60ad1SHasso Tepper }
7437f60ad1SHasso Tepper found:
7537f60ad1SHasso Tepper bt_endhostent();
7637f60ad1SHasso Tepper
7737f60ad1SHasso Tepper return (p);
7837f60ad1SHasso Tepper }
7937f60ad1SHasso Tepper
8037f60ad1SHasso Tepper struct hostent *
bt_gethostbyaddr(void const * addr,socklen_t len,int type)8163bd4a35SSascha Wildner bt_gethostbyaddr(void const *addr, socklen_t len, int type)
8237f60ad1SHasso Tepper {
8337f60ad1SHasso Tepper struct hostent *p;
8437f60ad1SHasso Tepper
8537f60ad1SHasso Tepper if (type != AF_BLUETOOTH || len != sizeof(bdaddr_t)) {
8637f60ad1SHasso Tepper h_errno = NO_RECOVERY;
8737f60ad1SHasso Tepper return (NULL);
8837f60ad1SHasso Tepper }
8937f60ad1SHasso Tepper
9037f60ad1SHasso Tepper bt_sethostent(host_stayopen);
9137f60ad1SHasso Tepper while ((p = bt_gethostent()) != NULL)
9237f60ad1SHasso Tepper if (p->h_addrtype == type && memcmp(p->h_addr, addr, len) == 0)
9337f60ad1SHasso Tepper break;
9437f60ad1SHasso Tepper bt_endhostent();
9537f60ad1SHasso Tepper
9637f60ad1SHasso Tepper return (p);
9737f60ad1SHasso Tepper }
9837f60ad1SHasso Tepper
9937f60ad1SHasso Tepper struct hostent *
bt_gethostent(void)10037f60ad1SHasso Tepper bt_gethostent(void)
10137f60ad1SHasso Tepper {
10237f60ad1SHasso Tepper char *p, *cp, **q;
10337f60ad1SHasso Tepper
10437f60ad1SHasso Tepper if (hostf == NULL)
10537f60ad1SHasso Tepper hostf = fopen(_PATH_BT_HOSTS, "r");
10637f60ad1SHasso Tepper
10737f60ad1SHasso Tepper if (hostf == NULL) {
10837f60ad1SHasso Tepper h_errno = NETDB_INTERNAL;
10937f60ad1SHasso Tepper return (NULL);
11037f60ad1SHasso Tepper }
11137f60ad1SHasso Tepper again:
11237f60ad1SHasso Tepper if ((p = fgets(buf, sizeof(buf), hostf)) == NULL) {
11337f60ad1SHasso Tepper h_errno = HOST_NOT_FOUND;
11437f60ad1SHasso Tepper return (NULL);
11537f60ad1SHasso Tepper }
11637f60ad1SHasso Tepper if (*p == '#')
11737f60ad1SHasso Tepper goto again;
11837f60ad1SHasso Tepper if ((cp = strpbrk(p, "#\n")) == NULL)
11937f60ad1SHasso Tepper goto again;
12037f60ad1SHasso Tepper *cp = 0;
12137f60ad1SHasso Tepper if ((cp = strpbrk(p, " \t")) == NULL)
12237f60ad1SHasso Tepper goto again;
12337f60ad1SHasso Tepper *cp++ = 0;
12437f60ad1SHasso Tepper if (bt_aton(p, &host_addr) == 0)
12537f60ad1SHasso Tepper goto again;
12637f60ad1SHasso Tepper host_addr_ptrs[0] = (char *) &host_addr;
12737f60ad1SHasso Tepper host_addr_ptrs[1] = NULL;
12837f60ad1SHasso Tepper host.h_addr_list = host_addr_ptrs;
12937f60ad1SHasso Tepper host.h_length = sizeof(host_addr);
13037f60ad1SHasso Tepper host.h_addrtype = AF_BLUETOOTH;
13137f60ad1SHasso Tepper while (*cp == ' ' || *cp == '\t')
13237f60ad1SHasso Tepper cp++;
13337f60ad1SHasso Tepper host.h_name = cp;
13437f60ad1SHasso Tepper q = host.h_aliases = host_aliases;
13537f60ad1SHasso Tepper if ((cp = strpbrk(cp, " \t")) != NULL)
13637f60ad1SHasso Tepper *cp++ = 0;
13737f60ad1SHasso Tepper while (cp != NULL && *cp != 0) {
13837f60ad1SHasso Tepper if (*cp == ' ' || *cp == '\t') {
13937f60ad1SHasso Tepper cp++;
14037f60ad1SHasso Tepper continue;
14137f60ad1SHasso Tepper }
14237f60ad1SHasso Tepper if (q < &host_aliases[MAXALIASES - 1])
14337f60ad1SHasso Tepper *q++ = cp;
14437f60ad1SHasso Tepper if ((cp = strpbrk(cp, " \t")) != NULL)
14537f60ad1SHasso Tepper *cp++ = 0;
14637f60ad1SHasso Tepper }
14737f60ad1SHasso Tepper *q = NULL;
14837f60ad1SHasso Tepper h_errno = NETDB_SUCCESS;
14937f60ad1SHasso Tepper
15037f60ad1SHasso Tepper return (&host);
15137f60ad1SHasso Tepper }
15237f60ad1SHasso Tepper
15337f60ad1SHasso Tepper void
bt_sethostent(int stayopen)15437f60ad1SHasso Tepper bt_sethostent(int stayopen)
15537f60ad1SHasso Tepper {
15637f60ad1SHasso Tepper if (hostf == NULL)
15737f60ad1SHasso Tepper hostf = fopen(_PATH_BT_HOSTS, "r");
15837f60ad1SHasso Tepper else
15937f60ad1SHasso Tepper rewind(hostf);
16037f60ad1SHasso Tepper
16137f60ad1SHasso Tepper host_stayopen = stayopen;
16237f60ad1SHasso Tepper }
16337f60ad1SHasso Tepper
16437f60ad1SHasso Tepper void
bt_endhostent(void)16537f60ad1SHasso Tepper bt_endhostent(void)
16637f60ad1SHasso Tepper {
16737f60ad1SHasso Tepper if (hostf != NULL && host_stayopen == 0) {
16837f60ad1SHasso Tepper (void) fclose(hostf);
16937f60ad1SHasso Tepper hostf = NULL;
17037f60ad1SHasso Tepper }
17137f60ad1SHasso Tepper }
17237f60ad1SHasso Tepper
17337f60ad1SHasso Tepper struct protoent *
bt_getprotobyname(char const * name)17437f60ad1SHasso Tepper bt_getprotobyname(char const *name)
17537f60ad1SHasso Tepper {
17637f60ad1SHasso Tepper struct protoent *p;
17737f60ad1SHasso Tepper char **cp;
17837f60ad1SHasso Tepper
17937f60ad1SHasso Tepper bt_setprotoent(proto_stayopen);
18037f60ad1SHasso Tepper while ((p = bt_getprotoent()) != NULL) {
18137f60ad1SHasso Tepper if (strcmp(p->p_name, name) == 0)
18237f60ad1SHasso Tepper break;
183*678e8cc6SSascha Wildner for (cp = p->p_aliases; *cp != NULL; cp++)
18437f60ad1SHasso Tepper if (strcmp(*cp, name) == 0)
18537f60ad1SHasso Tepper goto found;
18637f60ad1SHasso Tepper }
18737f60ad1SHasso Tepper found:
18837f60ad1SHasso Tepper bt_endprotoent();
18937f60ad1SHasso Tepper
19037f60ad1SHasso Tepper return (p);
19137f60ad1SHasso Tepper }
19237f60ad1SHasso Tepper
19337f60ad1SHasso Tepper struct protoent *
bt_getprotobynumber(int num)19437f60ad1SHasso Tepper bt_getprotobynumber(int num)
19537f60ad1SHasso Tepper {
19637f60ad1SHasso Tepper struct protoent *p;
19737f60ad1SHasso Tepper
19837f60ad1SHasso Tepper bt_setprotoent(proto_stayopen);
19937f60ad1SHasso Tepper while ((p = bt_getprotoent()) != NULL)
20037f60ad1SHasso Tepper if (p->p_proto == num)
20137f60ad1SHasso Tepper break;
20237f60ad1SHasso Tepper bt_endprotoent();
20337f60ad1SHasso Tepper
20437f60ad1SHasso Tepper return (p);
20537f60ad1SHasso Tepper }
20637f60ad1SHasso Tepper
20737f60ad1SHasso Tepper struct protoent *
bt_getprotoent(void)20837f60ad1SHasso Tepper bt_getprotoent(void)
20937f60ad1SHasso Tepper {
21037f60ad1SHasso Tepper char *p, *cp, **q;
21137f60ad1SHasso Tepper
21237f60ad1SHasso Tepper if (protof == NULL)
21337f60ad1SHasso Tepper protof = fopen(_PATH_BT_PROTOCOLS, "r");
21437f60ad1SHasso Tepper
21537f60ad1SHasso Tepper if (protof == NULL)
21637f60ad1SHasso Tepper return (NULL);
21737f60ad1SHasso Tepper again:
21837f60ad1SHasso Tepper if ((p = fgets(buf, sizeof(buf), protof)) == NULL)
21937f60ad1SHasso Tepper return (NULL);
22037f60ad1SHasso Tepper if (*p == '#')
22137f60ad1SHasso Tepper goto again;
22237f60ad1SHasso Tepper if ((cp = strpbrk(p, "#\n")) == NULL)
22337f60ad1SHasso Tepper goto again;
22437f60ad1SHasso Tepper *cp = '\0';
22537f60ad1SHasso Tepper proto.p_name = p;
22637f60ad1SHasso Tepper if ((cp = strpbrk(p, " \t")) == NULL)
22737f60ad1SHasso Tepper goto again;
22837f60ad1SHasso Tepper *cp++ = '\0';
22937f60ad1SHasso Tepper while (*cp == ' ' || *cp == '\t')
23037f60ad1SHasso Tepper cp++;
23137f60ad1SHasso Tepper if ((p = strpbrk(cp, " \t")) != NULL)
23237f60ad1SHasso Tepper *p++ = '\0';
23337f60ad1SHasso Tepper proto.p_proto = (int)strtol(cp, NULL, 0);
23437f60ad1SHasso Tepper q = proto.p_aliases = proto_aliases;
23537f60ad1SHasso Tepper if (p != NULL) {
23637f60ad1SHasso Tepper cp = p;
23737f60ad1SHasso Tepper while (cp != NULL && *cp != 0) {
23837f60ad1SHasso Tepper if (*cp == ' ' || *cp == '\t') {
23937f60ad1SHasso Tepper cp++;
24037f60ad1SHasso Tepper continue;
24137f60ad1SHasso Tepper }
24237f60ad1SHasso Tepper if (q < &proto_aliases[MAXALIASES - 1])
24337f60ad1SHasso Tepper *q++ = cp;
24437f60ad1SHasso Tepper if ((cp = strpbrk(cp, " \t")) != NULL)
24537f60ad1SHasso Tepper *cp++ = '\0';
24637f60ad1SHasso Tepper }
24737f60ad1SHasso Tepper }
24837f60ad1SHasso Tepper *q = NULL;
24937f60ad1SHasso Tepper
25037f60ad1SHasso Tepper return (&proto);
25137f60ad1SHasso Tepper }
25237f60ad1SHasso Tepper
25337f60ad1SHasso Tepper void
bt_setprotoent(int stayopen)25437f60ad1SHasso Tepper bt_setprotoent(int stayopen)
25537f60ad1SHasso Tepper {
25637f60ad1SHasso Tepper if (protof == NULL)
25737f60ad1SHasso Tepper protof = fopen(_PATH_BT_PROTOCOLS, "r");
25837f60ad1SHasso Tepper else
25937f60ad1SHasso Tepper rewind(protof);
26037f60ad1SHasso Tepper
26137f60ad1SHasso Tepper proto_stayopen = stayopen;
26237f60ad1SHasso Tepper }
26337f60ad1SHasso Tepper
26437f60ad1SHasso Tepper void
bt_endprotoent(void)26537f60ad1SHasso Tepper bt_endprotoent(void)
26637f60ad1SHasso Tepper {
26737f60ad1SHasso Tepper if (protof != NULL) {
26837f60ad1SHasso Tepper (void) fclose(protof);
26937f60ad1SHasso Tepper protof = NULL;
27037f60ad1SHasso Tepper }
27137f60ad1SHasso Tepper }
27237f60ad1SHasso Tepper
27337f60ad1SHasso Tepper char const *
bt_ntoa(bdaddr_t const * ba,char * str)27437f60ad1SHasso Tepper bt_ntoa(bdaddr_t const *ba, char *str)
27537f60ad1SHasso Tepper {
27637f60ad1SHasso Tepper static char buffer[24];
27737f60ad1SHasso Tepper
27837f60ad1SHasso Tepper if (str == NULL)
27937f60ad1SHasso Tepper str = buffer;
28037f60ad1SHasso Tepper
28137f60ad1SHasso Tepper sprintf(str, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
28237f60ad1SHasso Tepper ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
28337f60ad1SHasso Tepper
28437f60ad1SHasso Tepper return (str);
28537f60ad1SHasso Tepper }
28637f60ad1SHasso Tepper
28737f60ad1SHasso Tepper int
bt_aton(char const * str,bdaddr_t * ba)28837f60ad1SHasso Tepper bt_aton(char const *str, bdaddr_t *ba)
28937f60ad1SHasso Tepper {
29037f60ad1SHasso Tepper int i, b;
29137f60ad1SHasso Tepper char *end = NULL;
29237f60ad1SHasso Tepper
29337f60ad1SHasso Tepper memset(ba, 0, sizeof(*ba));
29437f60ad1SHasso Tepper
29537f60ad1SHasso Tepper for (i = 5, end = strchr(str, ':');
29637f60ad1SHasso Tepper i > 0 && *str != '\0' && end != NULL;
29737f60ad1SHasso Tepper i --, str = end + 1, end = strchr(str, ':')) {
29837f60ad1SHasso Tepper switch (end - str) {
29937f60ad1SHasso Tepper case 1:
30037f60ad1SHasso Tepper b = bt_hex_nibble(str[0]);
30137f60ad1SHasso Tepper break;
30237f60ad1SHasso Tepper
30337f60ad1SHasso Tepper case 2:
30437f60ad1SHasso Tepper b = bt_hex_byte(str);
30537f60ad1SHasso Tepper break;
30637f60ad1SHasso Tepper
30737f60ad1SHasso Tepper default:
30837f60ad1SHasso Tepper b = -1;
30937f60ad1SHasso Tepper break;
31037f60ad1SHasso Tepper }
31137f60ad1SHasso Tepper
31237f60ad1SHasso Tepper if (b < 0)
31337f60ad1SHasso Tepper return (0);
31437f60ad1SHasso Tepper
31537f60ad1SHasso Tepper ba->b[i] = b;
31637f60ad1SHasso Tepper }
31737f60ad1SHasso Tepper
31837f60ad1SHasso Tepper if (i != 0 || end != NULL || *str == 0)
31937f60ad1SHasso Tepper return (0);
32037f60ad1SHasso Tepper
32137f60ad1SHasso Tepper switch (strlen(str)) {
32237f60ad1SHasso Tepper case 1:
32337f60ad1SHasso Tepper b = bt_hex_nibble(str[0]);
32437f60ad1SHasso Tepper break;
32537f60ad1SHasso Tepper
32637f60ad1SHasso Tepper case 2:
32737f60ad1SHasso Tepper b = bt_hex_byte(str);
32837f60ad1SHasso Tepper break;
32937f60ad1SHasso Tepper
33037f60ad1SHasso Tepper default:
33137f60ad1SHasso Tepper b = -1;
33237f60ad1SHasso Tepper break;
33337f60ad1SHasso Tepper }
33437f60ad1SHasso Tepper
33537f60ad1SHasso Tepper if (b < 0)
33637f60ad1SHasso Tepper return (0);
33737f60ad1SHasso Tepper
33837f60ad1SHasso Tepper ba->b[i] = b;
33937f60ad1SHasso Tepper
34037f60ad1SHasso Tepper return (1);
34137f60ad1SHasso Tepper }
34237f60ad1SHasso Tepper
34337f60ad1SHasso Tepper static int
bt_hex_byte(char const * str)34437f60ad1SHasso Tepper bt_hex_byte(char const *str)
34537f60ad1SHasso Tepper {
34637f60ad1SHasso Tepper int n1, n2;
34737f60ad1SHasso Tepper
34837f60ad1SHasso Tepper if ((n1 = bt_hex_nibble(str[0])) < 0)
34937f60ad1SHasso Tepper return (-1);
35037f60ad1SHasso Tepper
35137f60ad1SHasso Tepper if ((n2 = bt_hex_nibble(str[1])) < 0)
35237f60ad1SHasso Tepper return (-1);
35337f60ad1SHasso Tepper
35437f60ad1SHasso Tepper return ((((n1 & 0x0f) << 4) | (n2 & 0x0f)) & 0xff);
35537f60ad1SHasso Tepper }
35637f60ad1SHasso Tepper
35737f60ad1SHasso Tepper static int
bt_hex_nibble(char nibble)35837f60ad1SHasso Tepper bt_hex_nibble(char nibble)
35937f60ad1SHasso Tepper {
36037f60ad1SHasso Tepper if ('0' <= nibble && nibble <= '9')
36137f60ad1SHasso Tepper return (nibble - '0');
36237f60ad1SHasso Tepper
36337f60ad1SHasso Tepper if ('a' <= nibble && nibble <= 'f')
36437f60ad1SHasso Tepper return (nibble - 'a' + 0xa);
36537f60ad1SHasso Tepper
36637f60ad1SHasso Tepper if ('A' <= nibble && nibble <= 'F')
36737f60ad1SHasso Tepper return (nibble - 'A' + 0xa);
36837f60ad1SHasso Tepper
36937f60ad1SHasso Tepper return (-1);
37037f60ad1SHasso Tepper }
371