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 #include <bluetooth.h>
47 static int process_pin_code_request_event
48 (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
49 static int process_link_key_request_event
50 (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
51 static int send_pin_code_reply
52 (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, char const *pin);
53 static int send_link_key_reply
54 (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, uint8_t *key);
55 static int process_link_key_notification_event
56 (int sock, struct sockaddr_hci *addr, ng_hci_link_key_notification_ep *ep);
66 main(int argc, char *argv[])
71 struct sockaddr_hci addr;
72 struct ng_btsocket_hci_raw_filter filter;
73 char buffer[HCSECD_BUFFER_SIZE];
74 ng_hci_event_pkt_t *event = NULL;
78 while ((n = getopt(argc, argv, "df:h")) != -1) {
95 if (config_file == NULL)
100 errx(1, "** ERROR: You should run %s as privileged user!",
103 /* Set signal handlers */
104 memset(&sa, 0, sizeof(sa));
105 sa.sa_handler = sigint;
106 sa.sa_flags = SA_NOCLDWAIT;
107 if (sigaction(SIGINT, &sa, NULL) < 0)
108 err(1, "Could not sigaction(SIGINT)");
109 if (sigaction(SIGTERM, &sa, NULL) < 0)
110 err(1, "Could not sigaction(SIGINT)");
112 memset(&sa, 0, sizeof(sa));
113 sa.sa_handler = sighup;
114 if (sigaction(SIGHUP, &sa, NULL) < 0)
115 err(1, "Could not sigaction(SIGHUP)");
117 /* Open socket and set filter */
118 sock = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI);
120 err(1, "Could not create HCI socket");
122 memset(&filter, 0, sizeof(filter));
123 bit_set(filter.event_mask, NG_HCI_EVENT_PIN_CODE_REQ - 1);
124 bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_REQ - 1);
125 bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1);
127 if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER,
128 (void * const) &filter, sizeof(filter)) < 0)
129 err(1, "Could not set HCI socket filter");
131 if (detach && daemon(0, 0) < 0)
132 err(1, "Could not daemon()ize");
134 openlog(HCSECD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON);
142 if ((pid = fopen(HCSECD_PIDFILE, "w")) == NULL) {
143 syslog(LOG_ERR, "Could not create PID file %s. %s (%d)",
144 HCSECD_PIDFILE, strerror(errno), errno);
148 fprintf(pid, "%d", getpid());
152 event = (ng_hci_event_pkt_t *) buffer;
155 n = recvfrom(sock, buffer, sizeof(buffer), 0,
156 (struct sockaddr *) &addr, &size);
161 syslog(LOG_ERR, "Could not receive from HCI socket. " \
162 "%s (%d)", strerror(errno), errno);
166 if (event->type != NG_HCI_EVENT_PKT) {
167 syslog(LOG_ERR, "Received unexpected HCI packet, " \
168 "type=%#x", event->type);
172 switch (event->event) {
173 case NG_HCI_EVENT_PIN_CODE_REQ:
174 process_pin_code_request_event(sock, &addr,
175 (bdaddr_p)(event + 1));
178 case NG_HCI_EVENT_LINK_KEY_REQ:
179 process_link_key_request_event(sock, &addr,
180 (bdaddr_p)(event + 1));
183 case NG_HCI_EVENT_LINK_KEY_NOTIFICATION:
184 process_link_key_notification_event(sock, &addr,
185 (ng_hci_link_key_notification_ep *)(event + 1));
189 syslog(LOG_ERR, "Received unexpected HCI event, " \
190 "event=%#x", event->event);
196 if (remove(HCSECD_PIDFILE) < 0)
197 syslog(LOG_ERR, "Could not remove PID file %s. %s (%d)",
198 HCSECD_PIDFILE, strerror(errno), errno);
208 /* Process PIN_Code_Request event */
210 process_pin_code_request_event(int sock, struct sockaddr_hci *addr,
213 link_key_p key = NULL;
215 syslog(LOG_DEBUG, "Got PIN_Code_Request event from '%s', " \
216 "remote bdaddr %s", addr->hci_node,
217 bt_ntoa(bdaddr, NULL));
219 if ((key = get_key(bdaddr, 0)) != NULL) {
220 syslog(LOG_DEBUG, "Found matching entry, " \
221 "remote bdaddr %s, name '%s', PIN code %s",
222 bt_ntoa(&key->bdaddr, NULL),
223 (key->name != NULL)? key->name : "No name",
224 (key->pin != NULL)? "exists" : "doesn't exist");
226 return (send_pin_code_reply(sock, addr, bdaddr, key->pin));
229 syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr %s",
230 bt_ntoa(bdaddr, NULL));
232 return (send_pin_code_reply(sock, addr, bdaddr, NULL));
235 /* Process Link_Key_Request event */
237 process_link_key_request_event(int sock, struct sockaddr_hci *addr,
240 link_key_p key = NULL;
242 syslog(LOG_DEBUG, "Got Link_Key_Request event from '%s', " \
243 "remote bdaddr %s", addr->hci_node,
244 bt_ntoa(bdaddr, NULL));
246 if ((key = get_key(bdaddr, 0)) != NULL) {
247 syslog(LOG_DEBUG, "Found matching entry, " \
248 "remote bdaddr %s, name '%s', link key %s",
249 bt_ntoa(&key->bdaddr, NULL),
250 (key->name != NULL)? key->name : "No name",
251 (key->key != NULL)? "exists" : "doesn't exist");
253 return (send_link_key_reply(sock, addr, bdaddr, key->key));
256 syslog(LOG_DEBUG, "Could not find link key for remote bdaddr %s",
257 bt_ntoa(bdaddr, NULL));
259 return (send_link_key_reply(sock, addr, bdaddr, NULL));
262 /* Send PIN_Code_[Negative]_Reply */
264 send_pin_code_reply(int sock, struct sockaddr_hci *addr,
265 bdaddr_p bdaddr, char const *pin)
267 uint8_t buffer[HCSECD_BUFFER_SIZE];
268 ng_hci_cmd_pkt_t *cmd = NULL;
270 memset(buffer, 0, sizeof(buffer));
272 cmd = (ng_hci_cmd_pkt_t *) buffer;
273 cmd->type = NG_HCI_CMD_PKT;
276 ng_hci_pin_code_rep_cp *cp = NULL;
278 cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
279 NG_HCI_OCF_PIN_CODE_REP));
280 cmd->length = sizeof(*cp);
282 cp = (ng_hci_pin_code_rep_cp *)(cmd + 1);
283 memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
284 strncpy((char *) cp->pin, pin, sizeof(cp->pin));
285 cp->pin_size = strlen((char const *) cp->pin);
287 syslog(LOG_DEBUG, "Sending PIN_Code_Reply to '%s' " \
288 "for remote bdaddr %s",
289 addr->hci_node, bt_ntoa(bdaddr, NULL));
291 ng_hci_pin_code_neg_rep_cp *cp = NULL;
293 cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
294 NG_HCI_OCF_PIN_CODE_NEG_REP));
295 cmd->length = sizeof(*cp);
297 cp = (ng_hci_pin_code_neg_rep_cp *)(cmd + 1);
298 memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
300 syslog(LOG_DEBUG, "Sending PIN_Code_Negative_Reply to '%s' " \
301 "for remote bdaddr %s",
302 addr->hci_node, bt_ntoa(bdaddr, NULL));
306 if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
307 (struct sockaddr *) addr, sizeof(*addr)) < 0) {
311 syslog(LOG_ERR, "Could not send PIN code reply to '%s' " \
312 "for remote bdaddr %s. %s (%d)",
313 addr->hci_node, bt_ntoa(bdaddr, NULL),
314 strerror(errno), errno);
321 /* Send Link_Key_[Negative]_Reply */
323 send_link_key_reply(int sock, struct sockaddr_hci *addr,
324 bdaddr_p bdaddr, uint8_t *key)
326 uint8_t buffer[HCSECD_BUFFER_SIZE];
327 ng_hci_cmd_pkt_t *cmd = NULL;
329 memset(buffer, 0, sizeof(buffer));
331 cmd = (ng_hci_cmd_pkt_t *) buffer;
332 cmd->type = NG_HCI_CMD_PKT;
335 ng_hci_link_key_rep_cp *cp = NULL;
337 cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
338 NG_HCI_OCF_LINK_KEY_REP));
339 cmd->length = sizeof(*cp);
341 cp = (ng_hci_link_key_rep_cp *)(cmd + 1);
342 memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
343 memcpy(&cp->key, key, sizeof(cp->key));
345 syslog(LOG_DEBUG, "Sending Link_Key_Reply to '%s' " \
346 "for remote bdaddr %s",
347 addr->hci_node, bt_ntoa(bdaddr, NULL));
349 ng_hci_link_key_neg_rep_cp *cp = NULL;
351 cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
352 NG_HCI_OCF_LINK_KEY_NEG_REP));
353 cmd->length = sizeof(*cp);
355 cp = (ng_hci_link_key_neg_rep_cp *)(cmd + 1);
356 memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
358 syslog(LOG_DEBUG, "Sending Link_Key_Negative_Reply to '%s' " \
359 "for remote bdaddr %s",
360 addr->hci_node, bt_ntoa(bdaddr, NULL));
364 if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
365 (struct sockaddr *) addr, sizeof(*addr)) < 0) {
369 syslog(LOG_ERR, "Could not send link key reply to '%s' " \
370 "for remote bdaddr %s. %s (%d)",
371 addr->hci_node, bt_ntoa(bdaddr, NULL),
372 strerror(errno), errno);
379 /* Process Link_Key_Notification event */
381 process_link_key_notification_event(int sock, struct sockaddr_hci *addr,
382 ng_hci_link_key_notification_ep *ep)
384 link_key_p key = NULL;
386 syslog(LOG_DEBUG, "Got Link_Key_Notification event from '%s', " \
387 "remote bdaddr %s", addr->hci_node,
388 bt_ntoa(&ep->bdaddr, NULL));
390 if ((key = get_key(&ep->bdaddr, 1)) == NULL) {
391 syslog(LOG_ERR, "Could not find entry for remote bdaddr %s",
392 bt_ntoa(&ep->bdaddr, NULL));
396 syslog(LOG_DEBUG, "Updating link key for the entry, " \
397 "remote bdaddr %s, name '%s', link key %s",
398 bt_ntoa(&key->bdaddr, NULL),
399 (key->name != NULL)? key->name : "No name",
400 (key->key != NULL)? "exists" : "doesn't exist");
402 if (key->key == NULL) {
403 key->key = (uint8_t *) malloc(NG_HCI_KEY_SIZE);
404 if (key->key == NULL) {
405 syslog(LOG_ERR, "Could not allocate link key");
410 memcpy(key->key, &ep->key, NG_HCI_KEY_SIZE);
415 /* Signal handlers */
419 syslog(LOG_DEBUG, "Got SIGHUP (%d)", s);
429 syslog(LOG_DEBUG, "Got signal %d, total number of signals %d",
433 /* Display usage and exit */
438 "Usage: %s [-d] -f config_file [-h]\n" \
440 "\t-d do not detach from terminal\n" \
441 "\t-f config_file use <config_file>\n" \
442 "\t-h display this message\n", HCSECD_IDENT);