src/internet-stack/ipv4-netfilter.cc
author Qasim Javed <qasimj@gmail.com>
Thu Aug 06 01:55:49 2009 +0600 (2009-08-06)
changeset 4638 19aa5f9b4bdf
parent 4637 0882bb6eac0b
permissions -rw-r--r--
Source NAT working! Run (examples/netfilter-example.cc)
     1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
     2 /* 
     3  * Copyright (c) 2009 University of Texas at Dallas
     4  * 
     5  * This program is free software; you can redistribute it and/or modify
     6  * it under the terms of the GNU General Public License version 2 as
     7  * published by the Free Software Foundation;
     8  *
     9  * This program is distributed in the hope that it will be useful,
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12  * GNU General Public License for more details.
    13  *
    14  * You should have received a copy of the GNU General Public License
    15  * along with this program; if not, write to the Free Software
    16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    17  * 
    18  * Author: Qasim Javed <qasim@utdallas.edu>
    19  */
    20 #include "ns3/log.h"
    21 #include "ns3/uinteger.h"
    22 #include "ipv4-netfilter.h"
    23 #include "ip-conntrack-info.h"
    24 #include "ipv4-conntrack-l3-protocol.h"
    25 #include "tcp-conntrack-l4-protocol.h"
    26 #include "udp-conntrack-l4-protocol.h"
    27 #include "icmpv4-conntrack-l4-protocol.h"
    28 #include "tcp-header.h"
    29 #include "udp-header.h"
    30 
    31 NS_LOG_COMPONENT_DEFINE ("Ipv4Netfilter");
    32 
    33 namespace ns3 {
    34 
    35 NS_OBJECT_ENSURE_REGISTERED (Ipv4Netfilter);
    36 
    37 TypeId 
    38 Ipv4Netfilter::GetTypeId (void)
    39 {
    40   static TypeId tId = TypeId ("ns3::Ipv4Netfilter")
    41     .SetParent<Object> ()
    42     .AddAttribute ("EnableNat", "0 disbales NAT and is the default, 1 enabled NAT",
    43                    UintegerValue (0),
    44                    MakeUintegerAccessor (&Ipv4Netfilter::m_enableNat),
    45                    MakeUintegerChecker <uint8_t> ())
    46     ;
    47 
    48   return tId;
    49 }
    50   
    51 Ipv4Netfilter::Ipv4Netfilter ()
    52   : m_enableNat (0)
    53 {
    54   NS_LOG_FUNCTION_NOARGS();
    55 
    56   /* Create callback chains for all of the hooks */
    57   for (int i=0; i < NF_INET_NUMHOOKS; i++)
    58     m_netfilterHooks[i] = NetfilterCallbackChain ();
    59 
    60   /* Create and register Ipv4 connection tracking module */
    61   Ptr<Ipv4ConntrackL3Protocol> ipv4 = Create<Ipv4ConntrackL3Protocol> ();
    62   this->RegisterL3Protocol (ipv4);
    63   
    64   /* Create and register TCP connection tracking module */
    65   Ptr<TcpConntrackL4Protocol> tcp = Create<TcpConntrackL4Protocol> ();
    66   this->RegisterL4Protocol (tcp);
    67   
    68   /* Create and register UDP connection tracking module */
    69   Ptr<UdpConntrackL4Protocol> udp = Create<UdpConntrackL4Protocol> ();
    70   this->RegisterL4Protocol (udp);
    71   
    72   /* Create and register ICMP connection tracking module */
    73   Ptr<Icmpv4ConntrackL4Protocol> icmpv4 = Create<Icmpv4ConntrackL4Protocol> ();
    74   this->RegisterL4Protocol (icmpv4);
    75   
    76   //Ptr <NetworkAddressTranslation> networkAddressTranslation = Create<NetworkAddressTranslation> (this);
    77 
    78   /* Create and register hook callbacks */
    79   NetfilterHookCallback preRouting = MakeCallback (&Ipv4Netfilter::NetfilterConntrackIn, this);
    80   NetfilterHookCallback localIn = MakeCallback (&Ipv4ConntrackL3Protocol::Ipv4Confirm, PeekPointer (ipv4));
    81 
    82   Ipv4NetfilterHook nfh = Ipv4NetfilterHook (1, NF_INET_PRE_ROUTING, NF_IP_PRI_CONNTRACK , preRouting); 
    83   Ipv4NetfilterHook nfh1 = Ipv4NetfilterHook (1, NF_INET_LOCAL_OUT, NF_IP_PRI_CONNTRACK, preRouting); 
    84   Ipv4NetfilterHook nfh2 = Ipv4NetfilterHook (1, NF_INET_POST_ROUTING, NF_IP_PRI_CONNTRACK_CONFIRM, localIn); 
    85   Ipv4NetfilterHook nfh3 = Ipv4NetfilterHook (1, NF_INET_LOCAL_IN, NF_IP_PRI_CONNTRACK_CONFIRM, localIn); 
    86   
    87   this->RegisterNetfilterHook (nfh);
    88   this->RegisterNetfilterHook (nfh1);
    89   this->RegisterNetfilterHook (nfh2);
    90   this->RegisterNetfilterHook (nfh3);
    91 
    92   if (m_enableNat)
    93     EnableNat ();
    94 
    95   nextAvailablePort = 1024;
    96 }
    97 
    98 uint32_t 
    99 Ipv4Netfilter::RegisterNetfilterHook (Ipv4NetfilterHook hook)
   100 {
   101   //NS_LOG_FUNCTION (this << hook);
   102   m_netfilterHooks[hook.GetHookNumber ()].Insert (hook);
   103   return 0;
   104 }
   105 
   106 uint32_t 
   107 Ipv4Netfilter::UnRegisterNetfilterHook (Ipv4NetfilterHook& hook)
   108 {
   109   m_netfilterHooks[hook.GetHookNumber ()].Remove (hook);
   110   return 0;
   111 }
   112 
   113 uint32_t 
   114 Ipv4Netfilter::ProcessHook(uint8_t protocolFamily, Hooks_t hookNumber, Ptr<Packet> p, 
   115                            Ptr<NetDevice> in, Ptr<NetDevice> out, 
   116                            ContinueCallback ccb)
   117 {
   118   return m_netfilterHooks[(uint32_t)hookNumber].IterateAndCallHook (hookNumber, p, in, out, ccb);
   119 }
   120 
   121 uint32_t 
   122 Ipv4Netfilter::RegisterL3Protocol(Ptr<NetfilterConntrackL3Protocol> l3Protocol)
   123 {
   124   //m_netfilterConntrackL3Protocols.push_back(l3Protocol);
   125   m_netfilterConntrackL3Protocols = l3Protocol;
   126   return 0;
   127 }
   128 
   129 uint32_t 
   130 Ipv4Netfilter::RegisterL4Protocol(Ptr<NetfilterConntrackL4Protocol> l4Protocol)
   131 {
   132   m_netfilterConntrackL4Protocols.push_back(l4Protocol);
   133   return 0;
   134 }
   135 
   136 Ptr<NetfilterConntrackL3Protocol> 
   137 Ipv4Netfilter::FindL3ProtocolHelper (uint8_t protocolFamily)
   138 {
   139   /*Ptr<NetfilterConntrackL3Protocol>::iterator it;
   140 
   141   for (; it != netfilerConntrackL3Protocols.end(); it++)
   142   {
   143     if (protocolFamily == it->protocol)
   144       return *it;
   145   }*/
   146 
   147   return m_netfilterConntrackL3Protocols;
   148 
   149 }
   150 
   151 Ptr<NetfilterConntrackL4Protocol> 
   152 Ipv4Netfilter::FindL4ProtocolHelper (uint8_t protocol)
   153 {
   154   std::vector<Ptr<NetfilterConntrackL4Protocol> >::iterator it;
   155 
   156   for (it =  m_netfilterConntrackL4Protocols.begin (); it != m_netfilterConntrackL4Protocols.end (); it++)
   157   {
   158     NS_LOG_DEBUG ( "L4 protocol: " << (*it)->GetL4Protocol () << ", This protocol : "<<(int)protocol );
   159     if ((*it)->GetL4Protocol () == protocol) {
   160       NS_LOG_DEBUG ( "Found protocol " <<(int)protocol );
   161       return *it;
   162     }
   163   }
   164 
   165   return NULL;
   166 }
   167 
   168 int 
   169 Ipv4Netfilter::UpdateConntrackInfo (uint8_t info)
   170 {
   171   m_hash[currentOriginalTuple].SetInfo (info);
   172   m_hash[currentReplyTuple].SetInfo (info);
   173   return 0;
   174 }
   175 
   176 bool 
   177 Ipv4Netfilter::NetfilterConntrackGetTuple (Ptr<Packet> packet, uint16_t l3Number, uint8_t protocolNumber, 
   178                NetfilterConntrackTuple& tuple, Ptr<NetfilterConntrackL3Protocol> l3Protocol, 
   179                Ptr<NetfilterConntrackL4Protocol> l4Protocol)
   180 {
   181   tuple.SetProtocol (l3Number);
   182 
   183   if (l3Protocol->PacketToTuple (packet, tuple) == false)
   184     return false;
   185 
   186   //TODO: Do we really need the Protocol Family as well?
   187   //tuple->Set
   188   Ipv4Header ipHeader;
   189   NS_LOG_DEBUG (" :: Remove Ipv4 Header :: ");
   190   packet->RemoveHeader (ipHeader);
   191   
   192   tuple.SetDirection (IP_CT_DIR_ORIGINAL);
   193   
   194   if (l4Protocol->PacketToTuple (packet, tuple) == false)
   195     return false;
   196   
   197   NS_LOG_DEBUG (" :: Add Ipv4 Header :: ");
   198   packet->AddHeader (ipHeader);
   199 
   200   return true;
   201 }
   202 
   203 TupleHashI
   204 Ipv4Netfilter::NewConnection (NetfilterConntrackTuple& tuple, Ptr<NetfilterConntrackL3Protocol> l3proto, 
   205                              Ptr<NetfilterConntrackL4Protocol> l4proto, Ptr<Packet> packet)
   206 {
   207   NS_LOG_FUNCTION ( this << packet );
   208 
   209   NetfilterConntrackTuple replyTuple;
   210 
   211   if (!InvertTuple (replyTuple, tuple, l3proto, l4proto))
   212     return m_hash.end ();
   213 
   214   // Invoke l4proto->New
   215 
   216   // Find expectatons here
   217 
   218   NS_LOG_DEBUG (":: Creating an unconfirmed entry for this tuple ::");
   219   m_unconfirmed[tuple] = IpConntrackInfo ();
   220  
   221   TupleHashI it = m_unconfirmed.find (tuple);
   222   
   223   return it;
   224 }
   225 
   226 uint32_t 
   227 Ipv4Netfilter::ResolveNormalConntrack (Ptr<Packet> packet, uint32_t protocolFamily, uint8_t protocol, 
   228                Ptr<NetfilterConntrackL3Protocol> l3Protocol, Ptr<NetfilterConntrackL4Protocol> l4Protocol, 
   229                int& setReply, ConntrackInfo_t& ctInfo, Ipv4Header ipHeader)
   230 {
   231   NS_LOG_FUNCTION (this << packet);
   232   //NetfilterConntrackTuple tuple (ipHeader.GetSource(), 0, ipHeader.GetDestination(), 0);
   233   NetfilterConntrackTuple tuple;
   234   uint8_t conntrackInfo = 0;
   235   
   236   /* Get a tuple from the information in the packet */
   237   if (!NetfilterConntrackGetTuple (packet, protocolFamily, protocol, tuple, l3Protocol, l4Protocol))
   238   {
   239     NS_LOG_DEBUG ("Cannot create a tuple from the packet");
   240     return -1;
   241   }
   242   
   243   TupleHashI it = m_hash.find (tuple);
   244 
   245   if (it == m_hash.end ())
   246   {
   247     NS_LOG_DEBUG ("No tuple found");
   248     //TupleHashI newIt = NewConnection(tuple, l3Protocol, l4Protocol, packet);
   249     it = NewConnection (tuple, l3Protocol, l4Protocol, packet);
   250   }
   251   
   252   NetfilterConntrackTuple replyTuple;
   253 
   254   if (!InvertTuple (replyTuple, tuple, l3Protocol, l4Protocol))
   255     return -1;
   256     
   257   currentOriginalTuple = tuple;
   258   currentReplyTuple = replyTuple;
   259 
   260   /* TODO: Add a pointer to the hashed tuple in IpConntrackInfo()
   261    * and store these tuples somehwere, when you destruct then you
   262    * you have to take care of the tuples stored in the vector as 
   263    * well 
   264    */
   265   if ((it->first).GetDirection () == (uint8_t)IP_CT_DIR_REPLY)
   266   {
   267     NS_LOG_DEBUG (":: **** This is a REPLY *** ::");
   268     conntrackInfo = IP_CT_ESTABLISHED + IP_CT_IS_REPLY;
   269     setReply = 1;
   270   } else {
   271     NS_LOG_DEBUG (":: Packet is in the original direction ::");
   272     if ( m_hash[tuple].GetStatus () & IPS_SEEN_REPLY) {
   273       NS_LOG_DEBUG (":: Connection ESTABLISHED! ::");
   274       conntrackInfo = IP_CT_ESTABLISHED;
   275     }
   276     else {
   277       NS_LOG_DEBUG (":: New connection :: ");
   278       conntrackInfo = IP_CT_NEW;
   279     }
   280 
   281   }
   282 
   283   m_unconfirmed[tuple].SetInfo (conntrackInfo);
   284   //UpdateConntrackInfo (conntrackInfo);
   285   /*NS_LOG_DEBUG ("Adding the conntrack packet tag" );
   286   ConntrackTag ctTag;
   287   bool tagFound = packet->PeekPacketTag (ctTag);
   288 
   289   if (!tagFound)
   290     packet->AddPacketTag (ConntrackTag (conntrackInfo));
   291   else
   292     NS_LOG_DEBUG ("Tag already present");
   293     */
   294 
   295   return NF_ACCEPT;
   296 
   297 }
   298 
   299 uint32_t 
   300 Ipv4Netfilter::NetfilterConntrackIn (Hooks_t hook, Ptr<Packet> packet, Ptr<NetDevice> in, 
   301                                     Ptr<NetDevice> out, ContinueCallback& ccb)
   302 {
   303   NS_LOG_DEBUG ("::: Executing Hook Function :::");
   304   int setReply=0;
   305   ConntrackInfo_t ctInfo;
   306   /* If this packet has been seen previously, Ignore. */
   307 
   308   /* Find layer 3 helper for this packet */
   309   Ptr<NetfilterConntrackL3Protocol> l3proto = FindL3ProtocolHelper (1);
   310 
   311   Ipv4Header ipHeader;
   312 
   313   packet->PeekHeader (ipHeader);
   314 
   315   NS_LOG_DEBUG ( "IP header protocol: " << (int)ipHeader.GetProtocol ());
   316   
   317   Ptr<NetfilterConntrackL4Protocol> l4proto = FindL4ProtocolHelper (ipHeader.GetProtocol ());
   318 
   319   /*if (l4proto != NULL) {
   320   }*/
   321 
   322   ResolveNormalConntrack (packet, 1 /* PF */, ipHeader.GetProtocol (), l3proto, l4proto, setReply, ctInfo, ipHeader);
   323 
   324   // Call layer 4 Packet callback
   325   //uint32_t ret = l4proto->packet(packet, protocolFamily, hookNumber);
   326 
   327   if (setReply)
   328   {
   329     NS_LOG_DEBUG ("Setting IPS_SEEN_REPLY");
   330     m_hash[currentOriginalTuple].SetStatus ( IPS_SEEN_REPLY );
   331     m_hash[currentReplyTuple].SetStatus ( IPS_SEEN_REPLY );
   332   }
   333 
   334   return NF_ACCEPT;
   335 
   336 }
   337 
   338 uint32_t
   339 Ipv4Netfilter::NetfilterConntrackConfirm (Ptr<Packet> packet)
   340     //, NetfilterConntrackTuple& orig,
   341      //          NetfilterConntrackTuple& reply)
   342 {
   343   NS_LOG_FUNCTION ( this << packet );
   344   /* If this packet has been seen previously, Ignore. */
   345 
   346   /* Find layer 3 helper for this packet */
   347   /*Ptr<NetfilterConntrackL3Protocol> l3proto = FindL3ProtocolHelper (1);
   348 
   349     Ipv4Header ipHeader;
   350 
   351   //packet->RemoveHeader(ipHeader);
   352   packet->PeekHeader (ipHeader);
   353 
   354   NS_LOG_DEBUG ( "IP header protocol: " << (int)ipHeader.GetProtocol ());
   355 
   356   Ptr<NetfilterConntrackL4Protocol> l4proto = FindL4ProtocolHelper (ipHeader.GetProtocol ());
   357 
   358   NetfilterConntrackTuple orig;*/
   359 
   360   /* Get a tuple from the information in the packet */
   361   /*if (!NetfilterConntrackGetTuple (packet, 1, ipHeader.GetProtocol (), orig, l3proto, l4proto))
   362     {
   363     NS_LOG_DEBUG ("Cannot create a tuple from the packet");
   364     return -1;
   365     }
   366 
   367     NetfilterConntrackTuple reply;
   368 
   369 
   370     InvertTuple (reply, orig, l3proto, l4proto);
   371 
   372     currentOriginalTuple = orig;
   373     currentReplyTuple = reply;
   374 
   375     NS_LOG_DEBUG ("Current Original Tuple: " << currentOriginalTuple.GetSource () << ", " << currentOriginalTuple.GetDestination ());
   376     NS_LOG_DEBUG ("Current Reply Tuple: " << currentReplyTuple.GetSource () << ", " << currentReplyTuple.GetDestination ());
   377   //currentTuple[IP_CT_DIR_REPLY] = reply;*/
   378 
   379   /**************************/
   380 
   381   /*ConntrackTag ctTag;
   382 
   383     if (!packet->PeekPacketTag (ctTag))
   384     {
   385     NS_LOG_DEBUG ("ConntrackTag not found");
   386     return 0;
   387     }
   388     else {
   389     if ( CTINFO2DIR (ctTag.GetConntrack ()) != IP_CT_DIR_ORIGINAL)
   390     return 0;
   391 
   392     if (m_hash.find (orig) != m_hash.end () && m_hash.find (reply) != m_hash.end () )
   393     {
   394     NS_LOG_DEBUG ("Entries already present!");
   395     return NF_DROP;
   396     }
   397 
   398     NS_LOG_DEBUG ("Creating confirmed hash entries");
   399   //m_hash[orig] = IpConntrackInfo().SetStatus(IPS_CONFIRMED);
   400   m_hash[orig] = IpConntrackInfo ();
   401   m_hash[reply] = IpConntrackInfo ();
   402 
   403   }*/
   404 
   405   if ( CTINFO2DIR (m_unconfirmed[currentOriginalTuple].GetInfo ()) != IP_CT_DIR_ORIGINAL) 
   406   {
   407     NS_LOG_DEBUG ("Not a packet in the original direction");
   408     return NF_ACCEPT;
   409   }
   410 
   411   /*if (m_hash.find (currentOriginalTuple) != m_hash.end () && m_hash.find (currentReplyTuple) != m_hash.end () )
   412   {
   413     NS_LOG_DEBUG ("Entries already present!");
   414     return NF_DROP;
   415   }*/
   416 
   417   NS_LOG_DEBUG ("Creating confirmed hash entries");
   418   m_hash[currentOriginalTuple] = m_unconfirmed[currentOriginalTuple];
   419   m_hash[currentReplyTuple] = m_unconfirmed[currentOriginalTuple];
   420 
   421   return 0;
   422 }
   423     
   424 uint32_t 
   425 Ipv4Netfilter::NetfilterDoNat (Hooks_t hookNumber, Ptr<Packet> p, 
   426                                Ptr<NetDevice> in, Ptr<NetDevice> out, ContinueCallback& ccb)
   427 {
   428   NS_LOG_FUNCTION ( this << p );
   429   /*ConntrackTag ctTag;
   430 
   431   bool found = p->PeekPacketTag (ctTag);
   432 
   433   if (!found)
   434   {
   435     NS_LOG_DEBUG ("Conntrack tag not found");
   436     return NF_ACCEPT;
   437   }*/
   438 
   439   /* Conntrack has a higher priority so currentOriginalTuple and
   440    * currentReply tuple should always be correct 
   441    */
   442 
   443   //std::vector<NatRule>::iterator it = FindNatDevice (out);
   444 
   445   /*if (it == m_natRules.end ())
   446   {
   447     NS_LOG_DEBUG ("No NAT rule for device " << out->GetId ());
   448     return NF_ACCEPT;
   449   }*/
   450         
   451   NS_LOG_DEBUG ("Current Original Tuple: " << currentOriginalTuple.GetSource () << ", " << currentOriginalTuple.GetDestination ());
   452   NS_LOG_DEBUG ("Current Reply Tuple: " << currentReplyTuple.GetSource () << ", " << currentReplyTuple.GetDestination ());
   453 
   454   NS_LOG_DEBUG ("ConntrackInfo: " << (uint16_t)m_unconfirmed[currentOriginalTuple].GetInfo () );
   455 
   456   /* TODO: Why are you checking m_hash here when the info is in
   457    * m_unconfirmed. This could be a problem because NAT is sandwiched
   458    * between conntrack hook callbacks 
   459    */
   460   switch (m_unconfirmed[currentOriginalTuple].GetInfo ())
   461   {
   462     case IP_CT_RELATED:
   463     case IP_CT_RELATED + IP_CT_IS_REPLY:
   464       /* This should be updated when "expectations" are added */
   465       break;
   466 
   467     case IP_CT_NEW:
   468 
   469       if ( hookNumber == NF_INET_POST_ROUTING )
   470       {
   471         NS_LOG_DEBUG ("SRC_NAT: New Connection encountered");
   472 
   473         TupleHashI it;
   474 
   475 
   476         if ( (it = m_hash.find (currentOriginalTuple)) != m_hash.end ())
   477         {
   478           if ( !((it->second).GetStatus () & IPS_SRC_NAT_DONE) )
   479           {
   480             /* Get a unique tuple and create a mapping */
   481 
   482             NS_LOG_DEBUG ("Doing rule lookup at device " << out->GetIfIndex ());
   483             std::vector<NatRule>::iterator it = 
   484               FindNatRule ( Ipv4Address (currentOriginalTuple.GetSource ()), out );
   485 
   486             if ( it == m_natRules.end () )
   487             {
   488               NS_LOG_DEBUG ("No rule matched!");
   489               return NF_ACCEPT;
   490             }
   491                                     
   492             NS_LOG_DEBUG ("Creating a NAT mapping");
   493 
   494             /* Create a NULL mapping, which does not contain port numbers */
   495             NetfilterConntrackTuple mapping = 
   496               NetfilterConntrackTuple (it->GetMangledSource (), nextAvailablePort,
   497                                          currentOriginalTuple.GetDestination (), 9);
   498             mapping.SetDirection (IP_CT_DIR_ORIGINAL);
   499             nextAvailablePort++;
   500 
   501             NS_LOG_DEBUG ("Creating a NAT mapping for the tuple " << currentOriginalTuple 
   502                           << ": " << mapping );
   503             m_natMappings[currentOriginalTuple] = mapping;
   504             m_natReplyLookup[mapping] = currentOriginalTuple;
   505           }
   506 
   507   
   508           NS_LOG_DEBUG (":: Translating addresses and fixing IP checksum ::");
   509           NetfilterNatPacket (hookNumber, p);
   510         }
   511         else
   512           NS_LOG_DEBUG ("BUG: currentTuple non-existent in hash!");
   513       }
   514 
   515       break;
   516 
   517     default:
   518       NS_LOG_DEBUG ("SRC_NAT: Connection is established!");
   519       NS_LOG_DEBUG (":: Translating addresses and fixing IP checksum ::");
   520       NetfilterNatPacket (hookNumber, p);
   521   
   522   }
   523 
   524 
   525   return NF_ACCEPT;
   526 }
   527     
   528 bool 
   529 Ipv4Netfilter::InvertTuple (NetfilterConntrackTuple& inverse, NetfilterConntrackTuple& orig,
   530                     Ptr<NetfilterConntrackL3Protocol> l3Protocol,
   531                     Ptr<NetfilterConntrackL4Protocol> l4Protocol)
   532 {
   533   inverse.SetProtocol (orig.GetProtocol ());
   534 
   535   if (!l3Protocol->InvertTuple (inverse, orig))
   536     return false;
   537 
   538   inverse.SetDirection (orig.GetDirection () == IP_CT_DIR_ORIGINAL ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL);
   539   
   540   return l4Protocol->InvertTuple (inverse, orig);
   541 
   542 }
   543     
   544 TupleHash&
   545 Ipv4Netfilter::GetHash ()
   546 {
   547   return m_hash;
   548 }
   549     
   550 void 
   551 Ipv4Netfilter::AddNatRule (NatRule natRule)
   552 {
   553   m_natRules.push_back (natRule);
   554 }
   555 
   556 std::vector<NatRule>::iterator
   557 Ipv4Netfilter::FindNatRule (NatRule natRule)
   558 {
   559   std::vector<NatRule>::iterator it = m_natRules.begin ();
   560 
   561   for ( ; it != m_natRules.end ();  it++)
   562   {
   563     if ( *it == natRule )
   564       return it;
   565   }
   566 
   567   return m_natRules.end ();
   568 }
   569 
   570 std::vector<NatRule>::iterator
   571 Ipv4Netfilter::FindNatRule (Ipv4Address orig, Ptr<NetDevice> out)
   572 {
   573   std::vector<NatRule>::iterator it = m_natRules.begin ();
   574 
   575   NS_LOG_DEBUG ("Number of rules: " << m_natRules.size () );
   576   NS_LOG_DEBUG ("Orig: " << orig );
   577 
   578   for ( ; it != m_natRules.end ();  it++)
   579   {
   580     NS_LOG_DEBUG ("Rule source: " << it->GetOriginalSource () << ", passed in source: " << orig);
   581     NS_LOG_DEBUG ("Rule device: " << it->GetDevice () << ", passed in dev: " << out);
   582     if ( it->GetOriginalSource () == orig && it->GetDevice () == out)
   583     {
   584       NS_LOG_DEBUG ("Rule match found!");
   585       return it;
   586     }
   587   }
   588 
   589   return m_natRules.end ();
   590 }
   591     
   592 void 
   593 Ipv4Netfilter::EnableNat ()
   594 {
   595   m_enableNat = 1;
   596 
   597   NS_LOG_DEBUG (":: Enabling NAT ::");
   598 
   599   NetfilterHookCallback doNat = MakeCallback (&Ipv4Netfilter::NetfilterDoNat, this);
   600 
   601   Ipv4NetfilterHook natCallback1 = Ipv4NetfilterHook (1, NF_INET_POST_ROUTING, NF_IP_PRI_NAT_SRC, doNat); 
   602   Ipv4NetfilterHook natCallback2 = Ipv4NetfilterHook (1, NF_INET_PRE_ROUTING, NF_IP_PRI_NAT_DST, doNat); 
   603   
   604 
   605   this->RegisterNetfilterHook (natCallback1);
   606   this->RegisterNetfilterHook (natCallback2);
   607 }
   608 
   609 uint32_t 
   610 Ipv4Netfilter::NetfilterNatPacket (Hooks_t hookNumber, Ptr<Packet> p)
   611 {
   612   NS_LOG_FUNCTION ( this << p );
   613   Ipv4Header ipHeader;
   614   uint16_t dstPort; //, srcPort;
   615   Ipv4Address dstAddress, srcAddress;
   616 
   617   p->RemoveHeader (ipHeader);
   618 
   619   uint16_t protocol = ipHeader.GetProtocol ();
   620 
   621   if (hookNumber == NF_INET_POST_ROUTING)
   622   {
   623     NetfilterConntrackTuple mapped = m_natMappings[currentOriginalTuple];
   624 
   625     ipHeader.SetSource (mapped.GetSource ());
   626 
   627     if (protocol == IPPROTO_TCP)
   628     {
   629       TcpHeader tcpHeader;
   630 
   631       p->RemoveHeader (tcpHeader);
   632 
   633       tcpHeader.SetSourcePort (mapped.GetSourcePort ());
   634 
   635       p->AddHeader (tcpHeader);
   636 
   637     }
   638     else
   639     {
   640       UdpHeader udpHeader;
   641 
   642       p->RemoveHeader (udpHeader);
   643 
   644       udpHeader.SetSourcePort (mapped.GetSourcePort ());
   645 
   646       p->AddHeader (udpHeader);
   647     }
   648 
   649     p->AddHeader (ipHeader);
   650 
   651     NetfilterConntrackTuple oldOriginalTuple = currentOriginalTuple;
   652 
   653 
   654     currentOriginalTuple = NetfilterConntrackTuple (mapped.GetSource(), mapped.GetSourcePort (),
   655                                                     currentOriginalTuple.GetDestination (),
   656                                                     currentOriginalTuple.GetDestinationPort ());
   657 
   658     currentOriginalTuple.SetDirection (IP_CT_DIR_ORIGINAL);
   659     
   660     currentReplyTuple = NetfilterConntrackTuple (currentOriginalTuple.GetDestination (),
   661                                                   currentOriginalTuple.GetDestinationPort (),
   662                                                   mapped.GetSource (), mapped.GetSourcePort ());
   663     
   664     currentReplyTuple.SetDirection (IP_CT_DIR_REPLY);
   665     
   666     std::cout <<" New Original Tuple: " << currentOriginalTuple << std::endl;
   667     std::cout <<" New Reply Tuple: " << currentReplyTuple << std::endl;
   668 
   669     m_unconfirmed[currentOriginalTuple] = m_unconfirmed[oldOriginalTuple];
   670 
   671   }
   672   else if (hookNumber == NF_INET_PRE_ROUTING)
   673   {
   674     NS_LOG_DEBUG ("Mapping back to LAN address");
   675     //NetfilterConntrackTuple mapped = m_natMappings[currentReplyTuple];
   676     NetfilterConntrackTuple temp = currentReplyTuple;
   677     temp.SetDirection (IP_CT_DIR_ORIGINAL);
   678     TranslationMapI transIt = m_natReplyLookup.find (temp);
   679 
   680     if (transIt == m_natMappings.end ())
   681     {
   682       NS_LOG_DEBUG ("No such mapping found!");
   683       return NF_ACCEPT;
   684     }
   685 
   686     dstPort = (transIt->second).GetSourcePort ();
   687     dstAddress = (transIt->second).GetSource ();
   688   
   689     currentOriginalTuple = NetfilterConntrackTuple ((transIt->second).GetSource (), (transIt->second).GetSourcePort (), dstAddress, dstPort);
   690     currentReplyTuple = NetfilterConntrackTuple (dstAddress, dstPort, (transIt->second).GetSource (), (transIt->second).GetSourcePort ());
   691 
   692     NS_LOG_DEBUG ("Setting Destination IP address to : " << dstAddress);
   693     ipHeader.SetDestination (dstAddress);
   694 
   695     if (protocol == IPPROTO_TCP)
   696     {
   697       TcpHeader tcpHeader;
   698 
   699       p->RemoveHeader (tcpHeader);
   700 
   701       tcpHeader.SetDestinationPort (dstPort);
   702 
   703       p->AddHeader (tcpHeader);
   704 
   705     }
   706     else
   707     {
   708       UdpHeader udpHeader;
   709 
   710       p->RemoveHeader (udpHeader);
   711 
   712       udpHeader.SetDestinationPort (dstPort);
   713       NS_LOG_DEBUG ("Setting destination port to: " << dstPort);
   714 
   715       p->AddHeader (udpHeader);
   716     }
   717 
   718     p->AddHeader (ipHeader);
   719   }
   720 
   721 
   722 
   723   return NF_ACCEPT;
   724 
   725 }
   726 
   727 } // Namespace ns3