This blog is only to remind myself of what I've learned (from others or by myself) and only for knowledge sharing. External sources will be clearly stated in [Reference] of each article. I hope this blog won't infringe any copyrights and that it can be useful for interested blog readers.

2008年2月20日 星期三

重點整理 -- converting to libpcap file format

Preface

Reference original web link


[lwlan-devel] converting to libpcap file format

parul singla parulsingla at hotmail.com
Wed Sep 3 01:35:53 EDT 2003
Hi,
Earlier I had written a tool in VC++ which composes 802.11 frames and stores
them as ".dat" files. I wish to read/parse/decompose them using Ethereal.
But, I have to first convert the ".dat" files into ethereal readable format
(one of them is libpcap).

Somewhere I read on this mailing list (which goes like this):

/************************************

libpcap format has a file header, followed by the packets, with each
packet consisting of a packet header followed immediately by the data in
the packet, with no padding between the file header and the first packet
header, the packet header and the packet data, or the packet data and
the header of the next packet, if any.

The file header consists of, in order:

a 32-bit "magic number";

a 16-bit major version number;

a 16-bit minor version number;

a 32-bit "time zone offset" field that's actually not used, so
you can (and probably should) just make it 0;

a 32-bit "time stamp accuracy" field that's not actually used,
so you can (and probably should) just make it 0;

a 32-bit "snapshot length" field;

a 32-bit "link layer type" field.

The magic number has the value hex a1b2c3d4. All the fields can be
written in either big-endian or little-endian format; the magic number
is one of those fields, so the program reading the file (tcpdump,
Ethereal, whatever) can infer from that fields value, when it reads it,
whether the file was written in the same byte order as the native byte
order of the machine reading the file or in the opposite byte order, and
can byte-swap the values if they're written in the opposite byte order
(both libpcap, the library tcpdump and many other programs use to read
those files, and the library Ethereal and the programs that come with it
use to read the file, do so).

All numbers in the headers are usually written in the byte order of the
processor on whatever device is saving the frames.

The major version number should have the value 2.

The minor version number should have the value 4.

The "time zone offset" and "time stamp accuracy" fields should both be
zero.

The "snapshot length" field should be the maximum number of bytes per
packet that will be captured. If the entire packet is captured, make it
65535; if you only capture, for example, the first 64 bytes of the
packet, make it 64.

The link-layer type depends on the type of link-layer header that the
packets in the capture file have:

0 BSD loopback devices, except for later OpenBSD
1 Ethernet, and Linux loopback devices
6 802.5 Token Ring
7 ARCnet
8 SLIP
9 PPP
10 FDDI
100 LLC/SNAP-encapsulated ATM
101 "raw IP", with no link
102 BSD/OS SLIP
103 BSD/OS PPP
104 Cisco HDLC
105 802.11
108 later OpenBSD loopback devices (with the AF_
value in network byte order)
113 special Linux "cooked" capture
114 LocalTalk

If you need a new type for a new link-layer header, send mail to
tcpdump-workers at tcpdump.org asking for one; do *not* pick one yourself,
as you may pick one that's already in use, or reserved for future use.

Immediately following that header are the actual frames.

Each frame consists of a frame header followed by the raw bytes of the
frame.

The frame header consists of:

a time stamp, consisting of:
    (!!NOTES: Mark: 4 bytes here)
a UNIX-format time-in-seconds when the packet was
captured, i.e. the number of seconds since January 1,
1970, 00:00:00 GMT (that's GMT, *NOT* local time!);
    (!!NOTES: Mark: 4 bytes here)
the number of microseconds since that second when the
packet was captured;

a 32-bit value giving the number of bytes of packet data that
were captured;

a 32-bit value giving the actual length of the packet, in bytes
(which may be greater than the previous number, if you're not
saving the entire packet).

All those numbers must be in the same byte order as the numbers in the
file header.

***************************************************************/

So my question is if I prepend my 802.11 frames which i composed earlier by
this file header and each frame by the header it mentions.. will ethereal be
able to decompose the frames?

If there is any better approach to do this, lemme know.

Thanks in advace,


=====================================================================


Example: convert IP packets to libpcap format file

!!NOTES: PCAP binary pseudo code => refer to TSParser
    // prepare pcap_header
unsigned char pcap_header[24];
pcap_header[0] = 0xD4; // magic number = 0xA1B2C3D4
pcap_header[1] = 0xC3;
pcap_header[2] = 0xB2;
pcap_header[3] = 0xA1;
pcap_header[4] = 0x02; // major version number, must be 2
pcap_header[5] = 0x00;
pcap_header[6] = 0x04; // minor version number, must be 4
pcap_header[7] = 0x00;
pcap_header[8] = 0x00; // time zone offset
pcap_header[9] = 0x00;
pcap_header[10] = 0x00;
pcap_header[11] = 0x00;
pcap_header[12] = 0x00; // time stamp accuracy
pcap_header[13] = 0x00;
pcap_header[14] = 0x00;
pcap_header[15] = 0x00;
pcap_header[16] = 0xFF; // snapshot field
pcap_header[17] = 0xFF;
pcap_header[18] = 0x00;
pcap_header[19] = 0x00;
pcap_header[20] = 0x01; // link layer type field, 0x01 => Ethernet
pcap_header[21] = 0x00;
pcap_header[22] = 0x00;
pcap_header[23] = 0x00;
    // prepare frame_header
unsigned char fake_frame_header[16];
fake_frame_header[0] = 0xB8; // 0x43D10BB8 seconds since 1970, 0:0:0 GMT
fake_frame_header[1] = 0x0B;
fake_frame_header[2] = 0xD1;
fake_frame_header[3] = 0x43;
fake_frame_header[4] = 0x95; // 0x000CCC95 microseconds when captured
fake_frame_header[5] = 0xCC;
fake_frame_header[6] = 0x0C;
fake_frame_header[7] = 0x00;
    // prepare ethernet_header
unsigned char fake_ethernet_header[14];
fake_ethernet_header[0] = 0x01; // destination
fake_ethernet_header[1] = 0x00;
fake_ethernet_header[2] = 0x5E;
fake_ethernet_header[3] = 0x06;
fake_ethernet_header[4] = 0x07;
fake_ethernet_header[5] = 0x0B;
fake_ethernet_header[6] = 0x00; // source
fake_ethernet_header[7] = 0x14;
fake_ethernet_header[8] = 0x22;
fake_ethernet_header[9] = 0xB0;
fake_ethernet_header[10] = 0xB1;
fake_ethernet_header[11] = 0x63;
    // Type
if (isIPV4) {
fake_ethernet_header[12] = 0x08; // 0x0800 -> ipv4
fake_ethernet_header[13] = 0x00;
} else if (isIPV6) {
fake_ethernet_header[12] = 0x86; // 0x86DD ->ipv6
fake_ethernet_header[13] = 0xDD;
}
    for (int i = 0; i < IP_PACKET_DATA_COUNT; ++i) {
        if (i == 0) {
// WRITE libpcap header first to file
fwrite(pcap_header, 1, 24, pFileToWrite);

}
         // add frame header ==> ethernet header length + ip:total_length
unsigned long frame_header_len = 14(ETHERNET-HEADER-LEN) + <IP-TOTAL-LENGTH>;
         // # of packet bytes
*((unsigned long*)(fake_frame_header + 8)) = frame_header_len;
// the actual length of packets in bytes
*((unsigned long*)(fake_frame_header + 12)) = frame_header_len;
         fwrite(fake_frame_header, 1, 16, pFileToWrite);
         // add ethernet header
fwrite(fake_ethernet_header, 1, 14, pFileToWrite);

// add ip header + payload
fwrite(<IP-PACKET-START-ADDRESS>, 1, IP-TOTAL-LENGTH, pFileToWrite);
    }
fclose(pFileToWrite);

沒有留言: