mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-26 21:54:33 +08:00
hcidump: Improved packet parser and output format.
This commit is contained in:
parent
b689aca5d8
commit
cde05014b3
194
tools/hcidump.c
194
tools/hcidump.c
@ -41,19 +41,9 @@
|
||||
#include <bluetooth/hci.h>
|
||||
#include <bluetooth/l2cap.h>
|
||||
|
||||
#define HEXDUMP 0
|
||||
#define ANALYZE 1
|
||||
|
||||
/* Default options */
|
||||
int action = ANALYZE;
|
||||
|
||||
char * hci_pkt_type[] = {
|
||||
"Unknown",
|
||||
"Command",
|
||||
"ACL Data",
|
||||
"SCO Data",
|
||||
"Event"
|
||||
};
|
||||
int snap_len = 1 + HCI_ACL_HDR_SIZE + L2CAP_HDR_SIZE + 40;
|
||||
int dump_type = 0;
|
||||
|
||||
void usage(void)
|
||||
{
|
||||
@ -62,62 +52,83 @@ void usage(void)
|
||||
printf("\thcidump <-i hciX> [-h]\n");
|
||||
}
|
||||
|
||||
void hex_dump(char *pref, unsigned char *buf, int len)
|
||||
void raw_dump(char *pref, unsigned char *buf, int len)
|
||||
{
|
||||
register char *ptr;
|
||||
register int i;
|
||||
char line[100];
|
||||
|
||||
if (!dump_type)
|
||||
return;
|
||||
|
||||
ptr = line; *ptr = 0;
|
||||
for(i=0; i<len; i++ ){
|
||||
for (i=0; i<len; i++) {
|
||||
ptr += sprintf(ptr, " %2.2X", buf[i]);
|
||||
if( i && !((i+1)%20) ){
|
||||
if (i && !((i+1)%20)) {
|
||||
printf("%s%s\n", pref, line);
|
||||
ptr = line; *ptr = 0;
|
||||
}
|
||||
}
|
||||
if( line[0] )
|
||||
if (line[0])
|
||||
printf("%s%s\n", pref, line);
|
||||
}
|
||||
|
||||
void inline command_dump(void *ptr, int len)
|
||||
static inline void command_dump(void *ptr, int len)
|
||||
{
|
||||
hci_command_hdr *hdr = ptr;
|
||||
__u16 opcode = __le16_to_cpu(hdr->opcode);
|
||||
printf("ogf 0x%x ocf 0x%x plen %d\n",
|
||||
|
||||
ptr += HCI_COMMAND_HDR_SIZE;
|
||||
len -= HCI_COMMAND_HDR_SIZE;
|
||||
|
||||
printf("Command: ogf 0x%x ocf 0x%x plen %d\n",
|
||||
cmd_opcode_ogf(opcode), cmd_opcode_ocf(opcode), hdr->plen);
|
||||
raw_dump(" ", ptr, len);
|
||||
}
|
||||
|
||||
void inline event_dump(void *ptr, int len)
|
||||
static inline void event_dump(void *ptr, int len)
|
||||
{
|
||||
hci_event_hdr *hdr = ptr;
|
||||
printf("code 0x%2.2x plen %d\n", hdr->evt, hdr->plen);
|
||||
|
||||
ptr += HCI_EVENT_HDR_SIZE;
|
||||
len -= HCI_EVENT_HDR_SIZE;
|
||||
|
||||
printf("Event: code 0x%2.2x plen %d\n", hdr->evt, hdr->plen);
|
||||
raw_dump(" ", ptr, len);
|
||||
}
|
||||
|
||||
void inline l2cap_dump(void *ptr, int len)
|
||||
static inline void l2cap_dump(void *ptr, int len)
|
||||
{
|
||||
l2cap_hdr *hdr = ptr;
|
||||
__u16 dlen = __le16_to_cpu(hdr->len);
|
||||
__u16 cid = __le16_to_cpu(hdr->cid);
|
||||
|
||||
printf(" L2CAP: cid 0x%x len %d\n", cid, dlen);
|
||||
|
||||
ptr += L2CAP_HDR_SIZE;
|
||||
len -= L2CAP_HDR_SIZE;
|
||||
|
||||
if (cid == 0x1) {
|
||||
l2cap_cmd_hdr *hdr = ptr;
|
||||
__u16 len = __le16_to_cpu(hdr->len);
|
||||
printf(" signaling: code 0x%x ident %d len %d\n",
|
||||
|
||||
ptr += L2CAP_CMD_HDR_SIZE;
|
||||
len -= L2CAP_CMD_HDR_SIZE;
|
||||
|
||||
printf(" L2CAP signaling: code 0x%2.2x ident %d len %d\n",
|
||||
hdr->code, hdr->ident, len);
|
||||
raw_dump(" ", ptr, len);
|
||||
} else {
|
||||
printf(" L2CAP data: cid 0x%x len %d\n", cid, dlen);
|
||||
raw_dump(" ", ptr, len);
|
||||
}
|
||||
}
|
||||
|
||||
void inline acl_dump(void *ptr, int len)
|
||||
static inline void acl_dump(void *ptr, int len)
|
||||
{
|
||||
hci_acl_hdr *hdr = ptr;
|
||||
__u16 handle = __le16_to_cpu(hdr->handle);
|
||||
__u16 dlen = __le16_to_cpu(hdr->dlen);
|
||||
|
||||
printf("handle 0x%x flags 0x%x dlen %d\n",
|
||||
printf("ACL data: handle 0x%x flags 0x%x dlen %d\n",
|
||||
acl_handle(handle), acl_flags(handle), dlen);
|
||||
|
||||
ptr += HCI_ACL_HDR_SIZE;
|
||||
@ -125,7 +136,7 @@ void inline acl_dump(void *ptr, int len)
|
||||
l2cap_dump(ptr, len);
|
||||
}
|
||||
|
||||
void analyze(int type, unsigned char *ptr, int len)
|
||||
static inline void analyze(int type, unsigned char *ptr, int len)
|
||||
{
|
||||
switch( type ){
|
||||
case HCI_COMMAND_PKT:
|
||||
@ -141,37 +152,89 @@ void analyze(int type, unsigned char *ptr, int len)
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("\n");
|
||||
printf("Unknown: type 0x%2.2x len %d\n",
|
||||
(__u8) type, len);
|
||||
|
||||
raw_dump(" ", ptr, len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void process_frames(int dev, int fd)
|
||||
{
|
||||
char data[HCI_MAX_FRAME_SIZE], ctrl[100], *ptr;
|
||||
struct cmsghdr *cmsg;
|
||||
struct msghdr msg;
|
||||
struct iovec iv;
|
||||
int len, type, in;
|
||||
|
||||
if (snap_len > sizeof(data))
|
||||
snap_len = sizeof(data);
|
||||
else if (snap_len < 20)
|
||||
snap_len = 20;
|
||||
|
||||
printf("device: hci%d snap_len: %d filter: none\n", dev, snap_len);
|
||||
|
||||
while (1) {
|
||||
iv.iov_base = data;
|
||||
iv.iov_len = snap_len;
|
||||
|
||||
msg.msg_iov = &iv;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = ctrl;
|
||||
msg.msg_controllen = sizeof(ctrl);
|
||||
|
||||
if( (len = recvmsg(fd, &msg, 0)) < 0 ){
|
||||
perror("Receive failed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Process control message */
|
||||
in = 0;
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
while( cmsg ){
|
||||
switch(cmsg->cmsg_type){
|
||||
case HCI_CMSG_DIR:
|
||||
in = *((int *)CMSG_DATA(cmsg));
|
||||
break;
|
||||
}
|
||||
cmsg = CMSG_NXTHDR(&msg, cmsg);
|
||||
}
|
||||
|
||||
ptr = data;
|
||||
type = *ptr++; len--;
|
||||
|
||||
/* Print data direction */
|
||||
printf("%c ", (in ? '>' : '<'));
|
||||
|
||||
analyze(type, ptr, len);
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
extern int optind,opterr,optopt;
|
||||
extern char *optarg;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char data[HCI_MAX_FRAME_SIZE], ctrl[100], *ptr;
|
||||
int s, len, type, opt, dev, in;
|
||||
struct sockaddr_hci addr;
|
||||
struct hci_filter flt;
|
||||
struct cmsghdr *cmsg;
|
||||
struct msghdr msg;
|
||||
struct iovec iv;
|
||||
int s, opt, dev;
|
||||
|
||||
dev = 0;
|
||||
while( (opt=getopt(argc, argv,"i:h")) != EOF ) {
|
||||
while( (opt=getopt(argc, argv,"i:s:h")) != EOF ) {
|
||||
switch(opt) {
|
||||
case 'i':
|
||||
dev = atoi(optarg+3);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
action = HEXDUMP;
|
||||
dump_type = 1;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
action = ANALYZE;
|
||||
case 's':
|
||||
snap_len = atoi(optarg);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -205,60 +268,15 @@ int main(int argc, char *argv[])
|
||||
addr.hci_family = AF_BLUETOOTH;
|
||||
addr.hci_dev = dev;
|
||||
if( bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0 ) {
|
||||
printf("Can't attach to device hci%d. %s(%d)\n", dev, strerror(errno), errno);
|
||||
printf("Can't attach to device hci%d. %s(%d)\n",
|
||||
dev, strerror(errno), errno);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
printf("HCIDump version %s\n", VERSION);
|
||||
printf("HCIDump - HCI packet analyzer ver %s.\n", VERSION);
|
||||
|
||||
while( 1 ) {
|
||||
iv.iov_base = data;
|
||||
iv.iov_len = sizeof(data);
|
||||
process_frames(dev, s);
|
||||
|
||||
msg.msg_iov = &iv;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = ctrl;
|
||||
msg.msg_controllen = sizeof(ctrl);
|
||||
|
||||
if( (len = recvmsg(s, &msg, 0)) < 0 ){
|
||||
perror("Receive failed");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Process controll message */
|
||||
in = 0;
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
while( cmsg ){
|
||||
switch(cmsg->cmsg_type){
|
||||
case HCI_CMSG_DIR:
|
||||
in = *((int *)CMSG_DATA(cmsg));
|
||||
break;
|
||||
}
|
||||
cmsg = CMSG_NXTHDR(&msg, cmsg);
|
||||
}
|
||||
|
||||
ptr = data;
|
||||
type = *ptr++; len--;
|
||||
if( type < 0 || type > 4 )
|
||||
type = 0;
|
||||
|
||||
switch (action) {
|
||||
case ANALYZE:
|
||||
printf("%c %s: ", (in ? '>' : '<'),
|
||||
hci_pkt_type[type] );
|
||||
|
||||
analyze(type, ptr, len);
|
||||
break;
|
||||
|
||||
case HEXDUMP:
|
||||
printf("%c type 0x%2.2x len %d\n",
|
||||
(in ? '>' : '<'),
|
||||
(__u8) type, len);
|
||||
|
||||
hex_dump(" ", ptr, len);
|
||||
break;
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user