ACC SHELL
Path : /sbin/ |
|
Current File : //sbin/ifup-dhcp |
#! /bin/bash
#
# Copyright (c) 2002 SuSE Linux AG Nuernberg, Germany. All rights reserved.
# 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, write to the Free Software Foundation, Inc., 59 Temple
# Place, Suite 330, Boston, MA 02111-1307 USA
#
# Author: Christian Zoz <zoz@suse.de>, 2002-2006
# Peter Poeml <poeml@suse.de>, 2002-2006
#
unset POSIXLY_CORRECT ; set +o posix # we're using non-posix bash features
usage () {
echo $@
echo "Usage: if{up,down,status}-dhcp [<config>] <interface> [-o <options>]"
echo ""
echo "Options are: boot : we are currently booting"
echo " hotplug : we are handling a hotplug event"
echo " debug : be verbose"
echo " rc : indicates that we are called from rcnetwork"
echo "All other or wrong options are silently ignored."
exit $R_USAGE
}
######################################################################
# change the working direcory and source some common files
#
R_INTERNAL=1 # internal error, e.g. no config or missing scripts
cd /etc/sysconfig/network || exit $R_INTERNAL
test -f ./config && . ./config
test -f scripts/functions && . scripts/functions || exit $R_INTERNAL
test "$DEBUG" = "EXTRA" && . scripts/extradebug
######################################################################
# check arguments and how we are called (in case of links)
#
SCRIPTNAME=${0##*/}
debug "$SCRIPTNAME $*"
case "${SCRIPTNAME}" in
ifup-*) ACTION=start ;;
ifdown-*) ACTION=stop ;;
ifstatus-*) ACTION=status ;;
ifrenew-*) ACTION=renew ;;
*) usage
esac
case "$1" in ""|-h|*help*) usage; esac
CONFIG=$1
shift
if [ -n "$1" -a "$1" != "-o" ] ; then
INTERFACE=$1
else
INTERFACE=$CONFIG
fi
shift
test "$1" = "-o" && shift
OPTIONS="$@"
MODE=manual
while [ $# -gt 0 ]; do
case $1 in
boot|onboot) MODE=onboot ;;
hotplug) MODE=hotplug ;;
quiet) be_quiet_has_gone ;;
debug) DEBUG=yes ;;
rc) RUN_FROM_RC=yes ;;
*) debug unknown option $1 ;;
esac
shift
done
######################################################################
# check presence of configuration files
#
test -f ./dhcp && . ./dhcp
test -f ./ifcfg-$CONFIG && . ./ifcfg-$CONFIG
######################################################################
# get the interface and check if it is up
#
if [ -z "$INTERFACE" ] ; then
usage "No interface given"
fi
if ! is_iface_available $INTERFACE ; then
# When a hotplug remove event occurs the interface has already gone.
# Nevertheless we have to clean up.
if [ \( "$ACTION" != stop -o "$MODE" != hotplug \) -a "$INTERFACE" != all ] ; then
logerror "interface ${INTERFACE} is not available"
exit $R_NODEV
fi
fi
######################################################################
# Normalize & resolve & cleanup the bootproto value from config
# Note:
# INTERFACE=all is a special case used by rcnetwork stop/ifdown
# to kill all dhcp clients that may still run on some interface
#
explicit_dhcp4=no
explicit_dhcp6=no
BOOTPROTO=$(echo "$BOOTPROTO" | awk '{print tolower($0);}')
# Override with iSCSI Boot Firmware Table (feature 308283, bnc 542225)
if [ "$INTERFACE" != "all" -a "${BOOTPROTO}" = "ibft" ] ; then
IBFT=yes # not used at the moment... remember before override
eval BOOTPROTO=none `parse_ifname_ibft_settings "$INTERFACE"`
fi
BOOTPROTOS=()
AUTOIP=no
add_bootproto_once() {
local b p
for b in $@ ; do
for p in ${BOOTPROTOS[@]} ; do
test "$p" = "$b" && continue 2
done
BOOTPROTOS=(${BOOTPROTOS[@]} ${b})
done
}
for bp in ${BOOTPROTO//+/ } ; do
case "$bp" in
(dhcp) add_bootproto_once dhcp4 dhcp6 ;;
(dhcp4)
explicit_dhcp4=yes
add_bootproto_once ${bp}
;;
(dhcp6)
explicit_dhcp6=yes
add_bootproto_once ${bp}
;;
# FIXME: dhcpcd has a builtin autoip support...
# at the moment we handle autoip in ifup;
# it needs a "quiet minute" to change it.
#(autoip) AUTOIP=yes ;;
(*) continue ;;
esac
done
if [ "$INTERFACE" != all ] ; then
# Read temporary startmode and handle it
# [kill -9 on stop, use dhcpcd -p flag on start]
tmp_startmode=`read_cached_config_data startmode $INTERFACE`
[ -n "$tmp_startmode" ] && STARTMODE="$tmp_startmode"
fi
######################################################################
# determine type of dhcp client
#
# This script is supposed to work with both dhcpcd and the ISC DHCP client,
# because there's a lot of common stuff.
# If neccesary you can preselect a dhcp client; just set DHCLIENT_BIN in
# one of the used config files. If not we prefer dhcpcd if available.
: ${DHCLIENT_BIN:=dhcpcd}
: ${DHCLIENT6_BIN:=dhcp6c}
DHCLIENT=""
for x in "$DHCLIENT_BIN" \
"/sbin/${DHCLIENT_BIN##*/}" \
"/sbin/dhcpcd" "/sbin/dhclient" ;
do
if [ "x$x" != x -a "${x##/*}" != "$x" -a -x "$x" ] ; then
DHCLIENT_BIN="$x"
DHCLIENT=${DHCLIENT_BIN##*/}
break
fi
done
DHCLIENT6=""
for x in "$DHCLIENT6_BIN" \
"/sbin/${DHCLIENT6_BIN##*/}" \
"/sbin/dhcp6c" "/sbin/dhclient6" ;
do
if [ "x$x" != x -a "${x##/*}" != "$x" -a -x "$x" ] ; then
DHCLIENT6_BIN="$x"
DHCLIENT6=${DHCLIENT6_BIN##*/}
break
fi
done
print_mesg() {
func=$1 ; shift
if [ "$RUN_FROM_RC" = yes -a "$INTERFACE" != all ] ; then
$func "`printf " %-9s $*" $INTERFACE`"
else
$func "$*"
fi
}
# check installation of supported dhcp clients
case "$ACTION" in
stop)
;;
*)
HAVE_IPv6=yes
if test -d /proc/sys/net/ipv6 ; then
val1=`cat "/proc/sys/net/ipv6/conf/$INTERFACE/disable_ipv6" 2>/dev/null`
val2=`cat "/proc/sys/net/ipv6/conf/all/disable_ipv6" 2>/dev/null`
test "x$val1" = x1 -o "x$val2" = x1 && HAVE_IPv6=no
else
HAVE_IPv6=no
fi
clients=0
bootprotos=(${BOOTPROTOS[@]})
BOOTPROTOS=()
# complain about missed clients
for BOOTPROTO in ${bootprotos[@]} ; do
case "$BOOTPROTO" in
(dhcp4)
case "$DHCLIENT" in
(dhcpcd|dhclient)
if [ -x "$DHCLIENT_BIN" ] ; then
clients=$((clients + 1))
BOOTPROTOS=(${BOOTPROTOS[@]} $BOOTPROTO)
else
# Huh?!
DHCLIENT=""
print_mesg err_mesg \
"DHCP4 client ($DHCLIENT_BIN) is not available."
print_mesg err_mesg \
" Please install 'dhcpcd' or 'dhcp-client'"
fi
;;
"")
if [ "x$explicit_dhcp4" = "xyes" ] ; then
print_mesg err_mesg "DHCP4 client is not available."
print_mesg err_mesg " Please install 'dhcpcd' or 'dhcp-client'"
fi
;;
*)
DHCLIENT=""
print_mesg err_mesg "DHCP4 client unknown/unsupported: $DHCLIENT_BIN"
print_mesg err_mesg " Please install 'dhcpcd' or 'dhcp-client'"
;;
esac
;;
(dhcp6)
[ "x$HAVE_IPv6" = xyes ] || DHCLIENT6=""
case "$DHCLIENT6" in
(dhcp6c|dhclient6)
if [ -x "$DHCLIENT6_BIN" ] ; then
clients=$((clients + 1))
BOOTPROTOS=(${BOOTPROTOS[@]} $BOOTPROTO)
else
# Huh?!
DHCLIENT6=""
print_mesg err_mesg \
"DHCP6 client ($DHCLIENT6_BIN) is not available."
print_mesg err_mesg \
" Please install the 'dhcpv6' or 'dhcp-client' package"
fi
;;
"")
if [ "x$explicit_dhcp6" = "xyes" ] ; then
if [ "x$HAVE_IPv6" = xyes ] ; then
print_mesg err_mesg "DHCP6 client is not available."
print_mesg err_mesg " Please install 'dhcpv6' or 'dhcp-client' package'"
else
print_mesg err_mesg "DHCP6 disabled - no IPv6 support"
fi
fi
;;
*)
DHCLIENT6=""
print_mesg err_mesg "DHCP6 client unknown/unsupported: $DHCLIENT6_BIN"
print_mesg err_mesg " Please install the 'dhcpv6' or 'dhcp-client' package"
;;
esac
;;
esac
done
# exit when not even one of the requested clients is installed
# or the a client was explicitely requested in bootproto
[ "x$HAVE_IPv6" = xyes ] && \
[ "x$explicit_dhcp6" = "xyes" -a "x$DHCLIENT6" = x ] && exit $R_ERROR
[ "x$explicit_dhcp4" = "xyes" -a "x$DHCLIENT" = x ] && exit $R_ERROR
[ $clients -eq 0 ] && exit $R_ERROR
;;
esac
start_dhcp4_dhcpcd() {
#
# Using netconfig, we can request all options and
# netconfig takes care to apply them properlly...
#
args="--netconfig -L"
#test "$AUTOIP" != "yes" && args="$args -L"
test "$DHCLIENT_USE_LAST_LEASE" = "yes" && args="$args -E"
test "$DHCLIENT_DEBUG" = "yes" && args="$args -d"
test "$DHCLIENT_SET_HOSTNAME" = "yes" && args="$args -HHH"
test "$DHCLIENT_SET_DEFAULT_ROUTE" != "yes" && args="$args -G"
# send hostname for DDNS?
case "$DHCLIENT_HOSTNAME_OPTION" in
AUTO|auto)
unset DHCLIENT_HOSTNAME_OPTION
test -s /etc/HOSTNAME && read -t 1 FQHOSTNAME < /etc/HOSTNAME
FQHOSTNAME=${FQHOSTNAME%%.*} # strip domain
FQHOSTNAME=${FQHOSTNAME%% *} # must not contain spaces, just in case
DHCLIENT_HOSTNAME_OPTION="$FQHOSTNAME"
;;
esac
# hardcoded in the dhcpcd binary when --netconfig is in use, but ...
args="$args -c /etc/sysconfig/network/scripts/dhcpcd-hook"
# avoid deconfiguration of the interface at startup in nfsroot case (bnc#397484)
test "$STARTMODE" = "nfsroot" && args="-p $args"
DHCLIENT_ARGS="$args"
# just in case /var is not mounted
test -d /var/lib/dhcpcd || mkdir -p /var/lib/dhcpcd && \
touch /var/lib/dhcpcd/dhcpcd-$INTERFACE.timestamp || return 1
# collect args that may contain spaces and write debug...
args="$args${DHCLIENT_TIMEOUT:+ -t \"$DHCLIENT_TIMEOUT\"}"
args="$args${DHCLIENT_CLIENT_ID:+ -I \"$DHCLIENT_CLIENT_ID\"}"
args="$args${DHCLIENT_VENDOR_CLASS_ID:+ -i \"$DHCLIENT_VENDOR_CLASS_ID\"}"
args="$args${DHCLIENT_LEASE_TIME:+ -l \"$DHCLIENT_LEASE_TIME\"}"
args="$args${DHCLIENT_HOSTNAME_OPTION:+ -h \"$DHCLIENT_HOSTNAME_OPTION\"}"
debug "Starting dhcp client: $DHCLIENT_BIN $DHCPCD_USER_OPTIONS $args $INTERFACE"
# now start dhcpcd
$DHCLIENT_BIN $DHCPCD_USER_OPTIONS $DHCLIENT_ARGS \
${DHCLIENT_TIMEOUT:+-t "$DHCLIENT_TIMEOUT"} \
${DHCLIENT_CLIENT_ID:+-I "$DHCLIENT_CLIENT_ID"} \
${DHCLIENT_VENDOR_CLASS_ID:+-i "$DHCLIENT_VENDOR_CLASS_ID"} \
${DHCLIENT_LEASE_TIME:+-l "$DHCLIENT_LEASE_TIME"} \
${DHCLIENT_HOSTNAME_OPTION:+-h "$DHCLIENT_HOSTNAME_OPTION"} \
$INTERFACE </dev/null &>/dev/null &
}
start_dhcp4_dhclient() {
#
# TODO: filter out statements (e.g. inerface blocks),
# apply DHCLIENT_* variables
#
local DHCPIFLEASE="/var/lib/dhcp/dhclient.${INTERFACE}.lease"
local DHCPIFCONF="/var/lib/dhcp/dhclient.${INTERFACE}.conf"
local DHCPIFPID="/var/run/dhclient.${INTERFACE}.pid"
# don't write copyright info
local args="-q"
test "$DHCLIENT_DEBUG" = "yes" && args=""
# send hostname for DDNS?
case "$DHCLIENT_HOSTNAME_OPTION" in
AUTO|auto)
unset DHCLIENT_HOSTNAME_OPTION
test -s /etc/HOSTNAME && read -t 1 FQHOSTNAME < /etc/HOSTNAME
FQHOSTNAME=${FQHOSTNAME%%.*} # strip domain
FQHOSTNAME=${FQHOSTNAME%% *} # must not contain spaces, just in case
DHCLIENT_HOSTNAME_OPTION="$FQHOSTNAME"
;;
esac
test -n "$DHCLIENT_HOSTNAME_OPTION" && args="$args -H $DHCLIENT_HOSTNAME_OPTION"
rm -f "$DHCPIFCONF" && awk '
/#/ { sub("#.*", ""); }
/^[ \t]*$/ { next; }
{ print $0; }
' < /etc/dhclient.conf > "$DHCPIFCONF" || return 1
debug "Starting dhcp client: $DHCLIENT_BIN $DHCLIENT_USER_OPTIONS -cf "$DHCPIFCONF" -lf "$DHCPIFLEASE" -pf "$DHCPIFPID" $args $INTERFACE"
$DHCLIENT_BIN $DHCLIENT_USER_OPTIONS -cf "$DHCPIFCONF" -lf "$DHCPIFLEASE" -pf "$DHCPIFPID" $args $INTERFACE </dev/null &>/dev/null &
}
start_dhcp6_dhcp6c() {
DHCP6IFCONF="/var/lib/dhcpv6/dhcp6c.${INTERFACE}.conf"
DHCP6IFPID="/var/run/dhcp6c.${INTERFACE}.pid"
args="--netconfig"
test "$DHCLIENT_DEBUG" = "yes" && \
args="$args -v"
args="${args} -c ${DHCP6IFCONF}"
args="${args} -p ${DHCP6IFPID}"
# TODO: more features on the todo list ...
# TODO: pid file handling ...
rm -f "$DHCP6IFCONF" && {
echo "# dhcp6c config generated by ifup-dhcp"
echo "interface $INTERFACE {"
echo " request domain-name-servers;"
echo " request domain-search-list;"
echo "};"
} > "$DHCP6IFCONF" || return 1
debug "Starting dhcp client: $DHCLIENT6_BIN $DHCP6C_USER_OPTIONS $args $INTERFACE"
$DHCLIENT6_BIN $DHCP6C_USER_OPTIONS $args $INTERFACE </dev/null &>/dev/null &
}
start_dhcp6_dhclient() {
#
# TODO: filter out statements (e.g. inerface blocks),
# apply DHCLIENT6_* variables
#
local DHCP6IFLEASE="/var/lib/dhcp6/dhclient6.${INTERFACE}.lease"
local DHCP6IFCONF="/var/lib/dhcp6/dhclient6.${INTERFACE}.conf"
local DHCP6IFPID="/var/run/dhclient6.${INTERFACE}.pid"
# don't write copyright info
local args="-q"
test "$DHCLIENT6_DEBUG" = "yes" && args=""
# send hostname for DDNS?
case "$DHCLIENT6_HOSTNAME_OPTION" in
AUTO|auto)
unset DHCLIENT6_HOSTNAME_OPTION
test -s /etc/HOSTNAME && read -t 1 FQHOSTNAME < /etc/HOSTNAME
FQHOSTNAME=${FQHOSTNAME%%.*} # strip domain
FQHOSTNAME=${FQHOSTNAME%% *} # must not contain spaces, just in case
DHCLIENT6_HOSTNAME_OPTION="$FQHOSTNAME"
;;
esac
test -n "$DHCLIENT6_HOSTNAME_OPTION" && args="$args -H $DHCLIENT6_HOSTNAME_OPTION"
rm -f "$DHCP6IFCONF" && awk '
/#/ { sub("#.*", ""); }
/^[ \t]*$/ { next; }
{ print $0; }
' < /etc/dhclient6.conf > "$DHCP6IFCONF" || return 1
debug "Starting dhcp client: $DHCLIENT6_BIN -6 $DHCLIENT6_USER_OPTIONS -cf "$DHCP6IFCONF" -lf "$DHCP6IFLEASE" -pf "$DHCP6IFPID" $args $INTERFACE"
$DHCLIENT6_BIN -6 $DHCLIENT6_USER_OPTIONS -cf "$DHCP6IFCONF" -lf "$DHCP6IFLEASE" -pf "$DHCP6IFPID" $args $INTERFACE </dev/null &>/dev/null &
}
case "$ACTION" in
start|renew)
# if we were called at boot time, increase the time startproc waits,
# because the next scripts might rely on a configured network
# test "$MODE" = "boot" && STARTPROC_TIMEOUT=5
# a previous dhcpcd daemon could have been killed leaving its pidfile,
# and we need to remove it before we can start a new one.
case "$DHCLIENT" in
(dhcpcd)
if [ -s /var/run/dhcpcd-$INTERFACE.pid ]; then
p=$(</var/run/dhcpcd-$INTERFACE.pid)
if [ "x$p" != x -a $((p)) -gt 0 ] ; then
cmdline="/proc/$p/cmdline"
[ -r "$cmdline" ] && \
grep -q "^$DHCLIENT_BIN" "$cmdline" || {
message_if_not_run_from_rc \
"Removing stale pid file /var/run/dhcpcd-$INTERFACE.pid"
rm -f /var/run/dhcpcd-$INTERFACE.pid
}
fi
fi
;;
dhclient)
if [ -s /var/run/dhclient.$INTERFACE.pid ]; then
p=$(</var/run/dhclient.$INTERFACE.pid)
if [ "x$p" != x -a $((p)) -gt 0 ] ; then
cmdline="/proc/$p/cmdline"
[ -r "$cmdline" ] && \
grep -q "^$DHCLIENT_BIN" "$cmdline" || {
message_if_not_run_from_rc \
"Removing stale pid file /var/run/dhclient.$INTERFACE.pid"
rm -f /var/run/dhclient.$INTERFACE.pid
}
fi
fi
;;
esac
case "$DHCLIENT6" in
(dhcp6c)
: # TODO: the new 1.0.20 version seems to write one...
;;
(dhclient6)
if [ -s /var/run/dhclient6.$INTERFACE.pid ]; then
p=$(</var/run/dhclient6.$INTERFACE.pid)
if [ "x$p" != x -a $((p)) -gt 0 ] ; then
cmdline="/proc/$p/cmdline"
[ -r "$cmdline" ] && \
grep -q "^$DHCLIENT6_BIN" "$cmdline" || {
message_if_not_run_from_rc \
"Removing stale pid file /var/run/dhclient6.$INTERFACE.pid"
rm -f /var/run/dhclient6.$INTERFACE.pid
}
fi
fi
;;
esac
# the following code block, is only relevant if DHCLIENT_PRIMARY_DEVICE is
# empty. it basically sets DHCLIENT_PRIMARY_DEVICE based on the informationen
# that is provided by the cached config data in a way that a user-defined
# DHCLIENT_PRIMARY_DEVICE remains untouched.
if [ -z "$DHCLIENT_PRIMARY_DEVICE" ]; then
# read cached config data into PRIMARY_FROM_CACHE
PRIMARY_FROM_CACHE="`grep_cached_config_data primary yes`"
if [ -z "$PRIMARY_FROM_CACHE" ]; then
# no primary interface up-> we're the primary interface
DHCLIENT_PRIMARY_DEVICE='yes'
# save this fact to cached config data
write_cached_config_data primary yes $INTERFACE
commit_cached_config_data $INTERFACE
else
# primary interface already up -> DHCLIENT_PRIMARY_DEVICE='no'
if [ "${PRIMARY_FROM_CACHE% }" = $INTERFACE ]; then
# special case for ifrenew:
# we are the primary interface which is up
DHCLIENT_PRIMARY_DEVICE='yes'
else
DHCLIENT_PRIMARY_DEVICE='no'
fi
fi
fi
DHCP4_STATUS=$R_NOTCONFIGURED
DHCP6_STATUS=$R_NOTCONFIGURED
DHCP4_STARTED="no"
DHCP6_STARTED="no"
case "$ACTION" in
(start)
for BOOTPROTO in ${BOOTPROTOS[@]} ; do
case "$BOOTPROTO" in
(dhcp4)
# reset dhcp4 status
DHCP4_STATUS=""
#if ( checkproc $DHCLIENT_BIN || [ "$DHCLIENT_PRIMARY_DEVICE" = no ] ) ; then
# let's first test if the running dhcpcd actually runs on this
# interface, because then we don't want to start another one:
if dhcpc4_on_iface -q; then
DHCP4_STATUS=$R_DHCP_BG
if test "$RUN_FROM_RC" = yes; then
print_mesg mesg "DHCP4 client is already running"
else
mesg "DHCP4 client is already running on $INTERFACE"
fi
while read a b c d e f g h i; do
case "$d" in
169.254.*) continue ;;
esac
print_mesg mesg "IP address: $d"
DHCP4_STATUS=$R_SUCCESS
done < <(ip -o -4 addr show $INTERFACE)
fi
#fi
;;
(dhcp6)
# reset dhcp6 status
DHCP6_STATUS=""
#if ( checkproc $DHCLIENT6_BIN || [ "$DHCLIENT_PRIMARY_DEVICE" = no ] ) ; then
# let's first test if the running dhcp6c actually runs on this
# interface, because then we don't want to start another one:
if dhcpc6_on_iface -q; then
DHCP6_STATUS=$R_DHCP_BG
if test "$RUN_FROM_RC" = yes; then
print_mesg mesg "DHCP6 client is already running"
else
mesg "DHCP6 client is already running on $INTERFACE"
fi
while read a b c d rest; do
case "$d" in
fe80::*) continue ;;
esac
print_mesg mesg "IP address: $d"
DHCP6_STATUS=$R_SUCCESS
done < <(ip -o -6 addr show $INTERFACE)
fi
#fi
;;
esac
done
;;
(renew)
for BOOTPROTO in ${BOOTPROTOS[@]} ; do
case "$BOOTPROTO" in
(dhcp4)
# reset dhcp4 status
DHCP4_STATUS=""
case "$DHCLIENT" in
(dhcpcd|dhclient)
$DHCLIENT_BIN -x $INTERFACE
;;
esac
for i in `dhcpc4_on_iface`; do
kill -TERM $i &>/dev/null
done
sleep 1
;;
(dhcp6)
# reset dhcp6 status
DHCP6_STATUS=""
case "$DHCLIENT6" in
(dhclient6)
$DHCLIENT6_BIN -6 -x $INTERFACE
;;
esac
for i in `dhcpc6_on_iface`; do
kill -TERM $i &>/dev/null
done
sleep 1
;;
esac
done
;;
esac
# start requested dhcp clients...
if [ -z "$DHCP4_STATUS" -o -z "$DHCP6_STATUS" ] ; then
# there is maybe already a dhcp client running (or scheduled). We probably
# don't want to set another default gateway and so on. Let's clear some
# variables and source the ifcfg-$CONFIG again -- unless
# DHCLIENT_PRIMARY_DEVICE is set to "yes".
if [ "$DHCLIENT_PRIMARY_DEVICE" != yes ]; then
unset DHCLIENT_SET_HOSTNAME \
DHCLIENT_SET_DEFAULT_ROUTE
test -f ./ifcfg-$CONFIG && . ./ifcfg-$CONFIG
fi
# remember the hostname to handle a change later
write_cached_config_data hostname "`hostname 2>/dev/null`" $INTERFACE
commit_cached_config_data $INTERFACE
debug "Activating interface $INTERFACE"
if ! is_iface_up $INTERFACE ; then
ip link set $INTERFACE up ${MTU:+mtu $MTU} \
${LLADDR:+address $LLADDR} $LINK_OPTIONS
# wait a bit or dhclient(6) may produce false send errors
link_ready_wait "$INTERFACE" 3
# (optionally) wait until a device is really configured
sleep ${DHCLIENT_SLEEP:-0}
fi
MESSAGE=""
for BOOTPROTO in ${BOOTPROTOS[@]} ; do
case "$BOOTPROTO" in
(dhcp4) test -n "$DHCP4_STATUS" || MESSAGE="$MESSAGE $BOOTPROTO" ;;
(dhcp6) test -n "$DHCP6_STATUS" || MESSAGE="$MESSAGE $BOOTPROTO" ;;
esac
done
MESSAGE=$(echo ${MESSAGE} | awk '{print toupper($0);}')
if [ "$RUN_FROM_RC" = "yes" ]; then
print_mesg mesg_n "Starting ${MESSAGE// /+} client"
else
mesg_n "Starting ${MESSAGE// /+} client on $INTERFACE"
fi
for BOOTPROTO in ${BOOTPROTOS[@]} ; do
case "$BOOTPROTO" in
(dhcp4)
case "$DHCLIENT" in
(dhcpcd)
test -n "$DHCP4_STATUS" || {
start_dhcp4_dhcpcd && {
DHCP4_STARTED="yes"
write_cached_config_data dhcp4_client $DHCLIENT $INTERFACE
write_cached_config_data dhcp4_state started $INTERFACE
commit_cached_config_data $INTERFACE
} || DHCP4_STATUS=$?
}
;;
(dhclient)
test -n "$DHCP4_STATUS" || {
start_dhcp4_dhclient && {
DHCP4_STARTED="yes"
write_cached_config_data dhcp4_client $DHCLIENT $INTERFACE
write_cached_config_data dhcp4_state started $INTERFACE
commit_cached_config_data $INTERFACE
} || DHCP4_STATUS=$?
}
;;
esac
;;
(dhcp6)
case "$DHCLIENT6" in
(dhcp6c)
test -n "$DHCP6_STATUS" || {
start_dhcp6_dhcp6c && {
DHCP6_STARTED="yes"
write_cached_config_data dhcp6_client $DHCLIENT $INTERFACE
write_cached_config_data dhcp6_state started $INTERFACE
commit_cached_config_data $INTERFACE
} || DHCP6_STATUS=$?
}
;;
(dhclient6)
test -n "$DHCP6_STATUS" || {
start_dhcp6_dhclient && {
DHCP6_STARTED="yes"
write_cached_config_data dhcp6_client $DHCLIENT $INTERFACE
write_cached_config_data dhcp6_state started $INTERFACE
commit_cached_config_data $INTERFACE
} || DHCP6_STATUS=$?
}
;;
esac
;;
esac
done
#
# in case we've started at least one client, wait the specified
# time until the dhcp client has done its job and show the results.
#
DHCP4_MESSAGE=''
DHCP6_MESSAGE=''
typeset -i wusleep=100000
typeset -i wab_max=${DHCLIENT_WAIT_AT_BOOT:-15};
let wab_max\*=10
for ((wab_cnt=0; wab_cnt<=wab_max; wab_cnt++)); do
for BOOTPROTO in ${BOOTPROTOS[@]} ; do
case "$BOOTPROTO" in
(dhcp4)
if ! dhcpc4_on_iface -q ; then
((wab_cnt== 0 || wab_cnt==10)) && message_n .\ .\
DHCP4_MESSAGE="DHCP4 client NOT running"
DHCP4_STATUS=$R_NOTRUNNING
continue
fi
[ -n "$DHCP4_STATUS" ] && continue
case "$DHCLIENT" in
(dhcpcd)
stamp=/var/lib/dhcpcd/dhcpcd-$INTERFACE.timestamp
info=/var/lib/dhcpcd/dhcpcd-$INTERFACE.info
state=`read_cached_config_data dhcp4_state $INTERFACE`
if [ "x$state" = "xcomplete" -a -e $info -a ! $info -ot $stamp ]; then
DHCP4_STATUS=$R_SUCCESS
IP='' ; NM='' ; HN=''
while read line ; do
case "$line" in
IPADDR=*) eval "${line/IPADDR=/IP=}" ;;
NETMASK=*) eval "${line/NETMASK=/NM=}" ;;
HOSTNAME=*) eval "${line/HOSTNAME=/HN=}" ;;
esac
done < $info
if test -n "$IP" ; then
DHCP4_MESSAGE="IP address: $IP"
NL=$(mask2pfxlen $NM)
if test -n "$NM" ; then
DHCP4_MESSAGE="$DHCP4_MESSAGE/$NL"
fi
if test -n "$HN" ; then
DHCP4_MESSAGE="$DHCP4_MESSAGE ($HN)"
fi
fi
fi
;;
(dhclient)
lease="/var/lib/dhcp/dhclient.${INTERFACE}.lease"
config="/var/lib/dhcp/dhclient.${INTERFACE}.conf"
state=`read_cached_config_data dhcp4_state $INTERFACE`
if [ "x$state" = "xcomplete" -a -e "$lease" -a "$lease" -nt "$config" ] ; then
DHCP4_STATUS=$R_SUCCESS
while read a b c d e f g h i ; do
case "$d" in
169.254.*) continue ;;
esac
if grep -q "${d%/*}" "$lease" &>/dev/null ; then
DHCP4_MESSAGE="IP address: $d"
fi
done < <(ip -o -4 addr show $INTERFACE)
fi
;;
esac
;;
(dhcp6)
if ! dhcpc6_on_iface -q ; then
((wab_cnt== 0 || wab_cnt==10)) && message_n .\ .\
DHCP6_MESSAGE="DHCP6 client NOT running"
DHCP6_STATUS=$R_NOTRUNNING
continue
fi
[ -n "$DHCP6_STATUS" ] && continue
case "$DHCLIENT6" in
(dhcp6c)
while read a b c d rest; do
config="/var/lib/dhcpv6/dhcp6c.${INTERFACE}.conf"
leases="/var/lib/dhcpv6/client6.leases*"
leases=$(grep -sl "^lease[ \t]\+${d}" $leases 2>/dev/null)
for lease in ${leases} ; do
if [ "$lease" -nt "$config" ] ; then
DHCP6_MESSAGE="IP address: $d"
DHCP6_STATUS=$R_SUCCESS
break 2
fi
done
done < <(ip -o -6 addr show $INTERFACE)
;;
(dhclient6)
lease="/var/lib/dhcp6/dhclient6.${INTERFACE}.lease"
config="/var/lib/dhcp6/dhclient6.${INTERFACE}.conf"
state=`read_cached_config_data dhcp6_state $INTERFACE`
if [ "x$state" = "xcomplete" ] ; then
DHCP6_STATUS=$R_SUCCESS
while read a b c d e f g h i ; do
case "$d" in
fe80:*) continue ;;
esac
if grep -q "${d%/*}" "$lease" &>/dev/null ; then
DHCP6_MESSAGE="IP address: $d"
fi
done < <(ip -o -6 addr show $INTERFACE)
fi
;;
esac
;;
esac
done
if [ -z "$DHCP4_STATUS" -o -z "$DHCP6_STATUS" ] ; then
((wab_cnt % 20 == 1)) && message_n .\
usleep $wusleep
else
# ok, we have status from both clients now => done
break
fi
done
message " "
[ "$DHCP4_STARTED" = yes -a -z "$DHCP4_STATUS" ] && DHCP4_STATUS=$R_DHCP_BG
[ "$DHCP6_STARTED" = yes -a -z "$DHCP6_STATUS" ] && DHCP6_STATUS=$R_DHCP_BG
if test -n "$DHCP4_MESSAGE" ; then
message "`printf " %-9s $DHCP4_MESSAGE" $INTERFACE`"
elif [ $DHCP4_STATUS = $R_DHCP_BG ] ; then
message "`printf " %-9s DHCP4 continues in background" $INTERFACE`"
fi
if test -n "$DHCP6_MESSAGE" ; then
message "`printf " %-9s $DHCP6_MESSAGE" $INTERFACE`"
elif [ $DHCP6_STATUS = $R_DHCP_BG ] ; then
message "`printf " %-9s DHCP6 continues in background" $INTERFACE`"
fi
fi
debug "DHCP4(required=$explicit_dhcp4) STARTED=$DHCP4_STARTED STATUS=$DHCP4_STATUS"
debug "DHCP6(required=$explicit_dhcp6) STARTED=$DHCP6_STARTED STATUS=$DHCP6_STATUS"
[ -z "$DHCP4_STATUS" ] && DHCP4_STATUS=$R_ERROR
[ -z "$DHCP6_STATUS" ] && DHCP6_STATUS=$R_ERROR
case "${explicit_dhcp4}_${explicit_dhcp6}" in
(yes_yes) # BOOTPROTO=dhcp4+dhcp6 (need both to report success)
if [ $DHCP4_STATUS = $R_SUCCESS -a $DHCP6_STATUS = $R_SUCCESS ] ; then
exit $R_SUCCESS
elif [ $DHCP4_STATUS = $R_DHCP_BG -o $DHCP6_STATUS = $R_DHCP_BG ] ; then
exit $R_DHCP_BG
elif [ $DHCP4_STATUS != $R_NOTCONFIGURED ] ; then
exit $DHCP4_STATUS
elif [ $DHCP6_STATUS != $R_NOTCONFIGURED ] ; then
exit $DHCP6_STATUS
fi
;;
(no_no) # BOOTPROTO=dhcp (one is sufficient)
if [ $DHCP4_STATUS = $R_SUCCESS -o $DHCP6_STATUS = $R_SUCCESS ] ; then
exit $R_SUCCESS
elif [ $DHCP4_STATUS = $R_DHCP_BG -o $DHCP6_STATUS = $R_DHCP_BG ] ; then
exit $R_DHCP_BG
elif [ $DHCP4_STATUS != $R_NOTCONFIGURED ] ; then
exit $DHCP4_STATUS
elif [ $DHCP6_STATUS != $R_NOTCONFIGURED ] ; then
exit $DHCP6_STATUS
fi
;;
(yes_no) # BOOTPROTO=dhcp4
exit $DHCP4_STATUS
;;
(no_yes) # BOOTPROTO=dhcp6
exit $DHCP6_STATUS
;;
esac
exit $R_ERROR
;;
stop)
ALL_INTERFACES=()
STOPPED_IFACES=()
if [ "$INTERFACE" != all ]; then
ALL_INTERFACES=($INTERFACE)
dhcpc4_pids=""
dhcpc6_pids=""
dhcpc4_signal="-TERM"
dhcpc6_signal="-TERM"
debug "Shutting down dhcp clients on $INTERFACE"
# first try the configured way
for BOOTPROTO in ${BOOTPROTOS[@]} ; do
case "$BOOTPROTO" in
(dhcp4)
dhcpc4_pids="`dhcpc4_on_iface`"
case $DHCLIENT in
(dhcpcd)
DHCPIFLEASE="/var/lib/dhcpcd/dhcpcd-$INTERFACE.info"
DHCPIFPID="/var/run/dhcpcd-$INTERFACE.pid"
if test "$STARTMODE" = "nfsroot" ;
then
dhcpc4_signal="-KILL"
elif test "$DHCLIENT_RELEASE_BEFORE_QUIT" = "yes" ;
then
$DHCLIENT_BIN --release \
$INTERFACE </dev/null &>/dev/null
else
$DHCLIENT_BIN --exit \
$INTERFACE </dev/null &>/dev/null
fi
;;
(dhclient)
DHCPIFLEASE="/var/lib/dhcp/dhclient.${INTERFACE}.lease"
DHCPIFPID="/var/run/dhclient.${INTERFACE}.pid"
if test "$STARTMODE" = "nfsroot" ;
then
dhcpc4_signal="-KILL"
elif test "$DHCLIENT_RELEASE_BEFORE_QUIT" = "yes" ;
then
$DHCLIENT_BIN -r \
-cf /dev/null \
-lf "$DHCPIFLEASE" \
-pf "$DHCPIFPID" \
$INTERFACE </dev/null &>/dev/null
else
$DHCLIENT_BIN -x \
$INTERFACE </dev/null &>/dev/null
fi
;;
esac
;;
(dhcp6)
dhcpc6_pids="`dhcpc6_on_iface`"
case $DHCLIENT6 in
(dhcp6c)
DHCP6IFCONF="/var/lib/dhcpv6/dhcp6c.${INTERFACE}.conf"
DHCP6IFPID="/var/run/dhcp6c.${INTERFACE}.pid"
if test "$STARTMODE" = "nfsroot" ;
then
dhcpc6_signal="-KILL"
elif test "$DHCLIENT6_RELEASE_BEFORE_QUIT" = "yes" ;
then
# dhcp6c daemon needs to get killed or
# dhcp6c -r fails to bind the interface
for i in $dhcpc6_pids; do
kill $dhcpc6_signal $i &>/dev/null
done
for i in $dhcpc6_pids; do
for ((wait=0; wait<=20; wait++)); do
if test -d /proc/$i ; then
usleep 300000
else
continue 2
fi
done
done
# then release the lease but stay in foreground
$DHCLIENT6_BIN -f -r all \
-c /dev/null \
-p "$DHCP6IFPID" \
$INTERFACE </dev/null &>/dev/null
fi
;;
(dhclient6)
DHCP6IFLEASE="/var/lib/dhcp6/dhclient6.${INTERFACE}.lease"
DHCP6IFPID="/var/run/dhclient6.${INTERFACE}.pid"
if test "$STARTMODE" = "nfsroot" ;
then
dhcpc6_signal="-KILL"
elif test "$DHCLIENT6_RELEASE_BEFORE_QUIT" = "yes" ;
then
$DHCLIENT6_BIN -6 -r \
-cf /dev/null \
-lf "$DHCP6IFLEASE" \
-pf "$DHCP6IFPID" \
$INTERFACE </dev/null &>/dev/null
else
$DHCLIENT6_BIN -6 -x \
$INTERFACE </dev/null &>/dev/null
fi
;;
esac
;;
esac
done
# same game again...
for BOOTPROTO in ${BOOTPROTOS[@]} ; do
case "$BOOTPROTO" in
(dhcp4)
# send termination signal
for i in $dhcpc4_pids; do
kill $dhcpc4_signal $i &>/dev/null
done
# wait until the processes are gone
for i in $dhcpc4_pids; do
for ((wait=0; wait<=20; wait++)); do
if test -d /proc/$i ; then
usleep 300000
else
continue 2
fi
if [ $wait -eq 20 ]; then
debug "process $i still not dead, sending SIGKILL"
kill -KILL $i &>/dev/null
fi
done
done
# remove old lease file and pid when they still exist
if test "$DHCLIENT_RELEASE_BEFORE_QUIT" = "yes" ; then
rm -f "$DHCPIFLEASE"
fi
rm -f "$DHCPIFPID"
;;
(dhcp6)
# send termination signal
for i in $dhcpc6_pids; do
kill $dhcpc6_signal $i &>/dev/null
done
# wait until the processes are gone
for i in $dhcpc6_pids; do
for ((wait=0; wait<=20; wait++)); do
if test -d /proc/$i ; then
usleep 300000
else
continue 2
fi
if [ $wait -eq 20 ]; then
debug "process $i still not dead, sending SIGKILL"
kill -KILL $i &>/dev/null
fi
done
done
# remove old lease file and pid when they still exist
if test "$DHCLIENT6_RELEASE_BEFORE_QUIT" = "yes" ; then
rm -f "$DHCP6IFLEASE"
fi
rm -f "$DHCP6IFPID"
;;
esac
done
else
debug "Shutting down dhcp clients on all interfaces"
for i in `ls -1 /sys/class/net 2>/dev/null` ; do
test -d "/sys/class/net/$i" || continue
ALL_INTERFACES=(${ALL_INTERFACES[@]} $i)
done
fi
STATUS=$R_SUCCESS
# now verify it & "kill them all"
# catching also INTERFACE=all case
for INTERFACE in ${ALL_INTERFACES[@]} ; do
# Read temporary startmode and use kill -9 to stop
tmp_startmode=`read_cached_config_data startmode $INTERFACE`
[ -n "$tmp_startmode" ] && STARTMODE="$tmp_startmode"
# try to catch also config changes
dhcpcd_on_device=`any_dhcpc_on_iface`
if test -n "$dhcpcd_on_device" ; then
# send termination signal
test "$STARTMODE" = "nfsroot" && \
USE_SIGNAL="-KILL" || \
USE_SIGNAL="-TERM"
for i in $dhcpcd_on_device; do
kill $USE_SIGNAL $i &>/dev/null
done
# wait until the processes are gone
for i in $dhcpcd_on_device; do
for ((wait=0; wait<=10; wait++)); do
if test -d /proc/$i ; then
usleep 300000
else
continue 2
fi
if [ $wait -eq 10 ]; then
debug "process $i still not dead, sending SIGKILL"
kill -KILL $i &>/dev/null
fi
done
done
# double check & set status
for i in $dhcpcd_on_device; do
kill -0 $i 2>/dev/null && STATUS=$R_ERROR
done
fi
# Hmm...:
#if [ $STATUS -eq $R_SUCCESS ] ; then
# delete primary flag from cache file if needed
delete_from_cached_config_data primary yes $INTERFACE
delete_from_cached_config_data 'dhcp4_*' '' $INTERFACE
delete_from_cached_config_data 'dhcp6_*' '' $INTERFACE
commit_cached_config_data $INTERFACE
# This is useful for pcmcia interfaces... before the modules can be
# unloaded, the device must be unused.
if [ "$STARTMODE" != "nfsroot" -a "$DHCLIENT_SET_DOWN_LINK" = yes ] ; then
if [ -d /sys/class/net/$INTERFACE ] ; then
ip link set down dev $INTERFACE
fi
fi
#fi
done
exit $STATUS
;;
status)
if ifup_on_iface ; then
print_mesg mesg ". . . is just beeing set up"
exit $R_DHCP_BG
fi
DHCP4_STATUS=$R_NOTCONFIGURED
DHCP6_STATUS=$R_NOTCONFIGURED
for BOOTPROTO in ${BOOTPROTOS[@]} ; do
case "$BOOTPROTO" in
(dhcp4)
if dhcpc4_on_iface -q; then
print_mesg mesg "DHCP4 client ($DHCLIENT) is running"
case "$DHCLIENT" in
(dhcpcd)
stamp=/var/lib/dhcpcd/dhcpcd-$INTERFACE.timestamp
info=/var/lib/dhcpcd/dhcpcd-$INTERFACE.info
state=`read_cached_config_data dhcp4_state $INTERFACE`
if [ "x$state" = "xcomplete" -a \
\( -e $info -a ! $info -ot $stamp \) -a -n \
"`ip -o -f inet addr show $INTERFACE`" ]; then
while read line ; do
case "$line" in
IPADDR=*) eval "${line/IPADDR=/IP=}" ;;
NETMASK=*) eval "${line/NETMASK=/NM=}" ;;
HOSTNAME=*) eval "${line/HOSTNAME=/HN=}" ;;
esac
done < $info
if test -n "$IP" ; then
DHCP4_MESSAGE="IP address: $IP"
NL=$(mask2pfxlen $NM)
if test -n "$NM" ; then
DHCP4_MESSAGE="$DHCP4_MESSAGE/$NL"
fi
if test -n "$HN" ; then
DHCP4_MESSAGE="$DHCP4_MESSAGE ($HN)"
fi
print_mesg mesg "$DHCP4_MESSAGE"
fi
DHCP4_STATUS=$R_SUCCESS
else
print_mesg mesg ". . . but is still waiting for data"
DHCP4_STATUS=$R_DHCP_BG
fi
;;
dhclient)
state=`read_cached_config_data dhcp4_state $INTERFACE`
if [ "x$state" = "xcomplete" -a \
-n "`ip -o -f inet addr show $INTERFACE`" ]; then
:
DHCP4_STATUS=$R_SUCCESS
else
print_mesg mesg ". . . but is still waiting for data"
DHCP4_STATUS=$R_DHCP_BG
fi
;;
esac
else
print_mesg mesg "DHCP4 client NOT running"
DHCP4_STATUS=$R_NOTRUNNING
fi
;;
(dhcp6)
if dhcpc6_on_iface -q; then
print_mesg mesg "DHCP6 client ($DHCLIENT6) is running"
case "$DHCLIENT6" in
(dhcp6c)
DHCP6_STATUS=$R_DHCP_BG
DHCP6_MESSAGE=''
while read a b c d rest; do
config="/var/lib/dhcpv6/dhcp6c.${INTERFACE}.conf"
leases="/var/lib/dhcpv6/client6.leases*"
leases=$(grep -sl "^lease[ \t]\+${d}" $leases 2>/dev/null)
for lease in ${leases} ; do
if [ $lease -nt $config ] ; then
DHCP6_MESSAGE="IP address: $d"
DHCP6_STATUS=$R_SUCCESS
break 2
fi
done
done < <(ip -o -6 addr show $INTERFACE)
if [ -n "$DHCP6_MESSAGE" ] ; then
print_mesg mesg "$DHCP6_MESSAGE"
else
print_mesg mesg ". . . but is still waiting for data"
fi
;;
dhclient6)
state=`read_cached_config_data dhcp6_state $INTERFACE`
if [ "x$state" = "xcomplete" -a \
-n "`ip -o -f inet6 addr show $INTERFACE`" ]; then
:
DHCP6_STATUS=$R_SUCCESS
else
DHCP6_STATUS=$R_DHCP_BG
print_mesg mesg ". . . but is still waiting for data"
fi
;;
esac
else
print_mesg mesg "DHCP6 client NOT running"
DHCP6_STATUS=$R_NOTRUNNING
fi
;;
esac
done
debug "DHCP4(required=$explicit_dhcp4) STATUS=$DHCP4_STATUS"
debug "DHCP6(required=$explicit_dhcp6) STATUS=$DHCP6_STATUS"
case "${explicit_dhcp4}_${explicit_dhcp6}" in
(yes_yes) # BOOTPROTO=dhcp4+dhcp6 (need both to report success)
if [ $DHCP4_STATUS = $R_SUCCESS -a $DHCP6_STATUS = $R_SUCCESS ] ; then
exit $R_SUCCESS
elif [ $DHCP4_STATUS = $R_DHCP_BG -o $DHCP6_STATUS = $R_DHCP_BG ] ; then
exit $R_DHCP_BG
elif [ $DHCP4_STATUS != $R_NOTCONFIGURED ] ; then
exit $DHCP4_STATUS
elif [ $DHCP6_STATUS != $R_NOTCONFIGURED ] ; then
exit $DHCP6_STATUS
fi
;;
(no_no) # BOOTPROTO=dhcp (one is sufficient)
if [ $DHCP4_STATUS = $R_SUCCESS -o $DHCP6_STATUS = $R_SUCCESS ] ; then
exit $R_SUCCESS
elif [ $DHCP4_STATUS = $R_DHCP_BG -o $DHCP6_STATUS = $R_DHCP_BG ] ; then
exit $R_DHCP_BG
elif [ $DHCP4_STATUS != $R_NOTCONFIGURED ] ; then
exit $DHCP4_STATUS
elif [ $DHCP6_STATUS != $R_NOTCONFIGURED ] ; then
exit $DHCP6_STATUS
fi
;;
(yes_no) # BOOTPROTO=dhcp4
exit $DHCP4_STATUS
;;
(no_yes) # BOOTPROTO=dhcp6
exit $DHCP6_STATUS
;;
esac
exit $R_ERROR
;;
esac
ACC SHELL 2018