home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 2007 January, February, March & April
/
Chip-Cover-CD-2007-02.iso
/
boot
/
i386
/
rescue
/
sbin
/
ifup-dhcp
< prev
next >
Wrap
Text File
|
2006-11-29
|
17KB
|
512 lines
#! /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
#
# $Id: ifup-dhcp 1525 2006-11-20 11:39:48Z zoz $
#
usage () {
echo $@
echo "Usage: if{up,down,status}-dhcp [<config>] <hwdesc> [-o <options>]"
echo " hwdesc may be the interface name or any valid description"
echo " of the corresponding device, for details see ifup(8)."
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
}
dhcpc_on_iface() {
local i
for i in `my_pidof $DHCLIENT`; do
case $(cat /proc/$i/cmdline) in
*$INTERFACE*) return 0
esac
done
return 1
}
ifup_on_iface() {
ps ax | grep -v grep | grep -qs "ifup.* $INTERFACE\>"
}
######################################################################
# 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
# . scripts/extradebug
######################################################################
# check arguments and how we are called (in case of links)
#
SCRIPTNAME=${0##*/}
debug $*
case "${SCRIPTNAME}" in
ifup-*) ACTION=start ;;
ifdown-*) ACTION=stop ;;
ifstatus-*) ACTION=status ;;
ifrenew-*) ACTION=renew ;;
*) usage
esac
INTERFACE=$1
case "$INTERFACE" in ""|-h|*help*) usage; esac
shift
if [ -n "$1" -a "$1" != "-o" ] ; then
CONFIG=$INTERFACE
INTERFACE=$1
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
######################################################################
# 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}
if [ -x $DHCLIENT_BIN ]; then
:
elif [ -x /sbin/$DHCLIENT_BIN ]; then
DHCLIENT_BIN=/sbin/$DHCLIENT_BIN;
elif [ -x /sbin/dhclient ]; then
DHCLIENT_BIN=/sbin/dhclient
else
if [ "$INTERFACE" = all ]; then
# 'rcnetwork stop' also calls us with "ifdown-dhcp all" in the end to make
# sure that all DHCP clients are stopped. But if there is none installed,
# there is nothing to do and we can silently quit
exit $R_SUCCESS
else
logerror "DHCP client $DHCLIENT_BIN is not available"
logerror "please install package 'dhcpcd' or 'dhcp-client'"
exit $R_ERROR
fi
fi
DHCLIENT=${DHCLIENT_BIN##*/}
case "$ACTION" in
start|renew)
# avoid that the temporary resolv.conf will persist after the client stops
# just because there hasn't been any resolv.conf to back up
test -e /etc/resolv.conf || touch /etc/resolv.conf
# 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.
if [ $DHCLIENT = dhcpcd ]; then
if [ -s /var/run/dhcpcd-$INTERFACE.pid ]; then
checkproc -k -p /var/run/dhcpcd-$INTERFACE.pid $DHCLIENT_BIN
ret=$?
if [ $ret = 1 -o $ret = 7 ]; then
message removing stale pid file /var/run/dhcpcd-$INTERFACE.pid
rm -f /var/run/dhcpcd-$INTERFACE.pid
fi
fi
fi
# 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
if [ "$ACTION" = 'start' ] \
&& ( 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:
already_running=false
for i in `my_pidof $DHCLIENT`; do
case $(cat /proc/$i/cmdline) in
*$INTERFACE*) already_running=true;;
esac
done
if $already_running; then
if test "$RUN_FROM_RC" = yes; then
while read a b c d e f g h i; do
message "`printf " %-9s IP address: %s (DHCP was already running)" $i $d`"
R_DHCP_BG=$R_SUCCESS
done < <(ip -o -4 addr show $INTERFACE)
if [ "$R_DHCP_BG" != "$R_SUCCESS" ] ; then
message "`printf " %-9s DHCP already running" $INTERFACE`"
fi
else
message "DHCP client is already running on $INTERFACE"
fi
exit $R_DHCP_BG
fi
elif [ "$ACTION" = 'renew' ]; then
case $DHCLIENT in
dhcpcd)
for i in `my_pidof $DHCLIENT`; do
case $(cat /proc/$i/cmdline) in
*$INTERFACE*) dhcpcd_on_device="$dhcpcd_on_device $i"
esac
done
for i in $dhcpcd_on_device; do
kill -TERM $i &>/dev/null
done
sleep 1
;;
dhclient)
killproc $DHCLIENT_BIN &>/dev/null
;;
esac
fi
# there is already a dhcpcd 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_DOMAINNAME \
DHCLIENT_KEEP_SEARCHLIST \
DHCLIENT_MODIFY_RESOLV_CONF \
DHCLIENT_SET_DEFAULT_ROUTE \
DHCLIENT_MODIFY_NTP_CONF \
DHCLIENT_MODIFY_NIS_CONF
test -f ./ifcfg-$CONFIG && . ./ifcfg-$CONFIG
fi
debug "Starting service dhcp client on $INTERFACE"
ip link set $INTERFACE up ${MTU:+mtu $MTU} \
${LLADDR:+address $LLADDR} $LINK_OPTIONS
for a in 1 2 3 4 5; do is_iface_up $INTERFACE && break; sleep 1; done
# (optionally) wait until a device is really configured
sleep ${DHCLIENT_SLEEP:-0}
if [ "$DHCLIENT" = "dhcpcd" ] ; then
# The following DHCLIENT_ARGS are specific to dhcpcd.
# (the ISC DHCP client can be finetuned via /etc/dhclient.conf
# and so-called hooks (see man 8 dhclient-script)
test "$DHCLIENT_DEBUG" = "yes" && args="-d"
test "$DHCLIENT_UDP_CHECKSUM" = "yes" && args="$args -C"
test "$DHCLIENT_SET_HOSTNAME" = "yes" && args="$args -H"
test "$DHCLIENT_SET_DOMAINNAME" = "yes" && args="$args -D"
test "$DHCLIENT_KEEP_SEARCHLIST" = "yes" && args="$args -K"
test "$DHCLIENT_MODIFY_RESOLV_CONF" != "yes" && args="$args -R"
test "$DHCLIENT_SET_DEFAULT_ROUTE" != "yes" && args="$args -G"
test "$DHCLIENT_MODIFY_NTP_CONF" != "yes" && args="$args -N"
test "$DHCLIENT_MODIFY_NIS_CONF" != "yes" && args="$args -Y"
test -n "$DHCLIENT_TIMEOUT" \
&& args="$args -t $DHCLIENT_TIMEOUT"
test -n "$DHCLIENT_REBOOT_TIMEOUT" \
&& args="$args -z $DHCLIENT_REBOOT_TIMEOUT"
test -n "$DHCLIENT_CLIENT_ID" \
&& args="$args -I $DHCLIENT_CLIENT_ID"
test -n "$DHCLIENT_VENDOR_CLASS_ID" \
&& args="$args -i $DHCLIENT_VENDOR_CLASS_ID"
test -n "$DHCLIENT_LEASE_TIME" \
&& args="$args -l $DHCLIENT_LEASE_TIME"
test -n "$DHCLIENT_ADDITIONAL_OPTIONS" \
&& args="$args $DHCLIENT_ADDITIONAL_OPTIONS"
# 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"
# this used to be hardcoded in the dhcpcd binary, but we have reverted it in order
# to allow innocent commandline users to use dhcpcd without calling the
# dhcpcd-hook/ifup machinery [#85849]
args="$args -c ${DHCLIENT_SCRIPT_EXE:-/etc/sysconfig/network/scripts/dhcpcd-hook}"
DHCLIENT_ARGS=$args
# just in case /var is not mounted
test -d /var/lib/dhcpcd || mkdir -p /var/lib/dhcpcd
timestamp=/var/lib/dhcpcd/dhcpcd-$INTERFACE.timestamp; touch $timestamp
info=/var/lib/dhcpcd/dhcpcd-$INTERFACE.info
if test "$RUN_FROM_RC" = yes; then
message_n "`printf " %-9s (DHCP) " $INTERFACE`"
# message_n "(DHCP) "
else
message_n "Starting DHCP Client Daemon on $INTERFACE... "
fi
# now start dhcpcd
$DHCLIENT_BIN $DHCLIENT_ARGS $INTERFACE </dev/null &>/dev/null &
# wait some more time until dhcpcd has done its job.
# it would be easier to wait for the pidfile, but it is written later
for ((i=0; i<${DHCLIENT_WAIT_AT_BOOT:-15}; i++)); do
if [ -e $info -a ! $info -ot $timestamp ]; then continue
else message_n .\ ; sleep 1
fi
done
if [ -e $info -a ! $info -ot $timestamp ]; then
while read line; do
case "$line" in
IPADDR*) message_n ${line/IPADDR=/IP/Netmask: };;
NETMASK*) message_n " / ${line/NETMASK=/}";;
HOSTNAME*) message_n " (${line/HOSTNAME=/})";;
esac
done < $info
message " "
R_DHCP_BG=$R_SUCCESS
else
message "no IP address yet... backgrounding. "
fi
exit $R_DHCP_BG
else
# if we are here, then $DHCLIENT is the ISC dhclient
# don't write copyright info
DHCLIENT_ARGS="-q"
# If ISC dhclient should be used for more than one interfaces, we have
# to stop it and restart it with all interfaces when adding an
# interface. !!! Currently, we do not provide that.
if checkproc $DHCLIENT_BIN; then
logerror "$DHCLIENT is already running for some interface." \
"Stop it first.\nIf you want to run dhcp on several " \
"interfaces, please use dhcpcd."
else
startproc -f -t ${STARTPROC_TIMEOUT:-1} -q $DHCLIENT_BIN \
$DHCLIENT_ARGS $INTERFACE
fi
fi
;;
stop)
debug "Shutting down service dhcp client on $INTERFACE"
case $DHCLIENT in
dhcpcd)
# let's first test if any dhcpcd processes are running on this
# interface. Unfortunately, the pid file is not there when it starts
# up, so we can't rely on that. Normally, only one process is running
# per interface. but we have made bad experiences with ...hotplug
for i in `my_pidof $DHCLIENT`; do
case $(cat /proc/$i/cmdline) in
*$INTERFACE*) dhcpcd_on_device="$dhcpcd_on_device $i"
esac
done
test "$DHCLIENT_RELEASE_BEFORE_QUIT" = "yes" \
&& USE_SIGNAL="-HUP" || 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<30; wait++)); do
if test -d /proc/$i; then usleep 300000
else continue 2
fi
if [ $wait = 20 ]; then
echo process $i still not dead, sending SIGKILL
kill -KILL $i &>/dev/null
fi
done
done
if [ -z "$dhcpcd_on_device" ]; then
# dhcpcd may not be running (it quits if it gets an
# infinite lease)
info=/var/lib/dhcpcd/dhcpcd-$INTERFACE.info
if test -s $info && grep -q LEASETIME=4294967295 $info; then
debug "dhcpcd is no longer running on $INTERFACE, since it got"
debug "an infinite lease. Manually shutting down the interface."
ip addr flush dev $INTERFACE &>/dev/null
ip link set dev $INTERFACE down &>/dev/null
fi
fi
;;
dhclient)
# If ISC dhclient is used for more than one interfaces, we have to stop
# it and restart it without this interface when removing one interface,
# or we have to use the OMAPI interface
# !!! Currently, we do not provide that.
killproc $DHCLIENT_BIN &>/dev/null
;;
esac
# We send -9 because interfaces have to stay up for STARTMODE==nfsroot
test "$INTERFACE" = all && killall -9 $DHCLIENT_BIN &>/dev/null
# delete primary flag from cache file
delete_from_cached_config_data primary yes $INTERFACE
commit_cached_config_data $INTERFACE
# This is useful for pcmcia interfaces... before the modules can be
# unloaded, the device must be unused.
if [ "$DHCLIENT_SET_DOWN_LINK" = yes ] ; then
ip link set down dev $INTERFACE
fi
;;
status)
if test -z "`ip -o -f inet addr show $INTERFACE`"; then
# interface has currently no ipv4 address assigned
if dhcpc_on_iface ; then
message "`printf " %-9s %s is still waiting for data" $INTERFACE $DHCLIENT`"
exit $R_DHCP_BG
elif ifup_on_iface ; then
message "`printf " %-9s is just beeing set up" $INTERFACE`"
exit $R_DHCP_BG
else
message "`printf " %-9s DHCP client NOT running" $INTERFACE`"
exit $R_NOTRUNNING
fi
else
# interface has at least one ipv4 address
if dhcpc_on_iface ; then
message "`printf " %-9s DHCP client (%s) is running" $INTERFACE $DHCLIENT`"
# Show more info if not run from initscript
if [ "$RUN_FROM_RC" != yes ] ; then
case $DHCLIENT in
dhcpcd)
if test -e /var/lib/dhcpcd/dhcpcd-$INTERFACE.info; then
# message " current lease for $INTERFACE:"
while read line; do
case "$line" in
IPADDR*|NETMASK*|GATEWAY*|HOSTNAME*|DOMAIN*)
message " "$line ;;
DNS*|DHCPCHADDR*|DHCPSIADDR*|REBINDTIME*)
message " "$line ;;
*) ;;
esac
done < /var/lib/dhcpcd/dhcpcd-$INTERFACE.info
else
message /var/lib/dhcpcd/dhcpcd-$INTERFACE.info file \
not available
fi
;;
dhclient)
if test -e /var/lib/dhcp/dhclient.leases; then
message last lease in /var/lib/dhcp/dhclient.leases:
awk 'BEGIN {RS="lease[[:blank:]]*{"; FS="}"} {lease=$1} END {print "{" lease "} "}' \
/var/lib/dhcp/dhclient.leases
else
message /var/lib/dhcp/dhclient.leases file not available
fi
;;
esac
fi
elif ifup_on_iface ; then
message "`printf " %-9s is just beeing set up" $INTERFACE`"
exit $R_DHCP_BG
else
message "`printf " %-9s DHCP client NOT running" $INTERFACE`"
if [ "$RUN_FROM_RC" = yes ] ; then
while read a b c d e f g h i; do
message "`printf " %-9s IP address: %s (DHCP)" ${i:-$b} $d`"
done < <(ip -o -4 addr show $INTERFACE)
else
message "$(ip addr show $INTERFACE)"
fi
exit $R_NOTRUNNING
fi
fi
esac