tcpdump
tcpdump copied to clipboard
netlink: Implement printer
This patch introduces a printer for DLT_NETLINK, Linux netlink packets. Each packet might contain multiple messages. The 16-byte header is the same as in SLL. Usually the packets are captured with the help of the nlmon kernel module ~~and do not cross host boundaries. Since the endianness of the platform is not captured, the printer will assume it is on a host with the same endianness for now~~.
There might be some capture files which use DLT_LINUX_SLL. In these cases, the dissector will call the new printer as well.
Usually the packets are captured with the help of the nlmon kernel module and do not cross host boundaries.
A packet crosses a host boundary if you email it to somebody so they can look at it, unless the capture was done on a time-sharing machine into which you both log in.
Since the endianness of the platform is not captured, the printer will assume it is on a host with the same endianness for now.
That's causing the tests to fail.
Wireshark makes an attempt to guess the byte order:
/*
* We do not know the endianness of the capture host, we have to guess.
* Compare the size of the message with the reported size of the TVB,
* take the endianness in which the messsage length is closer to
* the size of the TVB. Normally we have messages with less
* than 10KiB here so the sizes are very huge in the wrong endianness.
*/
What it does is:
- find the remaining length of the packet on the wire (len, not caplen, so that's len - amount parsed before the length of the message);
- fetch the length of the message, both in big-endian and little-endian byte orders;
- pick the byte order that minimizes the absolute value of the difference between the length remaining and the length of the message.
Can you assume that a live capture is host endian, and then use pcap_is_swapped() to decide to swap fields when reading from a capture file? (Obviously some infrastructure would have to be created to propagate the swapped-ness info from pcap into the printer)
Can you assume that a live capture is host endian, and then use
pcap_is_swapped()to decide to swap fields when reading from a capture file?
That almost works. However, if, for example:
-
you do a capture on a big-endian machine;
-
you read the capture on a little-endian machine, filtering it, and writing the packets that match the filter to a new file, doing
tcpdump -r {file} -w {new file} {filter};
you end up with a little-endian version of the file.
That's why libpcap has code to byte-swap fields in some formats where the link-layer header is specified as host-endian (swap_pseudo_headers(), and routines it calls, in pcap-common.c), and Wireshark's pcap/pcapng-reading code does the same. Unfortunately, that's more work to do with netlink.
Thank you for the review! I added the same heuristic to guess the endianness and added a capture file which was captured on a big-endian system but filtered (and thus rewritten) on a little-endian system.
Any reason for some "truncated" messages? Example:
sudo ./tcpdump -#v -i nlmon0
tcpdump: listening on nlmon0, link-type NETLINK (Linux netlink), snapshot length 262144 bytes
1 09:26:47.203019 Route: length 56
type 18, length 40, flags 0x0301, sequence 1621322808, pid 0
[...]
6 09:26:47.203513 Route: length 168
type 22, length 24, flags 0x0301, sequence 1621322809, pid 0
type 0, length 0, flags 0x0000, sequence 0, pid 0 [|netlink] <-------------------------------------------
To reproduce (on Debian Bullseye):
sudo modprobe nlmon
sudo ip link add type nlmon
sudo ip link set nlmon0 up
ip a