# dhclient net.eth0 shutdown problem

## Col.Kurtz

I'm trying to get dhclient working 100% the way I'd like it to work.

Everything is working just fine except for when I shut it down, I end up with an operation timed out.

My /etc/dhcp/dhclient.conf is in good working order.

My /etc/conf.d/net is as follows (pretaining to dhcp):

 *Quote:*   

> # For DHCP set iface_eth? to "dhcp"
> 
> # For passing options to dhclient use dhclient_eth?
> 
> #
> ...

 

The problem I believe is located in the net.eth0 script, in the "stop" section. I went throught the file and changed every instance of "dhcpcd" and replaced it with "dhclient". The "stop" section for dhcp is as follows: 

 *Quote:*   

> if [ "${iface_IFACE}" = "dhcp" ]
> 
> 	then
> 
> 		local count=0
> ...

 

Something in there has to be causing my problem.

Everything works just fine if I do it all on the command line.

net.eth0 stop: dhclient -r -cf /etc/dhcp/dhclient.conf eth0

Works, no timeout, and it releases the address.

Any pointers? I don't understand most of the stuff in the "stop" section (or anything in scripts, yet).

Thanks,

Col.

----------

## mattschwartz

I'm not familiar with dhclient, but I would try checking its parameters first (dhclient --help or something like that at the prompt).  dhclient and dhcpd may not be identical, although I used to have a system where dhclient was only a link to dhcpd.  Your dhclient may be something else, so check you're passing the correct parameters in the stop portion of the script.  Good luck.

----------

## Col.Kurtz

I "think" I figured it out.

Though my intelligence when in comes to scripting language is sucky, I think I can see whats going on in the stop section of net.eth0.

Since it was made for the dhcpcd client, that might explain it.

Since I come from the LinuxFromScratch world, my first dhcp client package I played with was dhcpcd. And no matter what, it would never shutdown right. It usually hung. Every version. Even my Mandrake system did it.

After tinkering with it by trial and error, I removed the "&" from this part:

&>/dev/null

I was then able to see what was going on, since everything wasn't going to the bit-bucket of /dev/null. So when I ran "./net.eth0 stop" I saw on the console that dhclient -r would keep releasing and releasing like 9 or so times. The first time it would shut down and stop the process (pid). Then the other times it would say something along the line of: "sh: 1: kill process number not found." So ps and top told me it was gone, but what was with this "looping" crap?

And so then I started to see what the "count" thing was all about. Since it was made for dhcpcd, it needed many attempts to kill the process. dhclient doesn't need that.

In the end, this is what I ended up with that works:

```
if [ "${iface_IFACE}" = "dhcp" ]

then

   /sbin/dhclient ${dhclientstop_IFACE} ${IFACE} >/dev/null

else

   /sbin/ifconfig ${IFACE} down >/dev/null

fi

eend 0
```

I even added the extra variablea in /etc/conf.d/net and in the setup_env section in net.eth0. (dhclientstart and dhclientstop)

I took out all that "count" stuff.

I can whip up with some diff's or copies of these files if anyones interested.

Until the next problem,

The Col.

----------

## jonner

I would like a copy of your net.eth0, since I would like to use dhclient instead of dhcpcd. I don't like how dhcpcd puts "search domainname" in my resolv.conf, rather than "domain domainname". It looks like this issue is trivial to fix with dhclient, since it uses a shell script to create the resolv.conf.

I think your version should be available as an alternative to any Gentoo user if it works well. I suppose that ideally, one would be able to switch between different DHCP clients by changing an option in /etc/conf.d/net.

----------

## jonner

I have it mostly working based on your descriptions, but I'm not sure what you put in dhclientstop_eth0.

----------

## Col.Kurtz

 *Quote:*   

> I think your version should be available as an alternative to any Gentoo user if it works well. I suppose that ideally, one would be able to switch between different DHCP clients by changing an option in /etc/conf.d/net.

 

That would be nice. Shouldn't be too difficult to have both client setup options in /etc/conf.d/net & /etc/init.d/net.eth(x). But then again, I'm no pro with Linux, so I'm not sure if what I have in place is "correct". The information on the files I'm providing are setup to ONLY work with dhclient. I didn't setup the files to have both clients, but it can be done.

You're gonna need to edit 2 files to get this to work (at least how I did it).

File #1: /etc/conf.d/net

```
# /etc/conf.d/net:

# $Header: /home/cvsroot/gentoo-src/rc-scripts/etc/conf.d/net,v 1.7 2002/11/18 19:39:22 azarah Exp $

# Global config file for net.* rc-scripts

# This is basically the ifconfig argument without the ifconfig $iface

#

#iface_eth0="192.168.0.2 broadcast 192.168.0.255 netmask 255.255.255.0"

#iface_eth1="207.170.82.202 broadcast 207.0.255.255 netmask 255.255.0.0"

# For DHCP set iface_eth? to "dhcp"

#

# For passing starting options to dhclient use dhclientstart_eth?

# For passing stopping options to dhclient use dhclientstop_eth?

#

iface_eth0="dhcp"

dhclientstart_eth0="-q -cf /etc/dhcp/dhclient.conf -sf /etc/dhcp/dhclient-script"

dhclientstop_eth0="-q -r -cf /etc/dhcp/dhclient.conf -sf /etc/dhcp/dhclient-script"

# For adding aliases to a interface

#

#alias_eth0="192.168.0.3 192.168.0.4"

# NB:  The next is only used for aliases.

#

# To add a custom netmask/broadcast address to created aliases,

# uncomment and change accordingly.  Leave commented to assign

# defaults for that interface.

#

#broadcast_eth0="192.168.0.255 192.168.0.255"

#netmask_eth0="255.255.255.0 255.255.255.0"

# For setting the default gateway

#

#gateway="eth0/192.168.0.1"
```

In the DHCP section, one is used to pass startup options to the client, the other to pass options when it shuts down. You can change/add to them (the -q is for quiet/don't-print-info-to-screen), but you have to keep the "-cf" and "-sf" lines. This is because of where the ebuild puts those files, yet the dhclient binary thinks they are somewhere else. This I think is a bug, but I haven't tinkered with my configs while playing with newer ebuilds, so it might have been fixed so you could leave those "-cf" and "-sf" arguments out. If you find out, let me know.

File #2: /etc/init.d/net.eth0

```
#!/sbin/runscript

# Copyright 1999-2003 Gentoo Technologies, Inc.

# Distributed under the terms of the GNU General Public License v2

# $Header: /home/cvsroot/gentoo-src/rc-scripts/init.d/net.eth0,v 1.34 2003/11/26 19:23:15 azarah Exp $

#NB: Config is in /etc/conf.d/net

# For pcmcia users. note that pcmcia must be added to the same

# runlevel as the net.* script that needs it.

depend() {

   use hotplug pcmcia

}

checkconfig() {

   if [ -z "${iface_IFACE}" ]

   then

      eerror "Please make sure that /etc/conf.d/net has \$iface_$IFACE set"

      return 1

   fi

   if [ -n "${vlans}" -a \! -x /sbin/vconfig ]

   then

      eerror "For VLAN (802.1q) support, emerge net-misc/vconfig"

      return 1

   fi

}

setup_env() {

   # No reason to check these multiple times in the file

   iface="${1/\./_}"

   iface_IFACE="$(eval echo \$\{iface_${iface}\})"

   # dhcpcd_IFACE="$(eval echo \$\{dhcpcd_${iface}\})"

   dhclientstart_IFACE="$(eval echo \$\{dhclientstart_${iface}\})"

   dhclientstop_IFACE="$(eval echo \$\{dhclientstop_${iface}\})"

   inet6_IFACE="$(eval echo \$\{inet6_${iface}\})"

   alias_IFACE="$(eval echo \$\{alias_${iface}\})"

   status_IFACE="$(ifconfig | gawk -v IFACE="${iface}" '$0 ~ /Link/ { if ($1 == IFACE) print "up" }')"

   vlans="$(eval echo \$\{iface_${IFACE}_vlans\})"

}

iface_start() {

   local retval=0

   setup_env ${1}

   checkconfig || return 1

   local IFACE="${1}"

   ebegin "Bringing ${IFACE} up"

   if [ "${iface_IFACE}" != "dhcp" ]

   then

      /sbin/ifconfig ${IFACE} ${iface_IFACE} >/dev/null || {

         retval=$?

         eend ${retval} "Failed to bring ${IFACE} up"

         return ${retval}

      }

      # ifconfig do not always return failure ..

      /sbin/ifconfig ${IFACE} &> /dev/null || {

         retval=$?

         eend ${retval} "Failed to bring ${IFACE} up"

         return ${retval}

      }

   else

      # Check that eth0 was not brough up by the kernel ...

      if [ "${status_IFACE}" != "up" ]

      then

         /sbin/dhclient ${dhclientstart_IFACE} ${IFACE} >/dev/null || {

            retval=$?

            eend ${retval} "Failed to bring ${IFACE} up"

            return ${retval}

         }

      fi

   fi

   eend 0

   if [ -n "${alias_IFACE}" ]

   then

      local x=""

      local num=0

      local aliasbcast=""

      local aliasnmask=""

      ebegin "  Adding aliases"

      for x in ${alias_IFACE}

      do

         aliasbcast="$(eval echo \$\{broadcast_${iface}\} \| awk \'\{ print \$$((num + 1)) \}\')"

         if [ -n "${aliasbcast}" ]

         then

            aliasbcast="broadcast ${aliasbcast}"

         fi

         aliasnmask="$(eval echo \$\{netmask_${iface}\} \| awk \'\{ print \$$((num + 1)) \}\')"

         if [ -n "${aliasnmask}" ]

         then

            aliasnmask="netmask ${aliasnmask}"

         fi

      

         ebegin "    ${IFACE}:${num}"

         /sbin/ifconfig ${IFACE}:${num} ${x} \

            ${aliasbcast} ${aliasnmask} >/dev/null

         num=$((num + 1))

         eend 0

      done

      save_options "alias" "${alias_IFACE}"

   fi

   if [ -n "${inet6_IFACE}" ]

   then

      local x=""

      ebegin "  Adding inet6 addresses"

      for x in ${inet6_IFACE}

      do

         ebegin "    ${IFACE} inet6 add ${x}"

         /sbin/ifconfig ${IFACE} inet6 add ${x} >/dev/null

         eend 0

      done

      save_options "inet6" "${inet6_IFACE}"

   fi

   

   if [ -n "${gateway}" ] && [ "${gateway%/*}" = "${IFACE}" ]

   then

      ebegin "  Setting default gateway"

      # First delete any existing routes if it was setup by kernel ..

      /sbin/route del default dev ${gateway%/*} &>/dev/null

      /sbin/route add default gw ${gateway#*/} dev ${gateway%/*} \

         netmask 0.0.0.0 metric 1 >/dev/null || {

         

         local error=$?

         ifconfig ${IFACE} down &>/dev/null

         eend ${error} "Failed to bring ${IFACE} up"

         stop

         return ${error}

      }

      eend 0

   fi

   # Enabling rp_filter causes wacky packets to be auto-dropped by

   # the kernel.  Note that we only do this if it is not set via

   # /etc/sysctl.conf ...

   if [ -e /proc/sys/net/ipv4/conf/${IFACE}/rp_filter ] && \

      [ -z "$(egrep '^[^#]*rp_filter' /etc/sysctl.conf 2>/dev/null)" ]

   then

      echo 1 > /proc/sys/net/ipv4/conf/${IFACE}/rp_filter

   fi

}

iface_stop() {

   local myalias="$(get_options alias)"

   local myinet6="$(get_options inet6)"

   setup_env ${1}

   local IFACE="${1}"

   ebegin "Bringing ${IFACE} down"

   # Also down the inet6 interfaces

   if [ -n "${myinet6}" ]

   then

      local x=""

      for x in ${myinet6}

      do

         /sbin/ifconfig ${IFACE} inet6 del ${x} >/dev/null

      done

   fi

   

   # Do some cleanup in case the amount of aliases change

   if [ -n "${myalias}" ]

   then

      local x=""

      local num=0

      for x in ${myalias}

      do

         /sbin/ifconfig ${IFACE}:${num} down >/dev/null

         num=$((num + 1))

      done

   fi

   if [ "${iface_IFACE}" = "dhcp" ]

   then

      /sbin/dhclient ${dhclientstop_IFACE} >/dev/null

   else

      /sbin/ifconfig ${IFACE} down >/dev/null

   fi

   eend 0

}

start() {

   iface_start ${IFACE} || return 1

   for vlan in ${vlans}

   do

      /sbin/vconfig add ${IFACE} ${vlan} >/dev/null

      iface_start ${IFACE}.${vlan}

   done

}

stop () {

   setup_env ${IFACE}

   checkconfig || return 1

   for vlan in ${vlans}

   do

      iface_stop ${IFACE}.${vlan}

      /sbin/vconfig rem ${IFACE}.${vlan} >/dev/null

   done

   iface_stop ${IFACE}

}

# vim:ts=4

```

If these files don't come through, I can email them. Let me know how you make out.

----------

## Col.Kurtz

One of the things that pushed me to use dhclient a few years ago was it's ability to do DynamicDNS registration. Something that I don't think dhcpcd can do. It even registers with Win2000 Server DNS (AD integrated/only secure updates) without problems.

However, one thing that would be nice is, in the dhclient.conf file, instead of having send host-name "gentoo-pc"; and for DynamicDNS send fqdn.fqdn "gentoo-pc";, the dhclient program should KNOW to look in /etc/hostname, and fill in those blanks. It just seems stupid to have to specify the name of your computer in multiple files, when it's common practice to have a hostname file on your Linux systems.

But maybe that's just wishful thinking on my part.

----------

## jonner

I am using your script and everything seems to be working well. I was stumped for a bit because runscript would complain about syntax errors until I added a newline at the end, which hadn't come through on the forum. I don't know why this is so critical.

I didn't bother doing anything with a config file, since the defaults seem to be fine for me. I put the supplied sample dhclient-script in /sbin, since that where it is expected by default. I edited that file slightly, but otherwise, I'm using defaults.

This allows me to have the following in my /etc/init.d/net:

```
iface_eth0="dhcp"

dhclientstart_eth0="-q"

dhclientstop_eth0="-q -r"

```

----------

## jonner

 *Quote:*   

> However, one thing that would be nice is, in the dhclient.conf file, instead of having send host-name "gentoo-pc"; and for DynamicDNS send fqdn.fqdn "gentoo-pc";, the dhclient program should KNOW to look in /etc/hostname, and fill in those blanks. It just seems stupid to have to specify the name of your computer in multiple files, when it's common practice to have a hostname file on your Linux systems. 

 

One thing that may complicate this is the fact that /etc/hostname shouldn't contain an FQDN, but the simple hostname, according to /etc/init.d/hostname. The DNS domain name should be in /etc/resolv.conf as a "domain x" line. Discovering these details is why I wanted to use dhclient, since dhcpcd was giving me a "search x" line instead.

Though it should be possible to find the correct FQDN for a host using standard library calls, it seems that things are often misconfigured.

----------

