A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
icmpv4-l4-protocol.cc
Go to the documentation of this file.
1 #include "icmpv4-l4-protocol.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
23 {
24  static TypeId tid = TypeId ("ns3::Icmpv4L4Protocol")
26  .AddConstructor<Icmpv4L4Protocol> ()
27  ;
28  return tid;
29 }
30 
32  : m_node (0)
33 {
34 }
36 {
37  NS_ASSERT (m_node == 0);
38 }
39 
40 void
42 {
43  m_node = node;
44 }
45 
46 /*
47  * This method is called by AddAgregate and completes the aggregation
48  * by setting the node in the ICMP stack and adding ICMP factory to
49  * IPv4 stack connected to the node
50  */
51 void
53 {
54  if (m_node == 0)
55  {
56  Ptr<Node> node = this->GetObject<Node> ();
57  if (node != 0)
58  {
59  Ptr<Ipv4> ipv4 = this->GetObject<Ipv4> ();
60  if (ipv4 != 0 && m_downTarget.IsNull ())
61  {
62  this->SetNode (node);
63  ipv4->Insert (this);
64  Ptr<Ipv4RawSocketFactoryImpl> rawFactory = CreateObject<Ipv4RawSocketFactoryImpl> ();
65  ipv4->AggregateObject (rawFactory);
66  this->SetDownTarget (MakeCallback (&Ipv4::Send, ipv4));
67  }
68  }
69  }
71 }
72 
73 uint16_t
75 {
76  return PROT_NUMBER;
77 }
78 
79 int
81 {
82  return PROT_NUMBER;
83 }
84 void
85 Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address dest, uint8_t type, uint8_t code)
86 {
87  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
88  NS_ASSERT (ipv4 != 0 && ipv4->GetRoutingProtocol () != 0);
89  Ipv4Header header;
90  header.SetDestination (dest);
91  header.SetProtocol (PROT_NUMBER);
92  Socket::SocketErrno errno_;
93  Ptr<Ipv4Route> route;
94  Ptr<NetDevice> oif (0); //specify non-zero if bound to a source address
95  route = ipv4->GetRoutingProtocol ()->RouteOutput (packet, header, oif, errno_);
96  if (route != 0)
97  {
98  NS_LOG_LOGIC ("Route exists");
99  Ipv4Address source = route->GetSource ();
100  SendMessage (packet, source, dest, type, code, route);
101  }
102  else
103  {
104  NS_LOG_WARN ("drop icmp message");
105  }
106 }
107 
108 void
109 Icmpv4L4Protocol::SendMessage (Ptr<Packet> packet, Ipv4Address source, Ipv4Address dest, uint8_t type, uint8_t code, Ptr<Ipv4Route> route)
110 {
111  Icmpv4Header icmp;
112  icmp.SetType (type);
113  icmp.SetCode (code);
114  if (Node::ChecksumEnabled ())
115  {
116  icmp.EnableChecksum ();
117  }
118  packet->AddHeader (icmp);
119 
120  m_downTarget (packet, source, dest, PROT_NUMBER, route);
121 }
122 void
124  Ptr<const Packet> orgData,
125  uint16_t nextHopMtu)
126 {
127  NS_LOG_FUNCTION (this << header << *orgData << nextHopMtu);
128  SendDestUnreach (header, orgData, Icmpv4DestinationUnreachable::FRAG_NEEDED, nextHopMtu);
129 }
130 void
132  Ptr<const Packet> orgData)
133 {
134  NS_LOG_FUNCTION (this << header << *orgData);
136 }
137 void
139  uint8_t code, uint16_t nextHopMtu)
140 {
141  NS_LOG_FUNCTION (this << header << *orgData << (uint32_t) code << nextHopMtu);
142  Ptr<Packet> p = Create<Packet> ();
144  unreach.SetNextHopMtu (nextHopMtu);
145  unreach.SetHeader (header);
146  unreach.SetData (orgData);
147  p->AddHeader (unreach);
148  SendMessage (p, header.GetSource (), Icmpv4Header::DEST_UNREACH, code);
149 }
150 
151 void
153 {
154  NS_LOG_FUNCTION (this << header << *orgData);
155  Ptr<Packet> p = Create<Packet> ();
156  Icmpv4TimeExceeded time;
157  time.SetHeader (header);
158  time.SetData (orgData);
159  p->AddHeader (time);
161 }
162 
163 void
165  Icmpv4Header header,
166  Ipv4Address source,
167  Ipv4Address destination)
168 {
169  NS_LOG_FUNCTION (this << p << header << source << destination);
170 
171  Ptr<Packet> reply = Create<Packet> ();
172  Icmpv4Echo echo;
173  p->RemoveHeader (echo);
174  reply->AddHeader (echo);
175  SendMessage (reply, destination, source, Icmpv4Header::ECHO_REPLY, 0, 0);
176 }
177 void
179  uint32_t info, Ipv4Header ipHeader,
180  const uint8_t payload[8])
181 {
182  Ptr<Ipv4> ipv4 = m_node->GetObject<Ipv4> ();
183  Ptr<IpL4Protocol> l4 = ipv4->GetProtocol (ipHeader.GetProtocol ());
184  if (l4 != 0)
185  {
186  l4->ReceiveIcmp (source, ipHeader.GetTtl (), icmp.GetType (), icmp.GetCode (),
187  info, ipHeader.GetSource (), ipHeader.GetDestination (), payload);
188  }
189 }
190 void
192  Icmpv4Header icmp,
193  Ipv4Address source,
194  Ipv4Address destination)
195 {
196  NS_LOG_FUNCTION (this << p << icmp << source << destination);
197 
199  p->PeekHeader (unreach);
200  uint8_t payload[8];
201  unreach.GetData (payload);
202  Ipv4Header ipHeader = unreach.GetHeader ();
203  Forward (source, icmp, unreach.GetNextHopMtu (), ipHeader, payload);
204 }
205 void
207  Icmpv4Header icmp,
208  Ipv4Address source,
209  Ipv4Address destination)
210 {
211  NS_LOG_FUNCTION (this << p << icmp << source << destination);
212 
213  Icmpv4TimeExceeded time;
214  p->PeekHeader (time);
215  uint8_t payload[8];
216  time.GetData (payload);
217  Ipv4Header ipHeader = time.GetHeader ();
218  // info field is zero for TimeExceeded on linux
219  Forward (source, icmp, 0, ipHeader, payload);
220 }
221 
224  Ipv4Header const &header,
225  Ptr<Ipv4Interface> incomingInterface)
226 {
227  NS_LOG_FUNCTION (this << p << header << incomingInterface);
228 
229  Icmpv4Header icmp;
230  p->RemoveHeader (icmp);
231  switch (icmp.GetType ()) {
232  case Icmpv4Header::ECHO:
233  HandleEcho (p, icmp, header.GetSource (), header.GetDestination ());
234  break;
236  HandleDestUnreach (p, icmp, header.GetSource (), header.GetDestination ());
237  break;
239  HandleTimeExceeded (p, icmp, header.GetSource (), header.GetDestination ());
240  break;
241  default:
242  NS_LOG_DEBUG (icmp << " " << *p);
243  break;
244  }
245  return IpL4Protocol::RX_OK;
246 }
249  Ipv6Address &src,
250  Ipv6Address &dst,
251  Ptr<Ipv6Interface> incomingInterface)
252 {
253  NS_LOG_FUNCTION (this << p << src << dst << incomingInterface);
255 }
256 void
258 {
259  NS_LOG_FUNCTION (this);
260  m_node = 0;
263 }
264 
265 void
267 {
268  m_downTarget = callback;
269 }
270 
271 void
273 {
274 }
275 
278 {
279  return m_downTarget;
280 }
281 
284 {
286 }
287 
288 } // namespace ns3