Diff between 8e1c754a1c9587b0892a218e5eba0f2becdb5965 and 52241871a690cbb0eb71709d635665632c51835f

Changed Files

File Additions Deletions Status
tools/hcidump.1 +6 -0 modified
tools/hcidump.c +135 -82 modified
tools/parser/bnep.c +39 -15 modified
tools/parser/tcpip.c +55 -11 modified

Full Patch

diff --git a/tools/hcidump.1 b/tools/hcidump.1
index 913471c..f0aa4d4 100644
--- a/tools/hcidump.1
+++ b/tools/hcidump.1
@@ -108,6 +108,12 @@ Don't display any vendor commands or events and don't show any pin code or link 
 .TP
 .BR -N ", " "\-\^\-noappend"
 No appending to existing files. Always create new files.
+.TP
+.BR -4 ", " "\-\^\-ipv4"
+Use IPv4 when sending information over the network
+.TP
+.BR -6 ", " "\-\^\-ipv6"
+Use IPv6 when sending information over the network
 .SH FILTERS
 .B
 filter
diff --git a/tools/hcidump.c b/tools/hcidump.c
index f1d0825..0458ab4 100644
--- a/tools/hcidump.c
+++ b/tools/hcidump.c
@@ -66,7 +66,7 @@ static inline uint64_t ntoh64(uint64_t n)
 #define hton64(x) ntoh64(x)
 
 #define SNAP_LEN 	HCI_MAX_FRAME_SIZE
-#define DEFAULT_PORT	10839;
+#define DEFAULT_PORT	"10839";
 
 /* Modes */
 enum {
@@ -92,8 +92,9 @@ 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;
+static char *dump_addr;
+static char *dump_port = DEFAULT_PORT;
+static int af = AF_UNSPEC;
 
 struct hcidump_hdr {
 	uint16_t	len;
@@ -504,88 +505,146 @@ static int open_socket(int dev, unsigned long flags)
 	return sk;
 }
 
-static int open_connection(in_addr_t addr, in_port_t port)
+static int open_connection(char *addr, char *port)
 {
-	struct sockaddr_in sa;
-	int sk, opt;
+	struct sockaddr_storage ss;
+	struct addrinfo hints, *res0, *res;
+	int sk = -1, opt = 1;
+	
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = af;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_protocol = IPPROTO_TCP;
+	
+	if (getaddrinfo(addr, port, &hints, &res0))
+		if(getaddrinfo(NULL, port, &hints, &res0)) {
+			perror("getaddrinfo");
+			exit(1);
+		}
+	
+	for (res = res0; res; res = res->ai_next) {
+		sk = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+		if (sk < 0) {
+			if (res->ai_next)
+				continue;
 
-	sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-	if (sk < 0) {
-		perror("Can't create inet socket");
-		exit(1);
-	}
+			perror("Can't create socket");
+			freeaddrinfo(res0);
+			exit(1);
+		}
 
-	opt = 1;
-	setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+		setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+		
+		memcpy(&ss, res->ai_addr, res->ai_addrlen);
 
-	sa.sin_family = AF_INET;
-	sa.sin_addr.s_addr = htonl(INADDR_ANY);
-	sa.sin_port = htons(0);
-	if (bind(sk, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
-		perror("Can't bind inet socket");
-		close(sk);
-		exit(1);
-	}
+		switch(ss.ss_family) {
+		case AF_INET:
+			((struct sockaddr_in *) &ss)->sin_addr.s_addr = htonl(INADDR_ANY);
+			((struct sockaddr_in *) &ss)->sin_port = 0;
+			break;
+		case AF_INET6:
+			memcpy(&((struct sockaddr_in6 *) &ss)->sin6_addr, &in6addr_any, sizeof(in6addr_any));
+			((struct sockaddr_in6 *) &ss)->sin6_port = 0;
+			break;
+		}
 
-	sa.sin_family = AF_INET;
-	sa.sin_addr.s_addr = htonl(addr);
-	sa.sin_port = htons(port);
-	if (connect(sk, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
-		perror("Can't connect inet socket");
-		close(sk);
-		exit(1);
+		if (bind(sk, (struct sockaddr *) &ss, sizeof(ss)) < 0) {
+			perror("Can't bind socket");
+			close(sk);
+			freeaddrinfo(res0);
+			exit(1);
+		}
+		
+		if (connect(sk, res->ai_addr, res->ai_addrlen) < 0) {
+			perror("Can't connect socket");
+			close(sk);
+			freeaddrinfo(res0);
+			exit(1);
+		}
 	}
 
+	freeaddrinfo(res0);
+
 	return sk;
 }
 
-static int wait_connection(in_addr_t addr, in_port_t port)
+static int wait_connection(char *addr, char *port)
 {
-	struct sockaddr_in sa;
-	struct hostent *host;
+	char hname[100], hport[10];
+	struct sockaddr_storage ss;
+	struct addrinfo hints, *res0, *res;
 	socklen_t len;
-	int sk, nsk, opt;
+	int sk = -1, nsk, opt = 1;
 
-	sk = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-	if (sk < 0) {
-		perror("Can't create inet socket");
-		exit(1);
-	}
+	memset(&hints, 0, sizeof(hints));
+	hints.ai_family = af;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_protocol = IPPROTO_TCP;
 
-	opt = 1;
-	setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
+	if (getaddrinfo(addr, port, &hints, &res0))
+		if (getaddrinfo(NULL, port, &hints, &res0)) {
+			perror("getaddrinfo");
+			exit(1);
+		}
+ 	
+	for (res = res0; res; res = res->ai_next) {
+		sk = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+		if (sk < 0) {
+			if (res->ai_next)
+				continue;
 
-	sa.sin_family = AF_INET;
-	sa.sin_addr.s_addr = htonl(addr);
-	sa.sin_port = htons(port);
-	if (bind(sk, (struct sockaddr *) &sa, sizeof(sa)) < 0) {
-		perror("Can't bind inet socket");
-		close(sk);
-		exit(1);
-	}
+			perror("Can't create socket");
+ 			freeaddrinfo(res0);
+			exit(1);
+		}
 
-	host = gethostbyaddr(&sa.sin_addr, sizeof(sa.sin_addr), AF_INET);
-	printf("device: %s:%d snap_len: %d filter: 0x%lx\n", 
-		host ? host->h_name : inet_ntoa(sa.sin_addr),
-		ntohs(sa.sin_port), snap_len, filter);
+		setsockopt(sk, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
 
-	if (listen(sk, 1)) {
-		perror("Can't listen on inet socket");
-		close(sk);
-		exit(1);
+		if (bind(sk, res->ai_addr, res->ai_addrlen) < 0) {
+			if(res->ai_next) {
+				close(sk);
+				continue;
+			}
+
+			perror("Can't bind socket");
+			close(sk);
+			freeaddrinfo(res0);
+			exit(1);
+ 		}
+
+		getnameinfo(res->ai_addr, res->ai_addrlen, hname, sizeof(hname),
+					hport, sizeof(hport), NI_NUMERICSERV);
+		printf("device: %s:%s snap_len: %d filter: 0x%lx\n", 
+					hname, hport, snap_len, filter);
+		if (listen(sk, 1) < 0) {
+			if (res->ai_next) {
+				close(sk);
+				continue;
+			}
+
+			perror("Can't listen on socket");
+			close(sk);
+			freeaddrinfo(res0);
+			exit(1);
+		}
 	}
 
-	len = sizeof(sa);
-	nsk = accept(sk, (struct sockaddr *) &sa, &len);
+	freeaddrinfo(res0);
+
+	len = sizeof(ss);
+	nsk = accept(sk, (struct sockaddr *) &ss, &len);
 	if (nsk < 0) {
-		perror("Can't accept new inet socket");
+		perror("Can't accept new socket");
 		close(sk);
+		freeaddrinfo(res0);
 		exit(1);
 	}
 
-	host = gethostbyaddr(&sa.sin_addr, sizeof(sa.sin_addr), AF_INET);
-	printf("device: %s snap_len: %d filter: 0x%lx\n", 
-		host ? host->h_name : inet_ntoa(sa.sin_addr), snap_len, filter);
+	getnameinfo((struct sockaddr *) &ss, sizeof(ss),
+					hname, sizeof(hname), NULL, 0, 0);
+
+	printf("device: %s snap_len: %d filter: 0x%lx\n",
+						hname, snap_len, filter);
 
 	close(sk);
 
@@ -657,6 +716,8 @@ static void usage(void)
 	"  -V, --verbose              Verbose decoding\n"
 	"  -Y, --novendor             No vendor commands or events\n"
 	"  -N, --noappend             No appending to existing files\n"
+	"  -4, --ipv4                 Use IPv4 as transport\n"
+	"  -6  --ipv6                 Use IPv6 as transport\n"
 	"  -h, --help                 Give this help list\n"
 	"      --usage                Give a short usage message\n"
 	);
@@ -687,19 +748,19 @@ static struct option main_options[] = {
 	{ "novendor",		0, 0, 'Y' },
 	{ "nopermcheck",	0, 0, 'Z' },
 	{ "noappend",		0, 0, 'N' },
+	{ "ipv4",		0, 0, '4' },
+	{ "ipv6",		0, 0, '6' },
 	{ "help",		0, 0, 'h' },
 	{ 0 }
 };
 
 int main(int argc, char *argv[])
 {
-	struct hostent *host;
-	struct in_addr addr;
 	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:D:A:BVYZNh", main_options, NULL)) != -1) {
+	while ((opt=getopt_long(argc, argv, "i:l:p:m:w:r:s:n:taxXRC:H:O:P:D:A:BVYZN46h", main_options, NULL)) != -1) {
 		switch(opt) {
 		case 'i':
 			if (strcasecmp(optarg, "none") && strcasecmp(optarg, "system"))
@@ -732,28 +793,12 @@ int main(int argc, char *argv[])
 
 		case 's':
 			mode = SEND;
-			host = gethostbyname(optarg);
-			if (host) {
-				bcopy(host->h_addr, &addr, sizeof(struct in_addr));
-				dump_addr = ntohl(addr.s_addr);
-				dump_port = DEFAULT_PORT;
-			} else {
-				dump_addr = INADDR_LOOPBACK;
-				dump_port = DEFAULT_PORT;
-			}
+			dump_addr = optarg;
 			break;
 
 		case 'n':
 			mode = RECEIVE;
-			host = gethostbyname(optarg);
-			if (host) {
-				bcopy(host->h_addr, &addr, sizeof(struct in_addr));
-				dump_addr = ntohl(addr.s_addr);
-				dump_port = DEFAULT_PORT;
-			} else {
-				dump_addr = INADDR_LOOPBACK;
-				dump_port = DEFAULT_PORT;
-			}
+			dump_addr = optarg;
 			break;
 
 		case 't': 
@@ -820,6 +865,14 @@ int main(int argc, char *argv[])
 			noappend = 1;
 			break;
 
+		case '4':
+			af = AF_INET;
+			break;
+
+		case '6':
+			af = AF_INET6;
+			break;
+
 		case 'h':
 		default:
 			usage();
diff --git a/tools/parser/bnep.c b/tools/parser/bnep.c
index 05aad2a..d026162 100644
--- a/tools/parser/bnep.c
+++ b/tools/parser/bnep.c
@@ -56,6 +56,10 @@
 /* BNEP Extension Type */
 #define BNEP_EXTENSION_CONTROL			0x00
 
+#ifndef ETHERTYPE_IPV6
+#define ETHERTYPE_IPV6 ETH_P_IPV6
+#endif
+
 static char *get_macaddr(struct frame *frm)
 {
 	static char str[20];
@@ -63,8 +67,10 @@ static char *get_macaddr(struct frame *frm)
 
 	sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
 		buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
+
 	frm->ptr += 6;
 	frm->len -= 6;
+
 	return str;
 }
 
@@ -131,12 +137,14 @@ static void bnep_control(int level, struct frame *frm, int header_length)
 		break;
 
 	case BNEP_SETUP_CONNECTION_RESPONSE_MSG:
-		printf("Setup Rsp(0x%02x) res 0x%04x\n", type, get_u16(frm));
+		printf("Setup Rsp(0x%02x) res 0x%04x\n",
+						type, get_u16(frm));
 		break;
 
 	case BNEP_FILTER_NET_TYPE_SET_MSG:
 		length = get_u16(frm);
-		printf("Filter NetType Set(0x%02x) len 0x%04x\n", type, length);
+		printf("Filter NetType Set(0x%02x) len 0x%04x\n",
+							type, length);
 		for (i = 0; i < length / 4; i++) {
 			p_indent(level + 1, frm);
 			printf("0x%04x - ", get_u16(frm));
@@ -145,12 +153,14 @@ static void bnep_control(int level, struct frame *frm, int header_length)
 		break;
 
 	case BNEP_FILTER_NET_TYPE_RESPONSE_MSG:
-		printf("Filter NetType Rsp(0x%02x) res 0x%04x\n", type, get_u16(frm));
+		printf("Filter NetType Rsp(0x%02x) res 0x%04x\n",
+							type, get_u16(frm));
 		break;
 
 	case BNEP_FILTER_MULT_ADDR_SET_MSG:
 		length = get_u16(frm);
-		printf("Filter MultAddr Set(0x%02x) len 0x%04x\n", type, length);
+		printf("Filter MultAddr Set(0x%02x) len 0x%04x\n",
+							type, length);
 		for (i = 0; i < length / 12; i++) {
 			p_indent(level + 1, frm);
 			printf("%s - ", get_macaddr(frm));
@@ -159,7 +169,8 @@ static void bnep_control(int level, struct frame *frm, int header_length)
 		break;
 
 	case BNEP_FILTER_MULT_ADDR_RESPONSE_MSG:
-		printf("Filter MultAddr Rsp(0x%02x) res 0x%04x\n", type, get_u16(frm));
+		printf("Filter MultAddr Rsp(0x%02x) res 0x%04x\n",
+							type, get_u16(frm));
 		break;
 
 	default:
@@ -174,26 +185,28 @@ static void bnep_control(int level, struct frame *frm, int header_length)
 static void bnep_eval_extension(int level, struct frame *frm)
 {
 	uint8_t type = get_u8(frm);
-	int extension = type & 0x80;
 	uint8_t length = get_u8(frm);
+	int extension = type & 0x80;
 
 	p_indent(level, frm);
+
 	switch (type & 0x7f) {
 	case BNEP_EXTENSION_CONTROL:
-		printf("Ext Control(0x%02x|%s) len 0x%02x\n", type & 0x7f, extension ? "1" : "0", length);
+		printf("Ext Control(0x%02x|%s) len 0x%02x\n",
+				type & 0x7f, extension ? "1" : "0", length);
 		bnep_control(level, frm, length);
 		break;
 
 	default:
-		printf("Ext Unknown(0x%02x|%s) len 0x%02x\n", type & 0x7f, extension ? "1" : "0", length);
+		printf("Ext Unknown(0x%02x|%s) len 0x%02x\n",
+				type & 0x7f, extension ? "1" : "0", length);
 		raw_ndump(level + 1, frm, length);
 		frm->ptr += length;
 		frm->len -= length;
 	}
 
-	if (extension) {
+	if (extension)
 		bnep_eval_extension(level, frm);
-	}
 }
 
 void bnep_dump(int level, struct frame *frm)
@@ -206,19 +219,22 @@ void bnep_dump(int level, struct frame *frm)
 
 	switch (type & 0x7f) {
 	case BNEP_CONTROL:
-		printf("BNEP: Control(0x%02x|%s)\n", type & 0x7f, extension ? "1" : "0");
+		printf("BNEP: Control(0x%02x|%s)\n",
+					type & 0x7f, extension ? "1" : "0");
 		bnep_control(level, frm, -1);
 		break;
 
 	case BNEP_COMPRESSED_ETHERNET:
-		printf("BNEP: Compressed(0x%02x|%s)\n", type & 0x7f, extension ? "1" : "0");
+		printf("BNEP: Compressed(0x%02x|%s)\n",
+					type & 0x7f, extension ? "1" : "0");
 		p_indent(++level, frm);
 		proto = get_u16(frm);
 		printf("[proto 0x%04x]\n", proto);
 		break;
 
 	case BNEP_GENERAL_ETHERNET:
-		printf("BNEP: General ethernet(0x%02x|%s)\n", type & 0x7f, extension ? "1" : "0");
+		printf("BNEP: General ethernet(0x%02x|%s)\n",
+					type & 0x7f, extension ? "1" : "0");
 		p_indent(++level, frm);
 		printf("dst %s ", get_macaddr(frm));
 		printf("src %s ", get_macaddr(frm));
@@ -227,7 +243,8 @@ void bnep_dump(int level, struct frame *frm)
 		break;
 
 	case BNEP_COMPRESSED_ETHERNET_DEST_ONLY:
-		printf("BNEP: Compressed DestOnly(0x%02x|%s)\n", type & 0x7f, extension ? "1" : "0");
+		printf("BNEP: Compressed DestOnly(0x%02x|%s)\n",
+					type & 0x7f, extension ? "1" : "0");
 		p_indent(++level, frm);
 		printf("dst %s ", get_macaddr(frm));
 		proto = get_u16(frm);
@@ -235,7 +252,8 @@ void bnep_dump(int level, struct frame *frm)
 		break;
 
 	case BNEP_COMPRESSED_ETHERNET_SOURCE_ONLY:
-		printf("BNEP: Compressed SrcOnly(0x%02x|%s)\n", type & 0x7f, extension ? "1" : "0");
+		printf("BNEP: Compressed SrcOnly(0x%02x|%s)\n",
+					type & 0x7f, extension ? "1" : "0");
 		p_indent(++level, frm);
 		printf("src %s ", get_macaddr(frm));
 		proto = get_u16(frm);
@@ -287,6 +305,12 @@ void bnep_dump(int level, struct frame *frm)
 		ip_dump(level, frm);
 		break;
 
+	case ETHERTYPE_IPV6:
+		p_indent(++level, frm);
+		printf("IPV6: ");
+		ip_dump(level, frm);
+		break;
+
 	default:
 		raw_dump(level, frm);
 		break;
diff --git a/tools/parser/tcpip.c b/tools/parser/tcpip.c
index d8791a7..6afac2b 100644
--- a/tools/parser/tcpip.c
+++ b/tools/parser/tcpip.c
@@ -35,26 +35,37 @@
 #include <net/ethernet.h>
 #include <netinet/in.h>
 #include <netinet/ip.h>
+#include <netinet/ip6.h>
 #include <netinet/if_ether.h>
 #include <arpa/inet.h>
+#include <netdb.h>
 
 #include "parser.h"
 
 void arp_dump(int level, struct frame *frm)
 {
 	int i;
+	char buf[20];
+	struct sockaddr_in sai;
 	struct ether_arp *arp = (struct ether_arp *) frm->ptr;
 
 	printf("Src ");
 	for (i = 0; i < 5; i++)
 		printf("%02x:", arp->arp_sha[i]);
 	printf("%02x", arp->arp_sha[5]);
-	printf("(%s) ", inet_ntoa(*(struct in_addr *) &arp->arp_spa));
+	sai.sin_family = AF_INET;
+	memcpy(&sai.sin_addr, &arp->arp_spa, sizeof(sai.sin_addr));
+	getnameinfo((struct sockaddr *) &sai, sizeof(sai), buf, sizeof(buf),
+		    NULL, 0, NI_NUMERICHOST);
+	printf("(%s) ", buf);
 	printf("Tgt ");
 	for (i = 0; i < 5; i++)
 		printf("%02x:", arp->arp_tha[i]);
 	printf("%02x", arp->arp_tha[5]);
-	printf("(%s)\n", inet_ntoa(*(struct in_addr *) &arp->arp_tpa));
+	memcpy(&sai.sin_addr, &arp->arp_tpa, sizeof(sai.sin_addr));
+	getnameinfo((struct sockaddr *) &sai, sizeof(sai), buf, sizeof(buf),
+		    NULL, 0, NI_NUMERICHOST);
+	printf("(%s)\n", buf);
 	frm->ptr += sizeof(struct ether_arp);
 	frm->len -= sizeof(struct ether_arp);
 	raw_dump(level, frm);		// not needed.
@@ -62,33 +73,66 @@ void arp_dump(int level, struct frame *frm)
 
 void ip_dump(int level, struct frame *frm)
 {
+	char src[50], dst[50];
 	struct ip *ip = (struct ip *) (frm->ptr);
-	int len = ip->ip_hl << 2;
+	int len;
+	uint8_t proto = 0;
+
+	if (ip->ip_v == 4) {
+		struct sockaddr_in sai;
+		proto = ip->ip_p;
+		len = ip->ip_hl << 2;
+		memset(&sai, 0, sizeof(sai));
+		sai.sin_family = AF_INET;
+		memcpy(&sai.sin_addr, &ip->ip_src, sizeof(struct in_addr));
+		getnameinfo((struct sockaddr *) &sai, sizeof(sai),
+			    src, sizeof(src), NULL, 0, NI_NUMERICHOST);
+		memcpy(&sai.sin_addr, &ip->ip_dst, sizeof(struct in_addr));
+		getnameinfo((struct sockaddr *) &sai, sizeof(sai),
+			    dst, sizeof(dst), NULL, 0, NI_NUMERICHOST);
+	} else if (ip->ip_v == 6) {
+		struct sockaddr_in6 sai6;
+		struct ip6_hdr *ip6 = (struct ip6_hdr *) ip;
+		proto = ip6->ip6_nxt;
+		len = sizeof(struct ip6_hdr);
+		memset(&sai6, 0, sizeof(sai6));
+		sai6.sin6_family = AF_INET6;
+		memcpy(&sai6.sin6_addr, &ip6->ip6_src, sizeof(struct in6_addr));
+		getnameinfo((struct sockaddr *) &sai6, sizeof(sai6),
+			    src, sizeof(src), NULL, 0, NI_NUMERICHOST);
+		memcpy(&sai6.sin6_addr, &ip6->ip6_dst, sizeof(struct in6_addr));
+		getnameinfo((struct sockaddr *) &sai6, sizeof(sai6),
+			    dst, sizeof(dst), NULL, 0, NI_NUMERICHOST);
+	}
+
+	printf("src %s ", src);
+	printf("dst %s\n", dst);
+
 	frm->ptr += len;
 	frm->len -= len;
-
-	printf("src %s ", inet_ntoa(*(struct in_addr *) &(ip->ip_src)));
-	printf("dst %s\n", inet_ntoa(*(struct in_addr *) &(ip->ip_dst)));
 	p_indent(++level, frm);
 
-	switch (ip->ip_p) {
+	switch (proto) {
 	case IPPROTO_TCP:
 		printf("TCP:\n");
-		raw_dump(level, frm);
 		break;
 
 	case IPPROTO_UDP:
 		printf("UDP:\n");
-		raw_dump(level, frm);
 		break;
 
 	case IPPROTO_ICMP:
 		printf("ICMP:\n");
-		raw_dump(level, frm);
+		break;
+
+	case IPPROTO_ICMPV6:
+		printf("ICMPv6:\n");
 		break;
 
 	default:
 		printf("Unknown Protocol: 0x%02x\n", ip->ip_p);
-		raw_dump(level, frm);
+		break;
 	}
+
+	raw_dump(level, frm);
 }