hcidump: Improved packet parser and output format.

This commit is contained in:
Max Krasnyansky 2001-08-05 16:57:21 +00:00 committed by Marcel Holtmann
parent b689aca5d8
commit cde05014b3

View File

@ -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;
}