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
34namespace ns3
35{
36
37NS_LOG_COMPONENT_DEFINE("Icmpv4L4Protocol");
38
39NS_OBJECT_ENSURE_REGISTERED(Icmpv4L4Protocol);
40
41// see rfc 792
42const uint8_t Icmpv4L4Protocol::PROT_NUMBER = 1;
43
44TypeId
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);
64}
65
66void
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 */
78void
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);
95 }
96 }
97 }
99}
100
101uint16_t
103{
105 return PROT_NUMBER;
106}
107
108int
110{
111 NS_LOG_FUNCTION(this);
112 return PROT_NUMBER;
113}
114
115void
116Icmpv4L4Protocol::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
141void
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);
155 {
156 icmp.EnableChecksum();
157 }
158 packet->AddHeader(icmp);
159
160 m_downTarget(packet, source, dest, PROT_NUMBER, route);
161}
162
163void
165 Ptr<const Packet> orgData,
166 uint16_t nextHopMtu)
167{
168 NS_LOG_FUNCTION(this << header << *orgData << nextHopMtu);
170}
171
172void
174{
175 NS_LOG_FUNCTION(this << header << *orgData);
177}
178
179void
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
195void
197{
198 NS_LOG_FUNCTION(this << header << *orgData);
199 Ptr<Packet> p = Create<Packet>();
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
220void
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
235void
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
259void
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
275void
277 Icmpv4Header icmp,
278 Ipv4Address source,
279 Ipv4Address destination)
280{
281 NS_LOG_FUNCTION(this << p << icmp << source << destination);
282
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
347 const Ipv6Header& header,
348 Ptr<Ipv6Interface> incomingInterface)
349{
350 NS_LOG_FUNCTION(this << p << header.GetSource() << header.GetDestination()
351 << incomingInterface);
353}
354
355void
357{
358 NS_LOG_FUNCTION(this);
359 m_node = nullptr;
362}
363
364void
366{
367 NS_LOG_FUNCTION(this << &callback);
368 m_downTarget = callback;
369}
370
371void
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: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 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.
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: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:59
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