Tuesday November 09, 2004 One of the great things about DHCP is that an a well configured environment there can be lots of interesting local configuration information available. Until Solaris 10 there was no easy way to add your own hooks into this that would run automatically at signficant DHCP events like the bind, extend, drop, release.
dhcpagent(1m) now provides such a hook. It is really simple to use, you just create your own /etc/dhcp/eventhook program (which can be a shell script or any other executable). Two arguments are passed, the first is the interface on which the event happened, the second is the event (BOUND | EXTEND | RELEASE | DROP).
I regularly use my laptop in a few different environments, some of which have NIS available but most don't. Combining the DHCP eventhook with SMF gives me the ability to automatically get DNS and NIS setup if they are available. My eventhook program looks like this:
#!/bin/ksh
#
# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
PATH=/sbin:/usr/sbin:/usr/bin
LOG=/var/log/dhcp-eventhook.log
INTERFACE=$1
ACTION=$2
eventhook_comment="# Added by /etc/dhcp/eventhook"
echo "`date`:$@" >> $LOG
if [ "$ACTION" == "BOUND" -o "$ACTION" == "EXTEND" ]; then
# Avoid the pesky caching of previous stuff
rm /etc/dhcp/${INTERFACE}.dhc
# See if we should preseve a statically configured resolv.conf
if [ -r /etc/resolv.conf ]; then
if ! grep "^$eventhook_comment" /etc/resolv.conf \
> /dev/null ; then
echo "Saving existing resolv.conf" >> $LOG
mv /etc/resolv.conf /etc/resolv.conf-pre-eventhook
fi
fi
echo $eventhook_comment >> /tmp/resolv.conf.$$
domain=`dhcpinfo -i $INTERFACE DNSdmain`
echo "domain = $domain" >> $LOG
if [ ! -z "$domain" ]; then
dhcpinfo -i $INTERFACE DNSdmain | \
awk '{ printf("domain %s\n", $1) }' >> /tmp/resolv.conf.$$
fi
echo Getting DNS servers >> $LOG
dhcpinfo -i $INTERFACE DNSserv | \
awk '{ printf("nameserver %s\n", $1) }' >> /tmp/resolv.conf.$$
mv /tmp/resolv.conf.$$ /etc/resolv.conf
chmod 644 /etc/resolv.conf
nis_domainname=`dhcpinfo -i $INTERFACE NISdmain`
[ -z "$nis_domainname" ] && exit 0
echo $nis_domainname > /etc/defaultdomain
svcadm restart svc:/system/identity:domain
# Temporarily enable NIS
svcadm enable -t svc:/network/nis/client:default
svcadm enable -t svc:/network/dns/client:default
svcadm restart svc:/system/name-service-cache:default
elif [ "$ACTION" == "DROP" -o "$ACTION" == "RELEASE" ]; then
rm /etc/resolv.conf
if [ -r /etc/resolv.conf-pre-eventhook ]; then
echo "Restoring pre-eventhook resolv.conf" >> $LOG
mv /etc/resolv.conf-pre-eventhook /etc/resolv.conf
fi
rm -f /var/yp/binding/$dh_domainname/ypservers
rm -f /etc/defaultdomain
svcadm restart svc:/system/identity:domain
svcadm disable svc:/network/dns/client:default
svcadm disable svc:/network/nis/client:default
# Avoid the pesky caching of previous stuff
rm /etc/dhcp/${INTERFACE}.dhc
fi
Note the use of `enable -t` when turning on NIS, this ensures that it doesn't automatically try and become active on reboot, which might be on a network that doesn't have NIS. You will probably also notice that I do not update the /etc/nsswitch.conf file at all in there. Instead I use the lesser known control features of the nsswitch.conf syntax to "ignore" DNS and NIS when they aren't available, all of the entries in my /etc/nsswitch.conf file are for the files repository with two exceptions shown below. This basicaly means, use DNS or NIS in addition to files if they are available but don't wait or complain if they aren't. I find this is ideal for laptop use, but I wouldn't do this on a desktop or server that never changes network.
hosts: files dns [UNAVAIL=return] automount: files nis [UNAVAIL=return]( Nov 09 2004, 04:45:20 PM GMT ) Permalink