Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 16 Mar 2012 16:29:22 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r233037 - head/usr.sbin/usbdump
Message-ID:  <201203161629.q2GGTM6P025670@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Fri Mar 16 16:29:21 2012
New Revision: 233037
URL: http://svn.freebsd.org/changeset/base/233037

Log:
  Fix cross-platform issue about the file-format in which
  usbdump stores data. Until this patch it was not possible
  to exchange traces between 32-bit, 64-bit, big- and
  little endian platforms. The problem is the dynamic nature
  of the BPF timestamp in the header. All other fields are
  fixed size and little endian.
  
  MFC after:	5 days

Modified:
  head/usr.sbin/usbdump/usbdump.c

Modified: head/usr.sbin/usbdump/usbdump.c
==============================================================================
--- head/usr.sbin/usbdump/usbdump.c	Fri Mar 16 16:12:10 2012	(r233036)
+++ head/usr.sbin/usbdump/usbdump.c	Fri Mar 16 16:29:21 2012	(r233037)
@@ -92,6 +92,26 @@ struct usbcap_filehdr {
 	uint8_t		reserved[26];
 } __packed;
 
+#define	HEADER_ALIGN(x,a) (((x) + (a) - 1) & ~((a) - 1))
+
+struct header_32 {
+	uint32_t ts_sec;
+	uint32_t ts_usec;
+	uint32_t caplen;
+	uint32_t datalen;
+	uint16_t hdrlen;
+	uint16_t dummy;
+} __packed;
+
+struct header_64 {
+	uint64_t ts_sec;
+	uint64_t ts_usec;
+	uint32_t caplen;
+	uint32_t datalen;
+	uint16_t hdrlen;
+	uint16_t dummy;
+} __packed;
+
 static int doexit = 0;
 static int pkt_captured = 0;
 static int verbose = 0;
@@ -413,7 +433,7 @@ hexdump(const uint8_t *region, uint32_t 
 }
 
 static void
-print_apacket(const struct bpf_hdr *hdr, const uint8_t *ptr, int ptr_len)
+print_apacket(const struct header_32 *hdr, const uint8_t *ptr, int ptr_len)
 {
 	struct tm *tm;
 	struct usbpf_pkthdr up_temp;
@@ -448,8 +468,8 @@ print_apacket(const struct bpf_hdr *hdr,
 	up->up_packet_count = le32toh(up->up_packet_count);
 	up->up_endpoint = le32toh(up->up_endpoint);
 
-	tv.tv_sec = hdr->bh_tstamp.tv_sec;
-	tv.tv_usec = hdr->bh_tstamp.tv_usec;
+	tv.tv_sec = hdr->ts_sec;
+	tv.tv_usec = hdr->ts_usec;
 	tm = localtime(&tv.tv_sec);
 
 	len = strftime(buf, sizeof(buf), "%H:%M:%S", tm);
@@ -516,17 +536,86 @@ print_apacket(const struct bpf_hdr *hdr,
 static void
 print_packets(uint8_t *data, const int datalen)
 {
-	const struct bpf_hdr *hdr;
+	struct header_32 temp;
 	uint8_t *ptr;
 	uint8_t *next;
 
 	for (ptr = data; ptr < (data + datalen); ptr = next) {
-		hdr = (const struct bpf_hdr *)ptr;
-		next = ptr + BPF_WORDALIGN(hdr->bh_hdrlen + hdr->bh_caplen);
+
+		/* automatically figure out endian and size of header */
+
+		if (r_arg != NULL) {
+
+			const struct header_32 *hdr32;
+			const struct header_64 *hdr64;
+
+			hdr32 = (const struct header_32 *)ptr;
+			hdr64 = (const struct header_64 *)ptr;
+
+			temp.hdrlen = le16toh(hdr32->hdrlen);
+			temp.dummy = le16toh(hdr32->dummy);
+
+			if ((temp.hdrlen != 18 && temp.hdrlen != 20) || (temp.dummy != 0)) {
+				temp.hdrlen = be16toh(hdr32->hdrlen);
+				temp.dummy = be16toh(hdr32->dummy);
+
+				if ((temp.hdrlen != 18 && temp.hdrlen != 20) || (temp.dummy != 0)) {
+					temp.hdrlen = le16toh(hdr64->hdrlen);
+					temp.dummy = le16toh(hdr64->dummy);
+
+					if ((temp.hdrlen != 28 && temp.hdrlen != 32) || (temp.dummy != 0)) {
+						temp.hdrlen = be16toh(hdr64->hdrlen);
+						temp.dummy = be16toh(hdr64->dummy);
+
+						if ((temp.hdrlen != 28 && temp.hdrlen != 32) || (temp.dummy != 0)) {
+							err(EXIT_FAILURE, "Invalid header detected");
+							next = NULL;
+						} else {
+							temp.ts_sec = be64toh(hdr64->ts_sec);
+							temp.ts_usec = be64toh(hdr64->ts_usec);
+							temp.caplen = be32toh(hdr64->caplen);
+							temp.datalen = be32toh(hdr64->datalen);
+							next = ptr + HEADER_ALIGN(temp.hdrlen + temp.caplen, 8);
+						}
+					} else {
+						temp.ts_sec = le64toh(hdr64->ts_sec);
+						temp.ts_usec = le64toh(hdr64->ts_usec);
+						temp.caplen = le32toh(hdr64->caplen);
+						temp.datalen = le32toh(hdr64->datalen);
+						next = ptr + HEADER_ALIGN(temp.hdrlen + temp.caplen, 8);
+					}
+				} else {
+					temp.ts_sec = be32toh(hdr32->ts_sec);
+					temp.ts_usec = be32toh(hdr32->ts_usec);
+					temp.caplen = be32toh(hdr32->caplen);
+					temp.datalen = be32toh(hdr32->datalen);
+					next = ptr + HEADER_ALIGN(temp.hdrlen + temp.caplen, 4);
+				}
+			} else {
+				temp.ts_sec = le32toh(hdr32->ts_sec);
+				temp.ts_usec = le32toh(hdr32->ts_usec);
+				temp.caplen = le32toh(hdr32->caplen);
+				temp.datalen = le32toh(hdr32->datalen);
+				next = ptr + HEADER_ALIGN(temp.hdrlen + temp.caplen, 4);
+			}
+		} else {
+			const struct bpf_hdr *hdr;
+
+			hdr = (const struct bpf_hdr *)ptr;
+			temp.ts_sec = hdr->bh_tstamp.tv_sec;
+			temp.ts_usec = hdr->bh_tstamp.tv_usec;
+			temp.caplen = hdr->bh_caplen;
+			temp.datalen = hdr->bh_datalen;
+			temp.hdrlen = hdr->bh_hdrlen;
+			next = ptr + BPF_WORDALIGN(temp.hdrlen + temp.caplen);
+		}
+
+		if (next <= ptr)
+			err(EXIT_FAILURE, "Invalid header length");
 
 		if (w_arg == NULL) {
-			print_apacket(hdr, ptr +
-			    hdr->bh_hdrlen, hdr->bh_caplen);
+			print_apacket(&temp, ptr +
+			    temp.hdrlen, temp.caplen);
 		}
 		pkt_captured++;
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203161629.q2GGTM6P025670>