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

📄 hcidump.c

📁 Linux下蓝牙探测工具
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * *  BlueZ - Bluetooth protocol stack for Linux * *  Copyright (C) 2000-2002  Maxim Krasnyansky <maxk@qualcomm.com> *  Copyright (C) 2003-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 <fcntl.h>#include <unistd.h>#include <stdlib.h>#include <string.h>#include <getopt.h>#include <sys/poll.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/ioctl.h>#include <sys/socket.h>#include <bluetooth/bluetooth.h>#include <bluetooth/hci.h>#include <bluetooth/hci_lib.h>#include <arpa/inet.h>#include <netinet/in.h>#include <netdb.h>#include "parser/parser.h"#include "parser/sdp.h"#if __BYTE_ORDER == __LITTLE_ENDIANstatic inline uint64_t ntoh64(uint64_t n){	uint64_t h;	uint64_t tmp = ntohl(n & 0x00000000ffffffff);	h = ntohl(n >> 32);	h |= tmp << 32;	return h;}#elif __BYTE_ORDER == __BIG_ENDIAN#define ntoh64(x) (x)#else#error "Unknown byte order"#endif#define hton64(x) ntoh64(x)#define SNAP_LEN 	HCI_MAX_FRAME_SIZE#define DEFAULT_PORT	"10839";/* Modes */enum {	PARSE,	READ,	WRITE,	RECEIVE,	SEND,	SERVER,	PPPDUMP,	AUDIO};/* Default options */static int  snap_len = SNAP_LEN;static int  mode = PARSE;static int  permcheck = 1;static int  noappend = 0;static char *dump_file = NULL;static char *pppdump_file = NULL;static char *audio_file = NULL;static char *dump_addr;static char *dump_port = DEFAULT_PORT;static int af = AF_UNSPEC;struct hcidump_hdr {	uint16_t	len;	uint8_t		in;	uint8_t		pad;	uint32_t	ts_sec;	uint32_t	ts_usec;} __attribute__ ((packed));#define HCIDUMP_HDR_SIZE (sizeof(struct hcidump_hdr))struct btsnoop_hdr {	uint8_t		id[8];		/* Identification Pattern */	uint32_t	version;	/* Version Number = 1 */	uint32_t	type;		/* Datalink Type */} __attribute__ ((packed));#define BTSNOOP_HDR_SIZE (sizeof(struct btsnoop_hdr))struct btsnoop_pkt {	uint32_t	size;		/* Original Length */	uint32_t	len;		/* Included Length */	uint32_t	flags;		/* Packet Flags */	uint32_t	drops;		/* Cumulative Drops */	uint64_t	ts;		/* Timestamp microseconds */	uint8_t		data[0];	/* Packet Data */} __attribute__ ((packed));#define BTSNOOP_PKT_SIZE (sizeof(struct btsnoop_pkt))static uint8_t btsnoop_id[] = { 0x62, 0x74, 0x73, 0x6e, 0x6f, 0x6f, 0x70, 0x00 };static uint32_t btsnoop_version = 0;static uint32_t btsnoop_type = 0;struct pktlog_hdr {	uint32_t	len;	uint64_t	ts;	uint8_t		type;} __attribute__ ((packed));#define PKTLOG_HDR_SIZE (sizeof(struct pktlog_hdr))static inline int read_n(int fd, char *buf, int len){	int t = 0, w;	while (len > 0) {		if ((w = read(fd, buf, len)) < 0) {			if (errno == EINTR || errno == EAGAIN)				continue;			return -1;		}		if (!w)			return 0;		len -= w; buf += w; t += w;	}	return t;}static inline int write_n(int fd, char *buf, int len){	int t = 0, w;	while (len > 0) {		if ((w = write(fd, buf, len)) < 0) {			if (errno == EINTR || errno == EAGAIN)				continue;			return -1;		}		if (!w)			return 0;		len -= w; buf += w; t += w;	}	return t;}static int process_frames(int dev, int sock, int fd, unsigned long flags){	struct cmsghdr *cmsg;	struct msghdr msg;	struct iovec  iv;	struct hcidump_hdr *dh;	struct btsnoop_pkt *dp;	struct frame frm;	struct pollfd fds[2];	int nfds = 0;	char *buf, *ctrl;	int len, hdr_size = HCIDUMP_HDR_SIZE;	if (sock < 0)		return -1;	if (mode == SERVER)		flags |= DUMP_BTSNOOP;	if (snap_len < SNAP_LEN)		snap_len = SNAP_LEN;	if (flags & DUMP_BTSNOOP)		hdr_size = BTSNOOP_PKT_SIZE;	buf = malloc(snap_len + hdr_size);	if (!buf) {		perror("Can't allocate data buffer");		return -1;	}	dh = (void *) buf;	dp = (void *) buf;	frm.data = buf + hdr_size;	ctrl = malloc(100);	if (!ctrl) {		free(buf);		perror("Can't allocate control buffer");		return -1;	}	if (dev == HCI_DEV_NONE)		printf("system: ");	else		printf("device: hci%d ", dev);	printf("snap_len: %d filter: 0x%lx\n", snap_len, parser.filter);	memset(&msg, 0, sizeof(msg));	if (mode == SERVER) {		struct btsnoop_hdr *hdr = (void *) buf;		btsnoop_version = 1;		btsnoop_type = 1002;		memcpy(hdr->id, btsnoop_id, sizeof(btsnoop_id));		hdr->version = htonl(btsnoop_version);		hdr->type = htonl(btsnoop_type);		printf("btsnoop version: %d datalink type: %d\n",						btsnoop_version, btsnoop_type);		len = write(fd, buf, BTSNOOP_HDR_SIZE);		if (len < 0) {			perror("Can't create dump header");			return -1;		}		if (len != BTSNOOP_HDR_SIZE) {			fprintf(stderr, "Header size mismatch\n");			return -1;		}		fds[nfds].fd = fd;		fds[nfds].events = POLLIN;		fds[nfds].revents = 0;		nfds++;	}	fds[nfds].fd = sock;	fds[nfds].events = POLLIN;	fds[nfds].revents = 0;	nfds++;	while (1) {		int i, n = poll(fds, nfds, -1);		if (n <= 0)			continue;		for (i = 0; i < nfds; i++) {			if (fds[i].revents & (POLLHUP | POLLERR | POLLNVAL)) {				if (fds[i].fd == sock)					printf("device: disconnected\n");				else					printf("client: disconnect\n");				return 0;			}		}		if (mode == SERVER) {			len = recv(fd, buf, snap_len, MSG_DONTWAIT);			if (len == 0) {				printf("client: disconnect\n");				return 0;			}			if (len < 0 && errno != EAGAIN && errno != EINTR) {				perror("Connection read failure");				return -1;			}		}		iv.iov_base = frm.data;		iv.iov_len  = snap_len;		msg.msg_iov = &iv;		msg.msg_iovlen = 1;		msg.msg_control = ctrl;		msg.msg_controllen = 100;		len = recvmsg(sock, &msg, MSG_DONTWAIT);		if (len < 0) {			if (errno == EAGAIN || errno == EINTR)				continue;			perror("Receive failed");			return -1;		}		/* Process control message */		frm.data_len = len;		frm.dev_id = dev;		frm.in = 0;		frm.pppdump_fd = parser.pppdump_fd;		frm.audio_fd   = parser.audio_fd;		cmsg = CMSG_FIRSTHDR(&msg);		while (cmsg) {			switch (cmsg->cmsg_type) {			case HCI_CMSG_DIR:				frm.in = *((int *) CMSG_DATA(cmsg));				break;			case HCI_CMSG_TSTAMP:				frm.ts = *((struct timeval *) CMSG_DATA(cmsg));				break;			}			cmsg = CMSG_NXTHDR(&msg, cmsg);		}		frm.ptr = frm.data;		frm.len = frm.data_len;		switch (mode) {		case WRITE:		case SEND:		case SERVER:			/* Save or send dump */			if (flags & DUMP_BTSNOOP) {				uint64_t ts;				uint8_t pkt_type = ((uint8_t *) frm.data)[0];				dp->size = htonl(frm.data_len);				dp->len  = dp->size;				dp->flags = ntohl(frm.in & 0x01);				dp->drops = 0;				ts = (frm.ts.tv_sec - 946684800ll) * 1000000ll + frm.ts.tv_usec;				dp->ts = hton64(ts + 0x00E03AB44A676000ll);				if (pkt_type == HCI_COMMAND_PKT ||						pkt_type == HCI_EVENT_PKT)					dp->flags |= ntohl(0x02);			} else {				dh->len = htobs(frm.data_len);				dh->in  = frm.in;				dh->ts_sec  = htobl(frm.ts.tv_sec);				dh->ts_usec = htobl(frm.ts.tv_usec);			}			if (write_n(fd, buf, frm.data_len + hdr_size) < 0) {				perror("Write error");				return -1;			}			break;		default:			/* Parse and print */			parse(&frm);			break;		}	}	return 0;}static void read_dump(int fd){	struct hcidump_hdr dh;	struct btsnoop_pkt dp;	struct pktlog_hdr ph;	struct frame frm;	uint8_t pkt_type;	int err;	frm.data = malloc(HCI_MAX_FRAME_SIZE);	if (!frm.data) {		perror("Can't allocate data buffer");		exit(1);	}	while (1) {		if (parser.flags & DUMP_PKTLOG)			err = read_n(fd, (void *) &ph, PKTLOG_HDR_SIZE);		else if (parser.flags & DUMP_BTSNOOP)			err = read_n(fd, (void *) &dp, BTSNOOP_PKT_SIZE);		else			err = read_n(fd, (void *) &dh, HCIDUMP_HDR_SIZE);		if (err < 0)			goto failed;		if (!err)			return;		if (parser.flags & DUMP_PKTLOG) {			switch (ph.type) {			case 0x00:				((uint8_t *) frm.data)[0] = HCI_COMMAND_PKT;				frm.in = 0;				break;			case 0x01:				((uint8_t *) frm.data)[0] = HCI_EVENT_PKT;				frm.in = 1;				break;			case 0x02:				((uint8_t *) frm.data)[0] = HCI_ACLDATA_PKT;				frm.in = 0;				break;			case 0x03:				((uint8_t *) frm.data)[0] = HCI_ACLDATA_PKT;				frm.in = 1;				break;			default:				lseek(fd, ntohl(ph.len) - 9, SEEK_CUR);				continue;			}			frm.data_len = ntohl(ph.len) - 8;			err = read_n(fd, frm.data + 1, frm.data_len - 1);		} else if (parser.flags & DUMP_BTSNOOP) {			switch (btsnoop_type) {			case 1001:				if (ntohl(dp.flags) & 0x02) {					if (ntohl(dp.flags) & 0x01)						pkt_type = HCI_EVENT_PKT;					else						pkt_type = HCI_COMMAND_PKT;				} else					pkt_type = HCI_ACLDATA_PKT;				((uint8_t *) frm.data)[0] = pkt_type;				frm.data_len = ntohl(dp.len) + 1;				err = read_n(fd, frm.data + 1, frm.data_len - 1);				break;			case 1002:				frm.data_len = ntohl(dp.len);				err = read_n(fd, frm.data, frm.data_len);				break;			}		} else {			frm.data_len = btohs(dh.len);			err = read_n(fd, frm.data, frm.data_len);		}		if (err < 0)			goto failed;		if (!err)			return;		frm.ptr = frm.data;		frm.len = frm.data_len;		if (parser.flags & DUMP_PKTLOG) {			uint64_t ts;			ts = ntoh64(ph.ts);			frm.ts.tv_sec = ts >> 32;			frm.ts.tv_usec = ts & 0xffffffff;		} else if (parser.flags & DUMP_BTSNOOP) {			uint64_t ts;			frm.in = ntohl(dp.flags) & 0x01;			ts = ntoh64(dp.ts) - 0x00E03AB44A676000ll;			frm.ts.tv_sec = (ts / 1000000ll) + 946684800ll;			frm.ts.tv_usec = ts % 1000000ll;		} else {			frm.in = dh.in;			frm.ts.tv_sec  = btohl(dh.ts_sec);			frm.ts.tv_usec = btohl(dh.ts_usec);		}		parse(&frm);	}failed:	perror("Read failed");	exit(1);}static int open_file(char *file, int mode, unsigned long flags){	unsigned char buf[BTSNOOP_HDR_SIZE];	struct btsnoop_hdr *hdr = (struct btsnoop_hdr *) buf;	int fd, len, open_flags;	if (mode == WRITE || mode == PPPDUMP || mode == AUDIO) {		if (noappend || flags & DUMP_BTSNOOP)			open_flags = O_WRONLY | O_CREAT | O_TRUNC;		else			open_flags = O_WRONLY | O_CREAT | O_APPEND;	} else		open_flags = O_RDONLY;	fd = open(file, open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);	if (fd < 0) {		perror("Can't open dump file");		exit(1);	}	if (mode == READ) {		len = read(fd, buf, BTSNOOP_HDR_SIZE);		if (len != BTSNOOP_HDR_SIZE) {			lseek(fd, 0, SEEK_SET);			return fd;		}		if (!memcmp(hdr->id, btsnoop_id, sizeof(btsnoop_id))) {			parser.flags |= DUMP_BTSNOOP;			btsnoop_version = ntohl(hdr->version);			btsnoop_type = ntohl(hdr->type);			printf("btsnoop version: %d datalink type: %d\n",						btsnoop_version, btsnoop_type);			if (btsnoop_version != 1) {				fprintf(stderr, "Unsupported BTSnoop version\n");				exit(1);			}			if (btsnoop_type != 1001 && btsnoop_type != 1002) {				fprintf(stderr, "Unsupported BTSnoop datalink type\n");				exit(1);			}		} else {			if (buf[0] == 0x00 && buf[1] == 0x00) {				parser.flags |= DUMP_PKTLOG;				printf("packet logger data format\n");			}			parser.flags &= ~DUMP_BTSNOOP;			lseek(fd, 0, SEEK_SET);			return fd;		}	} else {		if (flags & DUMP_BTSNOOP) {			btsnoop_version = 1;			btsnoop_type = 1002;			memcpy(hdr->id, btsnoop_id, sizeof(btsnoop_id));			hdr->version = htonl(btsnoop_version);			hdr->type = htonl(btsnoop_type);			printf("btsnoop version: %d datalink type: %d\n",						btsnoop_version, btsnoop_type);			len = write(fd, buf, BTSNOOP_HDR_SIZE);			if (len < 0) {				perror("Can't create dump header");				exit(1);			}			if (len != BTSNOOP_HDR_SIZE) {				fprintf(stderr, "Header size mismatch\n");				exit(1);			}		}	}	return fd;}static int open_socket(int dev, unsigned long flags){	struct sockaddr_hci addr;	struct hci_filter flt;	struct hci_dev_info di;	int sk, dd, opt;	if (permcheck && dev != HCI_DEV_NONE) {		dd = hci_open_dev(dev);		if (dd < 0) {			perror("Can't open device");			return -1;		}		if (hci_devinfo(dev, &di) < 0) {			perror("Can't get device info");			return -1;		}		opt = hci_test_bit(HCI_RAW, &di.flags);		if (ioctl(dd, HCISETRAW, opt) < 0) {			if (errno == EACCES) {				perror("Can't access device");				return -1;			}		}		hci_close_dev(dd);	}	/* Create HCI socket */	sk = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);	if (sk < 0) {		perror("Can't create raw socket");

⌨️ 快捷键说明

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