A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
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"
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
35namespace ns3
36{
37
38NS_LOG_COMPONENT_DEFINE("Icmpv4L4Protocol");
39
40NS_OBJECT_ENSURE_REGISTERED(Icmpv4L4Protocol);
41
42// see rfc 792
43const uint8_t Icmpv4L4Protocol::PROT_NUMBER = 1;
44
45TypeId
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);
65}
66
67void
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 */
79void
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);
96 }
97 }
98 }
100}
101
102uint16_t
104{
106 return PROT_NUMBER;
107}
108
109int
111{
112 NS_LOG_FUNCTION(this);
113 return PROT_NUMBER;
114}
115
116void
117Icmpv4L4Protocol::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));
121 Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4>();
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
142void
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);
156 {
157 icmp.EnableChecksum();
158 }
159 packet->AddHeader(icmp);
160
161 m_downTarget(packet, source, dest, PROT_NUMBER, route);
162}
163
164void
166 Ptr<const Packet> orgData,
167 uint16_t nextHopMtu)
168{
169 NS_LOG_FUNCTION(this << header << *orgData << nextHopMtu);
171}
172
173void
175{
176 NS_LOG_FUNCTION(this << header << *orgData);
178}
179
180void
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
196void
198{
199 NS_LOG_FUNCTION(this << header << *orgData);
200 Ptr<Packet> p = Create<Packet>();
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
221void
223 Icmpv4Header header,
224 Ipv4Address source,
225 Ipv4Address destination)
226{
227 NS_LOG_FUNCTION(this << p << header << source << destination);
228
229 Ptr<Packet> reply = Create<Packet>();
230 Icmpv4Echo echo;
231 p->RemoveHeader(echo);
232 reply->AddHeader(echo);
233 SendMessage(reply, destination, source, Icmpv4Header::ICMPV4_ECHO_REPLY, 0, nullptr);
234}
235
236void
238 Icmpv4Header icmp,
239 uint32_t info,
240 Ipv4Header ipHeader,
241 const uint8_t payload[8])
242{
243 NS_LOG_FUNCTION(this << source << icmp << info << ipHeader << payload);
244
245 Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4>();
246 Ptr<IpL4Protocol> l4 = ipv4->GetProtocol(ipHeader.GetProtocol());
247 if (l4)
248 {
249 l4->ReceiveIcmp(source,
250 ipHeader.GetTtl(),
251 icmp.GetType(),
252 icmp.GetCode(),
253 info,
254 ipHeader.GetSource(),
255 ipHeader.GetDestination(),
256 payload);
257 }
258}
259
260void
262 Icmpv4Header icmp,
263 Ipv4Address source,
264 Ipv4Address destination)
265{
266 NS_LOG_FUNCTION(this << p << icmp << source << destination);
267
269 p->PeekHeader(unreach);
270 uint8_t payload[8];
271 unreach.GetData(payload);
272 Ipv4Header ipHeader = unreach.GetHeader();
273 Forward(source, icmp, unreach.GetNextHopMtu(), ipHeader, payload);
274}
275
276void
278 Icmpv4Header icmp,
279 Ipv4Address source,
280 Ipv4Address destination)
281{
282 NS_LOG_FUNCTION(this << p << icmp << source << destination);
283
285 p->PeekHeader(time);
286 uint8_t payload[8];
287 time.GetData(payload);
288 Ipv4Header ipHeader = time.GetHeader();
289 // info field is zero for TimeExceeded on linux
290 Forward(source, icmp, 0, ipHeader, payload);
291}
292
295 const Ipv4Header& header,
296 Ptr<Ipv4Interface> incomingInterface)
297{
298 NS_LOG_FUNCTION(this << p << header << incomingInterface);
299
300 Icmpv4Header icmp;
301 p->RemoveHeader(icmp);
302 switch (icmp.GetType())
303 {
305 Ipv4Address dst = header.GetDestination();
306 // We could have received an Echo request to a broadcast-type address.
307 if (dst.IsBroadcast())
308 {
309 Ipv4Address src = header.GetSource();
310 for (uint32_t index = 0; index < incomingInterface->GetNAddresses(); index++)
311 {
312 Ipv4InterfaceAddress addr = incomingInterface->GetAddress(index);
313 if (addr.IsInSameSubnet(src))
314 {
315 dst = addr.GetAddress();
316 }
317 }
318 }
319 else
320 {
321 for (uint32_t index = 0; index < incomingInterface->GetNAddresses(); index++)
322 {
323 Ipv4InterfaceAddress addr = incomingInterface->GetAddress(index);
324 if (dst == addr.GetBroadcast())
325 {
326 dst = addr.GetAddress();
327 }
328 }
329 }
330 HandleEcho(p, icmp, header.GetSource(), dst);
331 break;
332 }
334 HandleDestUnreach(p, icmp, header.GetSource(), header.GetDestination());
335 break;
337 HandleTimeExceeded(p, icmp, header.GetSource(), header.GetDestination());
338 break;
339 default:
340 NS_LOG_DEBUG(icmp << " " << *p);
341 break;
342 }
343 return IpL4Protocol::RX_OK;
344}
345
348 const Ipv6Header& header,
349 Ptr<Ipv6Interface> incomingInterface)
350{
351 NS_LOG_FUNCTION(this << p << header.GetSource() << header.GetDestination()
352 << incomingInterface);
354}
355
356void
358{
359 NS_LOG_FUNCTION(this);
360 m_node = nullptr;
363}
364
365void
367{
368 NS_LOG_FUNCTION(this << &callback);
369 m_downTarget = callback;
370}
371
372void
374{
375 NS_LOG_FUNCTION(this << &callback);
376}
377
380{
381 NS_LOG_FUNCTION(this);
382 return m_downTarget;
383}
384
387{
388 NS_LOG_FUNCTION(this);
390}
391
392} // namespace ns3
void Nullify()
Discard the implementation, set it to null.
Definition: callback.h:573
bool IsNull() const
Check for null implementation.
Definition: callback.h:567
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::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 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
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.
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
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:78
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:936
#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:702