Robert Lowe wrote:
Well, I was reporting this from memory. Let me back up a bit. When I first
looked at pcap, I went through Tim Carsten's tutorial, referenced from the
tcpdump.org website. Using that code (sniffer.c) on Linux with a downed eth0
i/f (forcing the dev to any) results in very weird ip src/dst addrs and ports that look partly like byte swapped information, and partly like wrong offsets.
For example, source might look like 253.103.127.0:1 and dest like
0.1.127.0:32792.
Is "sniffer.c" calling "pcap_datalink()", checking for DLT_LINUX_SLL, and processing a link-layer header that looks like what's described in recent versions of the libpcap man page? I suspect it's not, which means it won't properly handle captures on the "any" device - the link-layer header you get in that case doesn't look like an Ethernet link-layer header, and isn't 14 bytes long, so if your program is assuming a 14-byte link-layer header, it will *not* work correctly - what it's reporting as the source and destination IP addresses are other parts of the packet.
I.e., to quote my previous message:
If you really want your app to work on anything other than Ethernet interfaces,
you would use that function to determine what to do with the link-layer header.
where "that function" is "pcap_datalink()". Yes, that could be a bit messy, but you're stuck with it.
See tcpdump for an example of how to handle this.
This leads me to another question. I've seen recommendations to roll your
own structs for IP/TCP headers, hinting that there might be slight differences
in the definitions between platforms. Is this really true?
Yes. For example, if I remember correctly, not all platforms' "struct ip" represent the "header length and version" field in the same way - some have bitfields and some have a single field for the header length and version and macros to extract the header length and version from it.
That's why tcpdump has its own headers.
I decided to use the definitions in the provided header files, and when I tested with my app, it showed correct behaviour in both cases (off the wire and loopback). But, if portability is an issue, what is the recommended course of action?
Use your own definitions for all packet data structures.
On what OS are you doing this?
Linux, FC2 (2.6.5-1.358) and FC3 (can't retrieve right now), in particular. But, I'd like this app to build and run on BSD-derived systems and Solaris.
Then you'd better use "pcap_datalink()" to determine the link-layer header - and you'd better not depend on the "any" device working, as that's Linux-specific, and you'd better not depend on being able to capture on the loopback device, because Solaris doesn't support that.
If you really want your app to work on anything other than Ethernet interfaces, you would use that function to determine what to do with the link-layer header.
...
Thank you for the information! I don't think I'll bother trying this now,
Then you'd better not expect your program to work on anything other than a device that produces Ethernet headers - which means it won't work on the "any" device. Note also that the "any" device doesn't use DLT_LOOP or DLT_NULL headers, so you won't need to handle them if you're capturing on the "any" device - but you will need to handle them if you're going to capture on loopback devices on BSD-derived systems.
but I certainly will at some point.
Only when you do that stuff will it work on the "any" device. Note that your program should print an error message if "pcap_datalink()" returns a DLT_ value that it can't handle.
-
This is the tcpdump-workers list.
Visit https://lists.sandelman.ca/ to unsubscribe.