Kea: icmp_msg.cc Source File

| Kea 3.2.0-git

icmp_msg.cc
Go to the documentation of this file.
1// Copyright (C) 2023-2026 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
7#include <config.h>
8#include <icmp_msg.h>
9#include <util/io.h>
10#include <exceptions/exceptions.h>
11
12#include <netinet/ip_icmp.h>
13#include <iostream>
14
15using namespace isc;
16using namespace isc::asiolink;
17using namespace isc::util;
18
19namespace isc {
20namespace ping_check {
21
22ICMPMsg::ICMPMsg()
23 : source_(IOAddress::IPV4_ZERO_ADDRESS()),
24 destination_(IOAddress::IPV4_ZERO_ADDRESS()),
25 msg_type_(0), code_(0), check_sum_(0), id_(0), sequence_(0),
26 payload_(0) {
27}
28
29 ICMPMsgPtr
30ICMPMsg::unpack(const uint8_t* wire_data, size_t length) {
31 ICMPMsgPtr msg(new ICMPMsg());
32 if (length < sizeof(struct ip)) {
33 isc_throw(BadValue,
34 "ICMPMsg::unpack - truncated ip header, length: "
35 << length);
36 }
37
38 // Find the IP header length...
39 struct ip const* ip_header = reinterpret_cast<struct ip const*>(wire_data);
40 auto hlen = (ip_header->ip_hl << 2);
41
42 // Make sure we received enough data.
43 if (length < (hlen + sizeof(struct icmp))) {
44 isc_throw(BadValue, "ICMPMsg::truncated packet? length: "
45 << length << ", hlen: " << hlen);
46 }
47
48 // Grab the source and destination addresses.
49 msg->setSource(IOAddress(ntohl(ip_header->ip_src.s_addr)));
50 msg->setDestination(IOAddress(ntohl(ip_header->ip_dst.s_addr)));
51
52 // Get the message type.
53 struct icmp const* reply =
54 reinterpret_cast<struct icmp const*>(wire_data + hlen);
55 msg->setType(reply->icmp_type);
56 msg->setCode(reply->icmp_code);
57
58 msg->setChecksum(ntohs(reply->icmp_cksum));
59 msg->setId(ntohs(reply->icmp_hun.ih_idseq.icd_id));
60 msg->setSequence(ntohs(reply->icmp_hun.ih_idseq.icd_seq));
61
62 auto payload_len = length - hlen - ICMP_HEADER_SIZE;
63 const uint8_t* idata = reinterpret_cast<const uint8_t*>(&reply->icmp_dun);
64 msg->setPayload(idata, payload_len);
65
66 return (msg);
67}
68
69 ICMPPtr
70ICMPMsg::pack() const {
71 ICMPPtr outbound(new struct icmp());
72 memset(outbound.get(), 0x00, sizeof(struct icmp));
73 outbound->icmp_type = msg_type_;
74 outbound->icmp_id = htons(id_);
75 outbound->icmp_seq = htons(sequence_);
77 uint8_t* odata = reinterpret_cast<uint8_t*>(outbound.get());
78 outbound->icmp_cksum = htons(~calcChecksum(odata, sizeof(struct icmp)));
79 return (outbound);
80}
81
82void
83ICMPMsg::setPayload(const uint8_t* data, size_t length) {
84 payload_.insert(payload_.end(), data, data + length);
85}
86
87uint32_t
88ICMPMsg::calcChecksum(const uint8_t* buf, size_t length) {
89 uint32_t sum = 0;
90
91 /* Checksum all the pairs of bytes first... */
92 size_t i;
93 for (i = 0; i < (length & ~1U); i += 2) {
94 sum += static_cast<uint32_t>(readUint16(buf + i, sizeof(uint16_t)));
95 /* Add carry. */
96 if (sum > 0xFFFF) {
97 sum -= 0xFFFF;
98 }
99 }
100
101 /* If there's a single byte left over, checksum it, too. Network
102 byte order is big-endian, so the remaining byte is the high byte. */
103 if (i < length) {
104 sum += buf[i] << 8;
105 /* Add carry. */
106 if (sum > 0xFFFF) {
107 sum -= 0xFFFF;
108 }
109 }
110
111 return (sum);
112}
113
114} // end of namespace ping_check
115} // end of namespace isc
isc::BadValue
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
Definition exceptions/exceptions.h:132
isc::asiolink::IOAddress
The IOAddress class represents an IP addresses (version agnostic).
Definition io_address.h:53
isc::ping_check::ICMPMsg::setPayload
void setPayload(const uint8_t *data, size_t length)
Sets the message payload to the given data.
Definition icmp_msg.cc:83
isc::ping_check::ICMPMsg::unpack
static ICMPMsgPtr unpack(const uint8_t *wire_data, size_t length)
Unpacks an ICMP message from the given wire_data.
Definition icmp_msg.cc:30
isc::ping_check::ICMPMsg::ICMPMsg
ICMPMsg()
Constructor.
Definition icmp_msg.cc:22
isc::ping_check::ICMPMsg::pack
ICMPPtr pack() const
Packs the message into an ICMP structure.
Definition icmp_msg.cc:70
isc::ping_check::ICMPMsg::calcChecksum
static uint32_t calcChecksum(const uint8_t *data, size_t length)
Calculates the checksum of the given data buffer.
Definition icmp_msg.cc:88
isc::ping_check::ICMPMsg::ICMP_HEADER_SIZE
static constexpr size_t ICMP_HEADER_SIZE
Size in octets of ICMP message header.
Definition icmp_msg.h:49
exceptions.h
isc_throw
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Definition exceptions/exceptions.h:210
icmp_msg.h
io.h
isc::asiolink
Definition addr_utilities.cc:170
isc::data
Definition base_stamped_element.cc:12
isc::ping_check
Definition config_cache.cc:19
isc::ping_check::ICMPMsgPtr
boost::shared_ptr< ICMPMsg > ICMPMsgPtr
Shared pointer type for ICMPMsg.
Definition icmp_msg.h:26
isc::ping_check::ICMPPtr
boost::shared_ptr< struct icmp > ICMPPtr
Shared pointer type for struct icmp.
Definition icmp_msg.h:29
isc::util
Definition time_utils.cc:43
isc::util::readUint16
uint16_t readUint16(void const *const buffer, size_t const length)
uint16_t wrapper over readUint.
Definition io.h:76
isc
Defines the logger used by the top-level component of kea-lfc.
Definition check_exists_add.cc:18