Diff between e6c5ffe4f09c07f2b687b4baf6e40389bfff3c3c and 42ad78700e4b4066b6b0e1bbeb4570f66b875e54

Changed Files

File Additions Deletions Status
tools/hcidump.1 +3 -0 modified
tools/hcidump.c +20 -8 modified
tools/parser/hci.c +1 -1 modified
tools/parser/l2cap.c +13 -12 modified
tools/parser/parser.c +22 -20 modified
tools/parser/parser.h +3 -1 modified
tools/parser/ppp.c +15 -0 modified
tools/parser/sdp.c +13 -12 modified

Full Patch

diff --git a/tools/hcidump.1 b/tools/hcidump.1
index 3f8a01f..d9bd7c2 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=" "<channel>"
 Sets the RFCOMM channel value for the Point-to-Point Protocol.
 .TP
+.BR -D ", " "\-\^\-pppdump=" "<file>"
+Extract PPP traffic with pppdump format.
+.TP
 .BR -A ", " "\-\^\-audio=" "<file>"
 Extract SCO audio data.
 .TP
diff --git a/tools/hcidump.c b/tools/hcidump.c
index 362e0e9..f330e28 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 14f733c..9a4b265 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 4855b20..a494198 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 cab8136..01d0e7e 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 ba16607..ee890fc 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 67ba1f7..9d1ca45 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 9a3121e..9111277 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;
 }