Wed Nov 3 08:27:27 2010 UTC ()
In server mode, relax the requirement to specify a channel number. If
one is not given, attempt to allocate the first unused one.


(plunky)
diff -r1.8 -r1.9 src/usr.bin/rfcomm_sppd/rfcomm_sppd.1
diff -r1.12 -r1.13 src/usr.bin/rfcomm_sppd/rfcomm_sppd.c

cvs diff -r1.8 -r1.9 src/usr.bin/rfcomm_sppd/rfcomm_sppd.1 (expand / switch to unified diff)

--- src/usr.bin/rfcomm_sppd/rfcomm_sppd.1 2010/11/02 19:44:09 1.8
+++ src/usr.bin/rfcomm_sppd/rfcomm_sppd.1 2010/11/03 08:27:27 1.9
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1.\" $NetBSD: rfcomm_sppd.1,v 1.8 2010/11/02 19:44:09 plunky Exp $ 1.\" $NetBSD: rfcomm_sppd.1,v 1.9 2010/11/03 08:27:27 plunky Exp $
2.\" 2.\"
3.\" Copyright (c) 2006 Itronix Inc. 3.\" Copyright (c) 2006 Itronix Inc.
4.\" All rights reserved. 4.\" All rights reserved.
5.\" 5.\"
6.\" Redistribution and use in source and binary forms, with or without 6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions 7.\" modification, are permitted provided that the following conditions
8.\" are met: 8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright 9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions and the following disclaimer. 10.\" notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright 11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\" notice, this list of conditions and the following disclaimer in the 12.\" notice, this list of conditions and the following disclaimer in the
13.\" documentation and/or other materials provided with the distribution. 13.\" documentation and/or other materials provided with the distribution.
14.\" 3. The name of Itronix Inc. may not be used to endorse 14.\" 3. The name of Itronix Inc. may not be used to endorse
@@ -55,63 +55,63 @@ @@ -55,63 +55,63 @@
55.Dd November 2, 2010 55.Dd November 2, 2010
56.Dt RFCOMM_SPPD 1 56.Dt RFCOMM_SPPD 1
57.Os 57.Os
58.Sh NAME 58.Sh NAME
59.Nm rfcomm_sppd 59.Nm rfcomm_sppd
60.Nd RFCOMM Serial Port Profile daemon 60.Nd RFCOMM Serial Port Profile daemon
61.Sh SYNOPSIS 61.Sh SYNOPSIS
62.Nm 62.Nm
63.Op Fl d Ar device 63.Op Fl d Ar device
64.Op Fl m Ar mode 64.Op Fl m Ar mode
65.Op Fl p Ar psm 65.Op Fl p Ar psm
66.Op Fl s Ar service 66.Op Fl s Ar service
67.Op Fl t Ar tty 67.Op Fl t Ar tty
68.Brq Fl a Ar address | Fl c Ar channel 68.Brq Fl a Ar address | Op Fl c Ar channel
69.Sh DESCRIPTION 69.Sh DESCRIPTION
70The 70The
71.Nm 71.Nm
72utility is a Serial Port Profile daemon, providing serial access over 72utility is a Serial Port Profile daemon, providing serial access over
73an RFCOMM connection to a remote device. 73an RFCOMM connection to a remote device.
74.Nm 74.Nm
75can work in client or server mode. 75can work in client or server mode.
76.Pp 76.Pp
77In client mode, 77In client mode,
78.Nm 78.Nm
79initiates an RFCOMM connection to the 79initiates an RFCOMM connection to the
80.Ar service 80.Ar service
81at the remote 81at the remote
82.Ar address . 82.Ar address .
83.Pp 83.Pp
84In server mode, 84In server mode,
85.Nm 85.Nm
86registers the 86registers the
87.Ar service 87.Ar service
88with the local SDP server and listens on the specified RFCOMM 88with the local SDP server and listens on the specified RFCOMM
89.Ar channel 89.Ar channel
90for an incoming connection. 90for an incoming connection, or the first unused channel if none
 91was given.
91.Pp 92.Pp
92The options are as follows: 93The options are as follows:
93.Bl -tag -width ".Fl c Ar channel" 94.Bl -tag -width ".Fl c Ar channel"
94.It Fl a Ar address 95.It Fl a Ar address
95Client mode. 96Client mode.
96Specify the address of the remote RFCOMM device. 97Specify the address of the remote RFCOMM device.
97The address can be specified as BD_ADDR or name. 98The address can be specified as BD_ADDR or name.
98If given as a name, then the 99If given as a name, then the
99.Nm 100.Nm
100utility will attempt to resolve the name via 101utility will attempt to resolve the name via
101.Xr bt_gethostbyname 3 . 102.Xr bt_gethostbyname 3 .
102.It Fl c Ar channel 103.It Fl c Ar channel
103Server mode. 104In server mode, specify the RFCOMM channel number to listen on.
104Specify the RFCOMM channel number to listen on. 
105.Nm 105.Nm
106will register the service with the local 106will register the service with the local
107.Xr sdpd 8 107.Xr sdpd 8
108daemon. 108daemon.
109Note that registering services with 109Note that registering services with
110.Xr sdpd 8 110.Xr sdpd 8
111is a privileged operation. 111is a privileged operation.
112.It Fl d Ar device 112.It Fl d Ar device
113Use the local device with the specified address. 113Use the local device with the specified address.
114The device can be specified by BD_ADDR or device name. 114The device can be specified by BD_ADDR or device name.
115See 115See
116.Xr btconfig 8 116.Xr btconfig 8
117for a list of available devices. 117for a list of available devices.

cvs diff -r1.12 -r1.13 src/usr.bin/rfcomm_sppd/rfcomm_sppd.c (expand / switch to unified diff)

--- src/usr.bin/rfcomm_sppd/rfcomm_sppd.c 2009/09/24 18:30:37 1.12
+++ src/usr.bin/rfcomm_sppd/rfcomm_sppd.c 2010/11/03 08:27:27 1.13
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: rfcomm_sppd.c,v 1.12 2009/09/24 18:30:37 plunky Exp $ */ 1/* $NetBSD: rfcomm_sppd.c,v 1.13 2010/11/03 08:27:27 plunky Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2006 Itronix Inc. 4 * Copyright (c) 2006 Itronix Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -52,27 +52,27 @@ @@ -52,27 +52,27 @@
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE. 56 * SUCH DAMAGE.
57 */ 57 */
58 58
59#include <sys/cdefs.h> 59#include <sys/cdefs.h>
60__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc.\ 60__COPYRIGHT("@(#) Copyright (c) 2009 The NetBSD Foundation, Inc.\
61 Copyright (c) 2007 Iain Hibbert.\ 61 Copyright (c) 2007 Iain Hibbert.\
62 Copyright (c) 2006 Itronix, Inc.\ 62 Copyright (c) 2006 Itronix, Inc.\
63 Copyright (c) 2003 Maksim Yevmenkin m_evmenkin@yahoo.com.\ 63 Copyright (c) 2003 Maksim Yevmenkin m_evmenkin@yahoo.com.\
64 All rights reserved."); 64 All rights reserved.");
65__RCSID("$NetBSD: rfcomm_sppd.c,v 1.12 2009/09/24 18:30:37 plunky Exp $"); 65__RCSID("$NetBSD: rfcomm_sppd.c,v 1.13 2010/11/03 08:27:27 plunky Exp $");
66 66
67#include <sys/param.h> 67#include <sys/param.h>
68 68
69#include <bluetooth.h> 69#include <bluetooth.h>
70#include <ctype.h> 70#include <ctype.h>
71#include <err.h> 71#include <err.h>
72#include <errno.h> 72#include <errno.h>
73#include <fcntl.h> 73#include <fcntl.h>
74#include <grp.h> 74#include <grp.h>
75#include <limits.h> 75#include <limits.h>
76#include <paths.h> 76#include <paths.h>
77#include <sdp.h> 77#include <sdp.h>
78#include <signal.h> 78#include <signal.h>
@@ -118,48 +118,50 @@ main(int argc, char *argv[]) @@ -118,48 +118,50 @@ main(int argc, char *argv[])
118 struct termios t; 118 struct termios t;
119 bdaddr_t laddr, raddr; 119 bdaddr_t laddr, raddr;
120 fd_set rdset; 120 fd_set rdset;
121 const char *service; 121 const char *service;
122 char *ep, *tty; 122 char *ep, *tty;
123 int lm, n, rfcomm, tty_in, tty_out; 123 int lm, n, rfcomm, tty_in, tty_out;
124 uint16_t psm; 124 uint16_t psm;
125 uint8_t channel; 125 uint8_t channel;
126 126
127 bdaddr_copy(&laddr, BDADDR_ANY); 127 bdaddr_copy(&laddr, BDADDR_ANY);
128 bdaddr_copy(&raddr, BDADDR_ANY); 128 bdaddr_copy(&raddr, BDADDR_ANY);
129 service = "SP"; 129 service = "SP";
130 tty = NULL; 130 tty = NULL;
131 channel = 0; 131 channel = RFCOMM_CHANNEL_ANY;
132 psm = L2CAP_PSM_RFCOMM; 132 psm = L2CAP_PSM_RFCOMM;
133 lm = 0; 133 lm = 0;
134 134
135 /* Parse command line options */ 135 /* Parse command line options */
136 while ((n = getopt(argc, argv, "a:c:d:hm:p:s:t:")) != -1) { 136 while ((n = getopt(argc, argv, "a:c:d:hm:p:s:t:")) != -1) {
137 switch (n) { 137 switch (n) {
138 case 'a': /* remote device address */ 138 case 'a': /* remote device address */
139 if (!bt_aton(optarg, &raddr)) { 139 if (!bt_aton(optarg, &raddr)) {
140 struct hostent *he = NULL; 140 struct hostent *he = NULL;
141 141
142 if ((he = bt_gethostbyname(optarg)) == NULL) 142 if ((he = bt_gethostbyname(optarg)) == NULL)
143 errx(EXIT_FAILURE, "%s: %s", optarg, 143 errx(EXIT_FAILURE, "%s: %s", optarg,
144 hstrerror(h_errno)); 144 hstrerror(h_errno));
145 145
146 bdaddr_copy(&raddr, (bdaddr_t *)he->h_addr); 146 bdaddr_copy(&raddr, (bdaddr_t *)he->h_addr);
147 } 147 }
148 break; 148 break;
149 149
150 case 'c': /* RFCOMM channel */ 150 case 'c': /* RFCOMM channel */
151 channel = strtoul(optarg, &ep, 10); 151 channel = strtoul(optarg, &ep, 10);
152 if (*ep != '\0' || channel < 1 || channel > 30) 152 if (*ep != '\0'
 153 || channel < RFCOMM_CHANNEL_MIN
 154 || channel > RFCOMM_CHANNEL_MAX)
153 errx(EXIT_FAILURE, "Invalid channel: %s", optarg); 155 errx(EXIT_FAILURE, "Invalid channel: %s", optarg);
154 156
155 break; 157 break;
156 158
157 case 'd': /* local device address */ 159 case 'd': /* local device address */
158 if (!bt_devaddr(optarg, &laddr)) 160 if (!bt_devaddr(optarg, &laddr))
159 err(EXIT_FAILURE, "%s", optarg); 161 err(EXIT_FAILURE, "%s", optarg);
160 162
161 break; 163 break;
162 164
163 case 'm': /* Link Mode */ 165 case 'm': /* Link Mode */
164 if (strcasecmp(optarg, "auth") == 0) 166 if (strcasecmp(optarg, "auth") == 0)
165 lm = RFCOMM_LM_AUTH; 167 lm = RFCOMM_LM_AUTH;
@@ -190,45 +192,44 @@ main(int argc, char *argv[]) @@ -190,45 +192,44 @@ main(int argc, char *argv[])
190 tty = optarg; 192 tty = optarg;
191 193
192 break; 194 break;
193 195
194 case 'h': 196 case 'h':
195 default: 197 default:
196 usage(); 198 usage();
197 /* NOT REACHED */ 199 /* NOT REACHED */
198 } 200 }
199 } 201 }
200 202
201 /* 203 /*
202 * validate options: 204 * validate options:
203 * must have channel or remote address but not both 205 * cannot have remote address if channel was given
204 */ 206 */
205 if ((channel == 0 && bdaddr_any(&raddr)) 207 if (channel != RFCOMM_CHANNEL_ANY && !bdaddr_any(&raddr))
206 || (channel != 0 && !bdaddr_any(&raddr))) 
207 usage(); 208 usage();
208 209
209 /* 210 /*
210 * grab ttys before we start the bluetooth 211 * grab ttys before we start the bluetooth
211 */ 212 */
212 if (tty == NULL) { 213 if (tty == NULL) {
213 tty_in = STDIN_FILENO; 214 tty_in = STDIN_FILENO;
214 tty_out = STDOUT_FILENO; 215 tty_out = STDOUT_FILENO;
215 } else { 216 } else {
216 tty_in = open_tty(tty); 217 tty_in = open_tty(tty);
217 tty_out = tty_in; 218 tty_out = tty_in;
218 } 219 }
219 220
220 /* open RFCOMM */ 221 /* open RFCOMM */
221 if (channel == 0) 222 if (!bdaddr_any(&raddr))
222 rfcomm = open_client(&laddr, &raddr, lm, psm, service); 223 rfcomm = open_client(&laddr, &raddr, lm, psm, service);
223 else 224 else
224 rfcomm = open_server(&laddr, psm, channel, lm, service); 225 rfcomm = open_server(&laddr, psm, channel, lm, service);
225 226
226 /* 227 /*
227 * now we are ready to go, so either detach or maybe turn 228 * now we are ready to go, so either detach or maybe turn
228 * off some input processing, so that rfcomm_sppd can 229 * off some input processing, so that rfcomm_sppd can
229 * be used directly with stdio 230 * be used directly with stdio
230 */ 231 */
231 if (tty == NULL) { 232 if (tty == NULL) {
232 if (tcgetattr(tty_in, &t) < 0) 233 if (tcgetattr(tty_in, &t) < 0)
233 err(EXIT_FAILURE, "tcgetattr"); 234 err(EXIT_FAILURE, "tcgetattr");
234 235
@@ -423,48 +424,54 @@ open_server(bdaddr_t *laddr, uint16_t ps @@ -423,48 +424,54 @@ open_server(bdaddr_t *laddr, uint16_t ps
423 sa.bt_psm = psm; 424 sa.bt_psm = psm;
424 sa.bt_channel = channel; 425 sa.bt_channel = channel;
425 bdaddr_copy(&sa.bt_bdaddr, laddr); 426 bdaddr_copy(&sa.bt_bdaddr, laddr);
426 if (bind(sv, (struct sockaddr *)&sa, sizeof(sa)) < 0) 427 if (bind(sv, (struct sockaddr *)&sa, sizeof(sa)) < 0)
427 err(EXIT_FAILURE, "bind(%s, 0x%04x, %d)", 428 err(EXIT_FAILURE, "bind(%s, 0x%04x, %d)",
428 bt_ntoa(laddr, NULL), psm, channel); 429 bt_ntoa(laddr, NULL), psm, channel);
429 430
430 if (setsockopt(sv, BTPROTO_RFCOMM, SO_RFCOMM_LM, &lm, sizeof(lm)) < 0) 431 if (setsockopt(sv, BTPROTO_RFCOMM, SO_RFCOMM_LM, &lm, sizeof(lm)) < 0)
431 err(EXIT_FAILURE, "link mode"); 432 err(EXIT_FAILURE, "link mode");
432 433
433 if (listen(sv, 1) < 0) 434 if (listen(sv, 1) < 0)
434 err(EXIT_FAILURE, "listen()"); 435 err(EXIT_FAILURE, "listen()");
435 436
 437 len = sizeof(sa);
 438 if (getsockname(sv, (struct sockaddr *)&sa, &len) < 0)
 439 err(EXIT_FAILURE, "getsockname()");
 440 if (len != sizeof(sa))
 441 errx(EXIT_FAILURE, "getsockname()");
 442
436 /* Build SDP record */ 443 /* Build SDP record */
437 rec.next = buffer; 444 rec.next = buffer;
438 rec.end = buffer + sizeof(buffer); 445 rec.end = buffer + sizeof(buffer);
439 446
440 sdp_put_uint16(&rec, SDP_ATTR_SERVICE_RECORD_HANDLE); 447 sdp_put_uint16(&rec, SDP_ATTR_SERVICE_RECORD_HANDLE);
441 sdp_put_uint32(&rec, 0x00000000); 448 sdp_put_uint32(&rec, 0x00000000);
442 449
443 sdp_put_uint16(&rec, SDP_ATTR_SERVICE_CLASS_ID_LIST); 450 sdp_put_uint16(&rec, SDP_ATTR_SERVICE_CLASS_ID_LIST);
444 sdp_put_seq(&rec, 3); 451 sdp_put_seq(&rec, 3);
445 sdp_put_uuid16(&rec, s->class); 452 sdp_put_uuid16(&rec, s->class);
446 453
447 len = (psm == L2CAP_PSM_RFCOMM ? 0 : 3); 454 len = (psm == L2CAP_PSM_RFCOMM ? 0 : 3);
448 455
449 sdp_put_uint16(&rec, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST); 456 sdp_put_uint16(&rec, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST);
450 sdp_put_seq(&rec, 12 + len); 457 sdp_put_seq(&rec, 12 + len);
451 sdp_put_seq(&rec, 3 + len); 458 sdp_put_seq(&rec, 3 + len);
452 sdp_put_uuid16(&rec, SDP_UUID_PROTOCOL_L2CAP); 459 sdp_put_uuid16(&rec, SDP_UUID_PROTOCOL_L2CAP);
453 if (len > 0) 460 if (len > 0)
454 sdp_put_uint16(&rec, psm); 461 sdp_put_uint16(&rec, psm);
455 sdp_put_seq(&rec, 5); 462 sdp_put_seq(&rec, 5);
456 sdp_put_uuid16(&rec, SDP_UUID_PROTOCOL_RFCOMM); 463 sdp_put_uuid16(&rec, SDP_UUID_PROTOCOL_RFCOMM);
457 sdp_put_uint8(&rec, channel); 464 sdp_put_uint8(&rec, sa.bt_channel);
458 465
459 sdp_put_uint16(&rec, SDP_ATTR_BROWSE_GROUP_LIST); 466 sdp_put_uint16(&rec, SDP_ATTR_BROWSE_GROUP_LIST);
460 sdp_put_seq(&rec, 3); 467 sdp_put_seq(&rec, 3);
461 sdp_put_uuid16(&rec, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP); 468 sdp_put_uuid16(&rec, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP);
462 469
463 sdp_put_uint16(&rec, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST); 470 sdp_put_uint16(&rec, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
464 sdp_put_seq(&rec, 9); 471 sdp_put_seq(&rec, 9);
465 sdp_put_uint16(&rec, 0x656e); /* "en" */ 472 sdp_put_uint16(&rec, 0x656e); /* "en" */
466 sdp_put_uint16(&rec, 106); /* UTF-8 */ 473 sdp_put_uint16(&rec, 106); /* UTF-8 */
467 sdp_put_uint16(&rec, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID); 474 sdp_put_uint16(&rec, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID);
468 475
469 if (s->class == SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP) { 476 if (s->class == SDP_SERVICE_CLASS_LAN_ACCESS_USING_PPP) {
470 sdp_put_uint16(&rec, SDP_ATTR_SERVICE_AVAILABILITY); 477 sdp_put_uint16(&rec, SDP_ATTR_SERVICE_AVAILABILITY);
@@ -661,27 +668,27 @@ void @@ -661,27 +668,27 @@ void
661reset_tio(void) 668reset_tio(void)
662{ 669{
663 670
664 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); 671 tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio);
665} 672}
666 673
667void 674void
668usage(void) 675usage(void)
669{ 676{
670 const char *cmd = getprogname(); 677 const char *cmd = getprogname();
671 struct service *s; 678 struct service *s;
672 679
673 fprintf(stderr, "Usage: %s [-d device] [-m mode] [-p psm] [-s service] [-t tty]\n" 680 fprintf(stderr, "Usage: %s [-d device] [-m mode] [-p psm] [-s service] [-t tty]\n"
674 " %*s {-a bdaddr | -c channel}\n" 681 " %*s {-a bdaddr | [-c channel]}\n"
675 "\n" 682 "\n"
676 "Where:\n" 683 "Where:\n"
677 "\t-a bdaddr remote device address\n" 684 "\t-a bdaddr remote device address\n"
678 "\t-c channel local RFCOMM channel\n" 685 "\t-c channel local RFCOMM channel\n"
679 "\t-d device local device address\n" 686 "\t-d device local device address\n"
680 "\t-m mode link mode\n" 687 "\t-m mode link mode\n"
681 "\t-p psm protocol/service multiplexer\n" 688 "\t-p psm protocol/service multiplexer\n"
682 "\t-s service service class\n" 689 "\t-s service service class\n"
683 "\t-t tty run in background using pty\n" 690 "\t-t tty run in background using pty\n"
684 "\n", cmd, (int)strlen(cmd), ""); 691 "\n", cmd, (int)strlen(cmd), "");
685 692
686 fprintf(stderr, "Known service classes:\n"); 693 fprintf(stderr, "Known service classes:\n");
687 for (s = services ; s->name != NULL ; s++) 694 for (s = services ; s->name != NULL ; s++)