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