Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 24 Sep 2004 10:24:18 -0700
From:      "Crist J. Clark" <cristjc@comcast.net>
To:        freebsd-net@freebsd.org
Subject:   nsupdate(8) rc.d Script
Message-ID:  <20040924172418.GA91417@blossom.cjclark.org>

next in thread | raw e-mail | index | archive | help

--1yeeQ81UyVL57Vl7
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

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
too.

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,

	nsupdate_enable="YES"

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@alum.mit.edu
                                   |     cjclark@jhu.edu
http://people.freebsd.org/~cjc/    |     cjc@freebsd.org

--1yeeQ81UyVL57Vl7
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="rc.nsupdate.patch"

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	24 Sep 2004 16:54:34 -0000
@@ -139,6 +139,22 @@
 				# Choose correct tunnel addrs.
 #gifconfig_gif0="10.1.1.1 10.1.2.1"	# Examples typically for a router.
 #gifconfig_gif1="10.1.1.2 10.1.2.2"	# 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::/17)
+# 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/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	24 Sep 2004 16:50:49 -0000
@@ -0,0 +1,124 @@
+#!/bin/sh
+#
+# $FreeBSD$
+#
+
+# PROVIDE: nsupdate
+# REQUIRE: NETWORKING
+# KEYWORD: FreeBSD
+
+. /etc/rc.subr
+. /etc/network.subr
+
+name="nsupdate"
+rcvar=`set_rcvar`
+start_cmd="nsupdate_start"
+stop_cmd="nsupdate_stop"
+
+nsupdate_run()
+{
+	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++) {
+						shorts[i] = substr("000" shorts[i],
+							length(shorts[i]));
+						ip6str = ip6str shorts[i];
+					}
+					revstr = "";
+					for (i = 1; i <= length(ip6str); i++) {
+						revstr = substr(ip6str, i, 1) "." revstr;
+					}
+					printf "update %s %sip6.arpa %s ptr %s\n",
+						action, revstr, ttl, hostname;
+					print "";
+				}
+			}'
+	done |
+	"${nsupdate_command}" ${nsupdate_flags}
+}
+
+nsupdate_start()
+{
+	nsupdate_run add
+}
+
+nsupdate_stop()
+{
+	checkyesno nsupdate_shutdown_remove || return 0
+	nsupdate_run delete
+}
+
+load_rc_config $name
+run_rc_command "$1"

--1yeeQ81UyVL57Vl7--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20040924172418.GA91417>