--- client/dhclient-script.8 +++ client/dhclient-script.8 2009/10/16 08:10:52 @@ -45,9 +45,10 @@ any, and also called once if no valid le This script is not meant to be customized by the end user. If local customizations are needed, they should be possible using the enter and exit hooks provided (see HOOKS for details). These hooks will allow the -user to override the default behaviour of the client in creating a +user to override the default behaviour of the client in applying of +additional settings like DNS (e.g. creating a .B /etc/resolv.conf -file. +file), NTP or YP to the system. .PP No standard client script exists for some operating systems, even though the actual client may work, so a pioneering user may well need to create @@ -59,12 +60,43 @@ customizing .B ETCDIR/dhclient.conf or using the enter and exit hooks, please submit a bug report. .SH HOOKS -When it starts, the client script first defines a shell function, -.B make_resolv_conf , -which is later used to create the +When it starts, the client script first defines several shell functions: +.BR use_netconfig , +.BR netconfig_modify , +.BR netconfig_remove , +.BR make_resolv_conf , +and +.BR restore_resolv_conf . +These functions are later used to apply DNS, NTP, YP, and other additional +settings to the system. + +The +.B use_netconfig +returns true (0), when the /sbin/netconfig script is installed and enables +the use of the +.B netconfig_modify +and +.B netconfig_remove +functions. +.br +Otherwise, the +.BR make_resolv_conf +and +.BR restore_resolv_conf +functions are used. These functions are modified to create +/var/lib/dhcp/resolv.conf.dhclient.$interface files only +instead of the .B /etc/resolv.conf -file. To override the default behaviour, redefine this function in -the enter hook script. +file. +To override the default behaviour, redefine these function in the enter +hook script. Before you start doing this, consider to implement own +netconfig modules. + +.IR Note : +Note, that since openSUSE 11.1, the modify_resolvconf script / mechanizm +is obsoleted by netconfig and not shipped or supported any more. +See the netconfig(8) manual page for more informations. + .PP On after defining the make_resolv_conf function, the client script checks for the presence of an executable @@ -221,7 +253,7 @@ valid, this shouldn't cause any real pro confusing. .SH SEE ALSO dhclient(8), dhcpd(8), dhcrelay(8), dhclient.conf(5) and -dhclient.leases(5). +dhclient.leases(5) and netconfig(8). .SH AUTHOR .B dhclient-script(8) has been written for Internet Systems Consortium --- client/scripts/linux +++ client/scripts/linux 2009/10/16 08:16:11 @@ -22,25 +22,183 @@ # 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious # of the $1 in its args. + +# Debugging: +# +# logs entire run of dhclient-script to /var/log/dhclient-script, +# if DHCLIENT_DEBUG is set in sysconfig/network/dhcp +# +eval `grep "^DHCLIENT_DEBUG=" /etc/sysconfig/network/dhcp 2>/dev/null` +if [ "$DHCLIENT_DEBUG" = yes ]; then + set -a # allexport + ( + echo '****************' + echo "$0 $*" + date + echo '----------------' + set + echo '----------------' + ) >> /var/log/dhclient-script.log + exec 2>> /var/log/dhclient-script.log + set +a + set -x +fi + +# netconfig makes all "additional" modifications as DNS or NTP +use_netconfig() { + test -x /sbin/netconfig +} +netconfig_modify() { + if test -x /sbin/netconfig -a -n "$interface" ; then + { + echo "INTERFACE='$interface'" + for v in ${!new_*}; do + case $v in + (new_ip_address) k='IPADDR' ;; + (new_subnet_mask) k='NETMASK' ;; + (new_network_number) k='NETWORK' ;; + (new_broadcast_address) k='BROADCAST' ;; + (new_interface_mtu) k='MTU' ;; + # (new_static_routes) k='ROUTES' ;; + (new_routers) k='GATEWAYS' ;; + (new_host_name) k='HOSTNAME' ;; + (new_domain_search) k='DNSSEARCH' ;; + (new_domain_name) k='DNSDOMAIN' ;; + (new_domain_name_servers) k='DNSSERVERS' ;; + (new_ntp_servers) k='NTPSERVERS' ;; + (new_nis_domain) k='NISDOMAIN' ;; + (new_nis_servers) k='NISSERVERS' ;; + (new_root_path) k='ROOTPATH' ;; + (new_dhcp_server_identifier)k='DHCPSID' ;; + (new_lpr_servers) k='LPRSERVER' ;; + (new_log_servers) k='LOGSERVER' ;; + (new_netbios_dd_server) k='NETBIOSDDSERVER' ;; + (new_netbios_name_servers) k='NETBIOSNAMESERVER' ;; + (new_netbios_node_type) k='NETBIOSNODETYPE' ;; + (new_netbios_scope) k='NETBIOSSCOPE' ;; + (*) k="dhclient_${v#new_}" ;; + esac + [ "k${k}" != k ] && echo "${k}='${!v}'" + done + } | /sbin/netconfig modify -s "dhclient3" -i "$interface" + fi +} +netconfig_remove() { + if test -x /sbin/netconfig -a -n "$interface" ; then + /sbin/netconfig remove -s "dhclient3" -i "$interface" /dev/null ; + then + eval `grep --no-filename '^[[:space:]]*DHCLIENT_SET_DEFAULT_ROUTE=' \ + /etc/sysconfig/network/dhcp + /etc/sysconfig/network/ifcfg-${interface} 2>/dev/null` + else + eval `grep --no-filename '^[[:space:]]*DHCLIENT_SET_DEFAULT_ROUTE=' \ + /etc/sysconfig/network/ifcfg-${interface} 2>/dev/null` + fi + else + eval `grep --no-filename '^[[:space:]]*DHCLIENT_SET_DEFAULT_ROUTE=' \ + /etc/sysconfig/network/dhcp 2>/dev/null` + fi + if [ "$DHCLIENT_SET_DEFAULT_ROUTE" = yes ] ; then + for router in $new_routers; do + err=`route add default gw $router $metric_arg dev $interface 2>&1` && break || \ + case "$err" in + SIOCADDRT:*) + # The gateway seems to be not reachable via local network + # route (implicitely created by ifconfig based on the IP + # an netmask provided by dhcp). + # Check this, set an explicit host route to the gateway + # over the current interface and try again (bnc#266215). + matches=$(test -x /sbin/ip && \ + /sbin/ip -f inet -o route list match $router | \ + grep -v ^default | grep -c -v "^$" 2>/dev/null) + if test -n "$matches" -a $(($matches)) -eq 0 ; then + route add -host $router dev $interface && \ + route add default gw $router $metric_arg dev $interface && break + fi + ;; + esac + done + fi +} +set_hostname() +{ + if test -f /etc/sysconfig/network/ifcfg-${interface} -o \ + -f /dev/shm/sysconfig/if-${interface} ; + then + if grep -qs '^primary=yes' /dev/shm/sysconfig/if-${interface} 2>/dev/null ; + then + eval `grep --no-filename "^[[:space:]]*DHCLIENT_SET_HOSTNAME=" \ + /etc/sysconfig/network/dhcp + /etc/sysconfig/network/ifcfg-${interface} 2>/dev/null` + else + eval `grep --no-filename "^[[:space:]]*DHCLIENT_SET_HOSTNAME=" \ + /etc/sysconfig/network/ifcfg-${interface} 2>/dev/null` + fi + else + eval `grep --no-filename "^[[:space:]]*DHCLIENT_SET_HOSTNAME=" \ + /etc/sysconfig/network/dhcp 2>/dev/null` + fi + if [ "$DHCLIENT_SET_HOSTNAME" = yes ] ; then + current_hostname=`hostname` + if [ "x${current_hostname%%.*}" = "x" ] || \ + [ "x${current_hostname%%.*}" = "x(none)" ] || \ + [ "x${current_hostname%%.*}" = "xlocalhost" ] || \ + [ "x${current_hostname%%.*}" != "x${new_host_name%%.*}" ]; then + + if [ "x${new_host_name%%.*}" != x ]; then + hostname "${new_host_name%%.*}" + else + if [ -x /usr/bin/host ] ; then + if out=`host -W 2 "$new_ip_address" 2>/dev/null` ; then + _hostname="`echo "$out" | sed 's:^.* ::; s:\..*::'`" + if [ "x${_hostname}" != x ]; then + hostname "${_hostname}" + fi + fi + fi + fi + fi + fi +} + +resolv_conf_dhclient="/var/lib/dhcp/resolv.conf.dhclient.$interface" make_resolv_conf() { + ### + ### note: this function is never used by default + ### and it has been modified to create the + ### /var/lib/dhcp/resolv.conf.dhclient.$interface + ### file instead /etc/resolv.conf. + ### if [ x"$new_domain_name_servers" != x ]; then - cat /dev/null > /etc/resolv.conf.dhclient - chmod 644 /etc/resolv.conf.dhclient + cat /dev/null > "$resolv_conf_dhclient" + chmod 644 "$resolv_conf_dhclient" if [ x"$new_domain_search" != x ]; then - echo search $new_domain_search >> /etc/resolv.conf.dhclient + echo search $new_domain_search >> "$resolv_conf_dhclient" elif [ x"$new_domain_name" != x ]; then # Note that the DHCP 'Domain Name Option' is really just a domain # name, and that this practice of using the domain name option as # a search path is both nonstandard and deprecated. - echo search $new_domain_name >> /etc/resolv.conf.dhclient + echo search $new_domain_name >> "$resolv_conf_dhclient" fi for nameserver in $new_domain_name_servers; do - echo nameserver $nameserver >>/etc/resolv.conf.dhclient + echo nameserver $nameserver >> "$resolv_conf_dhclient" done - mv /etc/resolv.conf.dhclient /etc/resolv.conf + ### mv /etc/resolv.conf.dhclient /etc/resolv.conf fi } +restore_resolv_conf() +{ + rm -f "$resolv_conf_dhclient" +} # Must be used on exit. Invokes the local dhcp client exit hooks, if any. exit_with_hooks() { @@ -84,7 +242,12 @@ if [ x$alias_subnet_mask != x ]; then alias_subnet_arg="netmask $alias_subnet_mask" fi if [ x$new_interface_mtu != x ]; then - mtu_arg="mtu $new_interface_mtu" + if [ $(( $new_interface_mtu )) -lt 576 ] ; then + # 68 is the minimal legal value, but 576 the real life minimum + unset new_interface_mtu + else + mtu_arg="mtu $new_interface_mtu" + fi fi if [ x$IF_METRIC != x ]; then metric_arg="metric $IF_METRIC" @@ -122,15 +285,6 @@ fi if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then - current_hostname=`hostname` - if [ x$current_hostname = x ] || \ - [ x$current_hostname = "x(none)" ] || \ - [ x$current_hostname = xlocalhost ] || \ - [ x$current_hostname = x$old_host_name ]; then - if [ x$new_host_name != x$old_host_name ]; then - hostname "$new_host_name" - fi - fi if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \ [ x$alias_ip_address != x$old_ip_address ]; then @@ -140,7 +294,7 @@ if [ x$reason = xBOUND ] || [ x$reason = if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then # IP address changed. Bringing down the interface will delete all routes, # and clear the ARP cache. - ifconfig $interface inet 0 down + ifconfig $interface inet 0 fi if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \ @@ -153,17 +307,25 @@ if [ x$reason = xBOUND ] || [ x$reason = ( [ $relmajor -eq 2 ] && [ $relminor -eq 0 ] ); then route add -net $new_network_number $new_subnet_arg dev $interface fi - for router in $new_routers; do - route add default gw $router $metric_arg dev $interface - done + + set_default_gw_route fi + if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ]; then ifconfig $interface:0- inet 0 ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg route add -host $alias_ip_address $interface:0 fi - make_resolv_conf + + if use_netconfig ; then + netconfig_modify + else + make_resolv_conf + fi + + set_hostname + exit_with_hooks 0 fi @@ -175,7 +337,7 @@ if [ x$reason = xEXPIRE ] || [ x$reason fi if [ x$old_ip_address != x ]; then # Shut down interface, which will delete routes and clear arp cache. - ifconfig $interface inet 0 down + ifconfig $interface inet 0 fi if [ x$alias_ip_address != x ]; then ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg @@ -190,7 +352,7 @@ if [ x$reason = xTIMEOUT ]; then fi ifconfig $interface inet $new_ip_address $new_subnet_arg \ $new_broadcast_arg $mtu_arg - set $new_routers + set -- $new_routers if ping -q -c 1 $1; then if [ x$new_ip_address != x$alias_ip_address ] && \ [ x$alias_ip_address != x ]; then @@ -201,14 +363,25 @@ if [ x$reason = xTIMEOUT ]; then ( [ $relmajor -eq 2 ] && [ $relminor -eq 0 ] ); then route add -net $new_network_number fi - for router in $new_routers; do - route add default gw $router $metric_arg dev $interface - done - make_resolv_conf + + set_default_gw_route + + if use_netconfig ; then + netconfig_modify + else + make_resolv_conf + fi + exit_with_hooks 0 fi - ifconfig $interface inet 0 down + ifconfig $interface inet 0 exit_with_hooks 1 fi +if use_netconfig ; then + netconfig_remove +else + restore_resolv_conf +fi + exit_with_hooks 0