#! /bin/bash # Copyright (c) 1996, 1997, 1998 S.u.S.E. GmbH # Copyright (c) 1998, 1999, 2000, 2001 SuSE GmbH # Copyright (c) 2002, 2003 SuSE Linux AG # Copyright (c) 2004-2014 SUSE LINUX Products GmbH, Nuernberg, Germany. # # 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 . # # Author: Rolf Haberrecker , 1997-1999 # Peter Poeml , 2000-2006 # Marius Tomaschewski , 2006-2010 # # /usr/lib/dhcp/dhcpd helper script, fromer /etc/init.d/dhcpd init script. # ### test -s /etc/sysconfig/dhcpd && . /etc/sysconfig/dhcpd SUPPORTS_CHROOT="yes" SUPPORTS_RUN_AS="yes" SUPPORTS_HUP="no" # note: $DAEMON_PIDFILE is a symlink to the # $DAEMON_STATE$DAEMON_PIDFILE (also # while DHCPD_RUN_CHROOTED=no) now, # as DHCPD_RUN_AS is not allowed to # create pid files in /run. DHCPv_OPT=$1 ; shift case $DHCPv_OPT in -4) DAEMON='ISC DHCPv4 Server' DAEMON_BIN=/usr/sbin/dhcpd DAEMON_CONF=/etc/dhcpd.conf DAEMON_STATE=/var/lib/dhcp DAEMON_LEASES=dhcpd.leases DAEMON_PIDFILE=/run/dhcpd.pid STARTPROC_LOGFILE=/var/log/rc.dhcpd.log LDAP_CONF=/etc/openldap/ldap.conf test "$DHCPD_RUN_CHROOTED" = "yes" && \ CHROOT_PREFIX="$DAEMON_STATE" || CHROOT_PREFIX='' DHCPD_CONF_INCLUDE_FILES=${DHCPD_CONF_INCLUDE_FILES:-/etc/dhcpd.d} ;; -6) DAEMON='ISC DHCPv6 Server' DAEMON_BIN=/usr/sbin/dhcpd DAEMON_CONF=/etc/dhcpd6.conf DAEMON_STATE=/var/lib/dhcp6 DAEMON_LEASES=dhcpd6.leases DAEMON_PIDFILE=/run/dhcpd6.pid STARTPROC_LOGFILE=/var/log/rc.dhcpd6.log LDAP_CONF="" test "$DHCPD6_RUN_CHROOTED" = "yes" && \ CHROOT_PREFIX="$DAEMON_STATE" || CHROOT_PREFIX='' DHCPD_RUN_AS=$DHCPD6_RUN_AS DHCPD_INTERFACE=$DHCPD6_INTERFACE DHCPD_OTHER_ARGS=$DHCPD6_OTHER_ARGS DHCPD_CONF_INCLUDE_FILES=${DHCPD6_CONF_INCLUDE_FILES:-/etc/dhcpd6.d} ;; *) echo >&2 "Usage: $0 <-4|-6> " exit 2 ;; esac # Return values acc. to LSB for all commands but status: # 0 - success # 1 - generic or unspecified error # 2 - invalid or excess argument(s) # 3 - unimplemented feature (e.g. "reload") # 4 - insufficient privilege # 5 - program is not installed # 6 - program is not configured # 7 - program is not running # # Note that starting an already running service, stopping # or restarting a not-running service as well as the restart # with force-reload (in case signalling is not supported) are # considered a success. if ! [ -x "$DAEMON_BIN" ]; then case $1 in stop) ;; *) echo -n >&2 "\"$DAEMON_BIN\" is not an executable file. Exiting." case $1 in status) exit 4 ;; *) exit 5 ;; esac ;; esac exit fi if ! [ -r "$DAEMON_CONF" ] ; then case $1 in stop|status) if test ! -s /etc/sysconfig/dhcpd ; then test -e $DAEMON_STATE/$DAEMON_PIDFILE && \ CHROOT_PREFIX="$DAEMON_STATE" || CHROOT_PREFIX='' fi ;; *) echo -n >&2 "\"$DAEMON_CONF\" config file missed. Exiting." exit 6 ;; esac fi # remove empty pid files to avoid disturbing warnings by checkproc/killproc # (these can occur if dhcpd does not start correctly) test -e $DAEMON_PIDFILE && ! test -s $DAEMON_PIDFILE && rm $DAEMON_PIDFILE test -e $DAEMON_STATE/$DAEMON_PIDFILE && ! test -s $DAEMON_STATE/$DAEMON_PIDFILE && rm $DAEMON_STATE/$DAEMON_PIDFILE case "$1" in start) echo -n "Starting $DAEMON " ## If there is no conf file, skip starting of dhcpd ## and return with "program not configured" if ! [ -f $DAEMON_CONF ]; then echo -n "... no configuration file found"; # service is not configured exit 6; fi ## If the interfaces are not set, skip starting of dhcpd ## and return with "program not configured" if [ -z "$DHCPD_INTERFACE" ]; then var="DHCPD_INTERFACE" case $DHCPv_OPT in -6) var=DHCPD6_INTERFACE ;; esac echo -n "... set $var in /etc/sysconfig/dhcpd" # service is not configured exit 6; fi if [ "$DHCPD_INTERFACE" = "ANY" ]; then DHCPD_INTERFACE="" fi jail=${CHROOT_PREFIX:-${DAEMON_STATE}}; leases=$DAEMON_LEASES if ! [ -e $jail/db/$leases ]; then # until 9.0, the lease file was in /var/lib/dhcp and part of the package if test -e $jail/$leases -a '!' -L $jail/$leases; then # this is the case where the %post script runs _before_ the old package is # removed (i.e., dhcpd.leases has not renamed to .rpmsave yet) mv $jail/$leases $jail/db/$leases && \ ln -s db/$leases $jail/ elif test -e $jail/$leases.rpmsave; then # this is what's left when the package is already gone. mv $jail/$leases.rpmsave $jail/db/$leases && \ ln -s db/$leases $jail/ else # fresh installation: # a lease file must be present. the server won't start without touch $jail/db/$leases fi fi if test "$DHCPD_RUN_CHROOTED" = "yes" ; then ## copy the conf file to the chroot jail (dhcpd has to be restarted anyway, ## when it has changed) and change path to leases file for i in $DAEMON_CONF $DHCPD_CONF_INCLUDE_FILES $LDAP_CONF /etc /dev; do if test -d "${i}" ; then test -d "$CHROOT_PREFIX/${i}" || \ mkdir -p "$CHROOT_PREFIX/${i}" elif test -e "${i}" ; then test -d "$CHROOT_PREFIX/${i%/*}" || \ mkdir -p "$CHROOT_PREFIX/${i%/*}" fi done rm -f $CHROOT_PREFIX/dev/urandom for i in $DAEMON_CONF $DHCPD_CONF_INCLUDE_FILES $LDAP_CONF /etc/{gai.conf,nsswitch.conf,resolv.conf,host.conf,hosts,localtime,bindresvport.blacklist} /dev/urandom; do if ! test -e "$i"; then continue; fi # neither of them is absolutely necessary cp -aL "$i" "${CHROOT_PREFIX}/${i%/*}/" &>/dev/null \ || { echo "...$0:$LINENO: could not copy $i to chroot jail"; exit 6; } done libdir=@LIBDIR@ if test -x /usr/bin/ldd ; then get_ldd_deps() { ldd_wl="\/${libdir}\/lib" ldd_bl="\/${libdir}\/libc\." /usr/bin/ldd "$1" | \ while read -sr a b c d ; do [ -n "$c" ] || continue [[ $c =~ $ldd_wl ]] || continue [[ $c =~ $ldd_bl ]] && continue echo $c done } else get_ldd_deps() { :; } fi cplibs=`for i in /$libdir/{libresolv.so.*,libnss_*.so.*} \ /$libdir/{libpthread.so.0,libdl.so.2,libgcc_s.so.*} ; do if [ -s "$i" ] ; then echo "$i" get_ldd_deps "$i" fi done | sort -u` for i in $cplibs ; do if [ -s "$i" ]; then cp -pL "$i" "${CHROOT_PREFIX}/$libdir/" \ || { echo "...$0:$LINENO: could not copy $i to chroot jail"; exit 6; } fi done # mount /proc into the chroot; the server fails if unable to read /proc/net/{dev,if_inet6} mkdir -p ${CHROOT_PREFIX}/proc mount -t proc -o ro proc ${CHROOT_PREFIX}/proc 2>/dev/null DHCPD_ARGS="-chroot $CHROOT_PREFIX -lf /db/$DAEMON_LEASES" ## If there is a pid file containing a pid, the machine might have crashed. pid files in ## /run are always cleaned up at boot time, but this is not the case for the pid file in ## the chroot jail. Therefore, and old pid file may exist. This is only a problem if it ## incidentally contains the pid of a running process. If this process is not a 'dhcpd', ## we remove the pid. (dhcpd itself only checks whether the pid is alive or not.) if test -s $DAEMON_STATE/$DAEMON_PIDFILE; then p=$(<$DAEMON_STATE/$DAEMON_PIDFILE) if test -n "$p" && grep -qsE "^${DAEMON_BIN}" "/proc/$p/cmdline" ; then echo -n '(already running) ' else rm -f $DAEMON_STATE/$DAEMON_PIDFILE fi fi PID_FILE_ARG="$DAEMON_PIDFILE" else DHCPD_ARGS="-lf ${DAEMON_STATE}/db/$DAEMON_LEASES" PID_FILE_ARG="$DAEMON_STATE$DAEMON_PIDFILE" fi if [ -n "$DHCPD_RUN_AS" ]; then DHCPD_RUN_AS_GROUP="$(getent group $(getent passwd $DHCPD_RUN_AS | cut -d: -f4) | cut -d: -f1)" DHCPD_ARGS="$DHCPD_ARGS -user $DHCPD_RUN_AS -group $DHCPD_RUN_AS_GROUP" chown "${DHCPD_RUN_AS}:${DHCPD_RUN_AS_GROUP}" \ "$DAEMON_STATE/${DAEMON_PIDFILE%/*}" fi ## check syntax with -t (output to log file) and start only when the syntax is okay rm -f $STARTPROC_LOGFILE # start log error=0 if ! $DAEMON_BIN $DHCPv_OPT -t -cf $CHROOT_PREFIX/$DAEMON_CONF -pf $PID_FILE_ARG > $STARTPROC_LOGFILE 2>&1 ; then error=1 else ## Start daemon. If this fails the return value is set appropriate. ## The init script should return 0, even if service is already running, ## to match the LSB spec. test "$2" = "-v" && echo -en \ "\nexecuting '$DAEMON_BIN $DHCPv_OPT -cf $DAEMON_CONF -pf $PID_FILE_ARG $DHCPD_ARGS $DHCPD_OTHER_ARGS $DHCPD_INTERFACE'" $DAEMON_BIN $DHCPv_OPT -cf $DAEMON_CONF -pf $PID_FILE_ARG $DHCPD_ARGS $DHCPD_OTHER_ARGS $DHCPD_INTERFACE &> $STARTPROC_LOGFILE ret=$? fi if [ $error -gt 0 -o ${ret:-0} -gt 0 ]; then ## be verbose echo "" echo -n " please see $STARTPROC_LOGFILE for details " ## set status to failed exit 1 else ln -sf "$DAEMON_STATE$DAEMON_PIDFILE" "$DAEMON_PIDFILE" [ "$DHCPD_RUN_CHROOTED" = "yes" ] && echo -n "[chroot]" || : fi ;; stop) echo -n "Shutting down $DAEMON " # Catch the case where daemon is running without chroot, # but sysconfig/dhcp has been changed to use chroot (and # another way around). # In this case is there is no $chroot/$pidfile, but there # should be a /pidfile that we use instead. # We can not kill without pid file or dhcp4 kills dhcp6. PID_FILE="$DAEMON_STATE$DAEMON_PIDFILE" if test "$DHCPD_RUN_CHROOTED" = "yes" ; then if test ! -s "$DAEMON_STATE$DAEMON_PIDFILE" -a \ -s "$DAEMON_PIDFILE" ; then PID_FILE="$DAEMON_PIDFILE" fi else if test ! -s "$DAEMON_PIDFILE" -a \ -s "$DAEMON_STATE$DAEMON_PIDFILE" ; then PID_FILE="$DAEMON_STATE$DAEMON_PIDFILE" fi fi ## Stop daemon with killproc(8) and if this fails ## set echo the echo return value. killproc -p "$PID_FILE" $DAEMON_BIN ret=$? # umount proc and remove libraries from the chroot jail, # so they are not left over if the server is deinstalled if [ "$DHCPD_RUN_CHROOTED" = yes -a -n "$CHROOT_PREFIX" ]; then umount ${CHROOT_PREFIX}/proc 2>/dev/null rm -f $CHROOT_PREFIX/lib*/* fi exit $ret ;; try-restart) ## Do a restart only if the service was active before. ## Note: try-restart is now part of LSB (as of 1.9). ## RH has a similar command named condrestart. $0 $DHCPv_OPT status if test $? = 0; then $0 $DHCPv_OPT restart fi ;; restart) ## Check syntax and when it is OK, stop the service ## and regardless of whether it was running or not, ## start it again. if ! $0 $DHCPv_OPT check-syntax &>/dev/null ; then echo -n "Syntax check reports errors, see log messages" exit 1 else $0 $DHCPv_OPT stop sleep 3 $0 $DHCPv_OPT start fi ;; force-reload) ## Signal the daemon to reload its config. Most daemons ## do this on signal 1 (SIGHUP). ## If it does not support it, restart. if [ "$SUPPORTS_HUP" = "yes" ]; then echo -n "Reload service $DAEMON" killproc -p $DAEMON_STATE/$DAEMON_PIDFILE -HUP $DAEMON_BIN #touch $DAEMON_STATE/$DAEMON_PIDFILE elif ! $0 $DHCPv_OPT check-syntax &>/dev/null ; then echo -n "Syntax check reports errors, see log messages" exit 1 else $0 $DHCPv_OPT stop && sleep 3 && $0 $DHCPv_OPT start fi ;; reload) ## Like force-reload, but if daemon does not support ## signalling, do nothing (!) echo -n "Reload service $DAEMON" if [ "$SUPPORTS_HUP" = "yes" ]; then # If it supports signalling: killproc -p $DAEMON_STATE/$DAEMON_PIDFILE -HUP $DAEMON_BIN #touch $DAEMON_STATE/$DAEMON_PIDFILE else ## Otherwise if it does not support reload: exit 3 fi ;; status) echo -n "Checking for $DAEMON: " ## Check status with checkproc(8), if process is running ## checkproc will return with exit status 0. # Status has a slightly different for the status command: # 0 - service running # 1 - service dead, but /run/ pid file exists # 2 - service dead, but /var/lock/ lock file exists # 3 - service not running # NOTE: checkproc returns LSB compliant status values. checkproc -p $DAEMON_STATE/$DAEMON_PIDFILE $DAEMON_BIN ;; probe) ## Optional: Probe for the necessity of a reload, ## give out the argument which is required for a reload. rc=0 for i in /etc/sysconfig/dhcpd $DAEMON_CONF $DHCPD_CONF_INCLUDE_FILES; do test $i -nt $DAEMON_STATE/$DAEMON_PIDFILE && rc=1 done test $rc = 1 && echo restart ;; check-syntax|syntax-check) echo -n "Checking syntax of $DAEMON_CONF: " ## this nice bit is from Edwin Groothuis: ## check syntax (quiet) $DAEMON_BIN $DHCPv_OPT -q -t -cf $DAEMON_CONF if [ $? -ne 0 ]; then echo "" ## check syntax (verbose) $DAEMON_BIN $DHCPv_OPT -t -cf $DAEMON_CONF echo -ne '\nConfig is NOT okay' exit 1 fi ;; check-lease|check-lease-file) echo -n "Checking lease file $DAEMON_LEASES: " if [ -s ${DAEMON_STATE}/db/$DAEMON_LEASES ] ; then ## check leases file (quiet) $DAEMON_BIN $DHCPv_OPT -q -T -cf /dev/null -lf ${DAEMON_STATE}/db/$DAEMON_LEASES if [ $? -ne 0 ]; then echo "" ## check leases file (verbose) $DAEMON_BIN $DHCPv_OPT -T -cf $DAEMON_CONF -lf ${DAEMON_STATE}/db/$DAEMON_LEASES echo -ne '\nLease file is NOT okay' exit 1 fi fi ;; *) SCRIPT="${SCRIPT:-${0##*/} $DHCPv_OPT}" echo "Usage: $SCRIPT {start|stop|status|try-restart|restart|force-reload|reload|probe|check-syntax} [-v]" exit 1 esac