summaryrefslogtreecommitdiffstats
path: root/usr.bin/bluetooth
diff options
context:
space:
mode:
authoremax <emax@FreeBSD.org>2007-01-25 20:54:59 +0000
committeremax <emax@FreeBSD.org>2007-01-25 20:54:59 +0000
commita11c42b474e87895ccbcaab629261ae9098091a3 (patch)
tree569619450f6012ed6c8536d90a37a592ef7fd682 /usr.bin/bluetooth
parent0dfda7f53e06f40a51cecf696b1a01e44c9b00aa (diff)
downloadFreeBSD-src-a11c42b474e87895ccbcaab629261ae9098091a3.zip
FreeBSD-src-a11c42b474e87895ccbcaab629261ae9098091a3.tar.gz
Add "server mode" to rfcomm_sppd(1).
Submitted by: Dave Eckhardt, bms Tested by: Dave Eckhardt, Eric Anderson, bms
Diffstat (limited to 'usr.bin/bluetooth')
-rw-r--r--usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.161
-rw-r--r--usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c132
2 files changed, 153 insertions, 40 deletions
diff --git a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1 b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1
index 2f7d3f5..4af7094 100644
--- a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1
+++ b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1
@@ -25,7 +25,7 @@
.\" $Id: rfcomm_sppd.1,v 1.3 2003/09/07 18:15:55 max Exp $
.\" $FreeBSD$
.\"
-.Dd April 26, 2003
+.Dd January 24, 2007
.Dt RFCOMM_SPPD 1
.Os
.Sh NAME
@@ -33,7 +33,7 @@
.Nd RFCOMM Serial Port Profile daemon
.Sh SYNOPSIS
.Nm
-.Op Fl bh
+.Op Fl bhS
.Fl a Ar address
.Fl c Ar channel
.Op Fl t Ar tty
@@ -41,7 +41,11 @@
The
.Nm
utility is a Serial Port Profile daemon.
-It opens RFCOMM connection to the specified
+It can operate in two modes: client and server.
+.Pp
+In client mode,
+.Nm
+opens RFCOMM connection to the specified
.Ar address
server and
.Ar channel .
@@ -54,6 +58,27 @@ interface if
.Fl t
option was specified.
.Pp
+If the
+.Fl S
+option is specified,
+.Nm
+will operate in server mode and act as RFCOMM server,
+listening on
+.Dv ANY
+address and advertising a virtual serial port
+via the
+.Xr sdpd 8
+daemon.
+The
+.Fl t
+option must be specified;
+the server side of the virtual serial port is attached to the pseudo-terminal
+.Ar tty .
+.Nm
+should be run as root in order to communicate with
+.Xr sdp 8
+in this case.
+.Pp
The
.Nm
utility opens both master and slave pseudo terminals.
@@ -71,17 +96,31 @@ port.
The options are as follows:
.Bl -tag -width indent
.It Fl a Ar address
-This required option specifies the address of the remote RFCOMM server.
+In client mode,
+this required option specifies the address of the remote RFCOMM server.
+If this option is specified in server mode,
+.Nm
+will only accept connections from the
+.Tn Bluetooth
+device with address
+.Ar address .
The address can be specified as BD_ADDR or name.
-If name was specified then the
+If name was specified then
.Nm
utility will attempt to resolve the name via
.Xr bt_gethostbyname 3 .
.It Fl b
Detach from the controlling terminal, i.e., run in background.
.It Fl c Ar channel
-This option specifies RFCOMM channel to connect to.
-RFCOMM channel could either be a number between 1 and 30 or a service name.
+In both client and server mode,
+this required option specifies the RFCOMM channel to connect to or listen on.
+In server mode,
+the channel should be a number between 1 and 30.
+If not specified,
+.Nm
+will try to allocate RFCOMM channel number based on process ID.
+In client mode,
+the channel could either be a number between 1 and 30 or a service name.
Supported service names are:
.Cm DUN
(for DialUp Networking service),
@@ -97,11 +136,16 @@ utility will try to obtain RFCOMM channel for Serial Port service via Service
Discovery Protocol from the server.
.It Fl h
Display usage message and exit.
+.It Fl S
+Server mode; see
+.Sx DESCRIPTION .
.It Fl t Ar tty
Slave pseudo tty name.
If not set stdin/stdout will be used.
This option is required if
.Fl b
+or
+.Fl S
option was specified.
.El
.Sh FILES
@@ -129,7 +173,8 @@ can be used to talk to the remote serial port on the server.
.Xr bluetooth 3 ,
.Xr ng_btsocket 4 ,
.Xr pty 4 ,
-.Xr rfcomm_pppd 8
+.Xr rfcomm_pppd 8 ,
+.Xr sdpd 8
.Sh AUTHORS
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com
.Sh BUGS
diff --git a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c
index 4ce893d..4c37d5f 100644
--- a/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c
+++ b/usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c
@@ -72,16 +72,17 @@ main(int argc, char *argv[])
struct sockaddr_rfcomm ra;
bdaddr_t addr;
int n, background, channel, service,
- s, amaster, aslave, fd;
+ s, amaster, aslave, fd, doserver;
fd_set rfd;
char *tty = NULL, *ep = NULL, buf[SPPD_BUFFER_SIZE];
memcpy(&addr, NG_HCI_BDADDR_ANY, sizeof(addr));
background = channel = 0;
service = SDP_SERVICE_CLASS_SERIAL_PORT;
+ doserver = 0;
/* Parse command line options */
- while ((n = getopt(argc, argv, "a:bc:t:h")) != -1) {
+ while ((n = getopt(argc, argv, "a:bc:t:hS")) != -1) {
switch (n) {
case 'a': /* BDADDR */
if (!bt_aton(optarg, &addr)) {
@@ -134,6 +135,10 @@ main(int argc, char *argv[])
tty = optarg;
break;
+ case 'S':
+ doserver = 1;
+ break;
+
case 'h':
default:
usage();
@@ -142,7 +147,7 @@ main(int argc, char *argv[])
}
/* Check if we have everything we need */
- if (memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0)
+ if (!doserver && memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0)
usage();
/* NOT REACHED */
@@ -165,17 +170,9 @@ main(int argc, char *argv[])
if (sigaction(SIGCHLD, &sa, NULL) < 0)
err(1, "Could not sigaction(SIGCHLD)");
- /* Check channel, if was not set then obtain it via SDP */
- if (channel == 0 && service != 0)
- if (rfcomm_channel_lookup(NULL, &addr,
- service, &channel, &n) != 0)
- errc(1, n, "Could not obtain RFCOMM channel");
- if (channel <= 0 || channel > 30)
- errx(1, "Invalid RFCOMM channel number %d", channel);
-
/* Open TTYs */
if (tty == NULL) {
- if (background)
+ if (background || doserver)
usage();
amaster = STDIN_FILENO;
@@ -187,24 +184,95 @@ main(int argc, char *argv[])
fd = amaster;
}
-
/* Open RFCOMM connection */
- memset(&ra, 0, sizeof(ra));
- ra.rfcomm_len = sizeof(ra);
- ra.rfcomm_family = AF_BLUETOOTH;
- s = socket(PF_BLUETOOTH, SOCK_STREAM, BLUETOOTH_PROTO_RFCOMM);
- if (s < 0)
- err(1, "Could not create socket");
-
- if (bind(s, (struct sockaddr *) &ra, sizeof(ra)) < 0)
- err(1, "Could not bind socket");
-
- memcpy(&ra.rfcomm_bdaddr, &addr, sizeof(ra.rfcomm_bdaddr));
- ra.rfcomm_channel = channel;
+ if (doserver) {
+ struct sockaddr_rfcomm ma;
+ bdaddr_t bt_addr_any;
+ sdp_lan_profile_t lan;
+ void *ss;
+ uint32_t sdp_handle;
+ int acceptsock, aaddrlen;
+
+ if (channel == 0) {
+ /* XXX: should check if selected channel is unused */
+ channel = (getpid() % 30) + 1;
+ }
+ acceptsock = socket(PF_BLUETOOTH, SOCK_STREAM,
+ BLUETOOTH_PROTO_RFCOMM);
+ if (acceptsock < 0)
+ err(1, "Could not create socket");
+
+ memset(&ma, 0, sizeof(ma));
+ ma.rfcomm_len = sizeof(ma);
+ ma.rfcomm_family = AF_BLUETOOTH;
+ ma.rfcomm_channel = channel;
+
+ if (bind(acceptsock, (struct sockaddr *)&ma, sizeof(ma)) < 0)
+ err(1, "Could not bind socket -- channel %d in use?",
+ channel);
+ listen(acceptsock, 10);
+
+ ss = sdp_open_local(NULL);
+ if (ss == NULL)
+ errx(1, "Unable to create local SDP session");
+ if (sdp_error(ss) != 0)
+ errx(1, "Unable to open local SDP session. %s (%d)",
+ strerror(sdp_error(ss)), sdp_error(ss));
+ memset(&lan, 0, sizeof(lan));
+ lan.server_channel = channel;
+
+ memcpy(&bt_addr_any, NG_HCI_BDADDR_ANY, sizeof(bt_addr_any));
+ if (sdp_register_service(ss, service, &bt_addr_any,
+ (void *)&lan, sizeof(lan), &sdp_handle) != 0) {
+ errx(1, "Unable to register LAN service with "
+ "local SDP daemon. %s (%d)",
+ strerror(sdp_error(ss)), sdp_error(ss));
+ }
- if (connect(s, (struct sockaddr *) &ra, sizeof(ra)) < 0)
- err(1, "Could not connect socket");
+ s = -1;
+ while (s < 0) {
+ aaddrlen = sizeof(ra);
+ s = accept(acceptsock, (struct sockaddr *)&ra,
+ &aaddrlen);
+ if (s < 0)
+ err(1, "Unable to accept()");
+ if (memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) &&
+ memcmp(&addr, &ra.rfcomm_bdaddr, sizeof(addr))) {
+ warnx("Connect from wrong client");
+ close(s);
+ s = -1;
+ }
+ }
+ sdp_unregister_service(ss, sdp_handle);
+ sdp_close(ss);
+ close(acceptsock);
+ } else {
+ /* Check channel, if was not set then obtain it via SDP */
+ if (channel == 0 && service != 0)
+ if (rfcomm_channel_lookup(NULL, &addr,
+ service, &channel, &n) != 0)
+ errc(1, n, "Could not obtain RFCOMM channel");
+ if (channel <= 0 || channel > 30)
+ errx(1, "Invalid RFCOMM channel number %d", channel);
+
+ s = socket(PF_BLUETOOTH, SOCK_STREAM, BLUETOOTH_PROTO_RFCOMM);
+ if (s < 0)
+ err(1, "Could not create socket");
+
+ memset(&ra, 0, sizeof(ra));
+ ra.rfcomm_len = sizeof(ra);
+ ra.rfcomm_family = AF_BLUETOOTH;
+
+ if (bind(s, (struct sockaddr *) &ra, sizeof(ra)) < 0)
+ err(1, "Could not bind socket");
+
+ memcpy(&ra.rfcomm_bdaddr, &addr, sizeof(ra.rfcomm_bdaddr));
+ ra.rfcomm_channel = channel;
+
+ if (connect(s, (struct sockaddr *) &ra, sizeof(ra)) < 0)
+ err(1, "Could not connect socket");
+ }
/* Became daemon if required */
if (background) {
@@ -346,7 +414,7 @@ sppd_ttys_open(char const *tty, int *amaster, int *aslave)
ttygid = -1;
(void) chown(tty, getuid(), ttygid);
- (void) chmod(tty, S_IRUSR|S_IWUSR|S_IWGRP);
+ (void) chmod(tty, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
(void) revoke(tty);
if ((*aslave = open(tty, O_RDWR, 0)) < 0) {
@@ -433,12 +501,12 @@ usage(void)
fprintf(stdout,
"Usage: %s options\n" \
"Where options are:\n" \
-"\t-a address Address to connect to (required)\n" \
+"\t-a address Peer address (required in client mode)\n" \
"\t-b Run in background\n" \
-"\t-c channel RFCOMM channel to connect to\n" \
-"\t-t tty TTY name (required in background mode)\n" \
+"\t-c channel RFCOMM channel to connect to or listen on\n" \
+"\t-t tty TTY name (required in background or server mode)\n" \
+"\t-S Server mode\n" \
"\t-h Display this message\n", SPPD_IDENT);
-
exit(255);
} /* usage */
OpenPOWER on IntegriCloud