diff options
author | emax <emax@FreeBSD.org> | 2003-10-12 22:04:24 +0000 |
---|---|---|
committer | emax <emax@FreeBSD.org> | 2003-10-12 22:04:24 +0000 |
commit | 41bb0e8fd2568243020852e22a6d176bccfa60cd (patch) | |
tree | 0ae0c2be63f9f9161693789721b96beb9cabcc77 /usr.sbin/bluetooth | |
parent | 66feac7937e372f502539e7d443aee80a25abe16 (diff) | |
download | FreeBSD-src-41bb0e8fd2568243020852e22a6d176bccfa60cd.zip FreeBSD-src-41bb0e8fd2568243020852e22a6d176bccfa60cd.tar.gz |
Update Bluetooth code.
Reviewed by: M. Warner Losh <imp@bsdimp.com>; John Hay <jhay@freebsd.org>
Approved by: M. Warner Losh <imp@bsdimp.com> (mentor)
Diffstat (limited to 'usr.sbin/bluetooth')
43 files changed, 1991 insertions, 463 deletions
diff --git a/usr.sbin/bluetooth/Makefile b/usr.sbin/bluetooth/Makefile index 32e1806..916a1aea 100644 --- a/usr.sbin/bluetooth/Makefile +++ b/usr.sbin/bluetooth/Makefile @@ -1,14 +1,16 @@ -# $Id: Makefile,v 1.3 2003/04/01 02:06:47 max Exp $ +# $Id: Makefile,v 1.5 2003/09/08 02:28:35 max Exp $ # $FreeBSD$ -SUBDIR= \ - bt3cfw \ - bcmfw \ - hccontrol \ - hcsecd \ - hcseriald \ - l2control \ - l2ping \ - rfcomm_pppd +SUBDIR= \ + bcmfw \ + bt3cfw \ + hccontrol \ + hcsecd \ + hcseriald \ + l2control \ + l2ping \ + rfcomm_pppd \ + sdpcontrol + .include <bsd.subdir.mk> diff --git a/usr.sbin/bluetooth/Makefile.inc b/usr.sbin/bluetooth/Makefile.inc new file mode 100644 index 0000000..c0e05cf --- /dev/null +++ b/usr.sbin/bluetooth/Makefile.inc @@ -0,0 +1,4 @@ +# $FreeBSD$ + +.include "${.CURDIR}/../../Makefile.inc" + diff --git a/usr.sbin/bluetooth/bcmfw/Makefile b/usr.sbin/bluetooth/bcmfw/Makefile index fc2abca..e601a76 100644 --- a/usr.sbin/bluetooth/bcmfw/Makefile +++ b/usr.sbin/bluetooth/bcmfw/Makefile @@ -1,23 +1,9 @@ -# $Id: Makefile,v 1.2 2003/04/27 00:44:54 max Exp $ +# $Id: Makefile,v 1.6 2003/08/14 20:05:58 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man PROG= bcmfw -MAN8= bcmfw.8 -WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include +MAN= bcmfw.8 SRCS= bcmfw.c +WARNS?= 2 -#FILESDIR= ../local/etc/ -#FILES+= BCM2033-FW.bin BCM2033-MD.hex -#CLEANFILES+= BCM2033-FW.bin BCM2033-MD.hex -# -#BCM2033-FW.bin: BCM2033-FW.bin.uue -# uudecode BCM2033-FW.bin.uue -# -#BCM2033-MD.hex: BCM2033-MD.hex.uue -# uudecode BCM2033-MD.hex.uue -# .include <bsd.prog.mk> -#.include <bsd.files.mk> diff --git a/usr.sbin/bluetooth/bcmfw/bcmfw.8 b/usr.sbin/bluetooth/bcmfw/bcmfw.8 index b961167..d5b984b 100644 --- a/usr.sbin/bluetooth/bcmfw/bcmfw.8 +++ b/usr.sbin/bluetooth/bcmfw/bcmfw.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: bcmfw.8,v 1.4 2003/04/28 17:10:56 max Exp $ +.\" $Id: bcmfw.8,v 1.7 2003/05/21 00:33:40 max Exp $ .\" $FreeBSD$ .\" .Dd March 31, 2003 @@ -51,6 +51,17 @@ The vendor ID should be 0x0a5c .Pq Dv USB_VENDOR_BROADCOM and the product ID should be 0x2033. .Pp +Due to copyright issues I will no longer provide mini-driver and firmware +files for the device. These files can be obtained from the Linux BlueZ BlueFW +package. +.Pp +Visit http://bluez.sourceforge.net/download/download.html for details. +.Pp +I am using the following files: +.Pp +.Dl "MD5 (BCM2033-MD.hex) = 5580317158d07fc4ace90af04f8e1c73" +.Dl "MD5 (BCM2033-FW.bin) = a3a0edfcb85029f4a5d0b1c9649b127d" +.Pp The options are as follows: .Bl -tag -width indent .It Fl f Ar firmware_file_name diff --git a/usr.sbin/bluetooth/bt3cfw/Makefile b/usr.sbin/bluetooth/bt3cfw/Makefile index 6310c0a..daa0f65 100644 --- a/usr.sbin/bluetooth/bt3cfw/Makefile +++ b/usr.sbin/bluetooth/bt3cfw/Makefile @@ -1,13 +1,10 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:06:53 max Exp $ +# $Id: Makefile,v 1.5 2003/08/14 20:06:00 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man PROG= bt3cfw -MAN8= bt3cfw.8 -WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include +MAN= bt3cfw.8 SRCS= bt3cfw.c +WARNS?= 2 DPADD= ${LIBNETGRAPH} LDADD= -lnetgraph diff --git a/usr.sbin/bluetooth/bt3cfw/bt3cfw.8 b/usr.sbin/bluetooth/bt3cfw/bt3cfw.8 index 83a3fcb..74aa6d7 100644 --- a/usr.sbin/bluetooth/bt3cfw/bt3cfw.8 +++ b/usr.sbin/bluetooth/bt3cfw/bt3cfw.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: bt3cfw.8,v 1.3 2003/04/27 19:45:22 max Exp $ +.\" $Id: bt3cfw.8,v 1.4 2003/05/21 00:34:51 max Exp $ .\" $FreeBSD$ .\" .Dd November 11, 2002 diff --git a/usr.sbin/bluetooth/bt3cfw/bt3cfw.c b/usr.sbin/bluetooth/bt3cfw/bt3cfw.c index d0a32a8..02b40ed 100644 --- a/usr.sbin/bluetooth/bt3cfw/bt3cfw.c +++ b/usr.sbin/bluetooth/bt3cfw/bt3cfw.c @@ -25,20 +25,20 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bt3cfw.c,v 1.1 2002/11/24 20:22:37 max Exp $ + * $Id: bt3cfw.c,v 1.2 2003/05/21 22:40:29 max Exp $ * $FreeBSD$ */ #include <sys/types.h> #include <errno.h> #include <netgraph.h> +#include <netgraph/bluetooth/include/ng_bt3c.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <syslog.h> #include <unistd.h> -#include "ng_bt3c.h" #define BT3CFW_IDENT "bt3cfw" #define BT3CFW_MAX_FIRMWARE_SIZE 0xffff diff --git a/usr.sbin/bluetooth/hccontrol/Makefile b/usr.sbin/bluetooth/hccontrol/Makefile index 5b68cd8..592247e 100644 --- a/usr.sbin/bluetooth/hccontrol/Makefile +++ b/usr.sbin/bluetooth/hccontrol/Makefile @@ -1,14 +1,14 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:07:39 max Exp $ +# $Id: Makefile,v 1.7 2003/08/14 20:06:17 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man PROG= hccontrol -MAN8= hccontrol.8 -WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include +MAN= hccontrol.8 SRCS= send_recv.c link_policy.c link_control.c \ host_controller_baseband.c info.c status.c node.c hccontrol.c \ util.c +WARNS?= 2 + +DPADD= ${LIBBLUETOOTH} +LDADD= -lbluetooth .include <bsd.prog.mk> diff --git a/usr.sbin/bluetooth/hccontrol/hccontrol.8 b/usr.sbin/bluetooth/hccontrol/hccontrol.8 index e55635c..559b5f6 100644 --- a/usr.sbin/bluetooth/hccontrol/hccontrol.8 +++ b/usr.sbin/bluetooth/hccontrol/hccontrol.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: hccontrol.8,v 1.3 2003/04/27 19:45:23 max Exp $ +.\" $Id: hccontrol.8,v 1.6 2003/08/06 21:26:38 max Exp $ .\" $FreeBSD$ .\" .Dd June 14, 2002 @@ -33,7 +33,7 @@ .Nd HCI configuration utility .Sh SYNOPSIS .Nm -.Op Fl h +.Op Fl hN .Fl n Ar HCI_node_name .Ar command .Op Ar parameters ... @@ -53,6 +53,11 @@ The options are as follows: .Bl -tag -width indent .It Fl h Display usage message and exit. +.It Fl N +Show Bluetooth addresses as numbers. +Normally +.Nm +attempts to resolve Bluetooth addresses, and display them symbolically. .It Fl n Ar HCI_node_name Connect to the specified HCI Netgraph node. .It Ar command @@ -118,6 +123,10 @@ are: .It Cm Write_SCO_Flow_Control_Enable .It Cm Read_Link_Supervision_Timeout .It Cm Write_Link_Supervision_Timeout +.It Cm Read_Page_Scan_Period_Mode +.It Cm Write_Page_Scan_Period_Mode +.It Cm Read_Page_Scan_Mode +.It Cm Write_Page_Scan_Mode .It Cm Read_Local_Version_Information .It Cm Read_Local_Supported_Features .It Cm Read_Buffer_Size diff --git a/usr.sbin/bluetooth/hccontrol/hccontrol.c b/usr.sbin/bluetooth/hccontrol/hccontrol.c index fafbf7b..0bf5583 100644 --- a/usr.sbin/bluetooth/hccontrol/hccontrol.c +++ b/usr.sbin/bluetooth/hccontrol/hccontrol.c @@ -25,20 +25,15 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: hccontrol.c,v 1.2 2003/04/27 19:45:24 max Exp $ + * $Id: hccontrol.c,v 1.5 2003/09/05 00:38:24 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/socket.h> +#include <bluetooth.h> #include <sys/sysctl.h> #include <assert.h> -#include <bitstring.h> #include <err.h> #include <errno.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -54,6 +49,7 @@ static void usage (void); /* Globals */ int verbose = 0; int timeout; +int numeric_bdaddr = 0; /* Main */ int @@ -63,12 +59,16 @@ main(int argc, char *argv[]) int n; /* Process command line arguments */ - while ((n = getopt(argc, argv, "n:vh")) != -1) { + while ((n = getopt(argc, argv, "n:Nvh")) != -1) { switch (n) { case 'n': node = optarg; break; + case 'N': + numeric_bdaddr = 1; + break; + case 'v': verbose = 1; break; @@ -254,7 +254,7 @@ find_hci_command(char const *command, struct hci_command *category) return (NULL); } /* find_hci_command */ -/* Try to find command in specified category */ +/* Print commands in specified category */ static void print_hci_command(struct hci_command *category) { diff --git a/usr.sbin/bluetooth/hccontrol/hccontrol.h b/usr.sbin/bluetooth/hccontrol/hccontrol.h index d578fea..001ca71 100644 --- a/usr.sbin/bluetooth/hccontrol/hccontrol.h +++ b/usr.sbin/bluetooth/hccontrol/hccontrol.h @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: hccontrol.h,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: hccontrol.h,v 1.2 2003/05/19 17:29:29 max Exp $ * $FreeBSD$ */ @@ -70,6 +70,7 @@ char const * const hci_features2str (u_int8_t *, char *, int); char const * const hci_cc2str (int); char const * const hci_con_state2str (int); char const * const hci_status2str (int); +char const * const hci_bdaddr2str (bdaddr_t const *); #endif /* _HCCONTROL_H_ */ diff --git a/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c b/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c index 5854b00..fd4d60e 100644 --- a/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c +++ b/usr.sbin/bluetooth/hccontrol/host_controller_baseband.c @@ -25,14 +25,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: host_controller_baseband.c,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: host_controller_baseband.c,v 1.4 2003/08/18 19:19:53 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/endian.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> #include <stdio.h> #include <string.h> #include "hccontrol.h" @@ -189,7 +187,7 @@ hci_read_stored_link_key(int s, int argc, char **argv) } ep; } __attribute__ ((packed)) event; - int n,a0,a1,a2,a3,a4,a5; + int n, n1; /* Send command */ memset(&cmd, 0, sizeof(cmd)); @@ -201,16 +199,14 @@ hci_read_stored_link_key(int s, int argc, char **argv) switch (argc) { case 1: /* parse BD_ADDR */ - if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", &a5, &a4, &a3, &a2, - &a1, &a0) != 6) - return (USAGE); + if (!bt_aton(argv[0], &cmd.cp.bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(argv[0])) == NULL) + return (USAGE); - cmd.cp.bdaddr.b[0] = (a0 & 0xff); - cmd.cp.bdaddr.b[1] = (a1 & 0xff); - cmd.cp.bdaddr.b[2] = (a2 & 0xff); - cmd.cp.bdaddr.b[3] = (a3 & 0xff); - cmd.cp.bdaddr.b[4] = (a4 & 0xff); - cmd.cp.bdaddr.b[5] = (a5 & 0xff); + memcpy(&cmd.cp.bdaddr, he->h_addr, sizeof(cmd.cp.bdaddr)); + } break; default: @@ -269,13 +265,11 @@ again: k = (struct _key *)(event.ep.b + sizeof(event.ep.key)); for (n = 0; n < event.ep.key.num_keys; n++) { - fprintf(stdout, "\t%d: %02x:%02x:%02x:%02x:%02x:%02x ", - n + 1, - k->bdaddr.b[5], k->bdaddr.b[4], k->bdaddr.b[3], - k->bdaddr.b[2], k->bdaddr.b[1], k->bdaddr.b[0]); + fprintf(stdout, "\t%d: %s ", + n + 1, hci_bdaddr2str(&k->bdaddr)); - for (a0 = 0; a0 < sizeof(k->key); a0++) - fprintf(stdout, "%02x", k->key[a0]); + for (n1 = 0; n1 < sizeof(k->key); n1++) + fprintf(stdout, "%02x", k->key[n1]); fprintf(stdout, "\n"); k ++; @@ -302,7 +296,7 @@ hci_write_stored_link_key(int s, int argc, char **argv) u_int8_t key[NG_HCI_KEY_SIZE]; } cp; ng_hci_write_stored_link_key_rp rp; - int32_t n, a0, a1, a2, a3, a4, a5; + int32_t n; memset(&cp, 0, sizeof(cp)); @@ -311,16 +305,14 @@ hci_write_stored_link_key(int s, int argc, char **argv) cp.p.num_keys_write = 1; /* parse BD_ADDR */ - if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) - return (USAGE); + if (!bt_aton(argv[0], &cp.bdaddr)) { + struct hostent *he = NULL; - cp.bdaddr.b[0] = (a0 & 0xff); - cp.bdaddr.b[1] = (a1 & 0xff); - cp.bdaddr.b[2] = (a2 & 0xff); - cp.bdaddr.b[3] = (a3 & 0xff); - cp.bdaddr.b[4] = (a4 & 0xff); - cp.bdaddr.b[5] = (a5 & 0xff); + if ((he = bt_gethostbyname(argv[0])) == NULL) + return (USAGE); + + memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); + } /* parse key */ if (hci_hexstring2array(argv[1], cp.key, sizeof(cp.key)) < 0) @@ -357,23 +349,21 @@ hci_delete_stored_link_key(int s, int argc, char **argv) { ng_hci_delete_stored_link_key_cp cp; ng_hci_delete_stored_link_key_rp rp; - int32_t n, a0, a1, a2, a3, a4, a5; + int32_t n; memset(&cp, 0, sizeof(cp)); switch (argc) { case 1: /* parse BD_ADDR */ - if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) - return (USAGE); + if (!bt_aton(argv[0], &cp.bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(argv[0])) == NULL) + return (USAGE); - cp.bdaddr.b[0] = (a0 & 0xff); - cp.bdaddr.b[1] = (a1 & 0xff); - cp.bdaddr.b[2] = (a2 & 0xff); - cp.bdaddr.b[3] = (a3 & 0xff); - cp.bdaddr.b[4] = (a4 & 0xff); - cp.bdaddr.b[5] = (a5 & 0xff); + memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); + } break; default: @@ -1372,6 +1362,131 @@ hci_write_link_supervision_timeout(int s, int argc, char **argv) return (OK); } /* hci_write_link_supervision_timeout */ +/* Send Read_Page_Scan_Period_Mode command to the unit */ +static int +hci_read_page_scan_period_mode(int s, int argc, char **argv) +{ + ng_hci_read_page_scan_period_rp rp; + int n; + + n = sizeof(rp); + if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND, + NG_HCI_OCF_READ_PAGE_SCAN_PERIOD), + (char *) &rp, &n) == ERROR) + return (ERROR); + + if (rp.status != 0x00) { + fprintf(stdout, "Status: %s [%#02x]\n", + hci_status2str(rp.status), rp.status); + return (FAILED); + } + + fprintf(stdout, "Page scan period mode: %#02x\n", + rp.page_scan_period_mode); + + return (OK); +} /* hci_read_page_scan_period_mode */ + +/* Send Write_Page_Scan_Period_Mode command to the unit */ +static int +hci_write_page_scan_period_mode(int s, int argc, char **argv) +{ + ng_hci_write_page_scan_period_cp cp; + ng_hci_write_page_scan_period_rp rp; + int n; + + /* parse command arguments */ + switch (argc) { + case 1: + if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 2) + return (USAGE); + + cp.page_scan_period_mode = (n & 0xff); + break; + + default: + return (USAGE); + } + + /* send command */ + n = sizeof(rp); + if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND, + NG_HCI_OCF_WRITE_PAGE_SCAN_PERIOD), + (char const *) &cp, sizeof(cp), + (char *) &rp, &n) == ERROR) + return (ERROR); + + if (rp.status != 0x00) { + fprintf(stdout, "Status: %s [%#02x]\n", + hci_status2str(rp.status), rp.status); + return (FAILED); + } + + return (OK); +} /* hci_write_page_scan_period_mode */ + +/* Send Read_Page_Scan_Mode command to the unit */ +static int +hci_read_page_scan_mode(int s, int argc, char **argv) +{ + ng_hci_read_page_scan_rp rp; + int n; + + n = sizeof(rp); + if (hci_simple_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND, + NG_HCI_OCF_READ_PAGE_SCAN), + (char *) &rp, &n) == ERROR) + return (ERROR); + + if (rp.status != 0x00) { + fprintf(stdout, "Status: %s [%#02x]\n", + hci_status2str(rp.status), rp.status); + return (FAILED); + } + + fprintf(stdout, "Page scan mode: %#02x\n", rp.page_scan_mode); + + return (OK); +} /* hci_read_page_scan_mode */ + +/* Send Write_Page_Scan_Mode command to the unit */ +static int +hci_write_page_scan_mode(int s, int argc, char **argv) +{ + ng_hci_write_page_scan_cp cp; + ng_hci_write_page_scan_rp rp; + int n; + + /* parse command arguments */ + switch (argc) { + case 1: + if (sscanf(argv[0], "%d", &n) != 1 || n < 0 || n > 3) + return (USAGE); + + cp.page_scan_mode = (n & 0xff); + break; + + default: + return (USAGE); + } + + /* send command */ + n = sizeof(rp); + if (hci_request(s, NG_HCI_OPCODE(NG_HCI_OGF_HC_BASEBAND, + NG_HCI_OCF_WRITE_PAGE_SCAN), + (char const *) &cp, sizeof(cp), + (char *) &rp, &n) == ERROR) + return (ERROR); + + if (rp.status != 0x00) { + fprintf(stdout, "Status: %s [%#02x]\n", + hci_status2str(rp.status), rp.status); + return (FAILED); + } + + return (OK); +} /* hci_write_page_scan_mode */ + struct hci_command host_controller_baseband_commands[] = { { "reset", @@ -1708,6 +1823,55 @@ struct hci_command host_controller_baseband_commands[] = { "\t<timeout> - dddd; timeout measured in number of baseband slots\n", &hci_write_link_supervision_timeout }, +{ +"read_page_scan_period_mode", +"\nThis command is used to read the mandatory Page_Scan_Period_Mode of the\n" \ +"local Bluetooth device. Every time an inquiry response message is sent, the\n"\ +"Bluetooth device will start a timer (T_mandatory_pscan), the value of which\n"\ +"is dependent on the Page_Scan_Period_Mode. As long as this timer has not\n" \ +"expired, the Bluetooth device will use the Page_Scan_Period_Mode for all\n" \ +"following page scans.", +&hci_read_page_scan_period_mode +}, +{ +"write_page_scan_period_mode <page_scan_period_mode>", +"\nThis command is used to write the mandatory Page_Scan_Period_Mode of the\n" \ +"local Bluetooth device. Every time an inquiry response message is sent, the\n"\ +"Bluetooth device will start a timer (T_mandatory_pscan), the value of which\n"\ +"is dependent on the Page_Scan_Period_Mode. As long as this timer has not\n" \ +"expired, the Bluetooth device will use the Page_Scan_Period_Mode for all\n" \ +"following page scans.\n\n" \ +"\t<page_scan_period_mode> - dd; page scan period mode:\n" \ +"\t0x00 - P0 (Default)\n" \ +"\t0x01 - P1\n" \ +"\t0x02 - P2", +&hci_write_page_scan_period_mode +}, +{ +"read_page_scan_mode", +"\nThis command is used to read the default page scan mode of the local\n" \ +"Bluetooth device. The Page_Scan_Mode parameter indicates the page scan mode\n"\ +"that is used for the default page scan. Currently one mandatory page scan\n"\ +"mode and three optional page scan modes are defined. Following an inquiry\n" \ +"response, if the Baseband timer T_mandatory_pscan has not expired, the\n" \ +"mandatory page scan mode must be applied.", +&hci_read_page_scan_mode +}, +{ +"write_page_scan_mode <page_scan_mode>", +"\nThis command is used to write the default page scan mode of the local\n" \ +"Bluetooth device. The Page_Scan_Mode parameter indicates the page scan mode\n"\ +"that is used for the default page scan. Currently, one mandatory page scan\n"\ +"mode and three optional page scan modes are defined. Following an inquiry\n"\ +"response, if the Baseband timer T_mandatory_pscan has not expired, the\n" \ +"mandatory page scan mode must be applied.\n\n" \ +"\t<page_scan_mode> - dd; page scan mode:\n" \ +"\t0x00 - Mandatory Page Scan Mode (Default)\n" \ +"\t0x01 - Optional Page Scan Mode I\n" \ +"\t0x02 - Optional Page Scan Mode II\n" \ +"\t0x03 - Optional Page Scan Mode III", +&hci_write_page_scan_mode +}, { NULL, } }; diff --git a/usr.sbin/bluetooth/hccontrol/info.c b/usr.sbin/bluetooth/hccontrol/info.c index 1a8649f..12b685b 100644 --- a/usr.sbin/bluetooth/hccontrol/info.c +++ b/usr.sbin/bluetooth/hccontrol/info.c @@ -25,14 +25,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: info.c,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: info.c,v 1.3 2003/08/18 19:19:54 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/endian.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> #include <stdio.h> #include <string.h> #include "hccontrol.h" @@ -173,9 +171,7 @@ hci_read_bd_addr(int s, int argc, char **argv) return (FAILED); } - fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - rp.bdaddr.b[5], rp.bdaddr.b[4], rp.bdaddr.b[3], - rp.bdaddr.b[2], rp.bdaddr.b[1], rp.bdaddr.b[0]); + fprintf(stdout, "BD_ADDR: %s\n", bt_ntoa(&rp.bdaddr, NULL)); return (OK); } /* hci_read_bd_addr */ diff --git a/usr.sbin/bluetooth/hccontrol/link_control.c b/usr.sbin/bluetooth/hccontrol/link_control.c index 2f3b4b2..0b8ec84 100644 --- a/usr.sbin/bluetooth/hccontrol/link_control.c +++ b/usr.sbin/bluetooth/hccontrol/link_control.c @@ -25,14 +25,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: link_control.c,v 1.2 2003/03/15 03:07:39 max Exp $ + * $Id: link_control.c,v 1.4 2003/08/18 19:19:54 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/endian.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> #include <stdio.h> #include <string.h> #include "hccontrol.h" @@ -158,9 +156,7 @@ hci_inquiry_response(int n, u_int8_t **b) } *ir = (struct inquiry_response *)(*b); fprintf(stdout, "Inquiry result #%d\n", n); - fprintf(stdout, "\tBD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - ir->bdaddr.b[5], ir->bdaddr.b[4], ir->bdaddr.b[3], - ir->bdaddr.b[2], ir->bdaddr.b[1], ir->bdaddr.b[0]); + fprintf(stdout, "\tBD_ADDR: %s\n", hci_bdaddr2str(&ir->bdaddr)); fprintf(stdout, "\tPage Scan Rep. Mode: %#02x\n", ir->page_scan_rep_mode); fprintf(stdout, "\tPage Scan Period Mode: %#02x\n", @@ -179,7 +175,7 @@ hci_inquiry_response(int n, u_int8_t **b) static int hci_create_connection(int s, int argc, char **argv) { - int n0, n1, n2, n3, n4, n5; + int n0; char b[512]; ng_hci_create_con_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; @@ -241,16 +237,14 @@ hci_create_connection(int s, int argc, char **argv) case 1: /* BD_ADDR */ - if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", - &n5, &n4, &n3, &n2, &n1, &n0) != 6) - return (USAGE); + if (!bt_aton(argv[0], &cp.bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(argv[0])) == NULL) + return (USAGE); - cp.bdaddr.b[0] = (n0 & 0xff); - cp.bdaddr.b[1] = (n1 & 0xff); - cp.bdaddr.b[2] = (n2 & 0xff); - cp.bdaddr.b[3] = (n3 & 0xff); - cp.bdaddr.b[4] = (n4 & 0xff); - cp.bdaddr.b[5] = (n5 & 0xff); + memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); + } break; default: @@ -286,9 +280,7 @@ again: return (FAILED); } - fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3], - ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]); + fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Connection handle: %d\n", le16toh(ep->con_handle)); fprintf(stdout, "Encryption mode: %s [%d]\n", @@ -443,9 +435,7 @@ again: return (FAILED); } - fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3], - ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]); + fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Connection handle: %d\n", le16toh(ep->con_handle)); fprintf(stdout, "Encryption mode: %s [%d]\n", @@ -531,7 +521,7 @@ again: static int hci_remote_name_request(int s, int argc, char **argv) { - int n0, n1, n2, n3, n4, n5; + int n0; char b[512]; ng_hci_remote_name_req_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; @@ -566,16 +556,14 @@ hci_remote_name_request(int s, int argc, char **argv) case 1: /* BD_ADDR */ - if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", - &n5, &n4, &n3, &n2, &n1, &n0) != 6) - return (USAGE); + if (!bt_aton(argv[0], &cp.bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(argv[0])) == NULL) + return (USAGE); - cp.bdaddr.b[0] = (n0 & 0xff); - cp.bdaddr.b[1] = (n1 & 0xff); - cp.bdaddr.b[2] = (n2 & 0xff); - cp.bdaddr.b[3] = (n3 & 0xff); - cp.bdaddr.b[4] = (n4 & 0xff); - cp.bdaddr.b[5] = (n5 & 0xff); + memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); + } break; default: @@ -612,9 +600,7 @@ again: return (FAILED); } - fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3], - ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]); + fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Name: %s\n", ep->name); } else goto again; diff --git a/usr.sbin/bluetooth/hccontrol/link_policy.c b/usr.sbin/bluetooth/hccontrol/link_policy.c index 0a40f56..387d601 100644 --- a/usr.sbin/bluetooth/hccontrol/link_policy.c +++ b/usr.sbin/bluetooth/hccontrol/link_policy.c @@ -25,15 +25,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: link_policy.c,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: link_policy.c,v 1.3 2003/08/18 19:19:54 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/endian.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> #include <stdio.h> +#include <string.h> #include "hccontrol.h" /* Send Role Discovery to the unit */ @@ -84,7 +83,7 @@ hci_role_discovery(int s, int argc, char **argv) static int hci_switch_role(int s, int argc, char **argv) { - int n0, n1, n2, n3, n4, n5; + int n0; char b[512]; ng_hci_switch_role_cp cp; ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b; @@ -93,16 +92,14 @@ hci_switch_role(int s, int argc, char **argv) switch (argc) { case 2: /* bdaddr */ - if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x", - &n5, &n4, &n3, &n2, &n1, &n0) != 6) - return (USAGE); + if (!bt_aton(argv[0], &cp.bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(argv[0])) == NULL) + return (USAGE); - cp.bdaddr.b[0] = n0 & 0xff; - cp.bdaddr.b[1] = n1 & 0xff; - cp.bdaddr.b[2] = n2 & 0xff; - cp.bdaddr.b[3] = n3 & 0xff; - cp.bdaddr.b[4] = n4 & 0xff; - cp.bdaddr.b[5] = n5 & 0xff; + memcpy(&cp.bdaddr, he->h_addr, sizeof(cp.bdaddr)); + } /* role */ if (sscanf(argv[1], "%d", &n0) != 1) @@ -144,9 +141,7 @@ again: return (FAILED); } - fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - ep->bdaddr.b[5], ep->bdaddr.b[4], ep->bdaddr.b[3], - ep->bdaddr.b[2], ep->bdaddr.b[1], ep->bdaddr.b[0]); + fprintf(stdout, "BD_ADDR: %s\n", hci_bdaddr2str(&ep->bdaddr)); fprintf(stdout, "Role: %s [%#x]\n", (ep->role == NG_HCI_ROLE_MASTER)? "Master" : "Slave", ep->role); diff --git a/usr.sbin/bluetooth/hccontrol/node.c b/usr.sbin/bluetooth/hccontrol/node.c index 4771027..863d516 100644 --- a/usr.sbin/bluetooth/hccontrol/node.c +++ b/usr.sbin/bluetooth/hccontrol/node.c @@ -25,18 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: node.c,v 1.4 2003/03/23 21:28:17 max Exp $ + * $Id: node.c,v 1.6 2003/07/22 21:14:02 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/socket.h> #include <sys/ioctl.h> -#include <bitstring.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -142,9 +137,7 @@ hci_read_node_bd_addr(int s, int argc, char **argv) if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BDADDR, &r, sizeof(r)) < 0) return (ERROR); - fprintf(stdout, "BD_ADDR: %02x:%02x:%02x:%02x:%02x:%02x\n", - r.bdaddr.b[5], r.bdaddr.b[4], r.bdaddr.b[3], - r.bdaddr.b[2], r.bdaddr.b[1], r.bdaddr.b[0]); + fprintf(stdout, "BD_ADDR: %s\n", bt_ntoa(&r.bdaddr, NULL)); return (OK); } /* hci_read_node_bd_addr */ @@ -243,14 +236,12 @@ hci_read_neighbor_cache(int s, int argc, char **argv) for (n = 0; n < r.num_entries; n++) { fprintf(stdout, -"%02x:%02x:%02x:%02x:%02x:%02x " \ +"%-17.17s " \ "%02x %02x %02x %02x %02x %02x %02x %02x " \ "%#12x " \ "%#9x " \ "%#9x\n", - r.entries[n].bdaddr.b[5], r.entries[n].bdaddr.b[4], - r.entries[n].bdaddr.b[3], r.entries[n].bdaddr.b[2], - r.entries[n].bdaddr.b[1], r.entries[n].bdaddr.b[0], + hci_bdaddr2str(&r.entries[n].bdaddr), r.entries[n].features[0], r.entries[n].features[1], r.entries[n].features[2], r.entries[n].features[3], r.entries[n].features[4], r.entries[n].features[5], @@ -297,7 +288,7 @@ hci_read_connection_list(int s, int argc, char **argv) for (n = 0; n < r.num_connections; n++) { fprintf(stdout, -"%02x:%02x:%02x:%02x:%02x:%02x " \ +"%-17.17s " \ "%6d " \ "%4.4s " \ "%4d " \ @@ -306,12 +297,7 @@ hci_read_connection_list(int s, int argc, char **argv) "%7d " \ "%5d " \ "%s\n", - r.connections[n].bdaddr.b[5], - r.connections[n].bdaddr.b[4], - r.connections[n].bdaddr.b[3], - r.connections[n].bdaddr.b[2], - r.connections[n].bdaddr.b[1], - r.connections[n].bdaddr.b[0], + hci_bdaddr2str(&r.connections[n].bdaddr), r.connections[n].con_handle, (r.connections[n].link_type == NG_HCI_LINK_ACL)? "ACL" : "SCO", diff --git a/usr.sbin/bluetooth/hccontrol/send_recv.c b/usr.sbin/bluetooth/hccontrol/send_recv.c index 43a2e2a..fc9c549 100644 --- a/usr.sbin/bluetooth/hccontrol/send_recv.c +++ b/usr.sbin/bluetooth/hccontrol/send_recv.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: send_recv.c,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: send_recv.c,v 1.2 2003/05/21 22:40:30 max Exp $ * $FreeBSD$ */ @@ -35,7 +35,7 @@ #include <sys/endian.h> #include <assert.h> #include <errno.h> -#include <ng_hci.h> +#include <netgraph/bluetooth/include/ng_hci.h> #include <string.h> #include <unistd.h> #include "hccontrol.h" diff --git a/usr.sbin/bluetooth/hccontrol/status.c b/usr.sbin/bluetooth/hccontrol/status.c index fdbf61f..86dd8c9 100644 --- a/usr.sbin/bluetooth/hccontrol/status.c +++ b/usr.sbin/bluetooth/hccontrol/status.c @@ -25,14 +25,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: status.c,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: status.c,v 1.2 2003/05/21 22:40:30 max Exp $ * $FreeBSD$ */ #include <sys/types.h> #include <sys/endian.h> #include <errno.h> -#include <ng_hci.h> +#include <netgraph/bluetooth/include/ng_hci.h> #include <stdio.h> #include "hccontrol.h" diff --git a/usr.sbin/bluetooth/hccontrol/util.c b/usr.sbin/bluetooth/hccontrol/util.c index 7abe4d4..53b110a 100644 --- a/usr.sbin/bluetooth/hccontrol/util.c +++ b/usr.sbin/bluetooth/hccontrol/util.c @@ -25,11 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: util.c,v 1.1 2002/11/24 20:22:38 max Exp $ + * $Id: util.c,v 1.2 2003/05/19 17:29:29 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> +#include <sys/param.h> +#include <bluetooth.h> +#include <stdio.h> #include <string.h> #define SIZE(x) (sizeof((x))/sizeof((x)[0])) @@ -348,3 +350,29 @@ hci_status2str(int status) return (status >= SIZE(t)? "Unknown error" : t[status]); } /* hci_status2str */ +char const * const +hci_bdaddr2str(bdaddr_t const *ba) +{ + extern int numeric_bdaddr; + static char buffer[MAXHOSTNAMELEN]; + struct hostent *he = NULL; + + if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) { + buffer[0] = '*'; + buffer[1] = 0; + + return (buffer); + } + + if (!numeric_bdaddr && + (he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) { + strlcpy(buffer, he->h_name, sizeof(buffer)); + + return (buffer); + } + + bt_ntoa(ba, buffer); + + return (buffer); +} /* hci_bdaddr2str */ + diff --git a/usr.sbin/bluetooth/hcsecd/Makefile b/usr.sbin/bluetooth/hcsecd/Makefile index b39ac22..d9a106f 100644 --- a/usr.sbin/bluetooth/hcsecd/Makefile +++ b/usr.sbin/bluetooth/hcsecd/Makefile @@ -1,12 +1,13 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:07:42 max Exp $ +# $Id: Makefile,v 1.8 2003/08/14 20:06:20 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man PROG= hcsecd -MAN8= hcsecd.8 -WARNS?= 1 -CFLAGS+= -g -I${.CURDIR} -I${.CURDIR}/../../../sys/netgraph/bluetooth/include +MAN= hcsecd.8 hcsecd.conf.5 SRCS= hcsecd.c lexer.l parser.y +WARNS?= 1 +CFLAGS+= -I${.CURDIR} + +DPADD= ${LIBBLUETOOTH} +LDADD= -lbluetooth .include <bsd.prog.mk> diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.8 b/usr.sbin/bluetooth/hcsecd/hcsecd.8 index 71ffcb8..1a3bb09 100644 --- a/usr.sbin/bluetooth/hcsecd/hcsecd.8 +++ b/usr.sbin/bluetooth/hcsecd/hcsecd.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: hcsecd.8,v 1.3 2003/04/27 19:45:32 max Exp $ +.\" $Id: hcsecd.8,v 1.8 2003/09/08 18:54:20 max Exp $ .\" $FreeBSD$ .\" .Dd November 16, 2002 @@ -38,22 +38,28 @@ .Sh DESCRIPTION The .Nm -daemon controls link keys and PIN code for Bluetooth devices. +daemon controls link keys and PIN codes for Bluetooth devices. It opens raw HCI socket and listens for the -.Dv Link_Key_Request -and +.Dv Link_Key_Request , .Dv PIN_Code_Request +and +.Dv Link_Key_Notification HCI events. -Once appropriate HCI event has been received, the daemon will +.Pp +Once +.Dv Link_Key_Request +or +.Dv PIN_Code_Request +HCI event is received, the daemon will scan configuration file for matching entry. -The remove device BD_ADDR is used as a key. +The remote device BD_ADDR is used as a key. If no matching entry was found, the default entry will be used. -If no default entry was found then it is assumed that no link key and no PIN code -exist. +If no default entry was found then it is assumed that no link key and no +PIN code exists. For any given entry, link key takes precedence over PIN code. If link key was not specified, it means device must generate link key from PIN code. -If entry was found and has the link key (or PIN code) then the +If entry was found and the link key (or PIN code) exists then the .Dv Link_Key_Request_Reply (or .Dv PIN_Code_Request_Reply ) @@ -66,12 +72,28 @@ command will be sent back to the device. .Pp The .Nm -daemon currently does not handle HCI +daemon also handles HCI .Dv Link_Key_Notification -event and does not cache link keys created from the PIN codes. -It means that the link key only exists while connection is opened. -After the connection has been terminated, the user will have to enter PIN code -again. +event and caches link keys created from the PIN codes in the memory. +To preserve link keys between restarts the +.Nm +daemon dumps link keys for all entries in the +.Pa /var/db/hcsecd.keys +link keys file. +If exists, the link keys file gets processed by +.Nm +daemon after it processes its main configuration file. +The link keys file gets written every time +.Nm +daemon is gracefully shutdown. +It is possible to force +.Nm +daemon to re-read its main configuration file and dump link keys file by sending +.Dv HUP +signal to the +.Nm +process. +User is not expected to modify link keys file by hand. .Pp The command line options are as follows: .Bl -tag -width indent @@ -80,7 +102,7 @@ Do not detach from the controlling terminal. .It Fl f Ar configfile Specify name of the configuration file. The default is -.Pa /usr/local/etc/hcsecd.conf . +.Pa /etc/bluetooth/hcsecd.conf . .It Fl h Display usage message and exit. .El @@ -91,15 +113,15 @@ Everything is based on remote device BD_ADDR. Also might implement interface for external helpers to obtain link keys and PIN codes. .Sh FILES -.Bl -tag -width ".Pa /usr/local/etc/hcsecd.conf" -compact -.It Pa /usr/local/etc/hcsecd.conf -.It Pa /var/run/hcsecd.pid +.Bl -tag -width ".Pa /etc/bluetooth/hcsecd.conf" -compact +.It Pa /etc/bluetooth/hcsecd.conf +.It Pa /var/db/hcsecd.pid +.It Pa /var/run/hcsecd.keys .El .Sh SEE ALSO -.Xr netgraph 3 , -.Xr netgraph 4 , .Xr ng_btsocket 4 , .Xr ng_hci 4 , +.Xr hcsecd.conf 5 , .Xr hccontrol 8 , .Xr hcseriald 8 .Sh AUTHORS diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.c b/usr.sbin/bluetooth/hcsecd/hcsecd.c index 0f72eb7..ac7eacb 100644 --- a/usr.sbin/bluetooth/hcsecd/hcsecd.c +++ b/usr.sbin/bluetooth/hcsecd/hcsecd.c @@ -25,20 +25,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: hcsecd.c,v 1.3 2003/04/27 19:45:32 max Exp $ + * $Id: hcsecd.c,v 1.6 2003/08/18 19:19:55 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/endian.h> -#include <sys/socket.h> #include <sys/queue.h> -#include <bitstring.h> +#include <bluetooth.h> #include <err.h> #include <errno.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> #include <signal.h> #include <stdarg.h> #include <stdio.h> @@ -48,10 +42,6 @@ #include <unistd.h> #include "hcsecd.h" -#define HCSECD_BUFFER_SIZE 512 -#define HCSECD_IDENT "hcsecd" -#define HCSECD_PIDFILE "/var/run/" HCSECD_IDENT ".pid" - static int done = 0; static int process_pin_code_request_event @@ -62,6 +52,10 @@ static int send_pin_code_reply (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, char const *pin); static int send_link_key_reply (int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr, u_int8_t *key); +static int process_link_key_notification_event + (int sock, struct sockaddr_hci *addr, ng_hci_link_key_notification_ep *ep); +static void sighup + (int s); static void sigint (int s); static void usage @@ -115,7 +109,7 @@ main(int argc, char *argv[]) err(1, "Could not sigaction(SIGINT)"); memset(&sa, 0, sizeof(sa)); - sa.sa_handler = read_config_file; + sa.sa_handler = sighup; if (sigaction(SIGHUP, &sa, NULL) < 0) err(1, "Could not sigaction(SIGHUP)"); @@ -127,6 +121,7 @@ main(int argc, char *argv[]) memset(&filter, 0, sizeof(filter)); bit_set(filter.event_mask, NG_HCI_EVENT_PIN_CODE_REQ - 1); bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_REQ - 1); + bit_set(filter.event_mask, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1); if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER, (void * const) &filter, sizeof(filter)) < 0) @@ -138,7 +133,8 @@ main(int argc, char *argv[]) openlog(HCSECD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON); - read_config_file(0); + read_config_file(); + read_keys_file(); if (detach) { FILE *pid = NULL; @@ -184,6 +180,11 @@ main(int argc, char *argv[]) (bdaddr_p)(event + 1)); break; + case NG_HCI_EVENT_LINK_KEY_NOTIFICATION: + process_link_key_notification_event(sock, &addr, + (ng_hci_link_key_notification_ep *)(event + 1)); + break; + default: syslog(LOG_ERR, "Received unexpected HCI event, " \ "event=%#x", event->event); @@ -196,6 +197,7 @@ main(int argc, char *argv[]) syslog(LOG_ERR, "Could not remove PID file %s. %s (%d)", HCSECD_PIDFILE, strerror(errno), errno); + dump_keys_file(); clean_config(); closelog(); close(sock); @@ -211,27 +213,21 @@ process_pin_code_request_event(int sock, struct sockaddr_hci *addr, link_key_p key = NULL; syslog(LOG_DEBUG, "Got PIN_Code_Request event from '%s', " \ - "remote bdaddr %x:%x:%x:%x:%x:%x", addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "remote bdaddr %s", addr->hci_node, + bt_ntoa(bdaddr, NULL)); if ((key = get_key(bdaddr, 0)) != NULL) { syslog(LOG_DEBUG, "Found matching entry, " \ - "remote bdaddr %x:%x:%x:%x:%x:%x, name '%s', " \ - "PIN code %s", - key->bdaddr.b[5], key->bdaddr.b[4], - key->bdaddr.b[3], key->bdaddr.b[2], - key->bdaddr.b[1], key->bdaddr.b[0], + "remote bdaddr %s, name '%s', PIN code %s", + bt_ntoa(&key->bdaddr, NULL), (key->name != NULL)? key->name : "No name", (key->pin != NULL)? "exists" : "doesn't exist"); return (send_pin_code_reply(sock, addr, bdaddr, key->pin)); } - syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr " \ - "%x:%x:%x:%x:%x:%x", - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + syslog(LOG_DEBUG, "Could not PIN code for remote bdaddr %s", + bt_ntoa(bdaddr, NULL)); return (send_pin_code_reply(sock, addr, bdaddr, NULL)); } @@ -244,27 +240,21 @@ process_link_key_request_event(int sock, struct sockaddr_hci *addr, link_key_p key = NULL; syslog(LOG_DEBUG, "Got Link_Key_Request event from '%s', " \ - "remote bdaddr %x:%x:%x:%x:%x:%x", addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "remote bdaddr %s", addr->hci_node, + bt_ntoa(bdaddr, NULL)); if ((key = get_key(bdaddr, 0)) != NULL) { syslog(LOG_DEBUG, "Found matching entry, " \ - "remote bdaddr %x:%x:%x:%x:%x:%x, name '%s', " \ - "link key %s", - key->bdaddr.b[5], key->bdaddr.b[4], - key->bdaddr.b[3], key->bdaddr.b[2], - key->bdaddr.b[1], key->bdaddr.b[0], + "remote bdaddr %s, name '%s', link key %s", + bt_ntoa(&key->bdaddr, NULL), (key->name != NULL)? key->name : "No name", (key->key != NULL)? "exists" : "doesn't exist"); return (send_link_key_reply(sock, addr, bdaddr, key->key)); } - syslog(LOG_DEBUG, "Could not find link key for remote bdaddr " \ - "%x:%x:%x:%x:%x:%x", - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + syslog(LOG_DEBUG, "Could not find link key for remote bdaddr %s", + bt_ntoa(bdaddr, NULL)); return (send_link_key_reply(sock, addr, bdaddr, NULL)); } @@ -295,10 +285,8 @@ send_pin_code_reply(int sock, struct sockaddr_hci *addr, cp->pin_size = strlen(cp->pin); syslog(LOG_DEBUG, "Sending PIN_Code_Reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "for remote bdaddr %s", + addr->hci_node, bt_ntoa(bdaddr, NULL)); } else { ng_hci_pin_code_neg_rep_cp *cp = NULL; @@ -310,10 +298,8 @@ send_pin_code_reply(int sock, struct sockaddr_hci *addr, memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr)); syslog(LOG_DEBUG, "Sending PIN_Code_Negative_Reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "for remote bdaddr %s", + addr->hci_node, bt_ntoa(bdaddr, NULL)); } again: @@ -323,10 +309,8 @@ again: goto again; syslog(LOG_ERR, "Could not send PIN code reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x. %s (%d)", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0], + "for remote bdaddr %s. %s (%d)", + addr->hci_node, bt_ntoa(bdaddr, NULL), strerror(errno), errno); return (-1); } @@ -359,10 +343,8 @@ send_link_key_reply(int sock, struct sockaddr_hci *addr, memcpy(&cp->key, key, sizeof(cp->key)); syslog(LOG_DEBUG, "Sending Link_Key_Reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "for remote bdaddr %s", + addr->hci_node, bt_ntoa(bdaddr, NULL)); } else { ng_hci_link_key_neg_rep_cp *cp = NULL; @@ -374,10 +356,8 @@ send_link_key_reply(int sock, struct sockaddr_hci *addr, memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr)); syslog(LOG_DEBUG, "Sending Link_Key_Negative_Reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0]); + "for remote bdaddr %s", + addr->hci_node, bt_ntoa(bdaddr, NULL)); } again: @@ -387,10 +367,8 @@ again: goto again; syslog(LOG_ERR, "Could not send link key reply to '%s' " \ - "for remote bdaddr %x:%x:%x:%x:%x:%x. %s (%d)", - addr->hci_node, - bdaddr->b[5], bdaddr->b[4], bdaddr->b[3], - bdaddr->b[2], bdaddr->b[1], bdaddr->b[0], + "for remote bdaddr %s. %s (%d)", + addr->hci_node, bt_ntoa(bdaddr, NULL), strerror(errno), errno); return (-1); } @@ -398,7 +376,53 @@ again: return (0); } -/* Signal handler */ +/* Process Link_Key_Notification event */ +static int +process_link_key_notification_event(int sock, struct sockaddr_hci *addr, + ng_hci_link_key_notification_ep *ep) +{ + link_key_p key = NULL; + + syslog(LOG_DEBUG, "Got Link_Key_Notification event from '%s', " \ + "remote bdaddr %s", addr->hci_node, + bt_ntoa(&ep->bdaddr, NULL)); + + if ((key = get_key(&ep->bdaddr, 1)) == NULL) { + syslog(LOG_ERR, "Could not find entry for remote bdaddr %s", + bt_ntoa(&ep->bdaddr, NULL)); + return (-1); + } + + syslog(LOG_DEBUG, "Updating link key for the entry, " \ + "remote bdaddr %s, name '%s', link key %s", + bt_ntoa(&key->bdaddr, NULL), + (key->name != NULL)? key->name : "No name", + (key->key != NULL)? "exists" : "doesn't exist"); + + if (key->key == NULL) { + key->key = (u_int8_t *) malloc(NG_HCI_KEY_SIZE); + if (key->key == NULL) { + syslog(LOG_ERR, "Could not allocate link key"); + exit(1); + } + } + + memcpy(key->key, &ep->key, NG_HCI_KEY_SIZE); + + return (0); +} + +/* Signal handlers */ +static void +sighup(int s) +{ + syslog(LOG_DEBUG, "Got SIGHUP (%d)", s); + + dump_keys_file(); + read_config_file(); + read_keys_file(); +} + static void sigint(int s) { diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.conf.5 b/usr.sbin/bluetooth/hcsecd/hcsecd.conf.5 new file mode 100644 index 0000000..d27025f --- /dev/null +++ b/usr.sbin/bluetooth/hcsecd/hcsecd.conf.5 @@ -0,0 +1,129 @@ +.\" Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: hcsecd.conf.5,v 1.1 2003/05/26 22:49:23 max Exp $ +.\" $FreeBSD$ +.\" +.Dd May 26, 2003 +.Dt HCSECD.CONF 5 +.Os +.Sh NAME +.Nm hcsecd.conf +.Nd +.Xr hcsecd 8 +configuration file +.Sh DESCRIPTION +The +.Nm +file is the configuration file for the +.Xr hcsecd 8 +Bluetooth link keys/PIN codes management daemon. +.Pp +The +.Nm +file is a free-form ASCII text file. +It is parsed by the recursive-descent parser built into +.Xr hcsecd 8 . +The file may contain extra tabs and newlines for formatting purposes. +Keywords in the file are case-sensitive. +Comments may be placed anywhere within the file (except within quotes). +Comments begin with the +.Dq # +character and end at the end of the line. +.Sh FILE FORMAT +The +.Nm +file consists of a list of +.Cm device +entries. +Each +.Cm device +entry defines a link key or PIN code for a remote Bluetooth device. +Each remote Bluetooth device is identified by its unique BD_ADDR. +.Pp +The +.Cm device +entry +.Pp +.Cm device +{ +.Cm option Ar argument ; +.Oo +.Cm option Ar argument ; +.Oc +} +.Pp +The following section describes all supported options and arguments +.Bl -tag -width indent +.It Cm bdaddr Ar BD_ADDR +Specify remote device BD_ADDR for the entry. +.It Cm name Ar device_name +Specify user friendly name for the entry. +Name is a string in a straight double quotes. +.It Cm key Ar link_key +Specify link key for the entry. +Link key is hexadecimal string upto 32 characters in length starting with +.Dq 0x . +.It Cm key nokey +Specify no link key for the entry. +.It Cm pin Ar PIN_code +Specify PIN code for the entry. +PIN code is a string upto 16 characters in length in a straight double quotes. +.It Cm pin nopin +Specify no PIN code for the entry. +.El +.Sh EXAMPLES +A sample +.Nm +file +.Bd -literal +# Default entry is applied if no better match found +# It MUST have 00:00:00:00:00:00 as bdaddr +device { + bdaddr 00:00:00:00:00:00; + name "Default entry"; + key nokey; + pin nopin; +} + +# Ericsson T68 phone +device { + bdaddr 00:80:37:5e:4d:d4; + name "Ericsson T68 phone"; + key nokey; + pin "0000"; # PIN code +} + +# Dummy device +device { + bdaddr 00:11:22:33:44:55; + name "Dummy"; + key 0x00112233445566778899aabbccddeeff; # 16 bytes key + pin nopin; +} +.Ed +.Sh SEE ALSO +.Xr hcsecd 8 +.Sh AUTHORS +.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com diff --git a/usr.sbin/bluetooth/hcsecd/hcsecd.h b/usr.sbin/bluetooth/hcsecd/hcsecd.h index 65820ed..4f53e99 100644 --- a/usr.sbin/bluetooth/hcsecd/hcsecd.h +++ b/usr.sbin/bluetooth/hcsecd/hcsecd.h @@ -25,13 +25,18 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: hcsecd.h,v 1.1 2002/11/24 20:22:39 max Exp $ + * $Id: hcsecd.h,v 1.3 2003/09/08 18:54:21 max Exp $ * $FreeBSD$ */ #ifndef _HCSECD_H_ #define _HCSECD_H_ 1 +#define HCSECD_BUFFER_SIZE 512 +#define HCSECD_IDENT "hcsecd" +#define HCSECD_PIDFILE "/var/run/" HCSECD_IDENT ".pid" +#define HCSECD_KEYSFILE "/var/db/" HCSECD_IDENT ".keys" + struct link_key { bdaddr_t bdaddr; /* remote device BDADDR */ @@ -49,9 +54,12 @@ extern char *config_file; void dump_config (void); #endif -void read_config_file(int s); +void read_config_file(void); void clean_config (void); link_key_p get_key (bdaddr_p bdaddr, int exact_match); +int read_keys_file (void); +int dump_keys_file (void); + #endif /* ndef _HCSECD_H_ */ diff --git a/usr.sbin/bluetooth/hcsecd/parser.y b/usr.sbin/bluetooth/hcsecd/parser.y index 750c068..d2e3696 100644 --- a/usr.sbin/bluetooth/hcsecd/parser.y +++ b/usr.sbin/bluetooth/hcsecd/parser.y @@ -26,14 +26,15 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: parser.y,v 1.1 2002/11/24 20:22:39 max Exp $ + * $Id: parser.y,v 1.5 2003/06/07 21:22:30 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> +#include <sys/fcntl.h> #include <sys/queue.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> +#include <limits.h> #include <stdio.h> #include <stdarg.h> #include <string.h> @@ -49,7 +50,7 @@ static int hexa2int8(char *a); extern int yylineno; static LIST_HEAD(, link_key) link_keys; - char *config_file = "/usr/local/etc/hcsecd.conf"; + char *config_file = "/etc/bluetooth/hcsecd.conf"; static link_key_p key = NULL; %} @@ -82,13 +83,8 @@ line: T_DEVICE { if (get_key(&key->bdaddr, 1) != NULL) { syslog(LOG_ERR, "Ignoring duplicated entry " \ - "for bdaddr %x:%x:%x:%x:%x:%x", - key->bdaddr.b[5], - key->bdaddr.b[4], - key->bdaddr.b[3], - key->bdaddr.b[2], - key->bdaddr.b[1], - key->bdaddr.b[0]); + "for bdaddr %s", + bt_ntoa(&key->bdaddr, NULL)); free_key(key); } else LIST_INSERT_HEAD(&link_keys, key, next); @@ -109,21 +105,11 @@ option: bdaddr bdaddr: T_BDADDR T_BDADDRSTRING { - int a0, a1, a2, a3, a4, a5; - - if (sscanf($2, "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) { + if (!bt_aton($2, &key->bdaddr)) { syslog(LOG_ERR, "Cound not parse BDADDR " \ "'%s'", $2); exit(1); } - - key->bdaddr.b[0] = (a0 & 0xff); - key->bdaddr.b[1] = (a1 & 0xff); - key->bdaddr.b[2] = (a2 & 0xff); - key->bdaddr.b[3] = (a3 & 0xff); - key->bdaddr.b[4] = (a4 & 0xff); - key->bdaddr.b[5] = (a5 & 0xff); } ; @@ -205,7 +191,7 @@ yyerror(char const *message) /* Re-read config file */ void -read_config_file(int s) +read_config_file(void) { extern FILE *yyin; @@ -286,18 +272,125 @@ dump_config(void) syslog(LOG_DEBUG, "device %s " \ -"bdaddr %x:%x:%x:%x:%x:%x " \ +"bdaddr %s " \ "pin %s " \ "key %s", (key->name != NULL)? key->name : "noname", - key->bdaddr.b[5], key->bdaddr.b[4], key->bdaddr.b[3], - key->bdaddr.b[2], key->bdaddr.b[1], key->bdaddr.b[0], + bt_ntoa(&key->bdaddr, NULL), (key->pin != NULL)? key->pin : "nopin", (key->key != NULL)? buffer : "nokey"); } } #endif +/* Read keys file */ +int +read_keys_file(void) +{ + FILE *f = NULL; + link_key_t *key = NULL; + char buf[HCSECD_BUFFER_SIZE], *p = NULL, *cp = NULL; + bdaddr_t bdaddr; + int i, len; + + if ((f = fopen(HCSECD_KEYSFILE, "r")) == NULL) { + if (errno == ENOENT) + return (0); + + syslog(LOG_ERR, "Could not open keys file %s. %s (%d)\n", + HCSECD_KEYSFILE, strerror(errno), errno); + + return (-1); + } + + while ((p = fgets(buf, sizeof(buf), f)) != NULL) { + if (*p == '#') + continue; + if ((cp = strpbrk(p, " ")) == NULL) + continue; + + *cp++ = '\0'; + + if (!bt_aton(p, &bdaddr)) + continue; + + if ((key = get_key(&bdaddr, 1)) == NULL) + continue; + + if (key->key == NULL) { + key->key = (u_int8_t *) malloc(NG_HCI_KEY_SIZE); + if (key->key == NULL) { + syslog(LOG_ERR, "Could not allocate link key"); + exit(1); + } + } + + memset(key->key, 0, NG_HCI_KEY_SIZE); + + len = strlen(cp) / 2; + if (len > NG_HCI_KEY_SIZE) + len = NG_HCI_KEY_SIZE; + + for (i = 0; i < len; i ++) + key->key[i] = hexa2int8(cp + 2*i); + + syslog(LOG_DEBUG, "Restored link key for the entry, " \ + "remote bdaddr %s, name '%s'", + bt_ntoa(&key->bdaddr, NULL), + (key->name != NULL)? key->name : "No name"); + } + + fclose(f); + + return (0); +} + +/* Dump keys file */ +int +dump_keys_file(void) +{ + link_key_p key = NULL; + char tmp[PATH_MAX], buf[HCSECD_BUFFER_SIZE]; + int f; + + snprintf(tmp, sizeof(tmp), "%s.tmp", HCSECD_KEYSFILE); + if ((f = open(tmp, O_RDWR|O_CREAT|O_TRUNC|O_EXCL, 0600)) < 0) { + syslog(LOG_ERR, "Could not create temp keys file %s. %s (%d)\n", + tmp, strerror(errno), errno); + return (-1); + } + + LIST_FOREACH(key, &link_keys, next) { + if (key->key == NULL) + continue; + + snprintf(buf, sizeof(buf), +"%s %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + bt_ntoa(&key->bdaddr, NULL), + key->key[0], key->key[1], key->key[2], key->key[3], + key->key[4], key->key[5], key->key[6], key->key[7], + key->key[8], key->key[9], key->key[10], key->key[11], + key->key[12], key->key[13], key->key[14], key->key[15]); + + if (write(f, buf, strlen(buf)) < 0) { + syslog(LOG_ERR, "Could not write temp keys file. " \ + "%s (%d)\n", strerror(errno), errno); + break; + } + } + + close(f); + + if (rename(tmp, HCSECD_KEYSFILE) < 0) { + syslog(LOG_ERR, "Could not rename(%s, %s). %s (%d)\n", + tmp, HCSECD_KEYSFILE, strerror(errno), errno); + unlink(tmp); + return (-1); + } + + return (0); +} + /* Free key entry */ static void free_key(link_key_p key) diff --git a/usr.sbin/bluetooth/hcseriald/Makefile b/usr.sbin/bluetooth/hcseriald/Makefile index 4d6b629..f21331b 100644 --- a/usr.sbin/bluetooth/hcseriald/Makefile +++ b/usr.sbin/bluetooth/hcseriald/Makefile @@ -1,15 +1,10 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:07:45 max Exp $ +# $Id: Makefile,v 1.5 2003/08/14 20:06:21 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man - PROG= hcseriald -MAN8= hcseriald.8 - -WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include +MAN= hcseriald.8 SRCS= hcseriald.c +WARNS?= 2 DPADD= ${LIBNETGRAPH} LDADD= -lnetgraph diff --git a/usr.sbin/bluetooth/hcseriald/hcseriald.8 b/usr.sbin/bluetooth/hcseriald/hcseriald.8 index 25b89b3..2bf9c54 100644 --- a/usr.sbin/bluetooth/hcseriald/hcseriald.8 +++ b/usr.sbin/bluetooth/hcseriald/hcseriald.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: hcseriald.8,v 1.2 2003/04/27 19:45:33 max Exp $ +.\" $Id: hcseriald.8,v 1.3 2003/05/21 00:47:26 max Exp $ .\" $FreeBSD$ .\" .Dd June 14, 2002 diff --git a/usr.sbin/bluetooth/hcseriald/hcseriald.c b/usr.sbin/bluetooth/hcseriald/hcseriald.c index a4e7f54..35429ad 100644 --- a/usr.sbin/bluetooth/hcseriald/hcseriald.c +++ b/usr.sbin/bluetooth/hcseriald/hcseriald.c @@ -25,7 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: hcseriald.c,v 1.2 2003/04/27 19:45:33 max Exp $ + * $Id: hcseriald.c,v 1.3 2003/05/21 22:40:32 max Exp $ * $FreeBSD$ */ @@ -34,7 +34,7 @@ #include <netgraph/ng_message.h> #include <netgraph.h> -#include <ng_h4.h> +#include <netgraph/bluetooth/include/ng_h4.h> #include <errno.h> #include <fcntl.h> diff --git a/usr.sbin/bluetooth/l2control/Makefile b/usr.sbin/bluetooth/l2control/Makefile index f6fb501..847ff4b 100644 --- a/usr.sbin/bluetooth/l2control/Makefile +++ b/usr.sbin/bluetooth/l2control/Makefile @@ -1,12 +1,12 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:07:47 max Exp $ +# $Id: Makefile,v 1.7 2003/08/14 20:06:22 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man PROG= l2control -MAN8= l2control.8 -WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include +MAN= l2control.8 SRCS= l2cap.c l2control.c +WARNS?= 2 + +DPADD= ${LIBBLUETOOTH} +LDADD= -lbluetooth .include <bsd.prog.mk> diff --git a/usr.sbin/bluetooth/l2control/l2cap.c b/usr.sbin/bluetooth/l2control/l2cap.c index ca4111d..c23106c 100644 --- a/usr.sbin/bluetooth/l2control/l2cap.c +++ b/usr.sbin/bluetooth/l2control/l2cap.c @@ -25,17 +25,13 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: l2cap.c,v 1.4 2003/04/26 23:11:25 max Exp $ + * $Id: l2cap.c,v 1.5 2003/05/16 19:52:37 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> #include <sys/ioctl.h> -#include <bitstring.h> +#include <bluetooth.h> #include <errno.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -43,6 +39,33 @@ #define SIZE(x) (sizeof((x))/sizeof((x)[0])) +/* Print BDADDR */ +static char * +bdaddrpr(bdaddr_t const *ba) +{ + extern int numeric_bdaddr; + static char str[24]; + struct hostent *he = NULL; + + if (memcmp(ba, NG_HCI_BDADDR_ANY, sizeof(*ba)) == 0) { + str[0] = '*'; + str[1] = 0; + + return (str); + } + + if (!numeric_bdaddr && + (he = bt_gethostbyaddr((char *)ba, sizeof(*ba), AF_BLUETOOTH)) != NULL) { + strlcpy(str, he->h_name, sizeof(str)); + + return (str); + } + + bt_ntoa(ba, str); + + return (str); +} /* bdaddrpr */ + /* Send read_node_flags command to the node */ static int l2cap_read_node_flags(int s, int argc, char **argv) @@ -134,17 +157,12 @@ l2cap_read_connection_list(int s, int argc, char **argv) "Remote BD_ADDR Handle Flags Pending State\n"); for (n = 0; n < r.num_connections; n++) { fprintf(stdout, - "%02x:%02x:%02x:%02x:%02x:%02x " \ + "%-17.17s " \ "%6d " \ "%c%c%c%c%c " \ "%7d " \ "%s\n", - r.connections[n].remote.b[5], - r.connections[n].remote.b[4], - r.connections[n].remote.b[3], - r.connections[n].remote.b[2], - r.connections[n].remote.b[1], - r.connections[n].remote.b[0], + bdaddrpr(&r.connections[n].remote), r.connections[n].con_handle, ((r.connections[n].flags & NG_L2CAP_CON_OUTGOING)? 'O' : 'I'), ((r.connections[n].flags & NG_L2CAP_CON_LP_TIMO)? 'L' : ' '), @@ -197,13 +215,11 @@ l2cap_read_channel_list(int s, int argc, char **argv) "Remote BD_ADDR SCID/ DCID PSM IMTU/ OMTU State\n"); for (n = 0; n < r.num_channels; n++) { fprintf(stdout, - "%02x:%02x:%02x:%02x:%02x:%02x " \ + "%-17.17s " \ "%5d/%5d %5d " \ "%5d/%5d " \ "%s\n", - r.channels[n].remote.b[5], r.channels[n].remote.b[4], - r.channels[n].remote.b[3], r.channels[n].remote.b[2], - r.channels[n].remote.b[1], r.channels[n].remote.b[0], + bdaddrpr(&r.channels[n].remote), r.channels[n].scid, r.channels[n].dcid, r.channels[n].psm, r.channels[n].imtu, r.channels[n].omtu, diff --git a/usr.sbin/bluetooth/l2control/l2control.8 b/usr.sbin/bluetooth/l2control/l2control.8 index dcd05fe..e98f301 100644 --- a/usr.sbin/bluetooth/l2control/l2control.8 +++ b/usr.sbin/bluetooth/l2control/l2control.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: l2control.8,v 1.3 2003/04/27 19:45:34 max Exp $ +.\" $Id: l2control.8,v 1.5 2003/05/21 00:53:00 max Exp $ .\" $FreeBSD$ .\" .Dd June 14, 2002 @@ -33,7 +33,7 @@ .Nd L2CAP configuration utility .Sh SYNOPSIS .Nm -.Op Fl h +.Op Fl hn .Fl a Ar BD_ADDR .Ar command .Op Ar parameters ... @@ -55,6 +55,11 @@ Example: .Fl a Li 00:01:02:03:04:05 . .It Fl h Display usage message and exit. +.It Fl n +Show Bluetooth addresses as numbers. +Normally +.Nm +attempts to resolve Bluetooth addresses, and display them symbolically. .It Ar command One of the supported commands (see below). Special command diff --git a/usr.sbin/bluetooth/l2control/l2control.c b/usr.sbin/bluetooth/l2control/l2control.c index a259657..585021c 100644 --- a/usr.sbin/bluetooth/l2control/l2control.c +++ b/usr.sbin/bluetooth/l2control/l2control.c @@ -25,19 +25,14 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: l2control.c,v 1.3 2003/04/27 19:45:34 max Exp $ + * $Id: l2control.c,v 1.6 2003/09/05 00:38:25 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/socket.h> -#include <bitstring.h> #include <assert.h> +#include <bluetooth.h> #include <err.h> #include <errno.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -52,6 +47,9 @@ static void print_l2cap_command (struct l2cap_command *); static void usage (void); /* Main */ + +int numeric_bdaddr = 0; + int main(int argc, char *argv[]) { @@ -61,24 +59,22 @@ main(int argc, char *argv[]) memset(&bdaddr, 0, sizeof(bdaddr)); /* Process command line arguments */ - while ((n = getopt(argc, argv, "a:h")) != -1) { + while ((n = getopt(argc, argv, "a:nh")) != -1) { switch (n) { - case 'a': { - int a0, a1, a2, a3, a4, a5; + case 'a': + if (!bt_aton(optarg, &bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(optarg)) == NULL) + errx(1, "%s: %s", optarg, hstrerror(h_errno)); - if (sscanf(optarg, "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) { - usage(); - break; + memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); } + break; - bdaddr.b[0] = (a0 & 0xff); - bdaddr.b[1] = (a1 & 0xff); - bdaddr.b[2] = (a2 & 0xff); - bdaddr.b[3] = (a3 & 0xff); - bdaddr.b[4] = (a4 & 0xff); - bdaddr.b[5] = (a5 & 0xff); - } break; + case 'n': + numeric_bdaddr = 1; + break; case 'h': default: @@ -144,10 +140,7 @@ do_l2cap_command(bdaddr_p bdaddr, int argc, char **argv) if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) err(2, -"Could not bind socket, bdaddr=%x:%x:%x:%x:%x:%x", - sa.l2cap_bdaddr.b[5], sa.l2cap_bdaddr.b[4], - sa.l2cap_bdaddr.b[3], sa.l2cap_bdaddr.b[2], - sa.l2cap_bdaddr.b[1], sa.l2cap_bdaddr.b[0]); +"Could not bind socket, bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL)); e = 0x0ffff; if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &e, sizeof(e)) < 0) @@ -200,7 +193,7 @@ find_l2cap_command(char const *command, struct l2cap_command *category) return (NULL); } /* find_l2cap_command */ -/* Try to find command in specified category */ +/* Print commands in specified category */ static void print_l2cap_command(struct l2cap_command *category) { @@ -214,7 +207,7 @@ print_l2cap_command(struct l2cap_command *category) static void usage(void) { - fprintf(stdout, "Usage: l2control -a BD_ADDR [-h] cmd [p1] [..]]\n"); + fprintf(stdout, "Usage: l2control -a BD_ADDR [-n] [-h] cmd [p1] [..]]\n"); exit(255); } /* usage */ diff --git a/usr.sbin/bluetooth/l2ping/Makefile b/usr.sbin/bluetooth/l2ping/Makefile index d99143b..e62d2af 100644 --- a/usr.sbin/bluetooth/l2ping/Makefile +++ b/usr.sbin/bluetooth/l2ping/Makefile @@ -1,12 +1,12 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:07:49 max Exp $ +# $Id: Makefile,v 1.6 2003/08/14 20:06:24 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man PROG= l2ping -MAN8= l2ping.8 +MAN= l2ping.8 SRCS= l2ping.c WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include + +DPADD= ${LIBBLUETOOTH} +LDADD= -lbluetooth .include <bsd.prog.mk> diff --git a/usr.sbin/bluetooth/l2ping/l2ping.8 b/usr.sbin/bluetooth/l2ping/l2ping.8 index 8ecd11e..13e2dfc 100644 --- a/usr.sbin/bluetooth/l2ping/l2ping.8 +++ b/usr.sbin/bluetooth/l2ping/l2ping.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: l2ping.8,v 1.2 2003/04/27 19:45:35 max Exp $ +.\" $Id: l2ping.8,v 1.3 2003/05/21 01:00:19 max Exp $ .\" $FreeBSD$ .\" .Dd June 14, 2002 diff --git a/usr.sbin/bluetooth/l2ping/l2ping.c b/usr.sbin/bluetooth/l2ping/l2ping.c index 5f3bc28..b7ef2a5 100644 --- a/usr.sbin/bluetooth/l2ping/l2ping.c +++ b/usr.sbin/bluetooth/l2ping/l2ping.c @@ -25,27 +25,22 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: l2ping.c,v 1.3 2003/04/27 19:45:36 max Exp $ + * $Id: l2ping.c,v 1.5 2003/05/16 19:54:40 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> #include <sys/ioctl.h> -#include <sys/socket.h> #include <sys/time.h> #include <arpa/inet.h> #include <netinet/in.h> #include <assert.h> -#include <bitstring.h> +#include <bluetooth.h> #include <err.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> static void usage (void); static void tv_sub (struct timeval *, struct timeval const *); @@ -64,11 +59,12 @@ static char const pattern[] = "1234567890-"; int main(int argc, char *argv[]) { - bdaddr_t src, dst; - struct sockaddr_l2cap sa; - struct ng_btsocket_l2cap_raw_ping r; - int n, s, count, wait, flood, fail; - struct timeval a, b; + bdaddr_t src, dst; + struct hostent *he = NULL; + struct sockaddr_l2cap sa; + struct ng_btsocket_l2cap_raw_ping r; + int n, s, count, wait, flood, fail; + struct timeval a, b; /* Set defaults */ memcpy(&src, NG_HCI_BDADDR_ANY, sizeof(src)); @@ -90,31 +86,22 @@ main(int argc, char *argv[]) while ((n = getopt(argc, argv, "a:c:fi:n:s:S:h")) != -1) { switch (n) { case 'a': - case 'S': { - int a0, a1, a2, a3, a4, a5; + if (!bt_aton(optarg, &dst)) { + if ((he = bt_gethostbyname(optarg)) == NULL) + errx(1, "%s: %s", optarg, hstrerror(h_errno)); - if (sscanf(optarg, "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) - usage(); + memcpy(&dst, he->h_addr, sizeof(dst)); + } + break; - if (n == 'a') { - /* destination bdaddr */ - dst.b[0] = (a0 & 0xff); - dst.b[1] = (a1 & 0xff); - dst.b[2] = (a2 & 0xff); - dst.b[3] = (a3 & 0xff); - dst.b[4] = (a4 & 0xff); - dst.b[5] = (a5 & 0xff); - } else { - /* source bdaddr */ - src.b[0] = (a0 & 0xff); - src.b[1] = (a1 & 0xff); - src.b[2] = (a2 & 0xff); - src.b[3] = (a3 & 0xff); - src.b[4] = (a4 & 0xff); - src.b[5] = (a5 & 0xff); + case 'S': + if (!bt_aton(optarg, &src)) { + if ((he = bt_gethostbyname(optarg)) == NULL) + errx(1, "%s: %s", optarg, hstrerror(h_errno)); + + memcpy(&src, he->h_addr, sizeof(src)); } - } break; + break; case 'c': count = atoi(optarg); @@ -162,10 +149,7 @@ main(int argc, char *argv[]) if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) err(3, -"Could not bind socket, src bdaddr=%x:%x:%x:%x:%x:%x", - sa.l2cap_bdaddr.b[5], sa.l2cap_bdaddr.b[4], - sa.l2cap_bdaddr.b[3], sa.l2cap_bdaddr.b[2], - sa.l2cap_bdaddr.b[1], sa.l2cap_bdaddr.b[0]); +"Could not bind socket, src bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL)); memset(&sa, 0, sizeof(sa)); sa.l2cap_len = sizeof(sa); @@ -174,10 +158,7 @@ main(int argc, char *argv[]) if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0) err(4, -"Could not connect socket, dst bdaddr=%x:%x:%x:%x:%x:%x", - sa.l2cap_bdaddr.b[5], sa.l2cap_bdaddr.b[4], - sa.l2cap_bdaddr.b[3], sa.l2cap_bdaddr.b[2], - sa.l2cap_bdaddr.b[1], sa.l2cap_bdaddr.b[0]); +"Could not connect socket, dst bdaddr=%s", bt_ntoa(&sa.l2cap_bdaddr, NULL)); /* Fill pattern */ for (n = 0; n < r.echo_size; ) { @@ -198,10 +179,8 @@ main(int argc, char *argv[]) r.result = errno; fail = 1; /* - warn("Could not ping, dst bdaddr=%x:%x:%x:%x:%x:%x", - r.echo_dst.b[5], r.echo_dst.b[4], - r.echo_dst.b[3], r.echo_dst.b[2], - r.echo_dst.b[1], r.echo_dst.b[0]); + warn("Could not ping, dst bdaddr=%s", + bt_ntoa(&r.echo_dst, NULL)); */ } @@ -211,10 +190,9 @@ main(int argc, char *argv[]) tv_sub(&b, &a); fprintf(stdout, -"%d bytes from %x:%x:%x:%x:%x:%x seq_no=%d time=%.3f ms result=%#x %s\n", - r.echo_size, - dst.b[5], dst.b[4], dst.b[3], - dst.b[2], dst.b[1], dst.b[0], +"%d bytes from %s seq_no=%d time=%.3f ms result=%#x %s\n", + r.echo_size, + bt_ntoa(&dst, NULL), ntohl(*((int *)(r.echo_data))), tv2msec(&b), r.result, ((fail == 0)? "" : strerror(errno))); diff --git a/usr.sbin/bluetooth/rfcomm_pppd/Makefile b/usr.sbin/bluetooth/rfcomm_pppd/Makefile index 0269123..adac64e 100644 --- a/usr.sbin/bluetooth/rfcomm_pppd/Makefile +++ b/usr.sbin/bluetooth/rfcomm_pppd/Makefile @@ -1,13 +1,14 @@ -# $Id: Makefile,v 1.2 2003/03/15 03:07:50 max Exp $ +# $Id: Makefile,v 1.7 2003/09/07 18:32:11 max Exp $ # $FreeBSD$ -DESTDIR= /usr/sbin/ -MANDIR= ../share/man/man +.PATH: ${.CURDIR}/../../../usr.bin/bluetooth/rfcomm_sppd + PROG= rfcomm_pppd -MAN8= rfcomm_pppd.8 +MAN= rfcomm_pppd.8 +SRCS= rfcomm_pppd.c rfcomm_sdp.c WARNS?= 2 -CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include -SRCS= rfcomm_pppd.c -.include <bsd.prog.mk> +DPADD= ${LIBBLUETOOTH} ${LIBSDP} +LDADD= -lbluetooth -lsdp +.include <bsd.prog.mk> diff --git a/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.8 b/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.8 index d6af46d..591a5ce 100644 --- a/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.8 +++ b/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.8 @@ -22,7 +22,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $Id: rfcomm_pppd.8,v 1.5 2003/04/27 19:45:37 max Exp $ +.\" $Id: rfcomm_pppd.8,v 1.7 2003/09/07 18:32:11 max Exp $ .\" $FreeBSD$ .\" .Dd February 4, 2003 @@ -54,7 +54,7 @@ It can operate in two modes: client and server. .Pp In the client mode, .Nm -opens an RFCOMM connection to the specified server's +opens a RFCOMM connection to the specified server's .Ar BD_ADRR and .Ar channel . @@ -75,7 +75,7 @@ and connect to the Internet. .Pp In the server mode, .Nm -opens an RFCOMM socket and listens for incomming connections from remote clients. +opens a RFCOMM socket and listens for incomming connections from remote clients. Once the new incomming connection is accepted, .Nm forks and executes @@ -92,7 +92,7 @@ the standard serial port thus providing network connectivity to remote clients. The options are as follows: .Bl -tag -width indent .It Fl a Ar BD_ADDR -In the client mode, this required option specifies the remote BD_ADDR of the +In the client mode this required option specifies the remote BD_ADDR of the RFCOMM server. In the server mode, this option can be used to specify the local BD_ADDR to listen on. @@ -100,21 +100,32 @@ By default, server will listen on .Dv ANY address. .It Fl C Ar channel -In both client and server modes, this required option specifies RFCOMM channel +In both client and server modes this required option specifies RFCOMM channel to connect to or listen on. +In the server mode RFCOMM channel should be number between 1 and 30. +In the client mode RFCOMM channel could be either number between 1 and 30 or +service name. Supported service names are: +.Cm DUN +for DialUp Networking service and +.Cm LAN +for LAN Access Using PPP service. +If service name was specified instead of numeric RFCOMM channel then +.Nm +utility will try to obtain RFCOMM channel for the service via Service +Discovery Protocol. .It Fl c -Act as an RFCOMM client. +Act as a RFCOMM client. This is the default mode. .It Fl d Do not detach from the controlling terminal, i.e., run in foreground. .It Fl h Display usage message and exit. .It Fl l Ar label -In both client and server modes, this required option specifies which +In both client and server modes this required option specifies which .Xr ppp 8 label will be used. .It Fl s -Act as an RFCOMM server. +Act as a RFCOMM server. .El .Sh PPP CONFIGURATION .Ss Important Notes on PPP Configuration @@ -265,7 +276,7 @@ label. The .Nm utility -is not currently integrated with the SDP (Service Discovery Protocol). +does not register services with local SDP (Service Discovery Protocol) daemon. .Sh SEE ALSO .Xr rfcomm_sppd 1 , .Xr ng_btsocket 4 , diff --git a/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.c b/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.c index 160988e..ec9f4ca4 100644 --- a/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.c +++ b/usr.sbin/bluetooth/rfcomm_pppd/rfcomm_pppd.c @@ -25,18 +25,16 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: rfcomm_pppd.c,v 1.3 2003/04/26 23:59:49 max Exp $ + * $Id: rfcomm_pppd.c,v 1.5 2003/09/07 18:32:11 max Exp $ * $FreeBSD$ */ -#include <sys/types.h> -#include <sys/socket.h> -#include <bitstring.h> +#include <bluetooth.h> +#include <ctype.h> +#include <err.h> #include <errno.h> #include <fcntl.h> -#include <ng_hci.h> -#include <ng_l2cap.h> -#include <ng_btsocket.h> +#include <sdp.h> #include <signal.h> #include <stdarg.h> #include <stdio.h> @@ -47,6 +45,10 @@ #define RFCOMM_PPPD "rfcomm_pppd" +int rfcomm_channel_lookup (bdaddr_t const *local, + bdaddr_t const *remote, + int service, int *channel, int *error); + static void exec_ppp (int s, char *label); static void sighandler (int s); static void usage (void); @@ -58,41 +60,49 @@ int main(int argc, char *argv[]) { struct sockaddr_rfcomm sock_addr; - char *label = NULL; + char *label = NULL, *ep = NULL; bdaddr_t addr; - int s, channel, detach, server; + int s, channel, detach, server, service; pid_t pid; memcpy(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)); channel = 0; detach = 1; server = 0; + service = 0; /* Parse command line arguments */ while ((s = getopt(argc, argv, "a:cC:dhl:s")) != -1) { switch (s) { - case 'a': { /* BDADDR */ - int a0, a1, a2, a3, a4, a5; - - if (sscanf(optarg, "%x:%x:%x:%x:%x:%x", - &a5, &a4, &a3, &a2, &a1, &a0) != 6) - usage(); - /* NOT REACHED */ - - addr.b[0] = a0 & 0xff; - addr.b[1] = a1 & 0xff; - addr.b[2] = a2 & 0xff; - addr.b[3] = a3 & 0xff; - addr.b[4] = a4 & 0xff; - addr.b[5] = a5 & 0xff; - } break; + case 'a': /* BDADDR */ + if (!bt_aton(optarg, &addr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(optarg)) == NULL) + errx(1, "%s: %s", optarg, hstrerror(h_errno)); + + memcpy(&addr, he->h_addr, sizeof(addr)); + } + break; case 'c': /* client */ server = 0; break; case 'C': /* RFCOMM channel */ - channel = atoi(optarg); + channel = strtoul(optarg, &ep, 10); + if (*ep != 0) { + channel = 0; + switch (tolower(optarg[0])) { + case 'd': /* DialUp Networking */ + service = SDP_SERVICE_CLASS_DIALUP_NETWORKING; + break; + + case 'l': /* LAN Access Using PPP */ + service = SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP; + break; + } + } break; case 'd': /* do not detach */ @@ -115,10 +125,22 @@ main(int argc, char *argv[]) } /* Check if we got everything we wanted */ - if ((channel <= 0 || channel > 30) || label == NULL || - (!server && memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0)) - usage(); - /* NOT REACHED */ + if (label == NULL) + errx(1, "Must specify PPP label"); + + if (!server) { + if (memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0) + errx(1, "Must specify server BD_ADDR"); + + /* Check channel, if was not set then obtain it via SDP */ + if (channel == 0 && service != 0) + if (rfcomm_channel_lookup(NULL, &addr, service, + &channel, &s) != 0) + errc(1, s, "Could not obtain RFCOMM channel"); + } + + if (channel <= 0 || channel > 30) + errx(1, "Invalid RFCOMM channel number %d", channel); openlog(RFCOMM_PPPD, LOG_PID | LOG_PERROR | LOG_NDELAY, LOG_USER); diff --git a/usr.sbin/bluetooth/sdpcontrol/Makefile b/usr.sbin/bluetooth/sdpcontrol/Makefile new file mode 100644 index 0000000..c0ec8d4 --- /dev/null +++ b/usr.sbin/bluetooth/sdpcontrol/Makefile @@ -0,0 +1,12 @@ +# $Id: Makefile,v 1.1 2003/09/08 02:27:27 max Exp $ +# $FreeBSD$ + +PROG= sdpcontrol +MAN= sdpcontrol.8 +SRCS= sdpcontrol.c search.c +WARNS?= 2 + +DPADD= ${LIBBLUETOOTH} ${LIBSDP} +LDADD= -lbluetooth -lsdp + +.include <bsd.prog.mk> diff --git a/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.8 b/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.8 new file mode 100644 index 0000000..a7f1f6b --- /dev/null +++ b/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.8 @@ -0,0 +1,100 @@ +.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: sdpcontrol.8,v 1.1 2003/09/08 02:27:27 max Exp $ +.\" $FreeBSD$ +.\" +.Dd September 7, 2003 +.Dt SDPCONTROL 8 +.Os +.Sh NAME +.Nm spdcontrol +.Nd SDP configuration utility +.Sh SYNOPSIS +.Nm +.Op Fl h +.Fl a Ar BD_ADDR +.Ar command +.Op Ar parameters ... +.Sh DESCRIPTION +The +.Nm +utility connects to the remote device with the specified BD_ADDR and attempts +to send query via Service Discovery Protocol (SDP). +The +.Nm +utility will use Service Search Attribute Request and will print results to +the standard output and error messages to the standard error. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl a Ar BD_ADDR +Connect to the remote device with the specified BD_ADDR. +Example: +.Fl a Li 00:01:02:03:04:05 . +.It Fl h +Display usage message and exit. +.It Ar command +One of the supported commands (see below). +Special command +.Cm help +can be used to obtain the list of all supported commands. +To get more information about specific command use +.Cm help Ar command . +.It Ar parameters +One or more optional space separated command parameters. +.El +.Sh COMMANDS +The currently supported node commands in +.Nm +are: +.Pp +.Bl -tag -offset indent -compact +.It Cm Browse +.It Cm Search +.El +.Sh CAVEAT +Currently, the +.Nm +utility only implements client side functionality. +.Pp +The +.Nm +utility only request the following attributes from the remote SDP server: +.Bl -enum -offset indent -compact +.It +Service Record Handle +.It +Service Class ID List +.It +Protocol Descriptor List +.It +Bluetooth Profile Descriptor List +.El +.Sh DIAGNOSTICS +.Ex -std +.Sh SEE ALSO +.Xr sdp 3 +.Sh AUTHORS +.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com diff --git a/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.c b/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.c new file mode 100644 index 0000000..b5a1a4d --- /dev/null +++ b/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.c @@ -0,0 +1,197 @@ +/* + * sdpcontrol.c + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: sdpcontrol.c,v 1.1 2003/09/08 02:27:27 max Exp $ + * $FreeBSD$ + */ + +#include <assert.h> +#include <bluetooth.h> +#include <err.h> +#include <errno.h> +#include <sdp.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "sdpcontrol.h" + +/* Prototypes */ +static int do_sdp_command (bdaddr_p, int, char **); +static struct sdp_command * find_sdp_command (char const *, + struct sdp_command *); +static void print_sdp_command (struct sdp_command *); +static void usage (void); + +/* Main */ +int +main(int argc, char *argv[]) +{ + int n; + bdaddr_t bdaddr; + + memset(&bdaddr, 0, sizeof(bdaddr)); + + /* Process command line arguments */ + while ((n = getopt(argc, argv, "a:h")) != -1) { + switch (n) { + case 'a': + if (!bt_aton(optarg, &bdaddr)) { + struct hostent *he = NULL; + + if ((he = bt_gethostbyname(optarg)) == NULL) + errx(1, "%s: %s", optarg, hstrerror(h_errno)); + + memcpy(&bdaddr, he->h_addr, sizeof(bdaddr)); + } + break; + + case 'h': + default: + usage(); + /* NOT REACHED */ + } + } + + argc -= optind; + argv += optind; + + if (*argv == NULL) + usage(); + + return (do_sdp_command(&bdaddr, argc, argv)); +} + +/* Execute commands */ +static int +do_sdp_command(bdaddr_p bdaddr, int argc, char **argv) +{ + char *cmd = argv[0]; + struct sdp_command *c = NULL; + void *xs = NULL; + int e, help; + + help = 0; + if (strcasecmp(cmd, "help") == 0) { + argc --; + argv ++; + + if (argc <= 0) { + fprintf(stdout, "Supported commands:\n"); + print_sdp_command(sdp_commands); + fprintf(stdout, "\nFor more information use " \ + "'help command'\n"); + + return (OK); + } + + help = 1; + cmd = argv[0]; + } + + c = find_sdp_command(cmd, sdp_commands); + if (c == NULL) { + fprintf(stdout, "Unknown command: \"%s\"\n", cmd); + return (ERROR); + } + + if (!help) { + if (memcmp(bdaddr, NG_HCI_BDADDR_ANY, sizeof(*bdaddr)) == 0) + usage(); + + if ((xs = sdp_open(NG_HCI_BDADDR_ANY, bdaddr)) == NULL) + errx(1, "Could not create SDP session object"); + + if (sdp_error(xs) == 0) + e = (c->handler)(xs, -- argc, ++ argv); + else + e = ERROR; + } else + e = USAGE; + + switch (e) { + case OK: + case FAILED: + break; + + case ERROR: + fprintf(stdout, "Could not execute command \"%s\". %s\n", + cmd, strerror(sdp_error(xs))); + break; + + case USAGE: + fprintf(stdout, "Usage: %s\n%s\n", c->command, c->description); + break; + + default: assert(0); break; + } + + sdp_close(xs); + + return (e); +} /* do_sdp_command */ + +/* Try to find command in specified category */ +static struct sdp_command * +find_sdp_command(char const *command, struct sdp_command *category) +{ + struct sdp_command *c = NULL; + + for (c = category; c->command != NULL; c++) { + char *c_end = strchr(c->command, ' '); + + if (c_end != NULL) { + int len = c_end - c->command; + + if (strncasecmp(command, c->command, len) == 0) + return (c); + } else if (strcasecmp(command, c->command) == 0) + return (c); + } + + return (NULL); +} /* find_sdp_command */ + +/* Print commands in specified category */ +static void +print_sdp_command(struct sdp_command *category) +{ + struct sdp_command *c = NULL; + + for (c = category; c->command != NULL; c++) + fprintf(stdout, "\t%s\n", c->command); +} /* print_sdp_command */ + +/* Usage */ +static void +usage(void) +{ + fprintf(stdout, "Usage: sdpcontrol -a BD_ADDR [-h] " \ + "cmd [p1] [..]]\n"); + exit(255); +} /* usage */ + diff --git a/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.h b/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.h new file mode 100644 index 0000000..4a1ee76f --- /dev/null +++ b/usr.sbin/bluetooth/sdpcontrol/sdpcontrol.h @@ -0,0 +1,49 @@ +/* + * sdpcontrol.h + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: sdpcontrol.h,v 1.1 2003/09/08 02:27:27 max Exp $ + * $FreeBSD$ + */ + +#ifndef __SDPCONTROL_H__ +#define __SDPCONTROL_H__ + +#define OK 0 /* everything was OK */ +#define ERROR 1 /* could not execute command */ +#define FAILED 2 /* error was reported */ +#define USAGE 3 /* invalid parameters */ + +struct sdp_command { + char const *command; + char const *description; + int (*handler)(void *, int, char **); +}; + +extern struct sdp_command sdp_commands[]; + +#endif /* __SDPCONTROL_H__ */ + diff --git a/usr.sbin/bluetooth/sdpcontrol/search.c b/usr.sbin/bluetooth/sdpcontrol/search.c new file mode 100644 index 0000000..7180952 --- /dev/null +++ b/usr.sbin/bluetooth/sdpcontrol/search.c @@ -0,0 +1,707 @@ +/* + * search.c + * + * Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: search.c,v 1.2 2003/09/08 17:35:15 max Exp $ + * $FreeBSD$ + */ + +#include <bluetooth.h> +#include <ctype.h> +#include <sdp.h> +#include <stdio.h> +#include <stdlib.h> +#include "sdpcontrol.h" + +/* List of the attributes we are looking for */ +static u_int32_t attrs[] = +{ + SDP_ATTR_RANGE( SDP_ATTR_SERVICE_RECORD_HANDLE, + SDP_ATTR_SERVICE_RECORD_HANDLE), + SDP_ATTR_RANGE( SDP_ATTR_SERVICE_CLASS_ID_LIST, + SDP_ATTR_SERVICE_CLASS_ID_LIST), + SDP_ATTR_RANGE( SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST, + SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST), + SDP_ATTR_RANGE( SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST, + SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST) +}; +#define attrs_len (sizeof(attrs)/sizeof(attrs[0])) + +/* Buffer for the attributes */ +#define NRECS 25 /* request this much records from the SDP server */ +#define BSIZE 256 /* one attribute buffer size */ +static u_int8_t buffer[NRECS * attrs_len][BSIZE]; + +/* SDP attributes */ +static sdp_attr_t values[NRECS * attrs_len]; +#define values_len (sizeof(values)/sizeof(values[0])) + +/* + * Print Service Class ID List + * + * The ServiceClassIDList attribute consists of a data element sequence in + * which each data element is a UUID representing the service classes that + * a given service record conforms to. The UUIDs are listed in order from + * the most specific class to the most general class. The ServiceClassIDList + * must contain at least one service class UUID. + */ + +static void +print_service_class_id_list(u_int8_t const *start, u_int8_t const *end) +{ + u_int32_t type, len, value; + + if (end - start < 2) { + fprintf(stderr, "Invalid Service Class ID List. " \ + "Too short, len=%d\n", end - start); + return; + } + + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + fprintf(stderr, "Invalid Service Class ID List. " \ + "Not a sequence, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + while (start < end) { + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_UUID16: + SDP_GET16(value, start); + fprintf(stdout, "\t%s (%#4.4x)\n", + sdp_uuid2desc(value), value); + break; + + case SDP_DATA_UUID32: + SDP_GET32(value, start); + fprintf(stdout, "\t%#8.8x\n", value); + break; + + case SDP_DATA_UUID128: { + int128_t uuid; + + SDP_GET128(&uuid, start); + fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", + *(u_int32_t *)&uuid.b[0], + *(u_int16_t *)&uuid.b[4], + *(u_int16_t *)&uuid.b[6], + *(u_int16_t *)&uuid.b[8], + *(u_int16_t *)&uuid.b[10], + *(u_int32_t *)&uuid.b[12]); + } break; + + default: + fprintf(stderr, "Invalid Service Class ID List. " \ + "Not a UUID, type=%#x\n", type); + return; + /* NOT REACHED */ + } + } +} /* print_service_class_id_list */ + +/* + * Print Protocol Descriptor List + * + * If the ProtocolDescriptorList describes a single stack, it takes the form + * of a data element sequence in which each element of the sequence is a + * protocol descriptor. Each protocol descriptor is, in turn, a data element + * sequence whose first element is a UUID identifying the protocol and whose + * successive elements are protocol-specific parameters. The protocol + * descriptors are listed in order from the lowest layer protocol to the + * highest layer protocol used to gain access to the service. If it is possible + * for more than one kind of protocol stack to be used to gain access to the + * service, the ProtocolDescriptorList takes the form of a data element + * alternative where each member is a data element sequence as described above. + */ + +static void +print_protocol_descriptor(u_int8_t const *start, u_int8_t const *end) +{ + union { + uint8_t uint8; + uint16_t uint16; + uint32_t uint32; + uint64_t uint64; + int128_t int128; + } value; + u_int32_t type, len, param; + + /* Get Protocol UUID */ + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_UUID16: + SDP_GET16(value.uint16, start); + fprintf(stdout, "\t%s (%#4.4x)\n", sdp_uuid2desc(value.uint16), + value.uint16); + break; + + case SDP_DATA_UUID32: + SDP_GET32(value.uint32, start); + fprintf(stdout, "\t%#8.8x\n", value.uint32); + break; + + case SDP_DATA_UUID128: + SDP_GET128(&value.int128, start); + fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", + *(u_int32_t *)&value.int128.b[0], + *(u_int16_t *)&value.int128.b[4], + *(u_int16_t *)&value.int128.b[6], + *(u_int16_t *)&value.int128.b[8], + *(u_int16_t *)&value.int128.b[10], + *(u_int32_t *)&value.int128.b[12]); + break; + + default: + fprintf(stderr, "Invalid Protocol Descriptor. " \ + "Not a UUID, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + /* Protocol specific parameters */ + for (param = 1; start < end; param ++) { + fprintf(stdout, "\t\tProtocol specific parameter #%d: ", param); + + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_NIL: + fprintf(stdout, "nil\n"); + break; + + case SDP_DATA_UINT8: + case SDP_DATA_INT8: + case SDP_DATA_BOOL: + SDP_GET8(value.uint8, start); + fprintf(stdout, "u/int8/bool %u\n", value.uint8); + break; + + case SDP_DATA_UINT16: + case SDP_DATA_INT16: + case SDP_DATA_UUID16: + SDP_GET16(value.uint16, start); + fprintf(stdout, "u/int/uuid16 %u\n", value.uint16); + break; + + case SDP_DATA_UINT32: + case SDP_DATA_INT32: + case SDP_DATA_UUID32: + SDP_GET32(value.uint32, start); + fprintf(stdout, "u/int/uuid32 %u\n", value.uint32); + break; + + case SDP_DATA_UINT64: + case SDP_DATA_INT64: + SDP_GET64(value.uint64, start); + fprintf(stdout, "u/int64 %llu\n", value.uint64); + break; + + case SDP_DATA_UINT128: + case SDP_DATA_INT128: + case SDP_DATA_UUID128: + SDP_GET128(&value.int128, start); + fprintf(stdout, "u/int/uuid128 %#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x\n", + *(u_int32_t *)&value.int128.b[0], + *(u_int16_t *)&value.int128.b[4], + *(u_int16_t *)&value.int128.b[6], + *(u_int16_t *)&value.int128.b[8], + *(u_int16_t *)&value.int128.b[10], + *(u_int32_t *)&value.int128.b[12]); + break; + + case SDP_DATA_STR8: + case SDP_DATA_URL8: + SDP_GET8(len, start); + fprintf(stdout, "%*.*s\n", len, len, (char *) start); + start += len; + break; + + case SDP_DATA_STR16: + case SDP_DATA_URL16: + SDP_GET16(len, start); + fprintf(stdout, "%*.*s\n", len, len, (char *) start); + start += len; + break; + + case SDP_DATA_STR32: + case SDP_DATA_URL32: + SDP_GET32(len, start); + fprintf(stdout, "%*.*s\n", len, len, (char *) start); + start += len; + break; + + case SDP_DATA_SEQ8: + case SDP_DATA_ALT8: + SDP_GET8(len, start); + for (; len > 0; start ++, len --) + fprintf(stdout, "%#2.2x ", *start); + fprintf(stdout, "\n"); + break; + + case SDP_DATA_SEQ16: + case SDP_DATA_ALT16: + SDP_GET16(len, start); + for (; len > 0; start ++, len --) + fprintf(stdout, "%#2.2x ", *start); + fprintf(stdout, "\n"); + break; + + case SDP_DATA_SEQ32: + case SDP_DATA_ALT32: + SDP_GET32(len, start); + for (; len > 0; start ++, len --) + fprintf(stdout, "%#2.2x ", *start); + fprintf(stdout, "\n"); + break; + + default: + fprintf(stderr, "Invalid Protocol Descriptor. " \ + "Unknown data type: %#02x\n", type); + return; + /* NOT REACHED */ + } + } +} /* print_protocol_descriptor */ + +static void +print_protocol_descriptor_list(u_int8_t const *start, u_int8_t const *end) +{ + u_int32_t type, len; + + if (end - start < 2) { + fprintf(stderr, "Invalid Protocol Descriptor List. " \ + "Too short, len=%d\n", end - start); + return; + } + + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + fprintf(stderr, "Invalid Protocol Descriptor List. " \ + "Not a sequence, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + while (start < end) { + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + fprintf(stderr, "Invalid Protocol Descriptor List. " \ + "Not a sequence, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + print_protocol_descriptor(start, start + len); + start += len; + } +} /* print_protocol_descriptor_list */ + +/* + * Print Bluetooth Profile Descriptor List + * + * The BluetoothProfileDescriptorList attribute consists of a data element + * sequence in which each element is a profile descriptor that contains + * information about a Bluetooth profile to which the service represented by + * this service record conforms. Each profile descriptor is a data element + * sequence whose first element is the UUID assigned to the profile and whose + * second element is a 16-bit profile version number. Each version of a profile + * is assigned a 16-bit unsigned integer profile version number, which consists + * of two 8-bit fields. The higher-order 8 bits contain the major version + * number field and the lower-order 8 bits contain the minor version number + * field. + */ + +static void +print_bluetooth_profile_descriptor_list(u_int8_t const *start, u_int8_t const *end) +{ + u_int32_t type, len, value; + + if (end - start < 2) { + fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \ + "Too short, len=%d\n", end - start); + return; + } + + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + fprintf(stderr, "Invalid Bluetooth Profile Descriptor List. " \ + "Not a sequence, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + while (start < end) { + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_SEQ8: + SDP_GET8(len, start); + break; + + case SDP_DATA_SEQ16: + SDP_GET16(len, start); + break; + + case SDP_DATA_SEQ32: + SDP_GET32(len, start); + break; + + default: + fprintf(stderr, "Invalid Bluetooth Profile " \ + "Descriptor List. " \ + "Not a sequence, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + /* Get UUID */ + SDP_GET8(type, start); + switch (type) { + case SDP_DATA_UUID16: + SDP_GET16(value, start); + fprintf(stdout, "\t%s (%#4.4x) ", + sdp_uuid2desc(value), value); + break; + + case SDP_DATA_UUID32: + SDP_GET32(value, start); + fprintf(stdout, "\t%#8.8x ", value); + break; + + case SDP_DATA_UUID128: { + int128_t uuid; + + SDP_GET128(&uuid, start); + fprintf(stdout, "\t%#8.8x-%4.4x-%4.4x-%4.4x-%4.4x%8.8x ", + *(u_int32_t *)&uuid.b[0], + *(u_int16_t *)&uuid.b[4], + *(u_int16_t *)&uuid.b[6], + *(u_int16_t *)&uuid.b[8], + *(u_int16_t *)&uuid.b[10], + *(u_int32_t *)&uuid.b[12]); + } break; + + default: + fprintf(stderr, "Invalid Bluetooth Profile " \ + "Descriptor List. " \ + "Not a UUID, type=%#x\n", type); + return; + /* NOT REACHED */ + } + + /* Get version */ + SDP_GET8(type, start); + if (type != SDP_DATA_UINT16) { + fprintf(stderr, "Invalid Bluetooth Profile " \ + "Descriptor List. " \ + "Invalid version type=%#x\n", type); + return; + } + + SDP_GET16(value, start); + fprintf(stdout, "ver. %d.%d\n", + (value >> 8) & 0xff, value & 0xff); + } +} /* print_bluetooth_profile_descriptor_list */ + +/* Perform SDP search command */ +static int +do_sdp_search(void *xs, int argc, char **argv) +{ + char *ep = NULL; + int32_t n, type, value; + u_int16_t service; + + /* Parse command line arguments */ + switch (argc) { + case 1: + n = strtoul(argv[0], &ep, 16); + if (*ep != 0) { + switch (tolower(argv[0][0])) { + case 'c': /* CIP/CTP */ + switch (tolower(argv[0][1])) { + case 'i': + service = SDP_SERVICE_CLASS_COMMON_ISDN_ACCESS; + break; + + case 't': + service = SDP_SERVICE_CLASS_CORDLESS_TELEPHONY; + break; + + default: + return (USAGE); + /* NOT REACHED */ + } + break; + + case 'd': /* DialUp Networking */ + service = SDP_SERVICE_CLASS_DIALUP_NETWORKING; + break; + + case 'f': /* Fax/OBEX File Transfer */ + switch (tolower(argv[0][1])) { + case 'a': + service = SDP_SERVICE_CLASS_FAX; + break; + + case 't': + service = SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER; + break; + + default: + return (USAGE); + /* NOT REACHED */ + } + break; + + case 'g': /* GN */ + service = SDP_SERVICE_CLASS_GN; + break; + + case 'h': /* Headset/HID */ + switch (tolower(argv[0][1])) { + case 'i': + service = SDP_SERVICE_CLASS_HUMAN_INTERFACE_DEVICE; + break; + + case 's': + service = SDP_SERVICE_CLASS_HEADSET; + break; + + default: + return (USAGE); + /* NOT REACHED */ + } + break; + + case 'l': /* LAN Access Using PPP */ + service = SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP; + break; + + case 'n': /* NAP */ + service = SDP_SERVICE_CLASS_NAP; + break; + + case 'o': /* OBEX Object Push */ + service = SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH; + break; + + case 's': /* Serial Port */ + service = SDP_SERVICE_CLASS_SERIAL_PORT; + break; + + default: + return (USAGE); + /* NOT REACHED */ + } + } else + service = (u_int16_t) n; + break; + + default: + return (USAGE); + } + + if (service < SDP_SERVICE_CLASS_SERVICE_DISCOVERY_SERVER) + return (USAGE); + + /* Initialize attribute values array */ + for (n = 0; n < values_len; n ++) { + values[n].flags = SDP_ATTR_INVALID; + values[n].attr = 0; + values[n].vlen = BSIZE; + values[n].value = buffer[n]; + } + + /* Do SDP Service Search Attribute Request */ + n = sdp_search(xs, 1, &service, attrs_len, attrs, values_len, values); + if (n != 0) + return (ERROR); + + /* Print attributes values */ + for (n = 0; n < values_len; n ++) { + if (values[n].flags != SDP_ATTR_OK) + break; + + switch (values[n].attr) { + case SDP_ATTR_SERVICE_RECORD_HANDLE: + fprintf(stdout, "\n"); + if (values[n].vlen == 5) { + SDP_GET8(type, values[n].value); + if (type == SDP_DATA_UINT32) { + SDP_GET32(value, values[n].value); + fprintf(stdout, "Record Handle: " \ + "%#8.8x\n", value); + } else + fprintf(stderr, "Invalid type=%#x " \ + "Record Handle " \ + "attribute!\n", type); + } else + fprintf(stderr, "Invalid size=%d for Record " \ + "Handle attribute\n", + values[n].vlen); + break; + + case SDP_ATTR_SERVICE_CLASS_ID_LIST: + fprintf(stdout, "Service Class ID List:\n"); + print_service_class_id_list(values[n].value, + values[n].value + values[n].vlen); + break; + + case SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST: + fprintf(stdout, "Protocol Descriptor List:\n"); + print_protocol_descriptor_list(values[n].value, + values[n].value + values[n].vlen); + break; + + case SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST: + fprintf(stdout, "Bluetooth Profile Descriptor List:\n"); + print_bluetooth_profile_descriptor_list(values[n].value, + values[n].value + values[n].vlen); + break; + + default: + fprintf(stderr, "Unexpected attribute ID=%#4.4x\n", + values[n].attr); + break; + } + } + + return (OK); +} /* do_sdp_search */ + +/* Perform SDP browse command */ +static int +do_sdp_browse(void *xs, int argc, char **argv) +{ +#undef _STR +#undef STR +#define _STR(x) #x +#define STR(x) _STR(x) + + static char const * const av[] = { + STR(SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP), + NULL + }; + + switch (argc) { + case 0: + argc = 1; + argv = (char **) av; + /* FALL THROUGH */ + case 1: + return (do_sdp_search(xs, argc, argv)); + } + + return (USAGE); +} /* do_sdp_browse */ + +/* List of SDP commands */ +struct sdp_command sdp_commands[] = { +{ +"Browse [<Group>]", +"Browse for services. The <Group> parameter is a 16-bit UUID of the group\n" \ +"to browse. If omitted <Group> is set to Public Browse Group.\n\n" \ +"\t<Group> - xxxx; 16-bit UUID of the group to browse\n", +do_sdp_browse +}, +{ +"Search <Service>", +"Search for the <Service>. The <Service> parameter is a 16-bit UUID of the\n" \ +"service to search for. For some services it is possible to use service name\n"\ +"instead of service UUID\n\n" \ +"\t<Service> - xxxx; 16-bit UUID of the service to search for\n\n" \ +"\tKnown service names\n" \ +"\t===================\n" \ +"\tCIP - Common ISDN Access\n" \ +"\tCTP - Cordless Telephony\n" \ +"\tDUN - DialUp Networking\n" \ +"\tFAX - Fax\n" \ +"\tFTRN - OBEX File Transfer\n" \ +"\tGN - GN\n" \ +"\tHID - Human Interface Device\n" \ +"\tHSET - Headset\n" \ +"\tLAN - LAN Access Using PPP\n" \ +"\tNAP - Network Access Point\n" \ +"\tOPUSH - OBEX Object Push\n" \ +"\tSP - Serial Port\n", +do_sdp_search +}, +{ NULL, NULL, NULL } +}; + |