Home | History | Annotate | Download | only in svc
      1 #!/sbin/sh
      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 # Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24 # Use is subject to license terms.
     25 #
     26 
     27 # Start/stop processes required for server NFS
     28 
     29 . /lib/svc/share/smf_include.sh
     30 . /lib/svc/share/ipf_include.sh
     31 zone=`smf_zonename`
     32 
     33 #
     34 # Handling a corner case here. If we were in offline state due to an
     35 # unsatisfied dependency, the ipf_method process wouldn't have generated
     36 # the ipfilter configuration. When we transition to online because the
     37 # dependency is satisfied, the start method will have to generate the
     38 # ipfilter configuration. To avoid all possible deadlock scenarios,
     39 # we restart ipfilter which will regenerate the ipfilter configuration
     40 # for the entire system.
     41 #
     42 # The ipf_method process signals that it didn't generate ipf rules by
     43 # removing the service's ipf file. Thus we only restart network/ipfilter
     44 # when the file is missing.
     45 #
     46 configure_ipfilter()
     47 {
     48 	ipfile=`fmri_to_file $SMF_FMRI $IPF_SUFFIX`
     49 	[ -f "$ipfile" ] && return 0
     50 
     51         #
     52 	# Nothing to do if:
     53         # - ipfilter isn't online 
     54 	# - global policy is 'custom'
     55 	# - service's policy is 'use_global'
     56         #
     57         service_check_state $IPF_FMRI $SMF_ONLINE || return 0
     58         [ "`get_global_def_policy`" = "custom" ] && return 0
     59 	[ "`get_policy $SMF_FMRI`" = "use_global" ] && return 0
     60 
     61 	svcadm restart $IPF_FMRI
     62 }
     63 
     64 case "$1" in
     65 'start')
     66 	# The NFS server is not supported in a local zone
     67 	if smf_is_nonglobalzone; then
     68 		/usr/sbin/svcadm disable -t svc:/network/nfs/server
     69 		echo "The NFS server is not supported in a local zone"
     70 		sleep 5 &
     71 		exit $SMF_EXIT_OK
     72 	fi
     73 
     74 	# Share all file systems enabled for sharing. sharemgr understands
     75 	# regular shares and ZFS shares and will handle both. Technically,
     76 	# the shares would have been started long before getting here since
     77 	# nfsd has a dependency on them.
     78 
     79 	startnfsd=0
     80 
     81 	# restart stopped shares from the repository
     82 	/usr/sbin/sharemgr start -P nfs -a
     83 
     84 	# Start up mountd and nfsd if anything is exported.
     85 
     86 	if /usr/bin/grep -s nfs /etc/dfs/sharetab >/dev/null; then
     87 		startnfsd=1
     88 	fi
     89 
     90 	# If auto-enable behavior is disabled, always start nfsd
     91 
     92 	if [ `svcprop -p application/auto_enable nfs/server` = "false" ]; then
     93 		startnfsd=1
     94 	fi
     95 
     96 	# Options for nfsd are now set in /etc/default/nfs
     97 	if [ $startnfsd -ne 0 ]; then
     98 		/usr/lib/nfs/mountd
     99 		rc=$?
    100 		if [ $rc != 0 ]; then
    101 			/usr/sbin/svcadm mark -t maintenance svc:/network/nfs/server
    102 			echo "$0: mountd failed with $rc"
    103 			sleep 5 &
    104 			exit $SMF_EXIT_ERR_FATAL
    105 		fi
    106 
    107 		/usr/lib/nfs/nfsd
    108 		rc=$?
    109 		if [ $rc != 0 ]; then
    110 			/usr/sbin/svcadm mark -t maintenance svc:/network/nfs/server
    111 			echo "$0: nfsd failed with $rc"
    112 			sleep 5 &
    113 			exit $SMF_EXIT_ERR_FATAL
    114 		fi
    115 
    116 		configure_ipfilter
    117 	else
    118 		/usr/sbin/svcadm disable -t svc:/network/nfs/server
    119 		echo "No NFS filesystems are shared"
    120 		sleep 5 &
    121 	fi
    122 
    123 	;;
    124 
    125 'refresh')
    126 	/usr/sbin/sharemgr start -P nfs -a
    127 	;;
    128 
    129 'stop')
    130 	/usr/bin/pkill -x -u 0,1 -z $zone '(nfsd|mountd)'
    131 
    132 	# Unshare all shared file systems using NFS
    133 
    134 	/usr/sbin/sharemgr stop -P nfs -a
    135 
    136 	#
    137 	# Wait up to 10 seconds for nfslogd to gracefully handle SIGHUP
    138 	#
    139 	/usr/bin/pkill -HUP -x -u 0 -z $zone nfslogd
    140 	wtime=10
    141 
    142 	while [ $wtime -gt 0 ]; do
    143 		/usr/bin/pgrep -x -u 0 -z $zone nfslogd >/dev/null || break
    144 		wtime=`expr $wtime - 1`
    145 		sleep 1
    146 	done
    147 
    148 	#
    149 	# Kill nfslogd more forcefully if it did not shutdown during
    150 	# the grace period
    151 	#
    152 	if [ $wtime -eq 0 ]; then
    153 		/usr/bin/pkill -TERM -x -u 0 -z $zone nfslogd
    154 	fi
    155 
    156 	# Kill any processes left in service contract
    157 	smf_kill_contract $2 TERM 1
    158 	[ $? -ne 0 ] && exit 1
    159 	;;
    160 
    161 'ipfilter')
    162 	#
    163 	# NFS related services are RPC. nfs/server has nfsd which has
    164 	# well-defined port number but mountd is an RPC daemon.
    165 	#
    166 	# Essentially, we generate rules for the following "services"
    167 	#  - nfs/server which has nfsd and mountd
    168 	#  - nfs/rquota
    169 	#
    170 	# The following services are enabled for both nfs client and
    171 	# server so we'll treat them as client services and simply
    172 	# allow incoming traffic.
    173 	#  - nfs/status
    174 	#  - nfs/nlockmgr
    175 	#  - nfs/cbd
    176 	#
    177 	NFS_FMRI="svc:/network/nfs/server:default"
    178 	RQUOTA_FMRI="svc:/network/nfs/rquota:default"
    179 	FMRI=$2
    180 
    181 	file=`fmri_to_file $FMRI $IPF_SUFFIX`
    182 	echo "# $FMRI" >$file
    183 	policy=`get_policy $NFS_FMRI`
    184 	ip="any"
    185 
    186 	#
    187 	# nfs/server configuration is processed in the start method.
    188 	#
    189 	if [ "$FMRI" = "$NFS_FMRI" ]; then
    190 		service_check_state $FMRI $SMF_ONLINE
    191 		if [ $? -ne 0 ]; then
    192 			rm  $file
    193 			exit $SMF_EXIT_OK
    194 		fi
    195 
    196 		nfs_name=`svcprop -p $FW_CONTEXT_PG/name $FMRI 2>/dev/null`
    197 		tport=`$SERVINFO -p -t -s $nfs_name 2>/dev/null`
    198 		if [ -n "$tport" ]; then
    199 			generate_rules $FMRI $policy "tcp" $ip $tport $file
    200 		fi
    201 
    202 		uport=`$SERVINFO -p -u -s $nfs_name 2>/dev/null`
    203 		if [ -n "$uport" ]; then
    204 			generate_rules $FMRI $policy "udp" $ip $uport $file
    205 		fi
    206 
    207 		tports=`$SERVINFO -R -p -t -s "mountd" 2>/dev/null`
    208 		if [ -n "$tports" ]; then
    209 			for tport in $tports; do
    210 				generate_rules $FMRI $policy "tcp" $ip \
    211 				    $tport $file
    212 			done
    213 		fi
    214 
    215 		uports=`$SERVINFO -R -p -u -s "mountd" 2>/dev/null`
    216 		if [ -n "$uports" ]; then
    217 			for uport in $uports; do
    218 				generate_rules $FMRI $policy "udp" $ip \
    219 				    $uport $file
    220 			done
    221 		fi
    222 
    223 	elif [ "$FMRI" = "$RQUOTA_FMRI" ]; then
    224 		iana_name=`svcprop -p inetd/name $FMRI`
    225 
    226 		tports=`$SERVINFO -R -p -t -s $iana_name 2>/dev/null`
    227 		if [ -n "$tports" ]; then
    228 			for tport in $tports; do
    229 				generate_rules $NFS_FMRI $policy "tcp" \
    230 				    $ip $tport $file
    231 			done
    232 		fi
    233 
    234 		uports=`$SERVINFO -R -p -u -s $iana_name 2>/dev/null`
    235 		if [ -n "$uports" ]; then
    236 			for uport in $uports; do
    237 				generate_rules $NFS_FMRI $policy "udp" \
    238 				    $ip $uport $file
    239 			done
    240 		fi
    241 	else
    242 		#
    243 		# Handle the client services here
    244 		#
    245 		restarter=`svcprop -p general/restarter $FMRI 2>/dev/null`
    246 		if [ "$restarter" = "$INETDFMRI" ]; then
    247 			iana_name=`svcprop -p inetd/name $FMRI`
    248 			isrpc=`svcprop -p inetd/isrpc $FMRI`
    249 		else
    250 			iana_name=`svcprop -p $FW_CONTEXT_PG/name $FMRI`
    251 			isrpc=`svcprop -p $FW_CONTEXT_PG/isrpc $FMRI`
    252 		fi
    253 
    254 		if [ "$isrpc" = "true" ]; then
    255 			tports=`$SERVINFO -R -p -t -s $iana_name 2>/dev/null`
    256 			uports=`$SERVINFO -R -p -u -s $iana_name 2>/dev/null`
    257 		else
    258 			tports=`$SERVINFO -p -t -s $iana_name 2>/dev/null`
    259 			uports=`$SERVINFO -p -u -s $iana_name 2>/dev/null`
    260 		fi
    261 
    262 		if [ -n "$tports" ]; then
    263 			for tport in $tports; do
    264 				echo "pass in log quick proto tcp from any" \
    265 				    "to any port = ${tport} flags S " \
    266 				    "keep state" >>${file}
    267 			done
    268 		fi
    269 
    270 		if [ -n "$uports" ]; then
    271 			for uport in $uports; do
    272 				echo "pass in log quick proto udp from any" \
    273 				    "to any port = ${uport}" >>${file}
    274 			done
    275 		fi
    276 	fi
    277 
    278 	;;
    279 
    280 *)
    281 	echo "Usage: $0 { start | stop | refresh }"
    282 	exit 1
    283 	;;
    284 esac
    285 exit $SMF_EXIT_OK
    286