• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // icmp_header.hpp
3 // ~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10 
11 #ifndef ICMP_HEADER_HPP
12 #define ICMP_HEADER_HPP
13 
14 #include <istream>
15 #include <ostream>
16 #include <algorithm>
17 
18 // ICMP header for both IPv4 and IPv6.
19 //
20 // The wire format of an ICMP header is:
21 //
22 // 0               8               16                             31
23 // +---------------+---------------+------------------------------+      ---
24 // |               |               |                              |       ^
25 // |     type      |     code      |          checksum            |       |
26 // |               |               |                              |       |
27 // +---------------+---------------+------------------------------+    8 bytes
28 // |                               |                              |       |
29 // |          identifier           |       sequence number        |       |
30 // |                               |                              |       v
31 // +-------------------------------+------------------------------+      ---
32 
33 class icmp_header
34 {
35 public:
36   enum { echo_reply = 0, destination_unreachable = 3, source_quench = 4,
37     redirect = 5, echo_request = 8, time_exceeded = 11, parameter_problem = 12,
38     timestamp_request = 13, timestamp_reply = 14, info_request = 15,
39     info_reply = 16, address_request = 17, address_reply = 18 };
40 
icmp_header()41   icmp_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); }
42 
type() const43   unsigned char type() const { return rep_[0]; }
code() const44   unsigned char code() const { return rep_[1]; }
checksum() const45   unsigned short checksum() const { return decode(2, 3); }
identifier() const46   unsigned short identifier() const { return decode(4, 5); }
sequence_number() const47   unsigned short sequence_number() const { return decode(6, 7); }
48 
type(unsigned char n)49   void type(unsigned char n) { rep_[0] = n; }
code(unsigned char n)50   void code(unsigned char n) { rep_[1] = n; }
checksum(unsigned short n)51   void checksum(unsigned short n) { encode(2, 3, n); }
identifier(unsigned short n)52   void identifier(unsigned short n) { encode(4, 5, n); }
sequence_number(unsigned short n)53   void sequence_number(unsigned short n) { encode(6, 7, n); }
54 
operator >>(std::istream & is,icmp_header & header)55   friend std::istream& operator>>(std::istream& is, icmp_header& header)
56     { return is.read(reinterpret_cast<char*>(header.rep_), 8); }
57 
operator <<(std::ostream & os,const icmp_header & header)58   friend std::ostream& operator<<(std::ostream& os, const icmp_header& header)
59     { return os.write(reinterpret_cast<const char*>(header.rep_), 8); }
60 
61 private:
decode(int a,int b) const62   unsigned short decode(int a, int b) const
63     { return (rep_[a] << 8) + rep_[b]; }
64 
encode(int a,int b,unsigned short n)65   void encode(int a, int b, unsigned short n)
66   {
67     rep_[a] = static_cast<unsigned char>(n >> 8);
68     rep_[b] = static_cast<unsigned char>(n & 0xFF);
69   }
70 
71   unsigned char rep_[8];
72 };
73 
74 template <typename Iterator>
compute_checksum(icmp_header & header,Iterator body_begin,Iterator body_end)75 void compute_checksum(icmp_header& header,
76     Iterator body_begin, Iterator body_end)
77 {
78   unsigned int sum = (header.type() << 8) + header.code()
79     + header.identifier() + header.sequence_number();
80 
81   Iterator body_iter = body_begin;
82   while (body_iter != body_end)
83   {
84     sum += (static_cast<unsigned char>(*body_iter++) << 8);
85     if (body_iter != body_end)
86       sum += static_cast<unsigned char>(*body_iter++);
87   }
88 
89   sum = (sum >> 16) + (sum & 0xFFFF);
90   sum += (sum >> 16);
91   header.checksum(static_cast<unsigned short>(~sum));
92 }
93 
94 #endif // ICMP_HEADER_HPP
95