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
52static volatile sig_atomic_t __io_canceled = 0;
53
54static void sig_hup(int sig)
55{
56	return;
57}
58
59static void sig_term(int sig)
60{
61	__io_canceled = 1;
62}
63
64static 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
77static 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
91static 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
131static 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
201static 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
224static 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
272static 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
301static 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
334static 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
404static 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
419static 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
442static struct option main_options[] = {
443	{ "help",	0, 0, 'h' },
444	{ "device",	1, 0, 'i' },
445	{ 0, 0, 0, 0 }
446};
447
448int 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