nsupdate(8) rc.d Script

Crist J. Clark cristjc at comcast.net
Mon Sep 27 22:17:13 PDT 2004

Silence from -net. Anyone have an opinion one way or the other
whether this would be useful to add to the rc.d startup?

----- Forwarded message from "Crist J. Clark" <cristjc at comcast.net> -----

Date: Fri, 24 Sep 2004 10:24:18 -0700
From: "Crist J. Clark" <cristjc at comcast.net>
To: freebsd-net at freebsd.org
Subject: nsupdate(8) rc.d Script

As I was setting up DNS for IPv6 on a test network, I started
to get really tired of entering 128-bit addresses, for both
forward and reverse lookups, into DNS by hand. It seemed somewhat
silly to be doing all of this manually when the actual IPv6 hosts
pretty much configure themselves with rtsol(8).

So I went ahead setting up an nsupdate script to have the systems
automatically use DNS updates to "register" themselves. I figured
I might as well do IPv4 while I was at it.

Now I'm wondering if this is something other people may find useful
and whether I should commit it. I think there are enough knobs to
make it work for most people. But there very well may be some
assumptions that may make it totally unsuitable for a lot of systems

I'm not 100% sure where to drop it into the rc.d order. Obviously,
it is a network service, but it would be nice to sign up in DNS
early so we have entries in DNS when other machines might try to
look us up when we contact them in later rc.d scripts. One thing
that might be nice is if we wait until a local DNS server starts
in the case we are the server, but having a DNS server auto-update
its own info... kinda a chicken-and-egg problem there, may not be a
best practice.

Finally, that is one long awk script. Is there a better tool or
method for converting an IPv6 presentation address into the ip6.arpa
format? And the script is not optimized to do the updates in the
fewest number of packets. An update can only contain updates for a
single zone. It makes the only safe assumption that any two domain
names are not in the same zone unless they are the same. I do not
know how to reduce the number of updates without making things a
LOT more complicated and doing more total DNS queries to find out
SOA information.

To enable the updates, just add,


To rc.conf(5). The patch to the default rc.conf has it disabled by
default. IPv4 and IPv6 updates may be toggled individually, but
IPv6 only works if ipv6_enable is also "on." Patch is against RELENG_5,
but it should work fine in CURRENT.

Suggestions, comments, or criticisms, public or private, are welcome.
Crist J. Clark                     |     cjclark at alum.mit.edu
                                   |     cjclark at jhu.edu
http://people.freebsd.org/~cjc/    |     cjc at freebsd.org
-------------- next part --------------
Index: src/etc/rc.d/nsupdate
RCS file: src/etc/rc.d/nsupdate
diff -N src/etc/rc.d/nsupdate
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/etc/rc.d/nsupdate	26 Sep 2004 23:23:02 -0000
@@ -0,0 +1,123 @@
+# $FreeBSD$
+# PROVIDE: nsupdate
+. /etc/rc.subr
+. /etc/network.subr
+	checkyesno nsupdate_ipv4
+	_ipv4_enable="$?"
+	checkyesno ipv6_enable && checkyesno nsupdate_ipv6
+	_ipv6_enable="$?"
+	checkyesno nsupdate_reverse
+	_do_reverse="$?"
+	case "$1" in
+		'add')
+			_action='add'
+			_ttl="${nsupdate_ttl}"
+			;;
+		'delete')
+			_action='delete'
+			_ttl=''
+			;;
+		*)
+			return 1
+			;;
+	esac
+	case "${nsupdate_ifaces}" in
+	'auto')
+		_interfaces=`list_net_interfaces`
+		;;
+	'dhcp')
+		_interfaces=`list_net_interfaces dhcp`
+		;;
+	'nodhcp')
+		_interfaces=`list_net_interfaces nodhcp`
+		;;
+	*)
+		_interfaces="${nsupdate_ifaces}"
+	esac
+	for _iface in ${_interfaces}; do
+		eval _hostname="\$nsupdate_hostname_${_iface}"
+		if [ -z "${_hostname}" ]; then
+			_hostname=`hostname`
+		fi
+		ifconfig "${_iface}" |
+		awk -v "inet4=${_ipv4_enable}" -v "inet6=${_ipv6_enable}" \
+		    -v "hostname=${_hostname}" -v "ttl=${_ttl}" \
+		    -v "do_reverse=${_do_reverse}" -v "action=${_action}" \
+			'! inet4 && /inet / && $2 !~ /^127\./ {
+				printf "update %s %s %s a %s\n", action,
+					hostname, ttl, $2;
+				ip4[++i] = $2;
+			}
+			! inet6 && /inet6 / && $2 !~ /^(fe80:|::1)/ {
+				printf "update %s %s %s aaaa %s\n", action,
+					hostname, ttl, $2;
+				ip6[++j] = $2;
+			}
+			END {
+				print "";
+				if (do_reverse != 0) {
+					exit 0;
+				}
+				for (i in ip4) {
+					split(ip4[i], oct, /\./);
+					printf "update %s %d.%d.%d.%d.in-addr.arpa %s ptr %s\n",
+						action,
+						oct[4], oct[3], oct[2], oct[1],
+						ttl, hostname;
+					print "";
+				}
+				for (j in ip6) {
+					cols = gsub(/:/, ":", ip6[j]);
+					zeroes = "";
+					for (i = cols; i < 8; i++) {
+						zeros = zeros ":0";
+					}
+					zeros = zeros ":";
+					sub(/::/, zeros, ip6[j]);
+					split(ip6[j], shorts, /:/);
+					ip6str = "";
+					for (i = 1; i <= 8; i++) {
+						ip6str = ip6str substr("000" shorts[i],
+							length(shorts[i]));
+					}
+					revstr = "ip6.arpa";
+					for (i = 1; i <= length(ip6str); i++) {
+						revstr = substr(ip6str, i, 1) "." revstr;
+					}
+					printf "update %s %s %s ptr %s\n",
+						action, revstr, ttl, hostname;
+					print "";
+				}
+			}'
+	done |
+	"${nsupdate_command}" ${nsupdate_flags}
+	nsupdate_run add
+	checkyesno nsupdate_shutdown_remove || return 0
+	nsupdate_run delete
+load_rc_config $name
+run_rc_command "$1"
Index: src/etc/defaults/rc.conf
RCS file: /ncvs/src/etc/defaults/rc.conf,v
retrieving revision 1.212
diff -u -r1.212 rc.conf
--- src/etc/defaults/rc.conf	27 Jul 2004 00:28:16 -0000	1.212
+++ src/etc/defaults/rc.conf	28 Sep 2004 05:11:11 -0000
@@ -139,6 +139,22 @@
 				# Choose correct tunnel addrs.
 #gifconfig_gif0=""	# Examples typically for a router.
 #gifconfig_gif1=""	# Examples typically for a router.
+# Nsupdate(8) allows the machine to send DNS updates to "register" in DNS.
+# IPv4 loopback (127/8), and IPv6 loopback (::1) and link-local (fe80::/10)
+# addresses are not registered.
+nsupdate_enable="NO"	# Do any DNS updates.
+nsupdate_flags=""	# Pass additional arguments, e.g. to use DNSSEC TSIG,
+			# "-k /etc/namedb:MY_DYN_DNS_KEY"
+nsupdate_command="/usr/sbin/nsupdate" # Default is base system's BIND.
+nsupdate_ipv4="YES"	# Register IPv4 addresses associated with interfaces.
+nsupdate_ipv6="YES"	# Register IPv6 addresses associated with interfaces.
+nsupdate_ifaces="auto"	# List interfaces, 'auto,' 'dhcp,' or 'nodhcp.'
+nsupdate_ttl="3600"	# Time-to-live for the DNS records.
+nsupdate_reverse="YES"	# Attempt to add "reverse" records, in-addr.arpa
+			# and ip6.arpa trees.
+nsupdate_shutdown_remove="YES" # Remove our records at shutdown.
+#nsupdate_hostname_ed0="dynamic-host.example.com" # Associate a hostname
+			# with an interface, otherwise system hostname used.
 # User ppp configuration.
 ppp_enable="NO"		# Start user-ppp (or NO).
Index: src/share/man/man5/rc.conf.5
RCS file: /ncvs/src/share/man/man5/rc.conf.5,v
retrieving revision 1.221
diff -u -r1.221 rc.conf.5
--- src/share/man/man5/rc.conf.5	18 Jul 2004 18:01:48 -0000	1.221
+++ src/share/man/man5/rc.conf.5	28 Sep 2004 05:04:30 -0000
@@ -1265,6 +1265,88 @@
 is not enabled.
 This variable is experimental.
 It may be removed or changed in the near future.
+.It Va nsupdate_enable
+.Pq Vt bool
+Set to
+.Dq Li YES
+to have the system attempt to perform DNS updates using the
+.Xr nsupdate 8
+command at start up to add records for itself and at shutdown
+to remove the same records.
+The system will attempt to enter records for each non-loopback, 
+non-link-local address associated with the interfaces specified 
+in the
+.Va nsupdate_interfaces
+By default, the domain name used for the address records and as
+the data for reverse entries is the system host name as returned by
+.Xr hostname 1 .
+The domain names associated with addresses on a specific interfaces
+can be set with
+.Va nsupdate_hostname_ Ns Aq Ar interface
+.It Va nsupdate_flags
+.Pq Vt str
+Used to pass additional arguments to the
+.Xr nsupdate 8
+For example, this may be used to pass key information to the program
+when using DNSSEC TSIG.
+.It Va nsupdate_command
+.Pq Vt str
+Set the full path of the
+.Xr nsupdate 8
+command to be uses.
+For example, this may be changed to use an
+.Xr nsupdate 8
+command with a locally installed version of BIND.
+.It Va nsupdate_ipv4
+.Pq Vt bool
+Set to
+.Dq Li NO
+to not attempt to register IPv4 address, A, records for the
+hostname or reverse pointer, PTR, records in the in-addr.arpa tree.
+.It Va nsupdate_ipv6
+.Pq Vt bool
+Set to
+.Dq Li NO
+to not attempt to register IPv6 address, AAAA, records for
+the hostname or a reverse pointer, PTR, records in the ip6.arpa tree.
+.It Va nsupdate_reverse
+.Pq Vt bool
+Set to
+.Dq Li NO
+to disable attempts to update the "reverse," in-addr.arpa and ip6.arpa,
+Reverse zones are often not under the direct administrative control 
+the users of the IP space.
+.It Va nsupdate_ifaces
+.Pq Vt str
+The default of
+.Dq Li auto
+attempts to determine all applicable interfaces on the system
+Set to
+.Dq Li dhcp
+to only perform updates with addresses associated with DHCP
+configured interfaces.
+Set to
+.Dq Li nodhcp
+to only perform updates with addresses associated with non-DHCP
+configured interfaces.
+The user may also provided an explicit list of interfaces.
+.It Va nsupdate_ttl
+.Pq Vt str
+The time-to-live value for the DNS records.
+This has to do with DNS caching lifetimes and has nothing to do
+with how long the records will be kept in the zone on the master
+.It Va nsupdate_shutdown_remove
+.Pq Vt bool
+Set to
+.Dq Li NO
+to disable the use of DNS updates to remove the records added at
+system startup during shutdown.
 .It Va kerberos5_server_enable
 .Pq Vt bool
 Set to

More information about the freebsd-current mailing list