• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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