xref: /netbsd-src/external/mpl/dhcp/dist/client/scripts/macos (revision 6fb29d29285c26a62fae51364e3aa9f51d403424)
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