1 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2 /*
3  * Copyright (c) 2008 INRIA
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation;
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  *
18  * Author: Mathieu Lacage <mathieu.lacage@sophia.inria.fr>
19  */
20 
21 #include "icmpv4.h"
22 #include "ns3/packet.h"
23 #include "ns3/log.h"
24 
25 namespace ns3 {
26 
27 NS_LOG_COMPONENT_DEFINE ("Icmpv4Header");
28 
29 /********************************************************
30  *        Icmpv4Header
31  ********************************************************/
32 
33 NS_OBJECT_ENSURE_REGISTERED (Icmpv4Header);
34 
35 TypeId
GetTypeId(void)36 Icmpv4Header::GetTypeId (void)
37 {
38   static TypeId tid = TypeId ("ns3::Icmpv4Header")
39     .SetParent<Header> ()
40     .SetGroupName ("Internet")
41     .AddConstructor<Icmpv4Header> ()
42   ;
43   return tid;
44 }
Icmpv4Header()45 Icmpv4Header::Icmpv4Header ()
46   : m_type (0),
47     m_code (0),
48     m_calcChecksum (false)
49 {
50   NS_LOG_FUNCTION (this);
51 }
~Icmpv4Header()52 Icmpv4Header::~Icmpv4Header ()
53 {
54   NS_LOG_FUNCTION (this);
55 }
56 void
EnableChecksum(void)57 Icmpv4Header::EnableChecksum (void)
58 {
59   NS_LOG_FUNCTION (this);
60   m_calcChecksum = true;
61 }
62 TypeId
GetInstanceTypeId(void) const63 Icmpv4Header::GetInstanceTypeId (void) const
64 {
65   NS_LOG_FUNCTION (this);
66   return GetTypeId ();
67 }
68 uint32_t
GetSerializedSize(void) const69 Icmpv4Header::GetSerializedSize (void) const
70 {
71   NS_LOG_FUNCTION (this);
72   return 4;
73 }
74 void
Serialize(Buffer::Iterator start) const75 Icmpv4Header::Serialize (Buffer::Iterator start) const
76 {
77   NS_LOG_FUNCTION (this << &start);
78   Buffer::Iterator i = start;
79   i.WriteU8 (m_type);
80   i.WriteU8 (m_code);
81   i.WriteHtonU16 (0);
82   if (m_calcChecksum)
83     {
84       i = start;
85       uint16_t checksum = i.CalculateIpChecksum (i.GetSize ());
86       i = start;
87       i.Next (2);
88       i.WriteU16 (checksum);
89     }
90 
91 }
92 uint32_t
Deserialize(Buffer::Iterator start)93 Icmpv4Header::Deserialize (Buffer::Iterator start)
94 {
95   NS_LOG_FUNCTION (this << &start);
96   m_type = start.ReadU8 ();
97   m_code = start.ReadU8 ();
98   start.Next (2); // uint16_t checksum = start.ReadNtohU16 ();
99   return 4;
100 }
101 void
Print(std::ostream & os) const102 Icmpv4Header::Print (std::ostream &os) const
103 {
104   NS_LOG_FUNCTION (this << &os);
105   os << "type=" << (uint32_t)m_type << ", code=" << (uint32_t)m_code;
106 }
107 
108 void
SetType(uint8_t type)109 Icmpv4Header::SetType (uint8_t type)
110 {
111   NS_LOG_FUNCTION (this << static_cast<uint32_t> (type));
112   m_type = type;
113 }
114 void
SetCode(uint8_t code)115 Icmpv4Header::SetCode (uint8_t code)
116 {
117   NS_LOG_FUNCTION (this << static_cast<uint32_t> (code));
118   m_code = code;
119 }
120 uint8_t
GetType(void) const121 Icmpv4Header::GetType (void) const
122 {
123   NS_LOG_FUNCTION (this);
124   return m_type;
125 }
126 uint8_t
GetCode(void) const127 Icmpv4Header::GetCode (void) const
128 {
129   NS_LOG_FUNCTION (this);
130   return m_code;
131 }
132 
133 /********************************************************
134  *        Icmpv4Echo
135  ********************************************************/
136 
137 NS_OBJECT_ENSURE_REGISTERED (Icmpv4Echo);
138 
139 void
SetIdentifier(uint16_t id)140 Icmpv4Echo::SetIdentifier (uint16_t id)
141 {
142   NS_LOG_FUNCTION (this << id);
143   m_identifier = id;
144 }
145 void
SetSequenceNumber(uint16_t seq)146 Icmpv4Echo::SetSequenceNumber (uint16_t seq)
147 {
148   NS_LOG_FUNCTION (this << seq);
149   m_sequence = seq;
150 }
151 void
SetData(Ptr<const Packet> data)152 Icmpv4Echo::SetData (Ptr<const Packet> data)
153 {
154   NS_LOG_FUNCTION (this << *data);
155 
156   uint32_t size = data->GetSize ();
157   //
158   // All kinds of optimizations are possible, but let's not get carried away
159   // since this is probably a very uncommon thing in the big picture.
160   //
161   // N.B. Zero is a legal size for the alloc below even though a hardcoded zero
162   // would result in  warning.
163   //
164   if (size != m_dataSize)
165     {
166       delete [] m_data;
167       m_data = new uint8_t[size];
168       m_dataSize = size;
169     }
170   data->CopyData (m_data, size);
171 }
172 uint16_t
GetIdentifier(void) const173 Icmpv4Echo::GetIdentifier (void) const
174 {
175   NS_LOG_FUNCTION (this);
176   return m_identifier;
177 }
178 uint16_t
GetSequenceNumber(void) const179 Icmpv4Echo::GetSequenceNumber (void) const
180 {
181   NS_LOG_FUNCTION (this);
182   return m_sequence;
183 }
184 uint32_t
GetDataSize(void) const185 Icmpv4Echo::GetDataSize (void) const
186 {
187   NS_LOG_FUNCTION (this);
188   return m_dataSize;
189 }
190 uint32_t
GetData(uint8_t payload[]) const191 Icmpv4Echo::GetData (uint8_t payload[]) const
192 {
193   NS_LOG_FUNCTION (this << payload);
194   memcpy (payload, m_data, m_dataSize);
195   return m_dataSize;
196 }
197 TypeId
GetTypeId(void)198 Icmpv4Echo::GetTypeId (void)
199 {
200   static TypeId tid = TypeId ("ns3::Icmpv4Echo")
201     .SetParent<Header> ()
202     .SetGroupName ("Internet")
203     .AddConstructor<Icmpv4Echo> ()
204   ;
205   return tid;
206 }
Icmpv4Echo()207 Icmpv4Echo::Icmpv4Echo ()
208   : m_identifier (0),
209     m_sequence (0),
210     m_dataSize (0)
211 {
212   NS_LOG_FUNCTION (this);
213   //
214   // After construction, m_data is always valid until destruction.  This is true
215   // even if m_dataSize is zero.
216   //
217   m_data = new uint8_t[m_dataSize];
218 }
~Icmpv4Echo()219 Icmpv4Echo::~Icmpv4Echo ()
220 {
221   NS_LOG_FUNCTION (this);
222   delete [] m_data;
223   m_data = 0;
224   m_dataSize = 0;
225 }
226 TypeId
GetInstanceTypeId(void) const227 Icmpv4Echo::GetInstanceTypeId (void) const
228 {
229   NS_LOG_FUNCTION (this);
230   return GetTypeId ();
231 }
232 uint32_t
GetSerializedSize(void) const233 Icmpv4Echo::GetSerializedSize (void) const
234 {
235   NS_LOG_FUNCTION (this);
236   return 4 + m_dataSize;
237 }
238 void
Serialize(Buffer::Iterator start) const239 Icmpv4Echo::Serialize (Buffer::Iterator start) const
240 {
241   NS_LOG_FUNCTION (this << &start);
242   start.WriteHtonU16 (m_identifier);
243   start.WriteHtonU16 (m_sequence);
244   start.Write (m_data, m_dataSize);
245 }
246 uint32_t
Deserialize(Buffer::Iterator start)247 Icmpv4Echo::Deserialize (Buffer::Iterator start)
248 {
249   NS_LOG_FUNCTION (this << &start);
250 
251   uint32_t optionalPayloadSize = start.GetRemainingSize () -4;
252   NS_ASSERT (start.GetRemainingSize () >= 4);
253 
254   m_identifier = start.ReadNtohU16 ();
255   m_sequence = start.ReadNtohU16 ();
256   if (optionalPayloadSize != m_dataSize)
257     {
258       delete [] m_data;
259       m_dataSize = optionalPayloadSize;
260       m_data = new uint8_t[m_dataSize];
261     }
262   start.Read (m_data, m_dataSize);
263   return m_dataSize+4;
264 }
265 void
Print(std::ostream & os) const266 Icmpv4Echo::Print (std::ostream &os) const
267 {
268   NS_LOG_FUNCTION (this << &os);
269   os << "identifier=" << m_identifier << ", sequence="  << m_sequence << ", data size=" << m_dataSize;
270 }
271 
272 
273 /********************************************************
274  *        Icmpv4DestinationUnreachable
275  ********************************************************/
276 
277 NS_OBJECT_ENSURE_REGISTERED (Icmpv4DestinationUnreachable);
278 
279 TypeId
GetTypeId(void)280 Icmpv4DestinationUnreachable::GetTypeId (void)
281 {
282   static TypeId tid = TypeId ("ns3::Icmpv4DestinationUnreachable")
283     .SetParent<Header> ()
284     .SetGroupName ("Internet")
285     .AddConstructor<Icmpv4DestinationUnreachable> ()
286   ;
287   return tid;
288 }
Icmpv4DestinationUnreachable()289 Icmpv4DestinationUnreachable::Icmpv4DestinationUnreachable ()
290 {
291   NS_LOG_FUNCTION (this);
292   // make sure that thing is initialized to get initialized bytes
293   // when the ip payload's size is smaller than 8 bytes.
294   for (uint8_t j = 0; j < 8; j++)
295     {
296       m_data[j] = 0;
297     }
298 }
299 
300 void
SetNextHopMtu(uint16_t mtu)301 Icmpv4DestinationUnreachable::SetNextHopMtu (uint16_t mtu)
302 {
303   NS_LOG_FUNCTION (this << mtu);
304   m_nextHopMtu = mtu;
305 }
306 uint16_t
GetNextHopMtu(void) const307 Icmpv4DestinationUnreachable::GetNextHopMtu (void) const
308 {
309   NS_LOG_FUNCTION (this);
310   return m_nextHopMtu;
311 }
312 
313 void
SetData(Ptr<const Packet> data)314 Icmpv4DestinationUnreachable::SetData (Ptr<const Packet> data)
315 {
316   NS_LOG_FUNCTION (this << *data);
317   data->CopyData (m_data, 8);
318 }
319 void
SetHeader(Ipv4Header header)320 Icmpv4DestinationUnreachable::SetHeader (Ipv4Header header)
321 {
322   NS_LOG_FUNCTION (this << header);
323   m_header = header;
324 }
325 void
GetData(uint8_t payload[8]) const326 Icmpv4DestinationUnreachable::GetData (uint8_t payload[8]) const
327 {
328   NS_LOG_FUNCTION (this << payload);
329   memcpy (payload, m_data, 8);
330 }
331 Ipv4Header
GetHeader(void) const332 Icmpv4DestinationUnreachable::GetHeader (void) const
333 {
334   NS_LOG_FUNCTION (this);
335   return m_header;
336 }
337 
338 
~Icmpv4DestinationUnreachable()339 Icmpv4DestinationUnreachable::~Icmpv4DestinationUnreachable ()
340 {
341 }
342 TypeId
GetInstanceTypeId(void) const343 Icmpv4DestinationUnreachable::GetInstanceTypeId (void) const
344 {
345   NS_LOG_FUNCTION (this);
346   return GetTypeId ();
347 }
348 uint32_t
GetSerializedSize(void) const349 Icmpv4DestinationUnreachable::GetSerializedSize (void) const
350 {
351   NS_LOG_FUNCTION (this);
352   return 4 + m_header.GetSerializedSize () + 8;
353 }
354 void
Serialize(Buffer::Iterator start) const355 Icmpv4DestinationUnreachable::Serialize (Buffer::Iterator start) const
356 {
357   NS_LOG_FUNCTION (this << &start);
358   start.WriteU16 (0);
359   start.WriteHtonU16 (m_nextHopMtu);
360   uint32_t size = m_header.GetSerializedSize ();
361   m_header.Serialize (start);
362   start.Next (size);
363   start.Write (m_data, 8);
364 }
365 
366 uint32_t
Deserialize(Buffer::Iterator start)367 Icmpv4DestinationUnreachable::Deserialize (Buffer::Iterator start)
368 {
369   NS_LOG_FUNCTION (this << &start);
370   Buffer::Iterator i = start;
371   i.Next (2);
372   m_nextHopMtu = i.ReadNtohU16 ();
373   uint32_t read = m_header.Deserialize (i);
374   i.Next (read);
375   for (uint8_t j = 0; j < 8; j++)
376     {
377       m_data[j] = i.ReadU8 ();
378     }
379   return i.GetDistanceFrom (start);
380 }
381 void
Print(std::ostream & os) const382 Icmpv4DestinationUnreachable::Print (std::ostream &os) const
383 {
384   NS_LOG_FUNCTION (this << &os);
385   m_header.Print (os);
386   os << " org data=";
387   for (uint8_t i = 0; i < 8; i++)
388     {
389       os << (uint32_t) m_data[i];
390       if (i != 8)
391         {
392           os << " ";
393         }
394     }
395 }
396 
397 /********************************************************
398  *        Icmpv4TimeExceeded
399  ********************************************************/
400 
401 NS_OBJECT_ENSURE_REGISTERED (Icmpv4TimeExceeded);
402 
403 TypeId
GetTypeId(void)404 Icmpv4TimeExceeded::GetTypeId (void)
405 {
406   static TypeId tid = TypeId ("ns3::Icmpv4TimeExceeded")
407     .SetParent<Header> ()
408     .SetGroupName ("Internet")
409     .AddConstructor<Icmpv4TimeExceeded> ()
410   ;
411   return tid;
412 }
Icmpv4TimeExceeded()413 Icmpv4TimeExceeded::Icmpv4TimeExceeded ()
414 {
415   NS_LOG_FUNCTION (this);
416   // make sure that thing is initialized to get initialized bytes
417   // when the ip payload's size is smaller than 8 bytes.
418   for (uint8_t j = 0; j < 8; j++)
419     {
420       m_data[j] = 0;
421     }
422 }
423 
424 
425 void
SetData(Ptr<const Packet> data)426 Icmpv4TimeExceeded::SetData (Ptr<const Packet> data)
427 {
428   NS_LOG_FUNCTION (this << *data);
429   data->CopyData (m_data, 8);
430 }
431 void
SetHeader(Ipv4Header header)432 Icmpv4TimeExceeded::SetHeader (Ipv4Header header)
433 {
434   NS_LOG_FUNCTION (this << header);
435   m_header = header;
436 }
437 void
GetData(uint8_t payload[8]) const438 Icmpv4TimeExceeded::GetData (uint8_t payload[8]) const
439 {
440   NS_LOG_FUNCTION (this << payload);
441   memcpy (payload, m_data, 8);
442 }
443 Ipv4Header
GetHeader(void) const444 Icmpv4TimeExceeded::GetHeader (void) const
445 {
446   NS_LOG_FUNCTION (this);
447   return m_header;
448 }
449 
450 
~Icmpv4TimeExceeded()451 Icmpv4TimeExceeded::~Icmpv4TimeExceeded ()
452 {
453   NS_LOG_FUNCTION (this);
454 }
455 TypeId
GetInstanceTypeId(void) const456 Icmpv4TimeExceeded::GetInstanceTypeId (void) const
457 {
458   NS_LOG_FUNCTION (this);
459   return GetTypeId ();
460 }
461 uint32_t
GetSerializedSize(void) const462 Icmpv4TimeExceeded::GetSerializedSize (void) const
463 {
464   NS_LOG_FUNCTION (this);
465   return 4 + m_header.GetSerializedSize () + 8;
466 }
467 void
Serialize(Buffer::Iterator start) const468 Icmpv4TimeExceeded::Serialize (Buffer::Iterator start) const
469 {
470   NS_LOG_FUNCTION (this << &start);
471   start.WriteU32 (0);
472   uint32_t size = m_header.GetSerializedSize ();
473   m_header.Serialize (start);
474   start.Next (size);
475   start.Write (m_data, 8);
476 }
477 
478 uint32_t
Deserialize(Buffer::Iterator start)479 Icmpv4TimeExceeded::Deserialize (Buffer::Iterator start)
480 {
481   NS_LOG_FUNCTION (this << &start);
482   Buffer::Iterator i = start;
483   i.Next (4);
484   uint32_t read = m_header.Deserialize (i);
485   i.Next (read);
486   for (uint8_t j = 0; j < 8; j++)
487     {
488       m_data[j] = i.ReadU8 ();
489     }
490   return i.GetDistanceFrom (start);
491 }
492 void
Print(std::ostream & os) const493 Icmpv4TimeExceeded::Print (std::ostream &os) const
494 {
495   NS_LOG_FUNCTION (this << &os);
496   m_header.Print (os);
497   os << " org data=";
498   for (uint8_t i = 0; i < 8; i++)
499     {
500       os << (uint32_t) m_data[i];
501       if (i != 8)
502         {
503           os << " ";
504         }
505     }
506 }
507 
508 } // namespace ns3
509