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 <sys/event.h> 61 #include <sys/types.h> 62 #include <bluetooth.h> 63 #include <errno.h> 64 #include <string.h> 65 #include <syslog.h> 66 #include <unistd.h> 67 68 #include "bthcid.h" 69 70 static int process_pin_code_request_event 71 (int, struct sockaddr_bt *, bdaddr_t *); 72 static int process_link_key_request_event 73 (int, struct sockaddr_bt *, bdaddr_t *); 74 static int process_link_key_notification_event 75 (int, struct sockaddr_bt *, hci_link_key_notification_ep *); 76 77 static int send_link_key_reply 78 (int, struct sockaddr_bt *, bdaddr_t *, uint8_t *); 79 static int send_hci_cmd 80 (int, struct sockaddr_bt *, uint16_t, size_t, void *); 81 82 static char dev_name[HCI_DEVNAME_SIZE]; 83 84 /* Initialise HCI Events */ 85 int 86 init_hci(bdaddr_t *bdaddr) 87 { 88 struct sockaddr_bt sa; 89 struct hci_filter filter; 90 struct kevent change; 91 struct timespec timeout = { 0, 0 }; 92 int hci; 93 94 hci = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI); 95 if (hci < 0) 96 return -1; 97 98 memset(&sa, 0, sizeof(sa)); 99 sa.bt_len = sizeof(sa); 100 sa.bt_family = AF_BLUETOOTH; 101 bdaddr_copy(&sa.bt_bdaddr, bdaddr); 102 if (bind(hci, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 103 close(hci); 104 return -1; 105 } 106 107 memset(&filter, 0, sizeof(filter)); 108 hci_filter_set(HCI_EVENT_PIN_CODE_REQ, &filter); 109 hci_filter_set(HCI_EVENT_LINK_KEY_REQ, &filter); 110 hci_filter_set(HCI_EVENT_LINK_KEY_NOTIFICATION, &filter); 111 112 if (setsockopt(hci, BTPROTO_HCI, SO_HCI_EVT_FILTER, 113 (const void *)&filter, sizeof(filter)) < 0) { 114 close(hci); 115 return -1; 116 } 117 118 EV_SET(&change, hci, EVFILT_READ, EV_ADD, 0, 0, NULL); 119 if (kevent(hci_kq, &change, 1, NULL, 0, &timeout) == -1) { 120 close(hci); 121 return -1; 122 } 123 124 return hci; 125 } 126 127 /* Process an HCI event */ 128 void 129 process_hci(int sock) 130 { 131 char buffer[HCI_EVENT_PKT_SIZE]; 132 hci_event_hdr_t *event = (hci_event_hdr_t *)buffer; 133 struct sockaddr_bt addr; 134 int n; 135 socklen_t size; 136 137 size = sizeof(addr); 138 n = recvfrom(sock, buffer, sizeof(buffer), 0, 139 (struct sockaddr *) &addr, &size); 140 if (n < 0) { 141 syslog(LOG_ERR, "Could not receive from HCI socket: %m"); 142 return; 143 } 144 145 if (event->type != HCI_EVENT_PKT) { 146 syslog(LOG_ERR, "Received unexpected HCI packet, " 147 "type=%#x", event->type); 148 149 return; 150 } 151 152 if (!bt_devname(dev_name, &addr.bt_bdaddr)) 153 strlcpy(dev_name, "unknown", sizeof(dev_name)); 154 155 switch (event->event) { 156 case HCI_EVENT_PIN_CODE_REQ: 157 process_pin_code_request_event(sock, &addr, 158 (bdaddr_t *)(event + 1)); 159 break; 160 161 case HCI_EVENT_LINK_KEY_REQ: 162 process_link_key_request_event(sock, &addr, 163 (bdaddr_t *)(event + 1)); 164 break; 165 166 case HCI_EVENT_LINK_KEY_NOTIFICATION: 167 process_link_key_notification_event(sock, &addr, 168 (hci_link_key_notification_ep *)(event + 1)); 169 break; 170 171 default: 172 syslog(LOG_ERR, "Received unexpected HCI event, " 173 "event=%#x", event->event); 174 break; 175 } 176 177 return; 178 } 179 180 /* Process PIN_Code_Request event */ 181 static int 182 process_pin_code_request_event(int sock, struct sockaddr_bt *addr, 183 bdaddr_t *bdaddr) 184 { 185 /* TODO: Add search pin in config file */ 186 187 uint8_t *pin; 188 uint8_t *pin2; 189 190 syslog(LOG_DEBUG, "Got PIN_Code_Request event from %s, " 191 "remote bdaddr %s", 192 dev_name, 193 bt_ntoa(bdaddr, NULL)); 194 195 pin = lookup_pin(&addr->bt_bdaddr, bdaddr); 196 if (pin != NULL) 197 return send_pin_code_reply(sock, addr, bdaddr, pin); 198 199 pin2 = lookup_pin_conf(&addr->bt_bdaddr, bdaddr); 200 if (pin2 != NULL) { 201 return send_pin_code_reply(sock, addr, bdaddr, pin2); 202 } 203 204 if (send_client_request(&addr->bt_bdaddr, bdaddr, sock) == 0) 205 return send_pin_code_reply(sock, addr, bdaddr, NULL); 206 207 return 0; 208 } 209 210 /* Process Link_Key_Request event */ 211 static int 212 process_link_key_request_event(int sock, struct sockaddr_bt *addr, 213 bdaddr_t *bdaddr) 214 { 215 uint8_t *key; 216 217 syslog(LOG_DEBUG, 218 "Got Link_Key_Request event from %s, remote bdaddr %s", 219 dev_name, bt_ntoa(bdaddr, NULL)); 220 221 key = lookup_key(&addr->bt_bdaddr, bdaddr); 222 223 if (key != NULL) { 224 syslog(LOG_DEBUG, "Found Key, remote bdaddr %s", 225 bt_ntoa(bdaddr, NULL)); 226 227 return send_link_key_reply(sock, addr, bdaddr, key); 228 } 229 230 syslog(LOG_DEBUG, "Could not find link key for remote bdaddr %s", 231 bt_ntoa(bdaddr, NULL)); 232 233 return send_link_key_reply(sock, addr, bdaddr, NULL); 234 } 235 236 /* Send PIN_Code_[Negative]_Reply */ 237 int 238 send_pin_code_reply(int sock, struct sockaddr_bt *addr, 239 bdaddr_t *bdaddr, uint8_t *pin) 240 { 241 int n; 242 243 if (pin != NULL) { 244 hci_pin_code_rep_cp cp; 245 246 syslog(LOG_DEBUG, "Sending PIN_Code_Reply to %s " 247 "for remote bdaddr %s", 248 dev_name, 249 bt_ntoa(bdaddr, NULL)); 250 251 bdaddr_copy(&cp.bdaddr, bdaddr); 252 memcpy(cp.pin, pin, HCI_PIN_SIZE); 253 254 n = HCI_PIN_SIZE; 255 while (n > 0 && pin[n - 1] == 0) 256 n--; 257 cp.pin_size = n; 258 259 n = send_hci_cmd(sock, addr, 260 HCI_CMD_PIN_CODE_REP, sizeof(cp), &cp); 261 262 } else { 263 syslog(LOG_DEBUG, "Sending PIN_Code_Negative_Reply to %s " 264 "for remote bdaddr %s", 265 dev_name, 266 bt_ntoa(bdaddr, NULL)); 267 268 n = send_hci_cmd(sock, addr, HCI_CMD_PIN_CODE_NEG_REP, 269 sizeof(bdaddr_t), bdaddr); 270 } 271 272 if (n < 0) { 273 syslog(LOG_ERR, "Could not send PIN code reply to %s " 274 "for remote bdaddr %s: %m", 275 dev_name, 276 bt_ntoa(bdaddr, NULL)); 277 278 return -1; 279 } 280 281 return 0; 282 } 283 284 /* Send Link_Key_[Negative]_Reply */ 285 static int 286 send_link_key_reply(int sock, struct sockaddr_bt *addr, 287 bdaddr_t *bdaddr, uint8_t *key) 288 { 289 int n; 290 291 if (key != NULL) { 292 hci_link_key_rep_cp cp; 293 294 bdaddr_copy(&cp.bdaddr, bdaddr); 295 memcpy(&cp.key, key, sizeof(cp.key)); 296 297 syslog(LOG_DEBUG, "Sending Link_Key_Reply to %s " 298 "for remote bdaddr %s", 299 dev_name, bt_ntoa(bdaddr, NULL)); 300 301 n = send_hci_cmd(sock, addr, HCI_CMD_LINK_KEY_REP, sizeof(cp), &cp); 302 } else { 303 hci_link_key_neg_rep_cp cp; 304 305 bdaddr_copy(&cp.bdaddr, bdaddr); 306 307 syslog(LOG_DEBUG, "Sending Link_Key_Negative_Reply to %s " 308 "for remote bdaddr %s", 309 dev_name, bt_ntoa(bdaddr, NULL)); 310 311 n = send_hci_cmd(sock, addr, HCI_CMD_LINK_KEY_NEG_REP, sizeof(cp), &cp); 312 } 313 314 if (n < 0) { 315 syslog(LOG_ERR, "Could not send link key reply to %s " 316 "for remote bdaddr %s: %m", 317 dev_name, bt_ntoa(bdaddr, NULL)); 318 return -1; 319 } 320 321 return 0; 322 } 323 324 /* Process Link_Key_Notification event */ 325 static int 326 process_link_key_notification_event(int sock __unused, struct sockaddr_bt *addr, 327 hci_link_key_notification_ep *ep) 328 { 329 330 syslog(LOG_DEBUG, "Got Link_Key_Notification event from %s, " 331 "remote bdaddr %s", 332 dev_name, 333 bt_ntoa(&ep->bdaddr, NULL)); 334 335 save_key(&addr->bt_bdaddr, &ep->bdaddr, ep->key); 336 return 0; 337 } 338 339 /* Send HCI Command Packet to socket */ 340 static int 341 send_hci_cmd(int sock, struct sockaddr_bt *sa, uint16_t opcode, size_t len, void *buf) 342 { 343 char msg[HCI_CMD_PKT_SIZE]; 344 hci_cmd_hdr_t *h = (hci_cmd_hdr_t *)msg; 345 346 h->type = HCI_CMD_PKT; 347 h->opcode = htole16(opcode); 348 h->length = len; 349 350 if (len > 0) 351 memcpy(msg + sizeof(hci_cmd_hdr_t), buf, len); 352 353 return sendto(sock, msg, sizeof(hci_cmd_hdr_t) + len, 0, 354 (struct sockaddr *)sa, sizeof(*sa)); 355 } 356