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 HandleEcho(p, icmp, header.GetSource(), header.GetDestination());
305 break;
307 HandleDestUnreach(p, icmp, header.GetSource(), header.GetDestination());
308 break;
310 HandleTimeExceeded(p, icmp, header.GetSource(), header.GetDestination());
311 break;
312 default:
313 NS_LOG_DEBUG(icmp << " " << *p);
314 break;
315 }
316 return IpL4Protocol::RX_OK;
317}
318
321 const Ipv6Header& header,
322 Ptr<Ipv6Interface> incomingInterface)
323{
324 NS_LOG_FUNCTION(this << p << header.GetSource() << header.GetDestination()
325 << incomingInterface);
327}
328
329void
331{
332 NS_LOG_FUNCTION(this);
333 m_node = nullptr;
336}
337
338void
340{
341 NS_LOG_FUNCTION(this << &callback);
342 m_downTarget = callback;
343}
344
345void
347{
348 NS_LOG_FUNCTION(this << &callback);
349}
350
353{
354 NS_LOG_FUNCTION(this);
355 return m_downTarget;
356}
357
360{
361 NS_LOG_FUNCTION(this);
363}
364
365} // namespace ns3
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:562
bool IsNull() const
Check for null implementation.
Definition: callback.h:556
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
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
Packet header for IPv6.
Definition: ipv6-header.h:36
Ipv6Address GetDestination() const
Get the "Destination address" field.
Definition: ipv6-header.cc:142
Ipv6Address GetSource() const
Get the "Source address" field.
Definition: ipv6-header.cc:118
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:45
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:691