Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
dhcp-ct/dhclient-script
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
executable file
754 lines (633 sloc)
23.8 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # | |
| # dhclient-script: Network interface configuration script run by | |
| # dhclient based on DHCP client communication | |
| # | |
| # Copyright (C) 2008, 2009, 2010 Red Hat, Inc. | |
| # | |
| # This program is free software; you can redistribute it and/or modify | |
| # it under the terms of the GNU General Public License as published by | |
| # the Free Software Foundation; either version 2 of the License, or | |
| # (at your option) any later version. | |
| # | |
| # This program is distributed in the hope that it will be useful, | |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| # GNU General Public License for more details. | |
| # | |
| # You should have received a copy of the GNU General Public License | |
| # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
| # | |
| # Author(s): David Cantrell <dcantrell@redhat.com> | |
| # | |
| # ---------- | |
| # This script is a rewrite/reworking on dhclient-script originally | |
| # included as part of dhcp-970306: | |
| # dhclient-script for Linux. Dan Halbert, March, 1997. | |
| # Updated for Linux 2.[12] by Brian J. Murrell, January 1999. | |
| # Modified by David Cantrell <dcantrell@redhat.com> for Fedora and RHEL | |
| # ---------- | |
| # | |
| PATH=/bin:/usr/bin:/sbin | |
| SAVEDIR=/var/lib/dhclient | |
| LOGFACILITY="local7" | |
| LOGLEVEL="notice" | |
| ETCDIR="/etc/dhcp" | |
| logmessage() { | |
| msg="${1}" | |
| logger -p ${LOGFACILITY}.${LOGLEVEL} -t "NET" "dhclient: ${msg}" | |
| } | |
| fix_context() { | |
| if [ -x /sbin/restorecon ]; then | |
| /sbin/restorecon ${1} >/dev/null 2>&1 | |
| fi | |
| } | |
| save_previous() { | |
| origfile="${1}" | |
| savefile="${SAVEDIR}/${origfile##*/}.predhclient.${interface}" | |
| if [ ! -d ${SAVEDIR} ]; then | |
| mkdir -p ${SAVEDIR} | |
| fi | |
| if [ -e ${origfile} ]; then | |
| contents="$(< ${origfile})" | |
| echo "${contents}" > ${savefile} | |
| rm -f ${origfile} | |
| else | |
| echo > ${savefile} | |
| fi | |
| fix_context ${savefile} | |
| } | |
| make_resolv_conf() { | |
| [ "${PEERDNS}" = "no" ] && return | |
| if [ "${reason}" = "RENEW" ] && | |
| [ "${new_domain_name}" = "${old_domain_name}" ] && | |
| [ "${new_domain_name_servers}" = "${old_domain_name_servers}" ]; then | |
| return | |
| fi | |
| if [ -n "${new_domain_name}" ] || | |
| [ -n "${new_domain_name_servers}" ] || | |
| [ -n "${new_domain_search}" ]; then | |
| save_previous /etc/resolv.conf | |
| rscf="$(mktemp /tmp/XXXXXX)" | |
| echo "; generated by /sbin/dhclient-script" > ${rscf} | |
| if [ -n "${SEARCH}" ]; then | |
| echo "search ${SEARCH}" >> $rscf | |
| else | |
| if [ -n "${new_domain_search}" ]; then | |
| echo "search ${new_domain_search//\\032/ }" >> ${rscf} | |
| elif [ -n "${new_domain_name}" ]; then | |
| # Note that the DHCP 'Domain Name Option' is really just a domain | |
| # name, and that this practice of using the domain name option as | |
| # a search path is both nonstandard and deprecated. | |
| echo "search ${new_domain_name//\\032/ }" >> ${rscf} | |
| fi | |
| fi | |
| if [ -n "${RES_OPTIONS}" ]; then | |
| echo "options ${RES_OPTIONS}" >> ${rscf} | |
| fi | |
| for nameserver in ${new_domain_name_servers} ; do | |
| echo "nameserver ${nameserver}" >> ${rscf} | |
| done | |
| change_resolv_conf ${rscf} | |
| rm -f ${rscf} | |
| fix_context /etc/resolv.conf | |
| elif [ -n "${new_dhcp6_name_servers}" ] || | |
| [ -n "${new_dhcp6_domain_search}" ]; then | |
| save_previous /etc/resolv.conf | |
| rscf="$(mktemp /tmp/XXXXXX)" | |
| echo "; generated by /sbin/dhclient-script" > ${rscf} | |
| if [ -n "${SEARCH}" ]; then | |
| echo "search ${SEARCH}" >> $rscf | |
| else | |
| if [ -n "${new_dhcp6_domain_search}" ]; then | |
| echo "search ${new_dhcp6_domain_search//\\032/ }" >> ${rscf} | |
| fi | |
| fi | |
| if [ -n "${RES_OPTIONS}" ]; then | |
| echo "options ${RES_OPTIONS}" >> ${rscf} | |
| fi | |
| for nameserver in ${new_dhcp6_name_servers} ; do | |
| echo "nameserver ${nameserver}" >> ${rscf} | |
| done | |
| change_resolv_conf ${rscf} | |
| rm -f ${rscf} | |
| fix_context /etc/resolv.conf | |
| fi | |
| } | |
| exit_with_hooks() { | |
| exit_status="${1}" | |
| if [ -x ${ETCDIR}/dhclient-exit-hooks ]; then | |
| . ${ETCDIR}/dhclient-exit-hooks | |
| fi | |
| exit ${exit_status} | |
| } | |
| quad2num() { | |
| if [ $# -eq 4 ]; then | |
| let n="${1} << 24 | ${2} << 16 | ${3} << 8 | ${4}" | |
| echo "${n}" | |
| return 0 | |
| else | |
| echo "0" | |
| return 1 | |
| fi | |
| } | |
| ip2num() { | |
| IFS="." quad2num ${1} | |
| } | |
| num2ip() { | |
| let n="${1}" | |
| let o1="(n >> 24) & 0xff" | |
| let o2="(n >> 16) & 0xff" | |
| let o3="(n >> 8) & 0xff" | |
| let o4="n & 0xff" | |
| echo "${o1}.${o2}.${o3}.${o4}" | |
| } | |
| get_network_address() { | |
| # get network address for the given IP address and (netmask or prefix) | |
| ip="${1}" | |
| nm="${2}" | |
| if [ -n "${ip}" -a -n "${nm}" ]; then | |
| if [[ "${nm}" = *.* ]]; then | |
| ipcalc -s -n ${ip} ${nm} | cut -d '=' -f 2 | |
| else | |
| ipcalc -s -n ${ip}/${nm} | cut -d '=' -f 2 | |
| fi | |
| fi | |
| } | |
| get_prefix() { | |
| # get prefix for the given IP address and mask | |
| ip="${1}" | |
| nm="${2}" | |
| if [ -n "${ip}" -a -n "${nm}" ]; then | |
| ipcalc -s -p ${ip} ${nm} | cut -d '=' -f 2 | |
| fi | |
| } | |
| class_bits() { | |
| let ip=$(IFS='.' ip2num $1) | |
| let bits=32 | |
| let mask='255' | |
| for ((i=0; i <= 3; i++, 'mask<<=8')); do | |
| let v='ip&mask' | |
| if [ "$v" -eq 0 ] ; then | |
| let bits-=8 | |
| else | |
| break | |
| fi | |
| done | |
| echo $bits | |
| } | |
| is_router_reachable() { | |
| # handle DHCP servers that give us a router not on our subnet | |
| router="${1}" | |
| routersubnet="$(get_network_address ${router} ${new_subnet_mask})" | |
| mysubnet="$(get_network_address ${new_ip_address} ${new_subnet_mask})" | |
| unreachable=0 | |
| if [ ! "${routersubnet}" = "${mysubnet}" ]; then | |
| unreachable=1 | |
| if arping -f -q -I ${interface} -w2 ${router}; then | |
| ip -4 route add ${router}/32 dev ${interface} | |
| if [ $? -eq 0 ]; then | |
| unreachable=0 | |
| else | |
| logmessage "failed to create host router for unreachable router ${router} not on subnet ${mysubnet}" | |
| fi | |
| else | |
| unreachable=1 | |
| logmessage "DHCP router ${router} is unreachable on DHCP subnet ${mysubnet} router subnet ${routersubnet}" | |
| fi | |
| fi | |
| return ${unreachable} | |
| } | |
| add_default_gateway() { | |
| router="${1}" | |
| metric="" | |
| if [ $# -gt 1 ] && [ ${2} -gt 0 ]; then | |
| metric="metric ${2}" | |
| fi | |
| if is_router_reachable ${router} ; then | |
| ip -4 route replace default via ${router} dev ${interface} ${metric} | |
| if [ $? -ne 0 ]; then | |
| logmessage "failed to create default route: ${router} dev ${interface} ${metric}" | |
| return 1 | |
| else | |
| return 0 | |
| fi | |
| fi | |
| return 1 | |
| } | |
| dhconfig() { | |
| if [ -n "${old_ip_address}" ] && [ -n "${alias_ip_address}" ] && | |
| [ ! "${alias_ip_address}" = "${old_ip_address}" ]; then | |
| # possible new alias, remove old alias first | |
| ip -4 addr del ${old_ip_address} dev ${interface}:0 | |
| fi | |
| if [ -n "${old_ip_address}" ] && | |
| [ ! "${old_ip_address}" = "${new_ip_address}" ]; then | |
| # IP address changed. Bringing down the interface will delete all | |
| # routes, and clear the ARP cache. | |
| ip -4 addr flush dev ${interface} >/dev/null 2>&1 | |
| fi | |
| if [ "${reason}" = "BOUND" ] || [ "${reason}" = "REBOOT" ] || | |
| [ ! "${old_ip_address}" = "${new_ip_address}" ] || | |
| [ ! "${old_subnet_mask}" = "${new_subnet_mask}" ] || | |
| [ ! "${old_network_number}" = "${new_network_number}" ] || | |
| [ ! "${old_broadcast_address}" = "${new_broadcast_address}" ] || | |
| [ ! "${old_routers}" = "${new_routers}" ] || | |
| [ ! "${old_interface_mtu}" = "${new_interface_mtu}" ]; then | |
| ip -4 addr add ${new_ip_address}/${new_prefix} broadcast ${new_broadcast_address} dev ${interface} | |
| ip link set dev ${interface} up | |
| # The 576 MTU is only used for X.25 and dialup connections | |
| # where the admin wants low latency. Such a low MTU can cause | |
| # problems with UDP traffic, among other things. As such, | |
| # disallow MTUs from 576 and below by default, so that broken | |
| # MTUs are ignored, but higher stuff is allowed (1492, 1500, etc). | |
| if [ -n "${new_interface_mtu}" ] && [ ${new_interface_mtu} -gt 576 ]; then | |
| ip link set ${interface} mtu ${new_interface_mtu} | |
| fi | |
| if [ -x ${ETCDIR}/dhclient-${interface}-up-hooks ]; then | |
| . ${ETCDIR}/dhclient-${interface}-up-hooks | |
| elif [ -x ${ETCDIR}/dhclient-up-hooks ]; then | |
| . ${ETCDIR}/dhclient-up-hooks | |
| fi | |
| # static routes | |
| if [ -n "${new_classless_static_routes}" ] || | |
| [ -n "${new_static_routes}" ]; then | |
| if [ -n "${new_classless_static_routes}" ]; then | |
| IFS=', |' static_routes=(${new_classless_static_routes}) | |
| # If the DHCP server returns both a Classless Static Routes option and | |
| # a Router option, the DHCP client MUST ignore the Router option. (RFC3442) | |
| new_routers="" | |
| else | |
| IFS=', |' static_routes=(${new_static_routes}) | |
| fi | |
| route_targets=() | |
| for((i=0; i<${#static_routes[@]}; i+=2)); do | |
| target=${static_routes[$i]} | |
| if [ -n "${new_classless_static_routes}" ]; then | |
| prefix=$(echo ${target} | cut -d "." -f 1) | |
| target=$(echo ${target} | cut -d "." -f 2-) | |
| IFS="." target_arr=(${target}) | |
| unset IFS | |
| ((pads=4-${#target_arr[@]})) | |
| for j in $(seq $pads); do | |
| target=${target}".0" | |
| done | |
| # Client MUST zero any bits in the subnet number where the corresponding bit in the mask is zero. | |
| # In other words, the subnet number installed in the routing table is the logical AND of | |
| # the subnet number and subnet mask given in the Classless Static Routes option. (RFC3442) | |
| target="$(get_network_address ${target} ${prefix})" | |
| else | |
| prefix=$(class_bits ${target}) | |
| fi | |
| gateway=${static_routes[$i+1]} | |
| metric='' | |
| for t in ${route_targets[@]}; do | |
| if [ ${t} = ${target} ]; then | |
| if [ -z "${metric}" ]; then | |
| metric=1 | |
| else | |
| ((metric=metric+1)) | |
| fi | |
| fi | |
| done | |
| if [ -n "${metric}" ]; then | |
| metric="metric ${metric}" | |
| fi | |
| if is_router_reachable ${gateway}; then | |
| ip -4 route replace ${target}/${prefix} via ${gateway} dev ${interface} ${metric} | |
| if [ $? -ne 0 ]; then | |
| logmessage "failed to create static route: ${target}/${prefix} via ${gateway} dev ${interface} ${metric}" | |
| else | |
| route_targets=(${route_targets[@]} ${target}) | |
| fi | |
| fi | |
| done | |
| fi | |
| # gateways | |
| if [[ ( "${DEFROUTE}" != "no") && | |
| (( -z "${GATEWAYDEV}" ) || | |
| ( "${GATEWAYDEV}" = "${interface}" )) ]]; then | |
| if [[ ( -z "$GATEWAY" ) || | |
| (( -n "$DHCLIENT_IGNORE_GATEWAY" ) && | |
| ( "$DHCLIENT_IGNORE_GATEWAY" = [Yy]* )) ]]; then | |
| metric="${METRIC:-}" | |
| let i="${METRIC:-0}" | |
| default_routers=() | |
| for router in ${new_routers} ; do | |
| added_router=- | |
| for r in ${default_routers[@]} ; do | |
| if [ "${r}" = "${router}" ]; then | |
| added_router=1 | |
| fi | |
| done | |
| if [ -z "${router}" ] || | |
| [ "${added_router}" = "1" ] || | |
| [ $(IFS=. ip2num ${router}) -le 0 ] || | |
| [[ ( "${router}" = "${new_broadcast_address}" ) && | |
| ( "${new_subnet_mask}" != "255.255.255.255" ) ]]; then | |
| continue | |
| fi | |
| default_routers=(${default_routers[@]} ${router}) | |
| add_default_gateway ${router} ${metric} | |
| let i=i+1 | |
| metric=${i} | |
| done | |
| elif [ -n "${GATEWAY}" ]; then | |
| routersubnet=$(get_network_address ${GATEWAY} ${new_subnet_mask}) | |
| mysubnet=$(get_network_address ${new_ip_address} ${new_subnet_mask}) | |
| if [ "${routersubnet}" = "${mysubnet}" ]; then | |
| ip -4 route replace default via ${GATEWAY} dev ${interface} | |
| fi | |
| fi | |
| fi | |
| fi | |
| if [ ! "${new_ip_address}" = "${alias_ip_address}" ] && | |
| [ -n "${alias_ip_address}" ]; then | |
| ip -4 addr flush dev ${interface}:0 >/dev/null 2>&1 | |
| ip -4 addr add ${alias_ip_address}/${alias_prefix} dev ${interface}:0 | |
| ip -4 route replace ${alias_ip_address}/32 dev ${interface}:0 | |
| fi | |
| make_resolv_conf | |
| if [ -n "${new_host_name}" ] && need_hostname; then | |
| hostname ${new_host_name} || echo "See -nc option in dhclient(8) man page." | |
| fi | |
| if [ -n "${DHCP_TIME_OFFSET_SETS_TIMEZONE}" ] && | |
| [[ "${DHCP_TIME_OFFSET_SETS_TIMEZONE}" = [yY1]* ]]; then | |
| if [ -n "${new_time_offset}" ]; then | |
| # DHCP option "time-offset" is requested by default and should be | |
| # handled. The geographical zone abbreviation cannot be determined | |
| # from the GMT offset, but the $ZONEINFO/Etc/GMT$offset file can be | |
| # used - note: this disables DST. | |
| ((z=new_time_offset/3600)) | |
| ((hoursWest=$(printf '%+d' $z))) | |
| if (( $hoursWest < 0 )); then | |
| # tzdata treats negative 'hours west' as positive 'gmtoff'! | |
| ((hoursWest*=-1)) | |
| fi | |
| tzfile=/usr/share/zoneinfo/Etc/GMT$(printf '%+d' ${hoursWest}) | |
| if [ -e ${tzfile} ]; then | |
| save_previous /etc/localtime | |
| cp -fp ${tzfile} /etc/localtime | |
| touch /etc/localtime | |
| fix_context /etc/localtime | |
| fi | |
| fi | |
| fi | |
| # execute any additional client side configuration scripts we have | |
| if [ -d ${ETCDIR}/dhclient.d ]; then | |
| for f in ${ETCDIR}/dhclient.d/*.sh ; do | |
| if [ -x ${f} ]; then | |
| subsystem="${f%.sh}" | |
| subsystem="${subsystem##*/}" | |
| . ${f} | |
| "${subsystem}_config" | |
| fi | |
| done | |
| fi | |
| } | |
| # Section 18.1.8. (Receipt of Reply Messages) of RFC 3315 says: | |
| # The client SHOULD perform duplicate address detection on each of | |
| # the addresses in any IAs it receives in the Reply message before | |
| # using that address for traffic. | |
| add_ipv6_addr_with_DAD() { | |
| ip -6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \ | |
| dev ${interface} scope global | |
| # repeatedly test whether newly added address passed | |
| # duplicate address detection (DAD) | |
| for i in $(seq 5); do | |
| sleep 1 # give the DAD some time | |
| # tentative flag = DAD is still not complete or failed | |
| duplicate=$(ip -6 addr show dev ${interface} tentative \ | |
| | grep ${new_ip6_address}/${new_ip6_prefixlen}) | |
| # if there's no tentative flag, address passed DAD | |
| if [ -z "${duplicate}" ]; then | |
| break | |
| fi | |
| done | |
| # if there's still tentative flag = address didn't pass DAD = | |
| # = it's duplicate = remove it | |
| if [ -n "${duplicate}" ]; then | |
| ip -6 addr del ${new_ip6_address}/${new_ip6_prefixlen} dev ${interface} | |
| exit_with_hooks 3 | |
| fi | |
| } | |
| dh6config() { | |
| case "${reason}" in | |
| BOUND6) | |
| if [ -z "${new_ip6_address}" ] && | |
| [ -z "${new_ip6_prefixlen}" ]; then | |
| exit_with_hooks 2 | |
| fi | |
| add_ipv6_addr_with_DAD | |
| make_resolv_conf | |
| ;; | |
| RENEW6|REBIND6) | |
| if [ -n "${new_ip6_prefixlen}" ] && | |
| [ -n "${new_ip6_address}" ] && | |
| [ ! "${new_ip6_address}" = "${old_ip6_address}" ]; then | |
| add_ipv6_addr_with_DAD | |
| fi | |
| if [ ! "${new_dhcp6_name_servers}" = "${old_dhcp6_name_servers}" ] || | |
| [ ! "${new_dhcp6_domain_search}" = "${old_dhcp6_domain_search}" ]; then | |
| make_resolv_conf | |
| fi | |
| ;; | |
| DEPREF6) | |
| if [ -z "${new_ip6_prefixlen}" ]; then | |
| exit_with_hooks 2 | |
| fi | |
| ip -6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \ | |
| dev ${interface} scope global preferred_lft 0 | |
| ;; | |
| esac | |
| # execute any additional client side configuration scripts we have | |
| if [ -d ${ETCDIR}/dhclient.d ]; then | |
| for f in ${ETCDIR}/dhclient.d/*.sh ; do | |
| if [ -x ${f} ]; then | |
| subsystem="${f%.sh}" | |
| subsystem="${subsystem##*/}" | |
| . ${f} | |
| "${subsystem}_config" | |
| fi | |
| done | |
| fi | |
| } | |
| # | |
| # ### MAIN | |
| # | |
| if [ -x ${ETCDIR}/dhclient-enter-hooks ]; then | |
| exit_status=0 | |
| # dhclient-enter-hooks can abort dhclient-script by setting | |
| # the exit_status variable to a non-zero value | |
| . ${ETCDIR}/dhclient-enter-hooks | |
| if [ ${exit_status} -ne 0 ]; then | |
| exit ${exit_status} | |
| fi | |
| fi | |
| if [ ! -r /etc/sysconfig/network-scripts/network-functions ]; then | |
| echo "Missing /etc/sysconfig/network-scripts/network-functions, exiting." >&2 | |
| exit 1 | |
| fi | |
| if [ ! -r /etc/rc.d/init.d/functions ]; then | |
| echo "Missing /etc/rc.d/init.d/functions, exiting." >&2 | |
| exit 1 | |
| fi | |
| . /etc/sysconfig/network-scripts/network-functions | |
| . /etc/rc.d/init.d/functions | |
| if [ -f /etc/sysconfig/network ]; then | |
| . /etc/sysconfig/network | |
| fi | |
| if [ -f /etc/sysconfig/networking/network ]; then | |
| . /etc/sysconfig/networking/network | |
| fi | |
| cd /etc/sysconfig/network-scripts | |
| CONFIG="ifcfg-${interface}" | |
| need_config ${CONFIG} | |
| source_config >/dev/null 2>&1 | |
| new_prefix="$(get_prefix ${new_ip_address} ${new_subnet_mask})" | |
| old_prefix="$(get_prefix ${old_ip_address} ${old_subnet_mask})" | |
| alias_prefix="$(get_prefix ${alias_ip_address} ${alias_subnet_mask})" | |
| case "${reason}" in | |
| MEDIUM) | |
| # Linux doesn't handle mediums (media) | |
| exit_with_hooks 0 | |
| ;; | |
| PREINIT) | |
| if [ -n "${alias_ip_address}" ]; then | |
| # Bring down alias interface, its routes will disappear too. | |
| ip link set ${interface}:0 down | |
| fi | |
| if [ "${keep_old_ip}" = "yes" ]; then | |
| ip link set ${interface} up | |
| else | |
| ip -4 addr flush dev ${interface} >/dev/null 2>&1 | |
| ip link set ${interface} up | |
| fi | |
| if [ -n "${DHCLIENT_DELAY}" ] && [ ${DHCLIENT_DELAY} -gt 0 ]; then | |
| sleep ${DHCLIENT_DELAY} | |
| fi | |
| exit_with_hooks 0 | |
| ;; | |
| PREINIT6) | |
| # ensure interface is up | |
| ip link set ${interface} up | |
| # remove any stale addresses from aborted clients | |
| ip -6 addr flush dev ${interface} scope global permanent | |
| exit_with_hooks 0 | |
| ;; | |
| ARPCHECK|ARPSEND) | |
| if [ -z "${new_ip_address}" ] || [ -z "${interface}" ] || | |
| arping -q -f -c 2 -w 3 -D -I ${interface} ${new_ip_address}; then | |
| exit_with_hooks 0 | |
| else | |
| exit_with_hooks 1 | |
| fi | |
| ;; | |
| BOUND|RENEW|REBIND|REBOOT) | |
| dhconfig | |
| exit_with_hooks 0 | |
| ;; | |
| BOUND6|RENEW6|REBIND6|DEPREF6) | |
| dh6config | |
| exit_with_hooks 0 | |
| ;; | |
| EXPIRE6|RELEASE6|STOP6) | |
| if [ -z "${old_ip6_address}" ] || [ -z "${old_ip6_prefixlen}" ]; then | |
| exit_with_hooks 2 | |
| fi | |
| ip -6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \ | |
| dev ${interface} | |
| # execute any additional client side configuration scripts we have | |
| if [ -d ${ETCDIR}/dhclient.d ]; then | |
| for f in ${ETCDIR}/dhclient.d/*.sh ; do | |
| if [ -x ${f} ]; then | |
| subsystem="${f%.sh}" | |
| subsystem="${subsystem##*/}" | |
| . ${f} | |
| "${subsystem}_restore" | |
| fi | |
| done | |
| fi | |
| if [ -x ${ETCDIR}/dhclient-${interface}-down-hooks ]; then | |
| . ${ETCDIR}/dhclient-${interface}-down-hooks | |
| elif [ -x ${ETCDIR}/dhclient-down-hooks ]; then | |
| . ${ETCDIR}/dhclient-down-hooks | |
| fi | |
| exit_with_hooks 0 | |
| ;; | |
| EXPIRE|FAIL|RELEASE|STOP) | |
| # only restore config files if there are no other dhclient processes | |
| # running (#306381) | |
| any_other_clients="$(ps -eo pid,ppid,comm | grep dhclient | grep -v ${PPID})" | |
| if [ -n "${any_other_clients}" ]; then | |
| if [ -f ${SAVEDIR}/resolv.conf.predhclient.${interface} ]; then | |
| change_resolv_conf ${SAVEDIR}/resolv.conf.predhclient.${interface} | |
| rm -f ${SAVEDIR}/resolv.conf.predhclient.${interface} | |
| fi | |
| if [ -n "${DHCP_TIME_OFFSET_SETS_TIMEZONE}" ] && | |
| [[ "${DHCP_TIME_OFFSET_SETS_TIMEZONE}" = [yY1]* ]]; then | |
| if [ -e ${SAVEDIR}/localtime.predhclient.${interface} ]; then | |
| rm -f /etc/localtime | |
| contents="$(< ${SAVEDIR}/localtime.predhclient.${interface})" | |
| echo "${contents}" > /etc/localtime | |
| rm -f ${SAVEDIR}/localtime.predhclient.${interface} | |
| touch /etc/localtime | |
| fix_context /etc/localtime | |
| fi | |
| fi | |
| fi | |
| # execute any additional client side configuration scripts we have | |
| if [ -d ${ETCDIR}/dhclient.d ]; then | |
| for f in ${ETCDIR}/dhclient.d/*.sh ; do | |
| if [ -x ${f} ]; then | |
| subsystem="${f%.sh}" | |
| subsystem="${subsystem##*/}" | |
| . ${f} | |
| "${subsystem}_restore" | |
| fi | |
| done | |
| fi | |
| if [ -x ${ETCDIR}/dhclient-${interface}-down-hooks ]; then | |
| . ${ETCDIR}/dhclient-${interface}-down-hooks | |
| elif [ -x ${ETCDIR}/dhclient-down-hooks ]; then | |
| . ${ETCDIR}/dhclient-down-hooks | |
| fi | |
| if [ -n "${alias_ip_address}" ]; then | |
| # Turn off alias interface | |
| ip link set ${interface}:0 down | |
| fi | |
| if [ -n "${old_ip_address}" ]; then | |
| # Shut down interface, which will delete routes and clear arp cache. | |
| ip -4 addr flush dev ${interface} >/dev/null 2>&1 | |
| ip link set ${interface} down | |
| fi | |
| if [ -n "${alias_ip_address}" ]; then | |
| ip -4 addr add ${alias_ip_address}/${alias_prefix} dev ${interface}:0 | |
| ip -4 route replace ${alias_ip_address}/32 ${interface}:0 | |
| fi | |
| exit_with_hooks 0 | |
| ;; | |
| TIMEOUT) | |
| if [ -n "${new_routers}" ]; then | |
| if [ -n "${alias_ip_address}" ]; then | |
| ip -4 addr flush dev ${interface}:0 >/dev/null 2>&1 | |
| fi | |
| ip -4 addr add ${new_ip_address}/${new_prefix} broadcast ${new_broadcast_address} dev ${interface} | |
| set ${new_routers} | |
| if ping -q -c 1 -w 10 -I ${interface} ${1}; then | |
| dhconfig | |
| exit_with_hooks 0 | |
| fi | |
| ip -4 addr flush dev ${interface} >/dev/null 2>&1 | |
| ip link set ${interface} down | |
| exit_with_hooks 1 | |
| else | |
| exit_with_hooks 1 | |
| fi | |
| ;; | |
| *) | |
| logmessage "unhandled state: ${reason}" | |
| exit_with_hooks 1 | |
| ;; | |
| esac | |
| exit_with_hooks 0 |