servers/roles/dnsmasq/templates/dnsmasq-script.j2
Timotej Lazar 8e3772e475 dnsmasq: store leases in sqlite database
To avoid dnsmasq writing out the whole leasefile on each request
before replying. This gets slow on high‐latency storage.

Also tweak DNS updates a bit.
2025-04-14 16:41:24 +02:00

77 lines
2 KiB
Django/Jinja

#!/bin/sh
# This script replaces the dnsmasq leasefile with an sqlite database
# for performance on slow storage, and updates DNS records for
# assigned addresses.
cmd="${1}"
# dnsmasq calls this script on startup for each known lease, ignore it
[ "${cmd}" != "init" ] && [ -z "${DNSMASQ_INTERFACE}" ] && exit 0
# parameters
db=/var/lib/misc/dnsmasq.leases.db
domain={{ domain }}
ldap_user={{ password.ldap_user }}
ttl=3600
# sanitize input
mac="${2//[![:xdigit:]:]/}"
ipv4="${3//[![:digit:].]/}"
hostname="${4//[![:alnum:]_-]/}"
client_id="${DNSMASQ_CLIENT_ID//[![:xdigit:]:]/}"
# construct SQL to query or update leases, and nsupdate script to update DNS records
dns=""
sql=""
case "${cmd}" in
"init")
# init runs as root, so ensure the dnsmasq user can write to database later
touch "${db}"
chown dnsmasq:dnsmasq "${db}"
setfacl -m u:dnsmasq:rwx "$(dirname ${db})"
setfacl -m u:dnsmasq:r "/etc/krb5.keytab" # needed for DNS updates
# ensure the leases table exists, and get all leases from it
sql="CREATE TABLE IF NOT EXISTS leases (
ipv4 TEXT PRIMARY KEY NOT NULL,
mac TEXT NOT NULL,
hostname TEXT NOT NULL,
client_id TEXT NOT NULL,
renewed INTEGER NOT NULL);
SELECT renewed, mac, ipv4, hostname, client_id FROM leases;"
;;
"add" | "old")
# add or update the lease
sql="INSERT INTO leases
VALUES ('${ipv4}', '${mac}', '${hostname:-*}', '${client_id:-*}', unixepoch())
ON CONFLICT(ipv4) DO UPDATE SET renewed = unixepoch();"
# add or update the DNS record
if [ -n "${hostname}" ] ; then
dns="update add ${hostname}.${domain} ${ttl} A ${ipv4}\n"
fi
if [ -n "${DNSMASQ_OLD_HOSTNAME}" ] ; then
dns="${dns}update del ${DNSMASQ_OLD_HOSTNAME}.${domain}\n"
fi
;;
"del")
# delete the lease
sql="DELETE FROM leases WHERE ipv4 = '${ipv4}';"
# TODO probably delete the DNS record
;;
esac
# update lease database
if [ -n "${sql}" ]; then
sqlite3 -separator " " "${db}" "${sql}"
fi
# update DNS records
if [ -n "${dns}" ]; then
kinit -k "${ldap_user}"
echo -e "${dns}send" | nsupdate -g
fi