dhclient-script revision 230728
143410Snewton#!/bin/sh 243410Snewton# 343410Snewton# $OpenBSD: dhclient-script,v 1.6 2004/05/06 18:22:41 claudio Exp $ 443410Snewton# $FreeBSD: stable/9/sbin/dhclient/dhclient-script 230728 2012-01-29 10:55:19Z dumbbell $ 543410Snewton# 643410Snewton# Copyright (c) 2003 Kenneth R Westerback <krw@openbsd.org> 743410Snewton# 843410Snewton# Permission to use, copy, modify, and distribute this software for any 943410Snewton# purpose with or without fee is hereby granted, provided that the above 1043410Snewton# copyright notice and this permission notice appear in all copies. 1143410Snewton# 1243410Snewton# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1343410Snewton# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1443410Snewton# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1543410Snewton# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1643410Snewton# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1743410Snewton# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1843410Snewton# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1943410Snewton# 2043410Snewton# 2143410Snewton 2243410SnewtonARP=/usr/sbin/arp 2343410SnewtonHOSTNAME=/bin/hostname 2443410SnewtonIFCONFIG='/sbin/ifconfig -n' 2543410Snewton 2643410SnewtonLOCALHOST=127.0.0.1 2743410Snewton 2843410Snewtonif [ -x /usr/bin/logger ]; then 2943410Snewton LOGGER="/usr/bin/logger -s -p user.notice -t dhclient" 3043410Snewtonelse 3143410Snewton LOGGER=echo 3249263Snewtonfi 3343410Snewton 3443410Snewton# 35119420Sobrien# Helper functions that implement common actions. 36119420Sobrien# 37119420Sobrien 3843410Snewtoncheck_hostname() { 3943410Snewton current_hostname=`$HOSTNAME` 4043410Snewton if [ -z "$current_hostname" ]; then 4143410Snewton $LOGGER "New Hostname ($interface): $new_host_name" 4243410Snewton $HOSTNAME $new_host_name 4343410Snewton elif [ "$current_hostname" = "$old_host_name" -a \ 4443410Snewton "$new_host_name" != "$old_host_name" ]; then 4543410Snewton $LOGGER "New Hostname ($interface): $new_host_name" 4643410Snewton $HOSTNAME $new_host_name 4743410Snewton fi 4843410Snewton} 4943410Snewton 5043410Snewtonarp_flush() { 5143410Snewton arp -an -i $interface | \ 5243410Snewton sed -n -e 's/^.*(\(.*\)) at .*$/arp -d \1/p' | \ 5343410Snewton sh >/dev/null 2>&1 5443410Snewton} 5543410Snewton 5643410Snewtondelete_old_address() { 5743410Snewton eval "$IFCONFIG $interface inet -alias $old_ip_address $medium" 5843410Snewton} 5965314Sobrien 6065314Sobrienadd_new_address() { 6165314Sobrien eval "$IFCONFIG $interface \ 6265314Sobrien inet $new_ip_address \ 6365314Sobrien netmask $new_subnet_mask \ 6465314Sobrien broadcast $new_broadcast_address \ 6543410Snewton $medium" 6692739Salfred 6792739Salfred $LOGGER "New IP Address ($interface): $new_ip_address" 6843410Snewton $LOGGER "New Subnet Mask ($interface): $new_subnet_mask" 6943410Snewton $LOGGER "New Broadcast Address ($interface): $new_broadcast_address" 70115550Sphk $LOGGER "New Routers ($interface): $new_routers" 7143410Snewton} 7243410Snewton 7343410Snewtondelete_old_alias() { 7443410Snewton if [ -n "$alias_ip_address" ]; then 7543410Snewton $IFCONFIG $interface inet -alias $alias_ip_address > /dev/null 2>&1 7643410Snewton #route delete $alias_ip_address $LOCALHOST > /dev/null 2>&1 7743410Snewton fi 7843410Snewton} 7943410Snewton 8043410Snewtonadd_new_alias() { 8143410Snewton if [ -n "$alias_ip_address" ]; then 8243410Snewton $IFCONFIG $interface inet alias $alias_ip_address netmask \ 8343410Snewton $alias_subnet_mask 8443410Snewton #route add $alias_ip_address $LOCALHOST 8543410Snewton fi 8643410Snewton} 8743410Snewton 8843410Snewtonfill_classless_routes() { 8943410Snewton set $1 9043410Snewton while [ $# -ge 5 ]; do 9189059Smsmith if [ $1 -eq 0 ]; then 9252114Snewton route="default" 9352114Snewton elif [ $1 -le 8 ]; then 9443410Snewton route="$2.0.0.0/$1" 95116546Sphk shift 96116546Sphk elif [ $1 -le 16 ]; then 97116546Sphk route="$2.$3.0.0/$1" 98116546Sphk shift; shift 99116546Sphk elif [ $1 -le 24 ]; then 100116546Sphk route="$2.$3.$4.0/$1" 101116546Sphk shift; shift; shift 10243410Snewton else 10343410Snewton route="$2.$3.$4.$5/$1" 10443410Snewton shift; shift; shift; shift 105126080Sphk fi 106126080Sphk shift 107111815Sphk router="$1.$2.$3.$4" 108111815Sphk classless_routes="$classless_routes $route $router" 10947625Sphk shift; shift; shift; shift 11043410Snewton done 11143410Snewton} 11243410Snewton 11343410Snewtondelete_old_routes() { 11443410Snewton #route delete "$old_ip_address" $LOCALHOST >/dev/null 2>&1 11543410Snewton if [ -n "$old_classless_routes" ]; then 11643410Snewton fill_classless_routes "$old_classless_routes" 11743410Snewton set $classless_routes 11843410Snewton while [ $# -gt 1 ]; do 11944208Snewton route delete "$1" "$2" 12044208Snewton shift; shift 12144208Snewton done 12244208Snewton return 0; 12344208Snewton fi 12449344Snewton 12552114Snewton # If we supported multiple default routes, we'd be removing each 12652114Snewton # one here. We don't so just delete the default route if it's 12752114Snewton # through our interface. 12852114Snewton if is_default_interface; then 12952114Snewton route delete default >/dev/null 2>&1 13052114Snewton fi 13152114Snewton 13252114Snewton if [ -n "$old_static_routes" ]; then 13352114Snewton set $old_static_routes 13452114Snewton while [ $# -gt 1 ]; do 13552114Snewton route delete "$1" "$2" 13652114Snewton shift; shift 13752114Snewton done 13852114Snewton fi 13952114Snewton 14052114Snewton arp_flush 14152114Snewton} 14252114Snewton 14352114Snewtonadd_new_routes() { 14452114Snewton #route add $new_ip_address $LOCALHOST >/dev/null 2>&1 14552114Snewton 14652114Snewton # RFC 3442: If the DHCP server returns both a Classless Static 14752114Snewton # Routes option and a Router option, the DHCP client MUST ignore 14852114Snewton # the Router option. 14952114Snewton # 15052114Snewton # DHCP clients that support this option (Classless Static Routes) 15152114Snewton # MUST NOT install the routes specified in the Static Routes 15244208Snewton # option (option code 33) if both a Static Routes option and the 15344208Snewton # Classless Static Routes option are provided. 15449344Snewton 15553000Sphk if [ -n "$new_classless_routes" ]; then 15653000Sphk fill_classless_routes "$new_classless_routes" 15753000Sphk $LOGGER "New Classless Static Routes ($interface): $classless_routes" 15853000Sphk set $classless_routes 15953000Sphk while [ $# -gt 1 ]; do 16053000Sphk if [ "0.0.0.0" = "$2" ]; then 16153000Sphk route add "$1" -iface "$interface" 16253000Sphk else 16353000Sphk route add "$1" "$2" 16453000Sphk fi 16552114Snewton shift; shift 16644208Snewton done 16744208Snewton return 16844208Snewton fi 16944208Snewton 17044208Snewton for router in $new_routers; do 17144208Snewton if is_default_interface; then 17244208Snewton 17344208Snewton if [ "$new_ip_address" = "$router" ]; then 17444208Snewton route add default -iface $router >/dev/null 2>&1 17544208Snewton else 17644208Snewton route add default $router >/dev/null 2>&1 17744208Snewton fi 17844208Snewton fi 17960060Sgreen # 2nd and subsequent default routers error out, so explicitly 18044208Snewton # stop processing the list after the first one. 18143410Snewton break 18243410Snewton done 18343410Snewton 18443410Snewton if [ -n "$new_static_routes" ]; then 18543410Snewton $LOGGER "New Static Routes ($interface): $new_static_routes" 18643410Snewton set $new_static_routes 18743410Snewton while [ $# -gt 1 ]; do 18843410Snewton route add $1 $2 18983366Sjulian shift; shift 19043410Snewton done 19143410Snewton fi 192121256Sdwmalone} 19343410Snewton 19443410Snewtonadd_new_resolv_conf() { 19543410Snewton # XXX Old code did not create/update resolv.conf unless both 19643410Snewton # $new_domain_name and $new_domain_name_servers were provided. PR 19783366Sjulian # #3135 reported some ISP's only provide $new_domain_name_servers and 19843410Snewton # thus broke the script. This code creates the resolv.conf if either 19971448Sjhb # are provided. 20083366Sjulian 20171448Sjhb local tmpres=/var/run/resolv.conf.${interface} 20243410Snewton rm -f $tmpres 20371448Sjhb 20471448Sjhb if [ -n "$new_domain_search" ]; then 20543410Snewton echo "search $new_domain_search" >>$tmpres 20643410Snewton elif [ -n "$new_domain_name" ]; then 20743410Snewton echo "search $new_domain_name" >>$tmpres 20843410Snewton fi 20943410Snewton 21043410Snewton if [ -n "$new_domain_name_servers" ]; then 21143410Snewton for nameserver in $new_domain_name_servers; do 21243410Snewton echo "nameserver $nameserver" >>$tmpres 21343410Snewton done 21443410Snewton fi 21543410Snewton 21643410Snewton if [ -f $tmpres ]; then 21743410Snewton if [ -f /etc/resolv.conf.tail ]; then 21843410Snewton cat /etc/resolv.conf.tail >>$tmpres 21943410Snewton fi 22043410Snewton 22143410Snewton case $resolvconf_enable in 22243410Snewton # "no", "false", "off", or "0" 22343410Snewton [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) 22443410Snewton # When resolv.conf is not changed actually, we don't 22543410Snewton # need to update it. 22643410Snewton # If /usr is not mounted yet, we cannot use cmp, then 22743410Snewton # the following test fails. In such case, we simply 22843410Snewton # ignore an error and do update resolv.conf. 22943410Snewton if cmp -s $tmpres /etc/resolv.conf; then 23043410Snewton rm -f $tmpres 23143410Snewton return 0 23243410Snewton fi 2>/dev/null 23343410Snewton 23443410Snewton # In case (e.g. during OpenBSD installs) 23543410Snewton # /etc/resolv.conf is a symbolic link, take 23643410Snewton # care to preserve the link and write the new 23743410Snewton # data in the correct location. 23843410Snewton 23943410Snewton if [ -f /etc/resolv.conf ]; then 24043410Snewton cat /etc/resolv.conf > /etc/resolv.conf.save 24143410Snewton fi 24243410Snewton cat $tmpres > /etc/resolv.conf 24343410Snewton 24443410Snewton # Try to ensure correct ownership and permissions. 24543410Snewton chown -RL root:wheel /etc/resolv.conf 24683366Sjulian chmod -RL 644 /etc/resolv.conf 24743410Snewton ;; 24843410Snewton 24943410Snewton *) 25043410Snewton /sbin/resolvconf -a ${interface} < $tmpres 25143410Snewton ;; 25283366Sjulian esac 25343410Snewton 254121256Sdwmalone rm -f $tmpres 25543410Snewton 25688739Srwatson return 0 25791406Sjhb fi 25889306Salfred 259121256Sdwmalone return 1 260121256Sdwmalone} 261121256Sdwmalone 262121256Sdwmalone# Must be used on exit. Invokes the local dhcp client exit hooks, if any. 263121256Sdwmaloneexit_with_hooks() { 264121256Sdwmalone exit_status=$1 26589306Salfred if [ -f /etc/dhclient-exit-hooks ]; then 266121256Sdwmalone . /etc/dhclient-exit-hooks 267121256Sdwmalone fi 268121256Sdwmalone # probably should do something with exit status of the local script 26943410Snewton exit $exit_status 27043410Snewton} 27143410Snewton 27289306Salfred# Get the interface with the current ipv4 default route on it using only 273109153Sdillon# commands that are available prior to /usr being mounted. 27443410Snewtonis_default_interface() 27549413Sgreen{ 27643410Snewton routeget="`route -n get -inet default`" 27789306Salfred oldifs="$IFS" 27843410Snewton IFS=" 27943410Snewton" 280121256Sdwmalone defif= 28171448Sjhb for line in $routeget ; do 28283366Sjulian case $line in 28371448Sjhb *interface:*) 28443410Snewton defif=${line##*: } 28543410Snewton ;; 28643410Snewton esac 28743410Snewton done 28883366Sjulian IFS=${oldifs} 28983366Sjulian 29043410Snewton if [ -z "$defif" -o "$defif" = "$interface" ]; then 29183366Sjulian return 0 29243410Snewton else 29343410Snewton return 1 29443410Snewton fi 29543410Snewton} 29643410Snewton 29743410Snewton# 29843410Snewton# Start of active code. 29943410Snewton# 30043410Snewton 30143410Snewton# Invoke the local dhcp client enter hooks, if they exist. 30243410Snewtonif [ -f /etc/dhclient-enter-hooks ]; then 30343410Snewton exit_status=0 30443410Snewton . /etc/dhclient-enter-hooks 30543410Snewton # allow the local script to abort processing of this state 30643410Snewton # local script must set exit_status variable to nonzero. 30743410Snewton if [ $exit_status -ne 0 ]; then 30843410Snewton exit $exit_status 30943410Snewton fi 31043410Snewtonfi 31143410Snewton 31243410Snewton: ${resolvconf_enable="YES"} 31343410Snewton 31443410Snewtoncase $reason in 315107849SalfredMEDIUM) 316107849Salfred eval "$IFCONFIG $interface $medium" 317107849Salfred eval "$IFCONFIG $interface inet -alias 0.0.0.0 $medium" >/dev/null 2>&1 31843410Snewton sleep 1 31943410Snewton ;; 32043410Snewton 32143410SnewtonPREINIT) 32243410Snewton delete_old_alias 32343410Snewton $IFCONFIG $interface inet alias 0.0.0.0 netmask 255.0.0.0 broadcast 255.255.255.255 up 32443410Snewton ;; 32543410Snewton 32683366SjulianARPCHECK|ARPSEND) 32743410Snewton ;; 32843410Snewton 32943410SnewtonBOUND|RENEW|REBIND|REBOOT) 33043410Snewton check_hostname 33171448Sjhb if [ -n "$old_ip_address" ]; then 33283366Sjulian if [ "$old_ip_address" != "$alias_ip_address" ]; then 33371448Sjhb delete_old_alias 33443410Snewton fi 33543410Snewton if [ "$old_ip_address" != "$new_ip_address" ]; then 33643410Snewton delete_old_address 33743410Snewton delete_old_routes 33843410Snewton fi 33943410Snewton fi 34043410Snewton if [ "$reason" = BOUND ] || \ 34143410Snewton [ "$reason" = REBOOT ] || \ 34243410Snewton [ -z "$old_ip_address" ] || \ 34343410Snewton [ "$old_ip_address" != "$new_ip_address" ]; then 34443410Snewton add_new_address 34543410Snewton add_new_routes 34643410Snewton fi 34743410Snewton if [ "$new_ip_address" != "$alias_ip_address" ]; then 34843410Snewton add_new_alias 34943410Snewton fi 35043410Snewton if is_default_interface; then 35143410Snewton add_new_resolv_conf 35243410Snewton fi 35343410Snewton ;; 35443410Snewton 35543410SnewtonEXPIRE|FAIL) 35643410Snewton delete_old_alias 357109153Sdillon if [ -n "$old_ip_address" ]; then 35843410Snewton delete_old_address 35989306Salfred delete_old_routes 36089306Salfred fi 36189306Salfred if [ -x $ARP ]; then 36289306Salfred $ARP -d -a -i $interface 36343410Snewton fi 36489306Salfred # XXX Why add alias we just deleted above? 36543410Snewton add_new_alias 36643410Snewton if is_default_interface; then 367111119Simp case $resolvconf_enable in 36843410Snewton # "no", "false", "off", or "0" 36943410Snewton [Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0) 37043410Snewton if [ -f /etc/resolv.conf.save ]; then 37143410Snewton cat /etc/resolv.conf.save > /etc/resolv.conf 37289306Salfred fi 37389306Salfred ;; 37489306Salfred *) 37589306Salfred /sbin/resolvconf -d ${interface} 37689306Salfred ;; 37789306Salfred esac 37889306Salfred fi 37989306Salfred ;; 38089306Salfred 38189306SalfredTIMEOUT) 38289306Salfred delete_old_alias 38389306Salfred add_new_address 38489306Salfred sleep 1 38543410Snewton if [ -n "$new_routers" ]; then 38643410Snewton $LOGGER "New Routers ($interface): $new_routers" 38743410Snewton set "$new_routers" 38843410Snewton if ping -q -c 1 -t 1 "$1"; then 38943410Snewton if [ "$new_ip_address" != "$alias_ip_address" ]; then 39043410Snewton add_new_alias 39143410Snewton fi 39243410Snewton add_new_routes 39343410Snewton if ! is_default_interface; then 39443410Snewton exit_with_hooks 0 395109153Sdillon fi 39643410Snewton if add_new_resolv_conf; then 39771448Sjhb exit_with_hooks 0 39871448Sjhb fi 39971448Sjhb fi 40071448Sjhb fi 40171448Sjhb eval "$IFCONFIG $interface inet -alias $new_ip_address $medium" 40243410Snewton delete_old_routes 40343410Snewton exit_with_hooks 1 40443410Snewton ;; 40571448Sjhbesac 40643410Snewton 40743410Snewtonexit_with_hooks 0 40843410Snewton