| Kea 3.0.2-git

icmp_msg.cc
Go to the documentation of this file.
1// Copyright (C) 2023-2025 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
15 using namespace isc;
16 using namespace isc::asiolink;
17 using namespace isc::util;
18
19 namespace isc {
20 namespace ping_check {
21
22 ICMPMsg::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
30 ICMPMsg::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* ip_header = (struct ip*)(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* reply = (struct icmp*)(wire_data + hlen);
54 msg->setType(reply->icmp_type);
55 msg->setCode(reply->icmp_code);
56
57 msg->setChecksum(ntohs(reply->icmp_cksum));
58 msg->setId(ntohs(reply->icmp_hun.ih_idseq.icd_id));
59 msg->setSequence(ntohs(reply->icmp_hun.ih_idseq.icd_seq));
60
61 auto payload_len = length - hlen - ICMP_HEADER_SIZE;
62 msg->setPayload((const uint8_t*)(&reply->icmp_dun), payload_len);
63
64 return (msg);
65}
66
67 ICMPPtr
68 ICMPMsg::pack() const {
69 ICMPPtr outbound(new struct icmp());
70 memset(outbound.get(), 0x00, sizeof(struct icmp));
71 outbound->icmp_type = msg_type_;
72 outbound->icmp_id = htons(id_);
73 outbound->icmp_seq = htons(sequence_);
75 outbound->icmp_cksum = htons(~calcChecksum((const uint8_t*)(outbound.get()), sizeof(struct icmp)));
76 return (outbound);
77}
78
79 void
80 ICMPMsg::setPayload(const uint8_t* data, size_t length) {
81 payload_.insert(payload_.end(), data, data + length);
82}
83
84uint32_t
85 ICMPMsg::calcChecksum(const uint8_t* buf, size_t length) {
86 uint32_t sum = 0;
87
88 /* Checksum all the pairs of bytes first... */
89 size_t i;
90 for (i = 0; i < (length & ~1U); i += 2) {
91 sum += static_cast<uint32_t>(readUint16(buf + i, sizeof(uint16_t)));
92 /* Add carry. */
93 if (sum > 0xFFFF) {
94 sum -= 0xFFFF;
95 }
96 }
97
98 /* If there's a single byte left over, checksum it, too. Network
99 byte order is big-endian, so the remaining byte is the high byte. */
100 if (i < length) {
101 sum += buf[i] << 8;
102 /* Add carry. */
103 if (sum > 0xFFFF) {
104 sum -= 0xFFFF;
105 }
106 }
107
108 return (sum);
109}
110
111} // end of namespace ping_check
112} // 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:45
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:80
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:68
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:85
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 agent_parser.cc:148