1 /*
2 *
3 * BlueZ - Bluetooth protocol stack for Linux
4 *
5 * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
6 *
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #define _GNU_SOURCE
29 #include <stdio.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <getopt.h>
36 #include <signal.h>
37 #include <termios.h>
38 #include <sys/poll.h>
39 #include <sys/param.h>
40 #include <sys/ioctl.h>
41 #include <sys/socket.h>
42 #include <sys/wait.h>
43
44 #include <bluetooth/bluetooth.h>
45 #include <bluetooth/hci.h>
46 #include <bluetooth/hci_lib.h>
47 #include <bluetooth/rfcomm.h>
48
49 #include "kword.h"
50
51 #ifdef NEED_PPOLL
52 #include "ppoll.h"
53 #endif
54
55 static char *rfcomm_config_file = NULL;
56 static int rfcomm_raw_tty = 0;
57 static int auth = 0;
58 static int encryption = 0;
59 static int secure = 0;
60 static int master = 0;
61 static int linger = 0;
62
63 static char *rfcomm_state[] = {
64 "unknown",
65 "connected",
66 "clean",
67 "bound",
68 "listening",
69 "connecting",
70 "connecting",
71 "config",
72 "disconnecting",
73 "closed"
74 };
75
76 static volatile sig_atomic_t __io_canceled = 0;
77
sig_hup(int sig)78 static void sig_hup(int sig)
79 {
80 return;
81 }
82
sig_term(int sig)83 static void sig_term(int sig)
84 {
85 __io_canceled = 1;
86 }
87
rfcomm_flagstostr(uint32_t flags)88 static char *rfcomm_flagstostr(uint32_t flags)
89 {
90 static char str[100];
91 str[0] = 0;
92
93 strcat(str, "[");
94
95 if (flags & (1 << RFCOMM_REUSE_DLC))
96 strcat(str, "reuse-dlc ");
97
98 if (flags & (1 << RFCOMM_RELEASE_ONHUP))
99 strcat(str, "release-on-hup ");
100
101 if (flags & (1 << RFCOMM_TTY_ATTACHED))
102 strcat(str, "tty-attached");
103
104 strcat(str, "]");
105 return str;
106 }
107
print_dev_info(struct rfcomm_dev_info * di)108 static void print_dev_info(struct rfcomm_dev_info *di)
109 {
110 char src[18], dst[18], addr[40];
111
112 ba2str(&di->src, src); ba2str(&di->dst, dst);
113
114 if (bacmp(&di->src, BDADDR_ANY) == 0)
115 sprintf(addr, "%s", dst);
116 else
117 sprintf(addr, "%s -> %s", src, dst);
118
119 printf("rfcomm%d: %s channel %d %s %s\n",
120 di->id, addr, di->channel,
121 rfcomm_state[di->state],
122 di->flags ? rfcomm_flagstostr(di->flags) : "");
123 }
124
print_dev_list(int ctl,int flags)125 static void print_dev_list(int ctl, int flags)
126 {
127 struct rfcomm_dev_list_req *dl;
128 struct rfcomm_dev_info *di;
129 int i;
130
131 dl = malloc(sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));
132 if (!dl) {
133 perror("Can't allocate memory");
134 exit(1);
135 }
136
137 dl->dev_num = RFCOMM_MAX_DEV;
138 di = dl->dev_info;
139
140 if (ioctl(ctl, RFCOMMGETDEVLIST, (void *) dl) < 0) {
141 perror("Can't get device list");
142 free(dl);
143 exit(1);
144 }
145
146 for (i = 0; i < dl->dev_num; i++)
147 print_dev_info(di + i);
148 free(dl);
149 }
150
create_dev(int ctl,int dev,uint32_t flags,bdaddr_t * bdaddr,int argc,char ** argv)151 static int create_dev(int ctl, int dev, uint32_t flags, bdaddr_t *bdaddr, int argc, char **argv)
152 {
153 struct rfcomm_dev_req req;
154 int err;
155
156 memset(&req, 0, sizeof(req));
157 req.dev_id = dev;
158 req.flags = flags;
159 bacpy(&req.src, bdaddr);
160
161 if (argc < 2) {
162 err = rfcomm_read_config(rfcomm_config_file);
163 if (err < 0) {
164 perror("Can't open RFCOMM config file");
165 return err;
166 }
167
168 bacpy(&req.dst, &rfcomm_opts[dev].bdaddr);
169 req.channel = rfcomm_opts[dev].channel;
170
171 if (bacmp(&req.dst, BDADDR_ANY) == 0) {
172 fprintf(stderr, "Can't find a config entry for rfcomm%d\n", dev);
173 return -EFAULT;
174 }
175 } else {
176 str2ba(argv[1], &req.dst);
177
178 if (argc > 2)
179 req.channel = atoi(argv[2]);
180 else
181 req.channel = 1;
182 }
183
184 err = ioctl(ctl, RFCOMMCREATEDEV, &req);
185 if (err == EOPNOTSUPP)
186 fprintf(stderr, "RFCOMM TTY support not available\n");
187 else if (err < 0)
188 perror("Can't create device");
189
190 return err;
191 }
192
create_all(int ctl)193 static int create_all(int ctl)
194 {
195 struct rfcomm_dev_req req;
196 int i, err;
197
198 err = rfcomm_read_config(rfcomm_config_file);
199 if (err < 0) {
200 perror("Can't open RFCOMM config file");
201 return err;
202 }
203
204 for (i = 0; i < RFCOMM_MAX_DEV; i++) {
205 if (!rfcomm_opts[i].bind)
206 continue;
207
208 memset(&req, 0, sizeof(req));
209 req.dev_id = i;
210 req.flags = 0;
211 bacpy(&req.src, BDADDR_ANY);
212 bacpy(&req.dst, &rfcomm_opts[i].bdaddr);
213 req.channel = rfcomm_opts[i].channel;
214
215 if (bacmp(&req.dst, BDADDR_ANY) != 0)
216 ioctl(ctl, RFCOMMCREATEDEV, &req);
217 }
218
219 return 0;
220 }
221
release_dev(int ctl,int dev,uint32_t flags)222 static int release_dev(int ctl, int dev, uint32_t flags)
223 {
224 struct rfcomm_dev_req req;
225 int err;
226
227 memset(&req, 0, sizeof(req));
228 req.dev_id = dev;
229
230 err = ioctl(ctl, RFCOMMRELEASEDEV, &req);
231 if (err < 0)
232 perror("Can't release device");
233
234 return err;
235 }
236
release_all(int ctl)237 static int release_all(int ctl)
238 {
239 struct rfcomm_dev_list_req *dl;
240 struct rfcomm_dev_info *di;
241 int i;
242
243 dl = malloc(sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));
244 if (!dl) {
245 perror("Can't allocate memory");
246 exit(1);
247 }
248
249 dl->dev_num = RFCOMM_MAX_DEV;
250 di = dl->dev_info;
251
252 if (ioctl(ctl, RFCOMMGETDEVLIST, (void *) dl) < 0) {
253 perror("Can't get device list");
254 free(dl);
255 exit(1);
256 }
257
258 for (i = 0; i < dl->dev_num; i++)
259 release_dev(ctl, (di + i)->id, 0);
260
261 free(dl);
262 return 0;
263 }
264
run_cmdline(struct pollfd * p,sigset_t * sigs,char * devname,int argc,char ** argv)265 static void run_cmdline(struct pollfd *p, sigset_t* sigs, char *devname,
266 int argc, char **argv)
267 {
268 int i;
269 pid_t pid;
270 char **cmdargv;
271
272 cmdargv = malloc((argc + 1) * sizeof(char*));
273 if (!cmdargv)
274 return;
275
276 for (i = 0; i < argc; i++)
277 cmdargv[i] = (strcmp(argv[i], "{}") == 0) ? devname : argv[i];
278 cmdargv[i] = NULL;
279
280 pid = fork();
281
282 switch (pid) {
283 case 0:
284 i = execvp(cmdargv[0], cmdargv);
285 fprintf(stderr, "Couldn't execute command %s (errno=%d:%s)\n",
286 cmdargv[0], errno, strerror(errno));
287 break;
288 case -1:
289 fprintf(stderr, "Couldn't fork to execute command %s\n",
290 cmdargv[0]);
291 break;
292 default:
293 while (1) {
294 int status;
295 pid_t child;
296 struct timespec ts;
297
298 child = waitpid(-1, &status, WNOHANG);
299 if (child == pid || (child < 0 && errno != EAGAIN))
300 break;
301
302 p->revents = 0;
303 ts.tv_sec = 0;
304 ts.tv_nsec = 200;
305 if (ppoll(p, 1, &ts, sigs) || __io_canceled) {
306 kill(pid, SIGTERM);
307 waitpid(pid, &status, 0);
308 break;
309 }
310 }
311 break;
312 }
313
314 free(cmdargv);
315 }
316
cmd_connect(int ctl,int dev,bdaddr_t * bdaddr,int argc,char ** argv)317 static void cmd_connect(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
318 {
319 struct sockaddr_rc laddr, raddr;
320 struct rfcomm_dev_req req;
321 struct termios ti;
322 struct sigaction sa;
323 struct pollfd p;
324 sigset_t sigs;
325 socklen_t alen;
326 char dst[18], devname[MAXPATHLEN];
327 int sk, fd, try = 30;
328
329 laddr.rc_family = AF_BLUETOOTH;
330 bacpy(&laddr.rc_bdaddr, bdaddr);
331 laddr.rc_channel = 0;
332
333 if (argc < 2) {
334 if (rfcomm_read_config(rfcomm_config_file) < 0) {
335 perror("Can't open RFCOMM config file");
336 return;
337 }
338
339 raddr.rc_family = AF_BLUETOOTH;
340 bacpy(&raddr.rc_bdaddr, &rfcomm_opts[dev].bdaddr);
341 raddr.rc_channel = rfcomm_opts[dev].channel;
342
343 if (bacmp(&raddr.rc_bdaddr, BDADDR_ANY) == 0) {
344 fprintf(stderr, "Can't find a config entry for rfcomm%d\n", dev);
345 return;
346 }
347 } else {
348 raddr.rc_family = AF_BLUETOOTH;
349 str2ba(argv[1], &raddr.rc_bdaddr);
350
351 if (argc > 2)
352 raddr.rc_channel = atoi(argv[2]);
353 else
354 raddr.rc_channel = 1;
355 }
356
357 sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
358 if (sk < 0) {
359 perror("Can't create RFCOMM socket");
360 return;
361 }
362
363 if (linger) {
364 struct linger l = { .l_onoff = 1, .l_linger = linger };
365
366 if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
367 perror("Can't set linger option");
368 return;
369 }
370 }
371
372 if (bind(sk, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) {
373 perror("Can't bind RFCOMM socket");
374 close(sk);
375 return;
376 }
377
378 if (connect(sk, (struct sockaddr *) &raddr, sizeof(raddr)) < 0) {
379 perror("Can't connect RFCOMM socket");
380 close(sk);
381 return;
382 }
383
384 alen = sizeof(laddr);
385 if (getsockname(sk, (struct sockaddr *)&laddr, &alen) < 0) {
386 perror("Can't get RFCOMM socket name");
387 close(sk);
388 return;
389 }
390
391 memset(&req, 0, sizeof(req));
392 req.dev_id = dev;
393 req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
394
395 bacpy(&req.src, &laddr.rc_bdaddr);
396 bacpy(&req.dst, &raddr.rc_bdaddr);
397 req.channel = raddr.rc_channel;
398
399 dev = ioctl(sk, RFCOMMCREATEDEV, &req);
400 if (dev < 0) {
401 perror("Can't create RFCOMM TTY");
402 close(sk);
403 return;
404 }
405
406 snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
407 while ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
408 if (errno == EACCES) {
409 perror("Can't open RFCOMM device");
410 goto release;
411 }
412
413 snprintf(devname, MAXPATHLEN - 1, "/dev/bluetooth/rfcomm/%d", dev);
414 if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
415 if (try--) {
416 snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
417 usleep(100 * 1000);
418 continue;
419 }
420 perror("Can't open RFCOMM device");
421 goto release;
422 }
423 }
424
425 if (rfcomm_raw_tty) {
426 tcflush(fd, TCIOFLUSH);
427
428 cfmakeraw(&ti);
429 tcsetattr(fd, TCSANOW, &ti);
430 }
431
432 close(sk);
433
434 ba2str(&req.dst, dst);
435 printf("Connected %s to %s on channel %d\n", devname, dst, req.channel);
436 printf("Press CTRL-C for hangup\n");
437
438 memset(&sa, 0, sizeof(sa));
439 sa.sa_flags = SA_NOCLDSTOP;
440 sa.sa_handler = SIG_IGN;
441 sigaction(SIGCHLD, &sa, NULL);
442 sigaction(SIGPIPE, &sa, NULL);
443
444 sa.sa_handler = sig_term;
445 sigaction(SIGTERM, &sa, NULL);
446 sigaction(SIGINT, &sa, NULL);
447
448 sa.sa_handler = sig_hup;
449 sigaction(SIGHUP, &sa, NULL);
450
451 sigfillset(&sigs);
452 sigdelset(&sigs, SIGCHLD);
453 sigdelset(&sigs, SIGPIPE);
454 sigdelset(&sigs, SIGTERM);
455 sigdelset(&sigs, SIGINT);
456 sigdelset(&sigs, SIGHUP);
457
458 p.fd = fd;
459 p.events = POLLERR | POLLHUP;
460
461 while (!__io_canceled) {
462 p.revents = 0;
463 if (ppoll(&p, 1, NULL, &sigs) > 0)
464 break;
465 }
466
467 printf("Disconnected\n");
468
469 close(fd);
470 return;
471
472 release:
473 memset(&req, 0, sizeof(req));
474 req.dev_id = dev;
475 req.flags = (1 << RFCOMM_HANGUP_NOW);
476 ioctl(ctl, RFCOMMRELEASEDEV, &req);
477
478 close(sk);
479 }
480
cmd_listen(int ctl,int dev,bdaddr_t * bdaddr,int argc,char ** argv)481 static void cmd_listen(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
482 {
483 struct sockaddr_rc laddr, raddr;
484 struct rfcomm_dev_req req;
485 struct termios ti;
486 struct sigaction sa;
487 struct pollfd p;
488 sigset_t sigs;
489 socklen_t alen;
490 char dst[18], devname[MAXPATHLEN];
491 int sk, nsk, fd, lm, try = 30;
492
493 laddr.rc_family = AF_BLUETOOTH;
494 bacpy(&laddr.rc_bdaddr, bdaddr);
495 laddr.rc_channel = (argc < 2) ? 1 : atoi(argv[1]);
496
497 sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
498 if (sk < 0) {
499 perror("Can't create RFCOMM socket");
500 return;
501 }
502
503 lm = 0;
504 if (master)
505 lm |= RFCOMM_LM_MASTER;
506 if (auth)
507 lm |= RFCOMM_LM_AUTH;
508 if (encryption)
509 lm |= RFCOMM_LM_ENCRYPT;
510 if (secure)
511 lm |= RFCOMM_LM_SECURE;
512
513 if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) {
514 perror("Can't set RFCOMM link mode");
515 close(sk);
516 return;
517 }
518
519 if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
520 perror("Can't bind RFCOMM socket");
521 close(sk);
522 return;
523 }
524
525 printf("Waiting for connection on channel %d\n", laddr.rc_channel);
526
527 listen(sk, 10);
528
529 alen = sizeof(raddr);
530 nsk = accept(sk, (struct sockaddr *) &raddr, &alen);
531
532 alen = sizeof(laddr);
533 if (getsockname(nsk, (struct sockaddr *)&laddr, &alen) < 0) {
534 perror("Can't get RFCOMM socket name");
535 close(nsk);
536 return;
537 }
538
539 if (linger) {
540 struct linger l = { .l_onoff = 1, .l_linger = linger };
541
542 if (setsockopt(nsk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
543 perror("Can't set linger option");
544 close(nsk);
545 return;
546 }
547 }
548
549 memset(&req, 0, sizeof(req));
550 req.dev_id = dev;
551 req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
552
553 bacpy(&req.src, &laddr.rc_bdaddr);
554 bacpy(&req.dst, &raddr.rc_bdaddr);
555 req.channel = raddr.rc_channel;
556
557 dev = ioctl(nsk, RFCOMMCREATEDEV, &req);
558 if (dev < 0) {
559 perror("Can't create RFCOMM TTY");
560 close(sk);
561 return;
562 }
563
564 snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
565 while ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
566 if (errno == EACCES) {
567 perror("Can't open RFCOMM device");
568 goto release;
569 }
570
571 snprintf(devname, MAXPATHLEN - 1, "/dev/bluetooth/rfcomm/%d", dev);
572 if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
573 if (try--) {
574 snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
575 usleep(100 * 1000);
576 continue;
577 }
578 perror("Can't open RFCOMM device");
579 goto release;
580 }
581 }
582
583 if (rfcomm_raw_tty) {
584 tcflush(fd, TCIOFLUSH);
585
586 cfmakeraw(&ti);
587 tcsetattr(fd, TCSANOW, &ti);
588 }
589
590 close(sk);
591 close(nsk);
592
593 ba2str(&req.dst, dst);
594 printf("Connection from %s to %s\n", dst, devname);
595 printf("Press CTRL-C for hangup\n");
596
597 memset(&sa, 0, sizeof(sa));
598 sa.sa_flags = SA_NOCLDSTOP;
599 sa.sa_handler = SIG_IGN;
600 sigaction(SIGCHLD, &sa, NULL);
601 sigaction(SIGPIPE, &sa, NULL);
602
603 sa.sa_handler = sig_term;
604 sigaction(SIGTERM, &sa, NULL);
605 sigaction(SIGINT, &sa, NULL);
606
607 sa.sa_handler = sig_hup;
608 sigaction(SIGHUP, &sa, NULL);
609
610 sigfillset(&sigs);
611 sigdelset(&sigs, SIGCHLD);
612 sigdelset(&sigs, SIGPIPE);
613 sigdelset(&sigs, SIGTERM);
614 sigdelset(&sigs, SIGINT);
615 sigdelset(&sigs, SIGHUP);
616
617 p.fd = fd;
618 p.events = POLLERR | POLLHUP;
619
620 if (argc <= 2) {
621 while (!__io_canceled) {
622 p.revents = 0;
623 if (ppoll(&p, 1, NULL, &sigs) > 0)
624 break;
625 }
626 } else
627 run_cmdline(&p, &sigs, devname, argc - 2, argv + 2);
628
629 sa.sa_handler = NULL;
630 sigaction(SIGTERM, &sa, NULL);
631 sigaction(SIGINT, &sa, NULL);
632
633 printf("Disconnected\n");
634
635 close(fd);
636 return;
637
638 release:
639 memset(&req, 0, sizeof(req));
640 req.dev_id = dev;
641 req.flags = (1 << RFCOMM_HANGUP_NOW);
642 ioctl(ctl, RFCOMMRELEASEDEV, &req);
643
644 close(sk);
645 }
646
cmd_watch(int ctl,int dev,bdaddr_t * bdaddr,int argc,char ** argv)647 static void cmd_watch(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
648 {
649 while (!__io_canceled) {
650 cmd_listen(ctl, dev, bdaddr, argc, argv);
651 usleep(10000);
652 }
653 }
654
cmd_create(int ctl,int dev,bdaddr_t * bdaddr,int argc,char ** argv)655 static void cmd_create(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
656 {
657 if (strcmp(argv[0], "all") == 0)
658 create_all(ctl);
659 else
660 create_dev(ctl, dev, 0, bdaddr, argc, argv);
661 }
662
cmd_release(int ctl,int dev,bdaddr_t * bdaddr,int argc,char ** argv)663 static void cmd_release(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
664 {
665 if (strcmp(argv[0], "all") == 0)
666 release_all(ctl);
667 else
668 release_dev(ctl, dev, 0);
669 }
670
cmd_show(int ctl,int dev,bdaddr_t * bdaddr,int argc,char ** argv)671 static void cmd_show(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
672 {
673 if (strcmp(argv[0], "all") == 0)
674 print_dev_list(ctl, 0);
675 else {
676 struct rfcomm_dev_info di = { id: atoi(argv[0]) };
677 if (ioctl(ctl, RFCOMMGETDEVINFO, &di) < 0) {
678 perror("Get info failed");
679 exit(1);
680 }
681
682 print_dev_info(&di);
683 }
684 }
685
686 struct {
687 char *cmd;
688 char *alt;
689 void (*func)(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv);
690 char *opt;
691 char *doc;
692 } command[] = {
693 { "bind", "create", cmd_create, "<dev> <bdaddr> [channel]", "Bind device" },
694 { "release", "unbind", cmd_release, "<dev>", "Release device" },
695 { "show", "info", cmd_show, "<dev>", "Show device" },
696 { "connect", "conn", cmd_connect, "<dev> <bdaddr> [channel]", "Connect device" },
697 { "listen", "server", cmd_listen, "<dev> [channel [cmd]]", "Listen" },
698 { "watch", "watch", cmd_watch, "<dev> [channel [cmd]]", "Watch" },
699 { NULL, NULL, NULL, 0, 0 }
700 };
701
usage(void)702 static void usage(void)
703 {
704 int i;
705
706 printf("RFCOMM configuration utility ver %s\n", VERSION);
707
708 printf("Usage:\n"
709 "\trfcomm [options] <command> <dev>\n"
710 "\n");
711
712 printf("Options:\n"
713 "\t-i [hciX|bdaddr] Local HCI device or BD Address\n"
714 "\t-h, --help Display help\n"
715 "\t-r, --raw Switch TTY into raw mode\n"
716 "\t-A, --auth Enable authentication\n"
717 "\t-E, --encrypt Enable encryption\n"
718 "\t-S, --secure Secure connection\n"
719 "\t-M, --master Become the master of a piconet\n"
720 "\t-f, --config [file] Specify alternate config file\n"
721 "\t-a Show all devices (default)\n"
722 "\n");
723
724 printf("Commands:\n");
725 for (i = 0; command[i].cmd; i++)
726 printf("\t%-8s %-24s\t%s\n",
727 command[i].cmd,
728 command[i].opt ? command[i].opt : " ",
729 command[i].doc);
730 printf("\n");
731 }
732
733 static struct option main_options[] = {
734 { "help", 0, 0, 'h' },
735 { "device", 1, 0, 'i' },
736 { "config", 1, 0, 'f' },
737 { "raw", 0, 0, 'r' },
738 { "auth", 0, 0, 'A' },
739 { "encrypt", 0, 0, 'E' },
740 { "secure", 0, 0, 'S' },
741 { "master", 0, 0, 'M' },
742 { "linger", 1, 0, 'L' },
743 { 0, 0, 0, 0 }
744 };
745
main(int argc,char * argv[])746 int main(int argc, char *argv[])
747 {
748 bdaddr_t bdaddr;
749 int i, opt, ctl, dev_id, show_all = 0;
750
751 bacpy(&bdaddr, BDADDR_ANY);
752
753 while ((opt = getopt_long(argc, argv, "+i:f:rahAESML:", main_options, NULL)) != -1) {
754 switch(opt) {
755 case 'i':
756 if (strncmp(optarg, "hci", 3) == 0)
757 hci_devba(atoi(optarg + 3), &bdaddr);
758 else
759 str2ba(optarg, &bdaddr);
760 break;
761
762 case 'f':
763 rfcomm_config_file = strdup(optarg);
764 break;
765
766 case 'r':
767 rfcomm_raw_tty = 1;
768 break;
769
770 case 'a':
771 show_all = 1;
772 break;
773
774 case 'h':
775 usage();
776 exit(0);
777
778 case 'A':
779 auth = 1;
780 break;
781
782 case 'E':
783 encryption = 1;
784 break;
785
786 case 'S':
787 secure = 1;
788 break;
789
790 case 'M':
791 master = 1;
792 break;
793
794 case 'L':
795 linger = atoi(optarg);
796 break;
797
798 default:
799 exit(0);
800 }
801 }
802
803 argc -= optind;
804 argv += optind;
805 optind = 0;
806
807 if (argc < 2) {
808 if (argc != 0) {
809 usage();
810 exit(1);
811 } else
812 show_all = 1;
813 }
814
815 ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
816 if (ctl < 0) {
817 perror("Can't open RFCOMM control socket");
818 exit(1);
819 }
820
821 if (show_all) {
822 print_dev_list(ctl, 0);
823 close(ctl);
824 exit(0);
825 }
826
827 if (strncmp(argv[1], "/dev/rfcomm", 11) == 0)
828 dev_id = atoi(argv[1] + 11);
829 else if (strncmp(argv[1], "rfcomm", 6) == 0)
830 dev_id = atoi(argv[1] + 6);
831 else
832 dev_id = atoi(argv[1]);
833
834 for (i = 0; command[i].cmd; i++) {
835 if (strncmp(command[i].cmd, argv[0], 4) && strncmp(command[i].alt, argv[0], 4))
836 continue;
837 argc--;
838 argv++;
839 command[i].func(ctl, dev_id, &bdaddr, argc, argv);
840 close(ctl);
841 exit(0);
842 }
843
844 usage();
845
846 close(ctl);
847
848 return 0;
849 }
850