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