// // icmp_header.hpp // ~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2016 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef ICMP_HEADER_HPP #define ICMP_HEADER_HPP #include #include #include // ICMP header for both IPv4 and IPv6. // // The wire format of an ICMP header is: // // 0 8 16 31 // +---------------+---------------+------------------------------+ --- // | | | | ^ // | type | code | checksum | | // | | | | | // +---------------+---------------+------------------------------+ 8 bytes // | | | | // | identifier | sequence number | | // | | | v // +-------------------------------+------------------------------+ --- class icmp_header { public: enum { echo_reply = 0, destination_unreachable = 3, source_quench = 4, redirect = 5, echo_request = 8, time_exceeded = 11, parameter_problem = 12, timestamp_request = 13, timestamp_reply = 14, info_request = 15, info_reply = 16, address_request = 17, address_reply = 18 }; icmp_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); } unsigned char type() const { return rep_[0]; } unsigned char code() const { return rep_[1]; } unsigned short checksum() const { return decode(2, 3); } unsigned short identifier() const { return decode(4, 5); } unsigned short sequence_number() const { return decode(6, 7); } void type(unsigned char n) { rep_[0] = n; } void code(unsigned char n) { rep_[1] = n; } void checksum(unsigned short n) { encode(2, 3, n); } void identifier(unsigned short n) { encode(4, 5, n); } void sequence_number(unsigned short n) { encode(6, 7, n); } friend std::istream& operator>>(std::istream& is, icmp_header& header) { return is.read(reinterpret_cast(header.rep_), 8); } friend std::ostream& operator<<(std::ostream& os, const icmp_header& header) { return os.write(reinterpret_cast(header.rep_), 8); } private: unsigned short decode(int a, int b) const { return (rep_[a] << 8) + rep_[b]; } void encode(int a, int b, unsigned short n) { rep_[a] = static_cast(n >> 8); rep_[b] = static_cast(n & 0xFF); } unsigned char rep_[8]; }; template void compute_checksum(icmp_header& header, Iterator body_begin, Iterator body_end) { unsigned int sum = (header.type() << 8) + header.code() + header.identifier() + header.sequence_number(); Iterator body_iter = body_begin; while (body_iter != body_end) { sum += (static_cast(*body_iter++) << 8); if (body_iter != body_end) sum += static_cast(*body_iter++); } sum = (sum >> 16) + (sum & 0xFFFF); sum += (sum >> 16); header.checksum(static_cast(~sum)); } #endif // ICMP_HEADER_HPP