Skip to content

Instantly share code, notes, and snippets.

@NeySlim
Created December 17, 2025 23:11
Show Gist options
  • Select an option

  • Save NeySlim/67917b6c3feece85a867f66321576862 to your computer and use it in GitHub Desktop.

Select an option

Save NeySlim/67917b6c3feece85a867f66321576862 to your computer and use it in GitHub Desktop.
Kea dhcp server sanitize hostname hook
#!/bin/bash
#debian trixie:
apt update && apt -y install kea-dev libboost-dev g++
g++ -fPIC -shared -o libkea_sanitize_hostname.so sanitize_hostname.cc \
-I/usr/include/kea -lkea-dhcp++ -lkea-hooks
cp libkea_sanitize_hostname.so /usr/local/lib/libkea_sanitize_hostname.so
{
"Dhcp4": {
"control-socket": {
"socket-type": "unix",
"socket-name": "kea4-ctrl-socket"
},
"hooks-libraries": [
{
"library": "/usr/lib/-ARCH-/kea/hooks/libdhcp_lease_cmds.so"
},
{
"library": "/usr/local/lib/libkea_sanitize_hostname.so"
}
],
...
#include <hooks/hooks.h>
#include <dhcp/pkt4.h>
#include <dhcp/option_string.h>
#include <boost/algorithm/string.hpp>
#include <iostream>
#include <chrono>
#include <iomanip>
#include <sstream>
#include <thread>
#include <unistd.h>
using namespace isc::hooks;
using namespace isc::dhcp;
using namespace std;
// Timestamp
static std::string kea_timestamp() {
using namespace std::chrono;
auto now = system_clock::now();
auto t = system_clock::to_time_t(now);
auto ms = duration_cast<milliseconds>(now.time_since_epoch()) % 1000;
std::tm tm{};
localtime_r(&t, &tm);
std::ostringstream oss;
oss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S")
<< "." << std::setw(3) << std::setfill('0') << ms.count();
return oss.str();
}
// Thread ID
static std::string thread_id() {
std::ostringstream oss;
oss << std::this_thread::get_id();
return oss.str();
}
// Logger Kea-like
static void kea_log(const std::string& msg) {
std::cerr
<< kea_timestamp()
<< " INFO [kea-dhcp4.hook_sanitize_hostname/"
<< getpid() << "." << thread_id()
<< "] MESSAGE "
<< msg
<< std::endl;
}
extern "C" {
int version() {
return KEA_HOOKS_VERSION;
}
bool multi_threading_compatible() {
return true;
}
int load(LibraryHandle&) {
kea_log("hook loaded");
return 0;
}
int unload() {
kea_log("hook unloaded");
return 0;
}
int lease4_select(CalloutHandle& handle) {
Pkt4Ptr query;
handle.getArgument("query4", query);
if (!query) {
return 0;
}
OptionPtr opt = query->getOption(DHO_HOST_NAME);
if (!opt) {
return 0;
}
auto hostname_opt = dynamic_pointer_cast<OptionString>(opt);
if (!hostname_opt) {
return 0;
}
std::string hostname = hostname_opt->getValue();
kea_log("original hostname: " + hostname);
boost::replace_all(hostname, "_", "-");
boost::algorithm::to_lower(hostname);
hostname_opt->setValue(hostname);
kea_log("rewritten hostname: " + hostname);
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment