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"
24 #include "ipv4-route.h"
25 #include "ipv4-routing-protocol.h"
26 #include "ipv4.h"
27 #include "ipv6-interface.h"
28 
29 #include "ns3/assert.h"
30 #include "ns3/boolean.h"
31 #include "ns3/log.h"
32 #include "ns3/node.h"
33 #include "ns3/packet.h"
34 
35 namespace ns3
36 {
37 
38 NS_LOG_COMPONENT_DEFINE("Icmpv4L4Protocol");
39 
40 NS_OBJECT_ENSURE_REGISTERED(Icmpv4L4Protocol);
41 
42 // see rfc 792
43 const uint8_t Icmpv4L4Protocol::PROT_NUMBER = 1;
44 
45 TypeId
47 {
48  static TypeId tid = TypeId("ns3::Icmpv4L4Protocol")
50  .SetGroupName("Internet")
51  .AddConstructor<Icmpv4L4Protocol>();
52  return tid;
53 }
54 
56  : m_node(nullptr)
57 {
58  NS_LOG_FUNCTION(this);
59 }
60 
62 {
63  NS_LOG_FUNCTION(this);
64  NS_ASSERT(!m_node);
65 }
66 
67 void
69 {
70  NS_LOG_FUNCTION(this << node);
71  m_node = node;
72 }
73 
74 /*
75  * This method is called by AggregateObject and completes the aggregation
76  * by setting the node in the ICMP stack and adding ICMP factory to
77  * IPv4 stack connected to the node
78  */
79 void
81 {
82  NS_LOG_FUNCTION(this);
83  if (!m_node)
84  {
85  Ptr<Node> node = this->GetObject<Node>();
86  if (node)
87  {
88  Ptr<Ipv4> ipv4 = this->GetObject<Ipv4>();
89  if (ipv4 && m_downTarget.IsNull())
90  {
91  this->SetNode(node);
92  ipv4->Insert(this);
93  Ptr<Ipv4RawSocketFactoryImpl> rawFactory = CreateObject<Ipv4RawSocketFactoryImpl>();
94  ipv4->AggregateObject(rawFactory);
95  this->SetDownTarget(MakeCallback(&Ipv4::Send, ipv4));
96  }
97  }
98  }
100 }
101 
102 uint16_t
104 {
106  return PROT_NUMBER;
107 }
108 
109 int
111 {
112  NS_LOG_FUNCTION(this);
113  return PROT_NUMBER;
114 }
115 
116 void
117 Icmpv4L4Protocol::SendMessage(Ptr<Packet> packet, Ipv4Address dest, uint8_t type, uint8_t code)
118 {
119  NS_LOG_FUNCTION(this << packet << dest << static_cast<uint32_t>(type)
120  << static_cast<uint32_t>(code));
122  NS_ASSERT(ipv4 && ipv4->GetRoutingProtocol());
123  Ipv4Header header;
124  header.SetDestination(dest);
125  header.SetProtocol(PROT_NUMBER);
126  Socket::SocketErrno errno_;
127  Ptr<Ipv4Route> route;
128  Ptr<NetDevice> oif(nullptr); // specify non-zero if bound to a source address
129  route = ipv4->GetRoutingProtocol()->RouteOutput(packet, header, oif, errno_);
130  if (route)
131  {
132  NS_LOG_LOGIC("Route exists");
133  Ipv4Address source = route->GetSource();
134  SendMessage(packet, source, dest, type, code, route);
135  }
136  else
137  {
138  NS_LOG_WARN("drop icmp message");
139  }
140 }
141 
142 void
144  Ipv4Address source,
145  Ipv4Address dest,
146  uint8_t type,
147  uint8_t code,
148  Ptr<Ipv4Route> route)
149 {
150  NS_LOG_FUNCTION(this << packet << source << dest << static_cast<uint32_t>(type)
151  << static_cast<uint32_t>(code) << route);
152  Icmpv4Header icmp;
153  icmp.SetType(type);
154  icmp.SetCode(code);
155  if (Node::ChecksumEnabled())
156  {
157  icmp.EnableChecksum();
158  }
159  packet->AddHeader(icmp);
160 
161  m_downTarget(packet, source, dest, PROT_NUMBER, route);
162 }
163 
164 void
166  Ptr<const Packet> orgData,
167  uint16_t nextHopMtu)
168 {
169  NS_LOG_FUNCTION(this << header << *orgData << nextHopMtu);
171 }
172 
173 void
175 {
176  NS_LOG_FUNCTION(this << header << *orgData);
178 }
179 
180 void
182  Ptr<const Packet> orgData,
183  uint8_t code,
184  uint16_t nextHopMtu)
185 {
186  NS_LOG_FUNCTION(this << header << *orgData << (uint32_t)code << nextHopMtu);
187  Ptr<Packet> p = Create<Packet>();
189  unreach.SetNextHopMtu(nextHopMtu);
190  unreach.SetHeader(header);
191  unreach.SetData(orgData);
192  p->AddHeader(unreach);
194 }
195 
196 void
198 {
199  NS_LOG_FUNCTION(this << header << *orgData);
200  Ptr<Packet> p = Create<Packet>();
201  Icmpv4TimeExceeded time;
202  time.SetHeader(header);
203  time.SetData(orgData);
204  p->AddHeader(time);
205  if (!isFragment)
206  {
207  SendMessage(p,
208  header.GetSource(),
211  }
212  else
213  {
214  SendMessage(p,
215  header.GetSource(),
218  }
219 }
220 
221 void
223  Icmpv4Header header,
224  Ipv4Address source,
225  Ipv4Address destination,
226  uint8_t tos)
227 {
228  NS_LOG_FUNCTION(this << p << header << source << destination << tos);
229 
230  Ptr<Packet> reply = Create<Packet>();
231  Icmpv4Echo echo;
232  p->RemoveHeader(echo);
233  reply->AddHeader(echo);
234  SocketIpTosTag ipTosTag;
235  ipTosTag.SetTos(tos);
236  reply->ReplacePacketTag(ipTosTag);
237  SendMessage(reply, destination, source, Icmpv4Header::ICMPV4_ECHO_REPLY, 0, nullptr);
238 }
239 
240 void
242  Icmpv4Header icmp,
243  uint32_t info,
244  Ipv4Header ipHeader,
245  const uint8_t payload[8])
246 {
247  NS_LOG_FUNCTION(this << source << icmp << info << ipHeader << payload);
248 
250  Ptr<IpL4Protocol> l4 = ipv4->GetProtocol(ipHeader.GetProtocol());
251  if (l4)
252  {
253  l4->ReceiveIcmp(source,
254  ipHeader.GetTtl(),
255  icmp.GetType(),
256  icmp.GetCode(),
257  info,
258  ipHeader.GetSource(),
259  ipHeader.GetDestination(),
260  payload);
261  }
262 }
263 
264 void
266  Icmpv4Header icmp,
267  Ipv4Address source,
268  Ipv4Address destination)
269 {
270  NS_LOG_FUNCTION(this << p << icmp << source << destination);
271 
273  p->PeekHeader(unreach);
274  uint8_t payload[8];
275  unreach.GetData(payload);
276  Ipv4Header ipHeader = unreach.GetHeader();
277  Forward(source, icmp, unreach.GetNextHopMtu(), ipHeader, payload);
278 }
279 
280 void
282  Icmpv4Header icmp,
283  Ipv4Address source,
284  Ipv4Address destination)
285 {
286  NS_LOG_FUNCTION(this << p << icmp << source << destination);
287 
288  Icmpv4TimeExceeded time;
289  p->PeekHeader(time);
290  uint8_t payload[8];
291  time.GetData(payload);
292  Ipv4Header ipHeader = time.GetHeader();
293  // info field is zero for TimeExceeded on linux
294  Forward(source, icmp, 0, ipHeader, payload);
295 }
296 
299  const Ipv4Header& header,
300  Ptr<Ipv4Interface> incomingInterface)
301 {
302  NS_LOG_FUNCTION(this << p << header << incomingInterface);
303 
304  Icmpv4Header icmp;
305  p->RemoveHeader(icmp);
306  switch (icmp.GetType())
307  {
309  Ipv4Address dst = header.GetDestination();
310  // We could have received an Echo request to a broadcast-type address.
311  if (dst.IsBroadcast())
312  {
313  Ipv4Address src = header.GetSource();
314  for (uint32_t index = 0; index < incomingInterface->GetNAddresses(); index++)
315  {
316  Ipv4InterfaceAddress addr = incomingInterface->GetAddress(index);
317  if (addr.IsInSameSubnet(src))
318  {
319  dst = addr.GetAddress();
320  }
321  }
322  }
323  else
324  {
325  for (uint32_t index = 0; index < incomingInterface->GetNAddresses(); index++)
326  {
327  Ipv4InterfaceAddress addr = incomingInterface->GetAddress(index);
328  if (dst == addr.GetBroadcast())
329  {
330  dst = addr.GetAddress();
331  }
332  }
333  }
334  HandleEcho(p, icmp, header.GetSource(), dst, header.GetTos());
335  break;
336  }
338  HandleDestUnreach(p, icmp, header.GetSource(), header.GetDestination());
339  break;
341  HandleTimeExceeded(p, icmp, header.GetSource(), header.GetDestination());
342  break;
343  default:
344  NS_LOG_DEBUG(icmp << " " << *p);
345  break;
346  }
347  return IpL4Protocol::RX_OK;
348 }
349 
352  const Ipv6Header& header,
353  Ptr<Ipv6Interface> incomingInterface)
354 {
355  NS_LOG_FUNCTION(this << p << header.GetSource() << header.GetDestination()
356  << incomingInterface);
358 }
359 
360 void
362 {
363  NS_LOG_FUNCTION(this);
364  m_node = nullptr;
367 }
368 
369 void
371 {
372  NS_LOG_FUNCTION(this << &callback);
373  m_downTarget = callback;
374 }
375 
376 void
378 {
379  NS_LOG_FUNCTION(this << &callback);
380 }
381 
384 {
385  NS_LOG_FUNCTION(this);
386  return m_downTarget;
387 }
388 
391 {
392  NS_LOG_FUNCTION(this);
394 }
395 
396 } // namespace ns3
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:575
bool IsNull() const
Check for null implementation.
Definition: callback.h:569
ICMP Destination Unreachable header.
Definition: icmpv4.h:175
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:110
Base class for all the ICMP packet headers.
Definition: icmpv4.h:43
@ ICMPV4_TIME_EXCEEDED
Definition: icmpv4.h:53
@ ICMPV4_DEST_UNREACH
Definition: icmpv4.h:51
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 HandleEcho(Ptr< Packet > p, Icmpv4Header header, Ipv4Address source, Ipv4Address destination, uint8_t tos)
Handles an incoming ICMP Echo packet.
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::RxStatus Receive(Ptr< Packet > p, const Ipv4Header &header, Ptr< Ipv4Interface > incomingInterface) override
Receive method.
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 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
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:250
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:42
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 GetTos() const
Definition: ipv4-header.cc:196
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:80
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.
Ipv4Address GetBroadcast() const
Get the broadcast address.
uint32_t GetNAddresses() const
Ipv4InterfaceAddress GetAddress(uint32_t index) const
Packet header for IPv6.
Definition: ipv6-header.h:35
Ipv6Address GetDestination() const
Get the "Destination address" field.
Definition: ipv6-header.cc:124
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:112
static bool ChecksumEnabled()
Definition: node.cc:285
virtual void NotifyNewAggregate()
Notify all Objects aggregated to this one of a new Object being aggregated.
Definition: object.cc:331
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:471
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:352
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
bool ReplacePacketTag(Tag &tag)
Replace the value of a packet tag.
Definition: packet.cc:975
SocketErrno
Enumeration of the possible errors returned by a socket.
Definition: socket.h:84
indicates whether the socket has IP_TOS set.
Definition: socket.h:1269
void SetTos(uint8_t tos)
Set the tag's TOS.
Definition: socket.cc:798
a unique identifier for an interface.
Definition: type-id.h:59
TypeId SetParent(TypeId tid)
Set the parent TypeId.
Definition: type-id.cc:931
#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:704