src/internet-stack/ipv4-l3-protocol.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)
mathieu@236
     1
// -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil; -*-
mathieu@236
     2
//
mathieu@236
     3
// Copyright (c) 2006 Georgia Tech Research Corporation
mathieu@236
     4
//
mathieu@236
     5
// This program is free software; you can redistribute it and/or modify
mathieu@236
     6
// it under the terms of the GNU General Public License version 2 as
mathieu@236
     7
// published by the Free Software Foundation;
mathieu@236
     8
//
mathieu@236
     9
// This program is distributed in the hope that it will be useful,
mathieu@236
    10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
mathieu@236
    11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
mathieu@236
    12
// GNU General Public License for more details.
mathieu@236
    13
//
mathieu@236
    14
// You should have received a copy of the GNU General Public License
mathieu@236
    15
// along with this program; if not, write to the Free Software
mathieu@236
    16
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
mathieu@236
    17
//
mathieu@236
    18
// Author: George F. Riley<riley@ece.gatech.edu>
mathieu@236
    19
//
mathieu@236
    20
mathieu@236
    21
#include "ns3/packet.h"
craigdo@1504
    22
#include "ns3/log.h"
tomh@345
    23
#include "ns3/callback.h"
mathieu@524
    24
#include "ns3/ipv4-address.h"
mathieu@524
    25
#include "ns3/ipv4-route.h"
mathieu@729
    26
#include "ns3/node.h"
tomh@3124
    27
#include "ns3/socket.h"
mathieu@568
    28
#include "ns3/net-device.h"
mathieu@2498
    29
#include "ns3/uinteger.h"
mathieu@2498
    30
#include "ns3/trace-source-accessor.h"
mathieu@2498
    31
#include "ns3/object-vector.h"
mathieu@3216
    32
#include "ns3/ipv4-header.h"
mathieu@3235
    33
#include "ns3/boolean.h"
tomh@4472
    34
#include "ns3/ipv4-routing-table-entry.h"
tomh@4472
    35
tomh@4472
    36
#include "loopback-net-device.h"
gjc@3172
    37
#include "arp-l3-protocol.h"
mathieu@733
    38
#include "ipv4-l3-protocol.h"
mathieu@236
    39
#include "ipv4-l4-protocol.h"
craigdo@3820
    40
#include "icmpv4-l4-protocol.h"
mathieu@236
    41
#include "ipv4-interface.h"
craigdo@3820
    42
#include "ipv4-raw-socket-impl.h"
mathieu@236
    43
craigdo@1504
    44
NS_LOG_COMPONENT_DEFINE ("Ipv4L3Protocol");
mathieu@236
    45
mathieu@236
    46
namespace ns3 {
mathieu@236
    47
mathieu@734
    48
const uint16_t Ipv4L3Protocol::PROT_NUMBER = 0x0800;
mathieu@293
    49
mathieu@2249
    50
NS_OBJECT_ENSURE_REGISTERED (Ipv4L3Protocol);
mathieu@2249
    51
mathieu@2250
    52
TypeId 
mathieu@2251
    53
Ipv4L3Protocol::GetTypeId (void)
mathieu@2232
    54
{
mathieu@2602
    55
  static TypeId tid = TypeId ("ns3::Ipv4L3Protocol")
tomh@4377
    56
    .SetParent<Ipv4> ()
mathieu@2498
    57
    .AddConstructor<Ipv4L3Protocol> ()
mathieu@2498
    58
    .AddAttribute ("DefaultTtl", "The TTL value set by default on all outgoing packets generated on this node.",
mathieu@2965
    59
                   UintegerValue (64),
mathieu@2498
    60
                   MakeUintegerAccessor (&Ipv4L3Protocol::m_defaultTtl),
mathieu@2498
    61
                   MakeUintegerChecker<uint8_t> ())
mathieu@2498
    62
    .AddTraceSource ("Tx", "Send ipv4 packet to outgoing interface.",
mathieu@2498
    63
                   MakeTraceSourceAccessor (&Ipv4L3Protocol::m_txTrace))
mathieu@2498
    64
    .AddTraceSource ("Rx", "Receive ipv4 packet from incoming interface.",
mathieu@2498
    65
                     MakeTraceSourceAccessor (&Ipv4L3Protocol::m_rxTrace))
mathieu@2498
    66
    .AddTraceSource ("Drop", "Drop ipv4 packet",
mathieu@2498
    67
                     MakeTraceSourceAccessor (&Ipv4L3Protocol::m_dropTrace))
mathieu@2537
    68
    .AddAttribute ("InterfaceList", "The set of Ipv4 interfaces associated to this Ipv4 stack.",
mathieu@2965
    69
                   ObjectVectorValue (),
mathieu@2498
    70
                   MakeObjectVectorAccessor (&Ipv4L3Protocol::m_interfaces),
mathieu@2933
    71
                   MakeObjectVectorChecker<Ipv4Interface> ())
mathieu@2498
    72
    ;
mathieu@2252
    73
  return tid;
mathieu@2232
    74
}
mathieu@2232
    75
qasimj@4637
    76
uint32_t NfPreRoutingHookFunction (Hooks_t hookNumber, Ptr<Packet> p, Ptr<NetDevice> in, Ptr<NetDevice> out, ContinueCallback& ccb)
qasimj@4634
    77
{
qasimj@4637
    78
  std::cout << "NfPreRoutingHookFunction called at node " << in->GetNode () << " at NF_PRE_ROUTING" << std::endl;
qasimj@4634
    79
  Ipv4Header ipHeader;
qasimj@4634
    80
qasimj@4637
    81
  p->PeekHeader (ipHeader);
qasimj@4634
    82
  
qasimj@4637
    83
  if (ipHeader.GetProtocol () == 6 /* TCP */ )
qasimj@4637
    84
    std::cout << "This is a TCP packet at node " << in->GetNode () << std::endl;
qasimj@4637
    85
  else if (ipHeader.GetProtocol () == 17 /* UDP */ )
qasimj@4637
    86
    std::cout << "This is a UDP packet at node " << in->GetNode () << std::endl;
qasimj@4637
    87
  
qasimj@4637
    88
  //p->Print (std::cout);
qasimj@4637
    89
  //std::cout<<std::endl;
qasimj@4634
    90
qasimj@4634
    91
  return 0;
qasimj@4634
    92
}
qasimj@4634
    93
qasimj@4637
    94
uint32_t NfPostRoutingHookFunction (Hooks_t hookNumber, Ptr<Packet> p, Ptr<NetDevice> in, Ptr<NetDevice> out, ContinueCallback& ccb)
qasimj@4634
    95
{
qasimj@4637
    96
  std::cout << "NfPostRoutingHookFunction called at node " << out->GetNode () << " at NF_POST_ROUTING" << std::endl;
qasimj@4634
    97
  Ipv4Header ipHeader;
qasimj@4634
    98
qasimj@4637
    99
  p->PeekHeader (ipHeader);
qasimj@4637
   100
qasimj@4637
   101
  if (ipHeader.GetProtocol () == 6 /* TCP */ )
qasimj@4637
   102
    std::cout << "This is a TCP packet at node " << out->GetNode () << std::endl;
qasimj@4637
   103
  else if (ipHeader.GetProtocol () == 17 /* UDP */ )
qasimj@4637
   104
    std::cout << "This is a UDP packet at node " << out->GetNode () << std::endl;
qasimj@4634
   105
  
qasimj@4637
   106
  //p->Print (std::cout);
qasimj@4637
   107
  //std::cout<<std::endl;
qasimj@4634
   108
qasimj@4634
   109
  return 0;
qasimj@4634
   110
}
qasimj@4634
   111
qasimj@4636
   112
Ipv4L3Protocol::Ipv4L3Protocol ()
mathieu@1176
   113
  : m_nInterfaces (0),
mathieu@2498
   114
    m_identification (0)
mathieu@444
   115
{
mathieu@2983
   116
  NS_LOG_FUNCTION_NOARGS ();
qasimj@4638
   117
  /*NetfilterHookCallback nhc = MakeCallback(&NfPreRoutingHookFunction);
qasimj@4637
   118
  NetfilterHookCallback nhc2 = MakeCallback(&NfPostRoutingHookFunction);
qasimj@4637
   119
  Ipv4NetfilterHook nfh = Ipv4NetfilterHook(1, NF_INET_PRE_ROUTING, 2, nhc); 
qasimj@4637
   120
  Ipv4NetfilterHook nfh2 = Ipv4NetfilterHook(1, NF_INET_POST_ROUTING, 2, nhc2); 
qasimj@4634
   121
  netfilter.RegisterNetfilterHook(nfh);
qasimj@4638
   122
  netfilter.RegisterNetfilterHook(nfh2);*/
mathieu@444
   123
}
craigdo@1429
   124
mathieu@734
   125
Ipv4L3Protocol::~Ipv4L3Protocol ()
craigdo@1429
   126
{
mathieu@3150
   127
  NS_LOG_FUNCTION (this);
craigdo@1429
   128
}
mathieu@496
   129
mathieu@2592
   130
void
mathieu@3588
   131
Ipv4L3Protocol::Insert(Ptr<Ipv4L4Protocol> protocol)
mathieu@3588
   132
{
mathieu@3588
   133
  m_protocols.push_back (protocol);
mathieu@3588
   134
}
mathieu@3588
   135
Ptr<Ipv4L4Protocol>
qasimj@4636
   136
Ipv4L3Protocol::GetProtocol (int protocolNumber) const
mathieu@3588
   137
{
qasimj@4636
   138
  for (L4List_t::const_iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
mathieu@3588
   139
    {
mathieu@3588
   140
      if ((*i)->GetProtocolNumber () == protocolNumber)
mathieu@3588
   141
	{
mathieu@3588
   142
	  return *i;
mathieu@3588
   143
	}
mathieu@3588
   144
    }
mathieu@3588
   145
  return 0;
mathieu@3588
   146
}
mathieu@3588
   147
void
mathieu@3588
   148
Ipv4L3Protocol::Remove (Ptr<Ipv4L4Protocol> protocol)
mathieu@3588
   149
{
mathieu@3588
   150
  m_protocols.remove (protocol);
mathieu@3588
   151
}
mathieu@3588
   152
mathieu@3588
   153
void
mathieu@2592
   154
Ipv4L3Protocol::SetNode (Ptr<Node> node)
mathieu@2592
   155
{
mathieu@2592
   156
  m_node = node;
tomh@4472
   157
  // Add a LoopbackNetDevice if needed, and an Ipv4Interface on top of it
mathieu@2592
   158
  SetupLoopback ();
mathieu@2592
   159
}
mathieu@2592
   160
craigdo@3820
   161
Ptr<Socket> 
craigdo@3820
   162
Ipv4L3Protocol::CreateRawSocket (void)
craigdo@3820
   163
{
craigdo@3820
   164
  NS_LOG_FUNCTION (this);
craigdo@3820
   165
  Ptr<Ipv4RawSocketImpl> socket = CreateObject<Ipv4RawSocketImpl> ();
craigdo@3820
   166
  socket->SetNode (m_node);
craigdo@3820
   167
  m_sockets.push_back (socket);
craigdo@3820
   168
  return socket;
craigdo@3820
   169
}
craigdo@3820
   170
void 
craigdo@3820
   171
Ipv4L3Protocol::DeleteRawSocket (Ptr<Socket> socket)
craigdo@3820
   172
{
craigdo@3820
   173
  NS_LOG_FUNCTION (this << socket);
craigdo@3820
   174
  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
craigdo@3820
   175
    {
craigdo@3820
   176
      if ((*i) == socket)
craigdo@3820
   177
        {
craigdo@3820
   178
          m_sockets.erase (i);
craigdo@3820
   179
          return;
craigdo@3820
   180
        }
craigdo@3820
   181
    }
craigdo@3820
   182
  return;
craigdo@3820
   183
}
tomh@4472
   184
/*
tomh@4472
   185
 * This method is called by AddAgregate and completes the aggregation
tomh@4472
   186
 * by setting the node in the ipv4 stack
tomh@4472
   187
 */
tomh@4472
   188
void
tomh@4472
   189
Ipv4L3Protocol::NotifyNewAggregate ()
tomh@4472
   190
{
tomh@4472
   191
  Ptr<Node>node = this->GetObject<Node>();
tomh@4472
   192
  // verify that it's a valid node and that
tomh@4472
   193
  // the node has not been set before
tomh@4472
   194
  if (node!= 0 && m_node == 0)
tomh@4472
   195
    {
tomh@4472
   196
      this->SetNode (node);
tomh@4472
   197
    }
tomh@4472
   198
  Object::NotifyNewAggregate ();
tomh@4472
   199
}
tomh@4472
   200
tomh@4472
   201
void 
tomh@4481
   202
Ipv4L3Protocol::SetRoutingProtocol (Ptr<Ipv4RoutingProtocol> routingProtocol)
tomh@4472
   203
{
tomh@4472
   204
  NS_LOG_FUNCTION (this);
tomh@4481
   205
  m_routingProtocol = routingProtocol;
mathieu@4560
   206
  m_routingProtocol->SetIpv4 (this);
tomh@4472
   207
}
tomh@4472
   208
tomh@4472
   209
tomh@4472
   210
Ptr<Ipv4RoutingProtocol> 
tomh@4472
   211
Ipv4L3Protocol::GetRoutingProtocol (void) const
tomh@4472
   212
{
tomh@4472
   213
  return m_routingProtocol;
tomh@4472
   214
}
craigdo@3820
   215
mathieu@496
   216
void 
mathieu@734
   217
Ipv4L3Protocol::DoDispose (void)
mathieu@496
   218
{
mathieu@3150
   219
  NS_LOG_FUNCTION (this);
qasimj@4636
   220
  for (L4List_t::iterator i = m_protocols.begin (); i != m_protocols.end (); ++i)
mathieu@3588
   221
    {
mathieu@3588
   222
      *i = 0;
mathieu@3588
   223
    }
mathieu@3588
   224
  m_protocols.clear ();
mathieu@3588
   225
craigdo@4283
   226
  for (Ipv4InterfaceList::iterator i = m_interfaces.begin (); i != m_interfaces.end (); ++i)
mathieu@3150
   227
    {
craigdo@4283
   228
      *i = 0;
mathieu@3150
   229
    }
mathieu@496
   230
  m_interfaces.clear ();
mathieu@555
   231
  m_node = 0;
mathieu@4616
   232
  m_routingProtocol = 0;
mathieu@1176
   233
  Object::DoDispose ();
mathieu@236
   234
}
mathieu@236
   235
mathieu@444
   236
void
mathieu@734
   237
Ipv4L3Protocol::SetupLoopback (void)
mathieu@444
   238
{
mathieu@2983
   239
  NS_LOG_FUNCTION_NOARGS ();
craigdo@1429
   240
tomh@4472
   241
  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
tomh@4472
   242
  Ptr<LoopbackNetDevice> device = 0;
tomh@4472
   243
  // First check whether an existing LoopbackNetDevice exists on the node
tomh@4472
   244
  for (uint32_t i = 0; i < m_node->GetNDevices (); i++)
tomh@4472
   245
    {
tomh@4472
   246
      if (device = DynamicCast<LoopbackNetDevice> (m_node->GetDevice (i)))
tomh@4472
   247
        {
tomh@4472
   248
          break;
tomh@4472
   249
        }
tomh@4472
   250
    }
tomh@4472
   251
  if (device == 0)
tomh@4472
   252
    {
tomh@4472
   253
      device = CreateObject<LoopbackNetDevice> (); 
tomh@4472
   254
      m_node->AddDevice (device);
tomh@4472
   255
    }
tomh@4472
   256
  interface->SetDevice (device);
mathieu@2592
   257
  interface->SetNode (m_node);
tomh@4375
   258
  Ipv4InterfaceAddress ifaceAddr = Ipv4InterfaceAddress (Ipv4Address::GetLoopback (), Ipv4Mask::GetLoopback ());
tomh@4375
   259
  interface->AddAddress (ifaceAddr);
mathieu@444
   260
  uint32_t index = AddIpv4Interface (interface);
tomh@4472
   261
  Ptr<Node> node = GetObject<Node> ();
tomh@4472
   262
  node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this), 
tomh@4472
   263
                                 Ipv4L3Protocol::PROT_NUMBER, device);
mathieu@4560
   264
  interface->SetUp ();
mathieu@4560
   265
  if (m_routingProtocol != 0)
tomh@4472
   266
    {
mathieu@4560
   267
      m_routingProtocol->NotifyInterfaceUp (index);
tomh@4472
   268
    }
mathieu@444
   269
}
mathieu@444
   270
mathieu@236
   271
void 
mathieu@734
   272
Ipv4L3Protocol::SetDefaultTtl (uint8_t ttl)
mathieu@236
   273
{
mathieu@2983
   274
  NS_LOG_FUNCTION_NOARGS ();
mathieu@236
   275
  m_defaultTtl = ttl;
mathieu@236
   276
}
mathieu@236
   277
    
mathieu@236
   278
uint32_t 
mathieu@734
   279
Ipv4L3Protocol::AddInterface (Ptr<NetDevice> device)
mathieu@444
   280
{
mathieu@2983
   281
  NS_LOG_FUNCTION (this << &device);
gjc@3172
   282
gjc@3172
   283
  Ptr<Node> node = GetObject<Node> ();
gjc@3172
   284
  node->RegisterProtocolHandler (MakeCallback (&Ipv4L3Protocol::Receive, this), 
gjc@3172
   285
                                 Ipv4L3Protocol::PROT_NUMBER, device);
gjc@3172
   286
  node->RegisterProtocolHandler (MakeCallback (&ArpL3Protocol::Receive, PeekPointer (GetObject<ArpL3Protocol> ())),
gjc@3172
   287
                                 ArpL3Protocol::PROT_NUMBER, device);
gjc@3172
   288
tomh@4472
   289
  Ptr<Ipv4Interface> interface = CreateObject<Ipv4Interface> ();
mathieu@2592
   290
  interface->SetNode (m_node);
mathieu@2592
   291
  interface->SetDevice (device);
tomh@4607
   292
  interface->SetForwarding (m_ipForward);
mathieu@444
   293
  return AddIpv4Interface (interface);
mathieu@444
   294
}
craigdo@1429
   295
mathieu@444
   296
uint32_t 
mathieu@1341
   297
Ipv4L3Protocol::AddIpv4Interface (Ptr<Ipv4Interface>interface)
mathieu@236
   298
{
mathieu@2983
   299
  NS_LOG_FUNCTION (this << interface);
mathieu@236
   300
  uint32_t index = m_nInterfaces;
mathieu@236
   301
  m_interfaces.push_back (interface);
mathieu@236
   302
  m_nInterfaces++;
mathieu@236
   303
  return index;
mathieu@236
   304
}
craigdo@1429
   305
mathieu@1341
   306
Ptr<Ipv4Interface>
mathieu@734
   307
Ipv4L3Protocol::GetInterface (uint32_t index) const
mathieu@236
   308
{
mathieu@2983
   309
  NS_LOG_FUNCTION (this << index);
mathieu@236
   310
  uint32_t tmp = 0;
mathieu@236
   311
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
mathieu@236
   312
    {
mathieu@236
   313
      if (index == tmp) 
mathieu@236
   314
	{
mathieu@236
   315
	  return *i;
mathieu@236
   316
	}
mathieu@236
   317
      tmp++;
mathieu@236
   318
    }
mathieu@236
   319
  return 0;
mathieu@236
   320
}
craigdo@1429
   321
mathieu@236
   322
uint32_t 
mathieu@734
   323
Ipv4L3Protocol::GetNInterfaces (void) const
mathieu@236
   324
{
mathieu@2983
   325
  NS_LOG_FUNCTION_NOARGS ();
mathieu@236
   326
  return m_nInterfaces;
mathieu@236
   327
}
mathieu@236
   328
tomh@4472
   329
int32_t 
tomh@4472
   330
Ipv4L3Protocol::GetInterfaceForAddress (
tomh@4472
   331
  Ipv4Address address) const
craigdo@1440
   332
{
tomh@4472
   333
  NS_LOG_FUNCTION (this << address);
craigdo@1440
   334
tomh@4472
   335
  int32_t interface = 0;
craigdo@1440
   336
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
craigdo@1440
   337
       i != m_interfaces.end (); 
tomh@4372
   338
       i++, interface++)
craigdo@1440
   339
    {
tomh@4472
   340
      for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
craigdo@1440
   341
        {
tomh@4472
   342
          if ((*i)->GetAddress (j).GetLocal () == address)
tomh@4375
   343
            {
tomh@4375
   344
              return interface;
tomh@4375
   345
            }
craigdo@1440
   346
        }
craigdo@1440
   347
    }
craigdo@1440
   348
tomh@4472
   349
  return -1;
craigdo@1440
   350
}
craigdo@1440
   351
tomh@4472
   352
int32_t 
tomh@4472
   353
Ipv4L3Protocol::GetInterfaceForPrefix (
tomh@4472
   354
  Ipv4Address address, 
tomh@4472
   355
  Ipv4Mask mask) const
craigdo@1440
   356
{
tomh@4472
   357
  NS_LOG_FUNCTION (this << address << mask);
craigdo@1440
   358
tomh@4472
   359
  int32_t interface = 0;
craigdo@1440
   360
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
craigdo@1440
   361
       i != m_interfaces.end (); 
tomh@4372
   362
       i++, interface++)
craigdo@1440
   363
    {
tomh@4375
   364
      for (uint32_t j = 0; j < (*i)->GetNAddresses (); j++)
craigdo@1440
   365
        {
tomh@4472
   366
          if ((*i)->GetAddress (j).GetLocal ().CombineMask (mask) == address.CombineMask (mask))
tomh@4375
   367
            {
tomh@4375
   368
              return interface;
tomh@4375
   369
            }
craigdo@1440
   370
        }
craigdo@1440
   371
    }
craigdo@1440
   372
tomh@4472
   373
  return -1;
craigdo@1440
   374
}
craigdo@1440
   375
craigdo@2711
   376
int32_t 
tomh@4472
   377
Ipv4L3Protocol::GetInterfaceForDevice (
tomh@4472
   378
  Ptr<const NetDevice> device) const
craigdo@2711
   379
{
tomh@4472
   380
  NS_LOG_FUNCTION (this << device->GetIfIndex());
craigdo@2711
   381
tomh@4472
   382
  int32_t interface = 0;
craigdo@2711
   383
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
craigdo@2711
   384
       i != m_interfaces.end (); 
tomh@4372
   385
       i++, interface++)
craigdo@2711
   386
    {
craigdo@2711
   387
      if ((*i)->GetDevice () == device)
craigdo@2711
   388
        {
tomh@4372
   389
          return interface;
craigdo@2711
   390
        }
craigdo@2711
   391
    }
craigdo@2711
   392
craigdo@2711
   393
  return -1;
craigdo@2711
   394
}
craigdo@2711
   395
mathieu@236
   396
void 
mathieu@3548
   397
Ipv4L3Protocol::Receive( Ptr<NetDevice> device, Ptr<const Packet> p, uint16_t protocol, const Address &from,
gjc@3448
   398
                         const Address &to, NetDevice::PacketType packetType)
mathieu@236
   399
{
mathieu@3548
   400
  NS_LOG_FUNCTION (this << &device << p << protocol <<  from);
craigdo@1429
   401
tomh@4472
   402
  NS_LOG_LOGIC ("Packet from " << from << " received on node " << 
tomh@4472
   403
    m_node->GetId ());
craigdo@1443
   404
tomh@4472
   405
  uint32_t interface = 0;
mathieu@3548
   406
  Ptr<Packet> packet = p->Copy ();
qasimj@4634
   407
  
qasimj@4634
   408
  // TODO: Netfilter
qasimj@4634
   409
  
qasimj@4634
   410
  NS_LOG_DEBUG ("NF_INET_PRE_ROUTING Hook");
qasimj@4636
   411
  netfilter.ProcessHook ((uint8_t)1, NF_INET_PRE_ROUTING, packet, device, device);
mathieu@3548
   412
gjc@1524
   413
  Ptr<Ipv4Interface> ipv4Interface;
craigdo@1432
   414
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); 
craigdo@1432
   415
       i != m_interfaces.end (); 
craigdo@1432
   416
       i++)
mathieu@457
   417
    {
gjc@1524
   418
      ipv4Interface = *i;
gjc@1524
   419
      if (ipv4Interface->GetDevice () == device)
mathieu@457
   420
        {
tomh@3958
   421
          if (ipv4Interface->IsUp ())
tomh@3958
   422
            {
tomh@4472
   423
              m_rxTrace (packet, interface);
tomh@3958
   424
              break;
tomh@4472
   425
            }
tomh@3958
   426
          else
tomh@3958
   427
            {
tomh@3958
   428
              NS_LOG_LOGIC ("Dropping received packet-- interface is down");
tomh@3958
   429
              m_dropTrace (packet);
tomh@3958
   430
              return;
tomh@3958
   431
            }
mathieu@457
   432
        }
tomh@4472
   433
      interface++;
mathieu@457
   434
    }
tomh@4472
   435
mathieu@236
   436
  Ipv4Header ipHeader;
mathieu@4558
   437
  if (Node::ChecksumEnabled ())
mathieu@3235
   438
    {
mathieu@3235
   439
      ipHeader.EnableChecksum ();
mathieu@3235
   440
    }
mathieu@1866
   441
  packet->RemoveHeader (ipHeader);
mathieu@236
   442
mathieu@236
   443
  if (!ipHeader.IsChecksumOk ()) 
mathieu@236
   444
    {
mathieu@3235
   445
      m_dropTrace (packet);
mathieu@236
   446
      return;
mathieu@236
   447
    }
mathieu@236
   448
craigdo@3820
   449
  for (SocketList::iterator i = m_sockets.begin (); i != m_sockets.end (); ++i)
craigdo@3820
   450
    {
craigdo@3820
   451
      Ptr<Ipv4RawSocketImpl> socket = *i;
craigdo@3820
   452
      socket->ForwardUp (packet, ipHeader, device);
craigdo@3820
   453
    }
craigdo@3820
   454
tomh@4472
   455
  m_routingProtocol->RouteInput (packet, ipHeader, device, 
tomh@4472
   456
    MakeCallback (&Ipv4L3Protocol::IpForward, this),
tomh@4472
   457
    MakeCallback (&Ipv4L3Protocol::IpMulticastForward, this),
tomh@4472
   458
    MakeCallback (&Ipv4L3Protocol::LocalDeliver, this),
tomh@4607
   459
    MakeCallback (&Ipv4L3Protocol::RouteInputError, this)
tomh@4472
   460
  );
mathieu@236
   461
mathieu@236
   462
}
mathieu@236
   463
craigdo@3820
   464
Ptr<Icmpv4L4Protocol> 
craigdo@3820
   465
Ipv4L3Protocol::GetIcmp (void) const
craigdo@3820
   466
{
craigdo@3820
   467
  Ptr<Ipv4L4Protocol> prot = GetProtocol (Icmpv4L4Protocol::GetStaticProtocolNumber ());
craigdo@3820
   468
  if (prot != 0)
craigdo@3820
   469
    {
craigdo@3820
   470
      return prot->GetObject<Icmpv4L4Protocol> ();
craigdo@3820
   471
    }
craigdo@3820
   472
  else
craigdo@3820
   473
    {
craigdo@3820
   474
      return 0;
craigdo@3820
   475
    }
craigdo@3820
   476
}
craigdo@3820
   477
craigdo@3820
   478
bool
craigdo@3820
   479
Ipv4L3Protocol::IsUnicast (Ipv4Address ad, Ipv4Mask interfaceMask) const
craigdo@3820
   480
{
craigdo@3820
   481
  return !ad.IsMulticast () && !ad.IsSubnetDirectedBroadcast (interfaceMask);
craigdo@3820
   482
}
gjc@983
   483
mathieu@236
   484
void 
mathieu@1866
   485
Ipv4L3Protocol::Send (Ptr<Packet> packet, 
mathieu@457
   486
            Ipv4Address source, 
mathieu@457
   487
            Ipv4Address destination,
tomh@4472
   488
            uint8_t protocol,
tomh@4472
   489
            Ptr<Ipv4Route> route)
mathieu@236
   490
{
tomh@4472
   491
  NS_LOG_FUNCTION (this << packet << source << destination << uint32_t(protocol) << route);
craigdo@1429
   492
mathieu@236
   493
  Ipv4Header ipHeader;
tomh@4472
   494
  bool mayFragment = true;
tomh@4472
   495
  uint8_t ttl = m_defaultTtl;
tomh@4472
   496
  SocketIpTtlTag tag;
qasimj@4637
   497
  Ptr<NetDevice> outDev;
qasimj@4637
   498
qasimj@4637
   499
  if (!route) 
qasimj@4637
   500
  {
qasimj@4637
   501
    std::cout<< "Route: " << *route << std::endl;
qasimj@4637
   502
    outDev = route->GetOutputDevice ();
qasimj@4637
   503
  }
qasimj@4634
   504
qasimj@4634
   505
  // Netfilter LOCAL_OUT Hook
qasimj@4635
   506
  //Ptr<Packet> packetCopy = packet->Copy ();
qasimj@4634
   507
mathieu@4502
   508
  bool found = packet->RemovePacketTag (tag);
tomh@4472
   509
  if (found)
mathieu@3235
   510
    {
tomh@4472
   511
      ttl = tag.GetTtl ();
mathieu@3235
   512
    }
mathieu@3235
   513
tomh@4472
   514
  // Handle a few cases:
tomh@4472
   515
  // 1) packet is destined to limited broadcast address
tomh@4472
   516
  // 2) packet is destined to a subnet-directed broadcast address
tomh@4472
   517
  // 3) packet is not broadcast, and is passed in with a route entry
tomh@4472
   518
  // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
tomh@4472
   519
  // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call, or ICMP)
craigdo@3820
   520
  
tomh@4472
   521
  // 1) packet is destined to limited broadcast address
tomh@3124
   522
  if (destination.IsBroadcast ()) 
tomh@3124
   523
    {
tomh@4472
   524
      NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 1:  limited broadcast");
tomh@4472
   525
      ttl = 1;
tomh@4472
   526
      ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
gjc@983
   527
      uint32_t ifaceIndex = 0;
gjc@983
   528
      for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
gjc@983
   529
           ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
qasimj@4634
   530
      {
qasimj@4634
   531
        Ptr<Ipv4Interface> outInterface = *ifaceIter;
qasimj@4634
   532
        Ptr<Packet> packetCopy = packet->Copy ();
mathieu@1308
   533
qasimj@4634
   534
        NS_ASSERT (packetCopy->GetSize () <= outInterface->GetDevice()->GetMtu ());
qasimj@4634
   535
        packetCopy->AddHeader (ipHeader);
qasimj@4634
   536
qasimj@4635
   537
        /*NS_LOG_DEBUG ("NF_INET_LOCAL_OUT Hook");
qasimj@4636
   538
        netfilter.ProcessHook ((uint8_t)1, NF_INET_LOCAL_OUT, packetCopy, outDev, outDev);*/
qasimj@4634
   539
qasimj@4634
   540
        NS_LOG_DEBUG ("NF_INET_POST_ROUTING Hook");
qasimj@4636
   541
        Callback<uint32_t, Ptr<Packet> > ccb = MakeCallback (&Ipv4Netfilter::NetfilterConntrackConfirm, &netfilter);
qasimj@4636
   542
        netfilter.ProcessHook ((uint8_t)1, NF_INET_POST_ROUTING, packetCopy, outDev, outDev, ccb);
qasimj@4634
   543
qasimj@4634
   544
        m_txTrace (packetCopy, ifaceIndex);
qasimj@4634
   545
        outInterface->Send (packetCopy, destination);
qasimj@4634
   546
      }
tomh@4472
   547
      return;
tomh@4472
   548
    }
tomh@4472
   549
tomh@4472
   550
  // 2) check: packet is destined to a subnet-directed broadcast address
tomh@4472
   551
  uint32_t ifaceIndex = 0;
tomh@4472
   552
  for (Ipv4InterfaceList::iterator ifaceIter = m_interfaces.begin ();
tomh@4472
   553
    ifaceIter != m_interfaces.end (); ifaceIter++, ifaceIndex++)
tomh@4472
   554
    {
tomh@4472
   555
      Ptr<Ipv4Interface> outInterface = *ifaceIter;
tomh@4472
   556
      for (uint32_t j = 0; j < GetNAddresses (ifaceIndex); j++)
tomh@4472
   557
        {
tomh@4472
   558
          Ipv4InterfaceAddress ifAddr = GetAddress (ifaceIndex, j);
tomh@4472
   559
          NS_LOG_LOGIC ("Testing address " << ifAddr.GetLocal () << " with mask " << ifAddr.GetMask ());
tomh@4472
   560
          if (destination.IsSubnetDirectedBroadcast (ifAddr.GetMask ()) && 
tomh@4472
   561
              destination.CombineMask (ifAddr.GetMask ()) == ifAddr.GetLocal ().CombineMask (ifAddr.GetMask ())   )  
qasimj@4634
   562
          {
qasimj@4634
   563
            NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 2:  subnet directed bcast to " << ifAddr.GetLocal ());
qasimj@4634
   564
            ttl = 1;
qasimj@4634
   565
            ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
qasimj@4634
   566
            Ptr<Packet> packetCopy = packet->Copy ();
qasimj@4634
   567
            packetCopy->AddHeader (ipHeader);
qasimj@4634
   568
qasimj@4635
   569
            /*NS_LOG_DEBUG ("NF_INET_LOCAL_OUT Hook");
qasimj@4636
   570
            netfilter.ProcessHook ((uint8_t)1, NF_INET_LOCAL_OUT, packetCopy, outDev, outDev);*/
qasimj@4634
   571
qasimj@4634
   572
            NS_LOG_DEBUG ("NF_INET_POST_ROUTING Hook");
qasimj@4636
   573
            Callback<uint32_t, Ptr<Packet> > ccb = MakeCallback (&Ipv4Netfilter::NetfilterConntrackConfirm, &netfilter);
qasimj@4636
   574
            netfilter.ProcessHook ((uint8_t)1, NF_INET_POST_ROUTING, packetCopy, outDev, outDev, ccb);
qasimj@4634
   575
qasimj@4634
   576
            m_txTrace (packetCopy, ifaceIndex);
qasimj@4634
   577
            outInterface->Send (packetCopy, destination);
qasimj@4634
   578
            return;
qasimj@4634
   579
          }
gjc@983
   580
        }
gjc@983
   581
    }
tomh@4472
   582
tomh@4472
   583
  // 3) packet is not broadcast, and is passed in with a route entry
tomh@4472
   584
  //    with a valid Ipv4Address as the gateway
tomh@4472
   585
  if (route && route->GetGateway () != Ipv4Address ())
qasimj@4635
   586
  {
qasimj@4635
   587
    NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 3:  passed in with route");
qasimj@4635
   588
qasimj@4635
   589
    Ptr<Packet> packetCopy = packet->Copy ();
qasimj@4635
   590
    NS_LOG_DEBUG ("NF_INET_LOCAL_OUT Hook");
qasimj@4635
   591
    ipHeader = BuildHeader (source, destination, protocol, packetCopy->GetSize (), ttl, mayFragment);
qasimj@4636
   592
    packetCopy->AddHeader (ipHeader);
qasimj@4635
   593
    NS_LOG_DEBUG (" :: Add Ipv4 Header :: ");
qasimj@4636
   594
    netfilter.ProcessHook ((uint8_t)1, NF_INET_LOCAL_OUT, packetCopy, outDev, outDev);
qasimj@4635
   595
    NS_LOG_DEBUG (" :: Remove Ipv4 Header :: ");
qasimj@4636
   596
    packetCopy->RemoveHeader (ipHeader);
qasimj@4635
   597
qasimj@4635
   598
    SendRealOut (route, packetCopy, ipHeader);
qasimj@4635
   599
    return; 
qasimj@4635
   600
  } 
tomh@4472
   601
  // 4) packet is not broadcast, and is passed in with a route entry but route->GetGateway is not set (e.g., on-demand)
tomh@4472
   602
  if (route && route->GetGateway () != Ipv4Address ())
tomh@4472
   603
    {
tomh@4472
   604
      // This could arise because the synchronous RouteOutput() call
tomh@4472
   605
      // returned to the transport protocol with a source address but
tomh@4472
   606
      // there was no next hop available yet (since a route may need
tomh@4571
   607
      // to be queried).  
tomh@4571
   608
      NS_FATAL_ERROR ("This case not yet implemented");
tomh@4472
   609
    }
tomh@4472
   610
  // 5) packet is not broadcast, and route is NULL (e.g., a raw socket call)
tomh@4472
   611
  NS_LOG_LOGIC ("Ipv4L3Protocol::Send case 4:  passed in with no route " << destination);
qasimj@4635
   612
  Ptr<Packet> packetCopy = packet->Copy ();
faker@4567
   613
  Socket::SocketErrno errno_; 
tomh@4472
   614
  uint32_t oif = 0; // unused for now
tomh@4472
   615
  ipHeader = BuildHeader (source, destination, protocol, packet->GetSize (), ttl, mayFragment);
qasimj@4634
   616
  
qasimj@4635
   617
  NS_LOG_DEBUG (" :: Add Ipv4 Header :: ");
qasimj@4636
   618
  packetCopy->AddHeader (ipHeader);
qasimj@4634
   619
  NS_LOG_DEBUG ("NF_INET_LOCAL_OUT Hook");
qasimj@4636
   620
  netfilter.ProcessHook ((uint8_t)1, NF_INET_LOCAL_OUT, packetCopy, outDev, outDev);
qasimj@4635
   621
  NS_LOG_DEBUG (" :: Remove Ipv4 Header :: ");
qasimj@4636
   622
  packetCopy->RemoveHeader (ipHeader);
qasimj@4634
   623
joshpelkey@4603
   624
  Ptr<Ipv4Route> newRoute = m_routingProtocol->RouteOutput (packet, ipHeader, oif, errno_);
tomh@4472
   625
  if (newRoute)
tomh@4472
   626
    {
tomh@4472
   627
      SendRealOut (newRoute, packet, ipHeader);
tomh@4472
   628
    }
gjc@983
   629
  else
gjc@983
   630
    {
tomh@4472
   631
      NS_LOG_WARN ("No route to host.  Drop.");
tomh@4472
   632
      m_dropTrace (packet);
gjc@983
   633
    }
gjc@983
   634
}
gjc@983
   635
tomh@4472
   636
// XXX when should we set ip_id?   check whether we are incrementing
tomh@4472
   637
// m_identification on packets that may later be dropped in this stack
tomh@4472
   638
// and whether that deviates from Linux
tomh@4472
   639
Ipv4Header
tomh@4472
   640
Ipv4L3Protocol::BuildHeader (
tomh@4472
   641
            Ipv4Address source, 
tomh@4472
   642
            Ipv4Address destination,
tomh@4472
   643
            uint8_t protocol,
tomh@4472
   644
            uint16_t payloadSize,
tomh@4472
   645
            uint8_t ttl,
tomh@4472
   646
            bool mayFragment)
tomh@4472
   647
{
tomh@4472
   648
  NS_LOG_FUNCTION_NOARGS ();
tomh@4472
   649
  Ipv4Header ipHeader;
tomh@4472
   650
  ipHeader.SetSource (source);
tomh@4472
   651
  ipHeader.SetDestination (destination);
tomh@4472
   652
  ipHeader.SetProtocol (protocol);
tomh@4472
   653
  ipHeader.SetPayloadSize (payloadSize);
tomh@4472
   654
  ipHeader.SetTtl (ttl);
tomh@4472
   655
  if (mayFragment == true)
tomh@4472
   656
    {
tomh@4472
   657
      ipHeader.SetMayFragment ();
tomh@4472
   658
      ipHeader.SetIdentification (m_identification);
tomh@4472
   659
      m_identification ++;
tomh@4472
   660
    }
tomh@4472
   661
  else
tomh@4472
   662
    {
tomh@4472
   663
      ipHeader.SetDontFragment ();
tomh@4472
   664
      // TBD:  set to zero here; will cause traces to change
tomh@4472
   665
      ipHeader.SetIdentification (m_identification);
tomh@4472
   666
      m_identification ++;
tomh@4472
   667
    }
mathieu@4558
   668
  if (Node::ChecksumEnabled ())
tomh@4472
   669
    {
tomh@4472
   670
      ipHeader.EnableChecksum ();
tomh@4472
   671
    }
tomh@4472
   672
  return ipHeader;
tomh@4472
   673
}
tomh@4472
   674
gjc@983
   675
void
tomh@4472
   676
Ipv4L3Protocol::SendRealOut (Ptr<Ipv4Route> route,
mathieu@1866
   677
                             Ptr<Packet> packet,
gjc@983
   678
                             Ipv4Header const &ipHeader)
gjc@983
   679
{
tomh@4472
   680
  NS_LOG_FUNCTION (this << packet << &ipHeader);
qasimj@4634
   681
  Ptr<NetDevice> outDev = route->GetOutputDevice ();
craigdo@1429
   682
tomh@4472
   683
  // We add a header regardless of whether there is a route, since 
tomh@4472
   684
  // we may want to drop trace
gjc@2325
   685
  packet->AddHeader (ipHeader);
qasimj@4634
   686
qasimj@4636
   687
  Callback<uint32_t, Ptr<Packet> > ccb = MakeCallback (&Ipv4Netfilter::NetfilterConntrackConfirm, &netfilter);
qasimj@4634
   688
  NS_LOG_DEBUG ("NF_INET_POST_ROUTING Hook");
qasimj@4636
   689
  netfilter.ProcessHook ((uint8_t)1, NF_INET_POST_ROUTING, packet, outDev, outDev, ccb);
qasimj@4634
   690
tomh@4472
   691
  if (route == 0)
gjc@983
   692
    {
craigdo@1504
   693
      NS_LOG_WARN ("No route to host.  Drop.");
tomh@345
   694
      m_dropTrace (packet);
mathieu@236
   695
      return;
mathieu@236
   696
    }
craigdo@1430
   697
tomh@4472
   698
  int32_t interface = GetInterfaceForDevice (outDev);
tomh@4472
   699
  NS_ASSERT (interface >= 0);
tomh@4472
   700
  Ptr<Ipv4Interface> outInterface = GetInterface (interface);
tomh@4472
   701
  NS_LOG_LOGIC ("Send via NetDevice ifIndex " << outDev->GetIfIndex () << " ipv4InterfaceIndex " << interface);
craigdo@1430
   702
tomh@4572
   703
  NS_ASSERT (packet->GetSize () <= outInterface->GetDevice ()->GetMtu ());
tomh@4472
   704
  if (!route->GetGateway ().IsEqual (Ipv4Address ("0.0.0.0"))) 
mathieu@236
   705
    {
tomh@4472
   706
      if (outInterface->IsUp ())
tomh@4472
   707
        {
tomh@4472
   708
          NS_LOG_LOGIC ("Send to gateway " << route->GetGateway ());
tomh@4472
   709
          m_txTrace (packet, interface);
tomh@4472
   710
          outInterface->Send (packet, route->GetGateway ());
tomh@4472
   711
        }
tomh@4472
   712
      else
tomh@4472
   713
        {
tomh@4472
   714
          NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << route->GetGateway ());
tomh@4472
   715
          m_dropTrace (packet);
tomh@4472
   716
        }
tomh@4472
   717
    } 
tomh@4472
   718
  else 
mathieu@236
   719
    {
tomh@4472
   720
      if (outInterface->IsUp ())
craigdo@3820
   721
        {
tomh@4472
   722
          NS_LOG_LOGIC ("Send to destination " << ipHeader.GetDestination ());
tomh@4472
   723
          m_txTrace (packet, interface);
tomh@4472
   724
          outInterface->Send (packet, ipHeader.GetDestination ());
tomh@4472
   725
        }
tomh@4472
   726
      else
craigdo@3820
   727
        {
tomh@4472
   728
          NS_LOG_LOGIC ("Dropping-- outgoing interface is down: " << ipHeader.GetDestination ());
tomh@4472
   729
          m_dropTrace (packet);
craigdo@3820
   730
        }
mathieu@236
   731
    }
mathieu@236
   732
}
mathieu@236
   733
tomh@4472
   734
// This function analogous to Linux ip_mr_forward()
tomh@4472
   735
void
tomh@4472
   736
Ipv4L3Protocol::IpMulticastForward (Ptr<Ipv4MulticastRoute> mrtentry, Ptr<const Packet> p, const Ipv4Header &header)
mathieu@1235
   737
{
tomh@4472
   738
  NS_LOG_FUNCTION (mrtentry << p << header);
tomh@4472
   739
  NS_LOG_LOGIC ("Multicast forwarding logic for node: " << m_node->GetId ());
tomh@4472
   740
  // The output interfaces we could forward this onto are encoded
tomh@4472
   741
  // in the OutputTtl of the Ipv4MulticastRoute
tomh@4472
   742
  for (uint32_t i = 0; i < Ipv4MulticastRoute::MAX_INTERFACES; i++)
mathieu@236
   743
    {
tomh@4472
   744
      if (mrtentry->GetOutputTtl (i) < Ipv4MulticastRoute::MAX_TTL)
mathieu@236
   745
        {
tomh@4472
   746
          Ptr<Packet> packet = p->Copy ();
tomh@4472
   747
          Ipv4Header h = header;
tomh@4472
   748
          h.SetTtl (header.GetTtl () - 1);
tomh@4472
   749
          if (h.GetTtl () == 0)
tomh@4375
   750
            {
tomh@4472
   751
              NS_LOG_WARN ("TTL exceeded.  Drop.");
tomh@4472
   752
              m_dropTrace (packet);
tomh@4472
   753
              return;
tomh@4375
   754
            }
tomh@4472
   755
          NS_LOG_LOGIC ("Forward multicast via interface " << i);
tomh@4472
   756
          Ptr<Ipv4Route> rtentry = Create<Ipv4Route> ();
tomh@4472
   757
          rtentry->SetSource (h.GetSource ());
tomh@4472
   758
          rtentry->SetDestination (h.GetDestination ());
tomh@4472
   759
          rtentry->SetGateway (Ipv4Address::GetAny ());
tomh@4472
   760
          rtentry->SetOutputDevice (GetNetDevice (i));
tomh@4472
   761
          SendRealOut (rtentry, packet, h);
tomh@4472
   762
          return; 
mathieu@236
   763
        }
mathieu@236
   764
    }
craigdo@3820
   765
}
craigdo@3820
   766
tomh@4472
   767
// This function analogous to Linux ip_forward()
craigdo@3820
   768
void
tomh@4472
   769
Ipv4L3Protocol::IpForward (Ptr<Ipv4Route> rtentry, Ptr<const Packet> p, const Ipv4Header &header)
craigdo@3820
   770
{
tomh@4472
   771
  NS_LOG_FUNCTION (rtentry << p << header);
tomh@4472
   772
  NS_LOG_LOGIC ("Forwarding logic for node: " << m_node->GetId ());
tomh@4472
   773
  // Forwarding
tomh@4472
   774
  Ipv4Header ipHeader = header;
tomh@4472
   775
  Ptr<Packet> packet = p->Copy ();
qasimj@4634
   776
  Ptr<NetDevice> outDev = rtentry->GetOutputDevice ();
craigdo@3820
   777
  ipHeader.SetTtl (ipHeader.GetTtl () - 1);
craigdo@3820
   778
  if (ipHeader.GetTtl () == 0)
craigdo@3820
   779
    {
tomh@4571
   780
      // Do not reply to ICMP or to multicast/broadcast IP address 
tomh@4571
   781
      if (ipHeader.GetProtocol () != Icmpv4L4Protocol::PROT_NUMBER && 
tomh@4571
   782
        ipHeader.GetDestination ().IsBroadcast () == false && 
tomh@4571
   783
        ipHeader.GetDestination ().IsMulticast () == false)
craigdo@3820
   784
        {
craigdo@3820
   785
          Ptr<Icmpv4L4Protocol> icmp = GetIcmp ();
craigdo@3820
   786
          icmp->SendTimeExceededTtl (ipHeader, packet);
craigdo@3820
   787
        }
tomh@3956
   788
      NS_LOG_WARN ("TTL exceeded.  Drop.");
craigdo@3820
   789
      m_dropTrace (packet);
craigdo@3820
   790
      return;
tomh@4472
   791
    }
qasimj@4634
   792
  // Netfilter FORWARD Hook
qasimj@4634
   793
  NS_LOG_DEBUG ("NF_INET_FORWARD Hook");
qasimj@4636
   794
  netfilter.ProcessHook ((uint8_t)1, NF_INET_FORWARD, packet, outDev, outDev);
qasimj@4634
   795
tomh@4472
   796
  SendRealOut (rtentry, packet, ipHeader);
mathieu@236
   797
}
mathieu@236
   798
mathieu@236
   799
void
tomh@4472
   800
Ipv4L3Protocol::LocalDeliver (Ptr<const Packet> packet, Ipv4Header const&ip, uint32_t iif)
mathieu@236
   801
{
tomh@4472
   802
  NS_LOG_FUNCTION (this << packet << &ip);
qasimj@4635
   803
  Ptr<Packet> pkt = packet->Copy (); // need to pass a non-const packet up
qasimj@4634
   804
  
qasimj@4634
   805
  // Netfilter LOCAL_IN Hook
qasimj@4634
   806
  Ptr<NetDevice> device;
qasimj@4635
   807
  pkt->AddHeader(ip);
qasimj@4636
   808
  Callback<uint32_t, Ptr<Packet> > ccb = MakeCallback (&Ipv4Netfilter::NetfilterConntrackConfirm, &netfilter);
qasimj@4634
   809
  NS_LOG_DEBUG ("NF_INET_LOCAL_IN Hook");
qasimj@4636
   810
  netfilter.ProcessHook ((uint8_t)1, NF_INET_LOCAL_IN, pkt, device, device, ccb);
qasimj@4635
   811
  
qasimj@4635
   812
qasimj@4635
   813
  Ptr<Packet> p = packet->Copy (); // need to pass a non-const packet up
qasimj@4635
   814
  //p->RemoveHeader(ip);
craigdo@1504
   815
mathieu@3588
   816
  Ptr<Ipv4L4Protocol> protocol = GetProtocol (ip.GetProtocol ());
craigdo@3820
   817
  if (protocol != 0)
craigdo@3820
   818
    {
craigdo@3820
   819
      // we need to make a copy in the unlikely event we hit the
craigdo@3820
   820
      // RX_ENDPOINT_UNREACH codepath
craigdo@3820
   821
      Ptr<Packet> copy = p->Copy ();
craigdo@3820
   822
      enum Ipv4L4Protocol::RxStatus status = 
tomh@4472
   823
        protocol->Receive (p, ip.GetSource (), ip.GetDestination (), GetInterface (iif));
craigdo@3820
   824
      switch (status) {
craigdo@3820
   825
      case Ipv4L4Protocol::RX_OK:
craigdo@3820
   826
        // fall through
craigdo@3820
   827
      case Ipv4L4Protocol::RX_CSUM_FAILED:
craigdo@3820
   828
        break;
craigdo@3820
   829
      case Ipv4L4Protocol::RX_ENDPOINT_UNREACH:
tomh@4571
   830
        if (ip.GetDestination ().IsBroadcast () == true || 
tomh@4571
   831
          ip.GetDestination ().IsMulticast () == true)
tomh@4571
   832
          {
tomh@4571
   833
            break;  // Do not reply to broadcast or multicast
tomh@4571
   834
          }
tomh@4571
   835
        // Another case to suppress ICMP is a subnet-directed broadcast
tomh@4571
   836
        bool subnetDirected = false;
tomh@4571
   837
        for (uint32_t i = 0; i < GetNAddresses (iif); i++)
tomh@4571
   838
          {
tomh@4571
   839
            Ipv4InterfaceAddress addr = GetAddress (iif, i);
qasimj@4636
   840
            if (addr.GetLocal ().CombineMask (addr.GetMask ()) == ip.GetDestination ().CombineMask (addr.GetMask ()) &&
tomh@4571
   841
              ip.GetDestination ().IsSubnetDirectedBroadcast (addr.GetMask ()))
tomh@4571
   842
              {
tomh@4571
   843
                subnetDirected = true;
tomh@4571
   844
              }
tomh@4571
   845
          }
tomh@4571
   846
        if (subnetDirected == false)
craigdo@3820
   847
          {
craigdo@3820
   848
            GetIcmp ()->SendDestUnreachPort (ip, copy);
craigdo@3820
   849
          }
craigdo@3820
   850
      }
craigdo@3820
   851
    }
mathieu@236
   852
}
mathieu@236
   853
tomh@4563
   854
bool
tomh@4373
   855
Ipv4L3Protocol::AddAddress (uint32_t i, Ipv4InterfaceAddress address)
mathieu@444
   856
{
mathieu@2983
   857
  NS_LOG_FUNCTION (this << i << address);
mathieu@1341
   858
  Ptr<Ipv4Interface> interface = GetInterface (i);
tomh@4563
   859
  bool retVal = interface->AddAddress (address);
mathieu@4560
   860
  if (m_routingProtocol != 0)
mathieu@4560
   861
    {
mathieu@4560
   862
      m_routingProtocol->NotifyAddAddress (i, address);
mathieu@4560
   863
    }
tomh@4563
   864
  return retVal;
mathieu@444
   865
}
craigdo@1429
   866
tomh@4472
   867
Ipv4InterfaceAddress 
tomh@4373
   868
Ipv4L3Protocol::GetAddress (uint32_t interfaceIndex, uint32_t addressIndex) const
mathieu@444
   869
{
tomh@4373
   870
  NS_LOG_FUNCTION (this << interfaceIndex << addressIndex);
tomh@4373
   871
  Ptr<Ipv4Interface> interface = GetInterface (interfaceIndex);
tomh@4373
   872
  return interface->GetAddress (addressIndex);
mathieu@444
   873
}
craigdo@1429
   874
tomh@4472
   875
uint32_t 
tomh@4373
   876
Ipv4L3Protocol::GetNAddresses (uint32_t interface) const
mathieu@444
   877
{
tomh@4373
   878
  NS_LOG_FUNCTION (this << interface);
tomh@4373
   879
  Ptr<Ipv4Interface> iface = GetInterface (interface);
tomh@4373
   880
  return iface->GetNAddresses ();
mathieu@444
   881
}
craigdo@1429
   882
tomh@4563
   883
bool
tomh@4563
   884
Ipv4L3Protocol::RemoveAddress (uint32_t i, uint32_t addressIndex)
tomh@4563
   885
{
tomh@4563
   886
  NS_LOG_FUNCTION (this << i << addressIndex);
tomh@4563
   887
  Ptr<Ipv4Interface> interface = GetInterface (i);
tomh@4563
   888
  Ipv4InterfaceAddress address = interface->RemoveAddress (addressIndex);
tomh@4563
   889
  if (address != Ipv4InterfaceAddress ())
tomh@4563
   890
    {
tomh@4563
   891
      if (m_routingProtocol != 0)
tomh@4563
   892
        {
tomh@4563
   893
          m_routingProtocol->NotifyRemoveAddress (i, address);
tomh@4563
   894
        }
tomh@4563
   895
      return true;
tomh@4563
   896
    }
tomh@4563
   897
  return false;
tomh@4563
   898
}
tomh@4563
   899
tomh@1776
   900
void 
tomh@1776
   901
Ipv4L3Protocol::SetMetric (uint32_t i, uint16_t metric)
tomh@1776
   902
{
mathieu@2983
   903
  NS_LOG_FUNCTION (i << metric);
tomh@1776
   904
  Ptr<Ipv4Interface> interface = GetInterface (i);
tomh@1776
   905
  interface->SetMetric (metric);
tomh@1776
   906
}
tomh@1776
   907
tomh@1776
   908
uint16_t
tomh@1776
   909
Ipv4L3Protocol::GetMetric (uint32_t i) const
tomh@1776
   910
{
mathieu@2983
   911
  NS_LOG_FUNCTION (i);
tomh@1776
   912
  Ptr<Ipv4Interface> interface = GetInterface (i);
tomh@1776
   913
  return interface->GetMetric ();
tomh@1776
   914
}
tomh@1776
   915
mathieu@444
   916
uint16_t 
mathieu@734
   917
Ipv4L3Protocol::GetMtu (uint32_t i) const
mathieu@444
   918
{
mathieu@2983
   919
  NS_LOG_FUNCTION (this << i);
mathieu@1341
   920
  Ptr<Ipv4Interface> interface = GetInterface (i);
tomh@4572
   921
  return interface->GetDevice ()->GetMtu ();
mathieu@444
   922
}
craigdo@1429
   923
mathieu@444
   924
bool 
mathieu@734
   925
Ipv4L3Protocol::IsUp (uint32_t i) const
mathieu@444
   926
{
mathieu@2983
   927
  NS_LOG_FUNCTION (this << i);
mathieu@1341
   928
  Ptr<Ipv4Interface> interface = GetInterface (i);
mathieu@444
   929
  return interface->IsUp ();
mathieu@444
   930
}
craigdo@1429
   931
mathieu@444
   932
void 
mathieu@734
   933
Ipv4L3Protocol::SetUp (uint32_t i)
mathieu@444
   934
{
mathieu@2983
   935
  NS_LOG_FUNCTION (this << i);
mathieu@1341
   936
  Ptr<Ipv4Interface> interface = GetInterface (i);
mathieu@444
   937
  interface->SetUp ();
tomh@979
   938
mathieu@4560
   939
  if (m_routingProtocol != 0)
tomh@979
   940
    {
mathieu@4560
   941
      m_routingProtocol->NotifyInterfaceUp (i);
tomh@979
   942
    }
mathieu@444
   943
}
craigdo@1429
   944
mathieu@444
   945
void 
tomh@979
   946
Ipv4L3Protocol::SetDown (uint32_t ifaceIndex)
mathieu@444
   947
{
mathieu@2983
   948
  NS_LOG_FUNCTION (this << ifaceIndex);
mathieu@1341
   949
  Ptr<Ipv4Interface> interface = GetInterface (ifaceIndex);
mathieu@444
   950
  interface->SetDown ();
tomh@979
   951
mathieu@4560
   952
  if (m_routingProtocol != 0)
tomh@979
   953
    {
mathieu@4560
   954
      m_routingProtocol->NotifyInterfaceDown (ifaceIndex);
tomh@979
   955
    }
mathieu@444
   956
}
mathieu@444
   957
tomh@4607
   958
bool 
tomh@4607
   959
Ipv4L3Protocol::IsForwarding (uint32_t i) const
tomh@4607
   960
{
tomh@4607
   961
  NS_LOG_FUNCTION (this << i);
tomh@4607
   962
  Ptr<Ipv4Interface> interface = GetInterface (i);
tomh@4607
   963
  NS_LOG_LOGIC ("Forwarding state: " << interface->IsForwarding ());
tomh@4607
   964
  return interface->IsForwarding ();
tomh@4607
   965
}
tomh@4607
   966
tomh@4607
   967
void 
tomh@4607
   968
Ipv4L3Protocol::SetForwarding (uint32_t i, bool val)
tomh@4607
   969
{
tomh@4607
   970
  NS_LOG_FUNCTION (this << i);
tomh@4607
   971
  Ptr<Ipv4Interface> interface = GetInterface (i);
tomh@4607
   972
  interface->SetForwarding (val);
tomh@4607
   973
}
tomh@4607
   974
tomh@4377
   975
Ptr<NetDevice>
tomh@4377
   976
Ipv4L3Protocol::GetNetDevice (uint32_t i)
tomh@4377
   977
{
tomh@4607
   978
  NS_LOG_FUNCTION (this << i);
tomh@4377
   979
  return GetInterface (i)-> GetDevice ();
tomh@4377
   980
}
tomh@4377
   981
tomh@4472
   982
void 
tomh@4472
   983
Ipv4L3Protocol::SetIpForward (bool forward) 
tomh@4472
   984
{
tomh@4607
   985
  NS_LOG_FUNCTION (this << forward);
tomh@4472
   986
  m_ipForward = forward;
tomh@4607
   987
  for (Ipv4InterfaceList::const_iterator i = m_interfaces.begin (); i != m_interfaces.end (); i++)
tomh@4607
   988
    {
tomh@4607
   989
      (*i)->SetForwarding (forward);
tomh@4607
   990
    }
tomh@4472
   991
}
tomh@4472
   992
tomh@4472
   993
bool 
tomh@4472
   994
Ipv4L3Protocol::GetIpForward (void) const
tomh@4472
   995
{
tomh@4472
   996
  return m_ipForward;
tomh@4472
   997
}
tomh@4377
   998
tomh@4607
   999
void
tomh@4607
  1000
Ipv4L3Protocol::RouteInputError (Ptr<const Packet> p, const Ipv4Header & ipHeader, Socket::SocketErrno sockErrno)
tomh@4607
  1001
{
tomh@4607
  1002
  NS_LOG_FUNCTION (this << p << ipHeader << sockErrno);
tomh@4607
  1003
  NS_LOG_LOGIC ("Route input failure-- dropping packet to " << ipHeader << " with errno " << sockErrno); 
tomh@4607
  1004
  m_dropTrace (p);
tomh@4607
  1005
}
qasimj@4638
  1006
  
qasimj@4638
  1007
Ipv4Netfilter* 
qasimj@4638
  1008
Ipv4L3Protocol::GetNetfilter()
qasimj@4638
  1009
{
qasimj@4638
  1010
  return &netfilter;
qasimj@4638
  1011
}
tomh@4607
  1012
tomh@4375
  1013
mathieu@236
  1014
}//namespace ns3