1 /* $NetBSD: hci.c,v 1.2 2007/01/25 20:33:41 plunky Exp $ */ 2 /* $DragonFly: src/usr.sbin/bthcid/hci.c,v 1.2 2008/02/02 09:21:24 swildner Exp $ */ 3 4 /*- 5 * Copyright (c) 2006 Itronix Inc. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. The name of Itronix Inc. may not be used to endorse 17 * or promote products derived from this software without specific 18 * prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY 24 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 27 * ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 /* 33 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions 38 * are met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce the above copyright 42 * notice, this list of conditions and the following disclaimer in the 43 * documentation and/or other materials provided with the distribution. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * SUCH DAMAGE. 56 */ 57 58 #include <sys/ioctl.h> 59 #include <sys/time.h> 60 #include <bluetooth.h> 61 #include <errno.h> 62 #include <event.h> 63 #include <string.h> 64 #include <syslog.h> 65 #include <unistd.h> 66 67 #include "bthcid.h" 68 69 static struct event hci_ev; 70 71 static void process_hci 72 (int, short, void *); 73 74 static int process_pin_code_request_event 75 (int, struct sockaddr_bt *, bdaddr_t *); 76 static int process_link_key_request_event 77 (int, struct sockaddr_bt *, bdaddr_t *); 78 static int process_link_key_notification_event 79 (int, struct sockaddr_bt *, hci_link_key_notification_ep *); 80 81 static int send_link_key_reply 82 (int, struct sockaddr_bt *, bdaddr_t *, uint8_t *); 83 static int send_hci_cmd 84 (int, struct sockaddr_bt *, uint16_t, size_t, void *); 85 86 static char dev_name[HCI_DEVNAME_SIZE]; 87 88 /* Initialise HCI Events */ 89 int 90 init_hci(bdaddr_t *bdaddr) 91 { 92 struct sockaddr_bt sa; 93 struct hci_filter filter; 94 int hci; 95 96 hci = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 97 if (hci < 0) 98 return -1; 99 100 memset(&sa, 0, sizeof(sa)); 101 sa.bt_len = sizeof(sa); 102 sa.bt_family = AF_BLUETOOTH; 103 bdaddr_copy(&sa.bt_bdaddr, bdaddr); 104 if (bind(hci, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 105 close(hci); 106 return -1; 107 } 108 109 memset(&filter, 0, sizeof(filter)); 110 hci_filter_set(HCI_EVENT_PIN_CODE_REQ, &filter); 111 hci_filter_set(HCI_EVENT_LINK_KEY_REQ, &filter); 112 hci_filter_set(HCI_EVENT_LINK_KEY_NOTIFICATION, &filter); 113 114 if (setsockopt(hci, BTPROTO_HCI, SO_HCI_EVT_FILTER, 115 (const void *)&filter, sizeof(filter)) < 0) { 116 close(hci); 117 return -1; 118 } 119 120 event_set(&hci_ev, hci, EV_READ | EV_PERSIST, process_hci, NULL); 121 if (event_add(&hci_ev, NULL) < 0) { 122 close(hci); 123 return -1; 124 } 125 126 return 0; 127 } 128 129 /* Process an HCI event */ 130 static void 131 process_hci(int sock, short ev __unused, void *arg __unused) 132 { 133 char buffer[HCI_EVENT_PKT_SIZE]; 134 hci_event_hdr_t *event = (hci_event_hdr_t *)buffer; 135 struct sockaddr_bt addr; 136 int n; 137 socklen_t size; 138 139 size = sizeof(addr); 140 n = recvfrom(sock, buffer, sizeof(buffer), 0, 141 (struct sockaddr *) &addr, &size); 142 if (n < 0) { 143 syslog(LOG_ERR, "Could not receive from HCI socket: %m"); 144 return; 145 } 146 147 if (event->type != HCI_EVENT_PKT) { 148 syslog(LOG_ERR, "Received unexpected HCI packet, " 149 "type=%#x", event->type); 150 151 return; 152 } 153 154 if (!bt_devname(dev_name, &addr.bt_bdaddr)) 155 strlcpy(dev_name, "unknown", sizeof(dev_name)); 156 157 switch (event->event) { 158 case HCI_EVENT_PIN_CODE_REQ: 159 process_pin_code_request_event(sock, &addr, 160 (bdaddr_t *)(event + 1)); 161 break; 162 163 case HCI_EVENT_LINK_KEY_REQ: 164 process_link_key_request_event(sock, &addr, 165 (bdaddr_t *)(event + 1)); 166 break; 167 168 case HCI_EVENT_LINK_KEY_NOTIFICATION: 169 process_link_key_notification_event(sock, &addr, 170 (hci_link_key_notification_ep *)(event + 1)); 171 break; 172 173 default: 174 syslog(LOG_ERR, "Received unexpected HCI event, " 175 "event=%#x", event->event); 176 break; 177 } 178 179 return; 180 } 181 182 /* Process PIN_Code_Request event */ 183 static int 184 process_pin_code_request_event(int sock, struct sockaddr_bt *addr, 185 bdaddr_t *bdaddr) 186 { 187 /* TODO: Add search pin in config file */ 188 189 uint8_t *pin; 190 uint8_t *pin2; 191 192 syslog(LOG_DEBUG, "Got PIN_Code_Request event from %s, " 193 "remote bdaddr %s", 194 dev_name, 195 bt_ntoa(bdaddr, NULL)); 196 197 pin = lookup_pin(&addr->bt_bdaddr, bdaddr); 198 if (pin != NULL) 199 return send_pin_code_reply(sock, addr, bdaddr, pin); 200 201 pin2 = lookup_pin_conf(&addr->bt_bdaddr, bdaddr); 202 if (pin2 != NULL) { 203 return send_pin_code_reply(sock, addr, bdaddr, pin2); 204 } 205 206 if (send_client_request(&addr->bt_bdaddr, bdaddr, sock) == 0) 207 return send_pin_code_reply(sock, addr, bdaddr, NULL); 208 209 return 0; 210 } 211 212 /* Process Link_Key_Request event */ 213 static int 214 process_link_key_request_event(int sock, struct sockaddr_bt *addr, 215 bdaddr_t *bdaddr) 216 { 217 uint8_t *key; 218 219 syslog(LOG_DEBUG, 220 "Got Link_Key_Request event from %s, remote bdaddr %s", 221 dev_name, bt_ntoa(bdaddr, NULL)); 222 223 key = lookup_key(&addr->bt_bdaddr, bdaddr); 224 225 if (key != NULL) { 226 syslog(LOG_DEBUG, "Found Key, remote bdaddr %s", 227 bt_ntoa(bdaddr, NULL)); 228 229 return send_link_key_reply(sock, addr, bdaddr, key); 230 } 231 232 syslog(LOG_DEBUG, "Could not find link key for remote bdaddr %s", 233 bt_ntoa(bdaddr, NULL)); 234 235 return send_link_key_reply(sock, addr, bdaddr, NULL); 236 } 237 238 /* Send PIN_Code_[Negative]_Reply */ 239 int 240 send_pin_code_reply(int sock, struct sockaddr_bt *addr, 241 bdaddr_t *bdaddr, uint8_t *pin) 242 { 243 int n; 244 245 if (pin != NULL) { 246 hci_pin_code_rep_cp cp; 247 248 syslog(LOG_DEBUG, "Sending PIN_Code_Reply to %s " 249 "for remote bdaddr %s", 250 dev_name, 251 bt_ntoa(bdaddr, NULL)); 252 253 bdaddr_copy(&cp.bdaddr, bdaddr); 254 memcpy(cp.pin, pin, HCI_PIN_SIZE); 255 256 n = HCI_PIN_SIZE; 257 while (n > 0 && pin[n - 1] == 0) 258 n--; 259 cp.pin_size = n; 260 261 n = send_hci_cmd(sock, addr, 262 HCI_CMD_PIN_CODE_REP, sizeof(cp), &cp); 263 264 } else { 265 syslog(LOG_DEBUG, "Sending PIN_Code_Negative_Reply to %s " 266 "for remote bdaddr %s", 267 dev_name, 268 bt_ntoa(bdaddr, NULL)); 269 270 n = send_hci_cmd(sock, addr, HCI_CMD_PIN_CODE_NEG_REP, 271 sizeof(bdaddr_t), bdaddr); 272 } 273 274 if (n < 0) { 275 syslog(LOG_ERR, "Could not send PIN code reply to %s " 276 "for remote bdaddr %s: %m", 277 dev_name, 278 bt_ntoa(bdaddr, NULL)); 279 280 return -1; 281 } 282 283 return 0; 284 } 285 286 /* Send Link_Key_[Negative]_Reply */ 287 static int 288 send_link_key_reply(int sock, struct sockaddr_bt *addr, 289 bdaddr_t *bdaddr, uint8_t *key) 290 { 291 int n; 292 293 if (key != NULL) { 294 hci_link_key_rep_cp cp; 295 296 bdaddr_copy(&cp.bdaddr, bdaddr); 297 memcpy(&cp.key, key, sizeof(cp.key)); 298 299 syslog(LOG_DEBUG, "Sending Link_Key_Reply to %s " 300 "for remote bdaddr %s", 301 dev_name, bt_ntoa(bdaddr, NULL)); 302 303 n = send_hci_cmd(sock, addr, HCI_CMD_LINK_KEY_REP, sizeof(cp), &cp); 304 } else { 305 hci_link_key_neg_rep_cp cp; 306 307 bdaddr_copy(&cp.bdaddr, bdaddr); 308 309 syslog(LOG_DEBUG, "Sending Link_Key_Negative_Reply to %s " 310 "for remote bdaddr %s", 311 dev_name, bt_ntoa(bdaddr, NULL)); 312 313 n = send_hci_cmd(sock, addr, HCI_CMD_LINK_KEY_NEG_REP, sizeof(cp), &cp); 314 } 315 316 if (n < 0) { 317 syslog(LOG_ERR, "Could not send link key reply to %s " 318 "for remote bdaddr %s: %m", 319 dev_name, bt_ntoa(bdaddr, NULL)); 320 return -1; 321 } 322 323 return 0; 324 } 325 326 /* Process Link_Key_Notification event */ 327 static int 328 process_link_key_notification_event(int sock __unused, struct sockaddr_bt *addr, 329 hci_link_key_notification_ep *ep) 330 { 331 332 syslog(LOG_DEBUG, "Got Link_Key_Notification event from %s, " 333 "remote bdaddr %s", 334 dev_name, 335 bt_ntoa(&ep->bdaddr, NULL)); 336 337 save_key(&addr->bt_bdaddr, &ep->bdaddr, ep->key); 338 return 0; 339 } 340 341 /* Send HCI Command Packet to socket */ 342 static int 343 send_hci_cmd(int sock, struct sockaddr_bt *sa, uint16_t opcode, size_t len, void *buf) 344 { 345 char msg[HCI_CMD_PKT_SIZE]; 346 hci_cmd_hdr_t *h = (hci_cmd_hdr_t *)msg; 347 348 h->type = HCI_CMD_PKT; 349 h->opcode = htole16(opcode); 350 h->length = len; 351 352 if (len > 0) 353 memcpy(msg + sizeof(hci_cmd_hdr_t), buf, len); 354 355 return sendto(sock, msg, sizeof(hci_cmd_hdr_t) + len, 0, 356 (struct sockaddr *)sa, sizeof(*sa)); 357 } 358