16#include <boost/lexical_cast.hpp>
35constexpr size_t PacketFuzzer::BUFFER_SIZE;
36constexpr size_t PacketFuzzer::MAX_SEND_SIZE;
37constexpr long PacketFuzzer::MAX_LOOP_COUNT;
40PacketFuzzer::PacketFuzzer(uint16_t
const port,
41 string const interface,
43 : loop_max_(MAX_LOOP_COUNT), sockaddr_len_(0), sockaddr_ptr_(nullptr), sockfd_(-1) {
51 const char *loop_max_ptr(
nullptr);
53 loop_max_ptr = getenv(
"KEA_AFL_LOOP_MAX");
57 loop_max_ = boost::lexical_cast<long>(loop_max_ptr);
58 }
catch (
const boost::bad_lexical_cast&) {
60 "cannot convert loop count " << loop_max_ptr <<
" to an integer");
64 isc_throw(FuzzInitFail,
"KEA_AFL_LOOP_MAX is "
66 <<
"It must be an integer greater than zero.");
73 createAddressStructures(port, interface, io_address);
78 sockfd_ = socket(io_address.isV4() ? AF_INET : AF_INET6, SOCK_DGRAM, 0);
80 LOG_FATAL(fuzz_logger, FUZZ_SOCKET_CREATE_FAIL)
81 .arg(strerror(errno));
85 LOG_INFO(fuzz_logger, FUZZ_INIT_COMPLETE).arg(interface).arg(address)
86 .arg(port).arg(loop_max_);
88 }
catch (
const FuzzInitFail& e) {
91 LOG_FATAL(fuzz_logger, FUZZ_INIT_FAIL).arg(e.what());
97PacketFuzzer::~PacketFuzzer() {
98 static_cast<void>(close(sockfd_));
103PacketFuzzer::createAddressStructures(uint16_t
const port,
104 string const& interface,
106 string const address(io_address.toText());
109 if (io_address.isV6()) {
112 memset(&servaddr6_, 0,
sizeof (servaddr6_));
114 servaddr6_.sin6_family = AF_INET6;
115 if (inet_pton(AF_INET6, address.c_str(), &servaddr6_.sin6_addr) != 1) {
117 "inet_pton() failed: can't convert " << address <<
" to an IPv6 address");
119 servaddr6_.sin6_port = htons(port);
122 servaddr6_.sin6_scope_id = if_nametoindex(interface.c_str());
123 if (servaddr6_.sin6_scope_id == 0) {
125 "error retrieving interface ID for " << interface <<
": " << strerror(errno));
128 sockaddr_ptr_ =
reinterpret_cast<sockaddr*
>(&servaddr6_);
129 sockaddr_len_ =
sizeof(servaddr6_);
131 }
else if (io_address.isV4()) {
135 memset(&servaddr4_, 0,
sizeof(servaddr4_));
137 servaddr4_.sin_family = AF_INET;
138 if (inet_pton(AF_INET, address.c_str(), &servaddr4_.sin_addr) != 1) {
140 "inet_pton() failed: can't convert " << address <<
" to an IPv4 address");
142 servaddr4_.sin_port = htons(port);
144 sockaddr_ptr_ =
reinterpret_cast<sockaddr*
>(&servaddr4_);
145 sockaddr_len_ =
sizeof(servaddr4_);
149 isc_throw(FuzzInitFail,
"unknown IOAddress IP version");
154PacketFuzzer::transfer()
const {
157 uint8_t buf[BUFFER_SIZE];
158 ssize_t
const length(read(0, buf,
sizeof(buf)));
160 transfer(&buf[0], length);
166PacketFuzzer::transfer(uint8_t
const* data,
size_t size)
const {
167 char buf[BUFFER_SIZE];
168 ssize_t
const length(size);
171 memcpy(&buf[0], data, min(BUFFER_SIZE, size));
177 LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE_DETAIL, FUZZ_DATA_READ).arg(length);
183 size_t send_len = (length < MAX_SEND_SIZE) ? length : MAX_SEND_SIZE;
184 ssize_t sent = sendto(sockfd_, buf, send_len, 0, sockaddr_ptr_,
187 LOG_ERROR(fuzz_logger, FUZZ_SEND_ERROR).arg(strerror(errno));
188 }
else if (sent != length) {
189 LOG_WARN(fuzz_logger, FUZZ_SHORT_SEND).arg(length).arg(sent);
191 LOG_DEBUG(fuzz_logger, FUZZ_DBG_TRACE_DETAIL, FUZZ_SEND).arg(sent);
197 LOG_ERROR(fuzz_logger, FUZZ_READ_FAIL).arg(strerror(errnum));
The IOAddress class represents an IP addresses (version agnostic)
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
#define LOG_WARN(LOGGER, MESSAGE)
Macro to conveniently test warn output and log it.
#define LOG_FATAL(LOGGER, MESSAGE)
Macro to conveniently test fatal output and log it.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
Defines the logger used by the top-level component of kea-lfc.