ifup-dhcp: fix for check whether ipv6 is enabled
[opensuse:chkpnts-sysconfig.git] / scripts / ifup-dhcp
1 #! /bin/bash
2 #
3 # Copyright (c) 2002 SuSE Linux AG Nuernberg, Germany. All rights reserved.
4 # This program is free software; you can redistribute it and/or modify it under
5 # the terms of the GNU General Public License as published by the Free Software
6 # Foundation; either version 2 of the License, or (at your option) any later
7 # version.
8 #
9 # This program is distributed in the hope that it will be useful, but WITHOUT
10 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11 # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
12 # details.
13 #
14 # You should have received a copy of the GNU General Public License along with
15 # this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 # Place, Suite 330, Boston, MA 02111-1307 USA
17 #
18 # Author: Christian Zoz <zoz@suse.de>, 2002-2006
19 #         Peter Poeml <poeml@suse.de>, 2002-2006
20 #
21 # $Id$
22 #
23
24 usage () {
25         echo $@
26         echo "Usage: if{up,down,status}-dhcp [<config>] <interface> [-o <options>]"
27         echo ""
28         echo "Options are: boot      : we are currently booting"
29         echo "             hotplug   : we are handling a hotplug event"
30         echo "             debug     : be verbose"
31         echo "             rc        : indicates that we are called from rcnetwork"
32         echo "All other or wrong options are silently ignored."
33         exit $R_USAGE
34 }
35
36 ######################################################################
37 # change the working direcory and source some common files
38 #
39 R_INTERNAL=1      # internal error, e.g. no config or missing scripts
40 cd /etc/sysconfig/network || exit $R_INTERNAL
41 test -f ./config && . ./config
42 test -f scripts/functions && . scripts/functions || exit $R_INTERNAL
43
44 test "$DEBUG" = "EXTRA" && . scripts/extradebug
45
46 ######################################################################
47 # check arguments and how we are called (in case of links)
48 #
49 SCRIPTNAME=${0##*/}
50 debug "$SCRIPTNAME $*"
51
52 case "${SCRIPTNAME}" in
53         ifup-*) ACTION=start ;;
54         ifdown-*) ACTION=stop ;;
55         ifstatus-*) ACTION=status ;;
56         ifrenew-*) ACTION=renew ;;
57         *) usage
58 esac
59 case "$1" in ""|-h|*help*) usage; esac
60 CONFIG=$1
61 shift
62 if [ -n "$1" -a "$1" != "-o" ] ; then
63         INTERFACE=$1
64 else
65         INTERFACE=$CONFIG
66 fi
67 shift
68 test "$1" = "-o" && shift
69 OPTIONS="$@"
70 MODE=manual
71 while [ $# -gt 0 ]; do
72         case $1 in
73                 boot|onboot) MODE=onboot ;;
74                 hotplug)     MODE=hotplug ;;
75                 quiet)       be_quiet_has_gone ;;
76                 debug)       DEBUG=yes ;;
77                 rc)          RUN_FROM_RC=yes ;;
78                 *)           debug unknown option $1 ;;
79         esac
80         shift
81 done
82
83 ######################################################################
84 # check presence of configuration files
85 #
86 test -f ./dhcp && . ./dhcp
87 test -f ./ifcfg-$CONFIG && . ./ifcfg-$CONFIG
88
89 ######################################################################
90 # get the interface and check if it is up
91 #
92 if [ -z "$INTERFACE" ] ; then
93         usage "No interface given"
94 fi
95 if ! is_iface_available $INTERFACE ; then
96         # When a hotplug remove event occurs the interface has already gone.
97         # Nevertheless we have to clean up.
98         if [ \( "$ACTION" != stop -o "$MODE" != hotplug \) -a "$INTERFACE" != all ] ; then
99                 logerror "interface ${INTERFACE} is not available"
100                 exit $R_NODEV
101         fi
102 fi
103
104 ######################################################################
105 # Normalize & resolve & cleanup the bootproto value from config
106 # Note:
107 # INTERFACE=all is a special case used by rcnetwork stop/ifdown
108 # to kill all dhcp clients that may still run on some interface
109 #
110 explicit_dhcp4=no
111 explicit_dhcp6=no
112 BOOTPROTO=$(echo "$BOOTPROTO" | awk '{print tolower($0);}')
113 # Override with iSCSI Boot Firmware Table (feature 308283, bnc 542225)
114 if [ "$INTERFACE" != "all" -a "${BOOTPROTO}" = "ibft" ] ; then
115         IBFT=yes # not used at the moment... remember before override
116         eval BOOTPROTO=none `parse_ifname_ibft_settings "$INTERFACE"`
117 fi
118 BOOTPROTOS=()
119 AUTOIP=no
120 add_bootproto_once() {
121         local b p
122         for b in $@ ; do
123                 for p in ${BOOTPROTOS[@]} ; do
124                         test "$p" = "$b" && continue 2
125                 done
126                 BOOTPROTOS=(${BOOTPROTOS[@]} ${b})
127         done
128 }
129 for bp in ${BOOTPROTO//+/ } ; do
130         case "$bp" in
131                 (dhcp)  add_bootproto_once dhcp4 dhcp6 ;;
132                 (dhcp4)
133                         explicit_dhcp4=yes
134                         add_bootproto_once ${bp}
135                 ;;
136                 (dhcp6)
137                         explicit_dhcp6=yes
138                         add_bootproto_once ${bp}
139                 ;;
140                 # FIXME: dhcpcd has a builtin autoip support...
141                 #        at the moment we handle autoip in ifup;
142                 #        it needs a "quiet minute" to change it.
143                 #(autoip) AUTOIP=yes ;;
144                 (*) continue ;;
145         esac
146 done
147 if [ "$INTERFACE" != all ] ; then
148         # Read temporary startmode and handle it
149         # [kill -9 on stop, use dhcpcd -p flag on start]
150         tmp_startmode=`read_cached_config_data startmode $INTERFACE`
151         [ -n "$tmp_startmode" ] && STARTMODE="$tmp_startmode"
152 fi
153
154
155 ######################################################################
156 # determine type of dhcp client
157 #
158 # This script is supposed to work with both dhcpcd and the ISC DHCP client,
159 # because there's a lot of common stuff.
160 # If neccesary you can preselect a dhcp client; just set DHCLIENT_BIN in
161 # one of the used config files. If not we prefer dhcpcd if available.
162 : ${DHCLIENT_BIN:=dhcpcd}
163 : ${DHCLIENT6_BIN:=dhcp6c}
164
165 DHCLIENT=""
166 for x in "$DHCLIENT_BIN" \
167          "/sbin/${DHCLIENT_BIN##*/}" \
168          "/sbin/dhcpcd" "/sbin/dhclient" ;
169 do
170         if [ "x$x" != x -a "${x##/*}" != "$x" -a -x "$x" ] ; then
171                 DHCLIENT_BIN="$x"
172                 DHCLIENT=${DHCLIENT_BIN##*/}
173                 break
174         fi
175 done
176 DHCLIENT6=""
177 for x in "$DHCLIENT6_BIN" \
178          "/sbin/${DHCLIENT6_BIN##*/}" \
179          "/sbin/dhcp6c" "/sbin/dhclient6" ;
180 do
181         if [ "x$x" != x -a "${x##/*}" != "$x" -a -x "$x" ] ; then
182                 DHCLIENT6_BIN="$x"
183                 DHCLIENT6=${DHCLIENT6_BIN##*/}
184                 break
185         fi
186 done
187
188
189 print_mesg() {
190         func=$1 ; shift
191         if [ "$RUN_FROM_RC" = yes -a "$INTERFACE" != all ] ; then
192                 $func "`printf "    %-9s $*" $INTERFACE`"
193         else
194                 $func "$*"
195         fi
196 }
197
198 # check installation of supported dhcp clients
199 case "$ACTION" in
200         stop)
201         ;;
202         *)
203                 HAVE_IPv6=yes
204                 test -d /proc/sys/net/ipv6 && {
205                         val1=`cat "/proc/sys/net/ipv6/conf/$INTERFACE/disable_ipv6" 2>/dev/null`
206                         val2=`cat "/proc/sys/net/ipv6/conf/all/disable_ipv6" 2>/dev/null`
207                         test "x$val1" = x1 -o "x$val2" = x1 && HAVE_IPv6=no
208                 } || HAVE_IPv6=no
209
210                 clients=0
211                 bootprotos=(${BOOTPROTOS[@]})
212                 BOOTPROTOS=()
213                 # complain about missed clients
214                 for BOOTPROTO in ${bootprotos[@]} ; do
215                         case "$BOOTPROTO" in
216                         (dhcp4)
217                                 case "$DHCLIENT" in
218                                 (dhcpcd|dhclient)
219                                         if [ -x "$DHCLIENT_BIN" ] ; then
220                                                 clients=$((clients + 1))
221                                                 BOOTPROTOS=(${BOOTPROTOS[@]} $BOOTPROTO)
222                                         else
223                                                 # Huh?!
224                                                 DHCLIENT=""
225                                                 print_mesg err_mesg \
226                                                         "DHCP4 client ($DHCLIENT_BIN) is not available."
227                                                 print_mesg err_mesg \
228                                                         "      Please install 'dhcpcd' or 'dhcp-client'"
229                                         fi
230                                 ;;
231                                 "")
232                                         if [ "x$explicit_dhcp4" = "xyes" ] ; then
233                                                 print_mesg err_mesg "DHCP4 client is not available."
234                                                 print_mesg err_mesg "      Please install 'dhcpcd' or 'dhcp-client'"
235                                         fi
236                                 ;;
237                                 *)
238                                         DHCLIENT=""
239                                         print_mesg err_mesg "DHCP4 client unknown/unsupported: $DHCLIENT_BIN"
240                                         print_mesg err_mesg "      Please install 'dhcpcd' or 'dhcp-client'"
241                                 ;;
242                                 esac
243                         ;;
244                         (dhcp6)
245                                 [ "x$HAVE_IPv6" = xyes ] || DHCLIENT6=""
246
247                                 case "$DHCLIENT6" in
248                                 (dhcp6c)
249                                         if [ -x "$DHCLIENT6_BIN" ] ; then
250                                                 clients=$((clients + 1))
251                                                 BOOTPROTOS=(${BOOTPROTOS[@]} $BOOTPROTO)
252                                         else
253                                                 # Huh?!
254                                                 DHCLIENT6=""
255                                                 print_mesg err_mesg \
256                                                         "DHCP6 client ($DHCLIENT6_BIN) is not available."
257                                                 print_mesg err_mesg \
258                                                         "      Please install the 'dhcpv6' package"
259                                         fi
260                                 ;;
261                                 "")
262                                         if [ "x$explicit_dhcp6" = "xyes" ] ; then
263                                                 if [ "x$HAVE_IPv6" = xyes ] ; then
264                                                         print_mesg err_mesg "DHCP6 client is not available."
265                                                         print_mesg err_mesg "      Please install 'dhcpv6' package'"
266                                                 else
267                                                         print_mesg err_mesg "DHCP6 disabled - no IPv6 support"
268                                                 fi
269                                         fi
270                                 ;;
271                                 *)
272                                         DHCLIENT6=""
273                                         print_mesg err_mesg "DHCP6 client unknown/unsupported: $DHCLIENT6_BIN"
274                                         print_mesg err_mesg "      Please install the 'dhcpv6' package"
275                                 ;;
276                                 esac
277                         ;;
278                         esac
279                 done
280
281                 # exit when not even one of the requested clients is installed
282                 # or the a client was explicitely requested in bootproto
283                 [ "x$HAVE_IPv6" = xyes ] && \
284                 [ "x$explicit_dhcp6" = "xyes" -a "x$DHCLIENT6" = x ] && exit $R_ERROR
285                 [ "x$explicit_dhcp4" = "xyes" -a "x$DHCLIENT"  = x ] && exit $R_ERROR
286                 [ $clients -eq 0 ] && exit $R_ERROR
287         ;;
288 esac
289
290
291 start_dhcp4_dhcpcd() {
292         #
293         # Using netconfig, we can request all options and
294         # netconfig takes care to apply them properlly...
295         #
296         args="--netconfig -L"
297
298         #test "$AUTOIP"                      != "yes" && args="$args -L"
299         test "$DHCLIENT_USE_LAST_LEASE"      = "yes" && args="$args -E"
300         test "$DHCLIENT_DEBUG"               = "yes" && args="$args -d"
301         test "$DHCLIENT_SET_HOSTNAME"        = "yes" && args="$args -HHH"
302         test "$DHCLIENT_SET_DEFAULT_ROUTE"  != "yes" && args="$args -G"
303
304         # send hostname for DDNS?
305         case "$DHCLIENT_HOSTNAME_OPTION" in
306                 AUTO|auto)
307                         unset DHCLIENT_HOSTNAME_OPTION
308                         test -s /etc/HOSTNAME && read -t 1 FQHOSTNAME < /etc/HOSTNAME
309                         FQHOSTNAME=${FQHOSTNAME%%.*} # strip domain
310                         FQHOSTNAME=${FQHOSTNAME%% *} # must not contain spaces, just in case
311                         DHCLIENT_HOSTNAME_OPTION="$FQHOSTNAME"
312                 ;;
313         esac
314
315         # hardcoded in the dhcpcd binary when --netconfig is in use, but ...
316         args="$args -c /etc/sysconfig/network/scripts/dhcpcd-hook"
317
318         # avoid deconfiguration of the interface at startup in nfsroot case (bnc#397484)
319         test "$STARTMODE" = "nfsroot" && args="-p $args"
320
321         DHCLIENT_ARGS="$args"
322
323         # just in case /var is not mounted
324         test -d /var/lib/dhcpcd || mkdir -p /var/lib/dhcpcd && \
325         touch /var/lib/dhcpcd/dhcpcd-$INTERFACE.timestamp || return 1
326
327         # collect args that may contain spaces and write debug...
328         args="$args${DHCLIENT_TIMEOUT:+ -t \"$DHCLIENT_TIMEOUT\"}"
329         args="$args${DHCLIENT_CLIENT_ID:+ -I \"$DHCLIENT_CLIENT_ID\"}"
330         args="$args${DHCLIENT_VENDOR_CLASS_ID:+ -i \"$DHCLIENT_VENDOR_CLASS_ID\"}"
331         args="$args${DHCLIENT_LEASE_TIME:+ -l \"$DHCLIENT_LEASE_TIME\"}"
332         args="$args${DHCLIENT_HOSTNAME_OPTION:+ -h \"$DHCLIENT_HOSTNAME_OPTION\"}"
333         debug "Starting dhcp client: $DHCLIENT_BIN $DHCPCD_USER_OPTIONS $args $INTERFACE"
334
335         # now start dhcpcd
336         $DHCLIENT_BIN $DHCPCD_USER_OPTIONS $DHCLIENT_ARGS \
337                 ${DHCLIENT_TIMEOUT:+-t "$DHCLIENT_TIMEOUT"}                 \
338                 ${DHCLIENT_CLIENT_ID:+-I "$DHCLIENT_CLIENT_ID"}             \
339                 ${DHCLIENT_VENDOR_CLASS_ID:+-i "$DHCLIENT_VENDOR_CLASS_ID"} \
340                 ${DHCLIENT_LEASE_TIME:+-l "$DHCLIENT_LEASE_TIME"}           \
341                 ${DHCLIENT_HOSTNAME_OPTION:+-h "$DHCLIENT_HOSTNAME_OPTION"} \
342                 $INTERFACE </dev/null &>/dev/null &
343 }
344
345 start_dhcp4_dhclient() {
346         #
347         # TODO: filter out statements (e.g. inerface blocks),
348         #       apply DHCLIENT_* variables
349         #
350         local DHCPIFLEASE="/var/lib/dhcp/dhclient.${INTERFACE}.lease"
351         local DHCPIFCONF="/var/lib/dhcp/dhclient.${INTERFACE}.conf"
352         local DHCPIFPID="/var/run/dhclient.${INTERFACE}.pid"
353
354         # don't write copyright info
355         local args="-q" 
356         test "$DHCLIENT_DEBUG" = "yes" && args=""
357
358         # send hostname for DDNS?
359         case "$DHCLIENT_HOSTNAME_OPTION" in
360                 AUTO|auto)
361                         unset DHCLIENT_HOSTNAME_OPTION
362                         test -s /etc/HOSTNAME && read -t 1 FQHOSTNAME < /etc/HOSTNAME
363                         FQHOSTNAME=${FQHOSTNAME%%.*} # strip domain
364                         FQHOSTNAME=${FQHOSTNAME%% *} # must not contain spaces, just in case
365                         DHCLIENT_HOSTNAME_OPTION="$FQHOSTNAME"
366                 ;;
367         esac
368         test -n "$DHCLIENT_HOSTNAME_OPTION" && args="$args -H $DHCLIENT_HOSTNAME_OPTION"
369
370         rm -f "$DHCPIFCONF" && awk '
371                 /#/             { sub("#.*", ""); }
372                 /^[ \t]*$/      { next; }
373                                 { print $0; }
374         ' < /etc/dhclient.conf > "$DHCPIFCONF" || return 1
375
376         debug "Starting dhcp client: $DHCLIENT_BIN $DHCLIENT_USER_OPTIONS -cf "$DHCPIFCONF" -lf "$DHCPIFLEASE" -pf "$DHCPIFPID" $args $INTERFACE"
377         $DHCLIENT_BIN $DHCLIENT_USER_OPTIONS -cf "$DHCPIFCONF" -lf "$DHCPIFLEASE" -pf "$DHCPIFPID" $args $INTERFACE </dev/null &>/dev/null &
378 }
379
380 start_dhcp6_dhcp6c() {
381         DHCP6IFCONF="/var/lib/dhcpv6/dhcp6c.${INTERFACE}.conf"
382         DHCP6IFPID="/var/run/dhcp6c.${INTERFACE}.pid"
383
384         args="--netconfig"
385
386         test "$DHCLIENT_DEBUG" = "yes" && \
387         args="$args -v"
388
389         args="${args} -c ${DHCP6IFCONF}"
390         args="${args} -p ${DHCP6IFPID}"
391
392         # TODO: more features on the todo list ...
393         # TODO: pid file handling ...
394         rm -f "$DHCP6IFCONF" && {
395                 echo "# dhcp6c config generated by ifup-dhcp"
396                 echo "interface $INTERFACE {"
397                 echo "  request domain-name-servers;"
398                 echo "  request domain-search-list;"
399                 echo "};"
400         } > "$DHCP6IFCONF" || return 1
401
402         debug "Starting dhcp client: $DHCLIENT6_BIN $DHCP6C_USER_OPTIONS $args $INTERFACE"
403         $DHCLIENT6_BIN $DHCP6C_USER_OPTIONS $args $INTERFACE </dev/null &>/dev/null &
404 }
405
406 case "$ACTION" in
407         start|renew)
408                 # if we were called at boot time, increase the time startproc waits,
409                 # because the next scripts might rely on a configured network
410                 # test "$MODE" = "boot" && STARTPROC_TIMEOUT=5
411
412                 # a previous dhcpcd daemon could have been killed leaving its pidfile, 
413                 # and we need to remove it before we can start a new one.
414                 case "$DHCLIENT" in
415                 (dhcpcd)
416                         if [ -s /var/run/dhcpcd-$INTERFACE.pid ]; then
417                                 p=$(</var/run/dhcpcd-$INTERFACE.pid)
418                                 if [ "x$p" != x -a $((p)) -gt 0 ] ; then
419                                         cmdline="/proc/$p/cmdline"
420                                         [ -r "$cmdline" ] && \
421                                         grep -q "^$DHCLIENT_BIN" "$cmdline" || {
422                                                 message_if_not_run_from_rc \
423                                                 "Removing stale pid file /var/run/dhcpcd-$INTERFACE.pid"
424                                                 rm -f /var/run/dhcpcd-$INTERFACE.pid
425                                         }
426                                 fi
427                         fi
428                 ;;
429                 dhclient)
430                         if [ -s /var/run/dhclient.$INTERFACE.pid ]; then
431                                 p=$(</var/run/dhclient.$INTERFACE.pid)
432                                 if [ "x$p" != x -a $((p)) -gt 0 ] ; then
433                                         cmdline="/proc/$p/cmdline"
434                                         [ -r "$cmdline" ] && \
435                                         grep -q "^$DHCLIENT_BIN" "$cmdline" || {
436                                                 message_if_not_run_from_rc \
437                                                 "Removing stale pid file /var/run/dhclient.$INTERFACE.pid"
438                                                 rm -f /var/run/dhclient.$INTERFACE.pid
439                                         }
440                                 fi
441                         fi
442                 ;;
443                 esac
444                 case "$DHCLIENT6" in
445                 (dhcp6c)
446                         : # TODO: the new 1.0.20 version seems to write one...
447                 ;;
448                 esac
449
450                 # the following code block, is only relevant if DHCLIENT_PRIMARY_DEVICE is
451                 # empty. it basically sets DHCLIENT_PRIMARY_DEVICE based on the informationen 
452                 # that is provided by the cached config data in a way that a user-defined  
453                 # DHCLIENT_PRIMARY_DEVICE remains untouched.
454
455                 if [ -z "$DHCLIENT_PRIMARY_DEVICE" ]; then
456
457                         # read cached config data into PRIMARY_FROM_CACHE
458                         PRIMARY_FROM_CACHE="`grep_cached_config_data primary yes`"
459
460                         if [ -z "$PRIMARY_FROM_CACHE" ]; then
461                                 # no primary interface up-> we're the primary interface
462                                 DHCLIENT_PRIMARY_DEVICE='yes'
463
464                                 # save this fact to cached config data          
465                                 write_cached_config_data primary yes $INTERFACE
466                                 commit_cached_config_data $INTERFACE
467                         else
468                                 # primary interface already up -> DHCLIENT_PRIMARY_DEVICE='no'
469                                 if [ "${PRIMARY_FROM_CACHE% }" = $INTERFACE ]; then
470                                         # special case for ifrenew:
471                                         # we are the primary interface which is up 
472                                         DHCLIENT_PRIMARY_DEVICE='yes'
473                                 else
474                                         DHCLIENT_PRIMARY_DEVICE='no'
475                                 fi
476                         fi
477
478                 fi              
479
480                 DHCP4_STATUS=$R_NOTCONFIGURED
481                 DHCP6_STATUS=$R_NOTCONFIGURED
482                 DHCP4_STARTED="no"
483                 DHCP6_STARTED="no"
484                 case "$ACTION" in
485                 (start)
486                         for BOOTPROTO in ${BOOTPROTOS[@]} ; do
487                                 case "$BOOTPROTO" in
488                                 (dhcp4)
489                                         # reset dhcp4 status
490                                         DHCP4_STATUS=""
491                                         #if ( checkproc $DHCLIENT_BIN || [ "$DHCLIENT_PRIMARY_DEVICE" = no ] ) ; then
492                                                 # let's first test if the running dhcpcd actually runs on this
493                                                 # interface, because then we don't want to start another one:
494                                                 if dhcpc4_on_iface -q; then
495                                                         DHCP4_STATUS=$R_DHCP_BG
496                                                         if test "$RUN_FROM_RC" = yes; then
497                                                                 print_mesg mesg "DHCP4 client is already running"
498                                                         else
499                                                                 mesg "DHCP4 client is already running on $INTERFACE"
500                                                         fi
501                                                         while read a b c d e f g h i; do
502                                                                 case "$d" in
503                                                                 169.254.*) continue ;;
504                                                                 esac
505                                                                 print_mesg mesg "IP address: $d"
506                                                                 DHCP4_STATUS=$R_SUCCESS
507                                                         done < <(ip -o -4 addr show $INTERFACE)
508                                                 fi
509                                         #fi
510                                 ;;
511                                 (dhcp6)
512                                         # reset dhcp6 status
513                                         DHCP6_STATUS=""
514                                         #if ( checkproc $DHCLIENT6_BIN || [ "$DHCLIENT_PRIMARY_DEVICE" = no ] ) ; then
515                                                 # let's first test if the running dhcp6c actually runs on this
516                                                 # interface, because then we don't want to start another one:
517                                                 if dhcpc6_on_iface -q; then
518                                                         DHCP6_STATUS=$R_DHCP_BG
519                                                         if test "$RUN_FROM_RC" = yes; then
520                                                                 print_mesg mesg "DHCP6 client is already running"
521                                                         else
522                                                                 mesg "DHCP6 client is already running on $INTERFACE"
523                                                         fi
524                                                         while read a b c d rest; do
525                                                                 case "$d" in
526                                                                 fe80::*) continue ;;
527                                                                 esac
528                                                                 print_mesg mesg "IP address: $d"
529                                                                 DHCP6_STATUS=$R_SUCCESS
530                                                         done < <(ip -o -6 addr show $INTERFACE)
531                                                 fi
532                                         #fi
533                                 ;;
534                                 esac
535                         done
536                 ;;
537                 (renew)
538                         for BOOTPROTO in ${BOOTPROTOS[@]} ; do
539                                 case "$BOOTPROTO" in
540                                 (dhcp4)
541                                         # reset dhcp4 status
542                                         DHCP4_STATUS=""
543                                         for i in `dhcpc4_on_iface`; do
544                                                 kill -TERM $i &>/dev/null
545                                         done
546                                         sleep 1
547                                 ;;
548                                 (dhcp6)
549                                         # reset dhcp6 status
550                                         DHCP6_STATUS=""
551                                         for i in `dhcpc6_on_iface`; do
552                                                 kill -TERM $i &>/dev/null
553                                         done
554                                         sleep 1
555                                 ;;
556                                 esac
557                         done
558                 ;;
559                 esac
560
561                 # start requested dhcp clients...
562                 if [ -z "$DHCP4_STATUS" -o -z "$DHCP6_STATUS" ] ; then
563
564                         # there is maybe already a dhcp client running (or scheduled). We probably
565                         # don't want to set another default gateway and so on. Let's clear some
566                         # variables and source the ifcfg-$CONFIG again -- unless
567                         # DHCLIENT_PRIMARY_DEVICE is set to "yes".
568                         if [ "$DHCLIENT_PRIMARY_DEVICE" != yes ]; then 
569                                 unset DHCLIENT_SET_HOSTNAME \
570                                       DHCLIENT_SET_DEFAULT_ROUTE
571
572                                 test -f ./ifcfg-$CONFIG && . ./ifcfg-$CONFIG
573                         fi
574
575                         # remember the hostname to handle a change later
576                         write_cached_config_data hostname "`hostname 2>/dev/null`" $INTERFACE
577                         commit_cached_config_data                                  $INTERFACE
578
579                         debug "Activating interface $INTERFACE"
580                         if ! is_iface_up $INTERFACE ; then
581                                 ip link set $INTERFACE up ${MTU:+mtu $MTU} \
582                                    ${LLADDR:+address $LLADDR} $LINK_OPTIONS
583                                 for ((count=200; count >= 0; count--)) ; do
584                                         is_iface_up $INTERFACE && break
585                                         usleep 25000
586                                 done
587
588                                 # (optionally) wait until a device is really configured
589                                 sleep ${DHCLIENT_SLEEP:-0}
590                         fi
591
592                         MESSAGE=""
593                         for BOOTPROTO in ${BOOTPROTOS[@]} ; do
594                                 case "$BOOTPROTO" in
595                                 (dhcp4) test -n "$DHCP4_STATUS" || MESSAGE="$MESSAGE $BOOTPROTO" ;;
596                                 (dhcp6) test -n "$DHCP6_STATUS" || MESSAGE="$MESSAGE $BOOTPROTO" ;;
597                                 esac
598                         done
599                         MESSAGE=$(echo ${MESSAGE} | awk '{print toupper($0);}')
600                         if [ "$RUN_FROM_RC" = "yes" ]; then
601                                 print_mesg mesg_n "Starting ${MESSAGE// /+} client"
602                         else
603                                 mesg_n "Starting ${MESSAGE// /+} client on $INTERFACE"
604                         fi
605
606                         for BOOTPROTO in ${BOOTPROTOS[@]} ; do
607                                 case "$BOOTPROTO" in
608                                 (dhcp4)
609                                         case "$DHCLIENT" in
610                                         (dhcpcd)
611                                                 test -n "$DHCP4_STATUS" || {
612                                                         start_dhcp4_dhcpcd && {
613                                                                 DHCP4_STARTED="yes"
614                                                                 write_cached_config_data dhcp4_client $DHCLIENT  $INTERFACE
615                                                                 write_cached_config_data dhcp4_state  started    $INTERFACE
616                                                                 commit_cached_config_data                        $INTERFACE
617                                                         } || DHCP4_STATUS=$?
618                                                 }
619                                         ;;
620                                         (dhclient)
621                                                 test -n "$DHCP4_STATUS" || {
622                                                         start_dhcp4_dhclient && {
623                                                                 DHCP4_STARTED="yes"
624                                                                 write_cached_config_data dhcp4_client $DHCLIENT  $INTERFACE
625                                                                 write_cached_config_data dhcp4_state  started    $INTERFACE
626                                                                 commit_cached_config_data                        $INTERFACE
627                                                         } || DHCP4_STATUS=$?
628                                                 }
629                                         ;;
630                                         esac
631                                 ;;
632                                 (dhcp6)
633                                         case "$DHCLIENT6" in
634                                         (dhcp6c)
635                                                 test -n "$DHCP6_STATUS" || {
636                                                         start_dhcp6_dhcp6c && {
637                                                                 DHCP6_STARTED="yes"
638                                                         } || DHCP6_STATUS=$?
639                                                 }
640                                         ;;
641                                         #(dhclient)
642                                         #       test -n "$DHCP6_STATUS" || {
643                                         #               start_dhcp6_dhclient
644                                         #               DHCP6_STARTED="yes"
645                                         #       }
646                                         #;;
647                                         esac
648                                 ;;
649                                 esac
650                         done
651
652                         #
653                         # in case we've started at least one client, wait the specified
654                         # time until the dhcp client has done its job and show the results.
655                         #
656                         DHCP4_MESSAGE=''
657                         DHCP6_MESSAGE=''
658
659                         typeset -i wusleep=100000
660                         typeset -i wab_max=${DHCLIENT_WAIT_AT_BOOT:-15};
661                         let wab_max\*=10
662                         for ((wab_cnt=0; wab_cnt<=wab_max; wab_cnt++)); do
663                                 for BOOTPROTO in ${BOOTPROTOS[@]} ; do
664                                         case "$BOOTPROTO" in
665                                         (dhcp4)
666                                                 case "$DHCLIENT" in
667                                                 (dhcpcd)
668                                                         stamp=/var/lib/dhcpcd/dhcpcd-$INTERFACE.timestamp
669                                                         info=/var/lib/dhcpcd/dhcpcd-$INTERFACE.info
670
671                                                         if ! dhcpc4_on_iface -q ; then
672                                                                 ((wab_cnt== 0 || wab_cnt==10)) && message_n .\ .\ 
673                                                                 DHCP4_MESSAGE="DHCP4 client NOT running"
674                                                                 DHCP4_STATUS=$R_NOTRUNNING
675                                                                 continue
676                                                         fi
677                                                         [ -n "$DHCP4_STATUS" ] && continue
678
679                                                         state=`read_cached_config_data dhcp4_state $INTERFACE`
680                                                         if [ "x$state" = "xcomplete" -a -e $info -a ! $info -ot $stamp ]; then
681                                                                 IP='' ; NM='' ; HN=''
682                                                                 while read line ; do
683                                                                         case "$line" in
684                                                                         IPADDR=*)   eval "${line/IPADDR=/IP=}"   ;;
685                                                                         NETMASK=*)  eval "${line/NETMASK=/NM=}"  ;;
686                                                                         HOSTNAME=*) eval "${line/HOSTNAME=/HN=}" ;;
687                                                                         esac
688                                                                 done < $info
689                                                                 if test -n "$IP" ; then
690                                                                         DHCP4_MESSAGE="IP address: $IP"
691                                                                         NL=$(mask2pfxlen $NM)
692                                                                         if test -n "$NM" ; then
693                                                                                 DHCP4_MESSAGE="$DHCP4_MESSAGE/$NL"
694                                                                         fi
695                                                                         if test -n "$HN" ; then
696                                                                                 DHCP4_MESSAGE="$DHCP4_MESSAGE ($HN)"
697                                                                         fi
698                                                                 fi
699                                                                 DHCP4_STATUS=$R_SUCCESS
700                                                         fi
701                                                 ;;
702                                                 (dhclient)
703                                                         # TODO: parse the lease?!
704                                                         if ! dhcpc4_on_iface -q ; then
705                                                                 ((wab_cnt== 0 || wab_cnt==10)) && message_n .\ .\ 
706                                                                 DHCP4_MESSAGE="DHCP4 client NOT running"
707                                                                 DHCP4_STATUS=$R_NOTRUNNING
708                                                                 continue
709                                                         fi
710                                                         [ -n "$DHCP4_STATUS" ] && continue
711
712                                                         lease="/var/lib/dhcp/dhclient.${INTERFACE}.lease"
713                                                         config="/var/lib/dhcp/dhclient.${INTERFACE}.conf"
714                                                         state=`read_cached_config_data dhcp4_state $INTERFACE`
715                                                         if [ "x$state" = "xcomplete" -a -e "$lease" -a "$lease" -nt "$config" ] ; then
716                                                                 while read a b c d e f g h i ; do
717                                                                         case "$d" in
718                                                                         169.254.*) continue ;;
719                                                                         esac
720                                                                         if grep -q "${d%/*}" "$lease" &>/dev/null ; then
721                                                                                 DHCP4_MESSAGE="IP address: $d"
722                                                                         fi
723                                                                 done < <(ip -o -4 addr show $INTERFACE)
724                                                                 DHCP4_STATUS=$R_SUCCESS
725                                                         fi
726                                                 ;;
727                                                 esac
728                                         ;;
729                                         (dhcp6)
730                                                 if ! dhcpc6_on_iface -q ; then
731                                                         ((wab_cnt== 0 || wab_cnt==10)) && message_n .\ .\ 
732                                                         DHCP6_MESSAGE="DHCP6 client NOT running"
733                                                         DHCP6_STATUS=$R_NOTRUNNING
734                                                         continue
735                                                 fi
736                                                 [ -n "$DHCP6_STATUS" ] && continue
737
738                                                 case "$DHCLIENT6" in
739                                                 (dhcp6c)
740                                                         while read a b c d rest; do
741                                                                 config="/var/lib/dhcpv6/dhcp6c.${INTERFACE}.conf"
742                                                                 leases="/var/lib/dhcpv6/client6.leases*"
743                                                                 leases=$(grep -sl "^lease[ \t]\+${d}" $leases 2>/dev/null)
744                                                                 for lease in ${leases} ; do
745                                                                         if [ "$lease" -nt "$config" ] ; then
746                                                                                 DHCP6_MESSAGE="IP address: $d"
747                                                                                 DHCP6_STATUS=$R_SUCCESS
748                                                                                 break 2
749                                                                         fi
750                                                                 done
751                                                         done < <(ip -o -6 addr show $INTERFACE)
752                                                 ;;
753                                                 esac
754                                         ;;
755                                         esac
756                                 done
757                                 if [ -z "$DHCP4_STATUS" -o -z "$DHCP6_STATUS" ] ; then
758                                         ((wab_cnt % 20 == 1)) && message_n .\ 
759                                         usleep $wusleep
760                                 else
761                                         # ok, we have status from both clients now => done
762                                         break
763                                 fi
764                         done
765                         message " "
766
767                         [ "$DHCP4_STARTED" = yes -a -z "$DHCP4_STATUS" ] && DHCP4_STATUS=$R_DHCP_BG
768                         [ "$DHCP6_STARTED" = yes -a -z "$DHCP6_STATUS" ] && DHCP6_STATUS=$R_DHCP_BG
769
770                         if test -n "$DHCP4_MESSAGE" ; then
771                                 message "`printf "    %-9s $DHCP4_MESSAGE" $INTERFACE`"
772                         elif [ $DHCP4_STATUS = $R_DHCP_BG ] ; then
773                                 message "`printf "    %-9s DHCP4 continues in background" $INTERFACE`"
774                         fi
775                         if test -n "$DHCP6_MESSAGE" ; then
776                                 message "`printf "    %-9s $DHCP6_MESSAGE" $INTERFACE`"
777                         elif [ $DHCP6_STATUS = $R_DHCP_BG ] ; then
778                                 message "`printf "    %-9s DHCP6 continues in background" $INTERFACE`"
779                         fi
780                 fi
781                 debug "DHCP4(required=$explicit_dhcp4) STARTED=$DHCP4_STARTED STATUS=$DHCP4_STATUS"
782                 debug "DHCP6(required=$explicit_dhcp6) STARTED=$DHCP6_STARTED STATUS=$DHCP6_STATUS"
783                 [ -z "$DHCP4_STATUS" ] && DHCP4_STATUS=$R_ERROR
784                 [ -z "$DHCP6_STATUS" ] && DHCP6_STATUS=$R_ERROR
785
786                 case "${explicit_dhcp4}_${explicit_dhcp6}" in
787                 (yes_yes)       # BOOTPROTO=dhcp4+dhcp6     (need both to report success)
788                         if   [ $DHCP4_STATUS = $R_SUCCESS        -a $DHCP6_STATUS = $R_SUCCESS    ] ; then
789                                 exit $R_SUCCESS
790                         elif [ $DHCP4_STATUS = $R_DHCP_BG        -o $DHCP6_STATUS = $R_DHCP_BG    ] ; then
791                                 exit $R_DHCP_BG
792                         elif [ $DHCP4_STATUS != $R_NOTCONFIGURED ] ; then
793                                 exit $DHCP4_STATUS
794                         elif [ $DHCP6_STATUS != $R_NOTCONFIGURED ] ; then
795                                 exit $DHCP6_STATUS
796                         fi
797                 ;;
798                 (no_no)         # BOOTPROTO=dhcp            (one is sufficient)
799                         if   [ $DHCP4_STATUS = $R_SUCCESS        -o $DHCP6_STATUS = $R_SUCCESS    ] ; then
800                                 exit $R_SUCCESS
801                         elif [ $DHCP4_STATUS = $R_DHCP_BG        -o $DHCP6_STATUS = $R_DHCP_BG    ] ; then
802                                 exit $R_DHCP_BG
803                         elif [ $DHCP4_STATUS != $R_NOTCONFIGURED ] ; then
804                                 exit $DHCP4_STATUS
805                         elif [ $DHCP6_STATUS != $R_NOTCONFIGURED ] ; then
806                                 exit $DHCP6_STATUS
807                         fi
808                 ;;
809                 (yes_no)        # BOOTPROTO=dhcp4
810                         exit $DHCP4_STATUS
811                 ;;
812                 (no_yes)        # BOOTPROTO=dhcp6
813                         exit $DHCP6_STATUS
814                 ;;
815                 esac
816                 exit $R_ERROR
817
818         ;;
819         stop)
820                 ALL_INTERFACES=()
821                 STOPPED_IFACES=()
822
823                 if [ "$INTERFACE" != all ]; then
824                         ALL_INTERFACES=($INTERFACE)
825
826                         dhcpc4_pids=""
827                         dhcpc6_pids=""
828                         dhcpc4_signal="-TERM"
829                         dhcpc6_signal="-TERM"
830
831                         debug "Shutting down dhcp clients on $INTERFACE"
832
833                         # first try the configured way
834                         for BOOTPROTO in ${BOOTPROTOS[@]} ; do
835                                 case "$BOOTPROTO" in
836                                 (dhcp4)
837                                         dhcpc4_pids="`dhcpc4_on_iface`"
838
839                                         case $DHCLIENT in
840                                         (dhcpcd)
841                                                 DHCPIFLEASE="/var/lib/dhcpcd/dhcpcd-$INTERFACE.info"
842                                                 DHCPIFPID="/var/run/dhcpcd-$INTERFACE.pid"
843
844                                                 if test "$STARTMODE" = "nfsroot" ;
845                                                 then
846                                                         dhcpc4_signal="-KILL"
847                                                 elif test "$DHCLIENT_RELEASE_BEFORE_QUIT" = "yes" ;
848                                                 then
849                                                         $DHCLIENT_BIN --release \
850                                                                 $INTERFACE </dev/null &>/dev/null
851                                                 fi
852                                         ;;
853                                         (dhclient)
854                                                 DHCPIFLEASE="/var/lib/dhcp/dhclient.${INTERFACE}.lease"
855                                                 DHCPIFPID="/var/run/dhclient.${INTERFACE}.pid"
856
857                                                 if test "$STARTMODE" = "nfsroot" ;
858                                                 then
859                                                         dhcpc4_signal="-KILL"
860                                                 elif test "$DHCLIENT_RELEASE_BEFORE_QUIT" = "yes" ;
861                                                 then
862                                                         $DHCLIENT_BIN -r \
863                                                                 -cf /dev/null \
864                                                                 -lf "$DHCPIFLEASE" \
865                                                                 -pf "$DHCPIFPID" \
866                                                                 $INTERFACE </dev/null &>/dev/null
867                                                 fi
868                                         ;;
869                                         esac
870
871                                 ;;
872                                 (dhcp6)
873                                         dhcpc6_pids="`dhcpc6_on_iface`"
874
875                                         case $DHCLIENT6 in
876                                         (dhcp6c)
877                                                 DHCP6IFCONF="/var/lib/dhcpv6/dhcp6c.${INTERFACE}.conf"
878                                                 DHCP6IFPID="/var/run/dhcp6c.${INTERFACE}.pid"
879
880                                                 if test "$STARTMODE" = "nfsroot" ;
881                                                 then
882                                                         dhcpc6_signal="-KILL"
883                                                 elif test "$DHCLIENT6_RELEASE_BEFORE_QUIT" = "yes" ;
884                                                 then
885                                                         # dhcp6c daemon needs to get killed or
886                                                         # dhcp6c -r fails to bind the interface
887                                                         for i in $dhcpc6_pids; do
888                                                                 kill $dhcpc6_signal $i &>/dev/null
889                                                         done
890                                                         for i in $dhcpc6_pids; do
891                                                                 for ((wait=0; wait<=20; wait++)); do
892                                                                         if test -d /proc/$i ; then
893                                                                                 usleep 300000
894                                                                         else
895                                                                                 continue 2
896                                                                         fi
897                                                                 done
898                                                         done
899
900                                                         # then release the lease but stay in foreground
901                                                         $DHCLIENT6_BIN -f -r all \
902                                                                 -c /dev/null \
903                                                                 -p "$DHCP6IFPID" \
904                                                                 $INTERFACE </dev/null &>/dev/null
905                                                 fi
906                                         ;;
907                                         (dhclient6)
908                                                 DHCP6IFLEASE="/var/lib/dhcp/dhclient6.${INTERFACE}.lease"
909                                                 DHCP6IFPID="/var/run/dhclient6.${INTERFACE}.pid"
910
911                                                 if test "$STARTMODE" = "nfsroot" ;
912                                                 then
913                                                         dhcpc6_signal="-KILL"
914                                                 elif test "$DHCLIENT6_RELEASE_BEFORE_QUIT" = "yes" ;
915                                                 then
916                                                         $DHCLIENT_BIN6 -6 -r \
917                                                                 -cf /dev/null \
918                                                                 -lf "$DHCP6IFLEASE" \
919                                                                 -pf "$DHCP6IFPID" \
920                                                                 $INTERFACE
921                                                 fi
922                                         ;;
923                                         esac
924
925                                 ;;
926                                 esac
927                         done
928
929                         # same game again...
930                         for BOOTPROTO in ${BOOTPROTOS[@]} ; do
931                                 case "$BOOTPROTO" in
932                                 (dhcp4)
933                                         # send termination signal
934                                         for i in $dhcpc4_pids; do
935                                                 kill $dhcpc4_signal $i &>/dev/null
936                                         done
937
938                                         # wait until the processes are gone
939                                         for i in $dhcpc4_pids; do
940                                                 for ((wait=0; wait<=20; wait++)); do
941                                                         if test -d /proc/$i ; then
942                                                                 usleep 300000
943                                                         else
944                                                                 continue 2
945                                                         fi
946                                                         if [ $wait -eq 20 ]; then
947                                                                 debug "process $i still not dead, sending SIGKILL"
948                                                                 kill -KILL $i &>/dev/null
949                                                         fi
950                                                 done
951                                         done
952
953                                         # remove old lease file and pid when they still exist
954                                         if test "$DHCLIENT_RELEASE_BEFORE_QUIT" = "yes" ; then
955                                                 rm -f "$DHCPIFLEASE"
956                                         fi
957                                         rm -f "$DHCPIFPID"
958                                 ;;
959                                 (dhcp6)
960                                         # send termination signal
961                                         for i in $dhcpc6_pids; do
962                                                 kill $dhcpc6_signal $i &>/dev/null
963                                         done
964
965                                         # wait until the processes are gone
966                                         for i in $dhcpc6_pids; do
967                                                 for ((wait=0; wait<=20; wait++)); do
968                                                         if test -d /proc/$i ; then
969                                                                 usleep 300000
970                                                         else
971                                                                 continue 2
972                                                         fi
973                                                         if [ $wait -eq 20 ]; then
974                                                                 debug "process $i still not dead, sending SIGKILL"
975                                                                 kill -KILL $i &>/dev/null
976                                                         fi
977                                                 done
978                                         done
979
980                                         # remove old lease file and pid when they still exist
981                                         if test "$DHCLIENT6_RELEASE_BEFORE_QUIT" = "yes" ; then
982                                                 rm -f "$DHCP6IFLEASE"
983                                         fi
984                                         rm -f "$DHCP6IFPID"
985                                 ;;
986                                 esac
987                         done
988                 else
989                         debug "Shutting down dhcp clients on all interfaces"
990                         for i in `ls -1 /sys/class/net 2>/dev/null` ; do
991                                 test -d "/sys/class/net/$i" || continue
992                                 ALL_INTERFACES=(${ALL_INTERFACES[@]} $i)
993                         done
994                 fi
995
996                 STATUS=$R_SUCCESS
997                 # now verify it & "kill them all"
998                 # catching also INTERFACE=all case
999                 for INTERFACE in ${ALL_INTERFACES[@]} ; do
1000                         # Read temporary startmode and use kill -9 to stop
1001                         tmp_startmode=`read_cached_config_data startmode $INTERFACE`
1002                         [ -n "$tmp_startmode" ] && STARTMODE="$tmp_startmode"
1003
1004                         # try to catch also config changes
1005                         dhcpcd_on_device=`any_dhcpc_on_iface`
1006
1007                         if test -n "$dhcpcd_on_device" ; then
1008                                 # send termination signal
1009                                 test "$STARTMODE" = "nfsroot" && \
1010                                         USE_SIGNAL="-KILL" || \
1011                                         USE_SIGNAL="-TERM"
1012
1013                                 for i in $dhcpcd_on_device; do
1014                                         kill $USE_SIGNAL $i &>/dev/null
1015                                 done
1016
1017                                 # wait until the processes are gone
1018                                 for i in $dhcpcd_on_device; do
1019                                         for ((wait=0; wait<=10; wait++)); do
1020                                                 if test -d /proc/$i ; then
1021                                                         usleep 300000
1022                                                 else
1023                                                         continue 2
1024                                                 fi
1025                                                 if [ $wait -eq 10 ]; then
1026                                                         debug "process $i still not dead, sending SIGKILL"
1027                                                         kill -KILL $i &>/dev/null
1028                                                 fi
1029                                         done
1030                                 done
1031
1032                                 # double check & set status
1033                                 for i in $dhcpcd_on_device; do
1034                                         kill -0 $i 2>/dev/null && STATUS=$R_ERROR
1035                                 done
1036                         fi
1037
1038                         # Hmm...:
1039                         #if [ $STATUS -eq $R_SUCCESS ] ; then
1040
1041                         # delete primary flag from cache file if needed
1042                         delete_from_cached_config_data primary yes  $INTERFACE
1043                         delete_from_cached_config_data 'dhcp4_*' '' $INTERFACE
1044                         delete_from_cached_config_data 'dhcp6_*' '' $INTERFACE
1045                         commit_cached_config_data                   $INTERFACE
1046
1047                         # This is useful for pcmcia interfaces... before the modules can be
1048                         # unloaded, the device must be unused.
1049                         if [ "$STARTMODE" != "nfsroot" -a "$DHCLIENT_SET_DOWN_LINK" = yes ] ; then
1050                                 if [ -d /sys/class/net/$INTERFACE ] ; then
1051                                         ip link set down dev $INTERFACE
1052                                 fi
1053                         fi
1054
1055                         #fi
1056                 done
1057
1058                 exit $STATUS
1059         ;;
1060         status)
1061                 if ifup_on_iface ; then
1062                         print_mesg mesg ". . . is just beeing set up"
1063                         exit $R_DHCP_BG
1064                 fi
1065
1066                 DHCP4_STATUS=$R_NOTCONFIGURED
1067                 DHCP6_STATUS=$R_NOTCONFIGURED
1068                 for BOOTPROTO in ${BOOTPROTOS[@]} ; do
1069                         case "$BOOTPROTO" in
1070                         (dhcp4)
1071                                 if dhcpc4_on_iface -q; then
1072                                         print_mesg mesg "DHCP4 client ($DHCLIENT) is running"
1073                                         case "$DHCLIENT" in
1074                                         (dhcpcd)
1075                                                 stamp=/var/lib/dhcpcd/dhcpcd-$INTERFACE.timestamp
1076                                                 info=/var/lib/dhcpcd/dhcpcd-$INTERFACE.info
1077
1078                                                 state=`read_cached_config_data dhcp4_state $INTERFACE`
1079                                                 if [ "x$state" = "xcomplete" -a \
1080                                                      \( -e $info -a ! $info -ot $stamp \) -a -n \
1081                                                      "`ip -o -f inet addr show $INTERFACE`" ]; then
1082                                                         while read line ; do
1083                                                                 case "$line" in
1084                                                                 IPADDR=*)   eval "${line/IPADDR=/IP=}"   ;;
1085                                                                 NETMASK=*)  eval "${line/NETMASK=/NM=}"  ;;
1086                                                                 HOSTNAME=*) eval "${line/HOSTNAME=/HN=}" ;;
1087                                                                 esac
1088                                                         done < $info
1089                                                         if test -n "$IP" ; then
1090                                                                 DHCP4_MESSAGE="IP address: $IP"
1091                                                                 NL=$(mask2pfxlen $NM)
1092                                                                 if test -n "$NM" ; then
1093                                                                         DHCP4_MESSAGE="$DHCP4_MESSAGE/$NL"
1094                                                                 fi
1095                                                                 if test -n "$HN" ; then
1096                                                                         DHCP4_MESSAGE="$DHCP4_MESSAGE ($HN)"
1097                                                                 fi
1098                                                                 print_mesg mesg "$DHCP4_MESSAGE"
1099                                                         fi
1100                                                         DHCP4_STATUS=$R_SUCCESS
1101                                                 else
1102                                                         print_mesg mesg ". . . but is still waiting for data"
1103                                                         DHCP4_STATUS=$R_DHCP_BG
1104                                                 fi
1105                                         ;;
1106                                         dhclient)
1107                                                 state=`read_cached_config_data dhcp4_state $INTERFACE`
1108                                                 if [ "x$state" = "xcomplete" -a \
1109                                                      -n "`ip -o -f inet addr show $INTERFACE`" ]; then
1110                                                         :
1111                                                         DHCP4_STATUS=$R_SUCCESS
1112                                                 else
1113                                                         print_mesg mesg ". . . but is still waiting for data"
1114                                                         DHCP4_STATUS=$R_DHCP_BG
1115                                                 fi
1116                                         ;;
1117                                         esac
1118                                 else
1119                                         print_mesg mesg "DHCP4 client NOT running"
1120                                         DHCP4_STATUS=$R_NOTRUNNING
1121                                 fi
1122                         ;;
1123                         (dhcp6)
1124                                 if dhcpc6_on_iface -q; then
1125                                         print_mesg mesg "DHCP6 client ($DHCLIENT6) is running"
1126                                         DHCP6_STATUS=$R_DHCP_BG
1127                                         DHCP6_MESSAGE=''
1128                                         while read a b c d rest; do
1129                                                 config="/var/lib/dhcpv6/dhcp6c.${INTERFACE}.conf"
1130                                                 leases="/var/lib/dhcpv6/client6.leases*"
1131                                                 leases=$(grep -sl "^lease[ \t]\+${d}" $leases 2>/dev/null)
1132                                                 for lease in ${leases} ; do
1133                                                         if [ $lease -nt $config ] ; then
1134                                                                 DHCP6_MESSAGE="IP address: $d"
1135                                                                 DHCP6_STATUS=$R_SUCCESS
1136                                                                 break 2
1137                                                         fi
1138                                                 done
1139                                         done < <(ip -o -6 addr show $INTERFACE)
1140                                         if [ -n "$DHCP6_MESSAGE" ] ; then
1141                                                 print_mesg mesg "$DHCP6_MESSAGE"
1142                                         else
1143                                                 print_mesg mesg ". . . but is still waiting for data"
1144                                         fi
1145                                 else
1146                                         print_mesg mesg "DHCP6 client NOT running"
1147                                         DHCP6_STATUS=$R_NOTRUNNING
1148                                 fi
1149                         ;;
1150                         esac
1151                 done
1152
1153                 debug "DHCP4(required=$explicit_dhcp4) STATUS=$DHCP4_STATUS"
1154                 debug "DHCP6(required=$explicit_dhcp6) STATUS=$DHCP6_STATUS"
1155
1156                 case "${explicit_dhcp4}_${explicit_dhcp6}" in
1157                 (yes_yes)       # BOOTPROTO=dhcp4+dhcp6     (need both to report success)
1158                         if   [ $DHCP4_STATUS = $R_SUCCESS        -a $DHCP6_STATUS = $R_SUCCESS    ] ; then
1159                                 exit $R_SUCCESS
1160                         elif [ $DHCP4_STATUS = $R_DHCP_BG        -o $DHCP6_STATUS = $R_DHCP_BG    ] ; then
1161                                 exit $R_DHCP_BG
1162                         elif [ $DHCP4_STATUS != $R_NOTCONFIGURED ] ; then
1163                                 exit $DHCP4_STATUS
1164                         elif [ $DHCP6_STATUS != $R_NOTCONFIGURED ] ; then
1165                                 exit $DHCP6_STATUS
1166                         fi
1167                 ;;
1168                 (no_no)         # BOOTPROTO=dhcp            (one is sufficient)
1169                         if   [ $DHCP4_STATUS = $R_SUCCESS        -o $DHCP6_STATUS = $R_SUCCESS    ] ; then
1170                                 exit $R_SUCCESS
1171                         elif [ $DHCP4_STATUS = $R_DHCP_BG        -o $DHCP6_STATUS = $R_DHCP_BG    ] ; then
1172                                 exit $R_DHCP_BG
1173                         elif [ $DHCP4_STATUS != $R_NOTCONFIGURED ] ; then
1174                                 exit $DHCP4_STATUS
1175                         elif [ $DHCP6_STATUS != $R_NOTCONFIGURED ] ; then
1176                                 exit $DHCP6_STATUS
1177                         fi
1178                 ;;
1179                 (yes_no)        # BOOTPROTO=dhcp4
1180                         exit $DHCP4_STATUS
1181                 ;;
1182                 (no_yes)        # BOOTPROTO=dhcp6
1183                         exit $DHCP6_STATUS
1184                 ;;
1185                 esac
1186                 exit $R_ERROR
1187         ;;
1188 esac