Home | History | Annotate | Download | only in tools
      1 /*
      2  *
      3  *  BlueZ - Bluetooth protocol stack for Linux
      4  *
      5  *  Copyright (C) 2002-2010  Marcel Holtmann <marcel (at) 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 
     54 static void sig_hup(int sig)
     55 {
     56 	return;
     57 }
     58 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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