Thursday 7 November 2013

Walkthrough. Part 3

Getting to know finer details....end of Week 5


Ankur - RFCs are so difficult to read.

Charitha - The IPv6 - IPv4 packet translation that is implemented by tayga is according to the RFC 6145. It defines how the IP header is translated for ICMP, TCP and UDP packets.

Ankur - Now Time to define and move step by step about what we are going to do in the project

Charitha - Lets keep our goal simple initial work at tranport layer then move up the stack.

Ankur - so We need to map many IPv6 to one IPv4 system (in genral n to m mapping) Some how we need to maintain the mapping .Better way would be extracting the port number in tcp segment + IPv6 address –> mapped to new port number generated by us + IPv4 address

Charitha - Yup got it we maintain a list of values

Our Binding Information Base of IP addresses would look like this.

IPv6
Port
IPv4
New Port
2001:db8:1:ffff::1
12345
192.255.0.1
23456
2001:db8:1:ffff::3
80
192.255.0.1
34568
2001:db8:1:2010::1
80
192.255.0.1
27890


Ankur : exactly,We can have Port numbers included in the cache structure which currently now maintains one to one mapping.  

Walkthrough. Part 2

Getting to know finer details....end of Week 5

Charitha - Long time since we have updated the blog.

Ankur - Yes, analyzing the code, we totally forget about updating the blog.
C code is implemented here with great expertise. Even the simple list implementation uses Macros, which is quite interesting.

Charitha - Yes, saw through it.

#define list_entry(x, TYPE, FIELD) \
({ \
      const typeof( ((type *)0)->field ) *__mptr = (x); \
      (type *)( (char *)__mptr - offsetof(type, field) ); \
})

This gets a pointer to the object containing x of type TYPE. This is something new.

Ankur - Lets get back to where we stopped i.e read_from_tun(). Once the tun driver gets the packet, the stream is filled into "recv_buf" buffer. This stream is defined by structure below for IPv6, IPv4 and ICMP. 

     struct 
     {
            struct tun_pi pi;
            struct ip6 ip6;
            struct ip6_frag ip6_frag;
     } __attribute__ ((__packed__)) header;

   OR

   struct
   {
           struct tun_pi pi;
           struct ip4 ip4;
   } __attribute__ ((__packed__)) header;

  OR

  struct
   {
           struct tun_pi pi;
           struct ip4 ip4; or struct ip6 ip6;
           struct icmp icmp;
   } __attribute__ ((__packed__)) header;
         

Tun driver adds its own header to the packet received. Hence it has to be excluded while taking the packet for conversion. 

     data_len = ret - sizeof(struct tun_pi);
     where 
             struct tun_pi is the header Tun driver adds to the packet it receives. 
             ret = length of recv_buf.

After this, depending on the request, IPv4 or IPv6 handle function is called which gets the packet for manipulation.
      handle_ip6(struct pkt *) or  handle_ip4(struct pkt *) 
This is where all the parsing ,check summing, checking of TTL(time to live) and translation is taken care of by calling appropriate function.

Charitha - Great !! Now concentrating on the function xlate_4to6_data(struct pkt *) or xlate_6to4_data(struct pkt *), which does the main translation.
And what is  __attribute__ ((__packed__)) header? This is something new.

Ankur - Oh ya, as we know structure definition basically has padding embedded into it and hence sizeof will not always be the same sum member size. Well, "__attribute__ ((__packed__)" doesn't allow padding.

Charitha - Now moving on.
Above mentioned function creates a cache entry where the mapping of IPv4 and IPv6 addresses are stored. 

But as we know this project aims to make NAT64 stateful, we need to store some extra information about the mapping, which is the port number of TCP or UDP packet.

Ankur - Exactly, Next we will look at what needs to be done to accommodate port numbers as part of the mapping and how the translation happens.