bpasniff.c revision 9594f14663b99363183735347aa5ab7bccf330b3
1/*
2 *
3 *  Bluetooth packet analyzer - BPA sniffer
4 *
5 *  Copyright (C) 2004-2005  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21 *
22 *
23 *  $Id$
24 */
25
26#ifdef HAVE_CONFIG_H
27#include <config.h>
28#endif
29
30#include <stdio.h>
31#include <errno.h>
32#include <ctype.h>
33#include <unistd.h>
34#include <stdlib.h>
35#include <malloc.h>
36#include <getopt.h>
37#include <signal.h>
38#include <sys/ioctl.h>
39#include <sys/socket.h>
40
41#include <bluetooth/bluetooth.h>
42#include <bluetooth/hci.h>
43#include <bluetooth/hci_lib.h>
44
45#include <netinet/in.h>
46
47static volatile sig_atomic_t __io_canceled = 0;
48
49static void sig_hup(int sig)
50{
51}
52
53static void sig_term(int sig)
54{
55	__io_canceled = 1;
56}
57
58static int read_revision(int dd, char *revision, int size)
59{
60	struct hci_request rq;
61	unsigned char req[] = { 0x07 };
62	unsigned char buf[46];
63
64	memset(&rq, 0, sizeof(rq));
65	rq.ogf    = OGF_VENDOR_CMD;
66	rq.ocf    = 0x000e;
67	rq.cparam = req;
68	rq.clen   = sizeof(req);
69	rq.rparam = &buf;
70	rq.rlen   = sizeof(buf);
71
72	if (hci_send_req(dd, &rq, 1000) < 0)
73		return -1;
74
75	if (buf[0] > 0) {
76		errno = EIO;
77		return -1;
78	}
79
80	if (revision)
81		strncpy(revision, buf + 1, size);
82
83	return 0;
84}
85
86static int enable_sniffer(int dd, uint8_t enable)
87{
88	struct hci_request rq;
89	unsigned char req[] = { 0x00, enable };
90	unsigned char buf[1];
91
92	memset(&rq, 0, sizeof(rq));
93	rq.ogf    = OGF_VENDOR_CMD;
94	rq.ocf    = 0x000e;
95	rq.cparam = req;
96	rq.clen   = sizeof(req);
97	rq.rparam = &buf;
98	rq.rlen   = sizeof(buf);
99
100	if (hci_send_req(dd, &rq, 1000) < 0)
101		return -1;
102
103	if (buf[0] > 0) {
104		errno = EIO;
105		return -1;
106	}
107
108	return 0;
109}
110
111static int enable_sync(int dd, uint8_t enable, bdaddr_t *bdaddr)
112{
113	struct hci_request rq;
114	unsigned char req[] = { 0x01, enable,
115				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116				0x00, 0xfa, 0x00 };
117
118	memcpy(req + 2, bdaddr, 6);
119
120	memset(&rq, 0, sizeof(rq));
121	rq.ogf    = OGF_VENDOR_CMD;
122	rq.ocf    = 0x000e;
123	rq.cparam = req;
124	rq.clen   = sizeof(req);
125
126	hci_send_req(dd, &rq, 1000);
127
128	return 0;
129}
130
131static void dump(unsigned char *buf, int count)
132{
133	int i, n = 0, size;
134
135	while (count > 0) {
136		printf("%04x: ", n);
137
138		size = count > 16 ? 16 : count;
139
140		for (i = 0; i < size; i++)
141			printf("%02x%s", buf[i], (i + 1) % 8 ? " " : "  ");
142		for (i = size; i < 16; i++)
143			printf("  %s", (i + 1) % 8 ? " " : "  ");
144
145		for (i = 0; i < size; i++)
146			printf("%1c", isprint(buf[i]) ? buf[i] : '.');
147		printf("\n");
148
149		buf   += size;
150		count -= size;
151		n     += size;
152	}
153}
154
155static void process_frames(int dev)
156{
157	struct sigaction sa;
158	struct hci_filter flt;
159	unsigned char *buf;
160	int dd, size = 2048;
161
162	buf = malloc(size);
163	if (!buf) {
164		fprintf(stderr, "Can't allocate buffer for hci%d: %s (%d)\n",
165						dev, strerror(errno), errno);
166		return;
167	}
168
169	dd = hci_open_dev(dev);
170	if (dd < 0) {
171		fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
172						dev, strerror(errno), errno);
173		free(buf);
174		return;
175	}
176
177	hci_filter_clear(&flt);
178	hci_filter_set_ptype(HCI_VENDOR_PKT, &flt);
179	hci_filter_set_ptype(HCI_EVENT_PKT, &flt);
180	hci_filter_set_event(EVT_VENDOR, &flt);
181
182	if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
183		fprintf(stderr, "Can't set filter for hci%d: %s (%d)\n",
184						dev, strerror(errno), errno);
185		hci_close_dev(dd);
186		free(buf);
187		return;
188	}
189
190	memset(&sa, 0, sizeof(sa));
191	sa.sa_flags   = SA_NOCLDSTOP;
192	sa.sa_handler = SIG_IGN;
193	sigaction(SIGCHLD, &sa, NULL);
194	sigaction(SIGPIPE, &sa, NULL);
195
196	sa.sa_handler = sig_term;
197	sigaction(SIGTERM, &sa, NULL);
198	sigaction(SIGINT,  &sa, NULL);
199
200	sa.sa_handler = sig_hup;
201	sigaction(SIGHUP, &sa, NULL);
202
203	while (!__io_canceled) {
204		int len;
205
206		len = read(dd, buf, size);
207		if (len < 0)
208			break;
209		if (len < 2)
210			continue;
211
212		if (buf[0] == 0x04 && buf[1] == 0xff) {
213			if (buf[3] == 0x02) {
214				switch (buf[4]) {
215				case 0x00:
216					printf("Waiting for synchronization...\n");
217					break;
218				case 0x08:
219					printf("Synchronization lost\n");
220					__io_canceled = 1;
221					break;
222				default:
223					printf("Unknown event 0x%02x\n", buf[4]);
224					break;
225				}
226			}
227		}
228
229		if (buf[0] != 0xff)
230			continue;
231
232		dump(buf + 1, len - 1);
233	}
234
235	hci_close_dev(dd);
236
237	free(buf);
238}
239
240static void usage(void)
241{
242	printf("bpasniff - Utility for the BPA 100/105 sniffers\n\n");
243	printf("Usage:\n"
244		"\tcsrsniff [-i <dev>] <bdaddr>\n");
245}
246
247static struct option main_options[] = {
248	{ "help",	0, 0, 'h' },
249	{ "device",	1, 0, 'i' },
250	{ 0, 0, 0, 0}
251};
252
253int main(int argc, char *argv[])
254{
255	struct hci_dev_info di;
256	struct hci_version ver;
257	char rev[46];
258	bdaddr_t bdaddr;
259	int dd, opt, dev = 0;
260
261	bacpy(&bdaddr, BDADDR_ANY);
262
263	while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {
264		switch (opt) {
265		case 'i':
266			dev = hci_devid(optarg);
267			if (dev < 0) {
268				perror("Invalid device");
269				exit(1);
270			}
271			break;
272
273		case 'h':
274		default:
275			usage();
276			exit(0);
277		}
278	}
279
280	argc -= optind;
281	argv += optind;
282	optind = 0;
283
284	argc -= optind;
285	argv += optind;
286	optind = 0;
287
288	if (argc < 1) {
289		usage();
290		exit(1);
291	}
292
293	str2ba(argv[0], &bdaddr);
294
295	dd = hci_open_dev(dev);
296	if (dd < 0) {
297		fprintf(stderr, "Can't open device hci%d: %s (%d)\n",
298						dev, strerror(errno), errno);
299		exit(1);
300	}
301
302	if (hci_devinfo(dev, &di) < 0) {
303		fprintf(stderr, "Can't get device info for hci%d: %s (%d)\n",
304						dev, strerror(errno), errno);
305		hci_close_dev(dd);
306		exit(1);
307	}
308
309	if (hci_read_local_version(dd, &ver, 1000) < 0) {
310		fprintf(stderr, "Can't read version info for hci%d: %s (%d)\n",
311						dev, strerror(errno), errno);
312		hci_close_dev(dd);
313		exit(1);
314	}
315
316	if (ver.manufacturer != 12) {
317		fprintf(stderr, "Can't find sniffer at hci%d: %s (%d)\n",
318						dev, strerror(ENOSYS), ENOSYS);
319		hci_close_dev(dd);
320		exit(1);
321	}
322
323	if (read_revision(dd, rev, sizeof(rev)) < 0) {
324		fprintf(stderr, "Can't read revision info for hci%d: %s (%d)\n",
325						dev, strerror(errno), errno);
326		hci_close_dev(dd);
327		exit(1);
328	}
329
330	printf("%s\n", rev);
331
332	if (enable_sniffer(dd, 0x01) < 0) {
333		fprintf(stderr, "Can't enable sniffer for hci%d: %s (%d)\n",
334						dev, strerror(errno), errno);
335		hci_close_dev(dd);
336		exit(1);
337	}
338
339	if (enable_sync(dd, 0x01, &bdaddr) < 0) {
340		fprintf(stderr, "Can't enable sync for hci%d: %s (%d)\n",
341						dev, strerror(errno), errno);
342		enable_sniffer(dd, 0x00);
343		hci_close_dev(dd);
344		exit(1);
345	}
346
347	process_frames(dev);
348
349	if (enable_sync(dd, 0x00, &bdaddr) < 0) {
350		fprintf(stderr, "Can't disable sync for hci%d: %s (%d)\n",
351						dev, strerror(errno), errno);
352		enable_sniffer(dd, 0x00);
353		hci_close_dev(dd);
354		exit(1);
355	}
356
357	if (enable_sniffer(dd, 0x00) < 0) {
358		fprintf(stderr, "Can't disable sniffer for hci%d: %s (%d)\n",
359						dev, strerror(errno), errno);
360		hci_close_dev(dd);
361		exit(1);
362	}
363
364	hci_close_dev(dd);
365
366	return 0;
367}
368