4 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * $Id: hcsecd.c,v 1.6 2003/08/18 19:19:55 max Exp $
32 #include <sys/queue.h>
33 #define L2CAP_SOCKET_CHECKED
34 #include <bluetooth.h>
48 static int process_pin_code_request_event
49 (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
50 static int process_link_key_request_event
51 (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
52 static int send_pin_code_reply
53 (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, char const *pin);
54 static int send_link_key_reply
55 (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, uint8_t *key);
56 static int process_link_key_notification_event
57 (int sock, struct sockaddr_hci *addr, ng_hci_link_key_notification_ep *ep);
67 main(int argc, char *argv[])
72 struct sockaddr_hci addr;
73 struct ng_btsocket_hci_raw_filter filter;
74 char buffer[HCSECD_BUFFER_SIZE];
75 ng_hci_event_pkt_t *event = NULL;
79 while ((n = getopt(argc, argv, "df:h")) != -1) {
96 if (config_file == NULL)
101 errx(1, "** ERROR: You should run %s as privileged user!",
104 /* Set signal handlers */
105 memset(&sa, 0, sizeof(sa));
106 sa.sa_handler = sigint;
107 sa.sa_flags = SA_NOCLDWAIT;
108 if (sigaction(SIGINT, &sa, NULL) < 0)
109 err(1, "Could not sigaction(SIGINT)");
110 if (sigaction(SIGTERM, &sa, NULL) < 0)
111 err(1, "Could not sigaction(SIGINT)");
113 memset(&sa, 0, sizeof(sa));
114 sa.sa_handler = sighup;
115 if (sigaction(SIGHUP, &sa, NULL) < 0)
116 err(1, "Could not sigaction(SIGHUP)");
118 /* Open socket and set filter */
119 sock = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI);
121 err(1, "Could not create HCI socket");
123 memset(&filter, 0, sizeof(filter));
124 bit_set(filter.event_mask, NG_HCI_EVENT_PIN_CODE_REQ - 1);
125 bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_REQ - 1);
126 bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1);
128 if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER,
129 (void * const) &filter, sizeof(filter)) < 0)
130 err(1, "Could not set HCI socket filter");
132 if (detach && daemon(0, 0) < 0)
133 err(1, "Could not daemon()ize");
135 openlog(HCSECD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON);
143 if ((pid = fopen(HCSECD_PIDFILE, "w")) == NULL) {
144 syslog(LOG_ERR, "Could not create PID file %s. %s (%d)",
145 HCSECD_PIDFILE, strerror(errno), errno);
149 fprintf(pid, "%d", getpid());
153 event = (ng_hci_event_pkt_t *) buffer;
156 n = recvfrom(sock, buffer, sizeof(buffer), 0,
157 (struct sockaddr *) &addr, &size);
162 syslog(LOG_ERR, "Could not receive from HCI socket. " \
163 "%s (%d)", strerror(errno), errno);
167 if (event->type != NG_HCI_EVENT_PKT) {
168 syslog(LOG_ERR, "Received unexpected HCI packet, " \
169 "type=%#x", event->type);
173 switch (event->event) {
174 case NG_HCI_EVENT_PIN_CODE_REQ:
175 process_pin_code_request_event(sock, &addr,
176 (bdaddr_p)(event + 1));
179 case NG_HCI_EVENT_LINK_KEY_REQ:
180 process_link_key_request_event(sock, &addr,
181 (bdaddr_p)(event + 1));
184 case NG_HCI_EVENT_LINK_KEY_NOTIFICATION:
185 process_link_key_notification_event(sock, &addr,
186 (ng_hci_link_key_notification_ep *)(event + 1));
190 syslog(LOG_ERR, "Received unexpected HCI event, " \
191 "event=%#x", event->event);
197 if (remove(HCSECD_PIDFILE) < 0)
198 syslog(LOG_ERR, "Could not remove PID file %s. %s (%d)",
199 HCSECD_PIDFILE, strerror(errno), errno);
209 /* Process PIN_Code_Request event */
211 process_pin_code_request_event(int sock, struct sockaddr_hci *addr,
214 link_key_p key = NULL;
216 syslog(LOG_DEBUG, "Got PIN_Code_Request event from '%s', " \
217 "remote bdaddr %s", addr->hci_node,
218 bt_ntoa(bdaddr, NULL));
220 if ((key = get_key(bdaddr, 0)) != NULL) {
221 syslog(LOG_DEBUG, "Found matching entry, " \
222 "remote bdaddr %s, name '%s', PIN code %s",
223 bt_ntoa(&key->bdaddr, NULL),
224 (key->name != NULL)? key->name : "No name",
225 (key->pin != NULL)? "exists" : "doesn't exist");
227 return (send_pin_code_reply(sock, addr, bdaddr, key->pin));
230 syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr %s",
231 bt_ntoa(bdaddr, NULL));
233 return (send_pin_code_reply(sock, addr, bdaddr, NULL));
236 /* Process Link_Key_Request event */
238 process_link_key_request_event(int sock, struct sockaddr_hci *addr,
241 link_key_p key = NULL;
243 syslog(LOG_DEBUG, "Got Link_Key_Request event from '%s', " \
244 "remote bdaddr %s", addr->hci_node,
245 bt_ntoa(bdaddr, NULL));
247 if ((key = get_key(bdaddr, 0)) != NULL) {
248 syslog(LOG_DEBUG, "Found matching entry, " \
249 "remote bdaddr %s, name '%s', link key %s",
250 bt_ntoa(&key->bdaddr, NULL),
251 (key->name != NULL)? key->name : "No name",
252 (key->key != NULL)? "exists" : "doesn't exist");
254 return (send_link_key_reply(sock, addr, bdaddr, key->key));
257 syslog(LOG_DEBUG, "Could not find link key for remote bdaddr %s",
258 bt_ntoa(bdaddr, NULL));
260 return (send_link_key_reply(sock, addr, bdaddr, NULL));
263 /* Send PIN_Code_[Negative]_Reply */
265 send_pin_code_reply(int sock, struct sockaddr_hci *addr,
266 bdaddr_p bdaddr, char const *pin)
268 uint8_t buffer[HCSECD_BUFFER_SIZE];
269 ng_hci_cmd_pkt_t *cmd = NULL;
271 memset(buffer, 0, sizeof(buffer));
273 cmd = (ng_hci_cmd_pkt_t *) buffer;
274 cmd->type = NG_HCI_CMD_PKT;
277 ng_hci_pin_code_rep_cp *cp = NULL;
279 cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
280 NG_HCI_OCF_PIN_CODE_REP));
281 cmd->length = sizeof(*cp);
283 cp = (ng_hci_pin_code_rep_cp *)(cmd + 1);
284 memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
285 strncpy((char *) cp->pin, pin, sizeof(cp->pin));
286 cp->pin_size = strlen((char const *) cp->pin);
288 syslog(LOG_DEBUG, "Sending PIN_Code_Reply to '%s' " \
289 "for remote bdaddr %s",
290 addr->hci_node, bt_ntoa(bdaddr, NULL));
292 ng_hci_pin_code_neg_rep_cp *cp = NULL;
294 cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
295 NG_HCI_OCF_PIN_CODE_NEG_REP));
296 cmd->length = sizeof(*cp);
298 cp = (ng_hci_pin_code_neg_rep_cp *)(cmd + 1);
299 memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
301 syslog(LOG_DEBUG, "Sending PIN_Code_Negative_Reply to '%s' " \
302 "for remote bdaddr %s",
303 addr->hci_node, bt_ntoa(bdaddr, NULL));
307 if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
308 (struct sockaddr *) addr, sizeof(*addr)) < 0) {
312 syslog(LOG_ERR, "Could not send PIN code reply to '%s' " \
313 "for remote bdaddr %s. %s (%d)",
314 addr->hci_node, bt_ntoa(bdaddr, NULL),
315 strerror(errno), errno);
322 /* Send Link_Key_[Negative]_Reply */
324 send_link_key_reply(int sock, struct sockaddr_hci *addr,
325 bdaddr_p bdaddr, uint8_t *key)
327 uint8_t buffer[HCSECD_BUFFER_SIZE];
328 ng_hci_cmd_pkt_t *cmd = NULL;
330 memset(buffer, 0, sizeof(buffer));
332 cmd = (ng_hci_cmd_pkt_t *) buffer;
333 cmd->type = NG_HCI_CMD_PKT;
336 ng_hci_link_key_rep_cp *cp = NULL;
338 cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
339 NG_HCI_OCF_LINK_KEY_REP));
340 cmd->length = sizeof(*cp);
342 cp = (ng_hci_link_key_rep_cp *)(cmd + 1);
343 memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
344 memcpy(&cp->key, key, sizeof(cp->key));
346 syslog(LOG_DEBUG, "Sending Link_Key_Reply to '%s' " \
347 "for remote bdaddr %s",
348 addr->hci_node, bt_ntoa(bdaddr, NULL));
350 ng_hci_link_key_neg_rep_cp *cp = NULL;
352 cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
353 NG_HCI_OCF_LINK_KEY_NEG_REP));
354 cmd->length = sizeof(*cp);
356 cp = (ng_hci_link_key_neg_rep_cp *)(cmd + 1);
357 memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
359 syslog(LOG_DEBUG, "Sending Link_Key_Negative_Reply to '%s' " \
360 "for remote bdaddr %s",
361 addr->hci_node, bt_ntoa(bdaddr, NULL));
365 if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
366 (struct sockaddr *) addr, sizeof(*addr)) < 0) {
370 syslog(LOG_ERR, "Could not send link key reply to '%s' " \
371 "for remote bdaddr %s. %s (%d)",
372 addr->hci_node, bt_ntoa(bdaddr, NULL),
373 strerror(errno), errno);
380 /* Process Link_Key_Notification event */
382 process_link_key_notification_event(int sock, struct sockaddr_hci *addr,
383 ng_hci_link_key_notification_ep *ep)
385 link_key_p key = NULL;
387 syslog(LOG_DEBUG, "Got Link_Key_Notification event from '%s', " \
388 "remote bdaddr %s", addr->hci_node,
389 bt_ntoa(&ep->bdaddr, NULL));
391 if ((key = get_key(&ep->bdaddr, 1)) == NULL) {
392 syslog(LOG_ERR, "Could not find entry for remote bdaddr %s",
393 bt_ntoa(&ep->bdaddr, NULL));
397 syslog(LOG_DEBUG, "Updating link key for the entry, " \
398 "remote bdaddr %s, name '%s', link key %s",
399 bt_ntoa(&key->bdaddr, NULL),
400 (key->name != NULL)? key->name : "No name",
401 (key->key != NULL)? "exists" : "doesn't exist");
403 if (key->key == NULL) {
404 key->key = (uint8_t *) malloc(NG_HCI_KEY_SIZE);
405 if (key->key == NULL) {
406 syslog(LOG_ERR, "Could not allocate link key");
411 memcpy(key->key, &ep->key, NG_HCI_KEY_SIZE);
416 /* Signal handlers */
420 syslog(LOG_DEBUG, "Got SIGHUP (%d)", s);
430 syslog(LOG_DEBUG, "Got signal %d, total number of signals %d",
434 /* Display usage and exit */
439 "Usage: %s [-d] -f config_file [-h]\n" \
441 "\t-d do not detach from terminal\n" \
442 "\t-f config_file use <config_file>\n" \
443 "\t-h display this message\n", HCSECD_IDENT);