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