From 3a07e294a9d355ee480de4afa469429b14d160de Mon Sep 17 00:00:00 2001 From: Philip Prindeville Date: Tue, 15 Dec 2020 13:39:34 -0700 Subject: [PATCH] isc-dhcp: add dynamic dns integration for local bind server Start after named is running. Add support for "cname", "domain", "mxhost", and "srvhost" configs. Signed-off-by: Philip Prindeville --- net/isc-dhcp/Makefile | 4 +- net/isc-dhcp/files/dhcpd.init | 190 +++++++++++++++++++++++++++++++++- 2 files changed, 191 insertions(+), 3 deletions(-) diff --git a/net/isc-dhcp/Makefile b/net/isc-dhcp/Makefile index a92763b90..68c60e58a 100644 --- a/net/isc-dhcp/Makefile +++ b/net/isc-dhcp/Makefile @@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=isc-dhcp UPSTREAM_NAME:=dhcp PKG_VERSION:=4.4.1 -PKG_RELEASE:=11 +PKG_RELEASE:=12 PKG_LICENSE:=BSD-3-Clause PKG_LICENSE_FILES:=LICENSE @@ -109,12 +109,14 @@ define Package/isc-dhcp-server-ipv4 $(call Package/isc-dhcp/Default) TITLE+= server (without IPv6) VARIANT:=ipv4 + DEPENDS+=bind-server bind-client endef define Package/isc-dhcp-server-ipv6 $(call Package/isc-dhcp/Default) TITLE+= server (with IPv6) VARIANT:=ipv6 + DEPENDS+=bind-server bind-client endef define Package/isc-dhcp-server/description diff --git a/net/isc-dhcp/files/dhcpd.init b/net/isc-dhcp/files/dhcpd.init index a5de52668..2c8d21b25 100755 --- a/net/isc-dhcp/files/dhcpd.init +++ b/net/isc-dhcp/files/dhcpd.init @@ -1,12 +1,23 @@ #!/bin/sh /etc/rc.common -START=19 +START=25 USE_PROCD=1 PROG=/usr/sbin/dhcpd +TTL=3600 +PREFIX="update add" + lease_file=/tmp/dhcpd.leases config_file=/tmp/run/dhcpd.conf +dyndir=/tmp/bind +conf_local_file=$dyndir/named.conf.local + +session_key_name=local-ddns +session_key_file=/var/run/named/session.key + +dyn_file=$(mktemp -u /tmp/dhcpd.XXXXXX) + time2seconds() { local timestring=$1 local multiplier number suffix @@ -67,12 +78,36 @@ typeof() { ' } +rev_quad() { + local ip="$1" + + echo "$ip" | awk -F '.' '{ printf "%s.%s.%s.%s\n", $4, $3, $2, $1; }' +} + +update() { + local lhs="$1" family="$2" type="$3" + shift 3 + + echo -e "$PREFIX" "$lhs $family $type $@\nsend" +} + explode() { local arg="$1" echo "$arg" | sed -e 's/\./, /g' } +create_empty_zone() +{ + local zone="$1" + + if [ ! -f $dyndir/db."$zone" ]; then + cp -p /etc/bind/db.empty $dyndir/db."$zone" + chmod g+w $dyndir/db."$zone" + chgrp bind $dyndir/db."$zone" + fi +} + append_routes() { local tuple tuples="$1" local string= @@ -122,6 +157,85 @@ append_dhcp_options() { echo " option $tag $formatted;" } +static_cname_add() { + local cfg="$1" + local cname target + + config_get cname "$cfg" "cname" + [ -n "$cname" ] || return 0 + config_get target "$cfg" "target" + [ -n "$target" ] || return 0 + + update "$cname.$domain." IN CNAME "$target.$domain." +} + +static_cnames() { + config_foreach static_cname_add cname "$@" +} + +static_domain_add() { + local cfg="$1" + local name ip revip + + config_get name "$cfg" "name" + [ -n "$name" ] || return 0 + config_get ip "$cfg" "ip" + [ -n "$ip" ] || return 0 + + revip="$(rev_quad "$ip")" + + update "$name.$domain." IN A "$ip" + update "$revip.in-addr.arpa." IN PTR "$name.$domain." +} + +static_domains() { + config_foreach static_domain_add domain "$@" +} + +static_mxhost_add() { + local cfg="$1" + local domain2 relay pref + + config_get domain2 "$cfg" "domain" + [ -n "$domain2" ] || return 0 + config_get relay "$cfg" "relay" + [ -n "$relay" ] || return 0 + config_get pref "$cfg" "pref" + [ -n "$pref" ] || return 0 + + if [ "$domain2" = "@" ]; then + update "$domain." IN MX "$pref" "$relay.$domain." + else + update "$domain2.$domain." IN MX "$pref" "$relay.$domain." + fi +} + +static_mxhosts() { + config_foreach static_mxhost_add mxhost "$@" +} + +static_srvhost_add() { + local cfg="$1" + local srv target port priority weight + + config_get srv "$cfg" "srv" + [ -n "$srv" ] || return 0 + config_get target "$cfg" "target" + [ -n "$target" ] || return 0 + config_get port "$cfg" "port" + [ -n "$port" ] || return 0 + config_get priority "$cfg" "priority" + [ -n "$priority" ] || return 0 + config_get weight "$cfg" "weight" + [ -n "$weight" ] || return 0 + + update "$srv.$domain." IN SRV "$priority" "$weight" "$port" "$target" +} + +static_srvhosts() { + config_foreach static_srvhost_add srvhost "$@" +} + static_host_add() { local cfg="$1" local broadcast hostid macn macs mac name ip leasetime @@ -278,6 +392,7 @@ general_config() { config_get log_facility "isc_dhcpd" "log_facility" config_get domain "isc_dhcpd" "domain" + config_get_bool dynamicdns "isc_dhcpd" dynamicdns 0 [ $always_broadcast -eq 1 ] && echo "always-broadcast true;" [ $authoritative -eq 1 ] && echo "authoritative;" @@ -288,6 +403,56 @@ general_config() { max_lease_time="$(time2seconds "$max_lease_time")" [ "$?" -ne 0 ] && return 1 + if [ $dynamicdns -eq 1 ]; then + create_empty_zone "$domain" + + create_empty_zone "168.192.in-addr.arpa" + + cat < $conf_local_file +zone "$domain" { + type master; + file "$dyndir/db.$domain"; + allow-update { key $session_key_name; }; + allow-transfer { key $session_key_name; }; +}; + +zone "168.192.in-addr.arpa" { + type master; + file "$dyndir/db.168.192.in-addr.arpa"; + allow-update { key $session_key_name; }; + allow-transfer { key $session_key_name; }; +}; + +EOF + /etc/init.d/named reload + sleep 1 + + cat <> $config_file + if [ $dynamicdns -eq 1 ]; then + cat < $dyn_file +; Generated by /etc/init.d/dhcpd at $(date) + +ttl $TTL + +EOF + + static_cnames >> $dyn_file + + static_domains >> $dyn_file + + static_mxhosts >> $dyn_file + + static_srvhosts >> $dyn_file + + nsupdate -l -v $dyn_file + + rm -f $dyn_file + fi + [ -z "$dhcp_ifs" ] && return 0 fi