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 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
240void
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
249 Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4>();
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
264void
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
280void
282 Icmpv4Header icmp,
283 Ipv4Address source,
284 Ipv4Address destination)
285{
286 NS_LOG_FUNCTION(this << p << icmp << source << destination);
287
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
360void
362{
363 NS_LOG_FUNCTION(this);
364 m_node = nullptr;
367}
368
369void
371{
372 NS_LOG_FUNCTION(this << &callback);
373 m_downTarget = callback;
374}
375
376void
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.
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:423
Ptr< T > GetObject() const
Get a pointer to the requested aggregated Object.
Definition: object.h:522
virtual void DoDispose()
Destructor implementation.
Definition: object.cc:444
Smart pointer class similar to boost::intrusive_ptr.
Definition: ptr.h:77
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:1271
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:932
#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