Subject: bin/8798: libpcap LP64 problem -- can't read files from LP32 tcpdump
To: None <gnats-bugs@gnats.netbsd.org>
From: Havard Eidnes <he@runit.no>
List: netbsd-bugs
Date: 11/14/1999 09:48:50
>Number:         8798
>Category:       bin
>Synopsis:       libpcap LP64 problem -- can't read files from LP32 tcpdump
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    bin-bug-people (Utility Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Nov 14 09:48:00 1999
>Last-Modified:
>Originator:     Havard Eidnes
>Organization:
	Me, myself.
>Release:        NetBSD 1.4.1
>Environment:
System: NetBSD albatross.runit.sintef.no 1.4.1 NetBSD 1.4.1 (ALBATROSS) #13: Fri Nov  5 13:42:55 MET 1999     he@albatross.runit.sintef.no:/usr/src/sys/arch/alpha/compile/ALBATROSS alpha

>Description:
	Tcpdump on NetBSD/alpha cannot read a tcpdump file produced
with "tcpdump -w" on NetBSD/i386 or any other LP32 platform.  The
problem is that the "packet header" includes a "struct timeval", which
has "u_long"s as components, resulting in different results for LP64
platforms.

>How-To-Repeat:
	Take packet dump on NetBSD/i386, try to read it with "tcpdump
-r" on NetBDS/alpha.

>Fix:
This fix makes the on-disk format conform to the LP32 model,
reintroducing a year-2032 (or thereabouts) problem for this code on
the Alpha.  However, I expect we can deal with that when the time
comes...

Index: pcap.h
===================================================================
RCS file: /cvsroot/basesrc/lib/libpcap/pcap.h,v
retrieving revision 1.7
diff -u -r1.7 pcap.h
--- pcap.h	1998/07/26 14:49:36	1.7
+++ pcap.h	1999/11/14 17:38:52
@@ -90,6 +90,17 @@
 };
 
 /*
+ * Well, "struct timeval" has different size between LP32 and LP64,
+ * so here's the LP32 version of the on-disk format.
+ */
+struct pcap_f_pkthdr {
+	bpf_u_int32 tv_sec;
+	bpf_u_int32 tv_usec;
+	bpf_u_int32 caplen;
+	bpf_u_int32 len;
+};
+
+/*
  * As returned by the pcap_stats()
  */
 struct pcap_stat {
Index: savefile.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libpcap/savefile.c,v
retrieving revision 1.5
diff -u -r1.5 savefile.c
--- savefile.c	1997/10/03 15:53:17	1.5
+++ savefile.c	1999/11/14 17:38:53
@@ -205,12 +205,17 @@
 sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, int buflen)
 {
 	FILE *fp = p->sf.rfile;
+	struct pcap_f_pkthdr pfh;
 
 	/* read the stamp */
-	if (fread((char *)hdr, sizeof(struct pcap_pkthdr), 1, fp) != 1) {
+	if (fread((char *)&pfh, sizeof(struct pcap_f_pkthdr), 1, fp) != 1) {
 		/* probably an EOF, though could be a truncated packet */
 		return (1);
 	}
+	hdr->ts.tv_sec = pfh.tv_sec;
+	hdr->ts.tv_usec = pfh.tv_usec;
+	hdr->caplen = pfh.caplen;
+	hdr->len = pfh.len;
 
 	if (p->sf.swapped) {
 		/* these were written in opposite byte order */
@@ -322,10 +327,16 @@
 pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
 {
 	register FILE *f;
+	struct pcap_f_pkthdr fh;
 
+	fh.tv_sec = h->ts.tv_sec;
+	fh.tv_usec = h->ts.tv_usec;
+	fh.caplen = h->caplen;
+	fh.len = h->len;
+
 	f = (FILE *)user;
 	/* XXX we should check the return status */
-	(void)fwrite((char *)h, sizeof(*h), 1, f);
+	(void)fwrite((char *)&fh, sizeof(fh), 1, f);
 	(void)fwrite((char *)sp, h->caplen, 1, f);
 }
 

>Audit-Trail:
>Unformatted: