xref: /netbsd-src/sys/netbt/hci_misc.c (revision d0735544b6ca51c7a77127694c53477d5dee9c6d)
1*d0735544Smsaitoh /*	$NetBSD: hci_misc.c,v 1.4 2021/11/22 05:33:57 msaitoh Exp $	*/
2a5c89047Sgdamore 
3a5c89047Sgdamore /*-
4a5c89047Sgdamore  * Copyright (c) 2005 Iain Hibbert.
5a5c89047Sgdamore  * Copyright (c) 2006 Itronix Inc.
6a5c89047Sgdamore  * All rights reserved.
7a5c89047Sgdamore  *
8a5c89047Sgdamore  * Redistribution and use in source and binary forms, with or without
9a5c89047Sgdamore  * modification, are permitted provided that the following conditions
10a5c89047Sgdamore  * are met:
11a5c89047Sgdamore  * 1. Redistributions of source code must retain the above copyright
12a5c89047Sgdamore  *    notice, this list of conditions and the following disclaimer.
13a5c89047Sgdamore  * 2. Redistributions in binary form must reproduce the above copyright
14a5c89047Sgdamore  *    notice, this list of conditions and the following disclaimer in the
15a5c89047Sgdamore  *    documentation and/or other materials provided with the distribution.
16a5c89047Sgdamore  * 3. The name of Itronix Inc. may not be used to endorse
17a5c89047Sgdamore  *    or promote products derived from this software without specific
18a5c89047Sgdamore  *    prior written permission.
19a5c89047Sgdamore  *
20a5c89047Sgdamore  * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
21a5c89047Sgdamore  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22a5c89047Sgdamore  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23a5c89047Sgdamore  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
24a5c89047Sgdamore  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25a5c89047Sgdamore  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26a5c89047Sgdamore  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27a5c89047Sgdamore  * ON ANY THEORY OF LIABILITY, WHETHER IN
28a5c89047Sgdamore  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29a5c89047Sgdamore  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30a5c89047Sgdamore  * POSSIBILITY OF SUCH DAMAGE.
31a5c89047Sgdamore  */
32a5c89047Sgdamore 
33a5c89047Sgdamore #include <sys/cdefs.h>
34*d0735544Smsaitoh __KERNEL_RCSID(0, "$NetBSD: hci_misc.c,v 1.4 2021/11/22 05:33:57 msaitoh Exp $");
35a5c89047Sgdamore 
36a5c89047Sgdamore #include <sys/param.h>
37a5c89047Sgdamore #include <sys/kernel.h>
38a5c89047Sgdamore #include <sys/malloc.h>
39a5c89047Sgdamore #include <sys/mbuf.h>
40a5c89047Sgdamore #include <sys/proc.h>
41a5c89047Sgdamore #include <sys/queue.h>
42a5c89047Sgdamore #include <sys/systm.h>
43a5c89047Sgdamore 
44a5c89047Sgdamore #include <netbt/bluetooth.h>
45a5c89047Sgdamore #include <netbt/hci.h>
46a5c89047Sgdamore 
47a5c89047Sgdamore /*
48a5c89047Sgdamore  * cache Inquiry Responses for this number of seconds for routing
49a5c89047Sgdamore  * purposes [sysctl]
50a5c89047Sgdamore  */
51a5c89047Sgdamore int hci_memo_expiry = 600;
52a5c89047Sgdamore 
53a5c89047Sgdamore /*
54a5c89047Sgdamore  * set 'src' address for routing to 'dest'
55a5c89047Sgdamore  */
56a5c89047Sgdamore int
hci_route_lookup(bdaddr_t * src,bdaddr_t * dest)57a5c89047Sgdamore hci_route_lookup(bdaddr_t *src, bdaddr_t *dest)
58a5c89047Sgdamore {
59a5c89047Sgdamore 	struct hci_unit *unit;
60a5c89047Sgdamore 	struct hci_link *link;
61a5c89047Sgdamore 	struct hci_memo *memo;
62a5c89047Sgdamore 
63a5c89047Sgdamore 	/*
64a5c89047Sgdamore 	 * Walk the ACL connections, if we have a connection
65a5c89047Sgdamore 	 * to 'dest' already then thats best..
66a5c89047Sgdamore 	 */
67a5c89047Sgdamore 	SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) {
68a5c89047Sgdamore 		if ((unit->hci_flags & BTF_UP) == 0)
69a5c89047Sgdamore 			continue;
70a5c89047Sgdamore 
71a5c89047Sgdamore 		TAILQ_FOREACH(link, &unit->hci_links, hl_next) {
72a5c89047Sgdamore 			if (link->hl_type != HCI_LINK_ACL)
73a5c89047Sgdamore 				continue;
74a5c89047Sgdamore 
75a5c89047Sgdamore 			if (bdaddr_same(&link->hl_bdaddr, dest))
76a5c89047Sgdamore 				goto found;
77a5c89047Sgdamore 		}
78a5c89047Sgdamore 	}
79a5c89047Sgdamore 
80a5c89047Sgdamore 	/*
81a5c89047Sgdamore 	 * Now check all the memos to see if there has been an
82*d0735544Smsaitoh 	 * inquiry response..
83a5c89047Sgdamore 	 */
84a5c89047Sgdamore 	SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) {
85a5c89047Sgdamore 		if ((unit->hci_flags & BTF_UP) == 0)
86a5c89047Sgdamore 			continue;
87a5c89047Sgdamore 
88a5c89047Sgdamore 		memo = hci_memo_find(unit, dest);
89a5c89047Sgdamore 		if (memo)
90a5c89047Sgdamore 			goto found;
91a5c89047Sgdamore 	}
92a5c89047Sgdamore 
93a5c89047Sgdamore 	/*
94a5c89047Sgdamore 	 * Last ditch effort, lets use the first unit we find
95a5c89047Sgdamore 	 * thats up and running. (XXX settable default route?)
96a5c89047Sgdamore 	 */
97a5c89047Sgdamore 	SIMPLEQ_FOREACH(unit, &hci_unit_list, hci_next) {
98a5c89047Sgdamore 		if ((unit->hci_flags & BTF_UP) == 0)
99a5c89047Sgdamore 			continue;
100a5c89047Sgdamore 
101a5c89047Sgdamore 		goto found;
102a5c89047Sgdamore 	}
103a5c89047Sgdamore 
104a5c89047Sgdamore 	return EHOSTUNREACH;
105a5c89047Sgdamore 
106a5c89047Sgdamore found:
107a5c89047Sgdamore 	bdaddr_copy(src, &unit->hci_bdaddr);
108a5c89047Sgdamore 	return 0;
109a5c89047Sgdamore }
110a5c89047Sgdamore 
111a5c89047Sgdamore /*
112a5c89047Sgdamore  * find unit memo from bdaddr
113a5c89047Sgdamore  */
114a5c89047Sgdamore struct hci_memo *
hci_memo_find(struct hci_unit * unit,bdaddr_t * bdaddr)115a5c89047Sgdamore hci_memo_find(struct hci_unit *unit, bdaddr_t *bdaddr)
116a5c89047Sgdamore {
117a5c89047Sgdamore 	struct hci_memo *memo, *m0;
118a5c89047Sgdamore 	struct timeval now;
119a5c89047Sgdamore 
120a5c89047Sgdamore 	microtime(&now);
121a5c89047Sgdamore 
122a5c89047Sgdamore 	m0 = LIST_FIRST(&unit->hci_memos);
123a5c89047Sgdamore 	while ((memo = m0) != NULL) {
124a5c89047Sgdamore 		m0 = LIST_NEXT(memo, next);
125a5c89047Sgdamore 
126a5c89047Sgdamore 		if (now.tv_sec > memo->time.tv_sec + hci_memo_expiry) {
127a5c89047Sgdamore 			DPRINTF("memo %p too old (expiring)\n", memo);
128a5c89047Sgdamore 			hci_memo_free(memo);
129a5c89047Sgdamore 			continue;
130a5c89047Sgdamore 		}
131a5c89047Sgdamore 
1329ab5b2f6Splunky 		if (bdaddr_same(bdaddr, &memo->bdaddr)) {
133a5c89047Sgdamore 			DPRINTF("memo %p found\n", memo);
134a5c89047Sgdamore 			return memo;
135a5c89047Sgdamore 		}
136a5c89047Sgdamore 	}
137a5c89047Sgdamore 
138a5c89047Sgdamore 	DPRINTF("no memo found\n");
139a5c89047Sgdamore 	return NULL;
140a5c89047Sgdamore }
141a5c89047Sgdamore 
142a0c60c7eSplunky /*
143a0c60c7eSplunky  * Make a new memo on unit for bdaddr. If a memo exists, just
144a0c60c7eSplunky  * update the timestamp.
145a0c60c7eSplunky  */
146a0c60c7eSplunky struct hci_memo *
hci_memo_new(struct hci_unit * unit,bdaddr_t * bdaddr)147a0c60c7eSplunky hci_memo_new(struct hci_unit *unit, bdaddr_t *bdaddr)
148a0c60c7eSplunky {
149a0c60c7eSplunky 	struct hci_memo *memo;
150a0c60c7eSplunky 
151a0c60c7eSplunky 	memo = hci_memo_find(unit, bdaddr);
152a0c60c7eSplunky 	if (memo == NULL) {
153a0c60c7eSplunky 		memo = malloc(sizeof(struct hci_memo),
154a0c60c7eSplunky 			M_BLUETOOTH, M_NOWAIT | M_ZERO);
155a0c60c7eSplunky 
156a0c60c7eSplunky 		if (memo == NULL) {
157a0c60c7eSplunky 			DPRINTFN(0, "no memory for memo!\n");
158a0c60c7eSplunky 			return NULL;
159a0c60c7eSplunky 		}
160a0c60c7eSplunky 
161a0c60c7eSplunky 		DPRINTF("memo created for %02x:%02x:%02x:%02x:%02x:%02x\n",
162a0c60c7eSplunky 			bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
163a0c60c7eSplunky 			bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
164a0c60c7eSplunky 
165a0c60c7eSplunky 		bdaddr_copy(&memo->bdaddr, bdaddr);
166a0c60c7eSplunky 		LIST_INSERT_HEAD(&unit->hci_memos, memo, next);
167a0c60c7eSplunky 	}
168a0c60c7eSplunky 	else
169a0c60c7eSplunky 		DPRINTF("memo updated for %02x:%02x:%02x:%02x:%02x:%02x\n",
170a0c60c7eSplunky 			bdaddr->b[5], bdaddr->b[4], bdaddr->b[3],
171a0c60c7eSplunky 			bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]);
172a0c60c7eSplunky 
173a0c60c7eSplunky 	microtime(&memo->time);
174a0c60c7eSplunky 	return memo;
175a0c60c7eSplunky }
176a0c60c7eSplunky 
177a5c89047Sgdamore void
hci_memo_free(struct hci_memo * memo)178a5c89047Sgdamore hci_memo_free(struct hci_memo *memo)
179a5c89047Sgdamore {
180a5c89047Sgdamore 
181a5c89047Sgdamore 	LIST_REMOVE(memo, next);
182a5c89047Sgdamore 	free(memo, M_BLUETOOTH);
183a5c89047Sgdamore }
184