| @@ -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 |
661 | reset_tio(void) | | 668 | reset_tio(void) |
662 | { | | 669 | { |
663 | | | 670 | |
664 | tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); | | 671 | tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio); |
665 | } | | 672 | } |
666 | | | 673 | |
667 | void | | 674 | void |
668 | usage(void) | | 675 | usage(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++) |