1#!/bin/bash 2# dhclient-script for Linux. Dan Halbert, March, 1997. 3# Updated for Linux 2.[12] by Brian J. Murrell, January 1999. 4# No guarantees about this. I'm a novice at the details of Linux 5# networking. 6 7# Notes: 8 9# 0. This script is based on the netbsd script supplied with dhcp-970306. 10 11# 1. ifconfig down apparently deletes all relevant routes and flushes 12# the arp cache, so this doesn't need to be done explicitly. 13 14# 2. The alias address handling here has not been tested AT ALL. 15# I'm just going by the doc of modern Linux ip aliasing, which uses 16# notations like eth0:0, eth0:1, for each alias. 17 18# 3. I have to calculate the network address, and calculate the broadcast 19# address if it is not supplied. This might be much more easily done 20# by the dhclient C code, and passed on. 21 22# 4. TIMEOUT not tested. ping has a flag I don't know, and I'm suspicious 23# of the $1 in its args. 24 25# 'ip' just looks too weird. /sbin/ip looks less weird. 26ip=/sbin/ip 27 28make_resolv_conf() { 29 if [ x"$new_domain_name_servers" != x ]; then 30 cat /dev/null > /etc/resolv.conf.dhclient 31 chmod 644 /etc/resolv.conf.dhclient 32 if [ x"$new_domain_search" != x ]; then 33 echo search $new_domain_search >> /etc/resolv.conf.dhclient 34 elif [ x"$new_domain_name" != x ]; then 35 # Note that the DHCP 'Domain Name Option' is really just a domain 36 # name, and that this practice of using the domain name option as 37 # a search path is both nonstandard and deprecated. 38 echo search $new_domain_name >> /etc/resolv.conf.dhclient 39 fi 40 for nameserver in $new_domain_name_servers; do 41 echo nameserver $nameserver >>/etc/resolv.conf.dhclient 42 done 43 44 mv /etc/resolv.conf.dhclient /etc/resolv.conf 45 elif [ "x${new_dhcp6_name_servers}" != x ] ; then 46 cat /dev/null > /etc/resolv.conf.dhclient6 47 chmod 644 /etc/resolv.conf.dhclient6 48 49 if [ "x${new_dhcp6_domain_search}" != x ] ; then 50 echo search ${new_dhcp6_domain_search} >> /etc/resolv.conf.dhclient6 51 fi 52 shopt -s nocasematch 53 for nameserver in ${new_dhcp6_name_servers} ; do 54 # If the nameserver has a link-local address 55 # add a <zone_id> (interface name) to it. 56 if [[ "$nameserver" =~ ^fe80:: ]] 57 then 58 zone_id="%$interface" 59 else 60 zone_id= 61 fi 62 echo nameserver ${nameserver}$zone_id >> /etc/resolv.conf.dhclient6 63 done 64 shopt -u nocasematch 65 66 mv /etc/resolv.conf.dhclient6 /etc/resolv.conf 67 fi 68} 69 70# Must be used on exit. Invokes the local dhcp client exit hooks, if any. 71exit_with_hooks() { 72 exit_status=$1 73 if [ -f /etc/dhclient-exit-hooks ]; then 74 . /etc/dhclient-exit-hooks 75 fi 76# probably should do something with exit status of the local script 77 exit $exit_status 78} 79 80# Invoke the local dhcp client enter hooks, if they exist. 81if [ -f /etc/dhclient-enter-hooks ]; then 82 exit_status=0 83 . /etc/dhclient-enter-hooks 84 # allow the local script to abort processing of this state 85 # local script must set exit_status variable to nonzero. 86 if [ $exit_status -ne 0 ]; then 87 exit $exit_status 88 fi 89fi 90 91### 92### DHCPv4 Handlers 93### 94 95if [ x$new_broadcast_address != x ]; then 96 new_broadcast_arg="broadcast $new_broadcast_address" 97fi 98if [ x$old_broadcast_address != x ]; then 99 old_broadcast_arg="broadcast $old_broadcast_address" 100fi 101if [ x$new_subnet_mask != x ]; then 102 new_subnet_arg="netmask $new_subnet_mask" 103fi 104if [ x$old_subnet_mask != x ]; then 105 old_subnet_arg="netmask $old_subnet_mask" 106fi 107if [ x$alias_subnet_mask != x ]; then 108 alias_subnet_arg="netmask $alias_subnet_mask" 109fi 110if [ x$new_interface_mtu != x ]; then 111 mtu_arg="mtu $new_interface_mtu" 112fi 113if [ x$IF_METRIC != x ]; then 114 metric_arg="metric $IF_METRIC" 115fi 116 117if [ x$reason = xMEDIUM ]; then 118 # Linux doesn't do mediums (ok, ok, media). 119 exit_with_hooks 0 120fi 121 122if [ x$reason = xPREINIT ]; then 123 if [ x$alias_ip_address != x ]; then 124 # Bring down alias interface. Its routes will disappear too. 125 ifconfig $interface:0- inet 0 126 fi 127 ifconfig $interface 0 up 128 129 # We need to give the kernel some time to get the interface up. 130 sleep 1 131 132 exit_with_hooks 0 133fi 134 135if [ x$reason = xARPCHECK ] || [ x$reason = xARPSEND ]; then 136 exit_with_hooks 0 137fi 138 139if [ x$reason = xBOUND ] || [ x$reason = xRENEW ] || \ 140 [ x$reason = xREBIND ] || [ x$reason = xREBOOT ]; then 141 current_hostname=`hostname` 142 if [ x$current_hostname = x ] || \ 143 [ x$current_hostname = "x(none)" ] || \ 144 [ x$current_hostname = xlocalhost ] || \ 145 [ x$current_hostname = x$old_host_name ]; then 146 if [ x$new_host_name != x$old_host_name ]; then 147 hostname "$new_host_name" 148 fi 149 fi 150 151 if [ x$old_ip_address != x ] && [ x$alias_ip_address != x ] && \ 152 [ x$alias_ip_address != x$old_ip_address ]; then 153 # Possible new alias. Remove old alias. 154 ifconfig $interface:0- inet 0 155 fi 156 if [ x$old_ip_address != x ] && [ x$old_ip_address != x$new_ip_address ]; then 157 # IP address changed. Bringing down the interface will delete all routes, 158 # and clear the ARP cache. 159 ifconfig $interface inet 0 down 160 161 fi 162 if [ x$old_ip_address = x ] || [ x$old_ip_address != x$new_ip_address ] || \ 163 [ x$reason = xBOUND ] || [ x$reason = xREBOOT ]; then 164 165 ifconfig $interface inet $new_ip_address $new_subnet_arg \ 166 $new_broadcast_arg $mtu_arg 167 # Add a network route to the computed network address. 168 for router in $new_routers; do 169 if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then 170 route add -host $router dev $interface 171 fi 172 route add default gw $router $metric_arg dev $interface 173 done 174 else 175 # we haven't changed the address, have we changed other options 176 # that we wish to update? 177 if [ x$new_routers != x ] && [ x$new_routers != x$old_routers ] ; then 178 # if we've changed routers delete the old and add the new. 179 for router in $old_routers; do 180 route del default gw $router 181 done 182 for router in $new_routers; do 183 if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then 184 route add -host $router dev $interface 185 fi 186 route add default gw $router $metric_arg dev $interface 187 done 188 fi 189 fi 190 if [ x$new_ip_address != x$alias_ip_address ] && [ x$alias_ip_address != x ]; 191 then 192 ifconfig $interface:0- inet 0 193 ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg 194 route add -host $alias_ip_address $interface:0 195 fi 196 make_resolv_conf 197 exit_with_hooks 0 198fi 199 200if [ x$reason = xEXPIRE ] || [ x$reason = xFAIL ] || [ x$reason = xRELEASE ] \ 201 || [ x$reason = xSTOP ]; then 202 if [ x$alias_ip_address != x ]; then 203 # Turn off alias interface. 204 ifconfig $interface:0- inet 0 205 fi 206 if [ x$old_ip_address != x ]; then 207 # Shut down interface, which will delete routes and clear arp cache. 208 ifconfig $interface inet 0 down 209 fi 210 if [ x$alias_ip_address != x ]; then 211 ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg 212 route add -host $alias_ip_address $interface:0 213 fi 214 exit_with_hooks 0 215fi 216 217if [ x$reason = xTIMEOUT ]; then 218 if [ x$alias_ip_address != x ]; then 219 ifconfig $interface:0- inet 0 220 fi 221 ifconfig $interface inet $new_ip_address $new_subnet_arg \ 222 $new_broadcast_arg $mtu_arg 223 set $new_routers 224 if ping -q -c 1 $1; then 225 if [ x$new_ip_address != x$alias_ip_address ] && \ 226 [ x$alias_ip_address != x ]; then 227 ifconfig $interface:0 inet $alias_ip_address $alias_subnet_arg 228 route add -host $alias_ip_address dev $interface:0 229 fi 230 for router in $new_routers; do 231 if [ "x$new_subnet_mask" = "x255.255.255.255" ] ; then 232 route add -host $router dev $interface 233 fi 234 route add default gw $router $metric_arg dev $interface 235 done 236 make_resolv_conf 237 exit_with_hooks 0 238 fi 239 ifconfig $interface inet 0 down 240 exit_with_hooks 1 241fi 242 243### 244### DHCPv6 Handlers 245### 246 247if [ x$reason = xPREINIT6 ] ; then 248 # Ensure interface is up. 249 ${ip} link set ${interface} up 250 251 # Remove any stale addresses from aborted clients. 252 ${ip} -f inet6 addr flush dev ${interface} scope global permanent 253 254 exit_with_hooks 0 255fi 256 257if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ] ; then 258 echo Prefix ${reason} old=${old_ip6_prefix} new=${new_ip6_prefix} 259 260 exit_with_hooks 0 261fi 262 263if [ x$reason = xBOUND6 ] ; then 264 if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then 265 exit_with_hooks 2; 266 fi 267 268 ${ip} -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \ 269 dev ${interface} scope global 270 271 # Check for nameserver options. 272 make_resolv_conf 273 274 exit_with_hooks 0 275fi 276 277if [ x$reason = xRENEW6 ] || [ x$reason = xREBIND6 ] ; then 278 if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ] ; then 279 exit_with_hooks 2; 280 fi 281 282 ${ip} -f inet6 addr add ${new_ip6_address}/${new_ip6_prefixlen} \ 283 dev ${interface} scope global 284 285 # Make sure nothing has moved around on us. 286 287 # Nameservers/domains/etc. 288 if [ "x${new_dhcp6_name_servers}" != "x${old_dhcp6_name_servers}" ] || 289 [ "x${new_dhcp6_domain_search}" != "x${old_dhcp6_domain_search}" ] ; then 290 make_resolv_conf 291 fi 292 293 exit_with_hooks 0 294fi 295 296if [ x$reason = xDEPREF6 ] ; then 297 if [ x${new_ip6_prefixlen} = x ] ; then 298 exit_with_hooks 2; 299 fi 300 301 ${ip} -f inet6 addr change ${new_ip6_address}/${new_ip6_prefixlen} \ 302 dev ${interface} scope global preferred_lft 0 303 304 exit_with_hooks 0 305fi 306 307if [ x$reason = xEXPIRE6 -o x$reason = xRELEASE6 -o x$reason = xSTOP6 ] ; then 308 if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ] ; then 309 exit_with_hooks 2; 310 fi 311 312 ${ip} -f inet6 addr del ${old_ip6_address}/${old_ip6_prefixlen} \ 313 dev ${interface} 314 315 exit_with_hooks 0 316fi 317 318exit_with_hooks 0 319