> > This makes sense; however, every application that uses libpcap must be
> > careful to define its own timeval structure that has 32-bit ints, instead
> > of using the one defined in the system headers.
>
> ...or "libpcap" needs to be changed not to use "struct timeval" in
> "pcap_pkthdr", and to use instead, say, "bpf_u_int32 ts_sec" and
> "bpf_u_int32 ts_usec", and the applications need to refer to "ts_sec"
> and "ts_usec" rather than "ts.tv_sec" and "ts.tv_usec".
...which won't fix the problem.
Unfortunately, as you note, having the "libpcap" packet header start
with anything other than a "struct timeval" breaks "libpcap" programs -
"tcpdump", for example, prints timestamps with
ts_print(&h->ts);
where "h" is a "const struct pcap_pkthdr *".
How does "pcap.h" define "struct pcap_pkthdr" on RedHat 5.2 and 6.0 on
Alpha? (Does it define it any differently on other platforms?)
In your original mail, you said:
> I'm running linux-2.2.10, redhat-5.2 on an alpha. With the 2.2-series
> kernel on alpha, the seconds and microseconds are stored as 64-bit
> integers instead of 32-bit integers. This is a nasty little problem I ran
> into with the stock tcpdump/libpcap in the stock redhat-5.2/alpha (glibc
> 2.0). The headers that come with redhat define a timestamp as two 32-bit
> ints, and this causes all sorts of nastyness. I got it to work by
> building libpcap/tcpdump after changing the struct timeval in timebits.h
> to look like the one in the kernel. I beleive RedHat have made this same
> change as of 6.0 (glibc 2.1).
What is "timebits.h"? A generic header used in userland (e.g., included
by <sys/time.h>), or something specific to 'libpcap"?
If 6.0 (and other 64-bit Linux distributions with 2.2-series kernels)
declare a "struct pcap_pkthdr" as
struct pcap_pkthdr {
struct timeval ts; /* time stamp */
bpf_u_int32 caplen; /* length of portion present */
bpf_u_int32 len; /* length this packet (off wire) */
};
with "struct timeval" having 64-bit "tv_sec" and "tv_usec", we probably
need to do the same in Wiretap.
> struct pcaprec_hdr maybe should be changed to use a struct timeval
> as defined in timebits.h, like libpcap does. There's a big problem with
> this, though -- traces on 64-bit machines won't be viewable on 32-bit
> machines and vica versa. This seems like a problem with libpcap.
Actually, if the "if" right above this is true, we *can* arrange to read
traces from 64-bit machines on 32-bit machines, and *vice versa*....
A 32-bit-time-stamp "libpcap" packet header looks like (all lines
represent 32-bit quantities):
tv_sec
tv_usec
caplen
len
A 64-bit-time-stamp big-endian "libpcap" packet header looks like:
upper 32 bits of "tv_sec" (probably 0)
lower 32 bits of "tv_sec"
upper 32 bits of "tv_usec", which should be 0 (tv_usec < 1000000)
lower 32 bits of "tv_usec"
caplen
len
A 64-bit-time-stamp little-endian header looks like:
lower 32 bits of "tv_sec"
upper 32 bits of "tv_sec" (probably 0)
lower 32 bits of "tv_usec"
upper 32 bits of "tv_usec", which should be 0 (tv_usec < 1000000)
caplen
len
If you read the first 4 32-bit words of the packet header, and it's from
a machine with 32-bit time stamps, the third and fourth 32-bit words
should be non-zero, as one is the captured length and one is the
on-the-wire length.
If it's from a big-endian machine with 64-bit time stamps, however, the
third word should be zero, as "tv_usec" should be less than 1 000 000,
and thus should fit in 32 bits. If it's from a little-endian machine
with 64-bit time stamps, the fourth word should be zero, for the same
reason.
So, if we keep a flag saying "32-bit timestamps, 64-bit timestamps, or
as-yet-unknown time stamp size", start it out as "as yet unknown", and:
if it's "as yet unknown", read the first 4 32-bit words of the
header into a structure with 32-bit time stamps and check
whether either "len" or "caplen" are zero - if so, flag it as
"64-bit", copy those 4 words to a structure with 64-bit time
stamps, and read the next 2 32-bit words into the fifth and
sixth words of that structure;
if it's "32 bits", read 4 32-bit words into a 32-bit time stamp
structure;
if it's "64 bits", read 6 32-bit words into a 64-bit time stamp
structure;
and then process the appropriate structure, we can handle either time
stamp size on both 32-bit and 64-bit machines.
A similar hack could be put into "libpcap" itself, so that, at least if
you have such a hacked "libpcap", programs using "libpcap" to read
capture files could read capture files both from machines with 32-bit
time stamps and from machines with 64-bit time stamps.
(When reading a *live* capture, it'd treat it as having the native time
stamp type.)