1121054Semax/*
2121054Semax * bluetooth.c
3189462Semax */
4189462Semax
5189462Semax/*-
6189462Semax * Copyright (c) 2001-2009 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7121054Semax * All rights reserved.
8121054Semax *
9121054Semax * Redistribution and use in source and binary forms, with or without
10121054Semax * modification, are permitted provided that the following conditions
11121054Semax * are met:
12121054Semax * 1. Redistributions of source code must retain the above copyright
13121054Semax *    notice, this list of conditions and the following disclaimer.
14121054Semax * 2. Redistributions in binary form must reproduce the above copyright
15121054Semax *    notice, this list of conditions and the following disclaimer in the
16121054Semax *    documentation and/or other materials provided with the distribution.
17121054Semax *
18121054Semax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19121054Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20121054Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21121054Semax * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22121054Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23121054Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24121054Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25121054Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26121054Semax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27121054Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28121054Semax * SUCH DAMAGE.
29121054Semax *
30121054Semax * $Id: bluetooth.c,v 1.3 2003/05/20 23:04:30 max Exp $
31121054Semax * $FreeBSD$
32121054Semax */
33281210Stakawata#define L2CAP_SOCKET_CHECKED
34121054Semax#include <bluetooth.h>
35121054Semax#include <stdio.h>
36121054Semax#include <stdlib.h>
37121054Semax#include <string.h>
38121054Semax
39121054Semax#define _PATH_BT_HOSTS		"/etc/bluetooth/hosts"
40121054Semax#define _PATH_BT_PROTOCOLS	"/etc/bluetooth/protocols"
41121054Semax#define MAXALIASES		 35
42121054Semax
43121054Semaxstatic FILE		*hostf = NULL;
44121054Semaxstatic int		 host_stayopen = 0;
45121054Semaxstatic struct hostent	 host;
46121054Semaxstatic bdaddr_t		 host_addr;
47121054Semaxstatic char		*host_addr_ptrs[2];
48121054Semaxstatic char		*host_aliases[MAXALIASES];
49121054Semax
50121054Semaxstatic FILE		*protof = NULL;
51121054Semaxstatic int		 proto_stayopen = 0;
52121054Semaxstatic struct protoent	 proto;
53121054Semaxstatic char		*proto_aliases[MAXALIASES];
54121054Semax
55121054Semaxstatic char		 buf[BUFSIZ + 1];
56121054Semax
57121054Semaxstatic int bt_hex_byte   (char const *str);
58121054Semaxstatic int bt_hex_nibble (char nibble);
59121054Semax
60121054Semaxstruct hostent *
61121054Semaxbt_gethostbyname(char const *name)
62121054Semax{
63121054Semax	struct hostent	*p;
64121054Semax	char		**cp;
65121054Semax
66121054Semax	bt_sethostent(host_stayopen);
67121054Semax	while ((p = bt_gethostent()) != NULL) {
68121054Semax		if (strcasecmp(p->h_name, name) == 0)
69121054Semax			break;
70298208Spfg		for (cp = p->h_aliases; *cp != NULL; cp++)
71121054Semax			if (strcasecmp(*cp, name) == 0)
72121054Semax				goto found;
73121054Semax	}
74121054Semaxfound:
75121054Semax	bt_endhostent();
76121054Semax
77121054Semax	return (p);
78121054Semax}
79121054Semax
80121054Semaxstruct hostent *
81121054Semaxbt_gethostbyaddr(char const *addr, int len, int type)
82121054Semax{
83121054Semax	struct hostent	*p;
84121054Semax
85121054Semax	if (type != AF_BLUETOOTH || len != sizeof(bdaddr_t)) {
86121054Semax		h_errno = NO_RECOVERY;
87121054Semax		return (NULL);
88121054Semax	}
89121054Semax
90121054Semax	bt_sethostent(host_stayopen);
91121054Semax	while ((p = bt_gethostent()) != NULL)
92121054Semax		if (p->h_addrtype == type && bcmp(p->h_addr, addr, len) == 0)
93121054Semax			break;
94121054Semax	bt_endhostent();
95121054Semax
96121054Semax	return (p);
97121054Semax}
98121054Semax
99121054Semaxstruct hostent *
100121054Semaxbt_gethostent(void)
101121054Semax{
102121054Semax	char	*p, *cp, **q;
103121054Semax
104121054Semax	if (hostf == NULL)
105121054Semax		hostf = fopen(_PATH_BT_HOSTS, "r");
106121054Semax
107121054Semax	if (hostf == NULL) {
108121054Semax		h_errno = NETDB_INTERNAL;
109121054Semax		return (NULL);
110121054Semax	}
111121054Semaxagain:
112121054Semax	if ((p = fgets(buf, sizeof(buf), hostf)) == NULL) {
113121054Semax		h_errno = HOST_NOT_FOUND;
114121054Semax		return (NULL);
115121054Semax	}
116121054Semax	if (*p == '#')
117121054Semax		goto again;
118121054Semax	if ((cp = strpbrk(p, "#\n")) == NULL)
119121054Semax		goto again;
120121054Semax	*cp = 0;
121121054Semax	if ((cp = strpbrk(p, " \t")) == NULL)
122121054Semax		goto again;
123121054Semax	*cp++ = 0;
124121054Semax	if (bt_aton(p, &host_addr) == 0)
125121054Semax		goto again;
126121054Semax	host_addr_ptrs[0] = (char *) &host_addr;
127121054Semax	host_addr_ptrs[1] = NULL;
128121054Semax	host.h_addr_list = host_addr_ptrs;
129121054Semax	host.h_length = sizeof(host_addr);
130121054Semax	host.h_addrtype = AF_BLUETOOTH;
131121054Semax	while (*cp == ' ' || *cp == '\t')
132121054Semax		cp++;
133121054Semax	host.h_name = cp;
134121054Semax	q = host.h_aliases = host_aliases;
135121054Semax	if ((cp = strpbrk(cp, " \t")) != NULL)
136121054Semax		*cp++ = 0;
137121054Semax	while (cp != NULL && *cp != 0) {
138121054Semax		if (*cp == ' ' || *cp == '\t') {
139121054Semax			cp++;
140121054Semax			continue;
141121054Semax		}
142121054Semax		if (q < &host_aliases[MAXALIASES - 1])
143121054Semax			*q++ = cp;
144121054Semax		if ((cp = strpbrk(cp, " \t")) != NULL)
145121054Semax			*cp++ = 0;
146121054Semax	}
147121054Semax	*q = NULL;
148121054Semax	h_errno = NETDB_SUCCESS;
149121054Semax
150121054Semax	return (&host);
151121054Semax}
152121054Semax
153121054Semaxvoid
154121054Semaxbt_sethostent(int stayopen)
155121054Semax{
156121054Semax	if (hostf == NULL)
157121054Semax		hostf = fopen(_PATH_BT_HOSTS, "r");
158121054Semax	else
159121054Semax		rewind(hostf);
160121054Semax
161121054Semax	host_stayopen = stayopen;
162121054Semax}
163121054Semax
164121054Semaxvoid
165121054Semaxbt_endhostent(void)
166121054Semax{
167121054Semax	if (hostf != NULL && host_stayopen == 0) {
168121054Semax		(void) fclose(hostf);
169121054Semax		hostf = NULL;
170121054Semax	}
171121054Semax}
172121054Semax
173121054Semaxstruct protoent *
174121054Semaxbt_getprotobyname(char const *name)
175121054Semax{
176121054Semax	struct protoent	 *p;
177121054Semax	char		**cp;
178121054Semax
179121054Semax	bt_setprotoent(proto_stayopen);
180121054Semax	while ((p = bt_getprotoent()) != NULL) {
181121054Semax		if (strcmp(p->p_name, name) == 0)
182121054Semax			break;
183298208Spfg		for (cp = p->p_aliases; *cp != NULL; cp++)
184121054Semax			if (strcmp(*cp, name) == 0)
185121054Semax				goto found;
186121054Semax	}
187121054Semaxfound:
188121054Semax	bt_endprotoent();
189121054Semax
190121054Semax	return (p);
191121054Semax}
192121054Semax
193121054Semaxstruct protoent *
194121054Semaxbt_getprotobynumber(int proto)
195121054Semax{
196121054Semax	struct protoent	*p;
197121054Semax
198121054Semax	bt_setprotoent(proto_stayopen);
199121054Semax	while ((p = bt_getprotoent()) != NULL)
200121054Semax		if (p->p_proto == proto)
201121054Semax			break;
202121054Semax	bt_endprotoent();
203121054Semax
204121054Semax	return (p);
205121054Semax}
206121054Semax
207121054Semaxstruct protoent *
208121054Semaxbt_getprotoent(void)
209121054Semax{
210121054Semax	char	*p, *cp, **q;
211121054Semax
212121054Semax	if (protof == NULL)
213121054Semax		protof = fopen(_PATH_BT_PROTOCOLS, "r");
214121054Semax
215121054Semax	if (protof == NULL)
216121054Semax		return (NULL);
217121054Semaxagain:
218121054Semax	if ((p = fgets(buf, sizeof(buf), protof)) == NULL)
219121054Semax		return (NULL);
220121054Semax	if (*p == '#')
221121054Semax		goto again;
222121054Semax	if ((cp = strpbrk(p, "#\n")) == NULL)
223121054Semax		goto again;
224121054Semax	*cp = '\0';
225121054Semax	proto.p_name = p;
226121054Semax	if ((cp = strpbrk(p, " \t")) == NULL)
227121054Semax		goto again;
228121054Semax	*cp++ = '\0';
229121054Semax	while (*cp == ' ' || *cp == '\t')
230121054Semax		cp++;
231121054Semax	if ((p = strpbrk(cp, " \t")) != NULL)
232121054Semax		*p++ = '\0';
233121054Semax	proto.p_proto = atoi(cp);
234121054Semax	q = proto.p_aliases = proto_aliases;
235121054Semax	if (p != NULL) {
236121054Semax		cp = p;
237121054Semax		while (cp != NULL && *cp != 0) {
238121054Semax			if (*cp == ' ' || *cp == '\t') {
239121054Semax				cp++;
240121054Semax				continue;
241121054Semax			}
242121054Semax			if (q < &proto_aliases[MAXALIASES - 1])
243121054Semax				*q++ = cp;
244121054Semax			if ((cp = strpbrk(cp, " \t")) != NULL)
245121054Semax				*cp++ = '\0';
246121054Semax		}
247121054Semax	}
248121054Semax	*q = NULL;
249121054Semax
250121054Semax	return (&proto);
251121054Semax}
252121054Semax
253121054Semaxvoid
254121054Semaxbt_setprotoent(int stayopen)
255121054Semax{
256121054Semax	if (protof == NULL)
257121054Semax		protof = fopen(_PATH_BT_PROTOCOLS, "r");
258121054Semax	else
259121054Semax		rewind(protof);
260121054Semax
261121054Semax	proto_stayopen = stayopen;
262121054Semax}
263121054Semax
264121054Semaxvoid
265121054Semaxbt_endprotoent(void)
266121054Semax{
267121054Semax	if (protof != NULL) {
268121054Semax		(void) fclose(protof);
269121054Semax		protof = NULL;
270121054Semax	}
271121054Semax}
272121054Semax
273121054Semaxchar const *
274121054Semaxbt_ntoa(bdaddr_t const *ba, char *str)
275121054Semax{
276121054Semax	static char	buffer[24];
277121054Semax
278121054Semax	if (str == NULL)
279121054Semax		str = buffer;
280121054Semax
281121054Semax	sprintf(str, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
282121054Semax		ba->b[5], ba->b[4], ba->b[3], ba->b[2], ba->b[1], ba->b[0]);
283121054Semax
284121054Semax	return (str);
285121054Semax}
286121054Semax
287121054Semaxint
288121054Semaxbt_aton(char const *str, bdaddr_t *ba)
289121054Semax{
290121054Semax	int	 i, b;
291121054Semax	char	*end = NULL;
292121054Semax
293121054Semax	memset(ba, 0, sizeof(*ba));
294121054Semax
295121054Semax	for (i = 5, end = strchr(str, ':');
296126643Smarkm	     i > 0 && *str != '\0' && end != NULL;
297121054Semax	     i --, str = end + 1, end = strchr(str, ':')) {
298121054Semax		switch (end - str) {
299121054Semax		case 1:
300121054Semax			b = bt_hex_nibble(str[0]);
301121054Semax			break;
302121054Semax
303121054Semax		case 2:
304121054Semax			b = bt_hex_byte(str);
305121054Semax			break;
306121054Semax
307121054Semax		default:
308121054Semax			b = -1;
309121054Semax			break;
310121054Semax		}
311121054Semax
312121054Semax		if (b < 0)
313121054Semax			return (0);
314121054Semax
315121054Semax		ba->b[i] = b;
316121054Semax	}
317121054Semax
318121054Semax	if (i != 0 || end != NULL || *str == 0)
319121054Semax		return (0);
320121054Semax
321121054Semax	switch (strlen(str)) {
322121054Semax	case 1:
323121054Semax		b = bt_hex_nibble(str[0]);
324121054Semax		break;
325121054Semax
326121054Semax	case 2:
327121054Semax		b = bt_hex_byte(str);
328121054Semax		break;
329121054Semax
330121054Semax	default:
331121054Semax		b = -1;
332121054Semax		break;
333121054Semax	}
334121054Semax
335121054Semax	if (b < 0)
336121054Semax		return (0);
337121054Semax
338121054Semax	ba->b[i] = b;
339121054Semax
340121054Semax	return (1);
341121054Semax}
342121054Semax
343121054Semaxstatic int
344121054Semaxbt_hex_byte(char const *str)
345121054Semax{
346121054Semax	int	n1, n2;
347121054Semax
348121054Semax	if ((n1 = bt_hex_nibble(str[0])) < 0)
349121054Semax		return (-1);
350121054Semax
351121054Semax	if ((n2 = bt_hex_nibble(str[1])) < 0)
352121054Semax		return (-1);
353121054Semax
354121054Semax	return ((((n1 & 0x0f) << 4) | (n2 & 0x0f)) & 0xff);
355121054Semax}
356121054Semax
357121054Semaxstatic int
358121054Semaxbt_hex_nibble(char nibble)
359121054Semax{
360121054Semax	if ('0' <= nibble && nibble <= '9')
361121054Semax		return (nibble - '0');
362121054Semax
363121054Semax	if ('a' <= nibble && nibble <= 'f')
364121054Semax		return (nibble - 'a' + 0xa);
365121054Semax
366121054Semax	if ('A' <= nibble && nibble <= 'F')
367121054Semax		return (nibble - 'A' + 0xa);
368121054Semax
369121054Semax	return (-1);
370121054Semax}
371121054Semax
372