DF-5749 / stub.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | /* * stub.c -- HCI-layer stubs for the l2uh_harness KLD (DF-5749). * * The production netbt files compiled verbatim into this module are * l2cap_upper.c (the file under audit) * l2cap_lower.c (l2cap_close / l2cap_start) * l2cap_misc.c (l2cap_request_alloc/free, l2cap_rtx, l2cap_cid_alloc) * l2cap_signal.c (signalling) * Everything they need from the layers we do NOT compile (hci_link.c, * hci_event.c, hci_unit.c, hci_socket.c, bt_proto.c, l2cap_socket.c) is * provided here with the minimum faithful behaviour: * * - M_BLUETOOTH malloc type (lives in bt_proto.c normally) * - l2cap_pdu_pool / l2cap_req_pool vm_zones (bt_proto.c netbt_init) * - hci_acl_close(): production hci_link.c:153-164 semantics minus the * expiry-callout path: KKASSERT(link != NULL), drop the reference, * kfree when it reaches zero with the link CLOSED (the immediate-free * branch). The NULL-deref sink of the double close * (--link->hl_refcnt with link == NULL) is exactly the production * code path. * - hci_acl_send()/hci_acl_setmode()/hci_acl_open()/hci_route_lookup()/ * hci_unit_lookup(): symbols only; never on the raced path. * * The channel upper layer (what l2cap_socket.c provides in production) * is a fake btproto with counters. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/systm.h> #include <sys/types.h> #include <net/if.h> #include <netbt/bluetooth.h> #include <netbt/hci.h> #include <netbt/l2cap.h> #include "l2uh.h" /* real malloc type lives in bt_proto.c which we do not compile in */ MALLOC_DEFINE(M_BLUETOOTH, "Bluetooth", "Bluetooth system memory"); /* zones: l2cap_pdu_pool / l2cap_req_pool are defined by the VERBATIM * l2cap_misc.c compiled into this module; harness.c zinits them at * MOD_LOAD (what netbt_init() in bt_proto.c does in production). */ /* counters for the fake upper layer (what l2cap_socket.c would do) */ int stub_proto_disconnected_count; int stub_proto_connecting_count; /* production hci_link.c:60 -- referenced by the harness diagnostics */ int hci_acl_expiry = 10; static void stub_connecting(void *); static void stub_connected(void *); static void stub_disconnected(void *, int); static void *stub_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); static void stub_complete(void *, int); static void stub_linkmode(void *, int); static void stub_input(void *, struct mbuf *); const struct btproto stub_btproto = { stub_connecting, stub_connected, stub_disconnected, stub_newconn, stub_complete, stub_linkmode, stub_input, }; static void stub_connecting(void *arg) { stub_proto_connecting_count++; } static void stub_connected(void *arg) { } static void stub_disconnected(void *arg, int err) { stub_proto_disconnected_count++; } static void * stub_newconn(void *arg, struct sockaddr_bt *laddr, struct sockaddr_bt *raddr) { return NULL; } static void stub_complete(void *arg, int count) { } static void stub_linkmode(void *arg, int new) { } static void stub_input(void *arg, struct mbuf *m) { m_freem(m); } /* ------------------------------------------------------------------ */ /* fake hci_link allocator: production hci_link_alloc() minus the unit * list attach (no struct hci_unit needed). Refcount 0, state CLOSED. */ struct hci_link * stub_link_new(void) { struct hci_link *link; link = kmalloc(sizeof(*link), M_BLUETOOTH, M_NOWAIT | M_ZERO); if (link == NULL) return NULL; link->hl_state = HCI_LINK_CLOSED; TAILQ_INIT(&link->hl_txq); TAILQ_INIT(&link->hl_reqs); link->hl_mtu = L2CAP_MTU_DEFAULT; return link; } /* ------------------------------------------------------------------ */ /* HCI-layer symbols used by the compiled production files */ void hci_acl_close(struct hci_link *link, int err) { /* production hci_link.c:153-164 (immediate-free branch): * KKASSERT(link != NULL) -- a no-op on production GENERIC, so a * NULL link reaches "--link->hl_refcnt" and faults. */ KKASSERT(link != NULL); if (--link->hl_refcnt == 0) kfree(link, M_BLUETOOTH); } int hci_acl_send(struct mbuf *m, struct hci_link *link, struct l2cap_channel *chan) { m_freem(m); return 0; } int hci_acl_setmode(struct hci_link *link) { return 0; } struct hci_link * hci_acl_open(struct hci_unit *unit, bdaddr_t *bdaddr) { /* the harness builds the channel state directly (what * l2cap_connect() + hci_acl_open() produce), this is never called */ return NULL; } int hci_route_lookup(bdaddr_t *laddr, bdaddr_t *raddr) { return EHOSTUNREACH; } struct hci_unit * hci_unit_lookup(bdaddr_t *bdaddr) { return NULL; } |