1 #!/usr/bin/ksh
2 #
3 # CDDL HEADER START
4 #
5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
8 #
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
13 #
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 #
20 # CDDL HEADER END
21 #
22
23 #
24 # Copyright 2008 Sun Microsystems, Inc. All rights reserved.
25 # Use is subject to license terms.
26 #
27 # dom_functions.sh - functions used to test the domain rules for nfsmapid
28 #
29 # Note: Some functions in this file uses ckreturn(), a function defined in
30 # testsh.ksh. Please make sure you have already source'd that file
31 # before you source this file.
32
33 # print_state - dumps all information possibly used by nfsmapid to obtain a
34 # domain value from different sources.
35 # all information is sent to stderr, return value is always 0
36 #
37
38 function print_state {
39 echo "\n>>>>>>>>>>>>>>>>>>>>>> DEBUG INFORMATION <<<<<<<<<<<<<<<<<<<<<"
40 echo "============== NFSMAPID_DOMAIN in /etc/default/nfs ============="
41 grep NFSMAPID_DOMAIN /etc/default/nfs
42 echo "======================= /etc/resolv.conf ======================="
43 cat /etc/resolv.conf
44 echo "=========== TXT RR in /var/named/dns.test.nfs.master ==========="
45 grep TXT /var/named/${dns_domain}.master
46 echo "======================= dns server state ======================="
47 svcs -xv svc:/network/dns/server:default
48 echo "========================== dig output =========================="
49 get_domain_txt_record $dns_domain
50 echo "========================== nis domain =========================="
51 domainname
52 echo "======================= nfs mapid domain ======================="
53 cat /var/run/nfs4_domain
54 echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>> END <<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"
55 }
56
57
58 #
59 # get_domain_txt_record - gets a nfsmapid text record from a (local) DNS server
60 # Usage get_domain_txt_record dns_domain
61 # dns_domain name of the dns_domain as specified in DNS files.
62 # function returns 0 on success or 1 on error, stdout has the value of the
63 # text record on success, else stderr has a diagnostic message.
64
65 function get_domain_txt_record {
66 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
67 n=get_domain_txt_record
68 if [ $# -ne 1 ]; then
69 echo "USAGE: $n dns_domain" >&2
70 exit 1
71 fi
72 typeset dns_domain=$1
73 if [ -z "$dns_domain" ]; then
74 echo "\t$n ERROR: DNS domain parameter is \"$dns_domain\"" >&2
75 return 1
76 fi
77 typeset serverName=`uname -n | cut -d. -f1`
78 typeset server=`getent hosts $serverName | cut -f1`
79
80 typeset type=TXT
81 typeset keyword="_nfsv4idmapdomain"
82 typeset ns=dig
83
84
85 pgrep -z `zonename` named 2> /dev/null > /dev/null
86 if [ $? -ne 0 ]; then
87 sleep 3
88 pgrep -z `zonename` named 2> /dev/null > /dev/null
89 if [ $? -ne 0 ]; then
90 echo "\t$n ERROR: DNS server not running" >&2
91 return 1
92 fi
93 fi
94
95
96 typeset res
97 res=$($ns @$server 2>&1)
98 if [ $? -ne 0 ]; then
99 echo "$n ERROR cannot access DNS server \"$server\"" >&2
100 printf "\tdig $server $server returned:\n%s\n" "$res" >&2
101 return 1
102 fi
103 typeset out=$($ns @$server $keyword.$dns_domain $type +domain=$dns_domain 2>&1)
104 typeset keys
105 keys=$(printf "%s\n" "$out" | grep $type | grep $keyword | grep -v ';')
106 if [ $? -ne 0 ]; then
107 echo "\t$n ERROR: DNS server \"$server\" did not have $type "\
108 "records for \"$keyword\"" >&2
109 printf "\t\tTXT records query results:\n%s\n" "$out" >&2
110 echo "===============================\n" >&2
111 return 1
112 fi
113 # if multiple records, use the last one
114 typeset key=$(printf "%s\n" "$keys" | tail -1)
115 typeset domain=$(echo $key | awk '{print $NF}' | awk -F= '{print $NF}' \
116 | sed 's/"//g')
117 if [ -z "$domain" ]; then
118 echo "\t$n ERROR: $type \"$keyword\"record was empty" >&2
119 printf "\t\trecords found were:\n%s\t<===\n" "$keys" >&2
120 echo "===============================\n" >&2
121 return 1
122 fi
123 typeset -l domain=$domain
124 echo $domain
125 return 0
126 }
127
128
129 #
130 # get_nfsmapid_domain - get nfsmapid domain from /var/run/nfs4_domain file
131 # Usage get_nfsmapid_domain
132 # function returns 0 on success or 1 on error, stdout has the value of the
133 # nfsmapid domain on success, else stderr has a diagnostic message.
134
135 function get_nfsmapid_domain {
136 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
137 n=get_nfsmapid_domain
138 if [ $# -ne 0 ]; then
139 echo "USAGE: $n" >&2
140 exit 1
141 fi
142
143 if [ ! -f /var/run/nfs4_domain ]; then
144 echo "/var/run/nfs4_domain file doens't exist" >&2
145 return 1
146 fi
147
148 cat /var/run/nfs4_domain
149 return 0
150 }
151
152
153 #
154 # get_nfsmapid_domain_tout - uses mdb to get nfsmapid's global
155 # nfscfg_domain_tmout
156 # Usage get_nfsmapid_domain_tout
157 # function returns 0 on success or 1 on error, stdout has the value of the
158 # global nfscfg_domain_tmout on success, else stderr has a diagnostic
159 # message.
160
161 function get_nfsmapid_domain_tout {
162 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
163 n=get_nfsmapid_domain_tout
164 if [ $# -ne 0 ]; then
165 echo "USAGE: $n" >&2
166 exit 1
167 fi
168
169 typeset dae=nfsmapid
170 typeset var=nfscfg_domain_tmout
171 typeset Pid=$(pgrep -z `zonename` -x $dae 2> /dev/null)
172 if [ -z "$Pid" ] && [ $D -ne 0 ]; then
173 echo "$n: $dae is not running" >&2
174 return 1
175 fi
176 typeset line=$(echo "$var/D" | mdb -p $Pid 2> $TMPDIR/domain2.$$ | tail -1)
177 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && cat $TMPDIR/domain2.$$
178 rm -f $TMPDIR/domain2.$$ >/dev/null 2>&1
179 # make sure we are getting valid results
180 typeset st=$(echo $line | grep $dae | grep "$var:" | wc -w 2>/dev/null)
181 if [ $st -ne 2 ]; then
182 echo "$n: Cannot get symbol $var from $dae" >&2
183 return 1
184 fi
185 typeset tout=$(echo $line | awk '{print $NF}')
186 echo $tout
187 return 0
188 }
189
190
191 #
192 # get_domain_default_nfs - gets nfsmapid's domain from /etc/default/nfs
193 # Usage get_domain_default_nfs
194 # function returns 0 on success or 1 on error, stdout has the value of the
195 # nfsmapid's domain on success, else stderr has a diagnostic message.
196
197 function get_domain_default_nfs {
198 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
199 n=get_domain_default_nfs
200 if [ $# -ne 0 ]; then
201 echo "USAGE: $n" >&2
202 exit 1
203 fi
204
205 file=/etc/default/nfs
206 str=NFSMAPID_DOMAIN
207 if [ ! -r $file ]; then
208 [ $D -ne 0 ] && echo "$n: Cannot read \"$file\"" >&2
209 return 1
210 fi
211 line=$(grep "^${str}=" $file)
212 st=$?
213 # domain not present
214 if [ $st -ne 0 ]; then
215 echo ""
216 return 0
217 fi
218 # domain present
219 domain=$(echo $line | awk -F= '{print $NF}')
220 typeset -l domain=$domain
221 echo $domain
222 return 0
223 }
224
225
226 #
227 # get_domain_resolv - gets first item on search field, or domain value if
228 # search field is not present, from file /etc/resolv.conf
229 # Usage get_domain_resolv
230 # function returns 0 on success or 1 on error, stdout has the value of the
231 # domain on success, else stderr has a diagnostic message.
232
233 function get_domain_resolv {
234 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
235 n=get_domain_resolv
236 if [ $# -ne 0 ]; then
237 echo "USAGE: $n" >&2
238 exit 1
239 fi
240
241 typeset file=/etc/resolv.conf
242 if [ ! -r $file ] && [ $D -ne 0 ]; then
243 echo "$n: Cannot read \"$file\"" >&2
244 return 1
245 fi
246 #resp;ver gives preference to search over domain
247 typeset str=search
248 typeset line
249 line=$(grep -i "^$str" $file)
250 typeset st=$?
251 typeset domain
252 # search present
253 if [ $st -eq 0 ]; then
254 domain=$(echo $line | awk '{print $2}')
255 typeset -l domain=$domain
256 echo $domain
257 return 0
258 fi
259 str=domain
260 line=$(grep -i "^$str" $file)
261 st=$?
262 # domain present
263 if [ $st -ne 0 ]; then
264 echo ""
265 return 0
266 fi
267 # domain present
268 domain=$(echo $line | awk '{print $2}')
269 typeset -l domain=$domain
270 echo $domain
271 return 0
272 }
273
274
275 #
276 # get_domain_domainname - gets domain value from command domainname
277 # Usage get_domain_domainname
278 # function returns 0 on success or 1 on error, stdout has the value of the
279 # domain on success, else stderr has a diagnostic message.
280
281 function get_domain_domainname {
282 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
283 n=get_domain_domainname
284 if [ $# -ne 0 ]; then
285 echo "USAGE: $n" >&2
286 exit 1
287 fi
288
289 typeset prog=domainname
290 typeset str=domain
291
292 typeset line=$(domainname)
293 typeset st=$?
294 # domain not set
295 if [ $st -ne 0 ] || [ -z "$line" ]; then
296 echo ""
297 return 0
298 fi
299 # domain present
300 typeset sdomain=$(echo $line | awk -F. '{for (i=2 ; i <= NF; i++) print $i}')
301 typeset domain=$(echo $sdomain | sed 's/ /./g')
302 echo $domain
303 return 0
304 }
305
306
307 #
308 # remove_search_from_dns - removes the search field from the file
309 # /etc/resolv.conf
310 # Usage remove_search_from_dns
311 # function returns 0 on success or 1 on error and stderr has a diagnostic
312 # message.
313
314 function remove_search_from_dns {
315 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
316 n=chg_txt_field_dns
317 if [ $# -ne 0 ]; then
318 echo "USAGE: $n" >&2
319 exit 1
320 fi
321
322 typeset file=/etc/resolv.conf
323 typeset key=search
324 sed "s/^${key}.*$//" $file > /tmp/resolv-new
325 if [ $? -ne 0 ]; then
326 echo "Could not remove $key entries in $file" >&2
327 rm -f /tmp/resolv-new > /dev/null 2>&1
328 return 1
329 fi
330 mv /tmp/resolv-new $file
331 if [ $? -ne 0 ]; then
332 echo "Could not remove $key entries in $file" >&2
333 return 1
334 fi
335 return 0
336 }
337
338
339 #
340 # chg_txt_field_dns - change the value of a nfsmapid text record, or the name
341 # and value of such text record for the specified master file.
342 # Usage chg_txt_field_dns master_file {domain | field_name=value}
343 # master_file DNS named config master file to modify
344 # domain domain value for the nfsmapid text field
345 # field_name=value new tag and value to replace the nfsmapid field
346 # function returns 0 on success or 1 on error and stderr has a diagnostic
347 # message.
348
349 function chg_txt_field_dns {
350 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
351 n=chg_txt_field_dns
352 if [ $# -ne 2 ]; then
353 echo "USAGE: $n master_file {domain | field_name=value}" >&2
354 exit 1
355 fi
356 typeset file=$1
357 if [ ! -r $file ]; then
358 echo " Can not read master_file $file" >&2
359 return 1
360 fi
361
362 typeset keyword
363 typeset field
364 typeset dns_txt=$2
365 typeset res
366 res=$(echo $dns_txt | egrep "[a-zA-Z0-9_-]+=.*" 2>&1)
367 if [ $? -ne 0 ]; then
368 keyword="_nfsv4idmapdomain"
369 field="$dns_txt"
370 else
371 keyword="$(echo $dns_txt | awk -F= '{print $1}')"
372 field="$(echo $dns_txt | awk -F= '{print $NF}')"
373 fi
374
375 nawk -v keyword="$keyword" -v field="$field" \
376 '( $2 == "IN" && $3 == "TXT" ) { \
377 printf("%s", keyword); \
378 for (i=2; i < NF; i++) \
379 printf("\t%s", $i); \
380 printf("\t%s\n", field); } \
381 !( $2 == "IN" && $3 == "TXT" ) { \
382 print $0; }' $file > /tmp/master-new
383 if [ $? -ne 0 ]; then
384 echo "Could not change ${str}... in $file" >&2
385 return 1
386 fi
387 cp -p $file $file.old
388 mv /tmp/master-new $file
389 if [ $? -ne 0 ]; then
390 echo "Could not change ${str}... in $file" >&2
391 return 1
392 fi
393 return 0
394 }
395
396
397 #
398 # chg_domain_dns - change the value of the domain field for /etc/resolv.conf
399 # Usage chg_domain_dns new_dns_domain
400 # new_dns_domain domain to replace current value
401 # function returns 0 on success or 1 on error and stderr has a diagnostic
402 # message.
403
404 function chg_domain_dns {
405 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
406 n=chg_domain_dns
407 if [ $# -ne 1 ]; then
408 echo "USAGE: $n dns_domain" >&2
409 exit 1
410 fi
411 typeset dns_domain=$1
412 typeset str=domain
413
414 sed "s/^$str .*\$/$str $dns_domain/" \
415 /etc/resolv.conf > /tmp/resolv-new
416 if [ $? -ne 0 ]; then
417 echo "Could not change $str in /etc/resolv.conf" >&2
418 return 1
419 fi
420 cp -p /etc/resolv.conf /etc/resolv.old
421 mv /tmp/resolv-new /etc/resolv.conf
422 if [ $? -ne 0 ]; then
423 echo "Could not change $str in /etc/resolv.conf" >&2
424 return 1
425 fi
426 return 0
427 }
428
429
430 #
431 # chg_server_dns - change the value of the nameserver field for /etc/resolv.conf
432 # Usage chg_server_dns new_dns_server
433 # new_dns_server nameserver value to replace current value
434 # function returns 0 on success or 1 on error and stderr has a diagnostic
435 # message.
436
437 function chg_server_dns {
438 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
439 n=chg_server_dns
440 if [ $# -ne 1 ]; then
441 echo "USAGE: $n dns_server" >&2
442 exit 1
443 fi
444 typeset server=$1
445 typeset str=nameserver
446 sed "s/^$str .*\$/$str $server/" \
447 /etc/resolv.conf > /tmp/resolv-new
448 if [ $? -ne 0 ]; then
449 echo "Could not change $str in /etc/resolv.conf" >&2
450 return 1
451 fi
452 cp -p /etc/resolv.conf /etc/resolv.old
453 mv /tmp/resolv-new /etc/resolv.conf
454 if [ $? -ne 0 ]; then
455 echo "Could not change $str in /etc/resolv.conf" >&2
456 return 1
457 fi
458 return 0
459 }
460
461
462 #
463 # chg_domain_default_nfs - change the value of the variable NFSMAPID_DOMAIN for
464 # /etc/default/nfs
465 # Usage chg_domain_default_nfs domain
466 # domain new value for the nfsmapid domain
467 # function returns 0 on success or 1 on error and stderr has a diagnostic
468 # message.
469
470 function chg_domain_default_nfs {
471 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
472 n=chg_domain_default_nfs
473 if [ $# -ne 1 ]; then
474 echo "USAGE: $n domain" >&2
475 exit 1
476 fi
477 typeset domain=$1
478 typeset str=NFSMAPID_DOMAIN
479 sed "/$str=.*/d" /etc/default/nfs > /tmp/nfs-new
480 if [ $? -ne 0 ]; then
481 echo "Could not generate tmp file for /etc/default/nfs" >&2
482 return 1
483 fi
484 echo "$str=$domain" >> /tmp/nfs-new
485 cp -p /etc/default/nfs /etc/default/nfs.old
486 mv /tmp/nfs-new /etc/default/nfs
487 if [ $? -ne 0 ]; then
488 echo "Could not change $str in /etc/default/nfs" >&2
489 return 1
490 fi
491 return 0
492 }
493
494
495 #
496 # comm_domain_default_nfs - comment the entry for the variable NFSMAPID_DOMAIN
497 # in /etc/default/nfs
498 # Usage comm_domain_default_nfs
499 # function returns 0 on success or 1 on error and stderr has a diagnostic
500 # message.
501
502 function comm_domain_default_nfs {
503 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
504 n=comm_domain_default_nfs
505
506 sed 's/^NFSMAPID_DOMAIN=/\# NFSMAPID_DOMAIN=/' /etc/default/nfs \
507 > /tmp/nfs-new
508 cp -p /etc/default/nfs /etc/default/nfs.old
509 mv /tmp/nfs-new /etc/default/nfs
510 }
511
512
513 #
514 # uncomm_domain_default_nfs - uncomment the entry for the variable
515 # NFSMAPID_DOMAIN in /etc/default/nfs
516 # Usage uncomm_domain_default_nfs
517 # function returns 0 on success or 1 on error and stderr has a diagnostic
518 # message.
519
520 function uncomm_domain_default_nfs {
521 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
522 n=uncomm_domain_default_nfs
523
524 sed 's/^\#[ \t]*NFSMAPID_DOMAIN=/NFSMAPID_DOMAIN=/' /etc/default/nfs \
525 > /tmp/nfs-new
526 cp -p /etc/default/nfs /etc/default/nfs.old
527 mv /tmp/nfs-new /etc/default/nfs
528 }
529
530
531 #
532 # save_file - stores the source file to a temporal file, can only be used
533 # for one file, and does not "overwrites" the temporal file, so multiple
534 # consecutive calls have the same effect as the first call only. Must be
535 # "reset" by a call to restore_file.
536 # Usage save_file filename
537 # filename source file to be backup in the temporal file
538 # function returns 0 on success or 1 on error and stderr has a diagnostic
539 # message.
540
541 function save_file {
542 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
543 n=save_file
544 if [ $# -ne 1 ]; then
545 echo "USAGE: $n filename" >&2
546 exit 1
547 fi
548
549 typeset TMPNAM="${TMPDIR}/temp_file.$(basename $1).NMAPID.$$"
550 typeset file1=$1
551 [ -e "$TMPNAM" ] && echo "$n: A file was already saved" && return 1
552 [ ! -f "$file1" ] && echo "$n: $file1 not a regular file" && return 1
553 res=$(cp -p $file1 $TMPNAM 2>&1)
554 [ $? -ne 0 ] && echo "$n: $file1 could not be saved" && return 1
555 return 0
556 }
557
558 #
559 # is_saved - checks if the specified file has been saved by save_file() or not.
560 # When one calls save_file() to back up one file, its contents is
561 # stored in a temporal file under $TMPDIR, whose name follows an
562 # implementation specific naming convention. What this function does is
563 # to check the existence of the temporal file. If it exists, the target
564 # file is supposed to be saved.
565 # Usage is_saved filename
566 # filename The target file whose temporal file is checked
567 # function returns 0 if the specified file is saved or 1 if not.
568 function is_saved {
569 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
570 n=is_saved
571 if [ $# -ne 1 ]; then
572 echo "USAGE: $n filename" >&2
573 exit 1
574 fi
575
576 typeset TMPNAM="${TMPDIR}/temp_file.$(basename $1).NMAPID.$$"
577 [ -e "$TMPNAM" ] && return 0
578 return 1
579 }
580
581 #
582 # restore_file - restores the specified file from a temporal file, can only be
583 # used to restore one file, and does not "destroys" the target file,
584 # so after the first call, multiple consecutive calls will fail.
585 # Must be "set" by a call to save_file.
586 # Usage restore_file filename
587 # filename Target file to be replaced by the temporal file
588 # function returns 0 on success or 1 on error and stderr has a diagnostic
589 # message.
590
591 function restore_file {
592 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
593 n=restore_file
594 if [ $# -ne 1 ]; then
595 echo "USAGE: $n filename" >&2
596 exit 1
597 fi
598
599 typeset TMPNAM="${TMPDIR}/temp_file.$(basename $1).NMAPID.$$"
600 typeset file1=$1
601 [ ! -e "$TMPNAM" ] && echo "$n: No file has been saved yet" && return 1
602 res=$(/usr/bin/mv -f $TMPNAM $file1 2>&1)
603 [ $? -ne 0 ] && echo "$n: $file1 could not be saved" && return 1
604 return 0
605 }
606
607 # Function get_nfsmapid_domain_tout_wrapper
608 # A simple wrapper around get_nfsmapid_domain_tout() function. This
609 # function calls get_nfsmapid_domain_tout() to get nfscfg_domain_tmout,
610 # increase it a bit, and then output it. If the call of
611 # get_nfsmapid_domain_tout() fails, the function output default value of
612 # 305 seconds, and if DEBUG is turned on, outputs error message on stderr.
613 # Usage
614 # get_nfsmapid_domain_tout_wrapper
615 # Return value
616 # On success it output timeout value on stdout; On failure it outputs
617 # default timeout(305 seconds) on stdout, and error message on stderr.
618
619 function get_nfsmapid_domain_tout_wrapper {
620 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
621 typeset timeout=$(get_nfsmapid_domain_tout 2>$TMPDIR/tout.err.$$)
622
623 ckreturn $? "failed to get nfsmapid timeout value" \
624 $TMPDIR/tout.err.$$ "WARNING" || timeout=300
625
626 rm -f $TMPDIR/tout.err.$$ >/dev/null 2>&1
627
628 timeout=$(($timeout + 5))
629 echo $timeout
630 }
631
632 # Function get_second_dns_server
633 # This function searchs for another dns server(instead of the one that
634 # we set up locally)which have TXT record. It will first check
635 # if $DNS_SERVER have TXT record. If so, $DNS_SERVER is returned; Otherwise
636 # 129.149.246.6(sundns1.sfbay.sun.com) is checked. If that doesn't have
637 # TXT record either, the function fails.
638 # Usage
639 # get_second_dns_server
640 # Return value
641 # On success it outputs the second dns server, its domain, and its txt
642 # record in the form of "server_name domain txt_record" and returns 0.
643 # On failure it outputs nothing and returns 1.
644
645 function get_second_dns_server {
646 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
647 n=get_second_dns_server
648
649 #
650 # Check if DNS_SERVER have TXT record
651 #
652
653 typeset dns_server_addr=$(getent hosts $DNS_SERVER | head -1 | cut -f1)
654 typeset txt_record
655 typeset dns_domain
656 typeset res
657
658 if [[ -n "$dns_server_addr" ]]; then
659 dns_domain=$(get_domain $dns_server_addr)
660 fi
661
662 if [[ -n "$dns_server_addr" && -n "$dns_domain" ]]; then
663 res=$(/usr/sbin/nslookup -domain=$dns_domain \
664 -query=txt _nfsv4idmapdomain $DNS_SERVER \
665 | grep "_nfsv4idmapdomain.*text.*=" 2>&1)
666
667 if [[ -n "$res" ]]; then
668 # the server has TXT RR for requested domain
669 txt_record=$(echo $res | cut -d'"' -f2)
670 echo "$dns_server_addr $dns_domain $txt_record"
671 return 0
672 fi
673 fi
674
675 #
676 # Then check 129.149.246.6 as last resort
677 #
678
679 res=$(/usr/sbin/nslookup -domain=sfbay.sun.com \
680 -query=txt _nfsv4idmapdomain 129.149.246.6 \
681 | grep "_nfsv4idmapdomain.*text.*=")
682
683 if [[ -n "$res" ]]; then
684 # the server has TXT RR for requested domain
685 txt_record=$(echo $res | cut -d'"' -f2)
686 echo "129.149.246.6 sfbay.sun.com $txt_record"
687 return 0
688 fi
689
690 return 1
691 }
692
693 # Function mapid_service
694 # refreshes, and restarts mapid service. The function is a wrapper
695 # around smf_fmri_transition_state(), which itself is a wrapper around
696 # svcadm command. It helps to save some typing, as well as
697 # to avoid the timing issue found when using smf_fmri_transition_state()
698 # to restart mapid service
699 # Usage
700 # mapid_service restart|refresh timeout errmsg result
701 # Return value
702 # function returns 0 on success
703 # or 1 on error and stdout has a diagnostic message.
704
705 function mapid_service {
706 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x && D=1
707 n=mapid_service
708 if (( $# < 3 )); then
709 echo "USAGE: $n restart|refresh timeout errmsg result" >&2
710 return 1
711 fi
712
713 typeset action=$1
714 typeset timeout=$2
715 typeset errmsg=$3
716 (($# > 3 )) && typeset result=$4
717
718 typeset logfile=$TMPDIR/mapid_service.tmp.$$
719 typeset ret
720
721 case $action in
722 restart )
723 smf_fmri_transition_state \
724 do svc:/network/nfs/mapid:default disabled $timeout \
725 >$logfile 2>&1
726 ckreturn $? "$errmsg" $logfile $result || return 1
727
728 smf_fmri_transition_state \
729 do svc:/network/nfs/mapid:default online $timeout \
730 >$logfile 2>&1
731 ckreturn $? "$errmsg" $logfile $result || return 1
732 ;;
733 refresh )
734 # s10(up-to-u6) doesn't have "refresh" method for nfsmapid
735 typeset os_rel=$(uname -r)
736 if echo $os_rel | grep "5.10." >/dev/null 2>&1 || \
737 echo $os_rel | grep "5.11" >/dev/null 2>&1;
738 then
739 svcadm refresh mapid >$logfile 2>&1 && sleep 3
740 ckreturn $? "$errmsg" $logfile $result || return 1
741 else
742 # so we use kill, but need to make sure
743 # the HUP signal is sent to the right process
744 kill -HUP `cat /etc/svc/volatile/nfs-mapid.lock` \
745 >$logfile 2>&1 && sleep 3
746 ckreturn $? "$errmsg" $logfile $result || return 1
747 fi
748 ;;
749 * )
750 echo "USAGE: $n restart|refresh timeout errmsg result" >&2
751 return 1
752 ;;
753 esac
754
755 rm -f $logfile >/dev/null 2>&1
756 return 0
757 }
758
759 # Function dns_service
760 # enables, disables, and restarts dns service. This function is a
761 # wrapper around smf_fmri_transition_state(), which itself is a wrapper
762 # around svcadm.
763 #
764 # Notes: while I used "svcadm restart svc:/network/dns/server:default"
765 # to restart dns server set up by dnscfg.ksh, I found the command
766 # didn't always work. Normally it took much time than expected,
767 # sometimes the service was never brought up anymore. For that reason,
768 # I would implement restart action by first disabling and then
769 # enabling it.
770 # Usage
771 # dns_service enable|disable|restart timeout errmsg resstr
772 # Return value
773 # returns 0 on success or 1 on error and stdout has a diagnostic
774 # message.
775
776 function dns_service {
777 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x && D=1
778 n=dns_service
779
780 if (( $# < 3 )); then
781 echo "USAGE: $n enable|disable|restart timeout errmsg [resstr]" >&2
782 return 1
783 fi
784
785 typeset action=$1
786 typeset timeout=$2
787 typeset errmsg=$3
788 (( $# > 3 )) && typeset resstr=$4
789 typeset ret
790 typeset logfile=$TMPDIR/dns_service.tmp.$$
791
792 case $action in
793 enable )
794 smf_fmri_transition_state \
795 do svc:/network/dns/server:default online ${timeout} \
796 >$logfile 2>&1
797 ckreturn $? "$errmsg" $logfile $resstr || return 1
798 ;;
799 disable )
800 smf_fmri_transition_state \
801 do svc:/network/dns/server:default disabled ${timeout} \
802 >$logfile 2>&1
803 ckreturn $? "$errmsg" $logfile $resstr || return 1
804 ;;
805 restart )
806 smf_fmri_transition_state \
807 do svc:/network/dns/server:default disabled ${timeout} \
808 >$logfile 2>&1
809 ckreturn $? "$errmsg" $logfile $resstr || return 1
810
811 smf_fmri_transition_state \
812 do svc:/network/dns/server:default online ${timeout} \
813 >$logfile 2>&1
814 ckreturn $? "$errmsg" $logfile $resstr || return 1
815 ;;
816 * )
817 echo "USAGE: $n enable|disable|restart timeout" >&2
818 return 1
819 ;;
820 esac
821
822 rm -f $logfile >/dev/null 2>&1
823 return 0
824 }
825
826 #
827 # Function get_dns_txt_cache_flag
828 # the function checks if we have access to dns_txt_cached variable
829 # in nfsmapid proccess via mdb. The varible is a flag in nfsmapid
830 # to indicate if the cached txt rr is valid or not.
831 # Usage
832 # get_dns_txt_cache_flag
833 # Return Value
834 # returns 0 on success, and output value of dns_txt_cached on stdout;
835 # returns 1 on error, and output error message on stderr.
836
837 function get_dns_txt_cache_flag {
838 [ -n "$DEBUG" ] && [ $DEBUG != 0 ] && set -x
839 n=get_dns_txt_cache_flag
840
841 typeset logfile=$TMPDIR/txt.tmp.$$
842
843 typeset daemon=nfsmapid
844 typeset pid=$(pgrep -z `zonename` -x $daemon 2>/dev/null)
845 if [[ -z "$pid" ]]; then
846 # no nfsmapid process found
847 echo "$n: $daemon is not running" 1>&2
848 return 1
849 fi
850
851 typeset var=dns_txt_cached
852 typeset result=$(echo "$var/D" | mdb -p $pid 2>$logfile | tail -1)
853 typeset found=$(echo $result | grep "$var:" | wc -w 2>/dev/null)
854 if [[ $found -ne 2 ]]; then
855 cat $logfile && rm -f $logfile
856 echo "$n: Cannot get symbol $var from $daemon" >&2
857 return 1
858 fi
859
860 echo $result | nawk '{print $NF}'
861
862 rm -f $logfile
863
864 return 0
865 }
866
867 # save_state - saves the system's current state(files, smf services' state,
868 # etc.), which can be restored later by calling restore_state().
869 # The function takes one argument to name the state to be saved. User
870 # can call this function consecutively to save system states at
871 # different stages during test script execution.
872 # Usage: save_state <state_name>
873 # state_name - the name for the state
874 # function returns 0 on success or 1 on error, stderr has a diagnostic message
875 # on error.
876 #
877
878 function save_state {
879 [[ -n "$DEBUG" ]] && [[ $DEBUG != 0 ]] && set -x
880 n=save_state
881 logfile=$TMPDIR/save_state.$$
882
883 if [[ $# != 1 ]]; then
884 echo "USAGE: $n tag"
885 return 1
886 fi
887 state_name=$1
888
889 # create a temporary directory
890 STATE_DIR=$TMPDIR/system_state.$$.$state_name
891 rm -rf $STATE_DIR >$logfile 2>&1 \
892 && mkdir $STATE_DIR >$logfile 2>&1
893 ckreturn $? "$n: failed to remove/create directory" $logfile "ERROR" \
894 || return 1
895
896 # save /etc/default/nfs
897 cp /etc/default/nfs $STATE_DIR/etc.default.nfs >$logfile 2>&1
898 ckreturn $? "$n: failed to save /etc/default/nfs" $logfile "ERROR" \
899 || return 1
900
901 # save /etc/resolv.conf if it exists
902 if [[ -f /etc/resolv.conf ]]; then
903 cp /etc/resolv.conf $STATE_DIR/etc.resolv.conf >$logfile 2>&1
904 ckreturn $? "$n: failed to save /etc/resolv.conf" $logfile \
905 "ERROR" || return 1
906 fi
907
908 # save /etc/named.conf if it exists
909 if [[ -f /etc/named.conf ]]; then
910 cp /etc/named.conf $STATE_DIR/etc.named.conf >$logfile 2>&1
911 ckreturn $? "$n: failed to save /etc/named.conf" $logfile \
912 "ERROR" || return 1
913 fi
914
915 # save /var/named directory if it exists
916 if [[ -d /var/named ]]; then
917 tar cf $STATE_DIR/var.named /var/named >$logfile 2>&1
918 ckreturn $? "$n: failed to save /var/named" $logfile "ERROR" \
919 || return 1
920 fi
921
922 # save NIS domain
923 domainname > $STATE_DIR/domainname
924
925 rm -f $logfile
926 }
927
928 # restore_state - restore a system state which was previously saved by
929 # save_state(). The function takes one argument, which specify the state
930 # to be restored.
931 # Usage: restore_state -c <state_name>
932 # -c - If this option is set, this function not only restores the
933 # original state on the system, but also removes the temporary
934 # files used to save the state; otherwise, those files are not
935 # removed by default.
936 # state_name - the name for the state
937 # function returns 0 on success or an non-zero value on error, stderr has a
938 # diagnostic message on error.
939 #
940
941 function restore_state {
942 [[ -n "$DEBUG" ]] && [[ $DEBUG != 0 ]] && set -x
943 n=restore_state
944 logfile=$TMPDIR/restore_state.$$
945
946 if (( $# < 1 )); then
947 echo "USAGE: $n -c state_name"
948 return 1
949 fi
950
951 removefile=0
952 if [[ "$1" == "-c" ]]; then
953 removefile=1
954 shift
955 fi
956 state_name=$1
957
958 STATE_DIR=$TMPDIR/system_state.$$.$state_name
959 if [[ ! -d $STATE_DIR ]]; then
960 echo "$state_name state doesn't exists!"
961 return 1
962 fi
963 ret=0
964
965 # If any of the following operations fails, the function doesn't
966 # return immediately. Instead, it continues to restore the system
967 # state as much as possible.
968
969 # resotre /etc/default/nfs
970 cp $STATE_DIR/etc.default.nfs /etc/default/nfs >$logfile 2>&1
971 ckreturn $? "$n: failed to restore /etc/default/nfs" $logfile "ERROR"
972 ret=$((ret + $?))
973
974 # restore /etc/resolv.conf if the back up exists
975 if [[ -f $STATE_DIR/etc.resolv.conf ]]; then
976 cp $STATE_DIR/etc.resolv.conf /etc/resolv.conf >$logfile 2>&1
977 ckreturn $? "$n: failed to restore /etc/resolv.conf" $logfile \
978 "ERROR"
979 ret=$((ret + $?))
980 else
981 rm -f /etc/resolv.conf
982 fi
983
984 # disable DNS server temporarily
985 dns_service disable 6 "failed to disable dns service" "ERROR"
986 ret=$((ret + $?))
987
988 # restore /etc/named.conf if the back up exists
989 if [[ -f $STATE_DIR/etc.named.conf ]]; then
990 cp $STATE_DIR/etc.named.conf /etc/named.conf >$logfile 2>&1
991 ckreturn $? "$n: failed to restore /etc/named.conf" $logfile \
992 "ERROR"
993 ret=$((ret + $?))
994 else
995 rm -f /etc/named.conf
996 fi
997
998 # restore /var/named directory if it exists
999 if [[ -f $STATE_DIR/var.named ]]; then
1000 tar xf $STATE_DIR/var.named >$logfile 2>&1
1001 ckreturn $? "$n: failed to restore /var/named" $logfile "ERROR"
1002 ret=$((ret + $?))
1003 else
1004 rm -rf /var/named
1005 ret=$((ret + $?))
1006 fi
1007
1008 # start dns server if necessary
1009 [[ -f /etc/named.conf ]] \
1010 && dns_service enable 6 "failed to disable dns service" "ERROR"
1011 ret=$((ret + $?))
1012
1013 # resotre NIS domain
1014 domainname $(cat $STATE_DIR/domainname) 2>$logfile
1015 ckreturn $? "$n: failed to restore NIS domain" $logfile "ERROR"
1016 ret=$((ret + $?))
1017
1018 # restart mapid service
1019 mapid_service refresh 6 "failed to restart mapid service" "UNRESOLVED"
1020 ret=$((ret + $?))
1021
1022 [[ $removefile -eq 1 ]] && rm -rf $STATE_DIR
1023 rm -f $logfile
1024
1025 return $ret
1026 }
1027
1028 # clear_state - clear a system state which was previously saved by
1029 # save_state(), which means, to remove the temporary files and directory
1030 # used for it.
1031 # Usage: clear_state <state_name>
1032 # state_name - the name for the state
1033 # function returns 0 on success or 1 if the state is unknown(that is, the
1034 # directory for it is not found).
1035 #
1036 function clear_state {
1037 [[ -n "$DEBUG" ]] && [[ $DEBUG != 0 ]] && set -x
1038 n=clear_state
1039 logfile=$TMPDIR/clear_state.$$
1040
1041 if (( $# < 1 )); then
1042 echo "USAGE: $n state_name"
1043 return 1
1044 fi
1045 state_name=$1
1046
1047 STATE_DIR=$TMPDIR/system_state.$$.$state_name
1048 if [[ ! -d $STATE_DIR ]]; then
1049 echo "$state_name state doesn't exists!"
1050 return 1
1051 fi
1052
1053 rm -rf $STATE_DIR
1054 }
1055
1056 # gen_assert_desc - generates assertion descriptions from the comments in
1057 # function headers.
1058 # Usage: gen_assert_desc file keyword
1059 # file - the file to be scanned
1060 # prefix - the prefix of assertion names, which is used to construct
1061 # a pattern to search for assertion descriptions. It can be null.
1062 # function always return 0.
1063 #
1064 function gen_assert_desc {
1065 [[ -n "$DEBUG" ]] && [[ $DEBUG != 0 ]] && set -x
1066
1067 file=$1
1068 assert_prefix=$2
1069
1070 grep "^# ${assert_prefix}.*: " $file >$TMPFILE 2>/dev/null
1071 set -A assert_names $(cat $TMPFILE | cut -d' ' -f2 | sed 's/://g')
1072 x=0
1073 while (( $x < ${#assert_names[*]} )); do
1074 assert_descs[$x]=$( \
1075 nawk -v assert=${assert_names[$x]} \
1076 'BEGIN { pattern = "# " assert ": "; } \
1077 (index($0, pattern ) != 0) { \
1078 $0 = substr($0, length(pattern)+1); \
1079 getline nextline; \
1080 while (index(nextline, "#\t") != 0) { \
1081 $0 = $0 " " substr(nextline, 3); \
1082 getline nextline; \
1083 } \
1084 print $0; \
1085 }' $file)
1086 x=$((x + 1))
1087 done
1088 rm -f $TMPFILE
1089 }
1090
1091 # get_assert_desc - gets assertion description from database generated by
1092 # gen_assert_desc(), for a specific assertion
1093 # Usage: get_assert_desc assert
1094 # assert - the name of the assertion to be search for
1095 # function always return 0.
1096 #
1097
1098 function get_assert_desc {
1099 [[ -n "$DEBUG" ]] && [[ $DEBUG != 0 ]] && set -x
1100
1101 assert=$assert_prefix$1
1102
1103 x=0
1104 while (( $x < ${#assert_names[*]} )); do
1105 [[ ${assert_names[$x]} == "$assert" ]] \
1106 && echo "${assert_descs[$x]}"
1107 x=$((x + 1))
1108 done
1109 }