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.

顯示具有 ipv4 標籤的文章。 顯示所有文章
顯示具有 ipv4 標籤的文章。 顯示所有文章

2008年2月20日 星期三

IPv4 header introduction

[IPv4]

Reference

MAC header IP header Data :::

IP header:

00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
Version IHL TOS Total length
Identification Flags Fragment offset
TTL Protocol Header checksum
Source IP address
Destination IP address
Options and padding :::

!!NOTES:

1) Real_Fragment_Offset = Fragment_Offset x 8

2) Identification and MF_in_Flags, and Fragment_Offset are used to assemble fragmented IP packets.

3) checksum in C code (ps: checksum field has to be set to 0 first)

typedef unsigned short u16;
typedef unsigned char u8;
typedef unsigned long u32;

//!!NOTES:
// before ip checksum is calculated,
// the IP_Header::Checksum should be 0
u16 ip_sum_calc(u16 len_ip_header, u8 buff[])
{
u16 word16;
u32 sum=0;
u16 i;

// make 16 bit words out of every two adjacent 8 bit words in the packet
// and add them up
for (i=0;i<len_ip_header;i=i+2){
word16 =((buff[i]<<8)&0xFF00)+(buff[i+1]&0xFF);
sum = sum + (u32) word16;
}

// take only 16 bits out of the 32 bit sum and add up the carries
while (sum>>16)
sum = (sum & 0xFFFF)+(sum >> 16);

// one's complement the result
sum = ~sum;

return ((u16) sum);
}

重點整理 -- 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);