rfcomm.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. *
  4. * BlueZ - Bluetooth protocol stack for Linux
  5. *
  6. * Copyright (C) 2002-2010 Marcel Holtmann <marcel@holtmann.org>
  7. *
  8. *
  9. */
  10. #ifdef HAVE_CONFIG_H
  11. #include <config.h>
  12. #endif
  13. #define _GNU_SOURCE
  14. #include <stdio.h>
  15. #include <errno.h>
  16. #include <fcntl.h>
  17. #include <unistd.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <getopt.h>
  21. #include <signal.h>
  22. #include <termios.h>
  23. #include <poll.h>
  24. #include <sys/param.h>
  25. #include <sys/ioctl.h>
  26. #include <sys/socket.h>
  27. #include <sys/wait.h>
  28. #include "lib/bluetooth.h"
  29. #include "lib/hci.h"
  30. #include "lib/hci_lib.h"
  31. #include "lib/rfcomm.h"
  32. static int rfcomm_raw_tty = 0;
  33. static int auth = 0;
  34. static int encryption = 0;
  35. static int secure = 0;
  36. static int central = 0;
  37. static int linger = 0;
  38. static char *rfcomm_state[] = {
  39. "unknown",
  40. "connected",
  41. "clean",
  42. "bound",
  43. "listening",
  44. "connecting",
  45. "connecting",
  46. "config",
  47. "disconnecting",
  48. "closed"
  49. };
  50. static volatile sig_atomic_t __io_canceled = 0;
  51. static void sig_hup(int sig)
  52. {
  53. return;
  54. }
  55. static void sig_term(int sig)
  56. {
  57. __io_canceled = 1;
  58. }
  59. static char *rfcomm_flagstostr(uint32_t flags)
  60. {
  61. static char str[100];
  62. str[0] = 0;
  63. strcat(str, "[");
  64. if (flags & (1 << RFCOMM_REUSE_DLC))
  65. strcat(str, "reuse-dlc ");
  66. if (flags & (1 << RFCOMM_RELEASE_ONHUP))
  67. strcat(str, "release-on-hup ");
  68. if (flags & (1 << RFCOMM_TTY_ATTACHED))
  69. strcat(str, "tty-attached");
  70. strcat(str, "]");
  71. return str;
  72. }
  73. static void print_dev_info(struct rfcomm_dev_info *di)
  74. {
  75. char src[18], dst[18], addr[40];
  76. ba2str(&di->src, src); ba2str(&di->dst, dst);
  77. if (bacmp(&di->src, BDADDR_ANY) == 0)
  78. sprintf(addr, "%s", dst);
  79. else
  80. sprintf(addr, "%s -> %s", src, dst);
  81. printf("rfcomm%d: %s channel %d %s %s\n",
  82. di->id, addr, di->channel,
  83. rfcomm_state[di->state],
  84. di->flags ? rfcomm_flagstostr(di->flags) : "");
  85. }
  86. static void print_dev_list(int ctl, int flags)
  87. {
  88. struct rfcomm_dev_list_req *dl;
  89. struct rfcomm_dev_info *di;
  90. int i;
  91. dl = malloc(sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));
  92. if (!dl) {
  93. perror("Can't allocate memory");
  94. exit(1);
  95. }
  96. dl->dev_num = RFCOMM_MAX_DEV;
  97. di = dl->dev_info;
  98. if (ioctl(ctl, RFCOMMGETDEVLIST, (void *) dl) < 0) {
  99. perror("Can't get device list");
  100. free(dl);
  101. exit(1);
  102. }
  103. for (i = 0; i < dl->dev_num; i++)
  104. print_dev_info(di + i);
  105. free(dl);
  106. }
  107. static int create_dev(int ctl, int dev, uint32_t flags, bdaddr_t *bdaddr, int argc, char **argv)
  108. {
  109. struct rfcomm_dev_req req;
  110. int err;
  111. memset(&req, 0, sizeof(req));
  112. req.dev_id = dev;
  113. req.flags = flags;
  114. bacpy(&req.src, bdaddr);
  115. if (argc < 2) {
  116. fprintf(stderr, "Missing dev parameter");
  117. return -EINVAL;
  118. }
  119. str2ba(argv[1], &req.dst);
  120. if (argc > 2)
  121. req.channel = atoi(argv[2]);
  122. else
  123. req.channel = 1;
  124. err = ioctl(ctl, RFCOMMCREATEDEV, &req);
  125. if (err == -1) {
  126. err = -errno;
  127. if (err == -EOPNOTSUPP)
  128. fprintf(stderr, "RFCOMM TTY support not available\n");
  129. else
  130. perror("Can't create device");
  131. }
  132. return err;
  133. }
  134. static int release_dev(int ctl, int dev, uint32_t flags)
  135. {
  136. struct rfcomm_dev_req req;
  137. int err;
  138. memset(&req, 0, sizeof(req));
  139. req.dev_id = dev;
  140. err = ioctl(ctl, RFCOMMRELEASEDEV, &req);
  141. if (err < 0)
  142. perror("Can't release device");
  143. return err;
  144. }
  145. static int release_all(int ctl)
  146. {
  147. struct rfcomm_dev_list_req *dl;
  148. struct rfcomm_dev_info *di;
  149. int i;
  150. dl = malloc(sizeof(*dl) + RFCOMM_MAX_DEV * sizeof(*di));
  151. if (!dl) {
  152. perror("Can't allocate memory");
  153. exit(1);
  154. }
  155. dl->dev_num = RFCOMM_MAX_DEV;
  156. di = dl->dev_info;
  157. if (ioctl(ctl, RFCOMMGETDEVLIST, (void *) dl) < 0) {
  158. perror("Can't get device list");
  159. free(dl);
  160. exit(1);
  161. }
  162. for (i = 0; i < dl->dev_num; i++)
  163. release_dev(ctl, (di + i)->id, 0);
  164. free(dl);
  165. return 0;
  166. }
  167. static void run_cmdline(struct pollfd *p, sigset_t *sigs, char *devname,
  168. int argc, char **argv)
  169. {
  170. int i;
  171. pid_t pid;
  172. char **cmdargv;
  173. cmdargv = malloc((argc + 1) * sizeof(char *));
  174. if (!cmdargv)
  175. return;
  176. for (i = 0; i < argc; i++)
  177. cmdargv[i] = (strcmp(argv[i], "{}") == 0) ? devname : argv[i];
  178. cmdargv[i] = NULL;
  179. pid = fork();
  180. switch (pid) {
  181. case 0:
  182. i = execvp(cmdargv[0], cmdargv);
  183. fprintf(stderr, "Couldn't execute command %s (errno=%d:%s)\n",
  184. cmdargv[0], errno, strerror(errno));
  185. break;
  186. case -1:
  187. fprintf(stderr, "Couldn't fork to execute command %s\n",
  188. cmdargv[0]);
  189. break;
  190. default:
  191. while (1) {
  192. int status;
  193. pid_t child;
  194. struct timespec ts;
  195. child = waitpid(-1, &status, WNOHANG);
  196. if (child == pid || (child < 0 && errno != EAGAIN))
  197. break;
  198. p->revents = 0;
  199. ts.tv_sec = 0;
  200. ts.tv_nsec = 200;
  201. if (ppoll(p, 1, &ts, sigs) || __io_canceled) {
  202. kill(pid, SIGTERM);
  203. waitpid(pid, &status, 0);
  204. break;
  205. }
  206. }
  207. break;
  208. }
  209. free(cmdargv);
  210. }
  211. static void cmd_connect(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
  212. {
  213. struct sockaddr_rc laddr, raddr;
  214. struct rfcomm_dev_req req;
  215. struct termios ti;
  216. struct sigaction sa;
  217. struct pollfd p;
  218. sigset_t sigs;
  219. socklen_t alen;
  220. char dst[18], devname[MAXPATHLEN];
  221. int sk, fd, try = 30;
  222. laddr.rc_family = AF_BLUETOOTH;
  223. bacpy(&laddr.rc_bdaddr, bdaddr);
  224. laddr.rc_channel = 0;
  225. if (argc < 2) {
  226. fprintf(stderr, "Missing dev parameter");
  227. return;
  228. }
  229. raddr.rc_family = AF_BLUETOOTH;
  230. str2ba(argv[1], &raddr.rc_bdaddr);
  231. if (argc > 2)
  232. raddr.rc_channel = atoi(argv[2]);
  233. else
  234. raddr.rc_channel = 1;
  235. sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
  236. if (sk < 0) {
  237. perror("Can't create RFCOMM socket");
  238. return;
  239. }
  240. if (linger) {
  241. struct linger l = { .l_onoff = 1, .l_linger = linger };
  242. if (setsockopt(sk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
  243. perror("Can't set linger option");
  244. return;
  245. }
  246. }
  247. if (bind(sk, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) {
  248. perror("Can't bind RFCOMM socket");
  249. close(sk);
  250. return;
  251. }
  252. if (connect(sk, (struct sockaddr *) &raddr, sizeof(raddr)) < 0) {
  253. perror("Can't connect RFCOMM socket");
  254. close(sk);
  255. return;
  256. }
  257. alen = sizeof(laddr);
  258. if (getsockname(sk, (struct sockaddr *)&laddr, &alen) < 0) {
  259. perror("Can't get RFCOMM socket name");
  260. close(sk);
  261. return;
  262. }
  263. memset(&req, 0, sizeof(req));
  264. req.dev_id = dev;
  265. req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
  266. bacpy(&req.src, &laddr.rc_bdaddr);
  267. bacpy(&req.dst, &raddr.rc_bdaddr);
  268. req.channel = raddr.rc_channel;
  269. dev = ioctl(sk, RFCOMMCREATEDEV, &req);
  270. if (dev < 0) {
  271. perror("Can't create RFCOMM TTY");
  272. close(sk);
  273. return;
  274. }
  275. snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
  276. while ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
  277. if (errno == EACCES) {
  278. perror("Can't open RFCOMM device");
  279. goto release;
  280. }
  281. snprintf(devname, MAXPATHLEN - 1, "/dev/bluetooth/rfcomm/%d", dev);
  282. if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
  283. if (try--) {
  284. snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
  285. usleep(100 * 1000);
  286. continue;
  287. }
  288. perror("Can't open RFCOMM device");
  289. goto release;
  290. }
  291. }
  292. if (rfcomm_raw_tty) {
  293. tcflush(fd, TCIOFLUSH);
  294. cfmakeraw(&ti);
  295. tcsetattr(fd, TCSANOW, &ti);
  296. }
  297. close(sk);
  298. ba2str(&req.dst, dst);
  299. printf("Connected %s to %s on channel %d\n", devname, dst, req.channel);
  300. printf("Press CTRL-C for hangup\n");
  301. memset(&sa, 0, sizeof(sa));
  302. sa.sa_flags = SA_NOCLDSTOP;
  303. sa.sa_handler = SIG_IGN;
  304. sigaction(SIGCHLD, &sa, NULL);
  305. sigaction(SIGPIPE, &sa, NULL);
  306. sa.sa_handler = sig_term;
  307. sigaction(SIGTERM, &sa, NULL);
  308. sigaction(SIGINT, &sa, NULL);
  309. sa.sa_handler = sig_hup;
  310. sigaction(SIGHUP, &sa, NULL);
  311. sigfillset(&sigs);
  312. sigdelset(&sigs, SIGCHLD);
  313. sigdelset(&sigs, SIGPIPE);
  314. sigdelset(&sigs, SIGTERM);
  315. sigdelset(&sigs, SIGINT);
  316. sigdelset(&sigs, SIGHUP);
  317. p.fd = fd;
  318. p.events = POLLERR | POLLHUP;
  319. while (!__io_canceled) {
  320. p.revents = 0;
  321. if (ppoll(&p, 1, NULL, &sigs) > 0)
  322. break;
  323. }
  324. printf("Disconnected\n");
  325. close(fd);
  326. return;
  327. release:
  328. memset(&req, 0, sizeof(req));
  329. req.dev_id = dev;
  330. req.flags = (1 << RFCOMM_HANGUP_NOW);
  331. ioctl(ctl, RFCOMMRELEASEDEV, &req);
  332. close(sk);
  333. }
  334. static void cmd_listen(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
  335. {
  336. struct sockaddr_rc laddr, raddr;
  337. struct rfcomm_dev_req req;
  338. struct termios ti;
  339. struct sigaction sa;
  340. struct pollfd p;
  341. sigset_t sigs;
  342. socklen_t alen;
  343. char dst[18], devname[MAXPATHLEN];
  344. int sk, nsk, fd, lm, try = 30;
  345. laddr.rc_family = AF_BLUETOOTH;
  346. bacpy(&laddr.rc_bdaddr, bdaddr);
  347. laddr.rc_channel = (argc < 2) ? 1 : atoi(argv[1]);
  348. sk = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);
  349. if (sk < 0) {
  350. perror("Can't create RFCOMM socket");
  351. return;
  352. }
  353. lm = 0;
  354. if (central)
  355. lm |= RFCOMM_LM_MASTER;
  356. if (auth)
  357. lm |= RFCOMM_LM_AUTH;
  358. if (encryption)
  359. lm |= RFCOMM_LM_ENCRYPT;
  360. if (secure)
  361. lm |= RFCOMM_LM_SECURE;
  362. if (lm && setsockopt(sk, SOL_RFCOMM, RFCOMM_LM, &lm, sizeof(lm)) < 0) {
  363. perror("Can't set RFCOMM link mode");
  364. close(sk);
  365. return;
  366. }
  367. if (bind(sk, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
  368. perror("Can't bind RFCOMM socket");
  369. close(sk);
  370. return;
  371. }
  372. printf("Waiting for connection on channel %d\n", laddr.rc_channel);
  373. listen(sk, 10);
  374. alen = sizeof(raddr);
  375. nsk = accept(sk, (struct sockaddr *) &raddr, &alen);
  376. alen = sizeof(laddr);
  377. if (getsockname(nsk, (struct sockaddr *)&laddr, &alen) < 0) {
  378. perror("Can't get RFCOMM socket name");
  379. close(nsk);
  380. return;
  381. }
  382. if (linger) {
  383. struct linger l = { .l_onoff = 1, .l_linger = linger };
  384. if (setsockopt(nsk, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) < 0) {
  385. perror("Can't set linger option");
  386. close(nsk);
  387. return;
  388. }
  389. }
  390. memset(&req, 0, sizeof(req));
  391. req.dev_id = dev;
  392. req.flags = (1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP);
  393. bacpy(&req.src, &laddr.rc_bdaddr);
  394. bacpy(&req.dst, &raddr.rc_bdaddr);
  395. req.channel = raddr.rc_channel;
  396. dev = ioctl(nsk, RFCOMMCREATEDEV, &req);
  397. if (dev < 0) {
  398. perror("Can't create RFCOMM TTY");
  399. close(sk);
  400. return;
  401. }
  402. snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
  403. while ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
  404. if (errno == EACCES) {
  405. perror("Can't open RFCOMM device");
  406. goto release;
  407. }
  408. snprintf(devname, MAXPATHLEN - 1, "/dev/bluetooth/rfcomm/%d", dev);
  409. if ((fd = open(devname, O_RDONLY | O_NOCTTY)) < 0) {
  410. if (try--) {
  411. snprintf(devname, MAXPATHLEN - 1, "/dev/rfcomm%d", dev);
  412. usleep(100 * 1000);
  413. continue;
  414. }
  415. perror("Can't open RFCOMM device");
  416. goto release;
  417. }
  418. }
  419. if (rfcomm_raw_tty) {
  420. tcflush(fd, TCIOFLUSH);
  421. cfmakeraw(&ti);
  422. tcsetattr(fd, TCSANOW, &ti);
  423. }
  424. close(sk);
  425. close(nsk);
  426. ba2str(&req.dst, dst);
  427. printf("Connection from %s to %s\n", dst, devname);
  428. printf("Press CTRL-C for hangup\n");
  429. memset(&sa, 0, sizeof(sa));
  430. sa.sa_flags = SA_NOCLDSTOP;
  431. sa.sa_handler = SIG_IGN;
  432. sigaction(SIGCHLD, &sa, NULL);
  433. sigaction(SIGPIPE, &sa, NULL);
  434. sa.sa_handler = sig_term;
  435. sigaction(SIGTERM, &sa, NULL);
  436. sigaction(SIGINT, &sa, NULL);
  437. sa.sa_handler = sig_hup;
  438. sigaction(SIGHUP, &sa, NULL);
  439. sigfillset(&sigs);
  440. sigdelset(&sigs, SIGCHLD);
  441. sigdelset(&sigs, SIGPIPE);
  442. sigdelset(&sigs, SIGTERM);
  443. sigdelset(&sigs, SIGINT);
  444. sigdelset(&sigs, SIGHUP);
  445. p.fd = fd;
  446. p.events = POLLERR | POLLHUP;
  447. if (argc <= 2) {
  448. while (!__io_canceled) {
  449. p.revents = 0;
  450. if (ppoll(&p, 1, NULL, &sigs) > 0)
  451. break;
  452. }
  453. } else
  454. run_cmdline(&p, &sigs, devname, argc - 2, argv + 2);
  455. sa.sa_handler = NULL;
  456. sigaction(SIGTERM, &sa, NULL);
  457. sigaction(SIGINT, &sa, NULL);
  458. printf("Disconnected\n");
  459. close(fd);
  460. return;
  461. release:
  462. memset(&req, 0, sizeof(req));
  463. req.dev_id = dev;
  464. req.flags = (1 << RFCOMM_HANGUP_NOW);
  465. ioctl(ctl, RFCOMMRELEASEDEV, &req);
  466. close(sk);
  467. }
  468. static void cmd_watch(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
  469. {
  470. while (!__io_canceled) {
  471. cmd_listen(ctl, dev, bdaddr, argc, argv);
  472. usleep(10000);
  473. }
  474. }
  475. static void cmd_create(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
  476. {
  477. create_dev(ctl, dev, 0, bdaddr, argc, argv);
  478. }
  479. static void cmd_release(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
  480. {
  481. if (strcmp(argv[0], "all") == 0)
  482. release_all(ctl);
  483. else
  484. release_dev(ctl, dev, 0);
  485. }
  486. static void cmd_show(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv)
  487. {
  488. if (strcmp(argv[0], "all") == 0)
  489. print_dev_list(ctl, 0);
  490. else {
  491. struct rfcomm_dev_info di = { .id = atoi(argv[0]) };
  492. if (ioctl(ctl, RFCOMMGETDEVINFO, &di) < 0) {
  493. perror("Get info failed");
  494. exit(1);
  495. }
  496. print_dev_info(&di);
  497. }
  498. }
  499. struct {
  500. char *cmd;
  501. char *alt;
  502. void (*func)(int ctl, int dev, bdaddr_t *bdaddr, int argc, char **argv);
  503. char *opt;
  504. char *doc;
  505. } command[] = {
  506. { "bind", "create", cmd_create, "<dev> <bdaddr> [channel]", "Bind device" },
  507. { "release", "unbind", cmd_release, "<dev>", "Release device" },
  508. { "show", "info", cmd_show, "<dev>", "Show device" },
  509. { "connect", "conn", cmd_connect, "<dev> <bdaddr> [channel]", "Connect device" },
  510. { "listen", "server", cmd_listen, "<dev> [channel [cmd]]", "Listen" },
  511. { "watch", "watch", cmd_watch, "<dev> [channel [cmd]]", "Watch" },
  512. { NULL, NULL, NULL, 0, 0 }
  513. };
  514. static void usage(void)
  515. {
  516. int i;
  517. printf("RFCOMM configuration utility ver %s\n", VERSION);
  518. printf("Usage:\n"
  519. "\trfcomm [options] <command> <dev>\n"
  520. "\n");
  521. printf("Options:\n"
  522. "\t-i, --device [hciX|bdaddr] Local HCI device or BD Address\n"
  523. "\t-h, --help Display help\n"
  524. "\t-r, --raw Switch TTY into raw mode\n"
  525. "\t-A, --auth Enable authentication\n"
  526. "\t-E, --encrypt Enable encryption\n"
  527. "\t-S, --secure Secure connection\n"
  528. "\t-C, --central Become the central of a piconet\n"
  529. "\t-L, --linger [seconds] Set linger timeout\n"
  530. "\t-a Show all devices (default)\n"
  531. "\n");
  532. printf("Commands:\n");
  533. for (i = 0; command[i].cmd; i++)
  534. printf("\t%-8s %-24s\t%s\n",
  535. command[i].cmd,
  536. command[i].opt ? command[i].opt : " ",
  537. command[i].doc);
  538. printf("\n");
  539. }
  540. static struct option main_options[] = {
  541. { "help", 0, 0, 'h' },
  542. { "device", 1, 0, 'i' },
  543. { "config", 1, 0, 'f' },
  544. { "raw", 0, 0, 'r' },
  545. { "auth", 0, 0, 'A' },
  546. { "encrypt", 0, 0, 'E' },
  547. { "secure", 0, 0, 'S' },
  548. { "master", 0, 0, 'M' }, /* Deprecated. Kept for compatibility. */
  549. { "central", 0, 0, 'C' },
  550. { "linger", 1, 0, 'L' },
  551. { 0, 0, 0, 0 }
  552. };
  553. int main(int argc, char *argv[])
  554. {
  555. bdaddr_t bdaddr;
  556. int i, opt, ctl, dev_id, show_all = 0;
  557. bacpy(&bdaddr, BDADDR_ANY);
  558. while ((opt = getopt_long(argc, argv, "+i:rahAESMCL:", main_options,
  559. NULL)) != -1) {
  560. switch(opt) {
  561. case 'i':
  562. if (strncmp(optarg, "hci", 3) == 0)
  563. hci_devba(atoi(optarg + 3), &bdaddr);
  564. else
  565. str2ba(optarg, &bdaddr);
  566. break;
  567. case 'r':
  568. rfcomm_raw_tty = 1;
  569. break;
  570. case 'a':
  571. show_all = 1;
  572. break;
  573. case 'h':
  574. usage();
  575. exit(0);
  576. case 'A':
  577. auth = 1;
  578. break;
  579. case 'E':
  580. encryption = 1;
  581. break;
  582. case 'S':
  583. secure = 1;
  584. break;
  585. case 'M': /* Deprecated. Kept for compatibility. */
  586. case 'C':
  587. central = 1;
  588. break;
  589. case 'L':
  590. linger = atoi(optarg);
  591. break;
  592. default:
  593. exit(0);
  594. }
  595. }
  596. argc -= optind;
  597. argv += optind;
  598. optind = 0;
  599. if (argc < 2) {
  600. if (argc != 0) {
  601. usage();
  602. exit(1);
  603. } else
  604. show_all = 1;
  605. }
  606. ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_RFCOMM);
  607. if (ctl < 0) {
  608. perror("Can't open RFCOMM control socket");
  609. exit(1);
  610. }
  611. if (show_all) {
  612. print_dev_list(ctl, 0);
  613. close(ctl);
  614. exit(0);
  615. }
  616. if (strncmp(argv[1], "/dev/rfcomm", 11) == 0)
  617. dev_id = atoi(argv[1] + 11);
  618. else if (strncmp(argv[1], "rfcomm", 6) == 0)
  619. dev_id = atoi(argv[1] + 6);
  620. else
  621. dev_id = atoi(argv[1]);
  622. for (i = 0; command[i].cmd; i++) {
  623. if (strncmp(command[i].cmd, argv[0], 4) && strncmp(command[i].alt, argv[0], 4))
  624. continue;
  625. argc--;
  626. argv++;
  627. command[i].func(ctl, dev_id, &bdaddr, argc, argv);
  628. close(ctl);
  629. exit(0);
  630. }
  631. usage();
  632. close(ctl);
  633. return 0;
  634. }