IP datagrams represent data to be routed.
They store informations like IP source and destination address.
Inside an iphdr struct is defined, allowing us to create a custom ip header. (More detailed information about IP header here)


struct iphdr

iphdr.ihl //[4 bit] Internet Header Length, contains the header length measured in 32 bit words.
iphdr.version //[4 bit] Datagram version. ipv4 version’s 4.
iphdr.tos //[8 bit] Type of service (we won’t use it).
iphdr.tot_len //[16 bit] Datagram total length in byte.
iphdr.id //[16 bit] Used on router fragmentation.
iphdr.frag_off//[3 bit] Fragmentation controls.
iphdr.ttl //[8 bit] Time to live, or max hops allowed before datagramm destruction.
iphdr.protocol //[8 bit] Payload protocol identifier  (6->TCP, 17->UDP, 1->ICMP …).
iphdr.check //[16 bit] Header checksum (16-bit checksum RFC1071).
iphdr.saddr //[32 bit] IP source address
iphdr.daddr //[32 bit] IP destination address

Now let’s define some usefull functions for future use:

int createIpv4Header(Iphdr* buffer, char * srcAddress, char * dstAddress, u_int8_t ttl);
void setPayloadInfo(Iphdr* ipheader, int payloadLength, u_int8_t protocolType);
Time for funny testing!
Editing the previous post code, we can create a function testIP(char* src, char* dest) able to send an empty datagram ip to a custom destination from a custom source.
So we initialize the buffer:

int length = createIpv4Header(ipheader, sourceAddress, destinationAddress, 100);
setPayloadInfo(ipheader, 0, 1);

Calling setPayloadInfo we are setting a ICMP protocol with 0 length (obviously that would be a malformed datagram, but now we want only to test the IP behaviour).
Now let’s call the testIP function inside a main(), with parameters (“”, “”).

Now let’s open our favourite traffic analyzer (like wireshark) and enable capturing on lo (loopback interface, or We’ll be able to see our little datagram :).

$ sudo ./test_ip

We will see on wireshark something like that:

We do it!

Here the code: