diff options
author | brooks <brooks@FreeBSD.org> | 2005-06-07 04:49:12 +0000 |
---|---|---|
committer | brooks <brooks@FreeBSD.org> | 2005-06-07 04:49:12 +0000 |
commit | 5a3d620fb15161572eed8cb406ccb6672fd2f93c (patch) | |
tree | 5b737af62b38f4124fab3c80ff903dbb7a8a0a1d | |
parent | 9a851b1b815c8f75342aef3c3bdd9d7943045a0d (diff) | |
download | FreeBSD-src-5a3d620fb15161572eed8cb406ccb6672fd2f93c.zip FreeBSD-src-5a3d620fb15161572eed8cb406ccb6672fd2f93c.tar.gz |
Support code for the OpenBSD dhclient. This significantly changes the
way interfaces are configured. Some key points:
- At startup, all interfaces are configured through /etc/rc.d/netif.
- ifconfig_<if> variables my now mix real ifconfig commands the with
DHCP and WPA directives. For example, this allows media
configuration prior to running dhclient.
- /etc/rc.d/dhclient is not run at startup except by netif to start
dhclient on specific interfaces.
- /etc/pccard_ether calls "/etc/rc.d/netif start <if>" to do most of
it's work.
- /etc/pccard_ether no longer takes additional arguments to pass to
ifconfig. Instead, ifconfig_<if> variables are now honored in favor
of pccard_ifconfig when available.
- /etc/pccard_ether will only run on interfaces specified in
removable_interfaces, even if pccard_ifconfig is set.
-rw-r--r-- | etc/defaults/rc.conf | 1 | ||||
-rw-r--r-- | etc/devd.conf | 15 | ||||
-rw-r--r-- | etc/network.subr | 111 | ||||
-rwxr-xr-x | etc/pccard_ether | 296 | ||||
-rwxr-xr-x | etc/rc.d/dhclient | 98 | ||||
-rw-r--r-- | etc/rc.d/netif | 4 |
6 files changed, 213 insertions, 312 deletions
diff --git a/etc/defaults/rc.conf b/etc/defaults/rc.conf index 790b473..9777198 100644 --- a/etc/defaults/rc.conf +++ b/etc/defaults/rc.conf @@ -42,6 +42,7 @@ pccard_ether_delay="5" # Delay before trying to start dhclient in pccard_ether powerd_enable="NO" # Run powerd to lower our power usage. powerd_flags="" # Flags to powerd (if enabled). removable_interfaces="" # Removable network interfaces for /etc/pccard_ether. +removable_route_flush="YES" # Flush routes when removing an interface tmpmfs="AUTO" # Set to YES to always create an mfs /tmp, NO to never tmpsize="20m" # Size of mfs /tmp if created tmpmfs_flags="-S" # Extra mdmfs options for the mfs /tmp diff --git a/etc/devd.conf b/etc/devd.conf index 0646585..6968a8b 100644 --- a/etc/devd.conf +++ b/etc/devd.conf @@ -32,7 +32,7 @@ options { # override these general rules. # -# For ethernet like devices, the default is to run dhclient. Due to +# For ethernet like devices start configuring the interface. Due to # a historical accident, this script is called pccard_ether. # attach 0 { @@ -45,6 +45,19 @@ detach 0 { action "/etc/pccard_ether $device-name stop"; }; +# +# Try to start dhclient on Ethernet like interfaces when the link comes +# up. Only devices that are configured to support DHCP will actually +# run it. No link down rule exists because dhclient automaticly exits +# when the link goes down. +# +notify 0 { + match "system" "IFNET"; + match "subsystem" "$ethernet-nic-regex"; + match "type" "LINK_UP"; + action "/etc/rc.d/dhclient start $subsystem"; +}; + # An entry like this might be in a different file, but is included here # as an example of how to override things. Normally 'ed50' would match # the above attach/detach stuff, but the value of 100 makes it diff --git a/etc/network.subr b/etc/network.subr index dfd2feb..a3059dd 100644 --- a/etc/network.subr +++ b/etc/network.subr @@ -34,16 +34,30 @@ # Evaluate ifconfig(8) arguments for interface $if and # run ifconfig(8) with those arguments. It returns 0 if # arguments were found and executed or 1 if the interface -# had no arguments. +# had no arguments. Pseudo arguments DHCP and WPA are handled +# here. # ifconfig_up() { - eval ifconfig_args=\$ifconfig_$1 + _cfg=1 + + ifconfig_args=`ifconfig_getargs $1` if [ -n "${ifconfig_args}" ]; then ifconfig $1 ${ifconfig_args} - return 0 + _cfg=0 fi - return 1 + + if wpaif $1; then + #/etc/rc.d/wpa_supplicant start $1 + _cfg=0 # XXX: not sure this should count + fi + + if dhcpif $1; then + /etc/rc.d/dhclient start $1 + _cfg=0 + fi + + return ${cfg} } # ifconfig_down if @@ -74,9 +88,98 @@ ifconfig_down() done IFS="$oldifs" + if wpaif $1; then + #/etc/rc.d/wpa_supplicant stop $1 + fi + + if dhcpif $1; then + /etc/rc.d/dhclient stop $1 + _cfg=0 + fi + return $_ret } +# _ifconfig_getargs if +# Echos the arguments for the supplied interface to stdout. +# returns 1 if empty. In general, ifconfig_getargs should be used +# outside this file. +_ifconfig_getargs() +{ + _ifn=$1 + if [ -z "$_ifn" ]; then + return 1 + fi + + eval _args=\$ifconfig_$1 + if [ -z "$_args" -a -n "${pccard_ifconfig}" ]; then + for _if in ${removable_interfaces} ; do + if [ "$_if" = "$_ifn" ] ; then + _args=${pccard_ifconfig} + break + fi + done + fi + + echo $_args +} + +# ifconfig_getargs if +# Takes the result from _ifconfig_getargs and removes pseudo +# args such as DHCP and WPA. +ifconfig_getargs() +{ + _tmpargs=`_ifconfig_getargs $1` + if [ $? -eq 1 ]; then + return 1 + fi + _args= + + for _arg in $_tmpargs; do + case $_arg in + [Dd][Hh][Cc][Pp]) + ;; + [Ww][Pp][Aa]) + ;; + *) + _args="$_args $_arg" + ;; + esac + done + + echo $_args +} + +# dhcpif if +# Returns 0 if the interface is a DHCP interface and 1 otherwise. +dhcpif() +{ + _tmpargs=`_ifconfig_getargs $1` + for _arg in $_tmpargs; do + case $_arg in + [Dd][Hh][Cc][Pp]) + return 0 + ;; + esac + done + return 1 +} + +# wpaif if +# Returns 0 if the interface is a WPA interface and 1 otherwise. +wpaif() +{ + _tmpargs=`_ifconfig_getargs $1` + for _arg in $_tmpargs; do + case $_arg in + [Ww][Pp][Aa]) + return 0 + ;; + esac + done + return 1 +} + # ifalias_up if # Configure aliases for network interface $if. # It returns 0 if at least one alias was configured or diff --git a/etc/pccard_ether b/etc/pccard_ether index 8c7b671..99c3204 100755 --- a/etc/pccard_ether +++ b/etc/pccard_ether @@ -2,271 +2,115 @@ # # $FreeBSD$ # -# pccard_ether interfacename [start|stop] [ifconfig option] +# pccard_ether interfacename [start|stop] # -# example: pccard_ether fxp0 start link0 +# example: pccard_ether fxp0 start # +. /etc/rc.subr . /etc/network.subr -stop_dhcp() { - # If dhclient is already running, record - # its interfaces. - if [ -x /usr/bin/grep ]; then - eval _active_list=\"`/bin/ps -axwww | \ - /usr/bin/grep dhclient | \ - /usr/bin/grep -v grep | \ - /usr/bin/sed -e 's|^.*dhclient||' | \ - /usr/bin/awk '{for (i=1;i<=NF;i++) \ - { if ($i~/[a-zA-Z].[0-9]$/) \ - { printf(" %s",$i) } }}'` \ - \" - fi +usage() +{ + err 3 'USAGE: $0 interface (start|stop)' +} - # Get the rc.conf list of dhcp configured interfaces - static_dhcp_list="`list_net_interfaces dhcp`" +ifn=$1 +shift +startstop=$1 +shift - # Get the current ifconfig list of interfaces - _aprefix= - _nlist= - for _if in ${_active_list} ; do - _test_if=`ifconfig ${_if} 2>&1` - case "$_test_if" in - "ifconfig: interface $_if does not exist") - ;; - ${interface}) - # Don't record the same device twice. - ;; - *) - # - # Catch devices which were specified before, - # but have not been part of the rc. We need - # them again for the restart. - # - for _cif in ${static_dhcp_list} ; do - case "$_cif" in - ${_if}) - # Nothing to add - ;; - *) - # Found interface beside rc.conf - _nlist="${_nlist}${_aprefix}${_if}" - ;; - esac - done - _dhcplist="${_dhcplist}${_aprefix}${_if}" - [ -z "$_aprefix" ] && _aprefix=' ' - ;; - esac - done +# Ignore interfaces not in removable_interfaces +expr "${removable_interfaces}" : ".*${ifn}" > /dev/null || exit 0 - if [ -s /var/run/dhclient.pid ]; then - pidfile="/var/run/dhclient.pid" - else - return - fi - /sbin/dhclient -r ${interface} - rm -f ${pidfile} - case ${startstop} in - [Ss][Tt][Oo][Pp]) - if [ -z "${_nlist}" ]; then - sh /etc/rc.d/dhclient start - else - start_dhcp_keep_current - fi +if [ -n "$1" ]; then + usage +fi + +setup_routes() +{ + # Add default route into $static_routes + case ${defaultrouter} in + [Nn][Oo] | '') ;; *) + static_routes="default ${static_routes}" + route_default="default ${defaultrouter}" ;; esac -} -start_dhcp() { - stop_dhcp - case ${pccard_ether_delay} in - [Nn][Oo]) - ;; - [0-9]*) - sleep ${pccard_ether_delay} - ;; - esac - [ -n "$dhcp_program" ] && dhclient_program="$dhcp_program" - [ -n "$dhcp_flags" ] && dhclient_flags="$dhcp_flags" - if [ -x "${dhclient_program}" ]; then - interfaces=`echo $_dhcplist ${interface} | xargs -n 1 echo | sort -u` - ${dhclient_program} ${dhclient_flags} ${interfaces} - else - echo "${dhclient_program}: DHCP client software not available" + # Add private route for this interface into $static_routes + eval ifx_routes=\$static_routes_${ifn} + if [ -n "${ifx_routes}" ]; then + static_routes="${ifx_routes} ${static_routes}" fi -} -# Called after detaching a card, if dhclient has been -# used for more than one interface. -start_dhcp_keep_current() { - [ -n "$dhcp_program" ] && dhclient_program="$dhcp_program" - [ -n "$dhcp_flags" ] && dhclient_flags="$dhcp_flags" - if [ -x "${dhclient_program}" ]; then - ${dhclient_program} ${dhclient_flags} \ - ${_dhcplist} - else - echo "${dhclient_program}: DHCP client software not available" + # Set up any static routes if specified + if [ -n "${static_routes}" ]; then + for i in ${static_routes}; do + eval route_args=\$route_${i} + route add ${route_args} + done fi } -# Suck in the configuration variables -# -if [ -r /etc/defaults/rc.conf ]; then - . /etc/defaults/rc.conf - source_rc_confs -elif [ -r /etc/rc.conf ]; then - . /etc/rc.conf -fi - -interface=$1 -shift -startstop=$1 -shift +remove_routes() +{ + # Delete static route if specified + eval ifx_routes=\$static_routes_${ifn} + if [ -n "${ifx_routes}" ]; then + for i in ${ifx_routes}; do + eval route_args=\$route_${i} + route delete ${route_args} + done + fi +} -case ${pccard_ifconfig} in -[Nn][Oo] | '') - expr "${removable_interfaces}" : ".*${interface}" > /dev/null || exit 0 - ;; -*) - # Backward compatible - eval ifconfig_${interface}=\${pccard_ifconfig} - ;; -esac +load_rc_config pccard_ether case ${startstop} in [Ss][Tt][Aa][Rr][Tt] | '') if [ -x /usr/bin/grep ]; then - if ifconfig ${interface} | grep -s netmask > /dev/null 2>&1; then + if ifconfig $ifn | grep -s netmask > /dev/null 2>&1; then # Interface is already up, so ignore it. exit 0 fi fi - if [ -r /etc/start_if.${interface} ]; then - . /etc/start_if.${interface} - fi + /etc/rc.d/netif start $ifn - eval ifconfig_args=\$ifconfig_${interface} - case ${ifconfig_args} in - [Nn][Oo] | '') - ;; - [Dd][Hh][Cc][Pp]) - # Start up the DHCP client program - start_dhcp - ;; - *) - # Do the primary ifconfig if specified - ifconfig ${interface} ${ifconfig_args} $* - - # Check to see if aliases need to be added - alias=0 - while : - do - eval ifx_args=\$ifconfig_${interface}_alias${alias} - if [ -n "${ifx_args}" ]; then - ifconfig ${interface} ${ifx_args} alias - alias=`expr ${alias} + 1` - else - break; - fi - done - - # Do ipx address if specified - eval ifx_args=\$ifconfig_${interface}_ipx - if [ -n "${ifx_args}" ]; then - ifconfig ${interface} ${ifx_args} - fi - - # Add default route into $static_routes - case ${defaultrouter} in - [Nn][Oo] | '') - ;; - *) - static_routes="default ${static_routes}" - route_default="default ${defaultrouter}" - ;; - esac - - # Add private route for this interface into $static_routes - eval ifx_routes=\$static_routes_${interface} - if [ -n "${ifx_routes}" ]; then - static_routes="${ifx_routes} ${static_routes}" - fi - - # Set up any static routes if specified - if [ -n "${static_routes}" ]; then - for i in ${static_routes}; do - eval route_args=\$route_${i} - route add ${route_args} - done + # Do route configuration if needed. + # XXX: should probably do this by calling rc.d/routing. + if [ -n "`ifconfig_getargs $ifn`" ]; then + if ! dhcpif $ifn; then + setup_routes fi - ;; - esac + fi # IPv6 setup - case ${ipv6_enable} in - [Yy][Ee][Ss]) - if [ -r /etc/network.subr ]; then - . /etc/network.subr - network6_interface_setup ${interface} - fi - ;; - esac - ;; -# Stop the interface -*) - if [ -r /etc/stop_if.${interface} ]; then - . /etc/stop_if.${interface} + if checkyesno ipv6_enable; then + network6_interface_setup $ifn fi + ;; - eval ifconfig_args=\$ifconfig_${interface} - case ${ifconfig_args} in - [Nn][Oo] | '') - ;; - [Dd][Hh][Cc][Pp]) - # Stop the DHCP client for this interface - stop_dhcp - ;; - *) - # Delete static route if specified - eval ifx_routes=\$static_routes_${interface} - if [ -n "${ifx_routes}" ]; then - for i in ${ifx_routes}; do - eval route_args=\$route_${i} - route delete ${route_args} - done +# Stop the interface +[Ss][Tt][Oo][Pp]) + if [ -n "`ifconfig_getargs $ifn`" ]; then + if ! dhcpif $ifn; then + remove_routes fi + fi - # Delete aliases if exist - alias=0 - while : - do - eval ifx_args=\$ifconfig_${interface}_alias${alias} - if [ -n "${ifx_args}" ]; then - ifconfig ${interface} ${ifx_args} alias delete - alias=`expr ${alias} + 1` - else - break; - fi - done - ;; - esac + /etc/rc.d/netif stop $ifn - # Remove the network interface and cleaning ARP table - ifconfig ${interface} delete + # clean ARP table arp -d -a # Clean the routing table - case ${removable_route_flush} in - [Nn][Oo]) - ;; - *) - # flush beforehand, just in case.... - route -n flush -inet - ;; - esac + if checkyesno removable_route_flush; then + route -n flush -inet > /dev/null + fi ;; +*) + usage esac diff --git a/etc/rc.d/dhclient b/etc/rc.d/dhclient index 5d28427..2e56f1f 100755 --- a/etc/rc.d/dhclient +++ b/etc/rc.d/dhclient @@ -7,10 +7,7 @@ # PROVIDE: dhclient # REQUIRE: netif ipfw ipfilter mountcritlocal cleanvar # BEFORE: NETWORKING -# KEYWORD: nojail -# -# Note that there no syslog logging of dhclient messages at boot because -# dhclient needs to start before services that syslog depends upon do. +# KEYWORD: nojail nostart # . /etc/rc.subr @@ -18,96 +15,39 @@ name="dhclient" rcvar= -pidfile="/var/run/${name}.pid" -start_precmd="dhclient_prestart" -start_postcmd="dhclient_poststart" -stop_precmd="dhclient_prestop" -stop_postcmd="dhclient_poststop" +start_cmd="dhclient_start" +stop_cmd="dhclient_stop" -dhclient_common() +dhclient_start() { - dhcp_list="`list_net_interfaces dhcp`" - if [ -z "$dhcp_list" ]; then - return 1 - fi - - # Determine the scope of the command - # - _cooked_list="$dhcp_list" - if [ -n "$_cmdifn" ]; then - eval _cooked_list=\"`expr "$dhcp_list" : ".*\($_cmdifn\).*"`\" - if [ -z "$_cooked_list" ]; then - err 1 "No such network interface: $_cmdifn" + # prevent unnecessicary restarts + # XXX: should use a pidfile + if [ -x /usr/bin/pgrep ]; then + pids=`/usr/bin/pgrep -f "dhclient: $ifn(\$| .*)"` + if [ -n "$pids" ]; then + echo "${name} ${ifn}: already running?" + exit 0 fi fi -} - -dhclient_prestart() -{ - if [ $dhclient_common_error -eq 1 ]; then - return 1 - fi - for ifn in ${_cooked_list}; do - ifscript_up ${ifn} - done if checkyesno background_dhclient; then - rc_flags="${rc_flags} -nw" + rc_flags="${rc_flags} -b" fi - rc_flags="${rc_flags} ${_cooked_list}" - return 0 + ${dhclient_program} ${rc_flags} $ifn } -dhclient_poststart() +dhclient_stop() { - for ifn in ${_cooked_list}; do - ifalias_up ${ifn} - ipx_up ${ifn} - ifconfig ${ifn} - done + ifconfig $ifn down # cause dhclient to die } -dhclient_prestop() -{ - if [ $dhclient_common_error -eq 1 ]; then - return 1 - fi - for ifn in ${_cooked_list}; do - ipx_down ${ifn} - ifalias_down ${ifn} - done - echo -n "Releasing DHCP leases:" - for ifn in $_cooked_list ; do - ${command} -r $ifn - if [ $? -eq 0 ]; then - echo -n " $ifn" - else - _fail="$_fail $ifn" - fi - done - echo '.' - debug "The following leases failed to release: $_fail" -} +ifn="$2" -dhclient_poststop() -{ - for ifn in ${_cooked_list}; do - ifscript_down ${ifn} - done -} +load_rc_config $name -if [ -n "$2" ]; then - _cmdifn="$2" - stop_cmd=":" +if ! dhcpif $ifn; then + return 1 fi -load_rc_config $name -dhclient_common_error=0 -dhclient_common || dhclient_common_error=1; -if [ -n "$_cooked_list" ]; then - if [ -s $pidfile ]; then - stop_cmd=":" - fi -fi run_rc_command "$1" diff --git a/etc/rc.d/netif b/etc/rc.d/netif index 58a9476..88bccb7 100644 --- a/etc/rc.d/netif +++ b/etc/rc.d/netif @@ -102,8 +102,8 @@ network_common() fi [ -n "$2" ] && _verbose=yes - # Get a list of network interfaces. Do not include dhcp interfaces. - _ifn_list="`list_net_interfaces nodhcp`" + # Get a list of network interfaces. + _ifn_list="`list_net_interfaces`" # Set the scope of the command (all interfaces or just one). # |