A Discrete-Event Network Simulator
API
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
icmpv4.cc
Go to the documentation of this file.
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 
24 namespace ns3 {
25 
26 /********************************************************
27  * Icmpv4Header
28  ********************************************************/
29 
30 NS_OBJECT_ENSURE_REGISTERED (Icmpv4Header);
31 
32 TypeId
34 {
35  static TypeId tid = TypeId ("ns3::Icmpv4Header")
36  .SetParent<Header> ()
37  .AddConstructor<Icmpv4Header> ()
38  ;
39  return tid;
40 }
42  : m_type (0),
43  m_code (0),
44  m_calcChecksum (false)
45 {
46 }
48 {
49 }
50 void
52 {
53  m_calcChecksum = true;
54 }
55 TypeId
57 {
58  return GetTypeId ();
59 }
60 uint32_t
62 {
63  return 4;
64 }
65 void
67 {
69  i.WriteU8 (m_type);
70  i.WriteU8 (m_code);
71  i.WriteHtonU16 (0);
72  if (m_calcChecksum)
73  {
74  i = start;
75  uint16_t checksum = i.CalculateIpChecksum (i.GetSize ());
76  i = start;
77  i.Next (2);
78  i.WriteU16 (checksum);
79  }
80 
81 }
82 uint32_t
84 {
85  m_type = start.ReadU8 ();
86  m_code = start.ReadU8 ();
87  start.Next (2); // uint16_t checksum = start.ReadNtohU16 ();
88  return 4;
89 }
90 void
91 Icmpv4Header::Print (std::ostream &os) const
92 {
93  os << "type=" << (uint32_t)m_type << ", code=" << (uint32_t)m_code;
94 }
95 
96 void
97 Icmpv4Header::SetType (uint8_t type)
98 {
99  m_type = type;
100 }
101 void
102 Icmpv4Header::SetCode (uint8_t code)
103 {
104  m_code = code;
105 }
106 uint8_t
108 {
109  return m_type;
110 }
111 uint8_t
113 {
114  return m_code;
115 }
116 
117 /********************************************************
118  * Icmpv4Echo
119  ********************************************************/
120 
122 
123 void
125 {
126  m_identifier = id;
127 }
128 void
130 {
131  m_sequence = seq;
132 }
133 void
135 {
136  uint32_t size = data->GetSize ();
137  //
138  // All kinds of optimizations are possible, but let's not get carried away
139  // since this is probably a very uncommon thing in the big picture.
140  //
141  // N.B. Zero is a legal size for the alloc below even though a hardcoded zero
142  // would result in warning.
143  //
144  if (size != m_dataSize)
145  {
146  delete [] m_data;
147  m_data = new uint8_t[size];
148  m_dataSize = size;
149  }
150  data->CopyData (m_data, size);
151 }
152 uint16_t
154 {
155  return m_identifier;
156 }
157 uint16_t
159 {
160  return m_sequence;
161 }
162 uint32_t
164 {
165  return m_dataSize;
166 }
167 uint32_t
168 Icmpv4Echo::GetData (uint8_t payload[]) const
169 {
170  memcpy (payload, m_data, m_dataSize);
171  return m_dataSize;
172 }
173 TypeId
175 {
176  static TypeId tid = TypeId ("ns3::Icmpv4Echo")
177  .SetParent<Header> ()
178  .AddConstructor<Icmpv4Echo> ()
179  ;
180  return tid;
181 }
183  : m_identifier (0),
184  m_sequence (0),
185  m_dataSize (0)
186 {
187  //
188  // After construction, m_data is always valid until destruction. This is true
189  // even if m_dataSize is zero.
190  //
191  m_data = new uint8_t[m_dataSize];
192 }
194 {
195  delete [] m_data;
196  m_data = 0;
197  m_dataSize = 0;
198 }
199 TypeId
201 {
202  return GetTypeId ();
203 }
204 uint32_t
206 {
207  return 4 + m_dataSize;
208 }
209 void
211 {
212  start.WriteHtonU16 (m_identifier);
213  start.WriteHtonU16 (m_sequence);
214  start.Write (m_data, m_dataSize);
215 }
216 uint32_t
218 {
219  m_identifier = start.ReadNtohU16 ();
220  m_sequence = start.ReadNtohU16 ();
221  NS_ASSERT (start.GetSize () >= 4);
222  uint32_t size = start.GetSize () - 4;
223  if (size != m_dataSize)
224  {
225  delete [] m_data;
226  m_data = new uint8_t[size];
227  m_dataSize = size;
228  }
229  start.Read (m_data, m_dataSize);
230  return m_dataSize;
231 }
232 void
233 Icmpv4Echo::Print (std::ostream &os) const
234 {
235  os << "identifier=" << m_identifier << ", sequence=" << m_sequence;
236 }
237 
238 
239 /********************************************************
240  * Icmpv4DestinationUnreachable
241  ********************************************************/
242 
244 
245 TypeId
247 {
248  static TypeId tid = TypeId ("ns3::Icmpv4DestinationUnreachable")
249  .SetParent<Header> ()
250  .AddConstructor<Icmpv4DestinationUnreachable> ()
251  ;
252  return tid;
253 }
255 {
256  // make sure that thing is initialized to get initialized bytes
257  // when the ip payload's size is smaller than 8 bytes.
258  for (uint8_t j = 0; j < 8; j++)
259  {
260  m_data[j] = 0;
261  }
262 }
263 
264 void
266 {
267  m_nextHopMtu = mtu;
268 }
269 uint16_t
271 {
272  return m_nextHopMtu;
273 }
274 
275 void
277 {
278  data->CopyData (m_data, 8);
279 }
280 void
282 {
283  m_header = header;
284 }
285 void
286 Icmpv4DestinationUnreachable::GetData (uint8_t payload[8]) const
287 {
288  memcpy (payload, m_data, 8);
289 }
290 Ipv4Header
292 {
293  return m_header;
294 }
295 
296 
298 {
299 }
300 TypeId
302 {
303  return GetTypeId ();
304 }
305 uint32_t
307 {
308  return 4 + m_header.GetSerializedSize () + 8;
309 }
310 void
312 {
313  start.WriteU16 (0);
314  start.WriteHtonU16 (m_nextHopMtu);
315  uint32_t size = m_header.GetSerializedSize ();
316  m_header.Serialize (start);
317  start.Next (size);
318  start.Write (m_data, 8);
319 }
320 
321 uint32_t
323 {
325  i.Next (2);
326  m_nextHopMtu = i.ReadNtohU16 ();
327  uint32_t read = m_header.Deserialize (i);
328  i.Next (read);
329  for (uint8_t j = 0; j < 8; j++)
330  {
331  m_data[j] = i.ReadU8 ();
332  }
333  return i.GetDistanceFrom (start);
334 }
335 void
336 Icmpv4DestinationUnreachable::Print (std::ostream &os) const
337 {
338  m_header.Print (os);
339  os << " org data=";
340  for (uint8_t i = 0; i < 8; i++)
341  {
342  os << (uint32_t) m_data[i];
343  if (i != 8)
344  {
345  os << " ";
346  }
347  }
348 }
349 
350 /********************************************************
351  * Icmpv4TimeExceeded
352  ********************************************************/
353 
355 
356 TypeId
358 {
359  static TypeId tid = TypeId ("ns3::Icmpv4TimeExceeded")
360  .SetParent<Header> ()
361  .AddConstructor<Icmpv4TimeExceeded> ()
362  ;
363  return tid;
364 }
366 {
367  // make sure that thing is initialized to get initialized bytes
368  // when the ip payload's size is smaller than 8 bytes.
369  for (uint8_t j = 0; j < 8; j++)
370  {
371  m_data[j] = 0;
372  }
373 }
374 
375 
376 void
378 {
379  data->CopyData (m_data, 8);
380 }
381 void
383 {
384  m_header = header;
385 }
386 void
387 Icmpv4TimeExceeded::GetData (uint8_t payload[8]) const
388 {
389  memcpy (payload, m_data, 8);
390 }
391 Ipv4Header
393 {
394  return m_header;
395 }
396 
397 
399 {
400 }
401 TypeId
403 {
404  return GetTypeId ();
405 }
406 uint32_t
408 {
409  return 4 + m_header.GetSerializedSize () + 8;
410 }
411 void
413 {
414  start.WriteU32 (0);
415  uint32_t size = m_header.GetSerializedSize ();
416  m_header.Serialize (start);
417  start.Next (size);
418  start.Write (m_data, 8);
419 }
420 
421 uint32_t
423 {
425  i.Next (4);
426  uint32_t read = m_header.Deserialize (i);
427  i.Next (read);
428  for (uint8_t j = 0; j < 8; j++)
429  {
430  m_data[j] = i.ReadU8 ();
431  }
432  return i.GetDistanceFrom (start);
433 }
434 void
435 Icmpv4TimeExceeded::Print (std::ostream &os) const
436 {
437  m_header.Print (os);
438  os << " org data=";
439  for (uint8_t i = 0; i < 8; i++)
440  {
441  os << (uint32_t) m_data[i];
442  if (i != 8)
443  {
444  os << " ";
445  }
446  }
447 }
448 
449 } // namespace ns3