From 42ad78700e4b4066b6b0e1bbeb4570f66b875e54 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 17 Jan 2006 18:28:55 +0000 Subject: [PATCH] hcidump: Add PPP extraction support --- tools/hcidump.1 | 3 +++ tools/hcidump.c | 28 ++++++++++++++++++++-------- tools/parser/hci.c | 2 +- tools/parser/l2cap.c | 25 +++++++++++++------------ tools/parser/parser.c | 42 ++++++++++++++++++++++-------------------- tools/parser/parser.h | 4 +++- tools/parser/ppp.c | 15 +++++++++++++++ tools/parser/sdp.c | 25 +++++++++++++------------ 8 files changed, 90 insertions(+), 54 deletions(-) diff --git a/tools/hcidump.1 b/tools/hcidump.1 index 3f8a01f34..d9bd7c22f 100644 --- a/tools/hcidump.1 +++ b/tools/hcidump.1 @@ -91,6 +91,9 @@ Sets the RFCOMM channel value for the Object Exchange Protocol. .BR -P ", " "\-\^\-ppp=" "" Sets the RFCOMM channel value for the Point-to-Point Protocol. .TP +.BR -D ", " "\-\^\-pppdump=" "" +Extract PPP traffic with pppdump format. +.TP .BR -A ", " "\-\^\-audio=" "" Extract SCO audio data. .TP diff --git a/tools/hcidump.c b/tools/hcidump.c index 362e0e958..f330e288e 100644 --- a/tools/hcidump.c +++ b/tools/hcidump.c @@ -75,6 +75,7 @@ enum { WRITE, RECEIVE, SEND, + PPPDUMP, AUDIO }; @@ -88,6 +89,7 @@ static int permcheck = 1; static long flags; static long filter; static char *dump_file = NULL; +static char *pppdump_file = NULL; static char *audio_file = NULL; static in_addr_t dump_addr = INADDR_LOOPBACK; static in_port_t dump_port = DEFAULT_PORT; @@ -218,7 +220,8 @@ static void process_frames(int dev, int sock, int fd, unsigned long flags) frm.data_len = len; frm.dev_id = dev; frm.in = 0; - frm.audio_fd = parser.audio_fd; + frm.pppdump_fd = parser.pppdump_fd; + frm.audio_fd = parser.audio_fd; cmsg = CMSG_FIRSTHDR(&msg); while (cmsg) { @@ -358,7 +361,7 @@ static int open_file(char *file, int mode, unsigned long flags) struct btsnoop_hdr hdr; int fd, len, open_flags; - if (mode == WRITE || mode == AUDIO) { + if (mode == WRITE || mode == PPPDUMP || mode == AUDIO) { if (flags & DUMP_BTSNOOP) open_flags = O_WRONLY | O_CREAT; else @@ -647,6 +650,7 @@ static void usage(void) " -H, --hcrp=psm PSM for HCRP\n" " -O, --obex=channel Channel for OBEX\n" " -P, --ppp=channel Channel for PPP\n" + " -D, --pppdump=file Extract PPP traffic\n" " -A, --audio=file Extract SCO audio data\n" " -B, --btsnoop Use BTSnoop file format\n" " -V, --verbose Verbose decoding\n" @@ -674,6 +678,7 @@ static struct option main_options[] = { { "hcrp", 1, 0, 'H' }, { "obex", 1, 0, 'O' }, { "ppp", 1, 0, 'P' }, + { "pppdump", 1, 0, 'D' }, { "audio", 1, 0, 'A' }, { "btsnoop", 0, 0, 'B' }, { "verbose", 0, 0, 'V' }, @@ -687,11 +692,11 @@ int main(int argc, char *argv[]) { struct hostent *host; struct in_addr addr; - int opt, fd = -1; + int opt, pppdump_fd = -1, audio_fd = -1; printf("HCI sniffer - Bluetooth packet analyzer ver %s\n", VERSION); - while ((opt=getopt_long(argc, argv, "i:l:p:m:w:r:s:n:taxXRC:H:O:P:A:BVYZh", main_options, NULL)) != -1) { + while ((opt=getopt_long(argc, argv, "i:l:p:m:w:r:s:n:taxXRC:H:O:P:D:A:BVYZh", main_options, NULL)) != -1) { switch(opt) { case 'i': if (strcasecmp(optarg, "none") && strcasecmp(optarg, "system")) @@ -784,6 +789,10 @@ int main(int argc, char *argv[]) set_proto(0, 0, atoi(optarg), SDP_UUID_LAN_ACCESS_PPP); break; + case 'D': + pppdump_file = strdup(optarg); + break; + case 'A': audio_file = strdup(optarg); break; @@ -822,17 +831,20 @@ int main(int argc, char *argv[]) if (!filter) filter = ~0L; + if (pppdump_file) + pppdump_fd = open_file(pppdump_file, PPPDUMP, flags); + if (audio_file) - fd = open_file(audio_file, AUDIO, flags); + audio_fd = open_file(audio_file, AUDIO, flags); switch (mode) { case PARSE: - init_parser(flags, filter, defpsm, defcompid, fd); + init_parser(flags, filter, defpsm, defcompid, pppdump_fd, audio_fd); process_frames(device, open_socket(device, flags), -1, flags); break; case READ: - init_parser(flags, filter, defpsm, defcompid, fd); + init_parser(flags, filter, defpsm, defcompid, pppdump_fd, audio_fd); read_dump(open_file(dump_file, mode, flags)); break; @@ -842,7 +854,7 @@ int main(int argc, char *argv[]) break; case RECEIVE: - init_parser(flags, filter, defpsm, defcompid, fd); + init_parser(flags, filter, defpsm, defcompid, pppdump_fd, audio_fd); read_dump(wait_connection(dump_addr, dump_port)); break; diff --git a/tools/parser/hci.c b/tools/parser/hci.c index 14f733c7e..9a4b2652c 100644 --- a/tools/parser/hci.c +++ b/tools/parser/hci.c @@ -2614,7 +2614,7 @@ static inline void sco_dump(int level, struct frame *frm) hci_sco_hdr *hdr = (void *) frm->ptr; uint16_t handle = btohs(hdr->handle); - if (frm->audio_fd > 2) + if (frm->audio_fd > fileno(stderr)) write(frm->audio_fd, frm->ptr + HCI_SCO_HDR_SIZE, hdr->dlen); if (!p_filter(FILT_SCO)) { diff --git a/tools/parser/l2cap.c b/tools/parser/l2cap.c index 4855b2060..a4941982e 100644 --- a/tools/parser/l2cap.c +++ b/tools/parser/l2cap.c @@ -868,18 +868,19 @@ void l2cap_dump(int level, struct frame *frm) return; } memcpy(fr->data, frm->ptr, frm->len); - fr->data_len = dlen + L2CAP_HDR_SIZE; - fr->len = frm->len; - fr->ptr = fr->data; - fr->dev_id = frm->dev_id; - fr->in = frm->in; - fr->ts = frm->ts; - fr->handle = frm->handle; - fr->cid = frm->cid; - fr->num = frm->num; - fr->dlci = frm->dlci; - fr->channel = frm->channel; - fr->audio_fd = frm->audio_fd; + fr->data_len = dlen + L2CAP_HDR_SIZE; + fr->len = frm->len; + fr->ptr = fr->data; + fr->dev_id = frm->dev_id; + fr->in = frm->in; + fr->ts = frm->ts; + fr->handle = frm->handle; + fr->cid = frm->cid; + fr->num = frm->num; + fr->dlci = frm->dlci; + fr->channel = frm->channel; + fr->pppdump_fd = frm->pppdump_fd; + fr->audio_fd = frm->audio_fd; } else { if (!(fr = get_frame(frm->handle))) { fprintf(stderr, "Not enough connection handles\n"); diff --git a/tools/parser/parser.c b/tools/parser/parser.c index cab8136bc..01d0e7e0b 100644 --- a/tools/parser/parser.c +++ b/tools/parser/parser.c @@ -43,17 +43,18 @@ struct parser_t parser; void init_parser(unsigned long flags, unsigned long filter, unsigned short defpsm, unsigned short defcompid, - int audio_fd) + int pppdump_fd, int audio_fd) { if ((flags & DUMP_RAW) && !(flags & DUMP_TYPE_MASK)) flags |= DUMP_HEX; - parser.flags = flags; - parser.filter = filter; - parser.defpsm = defpsm; - parser.defcompid = defcompid; - parser.state = 0; - parser.audio_fd = audio_fd; + parser.flags = flags; + parser.filter = filter; + parser.defpsm = defpsm; + parser.defcompid = defcompid; + parser.state = 0; + parser.pppdump_fd = pppdump_fd; + parser.audio_fd = audio_fd; } #define PROTO_TABLE_SIZE 20 @@ -182,19 +183,20 @@ struct frame *add_frame(struct frame *frm) if (fr->data) free(fr->data); - fr->data = data; - fr->data_len = fr->len + frm->len; - fr->len = fr->data_len; - fr->ptr = fr->data; - fr->dev_id = frm->dev_id; - fr->in = frm->in; - fr->ts = frm->ts; - fr->handle = frm->handle; - fr->cid = frm->cid; - fr->num = frm->num; - fr->dlci = frm->dlci; - fr->channel = frm->channel; - fr->audio_fd = frm->audio_fd; + fr->data = data; + fr->data_len = fr->len + frm->len; + fr->len = fr->data_len; + fr->ptr = fr->data; + fr->dev_id = frm->dev_id; + fr->in = frm->in; + fr->ts = frm->ts; + fr->handle = frm->handle; + fr->cid = frm->cid; + fr->num = frm->num; + fr->dlci = frm->dlci; + fr->channel = frm->channel; + fr->pppdump_fd = frm->pppdump_fd; + fr->audio_fd = frm->audio_fd; return fr; } diff --git a/tools/parser/parser.h b/tools/parser/parser.h index ba166078d..ee890fcd0 100644 --- a/tools/parser/parser.h +++ b/tools/parser/parser.h @@ -45,6 +45,7 @@ struct frame { uint8_t channel; unsigned long flags; struct timeval ts; + int pppdump_fd; int audio_fd; }; @@ -96,6 +97,7 @@ struct parser_t { unsigned short defpsm; unsigned short defcompid; int state; + int pppdump_fd; int audio_fd; }; @@ -103,7 +105,7 @@ extern struct parser_t parser; void init_parser(unsigned long flags, unsigned long filter, unsigned short defpsm, unsigned short defcompid, - int audio_fd); + int pppdump_fd, int audio_fd); static inline int p_filter(unsigned long f) { diff --git a/tools/parser/ppp.c b/tools/parser/ppp.c index 67ba1f713..9d1ca45e3 100644 --- a/tools/parser/ppp.c +++ b/tools/parser/ppp.c @@ -76,6 +76,21 @@ void ppp_dump(int level, struct frame *frm) void *ptr, *end; int len, pos = 0; + if (frm->pppdump_fd > fileno(stderr)) { + unsigned char id; + uint16_t len = htons(frm->len); + uint32_t ts = htonl(frm->ts.tv_sec & 0xffffffff); + + id = 0x07; + write(frm->pppdump_fd, &id, 1); + write(frm->pppdump_fd, &ts, 4); + + id = frm->in ? 0x02 : 0x01; + write(frm->pppdump_fd, &id, 1); + write(frm->pppdump_fd, &len, 2); + write(frm->pppdump_fd, frm->ptr, frm->len); + } + if (!ppp_traffic) { pos = check_for_ppp_traffic(frm->ptr, frm->len); if (pos < 0) { diff --git a/tools/parser/sdp.c b/tools/parser/sdp.c index 9a3121e71..9111277b9 100644 --- a/tools/parser/sdp.c +++ b/tools/parser/sdp.c @@ -636,18 +636,19 @@ static int frame_add(struct frame *frm, int count) if (fr->data) free(fr->data); - fr->data = data; - fr->data_len = len + count; - fr->len = fr->data_len; - fr->ptr = fr->data; - fr->dev_id = frm->dev_id; - fr->in = frm->in; - fr->ts = frm->ts; - fr->handle = frm->handle; - fr->cid = frm->cid; - fr->num = frm->num; - fr->channel = frm->channel; - fr->audio_fd = frm->audio_fd; + fr->data = data; + fr->data_len = len + count; + fr->len = fr->data_len; + fr->ptr = fr->data; + fr->dev_id = frm->dev_id; + fr->in = frm->in; + fr->ts = frm->ts; + fr->handle = frm->handle; + fr->cid = frm->cid; + fr->num = frm->num; + fr->channel = frm->channel; + fr->pppdump_fd = frm->pppdump_fd; + fr->audio_fd = frm->audio_fd; return pos; } -- 2.47.3