Part 2 of the commit if new bluetooth code.

Submitted by:	Maksim Yevmenkin <m_evmenkin@yahoo.com>
Approved by: re@
This commit is contained in:
Julian Elischer 2003-05-10 21:50:37 +00:00
parent f2bb1cae36
commit 1a63eb31c7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=114879
37 changed files with 2193 additions and 393 deletions

View File

@ -1,12 +1,15 @@
# $Id$
# $Id: Makefile,v 1.3 2003/04/01 02:06:47 max Exp $
# $FreeBSD$
SUBDIR= \
bcmfw \
bt3cfw \
hccontrol \
hcsecd \
hcseriald \
l2control \
l2ping
l2ping \
rfcomm_pppd
.include <bsd.subdir.mk>

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.1.1.1 2002/11/12 00:39:18 max Exp $
# $Id: Makefile,v 1.2 2003/03/15 03:06:53 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
@ -6,7 +6,7 @@ MANDIR= ../share/man/man
PROG= bt3cfw
MAN8= bt3cfw.8
WARNS?= 2
CFLAGS+= -g -I../../../sys/netgraph/bluetooth/include
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
SRCS= bt3cfw.c
DPADD= ${LIBNETGRAPH}

View File

@ -1,6 +1,8 @@
.\" bt3cfw.8
.\"
.\" 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:
@ -9,7 +11,7 @@
.\" 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
@ -21,43 +23,44 @@
.\" 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: bt3cfw.8,v 1.3 2003/04/27 19:45:22 max Exp $
.\" $FreeBSD$
.\"
.Dd November 11, 2002
.Dt BT3CFW 8
.Os
.Sh NAME
.Nm bt3cfw
.Nd firmware download utility for 3Com Bluetooth PC card driver
.Nm BT3CFW
.Nd Firmware download utility for 3Com Bluetooth PC card driver
.Sh SYNOPSIS
.Nm
.Op Fl n Ar Netgraph_node_name
.Op Fl f Ar Firmware_file_name
.Op Fl n Ar Netgraph node name
.Op Fl f Ar Firmware file name
.Op Fl h
.Sh DESCRIPTION
The
.Nm
utility connects to the specified Netgraph driver node of type
utility connects to the specified Netgraph driver node of type
.Dv BTCCC
and downloads specified firmware file.
and downloads specified firmware file.
.Pp
Due to copyright issues I will no longer provide firmware with the card
driver.
The firmware can be obtained from the Windows driver package that
can be downloaded from the 3COM web site at no charge.
The firmware name is
.Pa BT3CPCC.BIN .
I am using original firmware that came with the card on CD-ROM.
.Pp
.Dl "MD5 (BT3CPCC.BIN) = 36170fda56ea9fdbf1702c966f8a97f1"
driver. The firmware can be obtained from the Windows driver package that
can be downloaded from the 3COM web site at no charge. The firmware name
is BT3CPCC.BIN. I'm using original firmware that came with the card on CD-ROM.
.Bd -literal -offset indent
MD5 (BT3CPCC.BIN) = 36170fda56ea9fdbf1702c966f8a97f1
.Ed
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl n Ar Netgraph_node_name
.It Fl n Ar Netgraph node name
Connect to the specified Netgraph driver node of type
.Dv BTCCC .
.It Fl f Ar Firmware_file_name
.It Fl f Ar Firmware file name
Specify firmware file name for download.
.It Fl h
Display usage message and exit.
.El
.Sh BUGS
Please report if found.

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: bt3cfw.c,v 1.1.1.1 2002/11/12 00:39:18 max Exp $
* $Id: bt3cfw.c,v 1.1 2002/11/24 20:22:37 max Exp $
* $FreeBSD$
*/

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.6 2002/09/06 18:52:41 max Exp $
# $Id: Makefile,v 1.2 2003/03/15 03:07:39 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
@ -6,7 +6,7 @@ MANDIR= ../share/man/man
PROG= hccontrol
MAN8= hccontrol.8
WARNS?= 2
CFLAGS+= -g -I../../../sys/netgraph/bluetooth/include
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
SRCS= send_recv.c link_policy.c link_control.c \
host_controller_baseband.c info.c status.c node.c hccontrol.c \
util.c

View File

@ -1,6 +1,8 @@
.\" hccontrol.8
.\"
.\" 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:
@ -9,7 +11,7 @@
.\" 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
@ -21,9 +23,9 @@
.\" 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: hccontrol.8,v 1.3 2003/04/27 19:45:23 max Exp $
.\" $FreeBSD$
.\"
.Dd June 14, 2002
.Dt HCCONTROL 8
.Os
@ -32,35 +34,34 @@
.Nd HCI configuration utility
.Sh SYNOPSIS
.Nm
.Op Fl n Ar HCI_node_name
.Op Ar command
.Op Fl n Ar HCI node name
.Op Fl h
.Op Ar command
.Op Ar parameters ...
.Sh DESCRIPTION
The
.Nm
utility connects to the specified Netgraph node of type
.Dv HCI
and attempts to send specified command to the HCI Netgraph node or to the
.Em HCI
and attempts to send specified command to the HCI Netgraph node or to the
associated Bluetooth device.
The
.Nm
utility
will print results to the standard output and error messages to
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 n Ar HCI_node_name
.It Fl n Ar HCI node name
Connect to the specified HCI Netgraph node.
.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
.It Fl h
Display usage message and exit.
.It command
One of the supported commands (see below). Special command
.Dq 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
.Dq help command .
.It parameters
One or more optional space separated command parameters.
.El
.Sh COMMANDS
@ -68,92 +69,92 @@ The currently supported HCI commands in
.Nm
are:
.Pp
.Bl -tag -offset indent -compact
.It Cm Inquiry
.It Cm Create_Connection
.It Cm Disconnect
.It Cm Add_SCO_Connection
.It Cm Change_Connection_Packet_Type
.It Cm Remote_Name_Request
.It Cm Read_Remote_Supported_Features
.It Cm Read_Remote_Version_Information
.It Cm Read_Clock_Offset
.It Cm Role_Discovery
.It Cm Switch_Role
.It Cm Read_Link_Policy_Settings
.It Cm Write_Link_Policy_Settings
.It Cm Reset
.It Cm Read_Pin_Type
.It Cm Write_Pin_Type
.It Cm Read_Stored_Link_Key
.It Cm Write_Stored_Link_Key
.It Cm Delete_Stored_Link_Key
.It Cm Change_Local_Name
.It Cm Read_Local_Name
.It Cm Read_Connection_Accept_Timeout
.It Cm Write_Connection_Accept_Timeout
.It Cm Read_Page_Timeout
.It Cm Write_Page_Timeout
.It Cm Read_Scan_Enable
.It Cm Write_Scan_Enable
.It Cm Read_Page_Scan_Activity
.It Cm Write_Page_Scan_Activity
.It Cm Read_Inquiry_Scan_Activity
.It Cm Write_Inquiry_Scan_Activity
.It Cm Read_Authentication_Enable
.It Cm Write_Authentication_Enable
.It Cm Read_Encryption_Mode
.It Cm Write_Encryption_Mode
.It Cm Read_Class_Of_Device
.It Cm Write_Class_Of_Device
.It Cm Read_Voice_Settings
.It Cm Write_Voice_Settings
.It Cm Read_Number_Broadcast_Retransmissions
.It Cm Write_Number_Broadcast_Retransmissions
.It Cm Read_Hold_Mode_Activity
.It Cm Write_Hold_Mode_Activity
.It Cm Read_SCO_Flow_Control_Enable
.It Cm Write_SCO_Flow_Control_Enable
.It Cm Read_Link_Supervision_Timeout
.It Cm Write_Link_Supervision_Timeout
.It Cm Read_Local_Version_Information
.It Cm Read_Local_Supported_Features
.It Cm Read_Buffer_Size
.It Cm Read_Country_Code
.It Cm Read_BD_ADDR
.It Cm Read_Failed_Contact_Counter
.It Cm Reset_Failed_Contact_Counter
.It Cm Get_Link_Quality
.It Cm Read_RSSI
.El
.Bd -literal -offset indent -compact
Inquiry
Create_Connection
Disconnect
Add_SCO_Connection
Change_Connection_Packet_Type
Remote_Name_Request
Read_Remote_Supported_Features
Read_Remote_Version_Information
Read_Clock_Offset
Role_Discovery
Switch_Role
Read_Link_Policy_Settings
Write_Link_Policy_Settings
Reset
Read_Pin_Type
Write_Pin_Type
Read_Stored_Link_Key
Write_Stored_Link_Key
Delete_Stored_Link_Key
Change_Local_Name
Read_Local_Name
Read_Connection_Accept_Timeout
Write_Connection_Accept_Timeout
Read_Page_Timeout
Write_Page_Timeout
Read_Scan_Enable
Write_Scan_Enable
Read_Page_Scan_Activity
Write_Page_Scan_Activity
Read_Inquiry_Scan_Activity
Write_Inquiry_Scan_Activity
Read_Authentication_Enable
Write_Authentication_Enable
Read_Encryption_Mode
Write_Encryption_Mode
Read_Class_Of_Device
Write_Class_Of_Device
Read_Voice_Settings
Write_Voice_Settings
Read_Number_Broadcast_Retransmissions
Write_Number_Broadcast_Retransmissions
Read_Hold_Mode_Activity
Write_Hold_Mode_Activity
Read_SCO_Flow_Control_Enable
Write_SCO_Flow_Control_Enable
Read_Link_Supervision_Timeout
Write_Link_Supervision_Timeout
Read_Local_Version_Information
Read_Local_Supported_Features
Read_Buffer_Size
Read_Country_Code
Read_BD_ADDR
Read_Failed_Contact_Counter
Reset_Failed_Contact_Counter
Get_Link_Quality
Read_RSSI
.Ed
.Pp
The currently supported node commands in
.Nm
are:
.Pp
.Bl -tag -offset indent -compact
.It Cm Read_Node_State
.It Cm Initialize
.It Cm Read_Debug_Level
.It Cm Write_Debug_Level
.It Cm Read_Command_Timeout
.It Cm Write_Command_Timeout
.It Cm Read_Node_Buffer_Size
.It Cm Read_Node_BD_ADDR
.It Cm Read_Node_Features
.It Cm Read_Node_Stat
.It Cm Reset_Node_Stat
.It Cm Flush_Neighbor_Cache
.It Cm Read_Neighbor_Cache
.It Cm Read_Connection_List
.It Cm Read_Node_Link_Policy_Settings_Mask
.It Cm Write_Node_Link_Policy_Settings_Mask
.It Cm Read_Node_Packet_Mask
.It Cm Write_Node_Packet_Mask
.El
.Bd -literal -offset indent -compact
Read_Node_State
Initialize
Read_Debug_Level
Write_Debug_Level
Read_Node_Buffer_Size
Read_Node_BD_ADDR
Read_Node_Features
Read_Node_Stat
Reset_Node_Stat
Flush_Neighbor_Cache
Read_Neighbor_Cache
Read_Connection_List
Read_Node_Link_Policy_Settings_Mask
Write_Node_Link_Policy_Settings_Mask
Read_Node_Packet_Mask
Write_Node_Packet_Mask
Read_Node_Role_Switch
Write_Node_Role_Switch
.Ed
.Pp
.Sh BUGS
Most likely.
Please report if found.
Most likely. Please report if found.
.Sh DIAGNOSTICS
.Ex -std
.Sh SEE ALSO

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: hccontrol.c,v 1.11 2002/09/12 18:19:43 max Exp $
* $Id: hccontrol.c,v 1.2 2003/04/27 19:45:24 max Exp $
* $FreeBSD$
*/
@ -63,7 +63,7 @@ main(int argc, char *argv[])
int n;
/* Process command line arguments */
while ((n = getopt(argc, argv, "n:v")) != -1) {
while ((n = getopt(argc, argv, "n:vh")) != -1) {
switch (n) {
case 'n':
node = optarg;
@ -73,7 +73,7 @@ main(int argc, char *argv[])
verbose = 1;
break;
case '?':
case 'h':
default:
usage();
}
@ -268,7 +268,7 @@ print_hci_command(struct hci_command *category)
static void
usage(void)
{
fprintf(stdout, "Usage: hccontrol -n HCI_node_name cmd [p1] [..]]\n");
fprintf(stdout, "Usage: hccontrol -n HCI_node_name [-h] cmd [p1] [..]]\n");
exit(255);
} /* usage */

View File

@ -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.8 2002/09/12 18:19:43 max Exp $
* $Id: hccontrol.h,v 1.1 2002/11/24 20:22:38 max Exp $
* $FreeBSD$
*/

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: host_controller_baseband.c,v 1.12 2002/11/19 18:34:06 max Exp $
* $Id: host_controller_baseband.c,v 1.1 2002/11/24 20:22:38 max Exp $
* $FreeBSD$
*/

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: info.c,v 1.7 2002/09/06 18:52:41 max Exp $
* $Id: info.c,v 1.1 2002/11/24 20:22:38 max Exp $
* $FreeBSD$
*/

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: link_control.c,v 1.12 2002/09/17 16:36:46 max Exp $
* $Id: link_control.c,v 1.2 2003/03/15 03:07:39 max Exp $
* $FreeBSD$
*/
@ -536,9 +536,35 @@ hci_remote_name_request(int s, int argc, char **argv)
ng_hci_remote_name_req_cp cp;
ng_hci_event_pkt_t *e = (ng_hci_event_pkt_t *) b;
memset(&cp, 0, sizeof(cp));
cp.page_scan_rep_mode = NG_HCI_SCAN_REP_MODE0;
cp.page_scan_mode = NG_HCI_MANDATORY_PAGE_SCAN_MODE;
/* parse command parameters */
switch (argc) {
case 4:
/* clock_offset */
if (sscanf(argv[3], "%x", &n0) != 1)
return (USAGE);
cp.clock_offset = (n0 & 0xffff);
cp.clock_offset = htole16(cp.clock_offset);
case 3:
/* page_scan_mode */
if (sscanf(argv[2], "%d", &n0) != 1 || n0 < 0x00 || n0 > 0x03)
return (USAGE);
cp.page_scan_mode = (n0 & 0xff);
case 2:
/* page_scan_rep_mode */
if (sscanf(argv[1], "%d", &n0) != 1 || n0 < 0x00 || n0 > 0x02)
return (USAGE);
cp.page_scan_rep_mode = (n0 & 0xff);
case 1:
/* BD_ADDR */
if (sscanf(argv[0], "%x:%x:%x:%x:%x:%x",
&n5, &n4, &n3, &n2, &n1, &n0) != 6)
@ -550,25 +576,6 @@ hci_remote_name_request(int s, int argc, char **argv)
cp.bdaddr.b[3] = (n3 & 0xff);
cp.bdaddr.b[4] = (n4 & 0xff);
cp.bdaddr.b[5] = (n5 & 0xff);
/* page_scan_rep_mode */
if (sscanf(argv[1], "%d", &n0) != 1 || n0 < 0x00 || n0 > 0x02)
return (USAGE);
cp.page_scan_rep_mode = (n0 & 0xff);
/* page_scan_mode */
if (sscanf(argv[2], "%d", &n0) != 1 || n0 < 0x00 || n0 > 0x03)
return (USAGE);
cp.page_scan_mode = (n0 & 0xff);
/* clock_offset */
if (sscanf(argv[3], "%x", &n0) != 1)
return (USAGE);
cp.clock_offset = (n0 & 0xffff);
cp.clock_offset = htole16(cp.clock_offset);
break;
default:

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: link_policy.c,v 1.3 2002/09/17 16:33:44 max Exp $
* $Id: link_policy.c,v 1.1 2002/11/24 20:22:38 max Exp $
* $FreeBSD$
*/

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: node.c,v 1.8 2002/11/12 22:33:17 max Exp $
* $Id: node.c,v 1.4 2003/03/23 21:28:17 max Exp $
* $FreeBSD$
*/
@ -52,7 +52,7 @@ hci_read_node_state(int s, int argc, char **argv)
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STATE, &r, sizeof(r)) < 0)
return (ERROR);
fprintf(stdout, "Node: %s\nState: %#x\n", r.hci_node, r.state);
fprintf(stdout, "State: %#x\n", r.state);
return (OK);
} /* hci_read_node_state */
@ -61,10 +61,7 @@ hci_read_node_state(int s, int argc, char **argv)
static int
hci_node_initialize(int s, int argc, char **argv)
{
struct ng_btsocket_hci_raw_node_init r;
memset(&r, 0, sizeof(r));
if (ioctl(s, SIOC_HCI_RAW_NODE_INIT, &r, sizeof(r)) < 0)
if (ioctl(s, SIOC_HCI_RAW_NODE_INIT) < 0)
return (ERROR);
return (OK);
@ -80,7 +77,7 @@ hci_read_debug_level(int s, int argc, char **argv)
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_DEBUG, &r, sizeof(r)) < 0)
return (ERROR);
fprintf(stdout, "Node: %s\nDebug level: %d\n", r.hci_node, r.debug);
fprintf(stdout, "Debug level: %d\n", r.debug);
return (OK);
} /* hci_read_debug_level */
@ -117,8 +114,6 @@ hci_read_node_buffer_size(int s, int argc, char **argv)
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_BUFFER, &r, sizeof(r)) < 0)
return (ERROR);
fprintf(stdout, "Node: %s\n",
r.hci_node);
fprintf(stdout, "Number of free command buffers: %d\n",
r.buffer.cmd_free);
fprintf(stdout, "Max. ACL packet size: %d\n",
@ -147,7 +142,6 @@ 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, "Node: %s\n", r.hci_node);
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]);
@ -167,7 +161,7 @@ hci_read_node_features(int s, int argc, char **argv)
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_FEATURES, &r, sizeof(r)) < 0)
return (ERROR);
fprintf(stdout, "Node: %s\nFeatures: ", r.hci_node);
fprintf(stdout, "Features: ");
for (n = 0; n < sizeof(r.features)/sizeof(r.features[0]); n++)
fprintf(stdout, "%#02x ", r.features[n]);
fprintf(stdout, "\n%s\n", hci_features2str(r.features,
@ -186,7 +180,6 @@ hci_read_node_stat(int s, int argc, char **argv)
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_STAT, &r, sizeof(r)) < 0)
return (ERROR);
fprintf(stdout, "Node: %s\n", r.hci_node);
fprintf(stdout, "Commands sent: %d\n", r.stat.cmd_sent);
fprintf(stdout, "Events received: %d\n", r.stat.evnt_recv);
fprintf(stdout, "ACL packets received: %d\n", r.stat.acl_recv);
@ -203,10 +196,7 @@ hci_read_node_stat(int s, int argc, char **argv)
static int
hci_reset_node_stat(int s, int argc, char **argv)
{
struct ng_btsocket_hci_raw_node_reset_stat r;
memset(&r, 0, sizeof(r));
if (ioctl(s, SIOC_HCI_RAW_NODE_RESET_STAT, &r, sizeof(r)) < 0)
if (ioctl(s, SIOC_HCI_RAW_NODE_RESET_STAT) < 0)
return (ERROR);
return (OK);
@ -216,11 +206,7 @@ hci_reset_node_stat(int s, int argc, char **argv)
static int
hci_flush_neighbor_cache(int s, int argc, char **argv)
{
struct ng_btsocket_hci_raw_node_flush_neighbor_cache r;
memset(&r, 0, sizeof(r));
if (ioctl(s, SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE,
&r, sizeof(r)) < 0)
if (ioctl(s, SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE) < 0)
return (ERROR);
return (OK);
@ -248,7 +234,6 @@ hci_read_neighbor_cache(int s, int argc, char **argv)
goto out;
}
fprintf(stdout, "Neighbor cache for the node: %s\n", r.hci_node);
fprintf(stdout,
"BD_ADDR " \
"Features " \
@ -299,7 +284,6 @@ hci_read_connection_list(int s, int argc, char **argv)
goto out;
}
fprintf(stdout, "Connections list for the node: %s\n", r.hci_node);
fprintf(stdout,
"Remote BD_ADDR " \
"Handle " \
@ -345,9 +329,9 @@ hci_read_connection_list(int s, int argc, char **argv)
return (error);
} /* hci_read_connection_list */
/* Send Read_Link_Policy_Settings_Mask command to the node */
/* Send Read_Node_Link_Policy_Settings_Mask command to the node */
int
hci_read_link_policy_settings_mask(int s, int argc, char **argv)
hci_read_node_link_policy_settings_mask(int s, int argc, char **argv)
{
struct ng_btsocket_hci_raw_node_link_policy_mask r;
@ -355,15 +339,14 @@ hci_read_link_policy_settings_mask(int s, int argc, char **argv)
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK, &r, sizeof(r)) < 0)
return (ERROR);
fprintf(stdout, "Node: %s\nLink Policy Settings mask: %#04x\n",
r.hci_node, r.policy_mask);
fprintf(stdout, "Link Policy Settings mask: %#04x\n", r.policy_mask);
return (OK);
} /* hci_read_link_policy_settings_mask */
} /* hci_read_node_link_policy_settings_mask */
/* Send Write_Link_Policy_Settings_Mask command to the node */
/* Send Write_Node_Link_Policy_Settings_Mask command to the node */
int
hci_write_link_policy_settings_mask(int s, int argc, char **argv)
hci_write_node_link_policy_settings_mask(int s, int argc, char **argv)
{
struct ng_btsocket_hci_raw_node_link_policy_mask r;
int m;
@ -386,11 +369,11 @@ hci_write_link_policy_settings_mask(int s, int argc, char **argv)
return (ERROR);
return (OK);
} /* hci_write_link_policy_settings_mask */
} /* hci_write_node_link_policy_settings_mask */
/* Send Read_Packet_Mask command to the node */
/* Send Read_Node_Packet_Mask command to the node */
int
hci_read_packet_mask(int s, int argc, char **argv)
hci_read_node_packet_mask(int s, int argc, char **argv)
{
struct ng_btsocket_hci_raw_node_packet_mask r;
@ -398,15 +381,14 @@ hci_read_packet_mask(int s, int argc, char **argv)
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_PACKET_MASK, &r, sizeof(r)) < 0)
return (ERROR);
fprintf(stdout, "Node: %s\nPacket mask: %#04x\n",
r.hci_node, r.packet_mask);
fprintf(stdout, "Packet mask: %#04x\n", r.packet_mask);
return (OK);
} /* hci_read_packet_mask */
} /* hci_read_node_packet_mask */
/* Send Write_Packet_Mask command to the node */
/* Send Write_Node_Packet_Mask command to the node */
int
hci_write_packet_mask(int s, int argc, char **argv)
hci_write_node_packet_mask(int s, int argc, char **argv)
{
struct ng_btsocket_hci_raw_node_packet_mask r;
int m;
@ -429,88 +411,175 @@ hci_write_packet_mask(int s, int argc, char **argv)
return (ERROR);
return (OK);
} /* hci_write_packet_mask */
} /* hci_write_node_packet_mask */
/* Send Read_Node_Role_Switch command to the node */
int
hci_read_node_role_switch(int s, int argc, char **argv)
{
struct ng_btsocket_hci_raw_node_role_switch r;
memset(&r, 0, sizeof(r));
if (ioctl(s, SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH, &r, sizeof(r)) < 0)
return (ERROR);
fprintf(stdout, "Role switch: %d\n", r.role_switch);
return (OK);
} /* hci_read_node_role_switch */
/* Send Write_Node_Role_Switch command to the node */
int
hci_write_node_role_switch(int s, int argc, char **argv)
{
struct ng_btsocket_hci_raw_node_role_switch r;
int m;
memset(&r, 0, sizeof(r));
switch (argc) {
case 1:
if (sscanf(argv[0], "%d", &m) != 1)
return (USAGE);
r.role_switch = m? 1 : 0;
break;
default:
return (USAGE);
}
if (ioctl(s, SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH, &r, sizeof(r)) < 0)
return (ERROR);
return (OK);
} /* hci_write_node_role_switch */
struct hci_command node_commands[] = {
{
"read_node_state",
"Get HCI node state",
"Get the HCI node state",
&hci_read_node_state
},
{
"initialize",
"Initialize HCI node",
"Initialize the HCI node",
&hci_node_initialize
},
{
"read_debug_level",
"Read HCI node debug level",
"Read the HCI node debug level",
&hci_read_debug_level
},
{
"write_debug_level <level>",
"Write HCI node debug level",
"Write the HCI node debug level",
&hci_write_debug_level
},
{
"read_node_buffer_size",
"Read HCI node buffer information",
"Read the HCI node buffer information. This will return current state of the\n"\
"HCI buffer for the HCI node",
&hci_read_node_buffer_size
},
{
"read_node_bd_addr",
"Read HCI node BD_ADDR",
"Read the HCI node BD_ADDR. Returns device BD_ADDR as cached by the HCI node",
&hci_read_node_bd_addr
},
{
"read_node_features",
"Read HCI node features",
"Read the HCI node features. This will return list of supported features as\n" \
"cached by the HCI node",
&hci_read_node_features
},
{
"read_node_stat",
"Read HCI node statistic information",
"Read packets and bytes counters for the HCI node",
&hci_read_node_stat
},
{
"reset_node_stat",
"Reset HCI node statistic information",
"Reset packets and bytes counters for the HCI node",
&hci_reset_node_stat
},
{
"flush_neighbor_cache",
"Flush HCI node neighbor cache",
"Flush content of the HCI node neighbor cache",
&hci_flush_neighbor_cache
},
{
"read_neighbor_cache",
"Read HCI node neighbor cache",
"Read content of the HCI node neighbor cache",
&hci_read_neighbor_cache
},
{
"read_connection_list",
"Read connection list",
"Read the baseband connection descriptors list for the HCI node",
&hci_read_connection_list
},
{
"read_node_link_policy_settings_mask",
"Read Link Policy Settinngs mask for the node",
&hci_read_link_policy_settings_mask
"Read the value of the Link Policy Settinngs mask for the HCI node",
&hci_read_node_link_policy_settings_mask
},
{
"write_node_link_policy_settings_mask <policy_mask>",
"Write Link Policy Settinngs mask for the node. Policy mask - xxxx",
&hci_write_link_policy_settings_mask
"Write the value of the Link Policy Settings mask for the HCI node. By default\n" \
"all supported Link Policy modes (as reported by the local device features) are\n"\
"enabled. The particular Link Policy mode is enabled if local device supports\n"\
"it and correspinding bit in the mask was set\n\n" \
"\t<policy_mask> - xxxx; Link Policy mask\n" \
"\t\t0x0000 - Disable All LM Modes\n" \
"\t\t0x0001 - Enable Master Slave Switch\n" \
"\t\t0x0002 - Enable Hold Mode\n" \
"\t\t0x0004 - Enable Sniff Mode\n" \
"\t\t0x0008 - Enable Park Mode\n",
&hci_write_node_link_policy_settings_mask
},
{
"read_node_packet_mask",
"Read Packet mask for the node",
&hci_read_packet_mask
"Read the value of the Packet mask for the HCI node",
&hci_read_node_packet_mask
},
{
"write_node_packet_mask <packet_mask>",
"Write Packet mask for the node. Packet mask - xxxx",
&hci_write_packet_mask
"Write the value of the Packet mask for the HCI node. By default all supported\n" \
"packet types (as reported by the local device features) are enabled. The\n" \
"particular packet type is enabled if local device supports it and corresponding\n" \
"bit in the mask was set\n\n" \
"\t<packet_mask> - xxxx; packet type mask\n" \
"" \
"\t\tACL packets\n" \
"\t\t-----------\n" \
"\t\t0x0008 DM1\n" \
"\t\t0x0010 DH1\n" \
"\t\t0x0400 DM3\n" \
"\t\t0x0800 DH3\n" \
"\t\t0x4000 DM5\n" \
"\t\t0x8000 DH5\n" \
"\n" \
"\t\tSCO packets\n" \
"\t\t-----------\n" \
"\t\t0x0020 HV1\n" \
"\t\t0x0040 HV2\n" \
"\t\t0x0080 HV3\n",
&hci_write_node_packet_mask
},
{
"read_node_role_switch",
"Read the value of the Role Switch parameter for the HCI node",
&hci_read_node_role_switch
},
{
"write_node_role_switch {0|1}",
"Write the value of the Role Switch parameter for the HCI node. By default,\n" \
"if Role Switch is supported, local device will try to perform Role Switch\n" \
"and become Master on incoming connection. Some devices do not support Role\n" \
"Switch and thus incomming connections from such devices will fail. Setting\n" \
"this parameter to zero will prevent Role Switch and thus accepting device\n" \
"will remain Slave",
&hci_write_node_role_switch
},
{
NULL,

View File

@ -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.4 2002/09/04 21:31:30 max Exp $
* $Id: send_recv.c,v 1.1 2002/11/24 20:22:38 max Exp $
* $FreeBSD$
*/

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: status.c,v 1.2 2002/09/06 18:52:41 max Exp $
* $Id: status.c,v 1.1 2002/11/24 20:22:38 max Exp $
* $FreeBSD$
*/
@ -231,7 +231,7 @@ struct hci_command status_commands[] = {
"read_rssi <connection_handle>",
"\nThis command will read the value for the difference between the\n" \
"measured Received Signal Strength Indication (RSSI) and the limits of\n" \
"the Golden Receive Power Range for an ACL connection handle to another\n" \
"the Golden Receive Power Range for a ACL connection handle to another\n" \
"Bluetooth device. Any positive RSSI value returned by the Host Controller\n" \
"indicates how many dB the RSSI is above the upper limit, any negative\n" \
"value indicates how many dB the RSSI is below the lower limit. The value\n" \

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: util.c,v 1.2 2002/09/12 18:19:43 max Exp $
* $Id: util.c,v 1.1 2002/11/24 20:22:38 max Exp $
* $FreeBSD$
*/

View File

@ -0,0 +1,12 @@
# $Id: Makefile,v 1.2 2003/03/15 03:07:42 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
MANDIR= ../share/man/man
PROG= hcsecd
MAN8= hcsecd.8
WARNS?= 1
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
SRCS= hcsecd.c lexer.l parser.y
.include <bsd.prog.mk>

View File

@ -0,0 +1,101 @@
.\" hcsecd.8
.\"
.\" 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.8,v 1.3 2003/04/27 19:45:32 max Exp $
.\" $FreeBSD$
.Dd November 16, 2002
.Dt HCSECD 8
.Os
.Sh NAME
.Nm hcsecd
.Nd control link keys and PIN codes for Bluetooth devices
.Sh SYNOPSIS
.Nm
.Op Fl f Ar configfile
.Op Fl d
.Op Fl h
.Sh DESCRIPTION
The
.Nm
daemon controls link keys and PIN code for Bluetooth devices. It opens raw
HCI socket and listens for the
.Dv Link_Key_Request
and
.Dv PIN_Code_Request
HCI events. Once appropriate HCI event has been received, the daemon will
scan configuration file for matching entry. The remove device BD_ADDR is used
as a key. If no matching entry was found then the default entry will be used.
If no default entry was found than it is assumed no link key and no PIN code
exist. For any given entry link key takes precedence over PIN code. If link key
was not specified then it means device must generate link key from PIN code. If
entry was found and has the link key (or PIN code) then
the
.Dv Link_Key_Request_Reply
(or
.Dv PIN_Code_Request_Reply
) command will be sent back to the device. Otherwise the
.Dv Link_Key_Request_Negative_Reply
(or
.Dv PIN_Code_Request_Negative_Reply
) command will be sent back to the device.
.Pp
The
.Nm
daemon currently does not handle 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.
.Pp
The command line options are as follows:
.Bl -tag -width Ds
.It Fl f Ar filename
Name of configuration file. Default is
.Pa /usr/local/etc/hcsecd.conf .
.It Fl d
Do not detach from the controlling terminal.
.It Fl h
Display usage message and exit.
.El
.Sh BUGS
Currently there is no way to select link key or PIN code based on which local
device received the request. 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 /etc/usbd.conf -compact
.It Pa /usr/local/etc/hcsecd.conf
.It Pa /var/run/hcsecd.pid
.El
.Sh SEE ALSO
.Xr netgraph 3 ,
.Xr netgraph 4 ,
.Xr ng_hci 4 ,
.Xr ng_btsocket 4 ,
.Xr hccontrol 8 ,
.Xr hcseriald 8
.Sh AUTHORS
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com

View File

@ -0,0 +1,422 @@
/*
* hcsecd.c
*
* 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.c,v 1.3 2003/04/27 19:45:32 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/endian.h>
#include <sys/socket.h>
#include <sys/queue.h>
#include <bitstring.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>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#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
(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
static int process_link_key_request_event
(int sock, struct sockaddr_hci *addr, bdaddr_p bdaddr);
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 void sigint
(int s);
static void usage
(void);
/* Main */
int
main(int argc, char *argv[])
{
int n, detach, sock, size;
struct sigaction sa;
struct sockaddr_hci addr;
struct ng_btsocket_hci_raw_filter filter;
char buffer[HCSECD_BUFFER_SIZE];
ng_hci_event_pkt_t *event = NULL;
detach = 1;
while ((n = getopt(argc, argv, "df:h")) != -1) {
switch (n) {
case 'd':
detach = 0;
break;
case 'f':
config_file = optarg;
break;
case 'h':
default:
usage();
/* NOT REACHED */
}
}
if (config_file == NULL)
usage();
/* NOT REACHED */
if (getuid() != 0)
errx(1, "** ERROR: You should run %s as privileged user!",
HCSECD_IDENT);
/* Set signal handlers */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sigint;
sa.sa_flags = SA_NOCLDWAIT;
if (sigaction(SIGINT, &sa, NULL) < 0)
err(1, "Could not sigaction(SIGINT)");
if (sigaction(SIGTERM, &sa, NULL) < 0)
err(1, "Could not sigaction(SIGINT)");
memset(&sa, 0, sizeof(sa));
sa.sa_handler = read_config_file;
if (sigaction(SIGHUP, &sa, NULL) < 0)
err(1, "Could not sigaction(SIGHUP)");
/* Open socket and set filter */
sock = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_HCI);
if (sock < 0)
err(1, "Could not create HCI socket");
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);
if (setsockopt(sock, SOL_HCI_RAW, SO_HCI_RAW_FILTER,
(void * const) &filter, sizeof(filter)) < 0)
err(1, "Could not set HCI socket filter");
if (detach)
if (daemon(0, 0) < 0)
err(1, "Could not daemon()ize");
openlog(HCSECD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON);
read_config_file(0);
if (detach) {
FILE *pid = NULL;
if ((pid = fopen(HCSECD_PIDFILE, "w")) == NULL) {
syslog(LOG_ERR, "Could not create PID file %s. %s (%d)",
HCSECD_PIDFILE, strerror(errno), errno);
exit(1);
}
fprintf(pid, "%d", getpid());
fclose(pid);
}
event = (ng_hci_event_pkt_t *) buffer;
while (!done) {
size = sizeof(addr);
n = recvfrom(sock, buffer, sizeof(buffer), 0,
(struct sockaddr *) &addr, &size);
if (n < 0) {
if (errno == EINTR)
continue;
syslog(LOG_ERR, "Could not receive from HCI socket. " \
"%s (%d)", strerror(errno), errno);
exit(1);
}
if (event->type != NG_HCI_EVENT_PKT) {
syslog(LOG_ERR, "Received unexpected HCI packet, " \
"type=%#x", event->type);
continue;
}
switch (event->event) {
case NG_HCI_EVENT_PIN_CODE_REQ:
process_pin_code_request_event(sock, &addr,
(bdaddr_p)(event + 1));
break;
case NG_HCI_EVENT_LINK_KEY_REQ:
process_link_key_request_event(sock, &addr,
(bdaddr_p)(event + 1));
break;
default:
syslog(LOG_ERR, "Received unexpected HCI event, " \
"event=%#x", event->event);
break;
}
}
if (detach)
if (remove(HCSECD_PIDFILE) < 0)
syslog(LOG_ERR, "Could not remove PID file %s. %s (%d)",
HCSECD_PIDFILE, strerror(errno), errno);
clean_config();
closelog();
close(sock);
return (0);
}
/* Process PIN_Code_Request event */
static int
process_pin_code_request_event(int sock, struct sockaddr_hci *addr,
bdaddr_p bdaddr)
{
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]);
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],
(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]);
return (send_pin_code_reply(sock, addr, bdaddr, NULL));
}
/* Process Link_Key_Request event */
static int
process_link_key_request_event(int sock, struct sockaddr_hci *addr,
bdaddr_p bdaddr)
{
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]);
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],
(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]);
return (send_link_key_reply(sock, addr, bdaddr, NULL));
}
/* Send PIN_Code_[Negative]_Reply */
static int
send_pin_code_reply(int sock, struct sockaddr_hci *addr,
bdaddr_p bdaddr, char const *pin)
{
u_int8_t buffer[HCSECD_BUFFER_SIZE];
ng_hci_cmd_pkt_t *cmd = NULL;
memset(buffer, 0, sizeof(buffer));
cmd = (ng_hci_cmd_pkt_t *) buffer;
cmd->type = NG_HCI_CMD_PKT;
if (pin != NULL) {
ng_hci_pin_code_rep_cp *cp = NULL;
cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
NG_HCI_OCF_PIN_CODE_REP));
cmd->length = sizeof(*cp);
cp = (ng_hci_pin_code_rep_cp *)(cmd + 1);
memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
strncpy(cp->pin, pin, sizeof(cp->pin));
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]);
} else {
ng_hci_pin_code_neg_rep_cp *cp = NULL;
cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
NG_HCI_OCF_PIN_CODE_NEG_REP));
cmd->length = sizeof(*cp);
cp = (ng_hci_pin_code_neg_rep_cp *)(cmd + 1);
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]);
}
again:
if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
(struct sockaddr *) addr, sizeof(*addr)) < 0) {
if (errno == EINTR)
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],
strerror(errno), errno);
return (-1);
}
return (0);
}
/* Send Link_Key_[Negative]_Reply */
static int
send_link_key_reply(int sock, struct sockaddr_hci *addr,
bdaddr_p bdaddr, u_int8_t *key)
{
u_int8_t buffer[HCSECD_BUFFER_SIZE];
ng_hci_cmd_pkt_t *cmd = NULL;
memset(buffer, 0, sizeof(buffer));
cmd = (ng_hci_cmd_pkt_t *) buffer;
cmd->type = NG_HCI_CMD_PKT;
if (key != NULL) {
ng_hci_link_key_rep_cp *cp = NULL;
cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
NG_HCI_OCF_LINK_KEY_REP));
cmd->length = sizeof(*cp);
cp = (ng_hci_link_key_rep_cp *)(cmd + 1);
memcpy(&cp->bdaddr, bdaddr, sizeof(cp->bdaddr));
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]);
} else {
ng_hci_link_key_neg_rep_cp *cp = NULL;
cmd->opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
NG_HCI_OCF_LINK_KEY_NEG_REP));
cmd->length = sizeof(*cp);
cp = (ng_hci_link_key_neg_rep_cp *)(cmd + 1);
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]);
}
again:
if (sendto(sock, buffer, sizeof(*cmd) + cmd->length, 0,
(struct sockaddr *) addr, sizeof(*addr)) < 0) {
if (errno == EINTR)
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],
strerror(errno), errno);
return (-1);
}
return (0);
}
/* Signal handler */
static void
sigint(int s)
{
syslog(LOG_DEBUG, "Got signal %d, total number of signals %d",
s, ++ done);
}
/* Display usage and exit */
static void
usage(void)
{
fprintf(stderr,
"Usage: %s [-d] -f config_file [-h]\n" \
"Where:\n" \
"\t-d do not detach from terminal\n" \
"\t-f config_file use <config_file>\n" \
"\t-h display this message\n", HCSECD_IDENT);
exit(255);
}

View File

@ -0,0 +1,64 @@
#
# $Id: hcsecd.conf,v 1.1 2002/11/24 20:22:39 max Exp $
# $FreeBSD$
#
# HCI security daemon configuration file
#
# Format:
#
# device {
# option value ;
# }
#
# Possible options and values
#
# Options Values
# ----------------------------------
# bdaddr xx:xx:xx:xx:xx:xx ; - remote device BD_ADDR
# name "any char" ; - to set user friendly device name
# key 0x11223344 | nokey ; - to set link key for the device
# pin "secret" | nopin ; - to PIN code for the device
#
# Notes:
#
# Currently there is no way to select keys/PIN code based on which
# local device received the request. Everything is based on remote
# device BD_ADDR.
#
# "nokey" means that no link key has been defined and we should
# send Link_Key_Negative_Reply command to the device.
#
# "nopin" means that no PIN code has been defined and we should
# send PIN_Code_Negative_Reply command to the device
#
# Default entry 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;
}
device {
bdaddr 00:80:37:5e:4d:d4;
name "Ericsson T68 phone";
key nokey;
pin "0000"; # PIN code (string up to 16 character)
}
device {
bdaddr 00:01:03:fc:6e:ec;
name "3COM PCCARD";
key nokey;
pin "0000";
}
device {
bdaddr 00:11:22:33:44:55;
name "Dummy";
key 0x00112233445566778899aabbccddeeff; # 16 bytes key (hex string)
pin nopin;
}

View File

@ -0,0 +1,57 @@
/*
* hcsecd.h
*
* 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.h,v 1.1 2002/11/24 20:22:39 max Exp $
* $FreeBSD$
*/
#ifndef _HCSECD_H_
#define _HCSECD_H_ 1
struct link_key
{
bdaddr_t bdaddr; /* remote device BDADDR */
char *name; /* remote device name */
u_int8_t *key; /* link key (or NULL if no key) */
char *pin; /* pin (or NULL if no pin) */
LIST_ENTRY(link_key) next; /* link to the next */
};
typedef struct link_key link_key_t;
typedef struct link_key * link_key_p;
extern char *config_file;
#if __config_debug__
void dump_config (void);
#endif
void read_config_file(int s);
void clean_config (void);
link_key_p get_key (bdaddr_p bdaddr, int exact_match);
#endif /* ndef _HCSECD_H_ */

View File

@ -0,0 +1,95 @@
%{
/*
* lexer.l
*
* 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: lexer.l,v 1.1 2002/11/24 20:22:39 max Exp $
* $FreeBSD$
*/
#include <string.h>
#include "parser.h"
%}
%option yylineno noyywrap nounput
delim [ \t\n]
ws {delim}+
empty {delim}*
comment \#.*
hexdigit [0-9a-fA-F]
hexbyte {hexdigit}{hexdigit}
device_word device
bdaddr_word bdaddr
name_word name
key_word key
nokey_word nokey
pin_word pin
nopin_word nopin
bdaddrstring {hexbyte}:{hexbyte}:{hexbyte}:{hexbyte}:{hexbyte}:{hexbyte}
hexstring 0x{hexbyte}+
string \".+\"
%%
\; return (';');
\: return (':');
\{ return ('{');
\} return ('}');
{ws} ;
{empty} ;
{comment} ;
{device_word} return (T_DEVICE);
{bdaddr_word} return (T_BDADDR);
{name_word} return (T_NAME);
{key_word} return (T_KEY);
{nokey_word} return (T_NOKEY);
{pin_word} return (T_PIN);
{nopin_word} return (T_NOPIN);
{bdaddrstring} {
yylval.string = yytext;
return (T_BDADDRSTRING);
}
{hexstring} {
yylval.string = &yytext[2];
return (T_HEXSTRING);
}
{string} {
yytext[strlen(yytext) - 1] = 0;
yylval.string = &yytext[1];
return (T_STRING);
}
%%

View File

@ -0,0 +1,339 @@
%{
/*
* parser.y
*
* 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: parser.y,v 1.1 2002/11/24 20:22:39 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/queue.h>
#include <errno.h>
#include <ng_hci.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <syslog.h>
#include "hcsecd.h"
int yyparse (void);
int yylex (void);
static void free_key (link_key_p key);
static int hexa2int4(char *a);
static int hexa2int8(char *a);
extern int yylineno;
static LIST_HEAD(, link_key) link_keys;
char *config_file = "/usr/local/etc/hcsecd.conf";
static link_key_p key = NULL;
%}
%union {
char *string;
}
%token <string> T_BDADDRSTRING T_HEXSTRING T_STRING
%token T_DEVICE T_BDADDR T_NAME T_KEY T_PIN T_NOKEY T_NOPIN T_JUNK
%%
config: line
| config line
;
line: T_DEVICE
{
key = (link_key_p) malloc(sizeof(*key));
if (key == NULL) {
syslog(LOG_ERR, "Could not allocate new " \
"config entry");
exit(1);
}
memset(key, 0, sizeof(*key));
}
'{' options '}'
{
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]);
free_key(key);
} else
LIST_INSERT_HEAD(&link_keys, key, next);
key = NULL;
}
;
options: option ';'
| options option ';'
;
option: bdaddr
| name
| key
| pin
;
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) {
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);
}
;
name: T_NAME T_STRING
{
if (key->name != NULL)
free(key->name);
key->name = strdup($2);
if (key->name == NULL) {
syslog(LOG_ERR, "Could not allocate new " \
"device name");
exit(1);
}
}
;
key: T_KEY T_HEXSTRING
{
int i, len;
if (key->key != NULL)
free(key->key);
key->key = (u_int8_t *) malloc(NG_HCI_KEY_SIZE);
if (key->key == NULL) {
syslog(LOG_ERR, "Could not allocate new " \
"link key");
exit(1);
}
memset(key->key, 0, NG_HCI_KEY_SIZE);
len = strlen($2) / 2;
if (len > NG_HCI_KEY_SIZE)
len = NG_HCI_KEY_SIZE;
for (i = 0; i < len; i ++)
key->key[i] = hexa2int8((char *)($2) + 2*i);
}
| T_KEY T_NOKEY
{
if (key->key != NULL)
free(key->key);
key->key = NULL;
}
;
pin: T_PIN T_STRING
{
if (key->pin != NULL)
free(key->pin);
key->pin = strdup($2);
if (key->pin == NULL) {
syslog(LOG_ERR, "Could not allocate new " \
"PIN code");
exit(1);
}
}
| T_PIN T_NOPIN
{
if (key->pin != NULL)
free(key->pin);
key->pin = NULL;
}
;
%%
/* Display parser error message */
void
yyerror(char const *message)
{
syslog(LOG_ERR, "%s in line %d", message, yylineno);
}
/* Re-read config file */
void
read_config_file(int s)
{
extern FILE *yyin;
if (config_file == NULL) {
syslog(LOG_ERR, "Unknown config file name!");
exit(1);
}
if ((yyin = fopen(config_file, "r")) == NULL) {
syslog(LOG_ERR, "Could not open config file '%s'. %s (%d)",
config_file, strerror(errno), errno);
exit(1);
}
clean_config();
if (yyparse() < 0) {
syslog(LOG_ERR, "Could not parse config file '%s'",config_file);
exit(1);
}
fclose(yyin);
yyin = NULL;
#if __config_debug__
dump_config();
#endif
}
/* Clean config */
void
clean_config(void)
{
link_key_p key = NULL;
while ((key = LIST_FIRST(&link_keys)) != NULL) {
LIST_REMOVE(key, next);
free_key(key);
}
}
/* Find link key entry in the list. Return exact or default match */
link_key_p
get_key(bdaddr_p bdaddr, int exact_match)
{
link_key_p key = NULL, defkey = NULL;
LIST_FOREACH(key, &link_keys, next) {
if (memcmp(bdaddr, &key->bdaddr, sizeof(key->bdaddr)) == 0)
break;
if (!exact_match)
if (memcmp(NG_HCI_BDADDR_ANY, &key->bdaddr,
sizeof(key->bdaddr)) == 0)
defkey = key;
}
return ((key != NULL)? key : defkey);
}
#if __config_debug__
/* Dump config */
void
dump_config(void)
{
link_key_p key = NULL;
char buffer[64];
LIST_FOREACH(key, &link_keys, next) {
if (key->key != NULL)
snprintf(buffer, sizeof(buffer),
"0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
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]);
syslog(LOG_DEBUG,
"device %s " \
"bdaddr %x:%x:%x:%x:%x:%x " \
"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],
(key->pin != NULL)? key->pin : "nopin",
(key->key != NULL)? buffer : "nokey");
}
}
#endif
/* Free key entry */
static void
free_key(link_key_p key)
{
if (key->name != NULL)
free(key->name);
if (key->key != NULL)
free(key->key);
if (key->pin != NULL)
free(key->pin);
memset(key, 0, sizeof(*key));
free(key);
}
/* Convert hex ASCII to int4 */
static int
hexa2int4(char *a)
{
if ('0' <= *a && *a <= '9')
return (*a - '0');
if ('A' <= *a && *a <= 'F')
return (*a - 'A' + 0xa);
if ('a' <= *a && *a <= 'f')
return (*a - 'a' + 0xa);
syslog(LOG_ERR, "Invalid hex character: '%c' (%#x)", *a, *a);
exit(1);
}
/* Convert hex ASCII to int8 */
static int
hexa2int8(char *a)
{
return ((hexa2int4(a) << 4) | hexa2int4(a + 1));
}

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.4 2002/09/04 21:29:58 max Exp $
# $Id: Makefile,v 1.2 2003/03/15 03:07:45 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
@ -8,7 +8,7 @@ PROG= hcseriald
MAN8= hcseriald.8
WARNS?= 2
CFLAGS+= -Wall -O2 -I../../../sys/netgraph/bluetooth/include
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
SRCS= hcseriald.c
DPADD= ${LIBNETGRAPH}

View File

@ -1,6 +1,8 @@
.\" hcseriald.8
.\"
.\" 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:
@ -9,7 +11,7 @@
.\" 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
@ -21,9 +23,9 @@
.\" 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: hcseriald.8,v 1.2 2003/04/27 19:45:33 max Exp $
.\" $FreeBSD$
.\"
.Dd June 14, 2002
.Dt HCSERIALD 8
.Os
@ -33,52 +35,50 @@
.Sh SYNOPSIS
.Nm
.Op Fl f Ar device
.Op Fl n Ar node_name
.Op Fl n Ar node name
.Op Fl s Ar speed
.Op Fl d
.Op Fl d
.Op Fl h
.Sh DESCRIPTION
The
.Nm
utility
handles serial Bluetooth devices.
It does one simple thing.
It opens
specified serial device, sets device parameters and pushes
.Em H4
handles serial Bluetooth devices. It does one simple thing. It opens
specified serial device, sets device parameters and pushes
.Em H4
line discipline.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl f Ar device
Callout device name.
Example:
.Fl f Pa /dev/cuaa0 .
.It Fl n Ar node_name
Set H4 Netgraph node name.
Example:
.Fl n Li sio0 .
Callout device name. Example:
.Fl f
.Pa /dev/cuaa0 .
.It Fl n Ar node name
Set H4 Netgraph node name. Example:
.Fl n Ar sio0 .
.It Fl s Ar speed
Set serial device speed to
.Ar speed .
.Em speed .
Example:
.Fl s Li 115200 .
.Fl s Ar 115200 .
.It Fl d
Do not disassociate from the controlling terminal, i.e. run in foreground.
.It Fl h
Display usage message and exit.
.El
.Sh FILES
.Bl -tag -width ".Pa /var/run/hcserial.*.pid" -compact
.Bl -tag -width /dev/consolectl -compact
.It Pa /var/run/hcserial.*.pid
Process ID of the currently running
process id of the currently running
.Nm
daemon,
where
.Ql *
daemon. Where
.Dq *
is a H4 Netgraph node name.
.El
.Sh SEE ALSO
.Xr tty 4 ,
.Xr ng_h4 4 ,
.Xr ng_hci 4 ,
.Xr tty 4 ,
.Xr hccontrol 8
.Sh AUTHORS
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com

View File

@ -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.4 2002/09/04 21:29:58 max Exp $
* $Id: hcseriald.c,v 1.2 2003/04/27 19:45:33 max Exp $
* $FreeBSD$
*/
@ -66,7 +66,7 @@ main(int argc, char *argv[])
struct sigaction sa;
/* Process command line arguments */
while ((n = getopt(argc, argv, "df:n:s:")) != -1) {
while ((n = getopt(argc, argv, "df:n:s:h")) != -1) {
switch (n) {
case 'd':
detach = 0;
@ -86,6 +86,7 @@ main(int argc, char *argv[])
usage(argv[0]);
break;
case 'h':
default:
usage(argv[0]);
break;
@ -267,12 +268,13 @@ sighandler(int s)
static void
usage(void)
{
fprintf(stderr, "Usage: %s -f device -n node_name [-s speed -d]\n" \
fprintf(stderr, "Usage: %s -f device -n node_name [-s speed -d -h]\n" \
"Where:\n" \
"\t-f device tty device name, ex. /dev/cuaa1\n" \
"\t-n node_name set Netgraph node name to node_name\n" \
"\t-s speed set tty speed, ex. 115200\n" \
"\t-d run in foreground\n",
"\t-d run in foreground\n" \
"\t-h display this message\n",
hcseriald);
exit(255);
} /* usage */

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.3 2002/09/04 21:30:40 max Exp $
# $Id: Makefile,v 1.2 2003/03/15 03:07:47 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
@ -6,7 +6,7 @@ MANDIR= ../share/man/man
PROG= l2control
MAN8= l2control.8
WARNS?= 2
CFLAGS+= -g -I../../../sys/netgraph/bluetooth/include
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
SRCS= l2cap.c l2control.c
.include <bsd.prog.mk>

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: l2cap.c,v 1.6 2002/09/04 21:30:40 max Exp $
* $Id: l2cap.c,v 1.4 2003/04/26 23:11:25 max Exp $
* $FreeBSD$
*/
@ -53,9 +53,6 @@ l2cap_read_node_flags(int s, int argc, char **argv)
if (ioctl(s, SIOC_L2CAP_NODE_GET_FLAGS, &r, sizeof(r)) < 0)
return (ERROR);
fprintf(stdout, "BD_ADDR: %x:%x:%x:%x:%x:%x\n",
r.src.b[5], r.src.b[4], r.src.b[3],
r.src.b[2], r.src.b[1], r.src.b[0]);
fprintf(stdout, "Connectionless traffic flags:\n");
fprintf(stdout, "\tSDP: %s\n",
(r.flags & NG_L2CAP_CLT_SDP_DISABLED)? "disabled" : "enabled");
@ -77,9 +74,6 @@ l2cap_read_debug_level(int s, int argc, char **argv)
if (ioctl(s, SIOC_L2CAP_NODE_GET_DEBUG, &r, sizeof(r)) < 0)
return (ERROR);
fprintf(stdout, "BD_ADDR: %x:%x:%x:%x:%x:%x\n",
r.src.b[5], r.src.b[4], r.src.b[3],
r.src.b[2], r.src.b[1], r.src.b[0]);
fprintf(stdout, "Debug level: %d\n", r.debug);
return (OK);
@ -135,17 +129,14 @@ l2cap_read_connection_list(int s, int argc, char **argv)
goto out;
}
fprintf(stdout, "BD_ADDR: %x:%x:%x:%x:%x:%x\n",
r.src.b[5], r.src.b[4], r.src.b[3],
r.src.b[2], r.src.b[1], r.src.b[0]);
fprintf(stdout, "L2CAP connections:\n");
fprintf(stdout,
"Remote BD_ADDR Handle Flags Pending State\n");
for (n = 0; n < r.num_connections; n++) {
fprintf(stdout,
"%02x:%02x:%02x:%02x:%02x:%02x " \
" %5d " \
"%2.2s %2.2s " \
"%6d " \
"%c%c%c%c%c " \
"%7d " \
"%s\n",
r.connections[n].remote.b[5],
@ -155,8 +146,11 @@ l2cap_read_connection_list(int s, int argc, char **argv)
r.connections[n].remote.b[1],
r.connections[n].remote.b[0],
r.connections[n].con_handle,
((r.connections[n].flags & NG_L2CAP_CON_TX)? "TX" : ""),
((r.connections[n].flags & NG_L2CAP_CON_RX)? "RX" : ""),
((r.connections[n].flags & NG_L2CAP_CON_OUTGOING)? 'O' : 'I'),
((r.connections[n].flags & NG_L2CAP_CON_LP_TIMO)? 'L' : ' '),
((r.connections[n].flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)? 'D' : ' '),
((r.connections[n].flags & NG_L2CAP_CON_TX)? 'T' : ' '),
((r.connections[n].flags & NG_L2CAP_CON_RX)? 'R' : ' '),
r.connections[n].pending,
con_state2str(r.connections[n].state));
}
@ -198,9 +192,6 @@ l2cap_read_channel_list(int s, int argc, char **argv)
goto out;
}
fprintf(stdout, "BD_ADDR: %x:%x:%x:%x:%x:%x\n",
r.src.b[5], r.src.b[4], r.src.b[3],
r.src.b[2], r.src.b[1], r.src.b[0]);
fprintf(stdout, "L2CAP channels:\n");
fprintf(stdout,
"Remote BD_ADDR SCID/ DCID PSM IMTU/ OMTU State\n");
@ -224,6 +215,46 @@ l2cap_read_channel_list(int s, int argc, char **argv)
return (error);
} /* l2cap_read_channel_list */
/* Send read_auto_disconnect_timeout command to the node */
static int
l2cap_read_auto_disconnect_timeout(int s, int argc, char **argv)
{
struct ng_btsocket_l2cap_raw_auto_discon_timo r;
memset(&r, 0, sizeof(r));
if (ioctl(s, SIOC_L2CAP_NODE_GET_AUTO_DISCON_TIMO, &r, sizeof(r)) < 0)
return (ERROR);
if (r.timeout != 0)
fprintf(stdout, "Auto disconnect timeout: %d sec\n", r.timeout);
else
fprintf(stdout, "Auto disconnect disabled\n");
return (OK);
} /* l2cap_read_auto_disconnect_timeout */
/* Send write_auto_disconnect_timeout command to the node */
static int
l2cap_write_auto_disconnect_timeout(int s, int argc, char **argv)
{
struct ng_btsocket_l2cap_raw_auto_discon_timo r;
memset(&r, 0, sizeof(r));
switch (argc) {
case 1:
r.timeout = atoi(argv[0]);
break;
default:
return (USAGE);
}
if (ioctl(s, SIOC_L2CAP_NODE_SET_AUTO_DISCON_TIMO, &r, sizeof(r)) < 0)
return (ERROR);
return (OK);
} /* l2cap_write_auto_disconnect_timeout */
struct l2cap_command l2cap_commands[] = {
{
"read_node_flags",
@ -251,6 +282,16 @@ struct l2cap_command l2cap_commands[] = {
&l2cap_read_channel_list
},
{
"read_auto_disconnect_timeout",
"Get L2CAP node auto disconnect timeout (in sec)",
&l2cap_read_auto_disconnect_timeout
},
{
"write_auto_disconnect_timeout <timeout>",
"Set L2CAP node auto disconnect timeout (in sec)",
&l2cap_write_auto_disconnect_timeout
},
{
NULL,
}};

View File

@ -1,6 +1,8 @@
.\" l2control.8
.\"
.\" 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:
@ -9,7 +11,7 @@
.\" 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
@ -21,9 +23,9 @@
.\" 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: l2control.8,v 1.3 2003/04/27 19:45:34 max Exp $
.\" $FreeBSD$
.\"
.Dd June 14, 2002
.Dt L2CONTROL 8
.Os
@ -32,38 +34,33 @@
.Nd L2CAP configuration utility
.Sh SYNOPSIS
.Nm
.Op Fl a Ar BD_ADDR
.Op Ar command
.Op Fl a Ar local BD_ADDR
.Op Fl h
.Op Ar command
.Op Ar parameters ...
.Sh DESCRIPTION
The
.Nm
utility connects to the local device with specified
.Ar BD_ADDR
and attempts to send specified
.Ar command .
The
utility connects to the local device with specified BD_ADDR and attempts
to send specified command.
.Nm
utility
will print results to the standard output and error messages to
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 local device with specified
.Ar BD_ADDR .
Example:
.Fl a Li 00:01:02:03:04:05 .
.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
.It Fl a Ar local BD_ADDR
Connect to the local device with specified BD_ADDR. Example:
.Fl a Ar 00:01:02:03:04:05 .
.It Fl h
Display usage message and exit.
.It command
One of the supported commands (see below). Special command
.Dq 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
.Dq help command .
.It parameters
One or more optional space separated command parameters.
.El
.Sh COMMANDS
@ -71,13 +68,16 @@ The currently supported node commands in
.Nm
are:
.Pp
.Bl -tag -offset indent -compact
.It Cm Read_Node_Flags
.It Cm Read_Debug_Level
.It Cm Write_Debug_Level
.It Cm Read_Connection_List
.It Cm Read_Channel_List
.El
.Bd -literal -offset indent -compact
Read_Node_Flags
Read_Debug_Level
Write_Debug_Level
Read_Connection_List
Read_Channel_List
Read_Auto_Disconnect_Timeout
Write_Auto_Disconnect_Timeout
.Ed
.Pp
.Sh DIAGNOSTICS
.Ex -std
.Sh SEE ALSO

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: l2control.c,v 1.5 2002/09/04 21:30:40 max Exp $
* $Id: l2control.c,v 1.3 2003/04/27 19:45:34 max Exp $
* $FreeBSD$
*/
@ -61,7 +61,7 @@ main(int argc, char *argv[])
memset(&bdaddr, 0, sizeof(bdaddr));
/* Process command line arguments */
while ((n = getopt(argc, argv, "a:")) != -1) {
while ((n = getopt(argc, argv, "a:h")) != -1) {
switch (n) {
case 'a': {
int a0, a1, a2, a3, a4, a5;
@ -80,6 +80,7 @@ main(int argc, char *argv[])
bdaddr.b[5] = (a5 & 0xff);
} break;
case 'h':
default:
usage();
break;
@ -148,13 +149,6 @@ do_l2cap_command(bdaddr_p bdaddr, int argc, char **argv)
sa.l2cap_bdaddr.b[3], sa.l2cap_bdaddr.b[2],
sa.l2cap_bdaddr.b[1], sa.l2cap_bdaddr.b[0]);
if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0)
err(2,
"Could not connect 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]);
e = 0x0ffff;
if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &e, sizeof(e)) < 0)
err(3, "Coult not setsockopt(RCVBUF, %d)", e);
@ -220,7 +214,7 @@ print_l2cap_command(struct l2cap_command *category)
static void
usage(void)
{
fprintf(stdout, "Usage: l2control -a BD_ADDR cmd [p1] [..]]\n");
fprintf(stdout, "Usage: l2control -a BD_ADDR [-h] cmd [p1] [..]]\n");
exit(255);
} /* usage */

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: l2control.h,v 1.2 2002/09/04 21:30:40 max Exp $
* $Id: l2control.h,v 1.1 2002/11/24 20:22:41 max Exp $
* $FreeBSD$
*/

View File

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.4 2002/09/04 21:28:05 max Exp $
# $Id: Makefile,v 1.2 2003/03/15 03:07:49 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
@ -7,6 +7,6 @@ PROG= l2ping
MAN8= l2ping.8
SRCS= l2ping.c
WARNS?= 2
CFLAGS+= -g -I../../../sys/netgraph/bluetooth/include
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
.include <bsd.prog.mk>

View File

@ -1,6 +1,8 @@
.\" l2ping.8
.\"
.\" 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:
@ -9,7 +11,7 @@
.\" 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
@ -21,9 +23,9 @@
.\" 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: l2ping.8,v 1.2 2003/04/27 19:45:35 max Exp $
.\" $FreeBSD$
.\"
.Dd June 14, 2002
.Dt L2PING 8
.Os
@ -32,61 +34,51 @@
.Nd send L2CAP ECHO_REQUEST to remote devices
.Sh SYNOPSIS
.Nm
.Op Fl a Ar BD_ADDR
.Op Fl S Ar BD_ADDR
.Op Fl a Ar remote BD_ADDR
.Op Fl S Ar source BD_ADDR
.Op Fl c Ar count
.Op Fl f
.Op Fl i Ar delay
.Op Fl s Ar size
.Op Fl h
.Sh DESCRIPTION
The
.Nm
uses L2CAP
.Dv ECHO_REQUEST
datagram to elicit a L2CAP
.Dv ECHO_RESPONSE
from a remote device.
uses L2CAP ECHO_REQUEST datagram to elicit a L2CAP ECHO_RESPONSE from a
remote device.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl a Ar BD_ADDR
Address of remote device to ping.
Example:
.Fl a Li 00:01:02:03:04:05 .
.It Fl S Ar BD_ADDR
Send L2CAP
.Dv ECHO_REQUEST
from local device that has
.Ar BD_ADDR .
Example:
.Fl S Li 00:05:04:03:02:01 .
.It Fl a Ar remote BD_ADDR
Address of remote device to ping. Example:
.Fl a Ar 00:01:02:03:04:05 .
.It Fl S Ar source BD_ADDR
Send L2CAP ECHO_REQUEST from local device that has BD_ADDR. Example:
.Fl S Ar 00:05:04:03:02:01 .
.It Fl c Ar count
Number of packets to send.
If this option is not specified,
Number of packets to send. If this option is not specified,
.Nm
will operate until interrupted.
.It Fl f
.Dq Flood
ping, i.e., no delay between packets.
ping, i.e. no delay between packets.
.It Fl i Ar wait
Wait
.Ar wait
seconds between sending each packet.
The default is to wait for one
second between each packet.
This option is ignored if
.Fl f
Wait
.Em wait
seconds between sending each packet. The default is to wait for one
second between each packet. This option is ignored if
.Fl f
has been specified.
.It Fl s Ar size
Specify the number of payload bytes to be sent.
The default is 64.
The maximum size is 65531.
Use this option with caution.
Some implementations may not like large sizes and may hang or even crash.
Specify the number of payload bytes to be sent. The default is 64. The
maximum size is 65531. Use this option with caution. Some implementations
may not like large sizes and may hang or even crash.
.It Fl h
Display usage message and exit.
.El
.Sh BUGS
Could collect more statistics.
Could check for duplicated, corrupted and lost packets.
Could collect more statistic. Could check for duplicated, corrupted
and lost packets.
.Sh DIAGNOSTICS
.Ex -std
.Sh SEE ALSO

View File

@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $Id: l2ping.c,v 1.9 2002/09/04 21:28:05 max Exp $
* $Id: l2ping.c,v 1.3 2003/04/27 19:45:36 max Exp $
* $FreeBSD$
*/
@ -64,11 +64,16 @@ 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;
/* Set defaults */
memcpy(&src, NG_HCI_BDADDR_ANY, sizeof(src));
memcpy(&dst, NG_HCI_BDADDR_ANY, sizeof(dst));
memset(&r, 0, sizeof(r));
r.echo_data = calloc(NG_L2CAP_MAX_ECHO_SIZE, sizeof(u_int8_t));
if (r.echo_data == NULL) {
@ -82,7 +87,7 @@ main(int argc, char *argv[])
flood = 0;
/* Parse command line arguments */
while ((n = getopt(argc, argv, "a:c:fi:n:s:S:")) != -1) {
while ((n = getopt(argc, argv, "a:c:fi:n:s:S:h")) != -1) {
switch (n) {
case 'a':
case 'S': {
@ -94,20 +99,20 @@ main(int argc, char *argv[])
if (n == 'a') {
/* destination bdaddr */
r.echo_dst.b[0] = (a0 & 0xff);
r.echo_dst.b[1] = (a1 & 0xff);
r.echo_dst.b[2] = (a2 & 0xff);
r.echo_dst.b[3] = (a3 & 0xff);
r.echo_dst.b[4] = (a4 & 0xff);
r.echo_dst.b[5] = (a5 & 0xff);
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 */
r.echo_src.b[0] = (a0 & 0xff);
r.echo_src.b[1] = (a1 & 0xff);
r.echo_src.b[2] = (a2 & 0xff);
r.echo_src.b[3] = (a3 & 0xff);
r.echo_src.b[4] = (a4 & 0xff);
r.echo_src.b[5] = (a5 & 0xff);
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);
}
} break;
@ -136,41 +141,43 @@ main(int argc, char *argv[])
r.echo_size = NG_L2CAP_MAX_ECHO_SIZE;
break;
case 'h':
default:
usage();
break;
}
}
if (memcmp(&r.echo_dst, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
if (memcmp(&dst, NG_HCI_BDADDR_ANY, sizeof(dst)) == 0)
usage();
s = socket(PF_BLUETOOTH, SOCK_RAW, BLUETOOTH_PROTO_L2CAP);
if (s < 0)
err(2, "Could not create socket");
if (memcmp(&r.echo_src, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) != 0) {
struct sockaddr_l2cap sa;
memset(&sa, 0, sizeof(sa));
sa.l2cap_len = sizeof(sa);
sa.l2cap_family = AF_BLUETOOTH;
memcpy(&sa.l2cap_bdaddr, &src, sizeof(sa.l2cap_bdaddr));
memset(&sa, 0, sizeof(sa));
sa.l2cap_len = sizeof(sa);
sa.l2cap_family = AF_BLUETOOTH;
memcpy(&sa.l2cap_bdaddr, &r.echo_src, sizeof(bdaddr_t));
if (bind(s, (struct sockaddr *) &sa, sizeof(sa)) < 0)
err(3,
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]);
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]);
if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0)
err(4,
"Could not connect 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]);
}
memset(&sa, 0, sizeof(sa));
sa.l2cap_len = sizeof(sa);
sa.l2cap_family = AF_BLUETOOTH;
memcpy(&sa.l2cap_bdaddr, &dst, sizeof(sa.l2cap_bdaddr));
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]);
/* Fill pattern */
for (n = 0; n < r.echo_size; ) {
@ -206,9 +213,8 @@ main(int argc, char *argv[])
fprintf(stdout,
"%d bytes from %x:%x:%x:%x:%x:%x seq_no=%d time=%.3f ms result=%#x %s\n",
r.echo_size,
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],
dst.b[5], dst.b[4], dst.b[3],
dst.b[2], dst.b[1], dst.b[0],
ntohl(*((int *)(r.echo_data))),
tv2msec(&b), r.result,
((fail == 0)? "" : strerror(errno)));
@ -264,7 +270,7 @@ static void
usage(void)
{
fprintf(stderr, "Usage: l2ping -a bd_addr " \
"[-S bd_addr -c count -i wait -s size]\n");
"[-S bd_addr -c count -i wait -s size -h]\n");
fprintf(stderr, "Where:\n");
fprintf(stderr, "\t-S bd_addr - Source BD_ADDR\n");
fprintf(stderr, "\t-a bd_addr - Remote BD_ADDR to ping\n");
@ -273,6 +279,7 @@ usage(void)
fprintf(stderr, "\t-i wait - Delay between packets (sec)\n");
fprintf(stderr, "\t-s size - Packet size (bytes), " \
"between %d and %d\n", sizeof(int), NG_L2CAP_MAX_ECHO_SIZE);
fprintf(stderr, "\t-h - Display this message\n");
exit(255);
} /* usage */

View File

@ -0,0 +1,13 @@
# $Id: Makefile,v 1.2 2003/03/15 03:07:50 max Exp $
# $FreeBSD$
DESTDIR= /usr/sbin/
MANDIR= ../share/man/man
PROG= rfcomm_pppd
MAN8= rfcomm_pppd.8
WARNS?= 2
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include
SRCS= rfcomm_pppd.c
.include <bsd.prog.mk>

View File

@ -0,0 +1,246 @@
.\" rfcomm_pppd.8
.\"
.\" 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: rfcomm_pppd.8,v 1.5 2003/04/27 19:45:37 max Exp $
.\" $FreeBSD$
.Dd February 4, 2003
.Dt RFCOMM_PPPD 8
.Os
.Sh NAME
.Nm rfcomm_pppd
.Nd RFCOMM PPP daemon
.Sh SYNOPSIS
.Nm
.Op Fl a Ar BD_ADDR
.Op Fl c
.Op Fl C Ar channel
.Op Fl d
.Op Fl h
.Op Fl l Ar label
.Op Fl s
.Sh DESCRIPTION
The
.Nm
daemon is a simple wrapper daemon that allows to use standard
.Nm ppp
on RFCOMM connection. It can operate in two modes: client and server.
.Pp
In the client mode
.Nm
opens a RFCOMM connection to the specified server's BD_ADRR and channel.
Once RFCOMM connection is established
.Nm
executes
.Nm ppp
in
.Dq direct
mode with the specified label. The
.Nm ppp
in its turn operates over the RFCOMM connection just like it would operate
over the standard serial port thus allowing user to
.Dq dial out
and connect to the Internet.
.Pp
In the server mode
.Nm
opens a RFCOMM socket and listens for incomming connections from remote
clients. Once new incomming connection is accepted
.Nm
forks and executes
.Nm ppp
in
.Dq direct
mode with the specified label. The
.Nm ppp
in its turn operates over the RFCOMM connection just like it would operate over
the standard serial port thus providing network connectivity to remote clients.
.Pp
The options are as follows:
.Bl -tag -width indent
.It Fl a Ar BD_ADDR
In the client mode this requied 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. By default server will listen on
.Dv ANY
address.
.It Fl c
Act as RFCOMM client. This is the default mode.
.It Fl C Ar channel
In both client and server modes this required option specifies RFCOMM channel
to connect to or listen on.
.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 PPP label
will be used.
.It Fl s
Act as RFCOMM server.
.El
.Sh PPP CONFIGURATION
.Ss Important notes on PPP configuration
Special attention is required when adding new RFCOMM configurations to the
existing PPP configuration. Please keep in mind that PPP will
.Em always
execute commands in the
.Dq default
label of your
.Pa /etc/ppp/ppp.conf
file. Please make sure that the
.Dq default
label
.Em only
contains commands that apply to
.Em every
other label. If you need to use PPP for both dialing out and accepting incoming
RFCOMM connections, please make sure you have moved all commands related to
dialing out from the
.Dq default
section into appropriate outgoing label.
.Ss RFCOMM server
One of the typical examples is LAN access. In this example RFCOMM connection
is used as a null-modem connection between client and server. Both client
and server will start talking PPP right after RFCOMM connection was established.
.Bd -literal -offset indent
rfcomm-server:
set timeout 0
set lqrperiod 10
set ifaddr 10.0.0.1 10.0.0.2 255.255.255.0
enable lqr
accept lqr
# Do not use PPP authentication. Assume that
# Bluetooth connection was authenticated already
disable pap
deny pap
disable chap
deny chap
.Ed
.Ss RFCOMM client
.Nm
supports both LAN and DUN (DialUp Networking) access. The client's
configuration for the LAN access is very similar to server's and might
look like this.
.Bd -literal -offset indent
rfcomm-client:
enable lqr
accept lqr
set dial
set timeout 0
disable iface-alias
set ifaddr 10.0.0.1/0 10.0.0.2/0 255.255.255.0 0.0.0.0
# Do not use PPP authentication. Assume that
# Bluetooth connection was authenticated already
deny pap
disable pap
deny chap
disable chap
.Ed
.Pp
The client's configuration for the DUN access is different. In this scenario
the client gets connected to the virtual serial port on the server. To open a
PPP session client must dial a number. Note that by default
.Nm ppp
will not execute any configured chat scripts. The
.Dq force-scripts
option can be used to override this behavior. The example of such configuration
is shown below.
.Bd -literal -offset indent
rfcomm-dialup:
# This is IMPORTANT option
enable force-scripts
# You might want to change these
set authname
set authkey
set phone "*99***1#"
# You might want to adjust dial string as well
set dial "ABORT BUSY ABORT NO\\\sCARRIER TIMEOUT 5 \\
\\"\\" AT OK-AT-OK ATE1Q0 OK \\\\dATD\\\\T TIMEOUT 40 CONNECT"
set login
set timeout 30
enable dns
resolv rewrite
set ifaddr 10.0.0.1/0 10.0.0.2/0 255.255.255.0 0.0.0.0
add default HISADDR
.Ed
.Pp
Note that by adjusting initialization string one can make CSD (Circuit
Switched Data), HSCSD (High Speed Circuit Switched Data) or GPRS (General
Packet Radio Service) connection. The availability of the particular connection
type depends on the phone model and service plan activated on the phone.
.Sh EXAMPLES
.Bl -tag -width indent
.It rfcomm_pppd -s -a 00:01:02:03:04:05 -C 1 -l rfcomm-server
.Pp
Will start
.Nm
in the server mode. The RFCOMM server will listen on local address
.Em 00:01:02:03:04:05
and channel
.Em 1 .
Once incomming connection has been accepted
.Nm
will execute
.Nm ppp
in
.Dq direct
mode with
.Dq rfcomm-server
label.
.It rfcomm_pppd -c -a 00:01:02:03:04:05 -C 1 -l rfcomm-client
.Pp
Will start
.Nm
in the client mode.
.Nm
will try to connect to the RFCOMM server at
.Em 00:01:02:03:04:05
address and channel
.Em 1 .
Once connected the
.Nm
will execute
.Nm ppp
in
.Dq direct
mode with
.Dq rfcomm-client
label.
.El
.Sh DIAGNOSTICS
.Ex -std
.Sh BUGS
.Nm
currently is not integrated with SDP (Service Discovery Protocol).
.Sh SEE ALSO
.Xr ppp 8 ,
.Xr ng_btsocket 4 ,
.Xr rfcomm_sppd 1
.Sh AUTHORS
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com

View File

@ -0,0 +1,332 @@
/*
* rfcomm_pppd.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: rfcomm_pppd.c,v 1.3 2003/04/26 23:59:49 max Exp $
* $FreeBSD$
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <bitstring.h>
#include <errno.h>
#include <fcntl.h>
#include <ng_hci.h>
#include <ng_l2cap.h>
#include <ng_btsocket.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#define RFCOMM_PPPD "rfcomm_pppd"
static void exec_ppp (int s, char *label);
static void sighandler (int s);
static void usage (void);
static int done;
/* Main */
int
main(int argc, char *argv[])
{
struct sockaddr_rfcomm sock_addr;
char *label = NULL;
bdaddr_t addr;
int s, channel, detach, server;
pid_t pid;
memcpy(&addr, NG_HCI_BDADDR_ANY, sizeof(addr));
channel = 0;
detach = 1;
server = 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 'c': /* client */
server = 0;
break;
case 'C': /* RFCOMM channel */
channel = atoi(optarg);
break;
case 'd': /* do not detach */
detach = 0;
break;
case 'l': /* PPP label */
label = optarg;
break;
case 's':
server = 1;
break;
case 'h':
default:
usage();
/* NOT REACHED */
}
}
/* 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 */
openlog(RFCOMM_PPPD, LOG_PID | LOG_PERROR | LOG_NDELAY, LOG_USER);
if (detach) {
pid = fork();
if (pid == (pid_t) -1) {
syslog(LOG_ERR, "Could not fork(). %s (%d)",
strerror(errno), errno);
exit(1);
}
if (pid != 0)
exit(0);
if (daemon(0, 0) < 0) {
syslog(LOG_ERR, "Could not daemon(0, 0). %s (%d)",
strerror(errno), errno);
exit(1);
}
}
s = socket(PF_BLUETOOTH, SOCK_STREAM, BLUETOOTH_PROTO_RFCOMM);
if (s < 0) {
syslog(LOG_ERR, "Could not create socket. %s (%d)",
strerror(errno), errno);
exit(1);
}
if (server) {
struct sigaction sa;
/* Install signal handler */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = sighandler;
if (sigaction(SIGTERM, &sa, NULL) < 0) {
syslog(LOG_ERR, "Could not sigaction(SIGTERM). %s (%d)",
strerror(errno), errno);
exit(1);
}
if (sigaction(SIGHUP, &sa, NULL) < 0) {
syslog(LOG_ERR, "Could not sigaction(SIGHUP). %s (%d)",
strerror(errno), errno);
exit(1);
}
if (sigaction(SIGINT, &sa, NULL) < 0) {
syslog(LOG_ERR, "Could not sigaction(SIGINT). %s (%d)",
strerror(errno), errno);
exit(1);
}
sa.sa_handler = SIG_IGN;
sa.sa_flags = SA_NOCLDWAIT;
if (sigaction(SIGCHLD, &sa, NULL) < 0) {
syslog(LOG_ERR, "Could not sigaction(SIGCHLD). %s (%d)",
strerror(errno), errno);
exit(1);
}
/* bind socket and listen for incoming connections */
sock_addr.rfcomm_len = sizeof(sock_addr);
sock_addr.rfcomm_family = AF_BLUETOOTH;
memcpy(&sock_addr.rfcomm_bdaddr, &addr,
sizeof(sock_addr.rfcomm_bdaddr));
sock_addr.rfcomm_channel = channel;
if (bind(s, (struct sockaddr *) &sock_addr,
sizeof(sock_addr)) < 0) {
syslog(LOG_ERR, "Could not bind socket. %s (%d)",
strerror(errno), errno);
exit(1);
}
if (listen(s, 10) < 0) {
syslog(LOG_ERR, "Could not listen on socket. %s (%d)",
strerror(errno), errno);
exit(1);
}
for (done = 0; !done; ) {
int len = sizeof(sock_addr);
int s1 = accept(s, (struct sockaddr *) &sock_addr, &len);
if (s1 < 0) {
syslog(LOG_ERR, "Could not accept connection " \
"on socket. %s (%d)", strerror(errno),
errno);
exit(1);
}
pid = fork();
if (pid == (pid_t) -1) {
syslog(LOG_ERR, "Could not fork(). %s (%d)",
strerror(errno), errno);
exit(1);
}
if (pid == 0) {
close(s);
/* Reset signal handler */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = SIG_DFL;
sigaction(SIGTERM, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGINT, &sa, NULL);
sigaction(SIGCHLD, &sa, NULL);
/* Become daemon */
daemon(0, 0);
exec_ppp(s1, label);
} else
close(s1);
}
} else {
sock_addr.rfcomm_len = sizeof(sock_addr);
sock_addr.rfcomm_family = AF_BLUETOOTH;
memcpy(&sock_addr.rfcomm_bdaddr, NG_HCI_BDADDR_ANY,
sizeof(sock_addr.rfcomm_bdaddr));
sock_addr.rfcomm_channel = 0;
if (bind(s, (struct sockaddr *) &sock_addr,
sizeof(sock_addr)) < 0) {
syslog(LOG_ERR, "Could not bind socket. %s (%d)",
strerror(errno), errno);
exit(1);
}
memcpy(&sock_addr.rfcomm_bdaddr, &addr,
sizeof(sock_addr.rfcomm_bdaddr));
sock_addr.rfcomm_channel = channel;
if (connect(s, (struct sockaddr *) &sock_addr,
sizeof(sock_addr)) < 0) {
syslog(LOG_ERR, "Could not connect socket. %s (%d)",
strerror(errno), errno);
exit(1);
}
exec_ppp(s, label);
}
exit(0);
} /* main */
/*
* Redirects stdin/stdout to s, stderr to /dev/null and exec ppp -direct label.
* Never retruns.
*/
static void
exec_ppp(int s, char *label)
{
char ppp[] = "/usr/sbin/ppp";
char *ppp_args[] = { ppp, "-direct", NULL, NULL };
close(0);
if (dup(s) < 0) {
syslog(LOG_ERR, "Could not dup(0). %s (%d)",
strerror(errno), errno);
exit(1);
}
close(1);
if (dup(s) < 0) {
syslog(LOG_ERR, "Could not dup(1). %s (%d)",
strerror(errno), errno);
exit(1);
}
close(2);
open("/dev/null", O_RDWR);
ppp_args[2] = label;
if (execv(ppp, ppp_args) < 0) {
syslog(LOG_ERR, "Could not exec(%s -direct %s). %s (%d)",
ppp, label, strerror(errno), errno);
exit(1);
}
} /* run_ppp */
/* Signal handler */
static void
sighandler(int s)
{
done = 1;
} /* sighandler */
/* Display usage and exit */
static void
usage(void)
{
fprintf(stdout,
"Usage: %s options\n" \
"Where options are:\n" \
"\t-a bdaddr BDADDR to listen on or connect to (required for client)\n" \
"\t-c Act as a clinet (default)\n" \
"\t-C channel RFCOMM channel to listen on or connect to (required)\n" \
"\t-d Run in foreground\n" \
"\t-l label Use PPP label (required)\n" \
"\t-s Act as a server\n" \
"\t-h Display this message\n", RFCOMM_PPPD);
exit(255);
} /* usage */