views:

173

answers:

1

Hello,

I have a small function that tries to print the fragment offset of an IP header.

ParseIpHeader(unsigned char *packet, int len)
{
    struct ethhdr *ethernet_header;
    struct iphdr *ip_header;

    /* First Check if the packet contains an IP header using
       the Ethernet header                                */

    ethernet_header = (struct ethhdr *)packet;

    if(ntohs(ethernet_header->h_proto) == ETH_P_IP)
    {
            /* The IP header is after the Ethernet header  */

            if(len >= (sizeof(struct ethhdr) + sizeof(struct iphdr)))
            {
                    ip_header = (struct iphdr*)(packet + sizeof(struct ethhdr));

                    /* print the Source and Destination IP address */

                    //printf("Dest IP address: %s\n", inet_ntoa(ip_header->daddr));
                    //printf("Source IP address: %s\n", inet_ntoa(ip_header->saddr));
                    printf("protocol %d\n", ip_header->protocol);
                    printf("Fragment off is %d\n", ntohs(ip_header->frag_off));

            }

}

My packets are TCP (the ip_header->protocol is always 6. the problem is that the frag_off is always 16384. I am sending a lot of data, why the frag_off is always constant?

Thanks.

+3  A: 

Fragment offset is shared with flags. You have the "DF" (don't fragment) bit set.

Which gives you 16384 for the entire 16-bit field, given the fragment offset of 0.

Take a look at the http://www.ietf.org/rfc/rfc791.txt, starting from page 10.

EDIT:

The DF bit in the TCP segments that you are receiving is set by the remote side, to perform the Path MTU discovery - in a nutshell, to try to avoid the fragmentation. In this case the sending side learns the biggest MTU that the overall path can handle, and chops the TCP segments such that they did not exceed it after the encapsulation into IP.

EDIT2:

regarding the use of recvfrom() and TCP: TCP is a connection-oriented protocol, and all of the segmentation/fragmentation details are already handled by it (fragmentation is obviously handled by the lower layer, IP) - so you do not need to deal with it. Anything you write() on the sending side will be eventually read() on the other side - possibly not in the same chunks though - i.e. two 4K writes may result in a single 8K read sometimes, and sometimes in two 4K reads - depending on the behaviour of the media inbetween concerning reordering/losses.

IP Fragmentation and reassembly is handled transparently by the operating system, so you do not need to worry about it, same as about packets out of order, etc. (you will just see the decreased performance as the effect on the application).

One good read I could recommend is this one: UNIX network programming. Given Steven's involvement with the TCP, it's a good book no matter which OS you use.

EDIT3:

And if you are doing something to be a "man in the middle" (assuming you have good and legitimate reasons for doing so :-) - then you can assess the upcoming work by looking at the prior art: chaosreader (one-script approach that works on pcap files, but adaptable to something else), or LibNIDS - that does emulate the IP defragmentation and the TCP stream reassembly; and maybe just reuse them for your purposes.

Andrew Y
cateof
Since the flags occupy the three most significant bits, the check above in fact checks that this packet is not fragmented at all (offset is zero and MF (more fragments) is not set). In any case this mask of 0x3fff would remove the DF, that is set by the remote side (default on most of the systems, to perform Path MTU discovery).
Andrew Y
Thanks Andrew. So what kind of code do I need to see if this is the first fragment or not?
cateof
If you only need to know fragment offset, then you'd mask away the 3 bits of flags by using the 0x1fff as the mask. Though would be interesting to know what you plan to do with this - merely knowing something is a first fragment might or might not be sufficient. I.e. if you assume that the TCP header always fits into the first fragment - in case of malicious/buggy implementations on the other side it will not be a correct assumption.
Andrew Y
OK. Assume that I have an echo server that sends lines of text. I am sniffing the wire.The first packet contains the text "Hello ... " and a few moments later comes a new packet with the text " ... world". How to I know that the second packet that comes after the first packet is the next packet? I want to concatenate them in order to create buf="hello ... world".
cateof
So, the question is whether you are sniffing the wire or you are the client on the other side using the sockets API ?
Andrew Y
I am actually using raw sockets. len = recvfrom(raw, packet_buffer, 5000, 0, ...); how do i know that the package is completely received?
cateof
uh. if you are using raw sockets, then there is **a lot** more work besides the full IP reassembly, TCP state machine handling, etc. But take a look at my 3rd edit and see if that is something that might suit you - you can study the source of these to see what you're up for :-)
Andrew Y
tomlogic