⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bpasniff.c

📁 Linux下蓝牙探测工具
💻 C
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2004-2007  Marcel Holtmann <marcel@holtmann.org> * * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <stdio.h>#include <errno.h>#include <ctype.h>#include <unistd.h>#include <stdlib.h>#include <malloc.h>#include <getopt.h>#include <signal.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <netinet/in.h>#include "parser/parser.h"static volatile sig_atomic_t __io_canceled = 0;static void sig_hup(int sig){}static void sig_term(int sig){	__io_canceled = 1;}static int read_revision(int dd, char *revision, int size){	struct hci_request rq;	unsigned char req[] = { 0x07 };	unsigned char buf[46];	memset(&rq, 0, sizeof(rq));	rq.ogf    = OGF_VENDOR_CMD;	rq.ocf    = 0x000e;	rq.cparam = req;	rq.clen   = sizeof(req);	rq.rparam = &buf;	rq.rlen   = sizeof(buf);	if (hci_send_req(dd, &rq, 1000) < 0)		return -1;	if (buf[0] > 0) {		errno = EIO;		return -1;	}	if (revision)		strncpy(revision, (char *) (buf + 1), size);	return 0;}static int enable_sniffer(int dd, uint8_t enable){	struct hci_request rq;	unsigned char req[] = { 0x00, enable };	unsigned char buf[1];	memset(&rq, 0, sizeof(rq));	rq.ogf    = OGF_VENDOR_CMD;	rq.ocf    = 0x000e;	rq.cparam = req;	rq.clen   = sizeof(req);	rq.rparam = &buf;	rq.rlen   = sizeof(buf);	if (hci_send_req(dd, &rq, 1000) < 0)		return -1;	if (buf[0] > 0) {		errno = EIO;		return -1;	}	return 0;}static int enable_sync(int dd, uint8_t enable, bdaddr_t *bdaddr){	struct hci_request rq;	unsigned char req[] = { 0x01, enable,				0x00, 0x00, 0x00, 0x00, 0x00, 0x00,				0x00, 0xfa, 0x00 };	memcpy(req + 2, bdaddr, 6);	memset(&rq, 0, sizeof(rq));	rq.ogf    = OGF_VENDOR_CMD;	rq.ocf    = 0x000e;	rq.cparam = req;	rq.clen   = sizeof(req);	hci_send_req(dd, &rq, 1000);	return 0;}static char *type2str(uint8_t type){	switch (type) {	case 0x00:		return "NULL";	case 0x01:		return "POLL";	case 0x02:		return "FHS";	case 0x03:		return "DM1";	case 0x04:		return "DH1";	case 0x05:		return "HV1";	case 0x06:		return "HV2";	case 0x07:		return "HV3";	case 0x08:		return "DV";	case 0x09:		return "AUX1";	case 0x0a:		return "DM3";	case 0x0b:		return "DH3";	case 0x0c:		return "EV4";	case 0x0d:		return "EV5";	case 0x0e:		return "DM5";	case 0x0f:		return "DH5";	case 0xff:		return "ID";	default:		return "UNK";	}}static void decode(unsigned char *buf, int count){	struct frame frm;	uint8_t id, status, channel;	uint16_t num, len;	uint32_t time;	uint8_t type, addr, temp, hdr;	uint8_t flow, arqn, seqn, hec, llid, pflow;	uint16_t plen;	if (count < 7)		return;	id = buf[0];	num = ntohs(bt_get_unaligned((uint16_t *) (buf + 1)));	len = btohs(bt_get_unaligned((uint16_t *) (buf + 3)));	status  = buf[5];	time    = ntohl(bt_get_unaligned((uint32_t *) (buf + 6)));	channel = buf[10];	if (len < 8)		return;	type = (len < 7) ? 0xff : bt_get_unaligned((uint8_t *) (buf + 11));	if (type < 2)		return;	p_indent(-1, NULL);	memset(&frm, 0, sizeof(frm));	frm.data     = buf + 12;	frm.data_len = count - 12;	frm.ptr      = frm.data;	frm.len      = frm.data_len;	frm.in       = 0;	frm.master   = 0;	frm.handle   = 0;	frm.flags    = 0;	p_indent(0, &frm);	printf("BPA: id %d num %d status 0x%02x time %d channel %2d len %d\n",		id, num, status, time, channel, len - 6);	if (type < 3) {		printf("  %s\n", type2str(type));		raw_dump(1, &frm);		return;	}	addr = bt_get_unaligned((uint8_t *) (buf + 12));	temp = bt_get_unaligned((uint8_t *) (buf + 13));	flow = (temp & 0x04) >> 2;	arqn = (temp & 0x02) >> 1;	seqn = (temp & 0x01);	hec  = bt_get_unaligned((uint8_t *) (buf + 14));	hdr = bt_get_unaligned((uint8_t *) (buf + 20));	plen  = ((hdr & 0x10) >> 4) | ((hdr & 0x08) >> 2) | (hdr & 0x04) | ((hdr & 0x02) << 2) | ((hdr & 0x01) << 4);	pflow = ((hdr & 0x20) >> 5);	llid = ((hdr & 0x80) >> 7) | ((hdr & 0x40) >> 5);	hdr = bt_get_unaligned((uint8_t *) (buf + 21));	plen = plen | ((hdr & 0x80) >> 2) | (hdr & 0x40) | ((hdr & 0x20) << 2) | ((hdr & 0x08) << 4);	p_indent(0, &frm);	printf("%s: addr 0x%02x flow %d arqn %d seqn %d hec 0x%02x llid %d pflow %d plen %d\n",		type2str(type), addr, flow, arqn, seqn, hec, llid, pflow, plen);	if (type == 0x03 && llid == 3) {		memset(&frm, 0, sizeof(frm));		frm.data     = buf + 22;		frm.data_len = plen;		frm.ptr      = frm.data;		frm.len      = frm.data_len;		frm.in       = 0;		frm.master   = 1;		frm.handle   = 0;		frm.flags    = llid;		lmp_dump(1, &frm);		return;	}	raw_dump(1, &frm);}static void process_frames(int dev){	struct sigaction sa;	struct hci_filter flt;	unsigned char *buf;	int dd, size = 2048;	buf = malloc(size);	if (!buf) {		fprintf(stderr, "Can't allocate buffer for hci%d: %s (%d)\n",						dev, strerror(errno), errno);		return;	}	dd = hci_open_dev(dev);	if (dd < 0) {		fprintf(stderr, "Can't open device hci%d: %s (%d)\n",						dev, strerror(errno), errno);		free(buf);		return;	}	hci_filter_clear(&flt);	hci_filter_set_ptype(HCI_VENDOR_PKT, &flt);	hci_filter_set_ptype(HCI_EVENT_PKT, &flt);	hci_filter_set_event(EVT_VENDOR, &flt);	if (setsockopt(dd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {		fprintf(stderr, "Can't set filter for hci%d: %s (%d)\n",						dev, strerror(errno), errno);		hci_close_dev(dd);		free(buf);		return;	}	memset(&sa, 0, sizeof(sa));	sa.sa_flags   = SA_NOCLDSTOP;	sa.sa_handler = SIG_IGN;	sigaction(SIGCHLD, &sa, NULL);	sigaction(SIGPIPE, &sa, NULL);	sa.sa_handler = sig_term;	sigaction(SIGTERM, &sa, NULL);	sigaction(SIGINT,  &sa, NULL);	sa.sa_handler = sig_hup;	sigaction(SIGHUP, &sa, NULL);	while (!__io_canceled) {		int len;		len = read(dd, buf, size);		if (len < 0)			break;		if (len < 2)			continue;		if (buf[0] == 0x04 && buf[1] == 0xff) {			if (buf[3] == 0x02) {				switch (buf[4]) {				case 0x00:					printf("Waiting for synchronization...\n");					break;				case 0x08:					printf("Synchronization lost\n");					__io_canceled = 1;					break;				default:					printf("Unknown event 0x%02x\n", buf[4]);					break;				}			}		}		if (buf[0] != 0xff)			continue;		decode(buf + 1, len - 1);	}	hci_close_dev(dd);	free(buf);}static void usage(void){	printf("bpasniff - Utility for the BPA 100/105 sniffers\n\n");	printf("Usage:\n"		"\tbpasniff [-i <dev>] <master-bdaddr>\n");}static struct option main_options[] = {	{ "help",	0, 0, 'h' },	{ "device",	1, 0, 'i' },	{ 0, 0, 0, 0}};int main(int argc, char *argv[]){	struct hci_dev_info di;	struct hci_version ver;	char rev[46];	bdaddr_t bdaddr;	int dd, opt, dev = 0;	bacpy(&bdaddr, BDADDR_ANY);	while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) {		switch (opt) {		case 'i':			dev = hci_devid(optarg);			if (dev < 0) {				perror("Invalid device");				exit(1);			}			break;		case 'h':		default:			usage();			exit(0);		}	}	argc -= optind;	argv += optind;	optind = 0;	argc -= optind;	argv += optind;	optind = 0;	if (argc < 1) {		usage();		exit(1);	}	str2ba(argv[0], &bdaddr);	dd = hci_open_dev(dev);	if (dd < 0) {		fprintf(stderr, "Can't open device hci%d: %s (%d)\n",						dev, strerror(errno), errno);		exit(1);	}	if (hci_devinfo(dev, &di) < 0) {		fprintf(stderr, "Can't get device info for hci%d: %s (%d)\n",						dev, strerror(errno), errno);		hci_close_dev(dd);		exit(1);	}	if (hci_read_local_version(dd, &ver, 1000) < 0) {		fprintf(stderr, "Can't read version info for hci%d: %s (%d)\n",						dev, strerror(errno), errno);		hci_close_dev(dd);		exit(1);	}	if (ver.manufacturer != 12) {		fprintf(stderr, "Can't find sniffer at hci%d: %s (%d)\n",						dev, strerror(ENOSYS), ENOSYS);		hci_close_dev(dd);		exit(1);	}	if (read_revision(dd, rev, sizeof(rev)) < 0) {		fprintf(stderr, "Can't read revision info for hci%d: %s (%d)\n",						dev, strerror(errno), errno);		hci_close_dev(dd);		exit(1);	}	printf("%s\n", rev);	if (enable_sniffer(dd, 0x01) < 0) {		fprintf(stderr, "Can't enable sniffer for hci%d: %s (%d)\n",						dev, strerror(errno), errno);		hci_close_dev(dd);		exit(1);	}	if (enable_sync(dd, 0x01, &bdaddr) < 0) {		fprintf(stderr, "Can't enable sync for hci%d: %s (%d)\n",						dev, strerror(errno), errno);		enable_sniffer(dd, 0x00);		hci_close_dev(dd);		exit(1);	}	init_parser(DUMP_EXT | DUMP_VERBOSE, ~0L, 0, DEFAULT_COMPID, -1, -1);	process_frames(dev);	if (enable_sync(dd, 0x00, &bdaddr) < 0) {		fprintf(stderr, "Can't disable sync for hci%d: %s (%d)\n",						dev, strerror(errno), errno);		enable_sniffer(dd, 0x00);		hci_close_dev(dd);		exit(1);	}	if (enable_sniffer(dd, 0x00) < 0) {		fprintf(stderr, "Can't disable sniffer for hci%d: %s (%d)\n",						dev, strerror(errno), errno);		hci_close_dev(dd);		exit(1);	}	hci_close_dev(dd);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -