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