configuration-templates – Blame information for rev 24
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
23 | office | 1 | #!/bin/sh |
2 | ########################################################################### |
||
3 | ## Copyright (C) Wizardry and Steamworks 2017 - License: GNU GPLv3 ## |
||
4 | ## Please see: http://www.gnu.org/licenses/gpl.html for legal details, ## |
||
5 | ## rights of fair usage, the disclaimer and warranty conditions. ## |
||
6 | ########################################################################### |
||
7 | # openvpn-osx-tuntap.sh # |
||
8 | # Up / Down script for OpenVPN running on OSX as a client. # |
||
9 | # The OpenVPN server is expected to serve clients with IP addresses via # |
||
10 | # a previously configured DHCP server. # |
||
11 | # Note that this script does not replace the default route but instead # |
||
12 | # uses the Mac OS capability of using scoped DNS servers to make the # |
||
13 | # remote network available whilst preserving the default route. # |
||
14 | # # |
||
15 | # Based on: # |
||
16 | # - 2006-09-21, Ben Low - original version # |
||
17 | # - Nick Williams - for TunnelBrick # |
||
18 | # - Jonathan K. Bullard - additions for Mountain Lion # |
||
19 | ########################################################################### |
||
20 | |||
21 | ########################################################################### |
||
22 | # CONFIGURATION # |
||
23 | ########################################################################### |
||
24 | # A MAC address for the tunnel interface. |
||
25 | STATIC_TUNTAP_MAC_ADDRESS="42:75:e2:67:43:db" |
||
26 | # Whether to prepend domain names instead of replacing the exiting ones. |
||
27 | PREPEND_DOMAIN_NAME="false" |
||
28 | |||
29 | ########################################################################### |
||
30 | # INTERNALS # |
||
31 | ########################################################################### |
||
32 | |||
33 | # Regular expression for matching IP addresses. |
||
34 | IPRX="(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)" |
||
35 | # Domain name regular expression. |
||
36 | DOMRX="(?:[A-Za-z0-9][A-Za-z0-9\-]{0,61}[A-Za-z0-9]|[A-Za-z0-9])" |
||
37 | |||
38 | ########################################################################### |
||
39 | # Utility function to flush the DNS cache on various Mac OS releases. # |
||
40 | ########################################################################### |
||
41 | flushDNSCache() |
||
42 | { |
||
43 | if [ "${OSVER}" = "10.4" ] ; then |
||
24 | office | 44 | if [ -f /usr/sbin/lookupd ] ; then |
45 | set +e # we will catch errors from lookupd |
||
46 | /usr/sbin/lookupd -flushcache |
||
47 | set -e # bash should again fail on errors |
||
48 | fi |
||
49 | else |
||
50 | if [ -f /usr/bin/dscacheutil ] ; then |
||
51 | set +e # we will catch errors from dscacheutil |
||
52 | /usr/bin/dscacheutil -flushcache |
||
53 | set -e # bash should again fail on errors |
||
54 | fi |
||
55 | if [ -f /usr/sbin/discoveryutil ] ; then |
||
56 | set +e # we will catch errors from discoveryutil |
||
57 | /usr/sbin/discoveryutil udnsflushcaches |
||
58 | /usr/sbin/discoveryutil mdnsflushcache |
||
59 | set -e # bash should again fail on errors |
||
60 | fi |
||
61 | set +e # "grep" will return error status (1) if no matches are found, so don't fail on individual errors |
||
62 | hands_off_ps="$( ps -ax | grep HandsOffDaemon | grep -v grep.HandsOffDaemon )" |
||
63 | set -e # We instruct bash that it CAN again fail on errors |
||
64 | if [ -z "${hands_off_ps}" ] ; then |
||
65 | if [ -f /usr/bin/killall ] ; then |
||
66 | set +e # ignore errors if mDNSResponder isn't currently running |
||
67 | /usr/bin/killall -HUP mDNSResponder |
||
68 | set -e # bash should again fail on errors |
||
69 | fi |
||
70 | fi |
||
71 | fi |
||
23 | office | 72 | } |
73 | |||
74 | ########################################################################### |
||
75 | # Sets all dynamic DHCP options on the tuntap interface. # |
||
76 | ########################################################################### |
||
77 | setDnsServersAndDomainName() |
||
78 | { |
||
79 | readonly PSID="DHCP-$dev" |
||
80 | |||
81 | # Set up the DYN_* variables to contain what is asked for (dynamically, by a 'push' directive, for example) |
||
24 | office | 82 | declare -a vDNS=("${!1}") |
83 | declare -a vSMB=("${!3}") |
||
84 | declare -a vSD=("${!4}") |
||
23 | office | 85 | |
24 | office | 86 | if [ ${#vDNS[*]} -eq 0 ] ; then |
87 | readonly DYN_DNS_SA="" |
||
88 | else |
||
89 | readonly DYN_DNS_SA="${!1}" |
||
90 | fi |
||
91 | |||
92 | if [ ${#vSMB[*]} -eq 0 ] ; then |
||
93 | readonly DYN_SMB_WA="" |
||
94 | else |
||
95 | readonly DYN_SMB_WA="${!3}" |
||
96 | fi |
||
23 | office | 97 | |
24 | office | 98 | if [ ${#vSD[*]} -eq 0 ] ; then |
99 | readonly DYN_DNS_SD="" |
||
100 | else |
||
101 | readonly DYN_DNS_SD="${!4}" |
||
102 | fi |
||
23 | office | 103 | |
24 | office | 104 | DYN_DNS_DN="$2" |
105 | |||
23 | office | 106 | # set up the FIN_* variables with what we want to set things to |
24 | office | 107 | # Three FIN_* variables are simple -- no aggregation is done for them |
108 | if [ ! -z "${DYN_DNS_DN}" ] ; then |
||
109 | readonly FIN_DNS_DN="${DYN_DNS_DN}" |
||
110 | else |
||
111 | readonly FIN_DNS_DN="" |
||
112 | fi |
||
113 | |||
114 | if [ ! -z "${DYN_SMB_NN}" ] ; then |
||
115 | readonly FIN_SMB_NN="${DYN_SMB_NN}" |
||
116 | else |
||
117 | readonly FIN_SMB_NN="" |
||
118 | fi |
||
119 | |||
120 | if [ ! -z "${DYN_SMB_WG}" ] ; then |
||
121 | readonly FIN_SMB_WG="${DYN_SMB_WG}" |
||
122 | else |
||
123 | readonly FIN_SMB_WG="" |
||
124 | fi |
||
23 | office | 125 | |
24 | office | 126 | # DNS ServerAddresses (FIN_DNS_SA) are aggregated for 10.4 and 10.5 |
127 | if [ ${#vDNS[*]} -eq 0 ] ; then |
||
128 | readonly FIN_DNS_SA="" |
||
129 | else |
||
130 | case "${OSVER}" in |
||
131 | 10.4 | 10.5 ) |
||
132 | # We need to remove duplicate DNS entries, so that our reference list matches MacOSX's |
||
133 | SDNS="$( echo -n "${DYN_DNS_SA}" | tr ' ' '\n' )" |
||
23 | office | 134 | i=0 |
24 | office | 135 | for n in "${vDNS[@]}" ; do |
136 | if echo -n "${SDNS}" | grep -q "${n}" ; then |
||
137 | unset vDNS[${i}] |
||
138 | fi |
||
23 | office | 139 | let i++ |
24 | office | 140 | done |
141 | if [ ${#vDNS[*]} -gt 0 ] ; then |
||
142 | readonly FIN_DNS_SA="$( echo -n "${DYN_DNS_SA}" | sed s/"${vDNS[*]}"//g )" |
||
143 | else |
||
144 | readonly FIN_DNS_SA="${DYN_DNS_SA}" |
||
145 | fi |
||
146 | ;; |
||
147 | * ) |
||
148 | # Do nothing - in 10.6 and higher -- we don't aggregate our configurations, apparently |
||
149 | readonly FIN_DNS_SA="${DYN_DNS_SA}" |
||
150 | ;; |
||
151 | esac |
||
152 | fi |
||
23 | office | 153 | |
24 | office | 154 | # SMB WINSAddresses (FIN_SMB_WA) are aggregated for 10.4 and 10.5 |
155 | if [ ${#vSMB[*]} -eq 0 ] ; then |
||
156 | readonly FIN_SMB_WA="" |
||
157 | else |
||
158 | case "${OSVER}" in |
||
159 | 10.4 | 10.5 ) |
||
160 | # We need to remove duplicate SMB entries, so that our reference list matches MacOSX's |
||
161 | SSMB="$( echo -n "${DYN_SMB_WA}" | tr ' ' '\n' )" |
||
23 | office | 162 | i=0 |
24 | office | 163 | for n in "${vSMB[@]}" ; do |
164 | if echo -n "${SSMB}" | grep -q "${n}" ; then |
||
165 | unset vSMB[${i}] |
||
166 | fi |
||
23 | office | 167 | let i++ |
24 | office | 168 | done |
169 | if [ ${#vSMB[*]} -gt 0 ] ; then |
||
170 | readonly FIN_SMB_WA="$( echo -n "${DYN_SMB_WA}" | sed s/"${vSMB[*]}"//g )" |
||
171 | else |
||
172 | readonly FIN_SMB_WA="${DYN_SMB_WA}" |
||
173 | fi |
||
174 | ;; |
||
175 | * ) |
||
176 | # Do nothing - in 10.6 and higher -- we don't aggregate our configurations, apparently |
||
177 | readonly FIN_SMB_WA="${DYN_SMB_WA}" |
||
178 | ;; |
||
179 | esac |
||
180 | fi |
||
23 | office | 181 | |
24 | office | 182 | # DNS SearchDomains (FIN_DNS_SD) is treated specially |
183 | # |
||
184 | # OLD BEHAVIOR: |
||
185 | # if SearchDomains was not set manually, we set SearchDomains to the DomainName |
||
186 | # else |
||
187 | # In OS X 10.4-10.5, we add the DomainName to the end of any manual SearchDomains (unless it is already there) |
||
188 | # In OS X 10.6+, if SearchDomains was entered manually, we ignore the DomainName |
||
189 | # else we set SearchDomains to the DomainName |
||
190 | # |
||
191 | # NEW BEHAVIOR (done if ARG_PREPEND_DOMAIN_NAME is "true"): |
||
192 | # |
||
193 | # if SearchDomains was entered manually, we do nothing |
||
194 | # else we PREpend new SearchDomains (if any) to the existing SearchDomains (NOT replacing them) |
||
195 | # and PREpend DomainName to that |
||
196 | # |
||
197 | # (done if ARG_PREPEND_DOMAIN_NAME is "false" and there are new SearchDomains from DOMAIN-SEARCH): |
||
198 | # |
||
199 | # if SearchDomains was entered manually, we do nothing |
||
200 | # else we PREpend any new SearchDomains to the existing SearchDomains (NOT replacing them) |
||
201 | # |
||
202 | # This behavior is meant to behave like Linux with Network Manager and Windows |
||
203 | if "${PREPEND_DOMAIN_NAME}" ; then |
||
204 | if [ ! -z "${DYN_DNS_SD}" ] ; then |
||
23 | office | 205 | readonly TMP_DNS_SD="${DYN_DNS_SD}" |
24 | office | 206 | if [ ! -z "${FIN_DNS_DN}" -a "${FIN_DNS_DN}" != "localdomain" ]; then |
23 | office | 207 | if ! echo -n "${TMP_DNS_SD}" | tr ' ' '\n' | grep -q "${FIN_DNS_DN}" ; then |
208 | readonly FIN_DNS_SD="$( echo -n "${FIN_DNS_DN}" | sed s/"${TMP_DNS_SD}"//g )" |
||
209 | else |
||
210 | readonly FIN_DNS_SD="${TMP_DNS_SD}" |
||
211 | fi |
||
212 | else |
||
24 | office | 213 | readonly FIN_DNS_SD="${TMP_DNS_SD}" |
214 | fi |
||
23 | office | 215 | else |
216 | readonly FIN_DNS_SD="${DYN_DNS_SD}" |
||
217 | fi |
||
24 | office | 218 | else |
219 | if [ ! -z "${DYN_DNS_SD}" ] ; then |
||
220 | readonly FIN_DNS_SD="${DYN_DNS_SD}" |
||
221 | else |
||
23 | office | 222 | if [ ! -z "${FIN_DNS_DN}" -a "${FIN_DNS_DN}" != "localdomain" ] ; then |
223 | case "${OSVER}" in |
||
224 | 10.4 | 10.5 ) |
||
225 | readonly FIN_DNS_SD="${FIN_DNS_DN}" |
||
226 | ;; |
||
227 | * ) |
||
228 | readonly FIN_DNS_SD="${FIN_DNS_DN}" |
||
229 | ;; |
||
230 | esac |
||
231 | else |
||
232 | readonly FIN_DNS_SD="" |
||
233 | fi |
||
24 | office | 234 | fi |
235 | fi |
||
23 | office | 236 | |
237 | # Set up SKP_* variables to inhibit scutil from making some changes |
||
24 | office | 238 | # SKP_DNS_* and SKP_SMB_* are used to comment out individual items |
23 | office | 239 | # that are not being set |
24 | office | 240 | if [ -z "${FIN_DNS_DN}" ] ; then |
241 | SKP_DNS_DN="#" |
||
242 | else |
||
243 | SKP_DNS_DN="" |
||
244 | fi |
||
245 | if [ -z "${FIN_DNS_SA}" ] ; then |
||
246 | SKP_DNS_SA="#" |
||
247 | else |
||
248 | SKP_DNS_SA="" |
||
249 | fi |
||
250 | if [ -z "${FIN_DNS_SD}" ] ; then |
||
251 | SKP_DNS_SD="#" |
||
252 | else |
||
253 | SKP_DNS_SD="" |
||
254 | fi |
||
255 | if [ -z "${FIN_SMB_NN}" ] ; then |
||
256 | SKP_SMB_NN="#" |
||
257 | else |
||
258 | SKP_SMB_NN="" |
||
259 | fi |
||
260 | if [ -z "${FIN_SMB_WG}" ] ; then |
||
261 | SKP_SMB_WG="#" |
||
262 | else |
||
263 | SKP_SMB_WG="" |
||
264 | fi |
||
265 | if [ -z "${FIN_SMB_WA}" ] ; then |
||
266 | SKP_SMB_WA="#" |
||
267 | else |
||
268 | SKP_SMB_WA="" |
||
269 | fi |
||
270 | |||
271 | # if any DNS items should be set, set all that have values |
||
272 | if [ "${SKP_DNS_DN}${SKP_DNS_SA}${SKP_DNS_SD}" = "###" ] ; then |
||
273 | readonly SKP_DNS="#" |
||
274 | else |
||
275 | readonly SKP_DNS="" |
||
276 | if [ ! -z "${FIN_DNS_DN}" ] ; then |
||
277 | SKP_DNS_DN="" |
||
278 | fi |
||
279 | if [ ! -z "${FIN_DNS_SA}" ] ; then |
||
280 | SKP_DNS_SA="" |
||
281 | fi |
||
282 | if [ ! -z "${FIN_DNS_SD}" ] ; then |
||
283 | SKP_DNS_SD="" |
||
284 | fi |
||
285 | fi |
||
23 | office | 286 | |
24 | office | 287 | # if any SMB items should be set, set all that have values |
288 | if [ "${SKP_SMB_NN}${SKP_SMB_WG}${SKP_SMB_WA}" = "###" ] ; then |
||
289 | readonly SKP_SMB="#" |
||
290 | else |
||
291 | readonly SKP_SMB="" |
||
292 | if [ ! -z "${FIN_SMB_NN}" ] ; then |
||
293 | SKP_SMB_NN="" |
||
294 | fi |
||
295 | if [ ! -z "${FIN_SMB_WG}" ] ; then |
||
296 | SKP_SMB_WG="" |
||
297 | fi |
||
298 | if [ ! -z "${FIN_SMB_WA}" ] ; then |
||
299 | SKP_SMB_WA="" |
||
300 | fi |
||
301 | fi |
||
23 | office | 302 | |
24 | office | 303 | readonly SKP_DNS_SA SKP_DNS_SD SKP_DNS_DN |
304 | readonly SKP_SMB_NN SKP_SMB_WG SKP_SMB_WA |
||
305 | |||
23 | office | 306 | # special-case fiddling: |
24 | office | 307 | # 10.8+ : ServerAddresses and SearchDomains must be set via the Setup: |
23 | office | 308 | # key in addition to the State: key |
24 | office | 309 | # 10.7 : if ServerAddresses or SearchDomains are manually set, |
23 | office | 310 | # ServerAddresses and SearchDomains must be similarly set with the |
311 | # Setup: key in addition to the State: key |
||
24 | office | 312 | case "${OSVER}" in |
313 | 10.4 | 10.5 | 10.6 | 10.7 ) |
||
314 | readonly SKP_SETUP_DNS="#" |
||
315 | ;; |
||
316 | * ) |
||
317 | readonly SKP_SETUP_DNS="" |
||
318 | ;; |
||
319 | esac |
||
320 | |||
23 | office | 321 | # Set all parameters. |
24 | office | 322 | /usr/sbin/scutil >/dev/null 2>&1 <<-EOF |
323 | open |
||
324 | |||
325 | # Initialize the new DNS map via State: |
||
326 | ${SKP_DNS}d.init |
||
327 | ${SKP_DNS}${SKP_DNS_SA}d.add ServerAddresses * ${FIN_DNS_SA} |
||
328 | ${SKP_DNS}${SKP_DNS_SD}d.add SearchDomains * ${FIN_DNS_SD} |
||
329 | ${SKP_DNS}${SKP_DNS_DN}d.add DomainName ${FIN_DNS_DN} |
||
23 | office | 330 | ${SKP_DNS}${SKP_DNS_DN}d.add SupplementalMatchDomains * ${FIN_DNS_DN} |
24 | office | 331 | ${SKP_DNS}set State:/Network/Service/${PSID}/DNS |
23 | office | 332 | |
24 | office | 333 | # If necessary, initialize the new DNS map via Setup: also |
334 | ${SKP_SETUP_DNS}${SKP_DNS}d.init |
||
335 | ${SKP_SETUP_DNS}${SKP_DNS}${SKP_DNS_SA}d.add ServerAddresses * ${FIN_DNS_SA} |
||
336 | ${SKP_SETUP_DNS}${SKP_DNS}${SKP_DNS_SD}d.add SearchDomains * ${FIN_DNS_SD} |
||
337 | ${SKP_SETUP_DNS}${SKP_DNS}${SKP_DNS_DN}d.add DomainName ${FIN_DNS_DN} |
||
338 | ${SKP_SETUP_DNS}${SKP_DNS}set Setup:/Network/Service/${PSID}/DNS |
||
23 | office | 339 | |
24 | office | 340 | # Initialize the SMB map |
341 | ${SKP_SMB}d.init |
||
342 | ${SKP_SMB}${SKP_SMB_NN}d.add NetBIOSName ${FIN_SMB_NN} |
||
343 | ${SKP_SMB}${SKP_SMB_WG}d.add Workgroup ${FIN_SMB_WG} |
||
344 | ${SKP_SMB}${SKP_SMB_WA}d.add WINSAddresses * ${FIN_SMB_WA} |
||
345 | ${SKP_SMB}set State:/Network/Service/${PSID}/SMB |
||
23 | office | 346 | |
24 | office | 347 | quit |
23 | office | 348 | EOF |
349 | |||
350 | } |
||
351 | |||
352 | # If OpenVPN has not brought up the device, then terminate. |
||
353 | if [ -z "$dev" ]; then |
||
24 | office | 354 | echo "$0: \$dev not defined, exiting"; |
355 | exit 1; |
||
23 | office | 356 | fi |
357 | |||
358 | # OpenVPN passes $script_type set to the script method. |
||
359 | case "$script_type" in |
||
360 | up) |
||
361 | |||
362 | # Set the MAC address for the tuntap device for static DHCP bindings |
||
363 | /sbin/ifconfig "$dev" ether $STATIC_TUNTAP_MAC_ADDRESS |
||
364 | # Set the interface to DHCP |
||
365 | /usr/sbin/ipconfig set "$dev" DHCP |
||
366 | |||
367 | { |
||
368 | # Issue the waitall command - even if it does not wait. |
||
369 | /usr/sbin/ipconfig waitall |
||
370 | |||
371 | unset PACKET |
||
372 | |||
373 | # Spin and check for packet from the tap device |
||
374 | set +e |
||
375 | n=0 |
||
376 | while [ -z "$PACKET" -a $n -lt 60 ] ; do |
||
24 | office | 377 | PACKET="$( /usr/sbin/ipconfig getpacket "$dev" )" |
23 | office | 378 | let n++ |
379 | sleep 1 |
||
380 | done |
||
381 | set -e |
||
382 | |||
383 | # Get packet to set options |
||
384 | if [ -z "$PACKET" ]; then |
||
385 | exit 1 |
||
386 | fi |
||
387 | |||
388 | unset DOMAIN_NAME |
||
389 | unset DOMAIN_NAME_SERVERS |
||
390 | unset SEARCH_DOMAINS |
||
391 | unset WINS_SERVERS |
||
392 | |||
393 | set +e |
||
394 | # Get domain name |
||
24 | office | 395 | DOMAIN_NAME="$( echo -n "$PACKET" | grep "domain_name " | grep -Eo ": $DOMRX" | grep -Eo "$DOMRX" | tr -d [:space:] )" |
23 | office | 396 | |
397 | # Get nameservers |
||
398 | DOMAIN_NAME_SERVERS_INDEX=1 |
||
399 | for DOMAIN_NAME_SERVER in $( echo -n "$PACKET" | grep "domain_name_server" | grep -Eo "\{($IPRX)(, $IPRX)*\}" | grep -Eo "($IPRX)" ); do |
||
400 | DOMAIN_NAME_SERVERS[DOMAIN_NAME_SERVERS_INDEX-1]=$DOMAIN_NAME_SERVER |
||
401 | let DOMAIN_NAME_SERVERS_INDEX++ |
||
402 | done |
||
403 | |||
404 | # Get search domains |
||
405 | SEARCH_DOMAINS_INDEX=1 |
||
24 | office | 406 | for SEARCH_DOMAIN in $( echo -n "$PACKET" | grep "search_domain" | grep -Eo "\{($DOMRX)(, $DOMRX)*\}" | grep -Eo "($DOMRX)" ); do |
407 | SEARCH_DOMAINS[SEARCH_DOMAINS_INDEX-1]=$SEARCH_DOMAIN |
||
408 | let SEARCH_DOMAINS_INDEX++ |
||
409 | done |
||
23 | office | 410 | |
411 | # Get WINS servers |
||
412 | WINS_SERVERS_INDEX=1 |
||
24 | office | 413 | for WINS_SERVER in $( echo -n "$PACKET" | grep "nb_over_tcpip_name_server" | grep -Eo "\{($IPRX)(, $IPRX)*\}" | grep -Eo "($IPRX)" ); do |
414 | WINS_SERVERS[WINS_SERVERS_INDEX-1]=$WINS_SERVER |
||
415 | let WINS_SERVERS_INDEX++ |
||
416 | done |
||
23 | office | 417 | |
24 | office | 418 | if [ ${#DOMAIN_NAME_SERVERS[*]} -gt 0 -a "$DOMAIN_NAME" ]; then |
419 | setDnsServersAndDomainName DOMAIN_NAME_SERVERS[@] "$DOMAIN_NAME" WINS_SERVERS[@] SEARCH_DOMAINS[@] |
||
23 | office | 420 | elif [ ${#DOMAIN_NAME_SERVERS[*]} -gt 0 ]; then |
24 | office | 421 | setDnsServersAndDomainName DOMAIN_NAME_SERVERS[@] "$DEFAULT_DOMAIN_NAME" WINS_SERVERS[@] SEARCH_DOMAINS[@] |
23 | office | 422 | else |
423 | exit 1 |
||
24 | office | 424 | fi |
23 | office | 425 | |
426 | set -e |
||
427 | |||
24 | office | 428 | sleep 1 |
23 | office | 429 | |
24 | office | 430 | flushDNSCache |
23 | office | 431 | |
24 | office | 432 | exit 0 |
23 | office | 433 | } & |
434 | ;; |
||
435 | down) |
||
436 | sleep 1 |
||
437 | |||
438 | /usr/sbin/scutil >/dev/null 2>&1 <<-EOF |
||
439 | open |
||
440 | remove State:/Network/Service/DHCP-$dev/IPv4 |
||
441 | remove State:/Network/Service/DHCP-$dev/DNS |
||
442 | close |
||
443 | EOF |
||
444 | |||
445 | flushDNSCache |
||
446 | |||
447 | exit 0 |
||
448 | ;; |
||
449 | *) |
||
450 | echo "$0: invalid script_type" && exit 1 |
||
451 | ;; |
||
452 | esac |
||
453 |