While developing a network sniffer I had to find a way to write pcap
logs. However the docs I found were rather fragmented. I try to do a short roundup here. In fact, the format is pretty plain and it’s a pity that there seems not to be a quick’n’easy doc for it.
Every log-file starts with a header:
struct pcap_hdr {
unsigned long magic; /* always 0xa1b2c3d4 */
unsigned short version_major; /* 2 for now */
unsigned short version_minor; /* 4 for now */
unsigned long thiszone; /* GMT to local correction */
unsigned long sigfigs; /* accuracy of timestamps, 0 is fine */
unsigned long snaplen; /* max length of captured packets */
unsigned long network; /* data link type */
};
The only really significant field here is network
, which defines the format of the packets. I’m using 113 in dietsniff which means DLT_LINUX_SLL
(“Linux cooked sockets”), i.e. those from PF_SOCKET
sockets. man pcap
contains a list and explanation of more possible formats.
While the header mentioned above appears only once at the beginning of a log file, the following applies to every single packet that is written to the log. First of all, every packet is preceded with a generic header:
struct pcap_rec_hdr {
struct timeval ts; /* timestamp */
unsigned long incl_len; /* number of octets of packet saved in file */
unsigned long orig_len; /* actual length of packet */
};
The timestamp of the packet, the length that is contained in the log and the real length. So it’s possible to save only a certain amount of bytes of every packet.
The following data of each packet depends heavily of the specified format. I’m going to show how I did it for DLT_LINUX_SLL
: first, we need just another header (again, for each packet):
struct pcap_sll_hdr {
unsigned short pkttype;
unsigned short hatype;
unsigned short halen;
char addr[8];
unsigned short protocol;
};
These fields resemble those from struct sockaddr_ll
which is returned with each packet so it’s just about 4 assignments and one memcpy()
. The definition of this struct can be deducted from the pcap man page in the explanation of DLT_LINUX_SLL
. I guess the other types should similarly straightforward.
After this, the packet can be finally dumped to the file.