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