Created
September 23, 2015 09:40
-
-
Save mooperd/c4903087941cfbf0abbe to your computer and use it in GitHub Desktop.
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-2014 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> | |
# Jiri Popelka <jpopelka@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 | |
# scripts in dhclient.d/ use $SAVEDIR (#833054) | |
SAVEDIR=/var/lib/dhclient | |
LOGFACILITY="local7" | |
LOGLEVEL="notice" | |
ETCDIR="/etc/dhcp" | |
logmessage() { | |
msg="${1}" | |
logger -p ${LOGFACILITY}.${LOGLEVEL} -t "NET" "dhclient: ${msg}" | |
} | |
if [ -x /sbin/restorecon ]; then | |
fix_context() { | |
/sbin/restorecon ${1} >/dev/null 2>&1 | |
} | |
else | |
fix_context() { :; } | |
fi | |
eventually_add_hostnames_domain_to_search() { | |
# For the case when hostname for this machine has a domain that is not in domain_search list | |
# 1) get a hostname with `ipcalc --hostname` or `hostname` | |
# 2) get the domain from this hostname | |
# 3) add this domain to search line in resolv.conf if it's not already | |
# there (domain list that we have recently added there is a parameter of this function) | |
# We can't do this directly when generating resolv.conf in make_resolv_conf(), because | |
# we need to first save the resolv.conf with obtained values before we can call `ipcalc --hostname`. | |
# See bug 637763 | |
search="${1}" | |
if need_hostname; then | |
status=1 | |
if [ -n "${new_ip_address}" ]; then | |
eval $(/bin/ipcalc --silent --hostname ${new_ip_address} ; echo "status=$?") | |
elif [ -n "${new_ip6_address}" ]; then | |
eval $(/bin/ipcalc --silent --hostname ${new_ip6_address} ; echo "status=$?") | |
fi | |
if [ ${status} -eq 0 ]; then | |
domain=$(echo $HOSTNAME | cut -s -d "." -f 2-) | |
fi | |
else | |
domain=$(hostname 2>/dev/null | cut -s -d "." -f 2-) | |
fi | |
if [ -n "${domain}" ] && | |
[ ! "${domain}" = "localdomain" ] && | |
[ ! "${domain}" = "localdomain6" ] && | |
[ ! "${domain}" = "(none)" ] && | |
[[ ! "${domain}" = *\ * ]]; then | |
is_in="false" | |
for s in ${search}; do | |
if [ "${s}" = "${domain}" ] || | |
[ "${s}" = "${domain}." ]; then | |
is_in="true" | |
fi | |
done | |
if [ "${is_in}" = "false" ]; then | |
# Add domain name to search list (#637763) | |
sed -i -e "s/${search}/${search} ${domain}/" /etc/resolv.conf | |
fi | |
fi | |
} | |
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 | |
rscf="$(mktemp ${TMPDIR:-/tmp}/XXXXXX)" | |
[[ -z "${rscf}" ]] && return | |
echo "; generated by /usr/sbin/dhclient-script" > ${rscf} | |
if [ -n "${SEARCH}" ]; then | |
search="${SEARCH}" | |
else | |
if [ -n "${new_domain_search}" ]; then | |
# Remove instaces of \032 (#450042) | |
search="${new_domain_search//\\032/ }" | |
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. | |
search="${new_domain_name}" | |
fi | |
fi | |
if [ -n "${search}" ]; then | |
echo "search ${search}" >> $rscf | |
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} | |
if [ -n "${search}" ]; then | |
eventually_add_hostnames_domain_to_search "${search}" | |
fi | |
fix_context /etc/resolv.conf | |
elif [ -n "${new_dhcp6_name_servers}" ] || | |
[ -n "${new_dhcp6_domain_search}" ]; then | |
rscf="$(mktemp ${TMPDIR:-/tmp}/XXXXXX)" | |
[[ -z "${rscf}" ]] && return | |
echo "; generated by /usr/sbin/dhclient-script" > ${rscf} | |
if [ -n "${SEARCH}" ]; then | |
search="${SEARCH}" | |
else | |
if [ -n "${new_dhcp6_domain_search}" ]; then | |
search="${new_dhcp6_domain_search//\\032/ }" | |
fi | |
fi | |
if [ -n "${search}" ]; then | |
echo "search ${search}" >> $rscf | |
fi | |
if [ -n "${RES_OPTIONS}" ]; then | |
echo "options ${RES_OPTIONS}" >> ${rscf} | |
fi | |
shopt -s nocasematch | |
for nameserver in ${new_dhcp6_name_servers} ; do | |
# If the nameserver has a link-local address | |
# add a <zone_id> (interface name) to it. | |
if [[ "$nameserver" =~ ^fe80:: ]] | |
then | |
zone_id="%${interface}" | |
else | |
zone_id= | |
fi | |
echo "nameserver ${nameserver}$zone_id" >> ${rscf} | |
done | |
shopt -u nocasematch | |
change_resolv_conf ${rscf} | |
rm -f ${rscf} | |
if [ -n "${search}" ]; then | |
eventually_add_hostnames_domain_to_search "${search}" | |
fi | |
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})" | |
if [ ! "${routersubnet}" = "${mysubnet}" ]; then | |
ip -4 route add ${router}/32 dev ${interface} | |
if [ $? -eq 0 ]; then | |
if ping -q -c1 -w2 -I ${interface} ${router}; then | |
return 0 | |
else | |
logmessage "DHCP router ${router} is unreachable on DHCP subnet ${mysubnet} router subnet ${routersubnet}" | |
ip route del ${router}/32 dev ${interface} | |
return 1 | |
fi | |
else | |
logmessage "failed to create host router for unreachable router ${router} not on subnet ${mysubnet}" | |
return 1 | |
fi | |
fi | |
return 0 | |
} | |
add_default_gateway() { | |
router="${1}" | |
if is_router_reachable ${router} ; then | |
metric="" | |
if [ $# -gt 1 ] && [ ${2} -gt 0 ]; then | |
metric="metric ${2}" | |
fi | |
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 | |
} | |
execute_client_side_configuration_scripts() { | |
# execute any additional client side configuration scripts we have | |
if [ "${1}" == "config" ] || [ "${1}" == "restore" ]; then | |
for f in ${ETCDIR}/dhclient.d/*.sh ; do | |
if [ -x ${f} ]; then | |
subsystem="${f%.sh}" | |
subsystem="${subsystem##*/}" | |
. ${f} | |
"${subsystem}_${1}" | |
fi | |
done | |
fi | |
} | |
flush_dev() { | |
# Instead of bringing the interface down (#574568) | |
# explicitly clear the ARP cache and flush all addresses & routes. | |
ip -4 addr flush dev ${1} >/dev/null 2>&1 | |
ip -4 route flush dev ${1} >/dev/null 2>&1 | |
ip -4 neigh flush dev ${1} >/dev/null 2>&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} label ${interface}:0 | |
fi | |
if [ -n "${old_ip_address}" ] && | |
[ ! "${old_ip_address}" = "${new_ip_address}" ]; then | |
# IP address changed. Delete all routes, and clear the ARP cache. | |
flush_dev ${interface} | |
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} \ | |
valid_lft ${new_dhcp_lease_time} preferred_lft ${new_dhcp_lease_time} >/dev/null 2>&1 | |
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 dev ${interface} mtu ${new_interface_mtu} | |
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}) | |
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 | |
if [ ${target} = "0" ]; then | |
# 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="" | |
prefix="0" | |
else | |
prefix=${target%%.*} | |
target=${target#*.} | |
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})" | |
fi | |
else | |
prefix=$(class_bits ${target}) | |
fi | |
gateway=${static_routes[$i+1]} | |
# special case 0.0.0.0 to allow static routing for link-local addresses | |
# (including IPv4 multicast) which will not have a next-hop (#769463, #787318) | |
if [ "${gateway}" = "0.0.0.0" ]; then | |
valid_gateway=0 | |
scope='scope link' | |
else | |
is_router_reachable ${gateway} | |
valid_gateway=$? | |
scope='' | |
fi | |
if [ ${valid_gateway} -eq 0 ]; then | |
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 | |
ip -4 route replace ${target}/${prefix} proto static via ${gateway} dev ${interface} ${metric} ${scope} | |
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 | |
else # RENEW||REBIND - only update address lifetimes | |
ip -4 addr change ${new_ip_address}/${new_prefix} broadcast ${new_broadcast_address} dev ${interface} \ | |
valid_lft ${new_dhcp_lease_time} preferred_lft ${new_dhcp_lease_time} >/dev/null 2>&1 | |
fi | |
if [ ! "${new_ip_address}" = "${alias_ip_address}" ] && | |
[ -n "${alias_ip_address}" ]; then | |
# Reset the alias address (fix: this should really only do this on changes) | |
ip -4 addr flush dev ${interface} label ${interface}:0 >/dev/null 2>&1 | |
ip -4 addr add ${alias_ip_address}/${alias_prefix} broadcast ${alias_broadcast_address} dev ${interface} label ${interface}:0 | |
ip -4 route replace ${alias_ip_address}/32 dev ${interface} | |
fi | |
# After dhclient brings an interface UP with a new IP address, subnet mask, | |
# and routes, in the REBOOT/BOUND states -> search for "dhclient-up-hooks". | |
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 | |
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 | |
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 [[ ( "${DHCP_TIME_OFFSET_SETS_TIMEZONE}" = [yY1]* ) && | |
( -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 | |
cp -fp ${tzfile} /etc/localtime | |
touch /etc/localtime | |
fix_context /etc/localtime | |
fi | |
fi | |
execute_client_side_configuration_scripts "config" | |
} | |
# 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 valid_lft ${new_max_life} \ | |
preferred_lft ${new_preferred_life} | |
# 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 | |
tentative=$(ip -6 addr show dev ${interface} tentative \ | |
| grep ${new_ip6_address}/${new_ip6_prefixlen}) | |
# dadfailed flag == address is already in use somewhere else | |
dadfailed=$(ip -6 addr show dev ${interface} dadfailed \ | |
| grep ${new_ip6_address}/${new_ip6_prefixlen}) | |
if [ -n "${dadfailed}" ] ; then | |
#ip -6 addr del ${new_ip6_address}/${new_ip6_prefixlen} dev ${interface} | |
exit_with_hooks 3 | |
fi | |
if [ -z "${tentative}" ] ; then | |
# DAD is over | |
return 0 | |
fi | |
done | |
} | |
dh6config() { | |
if [ -n "${old_ip6_prefix}" ] || | |
[ -n "${new_ip6_prefix}" ]; then | |
echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix} | |
exit_with_hooks 0 | |
fi | |
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 [ -z "${new_ip6_address}" ] || | |
[ -z "${new_ip6_prefixlen}" ]; then | |
exit_with_hooks 2 | |
fi | |
if [ ! "${new_ip6_address}" = "${old_ip6_address}" ]; then | |
add_ipv6_addr_with_DAD | |
else # only update address lifetimes | |
ip -6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \ | |
dev ${interface} scope global valid_lft ${new_max_life} \ | |
preferred_lft ${new_preferred_life} | |
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_client_side_configuration_scripts "config" | |
} | |
# | |
# ### 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="${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|ARPCHECK|ARPSEND) | |
# Do nothing | |
exit_with_hooks 0 | |
;; | |
PREINIT) | |
if [ -n "${alias_ip_address}" ]; then | |
# Flush alias, its routes will disappear too. | |
ip -4 addr flush dev ${interface} label ${interface}:0 >/dev/null 2>&1 | |
fi | |
# upstream dhclient-script removes (ifconfig $interface 0 up) old adresses in PREINIT, | |
# but we sometimes (#125298) need (for iSCSI/nfs root to have a dhcp interface) to keep the existing ip | |
# flush_dev ${interface} | |
ip link set dev ${interface} up | |
if [ -n "${DHCLIENT_DELAY}" ] && [ ${DHCLIENT_DELAY} -gt 0 ]; then | |
# We need to give the kernel some time to get the interface up. | |
sleep ${DHCLIENT_DELAY} | |
fi | |
exit_with_hooks 0 | |
;; | |
PREINIT6) | |
# ensure interface is up | |
ip link set dev ${interface} up | |
# remove any stale addresses from aborted clients | |
ip -6 addr flush dev ${interface} scope global permanent | |
exit_with_hooks 0 | |
;; | |
BOUND|RENEW|REBIND|REBOOT) | |
if [ -z "${interface}" ] || [ -z "${new_ip_address}" ]; then | |
exit_with_hooks 2 | |
fi | |
if arping -D -q -c2 -I ${interface} ${new_ip_address}; then | |
dhconfig | |
exit_with_hooks 0 | |
else | |
# DAD failed, i.e. address is already in use | |
exit_with_hooks 1 | |
fi | |
;; | |
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_client_side_configuration_scripts "restore" | |
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) | |
execute_client_side_configuration_scripts "restore" | |
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 | |
# Flush alias | |
ip -4 addr flush dev ${interface} label ${interface}:0 >/dev/null 2>&1 | |
fi | |
if [ -n "${old_ip_address}" ]; then | |
# Delete addresses/routes/arp cache. | |
flush_dev ${interface} | |
fi | |
if [ -n "${alias_ip_address}" ]; then | |
ip -4 addr add ${alias_ip_address}/${alias_prefix} broadcast ${alias_broadcast_address} dev ${interface} label ${interface}:0 | |
ip -4 route replace ${alias_ip_address}/32 dev ${interface} | |
fi | |
exit_with_hooks 0 | |
;; | |
TIMEOUT) | |
if [ -n "${new_routers}" ]; then | |
if [ -n "${alias_ip_address}" ]; then | |
ip -4 addr flush dev ${interface} label ${interface}:0 >/dev/null 2>&1 | |
fi | |
ip -4 addr add ${new_ip_address}/${new_prefix} \ | |
broadcast ${new_broadcast_address} dev ${interface} \ | |
valid_lft ${new_dhcp_lease_time} preferred_lft ${new_dhcp_lease_time} | |
set ${new_routers} | |
if ping -q -c 1 -w 10 -I ${interface} ${1}; then | |
dhconfig | |
exit_with_hooks 0 | |
fi | |
flush_dev ${interface} | |
exit_with_hooks 1 | |
else | |
exit_with_hooks 1 | |
fi | |
;; | |
*) | |
logmessage "unhandled state: ${reason}" | |
exit_with_hooks 1 | |
;; | |
esac | |
exit_with_hooks 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment