A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
icmpv4-l4-protocol.cc
1 #include "icmpv4-l4-protocol.h"
2 #include "ipv4-raw-socket-factory-impl.h"
3 #include "ipv4-interface.h"
4 #include "ipv4-l3-protocol.h"
5 #include "ns3/assert.h"
6 #include "ns3/log.h"
7 #include "ns3/node.h"
8 #include "ns3/packet.h"
9 #include "ns3/boolean.h"
10 #include "ns3/ipv4-route.h"
11 
12 namespace ns3 {
13 
14 NS_LOG_COMPONENT_DEFINE ("Icmpv4L4Protocol");
15 
16 NS_OBJECT_ENSURE_REGISTERED (Icmpv4L4Protocol);
17 
18 // see rfc 792
19 const uint8_t Icmpv4L4Protocol::PROT_NUMBER = 1;
20 
21 TypeId
22 Icmpv4L4Protocol::GetTypeId (void)
23 {
24  static TypeId tid = TypeId ("ns3::Icmpv4L4Protocol")
25  .SetParent<IpL4Protocol> ()
26  .AddConstructor<Icmpv4L4Protocol> ()
27  ;
28  return tid;
29 }
30 
31 Icmpv4L4Protocol::Icmpv4L4Protocol ()
32  : m_node (0)
33 {
34  NS_LOG_FUNCTION (this);
35 }
36 Icmpv4L4Protocol::~Icmpv4L4Protocol ()
37 {
38  NS_LOG_FUNCTION (this);
39  NS_ASSERT (m_node == 0);
40 }
41 
42 void
43 Icmpv4L4Protocol::SetNode (Ptr<Node> node)
44 {
45  NS_LOG_FUNCTION (this << node);
46  m_node = node;
47 }
48 
49 /*
50  * This method is called by AddAgregate and completes the aggregation
51  * by setting the node in the ICMP stack and adding ICMP factory to
52  * IPv4 stack connected to the node
53  */
54 void
56 {
57  NS_LOG_FUNCTION (this);
58  if (m_node == 0)
59  {
60  Ptr<Node> node = this->GetObject<Node> ();
61  if (node != 0)
62  {
63  Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
64  if (ipv4 != 0 && m_downTarget.IsNull ())
65  {
66  this->SetNode (node);
67  ipv4->Insert (this);
68  Ptr<Ipv4RawSocketFactoryImpl> rawFactory = CreateObject<Ipv4RawSocketFactoryImpl> ();
69  ipv4->AggregateObject (rawFactory);
70  this->SetDownTarget (MakeCallback (&Ipv4::Send, ipv4));
71  }
72  }
73  }
75 }
76 
77 uint16_t
78 Icmpv4L4Protocol::GetStaticProtocolNumber (void)
79 {
81  return PROT_NUMBER;
82 }
83 
84 int
86 {
87  NS_LOG_FUNCTION (this);
88  return PROT_NUMBER;
89 }
90 void
91 Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address dest, uint8_t type, uint8_t code)
92 {
93  NS_LOG_FUNCTION (this << packet << dest << static_cast<uint32_t> (type) << static_cast<uint32_t> (code));
94  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
95  NS_ASSERT (ipv4 != 0 && ipv4->GetRoutingProtocol () != 0);
96  Ipv4Header header;
97  header.SetDestination (dest);
98  header.SetProtocol (PROT_NUMBER);
99  Socket::SocketErrno errno_;
100  Ptr<Ipv4Route> route;
101  Ptr<NetDevice> oif (0); //specify non-zero if bound to a source address
102  route = ipv4->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
103  if (route != 0)
104  {
105  NS_LOG_LOGIC ("Route exists");
106  Ipv4Address source = route->GetSource ();
107  SendMessage (packet, source, dest, type, code, route);
108  }
109  else
110  {
111  NS_LOG_WARN ("drop icmp message");
112  }
113 }
114 
115 void
116 Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code, Ptr<Ipv4Route> route)
117 {
118  NS_LOG_FUNCTION (this << packet << source << dest << static_cast<uint32_t> (type) << static_cast<uint32_t> (code) << route);
119  Icmpv4Header icmp;
120  icmp.SetType (type);
121  icmp.SetCode (code);
122  if (Node::ChecksumEnabled ())
123  {
124  icmp.EnableChecksum ();
125  }
126  packet->AddHeader (icmp);
127 
128  m_downTarget (packet, source, dest, PROT_NUMBER, route);
129 }
130 void
131 Icmpv4L4Protocol::SendDestUnreachFragNeeded (Ipv4Header header,
132  Ptr<const Packet> orgData,
133  uint16_t nextHopMtu)
134 {
135  NS_LOG_FUNCTION (this << header << *orgData << nextHopMtu);
136  SendDestUnreach (header, orgData, Icmpv4DestinationUnreachable::FRAG_NEEDED, nextHopMtu);
137 }
138 void
139 Icmpv4L4Protocol::SendDestUnreachPort (Ipv4Header header,
140  Ptr<const Packet> orgData)
141 {
142  NS_LOG_FUNCTION (this << header << *orgData);
143  SendDestUnreach (header, orgData, Icmpv4DestinationUnreachable::PORT_UNREACHABLE, 0);
144 }
145 void
146 Icmpv4L4Protocol::SendDestUnreach (Ipv4Header header, Ptr<const Packet> orgData,
147  uint8_t code, uint16_t nextHopMtu)
148 {
149  NS_LOG_FUNCTION (this << header << *orgData << (uint32_t) code << nextHopMtu);
150  Ptr<Packet> p = Create<Packet> ();
151  Icmpv4DestinationUnreachable unreach;
152  unreach.SetNextHopMtu (nextHopMtu);
153  unreach.SetHeader (header);
154  unreach.SetData (orgData);
155  p->AddHeader (unreach);
156  SendMessage (p, header.GetSource (), Icmpv4Header::DEST_UNREACH, code);
157 }
158 
159 void
160 Icmpv4L4Protocol::SendTimeExceededTtl (Ipv4Header header, Ptr<const Packet> orgData)
161 {
162  NS_LOG_FUNCTION (this << header << *orgData);
163  Ptr<Packet> p = Create<Packet> ();
164  Icmpv4TimeExceeded time;
165  time.SetHeader (header);
166  time.SetData (orgData);
167  p->AddHeader (time);
168  SendMessage (p, header.GetSource (), Icmpv4Header::TIME_EXCEEDED, Icmpv4TimeExceeded::TIME_TO_LIVE);
169 }
170 
171 void
172 Icmpv4L4Protocol::HandleEcho (Ptr<Packet> p,
173  Icmpv4Header header,
174  Ipv4Address source,
175  Ipv4Address destination)
176 {
177  NS_LOG_FUNCTION (this << p << header << source << destination);
178 
179  Ptr<Packet> reply = Create<Packet> ();
180  Icmpv4Echo echo;
181  p->RemoveHeader (echo);
182  reply->AddHeader (echo);
183  SendMessage (reply, destination, source, Icmpv4Header::ECHO_REPLY, 0, 0);
184 }
185 void
186 Icmpv4L4Protocol::Forward (Ipv4Address source, Icmpv4Header icmp,
187  uint32_t info, Ipv4Header ipHeader,
188  const uint8_t payload[8])
189 {
190  NS_LOG_FUNCTION (this << source << icmp << info << ipHeader << payload);
191 
192  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
193  Ptr<IpL4Protocol> l4 = ipv4->GetProtocol (ipHeader.GetProtocol ());
194  if (l4 != 0)
195  {
196  l4->ReceiveIcmp (source, ipHeader.GetTtl (), icmp.GetType (), icmp.GetCode (),
197  info, ipHeader.GetSource (), ipHeader.GetDestination (), payload);
198  }
199 }
200 void
201 Icmpv4L4Protocol::HandleDestUnreach (Ptr<Packet> p,
202  Icmpv4Header icmp,
203  Ipv4Address source,
204  Ipv4Address destination)
205 {
206  NS_LOG_FUNCTION (this << p << icmp << source << destination);
207 
208  Icmpv4DestinationUnreachable unreach;
209  p->PeekHeader (unreach);
210  uint8_t payload[8];
211  unreach.GetData (payload);
212  Ipv4Header ipHeader = unreach.GetHeader ();
213  Forward (source, icmp, unreach.GetNextHopMtu (), ipHeader, payload);
214 }
215 void
216 Icmpv4L4Protocol::HandleTimeExceeded (Ptr<Packet> p,
217  Icmpv4Header icmp,
218  Ipv4Address source,
219  Ipv4Address destination)
220 {
221  NS_LOG_FUNCTION (this << p << icmp << source << destination);
222 
223  Icmpv4TimeExceeded time;
224  p->PeekHeader (time);
225  uint8_t payload[8];
226  time.GetData (payload);
227  Ipv4Header ipHeader = time.GetHeader ();
228  // info field is zero for TimeExceeded on linux
229  Forward (source, icmp, 0, ipHeader, payload);
230 }
231 
232 enum IpL4Protocol::RxStatus
234  Ipv4Header const &header,
235  Ptr<Ipv4Interface> incomingInterface)
236 {
237  NS_LOG_FUNCTION (this << p << header << incomingInterface);
238 
239  Icmpv4Header icmp;
240  p->RemoveHeader (icmp);
241  switch (icmp.GetType ()) {
242  case Icmpv4Header::ECHO:
243  HandleEcho (p, icmp, header.GetSource (), header.GetDestination ());
244  break;
245  case Icmpv4Header::DEST_UNREACH:
246  HandleDestUnreach (p, icmp, header.GetSource (), header.GetDestination ());
247  break;
248  case Icmpv4Header::TIME_EXCEEDED:
249  HandleTimeExceeded (p, icmp, header.GetSource (), header.GetDestination ());
250  break;
251  default:
252  NS_LOG_DEBUG (icmp << " " << *p);
253  break;
254  }
255  return IpL4Protocol::RX_OK;
256 }
257 enum IpL4Protocol::RxStatus
259  Ipv6Header const &header,
260  Ptr<Ipv6Interface> incomingInterface)
261 {
262  NS_LOG_FUNCTION (this << p << header.GetSourceAddress () << header.GetDestinationAddress () << incomingInterface);
263  return IpL4Protocol::RX_ENDPOINT_UNREACH;
264 }
265 void
267 {
268  NS_LOG_FUNCTION (this);
269  m_node = 0;
270  m_downTarget.Nullify ();
272 }
273 
274 void
276 {
277  NS_LOG_FUNCTION (this << &callback);
278  m_downTarget = callback;
279 }
280 
281 void
282 Icmpv4L4Protocol::SetDownTarget6 (IpL4Protocol::DownTargetCallback6 callback)
283 {
284  NS_LOG_FUNCTION (this << &callback);
285 }
286 
287 IpL4Protocol::DownTargetCallback
289 {
290  NS_LOG_FUNCTION (this);
291  return m_downTarget;
292 }
293 
295 Icmpv4L4Protocol::GetDownTarget6 (void) const
296 {
297  NS_LOG_FUNCTION (this);
299 }
300 
301 } // namespace ns3
uint32_t RemoveHeader(Header &header)
Definition: packet.cc:285
Packet header for IPv6.
Definition: ipv6-header.h:33
void SetDestination(Ipv4Address destination)
Definition: ipv4-header.cc:297
#define NS_LOG_FUNCTION(parameters)
Definition: log.h:311
static bool ChecksumEnabled(void)
Definition: node.cc:267
Ipv4Address GetDestination(void) const
Definition: ipv4-header.cc:303
#define NS_ASSERT(condition)
Definition: assert.h:64
#define NS_LOG_COMPONENT_DEFINE(name)
Definition: log.h:122
virtual void DoDispose(void)
Definition: object.cc:335
Ipv4Address GetSource(void) const
Definition: ipv4-header.cc:290
#define NS_LOG_FUNCTION_NOARGS()
Definition: log.h:275
Packet header for IPv4.
Definition: ipv4-header.h:31
Callback< R > MakeCallback(R(T::*memPtr)(void), OBJ objPtr)
Definition: callback.h:502
Ipv4Address GetSource(void) const
Definition: ipv4-route.cc:56
#define NS_LOG_LOGIC(msg)
Definition: log.h:334
virtual IpL4Protocol::DownTargetCallback GetDownTarget(void) const
virtual void NotifyNewAggregate(void)
Definition: object.cc:314
Access to the Ipv4 forwarding table, interfaces, and configuration.
Definition: ipv4.h:75
virtual int GetProtocolNumber(void) const
virtual void Send(Ptr< Packet > packet, Ipv4Address source, Ipv4Address destination, uint8_t protocol, Ptr< Ipv4Route > route)=0
virtual void NotifyNewAggregate()
virtual enum IpL4Protocol::RxStatus Receive(Ptr< Packet > p, Ipv4Header const &header, Ptr< Ipv4Interface > incomingInterface)
Ipv4 addresses are stored in host order in this class.
Definition: ipv4-address.h:38
virtual void DoDispose(void)
#define NS_LOG_WARN(msg)
Definition: log.h:246
Ipv6Address GetSourceAddress(void) const
Get the "Source address" field.
Definition: ipv6-header.cc:101
#define NS_LOG_DEBUG(msg)
Definition: log.h:255
Ptr< T > GetObject(void) const
Definition: object.h:332
virtual void SetDownTarget(IpL4Protocol::DownTargetCallback cb)
Ipv6Address GetDestinationAddress(void) const
Get the "Destination address" field.
Definition: ipv6-header.cc:111