xref: /freebsd/usr.sbin/bluetooth/hcsecd/hcsecd.c (revision 42b38843)
11de7b4b8SPedro F. Giffuni /*-
21a63eb31SJulian Elischer  * hcsecd.c
31a63eb31SJulian Elischer  *
44d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
51de7b4b8SPedro F. Giffuni  *
61a63eb31SJulian Elischer  * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
71a63eb31SJulian Elischer  * All rights reserved.
81a63eb31SJulian Elischer  *
91a63eb31SJulian Elischer  * Redistribution and use in source and binary forms, with or without
101a63eb31SJulian Elischer  * modification, are permitted provided that the following conditions
111a63eb31SJulian Elischer  * are met:
121a63eb31SJulian Elischer  * 1. Redistributions of source code must retain the above copyright
131a63eb31SJulian Elischer  *    notice, this list of conditions and the following disclaimer.
141a63eb31SJulian Elischer  * 2. Redistributions in binary form must reproduce the above copyright
151a63eb31SJulian Elischer  *    notice, this list of conditions and the following disclaimer in the
161a63eb31SJulian Elischer  *    documentation and/or other materials provided with the distribution.
171a63eb31SJulian Elischer  *
181a63eb31SJulian Elischer  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
191a63eb31SJulian Elischer  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
201a63eb31SJulian Elischer  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
211a63eb31SJulian Elischer  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
221a63eb31SJulian Elischer  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
231a63eb31SJulian Elischer  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
241a63eb31SJulian Elischer  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
251a63eb31SJulian Elischer  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
261a63eb31SJulian Elischer  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
271a63eb31SJulian Elischer  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
281a63eb31SJulian Elischer  * SUCH DAMAGE.
291a63eb31SJulian Elischer  *
300986ab12SMaksim Yevmenkin  * $Id: hcsecd.c,v 1.6 2003/08/18 19:19:55 max Exp $
311a63eb31SJulian Elischer  */
321a63eb31SJulian Elischer 
331a63eb31SJulian Elischer #include <sys/queue.h>
348d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED
350986ab12SMaksim Yevmenkin #include <bluetooth.h>
361a63eb31SJulian Elischer #include <err.h>
371a63eb31SJulian Elischer #include <errno.h>
381a63eb31SJulian Elischer #include <signal.h>
391a63eb31SJulian Elischer #include <stdarg.h>
401a63eb31SJulian Elischer #include <stdio.h>
411a63eb31SJulian Elischer #include <stdlib.h>
421a63eb31SJulian Elischer #include <string.h>
431a63eb31SJulian Elischer #include <syslog.h>
441a63eb31SJulian Elischer #include <unistd.h>
451a63eb31SJulian Elischer #include "hcsecd.h"
461a63eb31SJulian Elischer 
471a63eb31SJulian Elischer static int	done = 0;
481a63eb31SJulian Elischer 
491a63eb31SJulian Elischer static int process_pin_code_request_event
501a63eb31SJulian Elischer 	(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
511a63eb31SJulian Elischer static int process_link_key_request_event
521a63eb31SJulian Elischer 	(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
531a63eb31SJulian Elischer static int send_pin_code_reply
541a63eb31SJulian Elischer 	(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, char const *pin);
551a63eb31SJulian Elischer static int send_link_key_reply
56079a8a3eSMaksim Yevmenkin 	(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, uint8_t *key);
570986ab12SMaksim Yevmenkin static int process_link_key_notification_event
580986ab12SMaksim Yevmenkin 	(int sock, struct sockaddr_hci *addr, ng_hci_link_key_notification_ep *ep);
590986ab12SMaksim Yevmenkin static void sighup
600986ab12SMaksim Yevmenkin 	(int s);
611a63eb31SJulian Elischer static void sigint
621a63eb31SJulian Elischer 	(int s);
631a63eb31SJulian Elischer static void usage
641a63eb31SJulian Elischer 	(void);
651a63eb31SJulian Elischer 
661a63eb31SJulian Elischer /* Main */
671a63eb31SJulian Elischer int
main(int argc,char * argv[])681a63eb31SJulian Elischer main(int argc, char *argv[])
691a63eb31SJulian Elischer {
70831a4264SMaksim Yevmenkin 	int					 n, detach, sock;
71831a4264SMaksim Yevmenkin 	socklen_t				 size;
721a63eb31SJulian Elischer 	struct sigaction			 sa;
731a63eb31SJulian Elischer 	struct sockaddr_hci			 addr;
741a63eb31SJulian Elischer 	struct ng_btsocket_hci_raw_filter	 filter;
751a63eb31SJulian Elischer 	char					 buffer[HCSECD_BUFFER_SIZE];
761a63eb31SJulian Elischer 	ng_hci_event_pkt_t			*event = NULL;
771a63eb31SJulian Elischer 
781a63eb31SJulian Elischer 	detach = 1;
791a63eb31SJulian Elischer 
801a63eb31SJulian Elischer 	while ((n = getopt(argc, argv, "df:h")) != -1) {
811a63eb31SJulian Elischer 		switch (n) {
821a63eb31SJulian Elischer 		case 'd':
831a63eb31SJulian Elischer 			detach = 0;
841a63eb31SJulian Elischer 			break;
851a63eb31SJulian Elischer 
861a63eb31SJulian Elischer 		case 'f':
871a63eb31SJulian Elischer 			config_file = optarg;
881a63eb31SJulian Elischer 			break;
891a63eb31SJulian Elischer 
901a63eb31SJulian Elischer 		case 'h':
911a63eb31SJulian Elischer 		default:
921a63eb31SJulian Elischer 			usage();
931a63eb31SJulian Elischer 			/* NOT REACHED */
941a63eb31SJulian Elischer 		}
951a63eb31SJulian Elischer 	}
961a63eb31SJulian Elischer 
971a63eb31SJulian Elischer 	if (config_file == NULL)
981a63eb31SJulian Elischer 		usage();
991a63eb31SJulian Elischer 		/* NOT REACHED */
1001a63eb31SJulian Elischer 
1011a63eb31SJulian Elischer 	if (getuid() != 0)
1021a63eb31SJulian Elischer 		errx(1, "** ERROR: You should run %s as privileged user!",
1031a63eb31SJulian Elischer 			HCSECD_IDENT);
1041a63eb31SJulian Elischer 
1051a63eb31SJulian Elischer 	/* Set signal handlers */
1061a63eb31SJulian Elischer 	memset(&sa, 0, sizeof(sa));
1071a63eb31SJulian Elischer 	sa.sa_handler = sigint;
1081a63eb31SJulian Elischer 	sa.sa_flags = SA_NOCLDWAIT;
1091a63eb31SJulian Elischer 	if (sigaction(SIGINT, &sa, NULL) < 0)
1101a63eb31SJulian Elischer 		err(1, "Could not sigaction(SIGINT)");
1111a63eb31SJulian Elischer 	if (sigaction(SIGTERM, &sa, NULL) < 0)
1121a63eb31SJulian Elischer 		err(1, "Could not sigaction(SIGINT)");
1131a63eb31SJulian Elischer 
1141a63eb31SJulian Elischer 	memset(&sa, 0, sizeof(sa));
1150986ab12SMaksim Yevmenkin 	sa.sa_handler = sighup;
1161a63eb31SJulian Elischer 	if (sigaction(SIGHUP, &sa, NULL) < 0)
1171a63eb31SJulian Elischer 		err(1, "Could not sigaction(SIGHUP)");
1181a63eb31SJulian Elischer 
1191a63eb31SJulian Elischer 	/* Open socket and set filter */
1201a63eb31SJulian Elischer 	sock = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI);
1211a63eb31SJulian Elischer 	if (sock < 0)
1221a63eb31SJulian Elischer 		err(1, "Could not create HCI socket");
1231a63eb31SJulian Elischer 
1241a63eb31SJulian Elischer 	memset(&filter, 0, sizeof(filter));
1251a63eb31SJulian Elischer 	bit_set(filter.event_mask, NG_HCI_EVENT_PIN_CODE_REQ - 1);
1261a63eb31SJulian Elischer 	bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_REQ - 1);
1270986ab12SMaksim Yevmenkin 	bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1);
1281a63eb31SJulian Elischer 
1291a63eb31SJulian Elischer 	if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER,
1301a63eb31SJulian Elischer 			(void * const) &filter, sizeof(filter)) < 0)
1311a63eb31SJulian Elischer 		err(1, "Could not set HCI socket filter");
1321a63eb31SJulian Elischer 
133d37245a0SMaksim Yevmenkin 	if (detach && daemon(0, 0) < 0)
1341a63eb31SJulian Elischer 		err(1, "Could not daemon()ize");
1351a63eb31SJulian Elischer 
1361a63eb31SJulian Elischer 	openlog(HCSECD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON);
1371a63eb31SJulian Elischer 
1380986ab12SMaksim Yevmenkin 	read_config_file();
1390986ab12SMaksim Yevmenkin 	read_keys_file();
1401a63eb31SJulian Elischer 
1411a63eb31SJulian Elischer 	if (detach) {
1421a63eb31SJulian Elischer 		FILE	*pid = NULL;
1431a63eb31SJulian Elischer 
1441a63eb31SJulian Elischer 		if ((pid = fopen(HCSECD_PIDFILE, "w")) == NULL) {
1451a63eb31SJulian Elischer 			syslog(LOG_ERR, "Could not create PID file %s. %s (%d)",
1461a63eb31SJulian Elischer 					HCSECD_PIDFILE, strerror(errno), errno);
1471a63eb31SJulian Elischer 			exit(1);
1481a63eb31SJulian Elischer 		}
1491a63eb31SJulian Elischer 
1501a63eb31SJulian Elischer 		fprintf(pid, "%d", getpid());
1511a63eb31SJulian Elischer 		fclose(pid);
1521a63eb31SJulian Elischer 	}
1531a63eb31SJulian Elischer 
1541a63eb31SJulian Elischer 	event = (ng_hci_event_pkt_t *) buffer;
1551a63eb31SJulian Elischer 	while (!done) {
1561a63eb31SJulian Elischer 		size = sizeof(addr);
1571a63eb31SJulian Elischer 		n = recvfrom(sock, buffer, sizeof(buffer), 0,
1581a63eb31SJulian Elischer 				(struct sockaddr *) &addr, &size);
1591a63eb31SJulian Elischer 		if (n < 0) {
1601a63eb31SJulian Elischer 			if (errno == EINTR)
1611a63eb31SJulian Elischer 				continue;
1621a63eb31SJulian Elischer 
1631a63eb31SJulian Elischer 			syslog(LOG_ERR, "Could not receive from HCI socket. " \
1641a63eb31SJulian Elischer 					"%s (%d)", strerror(errno), errno);
1651a63eb31SJulian Elischer 			exit(1);
1661a63eb31SJulian Elischer 		}
1671a63eb31SJulian Elischer 
1681a63eb31SJulian Elischer 		if (event->type != NG_HCI_EVENT_PKT) {
1691a63eb31SJulian Elischer 			syslog(LOG_ERR, "Received unexpected HCI packet, " \
1701a63eb31SJulian Elischer 					"type=%#x", event->type);
1711a63eb31SJulian Elischer 			continue;
1721a63eb31SJulian Elischer 		}
1731a63eb31SJulian Elischer 
1741a63eb31SJulian Elischer 		switch (event->event) {
1751a63eb31SJulian Elischer 		case NG_HCI_EVENT_PIN_CODE_REQ:
1761a63eb31SJulian Elischer 			process_pin_code_request_event(sock, &addr,
1771a63eb31SJulian Elischer 							(bdaddr_p)(event + 1));
1781a63eb31SJulian Elischer 			break;
1791a63eb31SJulian Elischer 
1801a63eb31SJulian Elischer 		case NG_HCI_EVENT_LINK_KEY_REQ:
1811a63eb31SJulian Elischer 			process_link_key_request_event(sock, &addr,
1821a63eb31SJulian Elischer 							(bdaddr_p)(event + 1));
1831a63eb31SJulian Elischer 			break;
1841a63eb31SJulian Elischer 
1850986ab12SMaksim Yevmenkin 		case NG_HCI_EVENT_LINK_KEY_NOTIFICATION:
1860986ab12SMaksim Yevmenkin 			process_link_key_notification_event(sock, &addr,
1870986ab12SMaksim Yevmenkin 				(ng_hci_link_key_notification_ep *)(event + 1));
1880986ab12SMaksim Yevmenkin 			break;
1890986ab12SMaksim Yevmenkin 
1901a63eb31SJulian Elischer 		default:
1911a63eb31SJulian Elischer 			syslog(LOG_ERR, "Received unexpected HCI event, " \
1921a63eb31SJulian Elischer 					"event=%#x", event->event);
1931a63eb31SJulian Elischer 			break;
1941a63eb31SJulian Elischer 		}
1951a63eb31SJulian Elischer 	}
1961a63eb31SJulian Elischer 
1971a63eb31SJulian Elischer 	if (detach)
1981a63eb31SJulian Elischer 		if (remove(HCSECD_PIDFILE) < 0)
1991a63eb31SJulian Elischer 			syslog(LOG_ERR, "Could not remove PID file %s. %s (%d)",
2001a63eb31SJulian Elischer 					HCSECD_PIDFILE, strerror(errno), errno);
2011a63eb31SJulian Elischer 
2020986ab12SMaksim Yevmenkin 	dump_keys_file();
2031a63eb31SJulian Elischer 	clean_config();
2041a63eb31SJulian Elischer 	closelog();
2051a63eb31SJulian Elischer 	close(sock);
2061a63eb31SJulian Elischer 
2071a63eb31SJulian Elischer 	return (0);
2081a63eb31SJulian Elischer }
2091a63eb31SJulian Elischer 
2101a63eb31SJulian Elischer /* Process PIN_Code_Request event */
2111a63eb31SJulian Elischer static int
process_pin_code_request_event(int sock,struct sockaddr_hci * addr,bdaddr_p bdaddr)2121a63eb31SJulian Elischer process_pin_code_request_event(int sock, struct sockaddr_hci *addr,
2131a63eb31SJulian Elischer 		bdaddr_p bdaddr)
2141a63eb31SJulian Elischer {
2151a63eb31SJulian Elischer 	link_key_p	key = NULL;
2161a63eb31SJulian Elischer 
2171a63eb31SJulian Elischer 	syslog(LOG_DEBUG, "Got PIN_Code_Request event from '%s', " \
2180986ab12SMaksim Yevmenkin 			"remote bdaddr %s", addr->hci_node,
2190986ab12SMaksim Yevmenkin 			bt_ntoa(bdaddr, NULL));
2201a63eb31SJulian Elischer 
2211a63eb31SJulian Elischer 	if ((key = get_key(bdaddr, 0)) != NULL) {
2221a63eb31SJulian Elischer 		syslog(LOG_DEBUG, "Found matching entry, " \
2230986ab12SMaksim Yevmenkin 				"remote bdaddr %s, name '%s', PIN code %s",
2240986ab12SMaksim Yevmenkin 				bt_ntoa(&key->bdaddr, NULL),
2251a63eb31SJulian Elischer 				(key->name != NULL)? key->name : "No name",
2261a63eb31SJulian Elischer 				(key->pin != NULL)? "exists" : "doesn't exist");
2271a63eb31SJulian Elischer 
2281a63eb31SJulian Elischer 		return (send_pin_code_reply(sock, addr, bdaddr, key->pin));
2291a63eb31SJulian Elischer 	}
2301a63eb31SJulian Elischer 
2310986ab12SMaksim Yevmenkin 	syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr %s",
2320986ab12SMaksim Yevmenkin 			bt_ntoa(bdaddr, NULL));
2331a63eb31SJulian Elischer 
2341a63eb31SJulian Elischer 	return (send_pin_code_reply(sock, addr, bdaddr, NULL));
2351a63eb31SJulian Elischer }
2361a63eb31SJulian Elischer 
2371a63eb31SJulian Elischer /* Process Link_Key_Request event */
2381a63eb31SJulian Elischer static int
process_link_key_request_event(int sock,struct sockaddr_hci * addr,bdaddr_p bdaddr)2391a63eb31SJulian Elischer process_link_key_request_event(int sock, struct sockaddr_hci *addr,
2401a63eb31SJulian Elischer 		bdaddr_p bdaddr)
2411a63eb31SJulian Elischer {
2421a63eb31SJulian Elischer 	link_key_p	key = NULL;
2431a63eb31SJulian Elischer 
2441a63eb31SJulian Elischer 	syslog(LOG_DEBUG, "Got Link_Key_Request event from '%s', " \
2450986ab12SMaksim Yevmenkin 			"remote bdaddr %s", addr->hci_node,
2460986ab12SMaksim Yevmenkin 			bt_ntoa(bdaddr, NULL));
2471a63eb31SJulian Elischer 
2481a63eb31SJulian Elischer 	if ((key = get_key(bdaddr, 0)) != NULL) {
2491a63eb31SJulian Elischer 		syslog(LOG_DEBUG, "Found matching entry, " \
2500986ab12SMaksim Yevmenkin 				"remote bdaddr %s, name '%s', link key %s",
2510986ab12SMaksim Yevmenkin 				bt_ntoa(&key->bdaddr, NULL),
2521a63eb31SJulian Elischer 				(key->name != NULL)? key->name : "No name",
2531a63eb31SJulian Elischer 				(key->key != NULL)? "exists" : "doesn't exist");
2541a63eb31SJulian Elischer 
2551a63eb31SJulian Elischer 		return (send_link_key_reply(sock, addr, bdaddr, key->key));
2561a63eb31SJulian Elischer 	}
2571a63eb31SJulian Elischer 
2580986ab12SMaksim Yevmenkin 	syslog(LOG_DEBUG, "Could not find link key for remote bdaddr %s",
2590986ab12SMaksim Yevmenkin 			bt_ntoa(bdaddr, NULL));
2601a63eb31SJulian Elischer 
2611a63eb31SJulian Elischer 	return (send_link_key_reply(sock, addr, bdaddr, NULL));
2621a63eb31SJulian Elischer }
2631a63eb31SJulian Elischer 
2641a63eb31SJulian Elischer /* Send PIN_Code_[Negative]_Reply */
2651a63eb31SJulian Elischer static int
send_pin_code_reply(int sock,struct sockaddr_hci * addr,bdaddr_p bdaddr,char const * pin)2661a63eb31SJulian Elischer send_pin_code_reply(int sock, struct sockaddr_hci *addr,
2671a63eb31SJulian Elischer 		bdaddr_p bdaddr, char const *pin)
2681a63eb31SJulian Elischer {
269079a8a3eSMaksim Yevmenkin 	uint8_t			 buffer[HCSECD_BUFFER_SIZE];
2701a63eb31SJulian Elischer 	ng_hci_cmd_pkt_t	*cmd = NULL;
2711a63eb31SJulian Elischer 
2721a63eb31SJulian Elischer 	memset(buffer, 0, sizeof(buffer));
2731a63eb31SJulian Elischer 
2741a63eb31SJulian Elischer 	cmd = (ng_hci_cmd_pkt_t *) buffer;
2751a63eb31SJulian Elischer 	cmd->type = NG_HCI_CMD_PKT;
2761a63eb31SJulian Elischer 
2771a63eb31SJulian Elischer 	if (pin != NULL) {
2781a63eb31SJulian Elischer 		ng_hci_pin_code_rep_cp	*cp = NULL;
2791a63eb31SJulian Elischer 
2801a63eb31SJulian Elischer 		cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
2811a63eb31SJulian Elischer 						NG_HCI_OCF_PIN_CODE_REP));
2821a63eb31SJulian Elischer 		cmd->length = sizeof(*cp);
2831a63eb31SJulian Elischer 
2841a63eb31SJulian Elischer 		cp = (ng_hci_pin_code_rep_cp *)(cmd + 1);
2851a63eb31SJulian Elischer 		memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
2866e9bee64SMaksim Yevmenkin 		strncpy((char *) cp->pin, pin, sizeof(cp->pin));
2876e9bee64SMaksim Yevmenkin 		cp->pin_size = strlen((char const *) cp->pin);
2881a63eb31SJulian Elischer 
2891a63eb31SJulian Elischer 		syslog(LOG_DEBUG, "Sending PIN_Code_Reply to '%s' " \
2900986ab12SMaksim Yevmenkin 				"for remote bdaddr %s",
2910986ab12SMaksim Yevmenkin 				addr->hci_node, bt_ntoa(bdaddr, NULL));
2921a63eb31SJulian Elischer 	} else {
2931a63eb31SJulian Elischer 		ng_hci_pin_code_neg_rep_cp	*cp = NULL;
2941a63eb31SJulian Elischer 
2951a63eb31SJulian Elischer 		cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
2961a63eb31SJulian Elischer 						NG_HCI_OCF_PIN_CODE_NEG_REP));
2971a63eb31SJulian Elischer 		cmd->length = sizeof(*cp);
2981a63eb31SJulian Elischer 
2991a63eb31SJulian Elischer 		cp = (ng_hci_pin_code_neg_rep_cp *)(cmd + 1);
3001a63eb31SJulian Elischer 		memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
3011a63eb31SJulian Elischer 
3021a63eb31SJulian Elischer 		syslog(LOG_DEBUG, "Sending PIN_Code_Negative_Reply to '%s' " \
3030986ab12SMaksim Yevmenkin 				"for remote bdaddr %s",
3040986ab12SMaksim Yevmenkin 				addr->hci_node, bt_ntoa(bdaddr, NULL));
3051a63eb31SJulian Elischer 	}
3061a63eb31SJulian Elischer 
3071a63eb31SJulian Elischer again:
3081a63eb31SJulian Elischer 	if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
3091a63eb31SJulian Elischer 			(struct sockaddr *) addr, sizeof(*addr)) < 0) {
3101a63eb31SJulian Elischer 		if (errno == EINTR)
3111a63eb31SJulian Elischer 			goto again;
3121a63eb31SJulian Elischer 
3131a63eb31SJulian Elischer 		syslog(LOG_ERR, "Could not send PIN code reply to '%s' " \
3140986ab12SMaksim Yevmenkin 				"for remote bdaddr %s. %s (%d)",
3150986ab12SMaksim Yevmenkin 				addr->hci_node, bt_ntoa(bdaddr, NULL),
3161a63eb31SJulian Elischer 				strerror(errno), errno);
3171a63eb31SJulian Elischer 		return (-1);
3181a63eb31SJulian Elischer 	}
3191a63eb31SJulian Elischer 
3201a63eb31SJulian Elischer 	return (0);
3211a63eb31SJulian Elischer }
3221a63eb31SJulian Elischer 
3231a63eb31SJulian Elischer /* Send Link_Key_[Negative]_Reply */
3241a63eb31SJulian Elischer static int
send_link_key_reply(int sock,struct sockaddr_hci * addr,bdaddr_p bdaddr,uint8_t * key)3251a63eb31SJulian Elischer send_link_key_reply(int sock, struct sockaddr_hci *addr,
326079a8a3eSMaksim Yevmenkin 		bdaddr_p bdaddr, uint8_t *key)
3271a63eb31SJulian Elischer {
328079a8a3eSMaksim Yevmenkin 	uint8_t			 buffer[HCSECD_BUFFER_SIZE];
3291a63eb31SJulian Elischer 	ng_hci_cmd_pkt_t	*cmd = NULL;
3301a63eb31SJulian Elischer 
3311a63eb31SJulian Elischer 	memset(buffer, 0, sizeof(buffer));
3321a63eb31SJulian Elischer 
3331a63eb31SJulian Elischer 	cmd = (ng_hci_cmd_pkt_t *) buffer;
3341a63eb31SJulian Elischer 	cmd->type = NG_HCI_CMD_PKT;
3351a63eb31SJulian Elischer 
3361a63eb31SJulian Elischer 	if (key != NULL) {
3371a63eb31SJulian Elischer 		ng_hci_link_key_rep_cp	*cp = NULL;
3381a63eb31SJulian Elischer 
3391a63eb31SJulian Elischer 		cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
3401a63eb31SJulian Elischer 						NG_HCI_OCF_LINK_KEY_REP));
3411a63eb31SJulian Elischer 		cmd->length = sizeof(*cp);
3421a63eb31SJulian Elischer 
3431a63eb31SJulian Elischer 		cp = (ng_hci_link_key_rep_cp *)(cmd + 1);
3441a63eb31SJulian Elischer 		memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
3451a63eb31SJulian Elischer 		memcpy(&cp->key, key, sizeof(cp->key));
3461a63eb31SJulian Elischer 
3471a63eb31SJulian Elischer 		syslog(LOG_DEBUG, "Sending Link_Key_Reply to '%s' " \
3480986ab12SMaksim Yevmenkin 				"for remote bdaddr %s",
3490986ab12SMaksim Yevmenkin 				addr->hci_node, bt_ntoa(bdaddr, NULL));
3501a63eb31SJulian Elischer 	} else {
3511a63eb31SJulian Elischer 		ng_hci_link_key_neg_rep_cp	*cp = NULL;
3521a63eb31SJulian Elischer 
3531a63eb31SJulian Elischer 		cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
3541a63eb31SJulian Elischer 						NG_HCI_OCF_LINK_KEY_NEG_REP));
3551a63eb31SJulian Elischer 		cmd->length = sizeof(*cp);
3561a63eb31SJulian Elischer 
3571a63eb31SJulian Elischer 		cp = (ng_hci_link_key_neg_rep_cp *)(cmd + 1);
3581a63eb31SJulian Elischer 		memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
3591a63eb31SJulian Elischer 
3601a63eb31SJulian Elischer 		syslog(LOG_DEBUG, "Sending Link_Key_Negative_Reply to '%s' " \
3610986ab12SMaksim Yevmenkin 				"for remote bdaddr %s",
3620986ab12SMaksim Yevmenkin 				addr->hci_node, bt_ntoa(bdaddr, NULL));
3631a63eb31SJulian Elischer 	}
3641a63eb31SJulian Elischer 
3651a63eb31SJulian Elischer again:
3661a63eb31SJulian Elischer 	if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
3671a63eb31SJulian Elischer 			(struct sockaddr *) addr, sizeof(*addr)) < 0) {
3681a63eb31SJulian Elischer 		if (errno == EINTR)
3691a63eb31SJulian Elischer 			goto again;
3701a63eb31SJulian Elischer 
3711a63eb31SJulian Elischer 		syslog(LOG_ERR, "Could not send link key reply to '%s' " \
3720986ab12SMaksim Yevmenkin 				"for remote bdaddr %s. %s (%d)",
3730986ab12SMaksim Yevmenkin 				addr->hci_node, bt_ntoa(bdaddr, NULL),
3741a63eb31SJulian Elischer 				strerror(errno), errno);
3751a63eb31SJulian Elischer 		return (-1);
3761a63eb31SJulian Elischer 	}
3771a63eb31SJulian Elischer 
3781a63eb31SJulian Elischer 	return (0);
3791a63eb31SJulian Elischer }
3801a63eb31SJulian Elischer 
3810986ab12SMaksim Yevmenkin /* Process Link_Key_Notification event */
3820986ab12SMaksim Yevmenkin static int
process_link_key_notification_event(int sock,struct sockaddr_hci * addr,ng_hci_link_key_notification_ep * ep)3830986ab12SMaksim Yevmenkin process_link_key_notification_event(int sock, struct sockaddr_hci *addr,
3840986ab12SMaksim Yevmenkin 		ng_hci_link_key_notification_ep *ep)
3850986ab12SMaksim Yevmenkin {
3860986ab12SMaksim Yevmenkin 	link_key_p	key = NULL;
3870986ab12SMaksim Yevmenkin 
3880986ab12SMaksim Yevmenkin 	syslog(LOG_DEBUG, "Got Link_Key_Notification event from '%s', " \
3890986ab12SMaksim Yevmenkin 			"remote bdaddr %s", addr->hci_node,
3900986ab12SMaksim Yevmenkin 			bt_ntoa(&ep->bdaddr, NULL));
3910986ab12SMaksim Yevmenkin 
3920986ab12SMaksim Yevmenkin 	if ((key = get_key(&ep->bdaddr, 1)) == NULL) {
3930986ab12SMaksim Yevmenkin 		syslog(LOG_ERR, "Could not find entry for remote bdaddr %s",
3940986ab12SMaksim Yevmenkin 				bt_ntoa(&ep->bdaddr, NULL));
3950986ab12SMaksim Yevmenkin 		return (-1);
3960986ab12SMaksim Yevmenkin 	}
3970986ab12SMaksim Yevmenkin 
3980986ab12SMaksim Yevmenkin 	syslog(LOG_DEBUG, "Updating link key for the entry, " \
3990986ab12SMaksim Yevmenkin 			"remote bdaddr %s, name '%s', link key %s",
4000986ab12SMaksim Yevmenkin 			bt_ntoa(&key->bdaddr, NULL),
4010986ab12SMaksim Yevmenkin 			(key->name != NULL)? key->name : "No name",
4020986ab12SMaksim Yevmenkin 			(key->key != NULL)? "exists" : "doesn't exist");
4030986ab12SMaksim Yevmenkin 
4040986ab12SMaksim Yevmenkin 	if (key->key == NULL) {
405079a8a3eSMaksim Yevmenkin 		key->key = (uint8_t *) malloc(NG_HCI_KEY_SIZE);
4060986ab12SMaksim Yevmenkin 		if (key->key == NULL) {
4070986ab12SMaksim Yevmenkin 			syslog(LOG_ERR, "Could not allocate link key");
4080986ab12SMaksim Yevmenkin 			exit(1);
4090986ab12SMaksim Yevmenkin 		}
4100986ab12SMaksim Yevmenkin 	}
4110986ab12SMaksim Yevmenkin 
4120986ab12SMaksim Yevmenkin 	memcpy(key->key, &ep->key, NG_HCI_KEY_SIZE);
4130986ab12SMaksim Yevmenkin 
4140986ab12SMaksim Yevmenkin 	return (0);
4150986ab12SMaksim Yevmenkin }
4160986ab12SMaksim Yevmenkin 
4170986ab12SMaksim Yevmenkin /* Signal handlers */
4180986ab12SMaksim Yevmenkin static void
sighup(int s)4190986ab12SMaksim Yevmenkin sighup(int s)
4200986ab12SMaksim Yevmenkin {
4210986ab12SMaksim Yevmenkin 	syslog(LOG_DEBUG, "Got SIGHUP (%d)", s);
4220986ab12SMaksim Yevmenkin 
4230986ab12SMaksim Yevmenkin 	dump_keys_file();
4240986ab12SMaksim Yevmenkin 	read_config_file();
4250986ab12SMaksim Yevmenkin 	read_keys_file();
4260986ab12SMaksim Yevmenkin }
4270986ab12SMaksim Yevmenkin 
4281a63eb31SJulian Elischer static void
sigint(int s)4291a63eb31SJulian Elischer sigint(int s)
4301a63eb31SJulian Elischer {
4311a63eb31SJulian Elischer 	syslog(LOG_DEBUG, "Got signal %d, total number of signals %d",
4321a63eb31SJulian Elischer 			s, ++ done);
4331a63eb31SJulian Elischer }
4341a63eb31SJulian Elischer 
4351a63eb31SJulian Elischer /* Display usage and exit */
4361a63eb31SJulian Elischer static void
usage(void)4371a63eb31SJulian Elischer usage(void)
4381a63eb31SJulian Elischer {
4391a63eb31SJulian Elischer 	fprintf(stderr,
4401a63eb31SJulian Elischer "Usage: %s [-d] -f config_file [-h]\n" \
4411a63eb31SJulian Elischer "Where:\n" \
4421a63eb31SJulian Elischer "\t-d              do not detach from terminal\n" \
4431a63eb31SJulian Elischer "\t-f config_file  use <config_file>\n" \
4441a63eb31SJulian Elischer "\t-h              display this message\n", HCSECD_IDENT);
4451a63eb31SJulian Elischer 
4461a63eb31SJulian Elischer 	exit(255);
4471a63eb31SJulian Elischer }
4481a63eb31SJulian Elischer 
449