A Discrete-Event Network Simulator
API
icmpv4-l4-protocol.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2008 INRIA
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation;
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16  *
17  * Author: Mathieu Lacage <mathieu.lacage@cutebugs.net>
18  */
19 
20 #include "icmpv4-l4-protocol.h"
21 
22 #include "ipv4-interface.h"
23 #include "ipv4-l3-protocol.h"
25 
26 #include "ns3/assert.h"
27 #include "ns3/boolean.h"
28 #include "ns3/ipv4-route.h"
29 #include "ns3/ipv6-interface.h"
30 #include "ns3/log.h"
31 #include "ns3/node.h"
32 #include "ns3/packet.h"
33 
34 namespace ns3
35 {
36 
37 NS_LOG_COMPONENT_DEFINE("Icmpv4L4Protocol");
38 
39 NS_OBJECT_ENSURE_REGISTERED(Icmpv4L4Protocol);
40 
41 // see rfc 792
42 const uint8_t Icmpv4L4Protocol::PROT_NUMBER = 1;
43 
44 TypeId
46 {
47  static TypeId tid = TypeId("ns3::Icmpv4L4Protocol")
49  .SetGroupName("Internet")
50  .AddConstructor<Icmpv4L4Protocol>();
51  return tid;
52 }
53 
55  : m_node(nullptr)
56 {
57  NS_LOG_FUNCTION(this);
58 }
59 
61 {
62  NS_LOG_FUNCTION(this);
63  NS_ASSERT(!m_node);
64 }
65 
66 void
68 {
69  NS_LOG_FUNCTION(this << node);
70  m_node = node;
71 }
72 
73 /*
74  * This method is called by AggregateObject and completes the aggregation
75  * by setting the node in the ICMP stack and adding ICMP factory to
76  * IPv4 stack connected to the node
77  */
78 void
80 {
81  NS_LOG_FUNCTION(this);
82  if (!m_node)
83  {
84  Ptr<Node> node = this->GetObject<Node>();
85  if (node)
86  {
87  Ptr<Ipv4> ipv4 = this->GetObject<Ipv4>();
88  if (ipv4 && m_downTarget.IsNull())
89  {
90  this->SetNode(node);
91  ipv4->Insert(this);
92  Ptr<Ipv4RawSocketFactoryImpl> rawFactory = CreateObject<Ipv4RawSocketFactoryImpl>();
93  ipv4->AggregateObject(rawFactory);
94  this->SetDownTarget(MakeCallback(&Ipv4::Send, ipv4));
95  }
96  }
97  }
99 }
100 
101 uint16_t
103 {
105  return PROT_NUMBER;
106 }
107 
108 int
110 {
111  NS_LOG_FUNCTION(this);
112  return PROT_NUMBER;
113 }
114 
115 void
116 Icmpv4L4Protocol::SendMessage(Ptr<Packet> packet, Ipv4Address dest, uint8_t type, uint8_t code)
117 {
118  NS_LOG_FUNCTION(this << packet << dest << static_cast<uint32_t>(type)
119  << static_cast<uint32_t>(code));
120  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4>();
121  NS_ASSERT(ipv4 && ipv4->GetRoutingProtocol());
122  Ipv4Header header;
123  header.SetDestination(dest);
124  header.SetProtocol(PROT_NUMBER);
125  Socket::SocketErrno errno_;
126  Ptr<Ipv4Route> route;
127  Ptr<NetDevice> oif(nullptr); // specify non-zero if bound to a source address
128  route = ipv4->GetRoutingProtocol()->RouteOutput(packet, header, oif, errno_);
129  if (route)
130  {
131  NS_LOG_LOGIC("Route exists");
132  Ipv4Address source = route->GetSource();
133  SendMessage(packet, source, dest, type, code, route);
134  }
135  else
136  {
137  NS_LOG_WARN("drop icmp message");
138  }
139 }
140 
141 void
143  Ipv4Address source,
144  Ipv4Address dest,
145  uint8_t type,
146  uint8_t code,
147  Ptr<Ipv4Route> route)
148 {
149  NS_LOG_FUNCTION(this << packet << source << dest << static_cast<uint32_t>(type)
150  << static_cast<uint32_t>(code) << route);
151  Icmpv4Header icmp;
152  icmp.SetType(type);
153  icmp.SetCode(code);
154  if (Node::ChecksumEnabled())
155  {
156  icmp.EnableChecksum();
157  }
158  packet->AddHeader(icmp);
159 
160  m_downTarget(packet, source, dest, PROT_NUMBER, route);
161 }
162 
163 void
165  Ptr<const Packet> orgData,
166  uint16_t nextHopMtu)
167 {
168  NS_LOG_FUNCTION(this << header << *orgData << nextHopMtu);
170 }
171 
172 void
174 {
175  NS_LOG_FUNCTION(this << header << *orgData);
177 }
178 
179 void
181  Ptr<const Packet> orgData,
182  uint8_t code,
183  uint16_t nextHopMtu)
184 {
185  NS_LOG_FUNCTION(this << header << *orgData << (uint32_t)code << nextHopMtu);
186  Ptr<Packet> p = Create<Packet>();
188  unreach.SetNextHopMtu(nextHopMtu);
189  unreach.SetHeader(header);
190  unreach.SetData(orgData);
191  p->AddHeader(unreach);
193 }
194 
195 void
197 {
198  NS_LOG_FUNCTION(this << header << *orgData);
199  Ptr<Packet> p = Create<Packet>();
200  Icmpv4TimeExceeded time;
201  time.SetHeader(header);
202  time.SetData(orgData);
203  p->AddHeader(time);
204  if (!isFragment)
205  {
206  SendMessage(p,
207  header.GetSource(),
210  }
211  else
212  {
213  SendMessage(p,
214  header.GetSource(),
217  }
218 }
219 
220 void
222  Icmpv4Header header,
223  Ipv4Address source,
224  Ipv4Address destination)
225 {
226  NS_LOG_FUNCTION(this << p << header << source << destination);
227 
228  Ptr<Packet> reply = Create<Packet>();
229  Icmpv4Echo echo;
230  p->RemoveHeader(echo);
231  reply->AddHeader(echo);
232  SendMessage(reply, destination, source, Icmpv4Header::ICMPV4_ECHO_REPLY, 0, nullptr);
233 }
234 
235 void
237  Icmpv4Header icmp,
238  uint32_t info,
239  Ipv4Header ipHeader,
240  const uint8_t payload[8])
241 {
242  NS_LOG_FUNCTION(this << source << icmp << info << ipHeader << payload);
243 
244  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4>();
245  Ptr<IpL4Protocol> l4 = ipv4->GetProtocol(ipHeader.GetProtocol());
246  if (l4)
247  {
248  l4->ReceiveIcmp(source,
249  ipHeader.GetTtl(),
250  icmp.GetType(),
251  icmp.GetCode(),
252  info,
253  ipHeader.GetSource(),
254  ipHeader.GetDestination(),
255  payload);
256  }
257 }
258 
259 void
261  Icmpv4Header icmp,
262  Ipv4Address source,
263  Ipv4Address destination)
264 {
265  NS_LOG_FUNCTION(this << p << icmp << source << destination);
266 
268  p->PeekHeader(unreach);
269  uint8_t payload[8];
270  unreach.GetData(payload);
271  Ipv4Header ipHeader = unreach.GetHeader();
272  Forward(source, icmp, unreach.GetNextHopMtu(), ipHeader, payload);
273 }
274 
275 void
277  Icmpv4Header icmp,
278  Ipv4Address source,
279  Ipv4Address destination)
280 {
281  NS_LOG_FUNCTION(this << p << icmp << source << destination);
282 
283  Icmpv4TimeExceeded time;
284  p->PeekHeader(time);
285  uint8_t payload[8];
286  time.GetData(payload);
287  Ipv4Header ipHeader = time.GetHeader();
288  // info field is zero for TimeExceeded on linux
289  Forward(source, icmp, 0, ipHeader, payload);
290 }
291 
294  const Ipv4Header& header,
295  Ptr<Ipv4Interface> incomingInterface)
296 {
297  NS_LOG_FUNCTION(this << p << header << incomingInterface);
298 
299  Icmpv4Header icmp;
300  p->RemoveHeader(icmp);
301  switch (icmp.GetType())
302  {
304  Ipv4Address dst = header.GetDestination();
305  // We could have received an Echo request to a broadcast-type address.
306  if (dst.IsBroadcast())
307  {
308  Ipv4Address src = header.GetSource();
309  for (uint32_t index = 0; index < incomingInterface->GetNAddresses(); index++)
310  {
311  Ipv4InterfaceAddress addr = incomingInterface->GetAddress(index);
312  if (addr.IsInSameSubnet(src))
313  {
314  dst = addr.GetAddress();
315  }
316  }
317  }
318  else
319  {
320  for (uint32_t index = 0; index < incomingInterface->GetNAddresses(); index++)
321  {
322  Ipv4InterfaceAddress addr = incomingInterface->GetAddress(index);
323  if (dst == addr.GetBroadcast())
324  {
325  dst = addr.GetAddress();
326  }
327  }
328  }
329  HandleEcho(p, icmp, header.GetSource(), dst);
330  break;
331  }
333  HandleDestUnreach(p, icmp, header.GetSource(), header.GetDestination());
334  break;
336  HandleTimeExceeded(p, icmp, header.GetSource(), header.GetDestination());
337  break;
338  default:
339  NS_LOG_DEBUG(icmp << " " << *p);
340  break;
341  }
342  return IpL4Protocol::RX_OK;
343 }
344 
346 Icmpv4L4Protocol::Receive(Ptr<Packet> p,
347  const Ipv6Header& header,
348  Ptr<Ipv6Interface> incomingInterface)
349 {
350  NS_LOG_FUNCTION(this << p << header.GetSource() << header.GetDestination()
351  << incomingInterface);
353 }
354 
355 void
357 {
358  NS_LOG_FUNCTION(this);
359  m_node = nullptr;
362 }
363 
364 void
366 {
367  NS_LOG_FUNCTION(this << &callback);
368  m_downTarget = callback;
369 }
370 
371 void
373 {
374  NS_LOG_FUNCTION(this << &callback);
375 }
376 
379 {
380  NS_LOG_FUNCTION(this);
381  return m_downTarget;
382 }
383 
386 {
387  NS_LOG_FUNCTION(this);
389 }
390 
391 } // namespace ns3
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:578
bool IsNull() const
Check for null implementation.
Definition: callback.h:572
ICMP Destination Unreachable header.
Definition: icmpv4.h:174
uint16_t GetNextHopMtu() const
Get the next hop MTU.
Definition: icmpv4.cc:331
Ipv4Header GetHeader() const
Get the ICMP carried IPv4 header.
Definition: icmpv4.cc:359
void GetData(uint8_t payload[8]) const
Get the ICMP carried data.
Definition: icmpv4.cc:352
void SetNextHopMtu(uint16_t mtu)
Set the next hop MTU.
Definition: icmpv4.cc:324
void SetHeader(Ipv4Header header)
Set the ICMP carried IPv4 header.
Definition: icmpv4.cc:345
void SetData(Ptr< const Packet > data)
Set the ICMP carried data.
Definition: icmpv4.cc:338
ICMP Echo header.
Definition: icmpv4.h:109
Base class for all the ICMP packet headers.
Definition: icmpv4.h:42
@ ICMPV4_TIME_EXCEEDED
Definition: icmpv4.h:52
@ ICMPV4_DEST_UNREACH
Definition: icmpv4.h:50
void SetCode(uint8_t code)
Set ICMP code.
Definition: icmpv4.cc:123
void SetType(uint8_t type)
Set ICMP type.
Definition: icmpv4.cc:116
void EnableChecksum()
Enables ICMP Checksum calculation.
Definition: icmpv4.cc:60
uint8_t GetCode() const
Get ICMP code.
Definition: icmpv4.cc:137
uint8_t GetType() const
Get ICMP type.
Definition: icmpv4.cc:130
This is the implementation of the ICMP protocol as described in RFC 792.
void SetDownTarget6(IpL4Protocol::DownTargetCallback6 cb) override
This method allows a caller to set the current down target callback set for this L4 protocol (IPv6 ca...
Ptr< Node > m_node
the node this protocol is associated with
void SendTimeExceededTtl(Ipv4Header header, Ptr< const Packet > orgData, bool isFragment)
Send a Time Exceeded ICMP error.
static const uint8_t PROT_NUMBER
ICMP protocol number (0x1)
void SetDownTarget(IpL4Protocol::DownTargetCallback cb) override
This method allows a caller to set the current down target callback set for this L4 protocol (IPv4 ca...
void SendDestUnreach(Ipv4Header header, Ptr< const Packet > orgData, uint8_t code, uint16_t nextHopMtu)
Send an ICMP Destination Unreachable packet.
void DoDispose() override
Destructor implementation.
IpL4Protocol::DownTargetCallback6 GetDownTarget6() const override
This method allows a caller to get the current down target callback set for this L4 protocol (IPv6 ca...
static TypeId GetTypeId()
Get the type ID.
void SetNode(Ptr< Node > node)
Set the node the protocol is associated with.
void SendDestUnreachPort(Ipv4Header header, Ptr< const Packet > orgData)
Send a Time Exceeded ICMP error.
static uint16_t GetStaticProtocolNumber()
Get the protocol number.
IpL4Protocol::DownTargetCallback GetDownTarget() const override
This method allows a caller to get the current down target callback set for this L4 protocol (IPv4 ca...
void HandleEcho(Ptr< Packet > p, Icmpv4Header header, Ipv4Address source, Ipv4Address destination)
Handles an incoming ICMP Echo packet.
void NotifyNewAggregate() override
Notify all Objects aggregated to this one of a new Object being aggregated.
void HandleTimeExceeded(Ptr< Packet > p, Icmpv4Header icmp, Ipv4Address source, Ipv4Address destination)
Handles an incoming ICMP Time Exceeded packet.
IpL4Protocol::DownTargetCallback m_downTarget
callback to Ipv4::Send
enum IpL4Protocol::RxStatus Receive(Ptr< Packet > p, const Ipv4Header &header, Ptr< Ipv4Interface > incomingInterface) override
Receive method.
void SendDestUnreachFragNeeded(Ipv4Header header, Ptr< const Packet > orgData, uint16_t nextHopMtu)
Send a Destination Unreachable - Fragmentation needed ICMP error.
void SendMessage(Ptr< Packet > packet, Ipv4Address dest, uint8_t type, uint8_t code)
Send a generic ICMP packet.
void HandleDestUnreach(Ptr< Packet > p, Icmpv4Header header, Ipv4Address source, Ipv4Address destination)
Handles an incoming ICMP Destination Unreachable packet.
int GetProtocolNumber() const override
Get the protocol number.
void Forward(Ipv4Address source, Icmpv4Header icmp, uint32_t info, Ipv4Header ipHeader, const uint8_t payload[8])
Forward the message to an L4 protocol.
ICMP Time Exceeded header.
Definition: icmpv4.h:249
Ipv4Header GetHeader() const
Get the ICMP carried IPv4 header.
Definition: icmpv4.cc:476
void SetHeader(Ipv4Header header)
Set the ICMP carried IPv4 header.
Definition: icmpv4.cc:462
void GetData(uint8_t payload[8]) const
Get the ICMP carried data.
Definition: icmpv4.cc:469
void SetData(Ptr< const Packet > data)
Get the ICMP carried data.
Definition: icmpv4.cc:455
L4 Protocol abstract base class.
Callback< void, Ptr< Packet >, Ipv6Address, Ipv6Address, uint8_t, Ptr< Ipv6Route > > DownTargetCallback6
callback to send packets over IPv6
RxStatus
Rx status codes.
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:43
bool IsBroadcast() const
Packet header for IPv4.
Definition: ipv4-header.h:34
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:309
Ipv4Address GetSource() const
Definition: ipv4-header.cc:302
uint8_t GetProtocol() const
Definition: ipv4-header.cc:281
Ipv4Address GetDestination() const
Definition: ipv4-header.cc:316
void SetProtocol(uint8_t num)
Definition: ipv4-header.cc:288
uint8_t GetTtl() const
Definition: ipv4-header.cc:274
Access to the IPv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:79
virtual void Send(Ptr< Packet > packet, Ipv4Address source, Ipv4Address destination, uint8_t protocol, Ptr< Ipv4Route > route)=0
a class to store IPv4 address information on an interface
bool IsInSameSubnet(const Ipv4Address b) const
Checks if the address is in the same subnet.
Ipv4Address GetAddress() const
Get the local address.
uint32_t GetNAddresses() const
Ipv4InterfaceAddress GetAddress(uint32_t index) const
static bool ChecksumEnabled()
Definition: node.cc:290
virtual void NotifyNewAggregate()
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:332
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:353
uint32_t RemoveHeader(Header &header)
Deserialize and remove the header from the internal buffer.
Definition: packet.cc:294
void AddHeader(const Header &header)
Add header to this packet.
Definition: packet.cc:268
uint32_t PeekHeader(Header &header) const
Deserialize but does not remove the header from the internal buffer.
Definition: packet.cc:305
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
a unique identifier for an interface.
Definition: type-id.h:60
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:935
#define NS_ASSERT(condition)
At runtime, in debugging builds, if this condition is not true, the program prints the source file,...
Definition: assert.h:66
#define NS_LOG_COMPONENT_DEFINE(name)
Define a Log component with a specific name.
Definition: log.h:202
#define NS_LOG_DEBUG(msg)
Use NS_LOG to output a message of level LOG_DEBUG.
Definition: log.h:268
#define NS_LOG_LOGIC(msg)
Use NS_LOG to output a message of level LOG_LOGIC.
Definition: log.h:282
#define NS_LOG_FUNCTION_NOARGS()
Output the name of the function.
#define NS_LOG_FUNCTION(parameters)
If log level LOG_FUNCTION is enabled, this macro will output all input parameters separated by ",...
#define NS_LOG_WARN(msg)
Use NS_LOG to output a message of level LOG_WARN.
Definition: log.h:261
#define NS_OBJECT_ENSURE_REGISTERED(type)
Register an Object subclass with the TypeId system.
Definition: object-base.h:46
Every class exported by the ns3 library is enclosed in the ns3 namespace.
Callback< R, Args... > MakeCallback(R(T::*memPtr)(Args...), OBJ objPtr)
Build Callbacks for class method members which take varying numbers of arguments and potentially retu...
Definition: callback.h:707