Home | History | Annotate | Line # | Download | only in scripts
      1 #!/bin/sh
      2 #
      3 # Id: macos,v 1.4 2011/09/20 16:59:54 sar Exp 
      4 #
      5 # automous run of this script will commit the DNS setting
      6 #
      7 
      8 if [ -x /usr/bin/logger ]; then
      9 	LOGGER="/usr/bin/logger -s -p user.notice -t dhclient"
     10 else
     11 	LOGGER=echo
     12 fi
     13 
     14 to_commit="yes"
     15 
     16 make_resolv_conf() {
     17   to_commit="no"
     18   if [ "x${new_dhcp6_name_servers}" != x ]; then
     19     ( cat /dev/null > /var/run/resolv.conf.dhclient6 )
     20     exit_status=$?
     21     if [ $exit_status -ne 0 ]; then
     22       $LOGGER "Unable to create /var/run/resolv.conf.dhclient6: Error $exit_status"
     23     else
     24       if [ "x${new_dhcp6_domain_search}" != x ]; then
     25 	( echo search ${new_dhcp6_domain_search} >> /var/run/resolv.conf.dhclient6 )
     26 	exit_status=$?
     27       fi
     28       for nameserver in ${new_dhcp6_name_servers} ; do
     29 	if [ $exit_status -ne 0 ]; then
     30 	  break
     31 	fi
     32 	# If the nameserver has a link-local address
     33 	# add a <zone_id> (interface name) to it.
     34 	case $nameserver in
     35 	    fe80:*) zone_id="%$interface";;
     36 	    FE80:*) zone_id="%$interface";;
     37 	   *)      zone_id="";;
     38 	esac
     39         ( echo nameserver ${nameserver}$zone_id >> /etc/resolv.conf.dhclient6 )
     40 	exit_status=$?
     41       done
     42 
     43       if [ $exit_status -eq 0 ]; then
     44 	to_commit="force"
     45 	commit_resolv_conf
     46       fi
     47     fi
     48   fi
     49 }
     50 
     51 # Try to commit /var/run/resolv.conf.dhclient6 contents to
     52 # System Configuration framework's Dynamic Store.
     53 # Note this will be cleared by the next location change
     54 # or preempted by IPv4.
     55 #
     56 # The System Configuration agent "IPMonitor" gets the DNS configuration
     57 # from the IPv4 or IPv6 primary service in the Dynamic Store
     58 # (managed by configd).
     59 commit_resolv_conf() {
     60   if [ -f /var/run/resolv.conf.dhclient6 ]; then
     61     if [ -x /usr/sbin/scutil ]; then
     62       serviceID=`echo show State:/Network/Global/IPv6 | \
     63           /usr/sbin/scutil | \
     64           awk '/PrimaryService/ { print $3 }'`
     65       echo $serviceID
     66       if [ x$serviceID = x ]; then
     67         $LOGGER "Can't find the primary IPv6 service"
     68       else
     69         tmp=`mktemp SC_dhclient6.XXXXXXXXXX`
     70         echo list | /usr/sbin/scutil > /tmp/$tmp
     71         grep -q State:/Network/Service/$serviceID/DNS /tmp/$tmp
     72         grep_status=$?
     73         if [ $grep_status -eq 0 ]; then
     74           $LOGGER "DNS service already set in primary IPv6 service"
     75           rm /tmp/$tmp
     76         else
     77           res=/var/run/resolv.conf.dhclient6
     78           cp /dev/null /tmp/$tmp
     79           grep -q '^nameserver' $res
     80           grep_status=$?
     81           if [ $grep_status -eq 0 ]; then
     82             echo d.add ServerAddresses '*' \
     83                  `awk 'BEGIN { n="" } \
     84                        /^nameserver/ { n=n " " $2 } \
     85                        END { print n}' < $res` >> /tmp/$tmp
     86           fi
     87           grep -q '^search' $res
     88           grep_status=$?
     89           if [ $grep_status -eq 0 ]; then
     90             echo d.add SearchDomains '*' \
     91                  `sed 's/^search//' < $res` >> /tmp/$tmp
     92           fi
     93           echo set State:/Network/Service/$serviceID/DNS >> /tmp/$tmp
     94           echo quit >> /tmp/$tmp
     95           cat /tmp/$tmp
     96           /usr/sbin/scutil < /tmp/$tmp
     97           rm /tmp/$tmp
     98         fi
     99       fi
    100     else
    101       $LOGGER "Can't find SystemConfiguration tools."
    102     fi
    103   else
    104     if [ $to_commit = force ]; then
    105       $LOGGER "Can't find /var/run/resolv.conf.dhclient6"
    106     fi
    107   fi
    108   to_commit="done"
    109 }
    110 
    111 # This function was largely borrowed from dhclient-script that
    112 # ships with Centos, authored by Jiri Popelka and David Cantrell
    113 # of Redhat. Thanks guys.
    114 add_ipv6_addr_with_DAD() {
    115     ifconfig ${interface} inet6 ${new_ip6_address}/${new_ip6_prefixlen} alias
    116 
    117     if [ ${dad_wait_time} -le 0 ]
    118     then
    119         # if we're not waiting for DAD, assume we're good
    120         return 0
    121     fi
    122 
    123     # Repeatedly test whether newly added address passed
    124     # duplicate address detection (DAD)
    125     for i in $(seq 1 ${dad_wait_time}); do
    126         sleep 1 # give the DAD some time
    127 
    128         addr=$(ifconfig ${interface} \
    129             | grep "${new_ip6_address} prefixlen ${new_ip6_prefixlen}")
    130 
    131         # tentative flag == DAD is still not complete
    132         tentative=$(echo "${addr}" | grep tentative)
    133         # dadfailed flag == address is already in use somewhere else
    134         dadfailed=$(echo "${addr}" | grep duplicated)
    135 
    136         if [ -n "${dadfailed}" ] ; then
    137             # dad failed, remove the address
    138             ifconfig ${interface} inet6 ${new_ip6_address}/${new_ip6_prefixlen} -alias
    139             exit_with_hooks 3
    140         fi
    141 
    142         if [ -z "${tentative}" ] ; then
    143             if [ -n "${addr}" ]; then
    144                 # DAD is over
    145                 return 0
    146             else
    147                 # address was auto-removed (or not added at all)
    148                 exit_with_hooks 3
    149             fi
    150         fi
    151     done
    152 
    153     return 0
    154 }
    155 
    156 # Must be used on exit.   Invokes the local dhcp client exit hooks, if any.
    157 exit_with_hooks() {
    158   exit_status=$1
    159   if [ -f /etc/dhclient-exit-hooks ]; then
    160     . /etc/dhclient-exit-hooks
    161   fi
    162 # probably should do something with exit status of the local script
    163   exit $exit_status
    164 }
    165 
    166 # Invoke the local dhcp client enter hooks, if they exist.
    167 if [ -f /etc/dhclient-enter-hooks ]; then
    168   exit_status=0
    169   . /etc/dhclient-enter-hooks
    170   # allow the local script to abort processing of this state
    171   # local script must set exit_status variable to nonzero.
    172   if [ $exit_status -ne 0 ]; then
    173     exit $exit_status
    174   fi
    175 fi
    176 
    177 if [ x$reason = xMEDIUM ]; then
    178   eval "ifconfig $interface $medium"
    179   eval "ifconfig $interface inet -alias 0.0.0.0 $medium" >/dev/null 2>&1
    180   sleep 1
    181   exit_with_hooks 0
    182 fi
    183 
    184 ###
    185 ### DHCPv6 Handlers
    186 ###
    187 
    188 if [ x$reason = xPREINIT6 ]; then
    189   # Ensure interface is up.
    190   ifconfig ${interface} up
    191 
    192   # We need to give the kernel some time to active interface
    193   interface_up_wait_time=5
    194   for i in $(seq 0 ${interface_up_wait_time})
    195   do
    196       ifconfig ${interface} | grep inactive &> /dev/null
    197       if [ $? -ne 0 ]; then
    198           break;
    199       fi
    200       sleep 1
    201   done
    202 
    203   # XXX: Remove any stale addresses from aborted clients.
    204 
    205   # Wait for duplicate address detection for this interface if the
    206   # --dad-wait-time parameter has been specified and is greater than
    207   # zero.
    208   if [ ${dad_wait_time} -gt 0 ]; then
    209       # Check if any IPv6 address on this interface is marked as
    210       # tentative.
    211       ifconfig ${interface} | grep inet6 | grep tentative \
    212           &> /dev/null
    213       if [ $? -eq 0 ]; then
    214           # Wait for duplicate address detection to complete or for
    215           # the timeout specified as --dad-wait-time.
    216           for i in $(seq 0 $dad_wait_time)
    217           do
    218               # We're going to poll for the tentative flag every second.
    219               sleep 1
    220               ifconfig ${interface} | grep inet6 | grep tentative \
    221                   &> /dev/null
    222               if [ $? -ne 0 ]; then
    223                   break;
    224               fi
    225           done
    226       fi
    227   fi
    228 
    229   exit_with_hooks 0
    230 fi
    231 
    232 if [ x${old_ip6_prefix} != x ] || [ x${new_ip6_prefix} != x ]; then
    233     echo Prefix $reason old=${old_ip6_prefix} new=${new_ip6_prefix}
    234 
    235     exit_with_hooks 0
    236 fi
    237 
    238 if [ x$reason = xBOUND6 ]; then
    239   if [ x${new_ip6_address} = x ] || [ x${new_ip6_prefixlen} = x ]; then
    240     exit_with_hooks 2;
    241   fi
    242 
    243   # Add address to interface, check for DAD if dad_wait_time > 0
    244   add_ipv6_addr_with_DAD
    245 
    246   # Check for nameserver options.
    247   make_resolv_conf
    248 
    249   exit_with_hooks 0
    250 fi
    251 
    252 if [ x$reason = xRENEW6 ] || [ x$reason = xREBIND6 ]; then
    253   # Make sure nothing has moved around on us.
    254 
    255   # Nameservers/domains/etc.
    256   if [ "x${new_dhcp6_name_servers}" != "x${old_dhcp6_name_servers}" ] ||
    257      [ "x${new_dhcp6_domain_search}" != "x${old_dhcp6_domain_search}" ]; then
    258     make_resolv_conf
    259   fi
    260 
    261   exit_with_hooks 0
    262 fi
    263 
    264 if [ x$reason = xDEPREF6 ]; then
    265   if [ x${new_ip6_address} = x ]; then
    266     exit_with_hooks 2;
    267   fi
    268 
    269   ifconfig ${interface} inet6 ${new_ip6_address} deprecated
    270 
    271   exit_with_hooks 0
    272 fi
    273 
    274 if [ x$reason = xEXPIRE6 -o x$reason = xRELEASE6 -o x$reason = xSTOP6 ]; then
    275   if [ x${old_ip6_address} = x ] || [ x${old_ip6_prefixlen} = x ]; then
    276     exit_with_hooks 2;
    277   fi
    278 
    279   ifconfig ${interface} inet6 ${old_ip6_address}/${old_ip6_prefixlen} -alias
    280 
    281   exit_with_hooks 0
    282 fi
    283 
    284 if [ $to_commit = yes ]; then
    285   commit_resolv_conf
    286 fi
    287 
    288 exit_with_hooks 0
    289