ciptool.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  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 <stdlib.h>
  17. #include <unistd.h>
  18. #include <string.h>
  19. #include <getopt.h>
  20. #include <signal.h>
  21. #include <poll.h>
  22. #include <sys/ioctl.h>
  23. #include <sys/socket.h>
  24. #include "lib/bluetooth.h"
  25. #include "lib/hci.h"
  26. #include "lib/hci_lib.h"
  27. #include "lib/l2cap.h"
  28. #include "lib/sdp.h"
  29. #include "lib/sdp_lib.h"
  30. #include "lib/cmtp.h"
  31. static volatile sig_atomic_t __io_canceled = 0;
  32. static void sig_hup(int sig)
  33. {
  34. return;
  35. }
  36. static void sig_term(int sig)
  37. {
  38. __io_canceled = 1;
  39. }
  40. static char *cmtp_state[] = {
  41. "unknown",
  42. "connected",
  43. "open",
  44. "bound",
  45. "listening",
  46. "connecting",
  47. "connecting",
  48. "config",
  49. "disconnecting",
  50. "closed"
  51. };
  52. static char *cmtp_flagstostr(uint32_t flags)
  53. {
  54. static char str[100] = "";
  55. strcat(str, "[");
  56. if (flags & (1 << CMTP_LOOPBACK))
  57. strcat(str, "loopback");
  58. strcat(str, "]");
  59. return str;
  60. }
  61. static int get_psm(bdaddr_t *src, bdaddr_t *dst, unsigned short *psm)
  62. {
  63. sdp_session_t *s;
  64. sdp_list_t *srch, *attrs, *rsp;
  65. uuid_t svclass;
  66. uint16_t attr;
  67. int err;
  68. if (!(s = sdp_connect(src, dst, 0)))
  69. return -1;
  70. sdp_uuid16_create(&svclass, CIP_SVCLASS_ID);
  71. srch = sdp_list_append(NULL, &svclass);
  72. attr = SDP_ATTR_PROTO_DESC_LIST;
  73. attrs = sdp_list_append(NULL, &attr);
  74. err = sdp_service_search_attr_req(s, srch, SDP_ATTR_REQ_INDIVIDUAL, attrs, &rsp);
  75. sdp_close(s);
  76. if (err)
  77. return 0;
  78. for (; rsp; rsp = rsp->next) {
  79. sdp_record_t *rec = (sdp_record_t *) rsp->data;
  80. sdp_list_t *protos;
  81. if (!sdp_get_access_protos(rec, &protos)) {
  82. unsigned short p = sdp_get_proto_port(protos, L2CAP_UUID);
  83. if (p > 0) {
  84. *psm = p;
  85. return 1;
  86. }
  87. }
  88. }
  89. return 0;
  90. }
  91. static int do_connect(int ctl, int dev_id, bdaddr_t *src, bdaddr_t *dst, unsigned short psm, uint32_t flags)
  92. {
  93. struct cmtp_connadd_req req;
  94. struct hci_dev_info di;
  95. struct sockaddr_l2 addr;
  96. struct l2cap_options opts;
  97. socklen_t size;
  98. int sk;
  99. hci_devinfo(dev_id, &di);
  100. if (!(di.link_policy & HCI_LP_RSWITCH)) {
  101. printf("Local device is not accepting role switch\n");
  102. }
  103. if ((sk = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_L2CAP)) < 0) {
  104. perror("Can't create L2CAP socket");
  105. exit(1);
  106. }
  107. memset(&addr, 0, sizeof(addr));
  108. addr.l2_family = AF_BLUETOOTH;
  109. bacpy(&addr.l2_bdaddr, src);
  110. if (bind(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  111. perror("Can't bind L2CAP socket");
  112. close(sk);
  113. exit(1);
  114. }
  115. memset(&opts, 0, sizeof(opts));
  116. size = sizeof(opts);
  117. if (getsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, &size) < 0) {
  118. perror("Can't get L2CAP options");
  119. close(sk);
  120. exit(1);
  121. }
  122. opts.imtu = CMTP_DEFAULT_MTU;
  123. opts.omtu = CMTP_DEFAULT_MTU;
  124. opts.flush_to = 0xffff;
  125. if (setsockopt(sk, SOL_L2CAP, L2CAP_OPTIONS, &opts, sizeof(opts)) < 0) {
  126. perror("Can't set L2CAP options");
  127. close(sk);
  128. exit(1);
  129. }
  130. memset(&addr, 0, sizeof(addr));
  131. addr.l2_family = AF_BLUETOOTH;
  132. bacpy(&addr.l2_bdaddr, dst);
  133. addr.l2_psm = htobs(psm);
  134. if (connect(sk, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
  135. perror("Can't connect L2CAP socket");
  136. close(sk);
  137. exit(1);
  138. }
  139. req.sock = sk;
  140. req.flags = flags;
  141. if (ioctl(ctl, CMTPCONNADD, &req) < 0) {
  142. perror("Can't create connection");
  143. exit(1);
  144. }
  145. return sk;
  146. }
  147. static void cmd_show(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
  148. {
  149. struct cmtp_connlist_req req;
  150. struct cmtp_conninfo ci[16];
  151. char addr[18];
  152. unsigned int i;
  153. req.cnum = 16;
  154. req.ci = ci;
  155. if (ioctl(ctl, CMTPGETCONNLIST, &req) < 0) {
  156. perror("Can't get connection list");
  157. exit(1);
  158. }
  159. for (i = 0; i < req.cnum; i++) {
  160. ba2str(&ci[i].bdaddr, addr);
  161. printf("%d %s %s %s\n", ci[i].num, addr,
  162. cmtp_state[ci[i].state],
  163. ci[i].flags ? cmtp_flagstostr(ci[i].flags) : "");
  164. }
  165. }
  166. static void cmd_search(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
  167. {
  168. inquiry_info *info = NULL;
  169. bdaddr_t src, dst;
  170. unsigned short psm;
  171. int i, dev_id, num_rsp, length, flags;
  172. char addr[18];
  173. uint8_t class[3];
  174. ba2str(bdaddr, addr);
  175. dev_id = hci_devid(addr);
  176. if (dev_id < 0) {
  177. dev_id = hci_get_route(NULL);
  178. hci_devba(dev_id, &src);
  179. } else
  180. bacpy(&src, bdaddr);
  181. length = 8; /* ~10 seconds */
  182. num_rsp = 0;
  183. flags = 0;
  184. printf("Searching ...\n");
  185. num_rsp = hci_inquiry(dev_id, length, num_rsp, NULL, &info, flags);
  186. for (i = 0; i < num_rsp; i++) {
  187. memcpy(class, (info+i)->dev_class, 3);
  188. if ((class[1] == 2) && ((class[0] / 4) == 5)) {
  189. bacpy(&dst, &(info+i)->bdaddr);
  190. ba2str(&dst, addr);
  191. printf("\tChecking service for %s\n", addr);
  192. if (!get_psm(&src, &dst, &psm))
  193. continue;
  194. bt_free(info);
  195. printf("\tConnecting to device %s\n", addr);
  196. do_connect(ctl, dev_id, &src, &dst, psm, 0);
  197. return;
  198. }
  199. }
  200. bt_free(info);
  201. fprintf(stderr, "\tNo devices in range or visible\n");
  202. exit(1);
  203. }
  204. static void cmd_create(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
  205. {
  206. bdaddr_t src, dst;
  207. unsigned short psm;
  208. int dev_id;
  209. char addr[18];
  210. if (argc < 2)
  211. return;
  212. str2ba(argv[1], &dst);
  213. ba2str(bdaddr, addr);
  214. dev_id = hci_devid(addr);
  215. if (dev_id < 0) {
  216. dev_id = hci_get_route(&dst);
  217. hci_devba(dev_id, &src);
  218. } else
  219. bacpy(&src, bdaddr);
  220. if (argc < 3) {
  221. if (!get_psm(&src, &dst, &psm))
  222. psm = 4099;
  223. } else
  224. psm = atoi(argv[2]);
  225. do_connect(ctl, dev_id, &src, &dst, psm, 0);
  226. }
  227. static void cmd_release(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
  228. {
  229. struct cmtp_conndel_req req;
  230. struct cmtp_connlist_req cl;
  231. struct cmtp_conninfo ci[16];
  232. if (argc < 2) {
  233. cl.cnum = 16;
  234. cl.ci = ci;
  235. if (ioctl(ctl, CMTPGETCONNLIST, &cl) < 0) {
  236. perror("Can't get connection list");
  237. exit(1);
  238. }
  239. if (cl.cnum == 0)
  240. return;
  241. if (cl.cnum != 1) {
  242. fprintf(stderr, "You have to specifiy the device address.\n");
  243. exit(1);
  244. }
  245. bacpy(&req.bdaddr, &ci[0].bdaddr);
  246. } else
  247. str2ba(argv[1], &req.bdaddr);
  248. if (ioctl(ctl, CMTPCONNDEL, &req) < 0) {
  249. perror("Can't release connection");
  250. exit(1);
  251. }
  252. }
  253. static void cmd_loopback(int ctl, bdaddr_t *bdaddr, int argc, char **argv)
  254. {
  255. struct cmtp_conndel_req req;
  256. struct sigaction sa;
  257. struct pollfd p;
  258. sigset_t sigs;
  259. bdaddr_t src, dst;
  260. unsigned short psm;
  261. int dev_id, sk;
  262. char addr[18];
  263. if (argc < 2)
  264. return;
  265. str2ba(argv[1], &dst);
  266. ba2str(bdaddr, addr);
  267. dev_id = hci_devid(addr);
  268. if (dev_id < 0) {
  269. dev_id = hci_get_route(&dst);
  270. hci_devba(dev_id, &src);
  271. } else
  272. bacpy(&src, bdaddr);
  273. ba2str(&dst, addr);
  274. printf("Connecting to %s in loopback mode\n", addr);
  275. if (argc < 3) {
  276. if (!get_psm(&src, &dst, &psm))
  277. psm = 4099;
  278. } else
  279. psm = atoi(argv[2]);
  280. sk = do_connect(ctl, dev_id, &src, &dst, psm, (1 << CMTP_LOOPBACK));
  281. printf("Press CTRL-C for hangup\n");
  282. memset(&sa, 0, sizeof(sa));
  283. sa.sa_flags = SA_NOCLDSTOP;
  284. sa.sa_handler = SIG_IGN;
  285. sigaction(SIGCHLD, &sa, NULL);
  286. sigaction(SIGPIPE, &sa, NULL);
  287. sa.sa_handler = sig_term;
  288. sigaction(SIGTERM, &sa, NULL);
  289. sigaction(SIGINT, &sa, NULL);
  290. sa.sa_handler = sig_hup;
  291. sigaction(SIGHUP, &sa, NULL);
  292. sigfillset(&sigs);
  293. sigdelset(&sigs, SIGCHLD);
  294. sigdelset(&sigs, SIGPIPE);
  295. sigdelset(&sigs, SIGTERM);
  296. sigdelset(&sigs, SIGINT);
  297. sigdelset(&sigs, SIGHUP);
  298. p.fd = sk;
  299. p.events = POLLERR | POLLHUP;
  300. while (!__io_canceled) {
  301. p.revents = 0;
  302. if (ppoll(&p, 1, NULL, &sigs) > 0)
  303. break;
  304. }
  305. bacpy(&req.bdaddr, &dst);
  306. ioctl(ctl, CMTPCONNDEL, &req);
  307. }
  308. static struct {
  309. char *cmd;
  310. char *alt;
  311. void (*func)(int ctl, bdaddr_t *bdaddr, int argc, char **argv);
  312. char *opt;
  313. char *doc;
  314. } command[] = {
  315. { "show", "list", cmd_show, 0, "Show remote connections" },
  316. { "search", "scan", cmd_search, 0, "Search for a remote device" },
  317. { "connect", "create", cmd_create, "<bdaddr>", "Connect a remote device" },
  318. { "release", "disconnect", cmd_release, "[bdaddr]", "Disconnect the remote device" },
  319. { "loopback", "test", cmd_loopback, "<bdaddr>", "Loopback test of a device" },
  320. { NULL, NULL, NULL, 0, 0 }
  321. };
  322. static void usage(void)
  323. {
  324. int i;
  325. printf("ciptool - Bluetooth Common ISDN Access Profile (CIP)\n\n");
  326. printf("Usage:\n"
  327. "\tciptool [options] [command]\n"
  328. "\n");
  329. printf("Options:\n"
  330. "\t-i [hciX|bdaddr] Local HCI device or BD Address\n"
  331. "\t-h, --help Display help\n"
  332. "\n");
  333. printf("Commands:\n");
  334. for (i = 0; command[i].cmd; i++)
  335. printf("\t%-8s %-10s\t%s\n", command[i].cmd,
  336. command[i].opt ? command[i].opt : " ",
  337. command[i].doc);
  338. printf("\n");
  339. }
  340. static struct option main_options[] = {
  341. { "help", 0, 0, 'h' },
  342. { "device", 1, 0, 'i' },
  343. { 0, 0, 0, 0 }
  344. };
  345. int main(int argc, char *argv[])
  346. {
  347. bdaddr_t bdaddr;
  348. int i, opt, ctl;
  349. bacpy(&bdaddr, BDADDR_ANY);
  350. while ((opt = getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {
  351. switch(opt) {
  352. case 'i':
  353. if (!strncmp(optarg, "hci", 3))
  354. hci_devba(atoi(optarg + 3), &bdaddr);
  355. else
  356. str2ba(optarg, &bdaddr);
  357. break;
  358. case 'h':
  359. usage();
  360. exit(0);
  361. default:
  362. exit(0);
  363. }
  364. }
  365. argc -= optind;
  366. argv += optind;
  367. optind = 0;
  368. if (argc < 1) {
  369. usage();
  370. return 0;
  371. }
  372. if ((ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_CMTP)) < 0 ) {
  373. perror("Can't open CMTP control socket");
  374. exit(1);
  375. }
  376. for (i = 0; command[i].cmd; i++) {
  377. if (strncmp(command[i].cmd, argv[0], 4) && strncmp(command[i].alt, argv[0], 4))
  378. continue;
  379. command[i].func(ctl, &bdaddr, argc, argv);
  380. close(ctl);
  381. exit(0);
  382. }
  383. usage();
  384. close(ctl);
  385. return 0;
  386. }