DF-5740 / sock_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 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | /* * sock_stub.c -- minimal L2CAP/SCO/RFCOMM/socket glue for the * hci_sock_harness KLD. * * The production netbt code (sys/netbt/hci_socket.c, hci_event.c, * hci_link.c, hci_misc.c, hci_unit.c, bt_input.c, bt_proto.c) is compiled * VERBATIM into this module. Everything those files need from the layers * we do not compile (l2cap_*.c except the two link-engine helpers, * sco_upper.c, sco_socket.c, rfcomm_*.c, hci_ioctl.c) is stubbed here: * * - the four pr_usrreqs / ctloutput functions referenced by btsw[] * (bt_proto.c) -- only BTPROTO_HCI sockets are created by the trigger, * the others just have to exist for the table to link; * - l2cap_close/l2cap_start/l2cap_request_free/l2cap_recv_frame and the * signalling senders used by hci_acl_linkmode()/hci_link.c; * - the SCO listener/list + sco_detach (hci_link.c); * - hci_ioctl (referenced by hci_socket.c:hci_scontrol; the trigger * issues no bt ioctls). * * NOTE: hci_mtap() and hci_drop() are NOT stubbed -- they come VERBATIM * from hci_socket.c. That is the code under test. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/malloc.h> #include <sys/mbuf.h> #include <sys/msgport.h> #include <sys/protosw.h> #include <sys/socket.h> #include <sys/socketvar.h> #include <sys/systm.h> #include <sys/types.h> #include <net/if.h> #include <sys/msgport2.h> #include <netbt/bluetooth.h> #include <netbt/hci.h> #include <netbt/l2cap.h> #include <netbt/sco.h> #include "stub.h" /* ------------------------------------------------------------------ */ /* btsw[] references (bt_proto.c) -- inert definitions */ int l2cap_sendspace = 4096; int l2cap_recvspace = 4096; int l2cap_response_timeout = 20; int l2cap_response_extended_timeout = 60; int rfcomm_sendspace = 4096; int rfcomm_recvspace = 4096; int rfcomm_mtu_default = 127; int rfcomm_ack_timeout = 2; int rfcomm_mcc_timeout = 4; int sco_sendspace = 4096; int sco_recvspace = 4096; /* defined in l2cap_misc.c / rfcomm_dlc.c normally; bt_proto.c only * assigns them in netbt_init(), so provide the storage here */ vm_zone_t l2cap_pdu_pool; vm_zone_t l2cap_req_pool; vm_zone_t rfcomm_credit_pool; /* * Inert pr_usrreqs for the protocols we don't compile. None of these * paths are exercised (the trigger only opens BTPROTO_HCI sockets); * they exist so btsw[] links. */ #define STUB_USRREQS { \ .pru_abort = pr_generic_notsupp, \ .pru_accept = pr_generic_notsupp, \ .pru_attach = pr_generic_notsupp, \ .pru_bind = pr_generic_notsupp, \ .pru_connect = pr_generic_notsupp, \ .pru_connect2 = pr_generic_notsupp, \ .pru_control = pr_generic_notsupp, \ .pru_detach = pr_generic_notsupp, \ .pru_disconnect = pr_generic_notsupp, \ .pru_listen = pr_generic_notsupp, \ .pru_peeraddr = pr_generic_notsupp, \ .pru_rcvd = pr_generic_notsupp, \ .pru_rcvoob = pr_generic_notsupp, \ .pru_send = pr_generic_notsupp, \ .pru_sense = pru_sense_null, \ .pru_shutdown = pr_generic_notsupp, \ .pru_sockaddr = pr_generic_notsupp, \ .pru_sosend = sosend, \ .pru_soreceive = soreceive, \ } struct pr_usrreqs l2cap_usrreqs = STUB_USRREQS; struct pr_usrreqs sco_usrreqs = STUB_USRREQS; struct pr_usrreqs rfcomm_usrreqs = STUB_USRREQS; /* l2cap.h / sco.h already declare the first two; rfcomm.h does not */ void rfcomm_ctloutput(netmsg_t msg); void l2cap_ctloutput(netmsg_t msg) { lwkt_replymsg(&msg->ctloutput.base.lmsg, ENOPROTOOPT); } void sco_ctloutput(netmsg_t msg) { lwkt_replymsg(&msg->ctloutput.base.lmsg, ENOPROTOOPT); } void rfcomm_ctloutput(netmsg_t msg) { lwkt_replymsg(&msg->ctloutput.base.lmsg, ENOPROTOOPT); } /* ------------------------------------------------------------------ */ /* hci_socket.c:hci_scontrol -> hci_ioctl (hci_ioctl.c not compiled) */ int hci_ioctl(unsigned long cmd, void *data, struct proc *p) { return ENOTTY; } /* ------------------------------------------------------------------ */ /* l2cap pieces used by the verbatim link engine (hci_link.c etc.) */ struct l2cap_channel_list l2cap_active_list = LIST_HEAD_INITIALIZER(l2cap_active_list); void l2cap_close(struct l2cap_channel *chan, int err) { if (chan->lc_lcid != L2CAP_NULL_CID) { LIST_REMOVE(chan, lc_ncid); chan->lc_lcid = L2CAP_NULL_CID; } } int l2cap_start(struct l2cap_channel *chan) { return 0; } void l2cap_request_free(struct l2cap_req *req) { kfree(req, M_BLUETOOTH); } void l2cap_recv_frame(struct mbuf *m, struct hci_link *link) { m_freem(m); } int l2cap_send_connect_req(struct l2cap_channel *chan) { return 0; } int l2cap_send_connect_rsp(struct hci_link *link, uint8_t ident, uint16_t dcid, uint16_t scid, uint16_t result) { return 0; } int l2cap_send_config_req(struct l2cap_channel *chan) { return 0; } /* ------------------------------------------------------------------ */ /* SCO pieces used by hci_link.c (same as the DF-5739 rig) */ struct sco_pcb_list sco_pcb = LIST_HEAD_INITIALIZER(sco_pcb); int stub_sco_newconn_count; int stub_sco_disconnected_count; static void *stub_sco_newconn(void *, struct sockaddr_bt *, struct sockaddr_bt *); static void stub_sco_disconnected(void *, int); static void stub_sco_connected(void *); static const struct btproto stub_sco_btproto = { NULL, /* connecting */ stub_sco_connected, /* connected */ stub_sco_disconnected, /* disconnected */ stub_sco_newconn, /* newconn */ NULL, /* complete */ NULL, /* linkmode */ NULL, /* input */ }; static struct sco_pcb stub_listener; void stub_sco_init(void) { memset(&stub_listener, 0, sizeof(stub_listener)); stub_listener.sp_flags = SP_LISTENING; stub_listener.sp_proto = &stub_sco_btproto; LIST_INSERT_HEAD(&sco_pcb, &stub_listener, sp_next); } static void * stub_sco_newconn(void *upper, struct sockaddr_bt *laddr, struct sockaddr_bt *raddr) { struct sco_pcb *pcb; pcb = kmalloc(sizeof(*pcb), M_BLUETOOTH, M_NOWAIT | M_ZERO); if (pcb == NULL) return NULL; pcb->sp_proto = &stub_sco_btproto; LIST_INSERT_HEAD(&sco_pcb, pcb, sp_next); stub_sco_newconn_count++; return pcb; } static void stub_sco_connected(void *arg) { } static void stub_sco_disconnected(void *arg, int err) { stub_sco_disconnected_count++; } int sco_detach(struct sco_pcb **handle) { struct sco_pcb *pcb = *handle; *handle = NULL; if (pcb == NULL) return EINVAL; if (pcb != &stub_listener) { LIST_REMOVE(pcb, sp_next); kfree(pcb, M_BLUETOOTH); } return 0; } |