#!/usr/sbin/sh # # Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. # # Start/stop processes required for server NFS . /lib/svc/share/smf_include.sh . /lib/svc/share/ipf_include.sh zone=`smf_zonename` # # Handling a corner case here. If we were in offline state due to an # unsatisfied dependency, the ipf_method process wouldn't have generated # the ipfilter configuration. When we transition to online because the # dependency is satisfied, the start method will have to generate the # ipfilter configuration. To avoid all possible deadlock scenarios, # we restart ipfilter which will regenerate the ipfilter configuration # for the entire system. # # The ipf_method process signals that it didn't generate ipf rules by # removing the service's ipf file. Thus we only restart network/ipfilter # when the file is missing. # configure_ipfilter() { svcs network/ipfilter > /dev/null 2>&1 || return 0 ipfile=`fmri_to_file $SMF_FMRI $IPF_SUFFIX` [ -f "$ipfile" ] && return 0 # # Nothing to do if: # - ipfilter isn't online # - global policy is 'custom' # - service's policy is 'use_global' # service_check_state $IPF_FMRI $SMF_ONLINE || return 0 [ "`get_global_def_policy`" = "custom" ] && return 0 [ "`get_policy $SMF_FMRI`" = "use_global" ] && return 0 svcadm restart $IPF_FMRI } case "$1" in 'start') # # NFS server is not supported in 'strict' profile. # Do not even try to start NFS server if the zone (global or # non-global) is configured with 'strict' file-mac-profile # if [ `smf_zone_file_mac_profile` = "strict" ]; then echo "NFS server is not supported in immutable zone" >&2 echo "configured with 'strict' file-mac-profile" >&2 smf_method_exit $SMF_EXIT_ERR_PERM file_mac_profile_strict \ "$SMF_FMRI is not supported in immutable zone configured \ with 'strict' file-mac-profile." fi # Share all file systems enabled for sharing. The # share(unshare) command can start(stop) all shares startnfsd=0 # restart stopped shares from the repository /usr/sbin/share -F nfs -a # Start up mountd and nfsd if anything is exported. if /usr/bin/grep -s nfs /etc/dfs/sharetab >/dev/null; then startnfsd=1 fi # If auto-enable behavior is disabled, always start nfsd if [ `svcprop -p application/auto_enable nfs/server` = "false" ]; then startnfsd=1 fi # Options for nfsd are now set in SMF if [ $startnfsd -ne 0 ]; then /usr/lib/nfs/mountd rc=$? if [ $rc != 0 ]; then /usr/sbin/svcadm mark -t maintenance svc:/network/nfs/server echo "$0: mountd failed with $rc" sleep 5 & exit $SMF_EXIT_ERR_FATAL fi /usr/lib/nfs/nfsd rc=$? if [ $rc != 0 ]; then /usr/sbin/svcadm mark -t maintenance svc:/network/nfs/server echo "$0: nfsd failed with $rc" sleep 5 & exit $SMF_EXIT_ERR_FATAL fi configure_ipfilter else smf_method_exit $SMF_EXIT_TEMP_DISABLE no_shares \ "No NFS filesystems are shared" fi ;; 'refresh') /usr/sbin/share -F nfs -a ;; 'stop') /usr/bin/pkill -x -u 0 -z $zone '(nfsd|mountd)' # Unshare all shared file systems using NFS /usr/sbin/unshare -F nfs -a # # Wait up to 10 seconds for nfslogd to gracefully handle SIGHUP # /usr/bin/pkill -HUP -x -u 0 -z $zone nfslogd wtime=10 while [ $wtime -gt 0 ]; do /usr/bin/pgrep -x -u 0 -z $zone nfslogd >/dev/null || break wtime=`expr $wtime - 1` sleep 1 done # # Kill nfslogd more forcefully if it did not shutdown during # the grace period # if [ $wtime -eq 0 ]; then /usr/bin/pkill -TERM -x -u 0 -z $zone nfslogd fi # Kill any processes left in service contract smf_kill_contract $2 TERM 1 [ $? -ne 0 ] && exit 1 ;; 'ipfilter') # # NFS related services are RPC. nfs/server has nfsd which has # well-defined port number but mountd is an RPC daemon. # # Essentially, we generate rules for the following "services" # - nfs/server which has nfsd and mountd # - nfs/rquota # # The following services are enabled for both nfs client and # server so we'll treat them as client services and simply # allow incoming traffic. # - nfs/status # - nfs/nlockmgr # - nfs/cbd # NFS_FMRI="svc:/network/nfs/server:default" RQUOTA_FMRI="svc:/network/nfs/rquota:default" FMRI=$2 file=`fmri_to_file $FMRI $IPF_SUFFIX` echo "# $FMRI" >$file policy=`get_policy $NFS_FMRI` ip="any" # # nfs/server configuration is processed in the start method. # if [ "$FMRI" = "$NFS_FMRI" ]; then service_check_state $FMRI $SMF_ONLINE if [ $? -ne 0 ]; then rm $file exit $SMF_EXIT_OK fi nfs_name=`svcprop -p $FW_CONTEXT_PG/name $FMRI 2>/dev/null` tport=`$SERVINFO -p -t -s $nfs_name 2>/dev/null` if [ -n "$tport" ]; then generate_rules $FMRI $policy "tcp" $ip $tport $file fi uport=`$SERVINFO -p -u -s $nfs_name 2>/dev/null` if [ -n "$uport" ]; then generate_rules $FMRI $policy "udp" $ip $uport $file fi tports=`$SERVINFO -R -p -t -s "mountd" 2>/dev/null` if [ -n "$tports" ]; then for tport in $tports; do generate_rules $FMRI $policy "tcp" $ip \ $tport $file done fi uports=`$SERVINFO -R -p -u -s "mountd" 2>/dev/null` if [ -n "$uports" ]; then for uport in $uports; do generate_rules $FMRI $policy "udp" $ip \ $uport $file done fi elif [ "$FMRI" = "$RQUOTA_FMRI" ]; then iana_name=`svcprop -p inetd/name $FMRI` tports=`$SERVINFO -R -p -t -s $iana_name 2>/dev/null` if [ -n "$tports" ]; then for tport in $tports; do generate_rules $NFS_FMRI $policy "tcp" \ $ip $tport $file done fi uports=`$SERVINFO -R -p -u -s $iana_name 2>/dev/null` if [ -n "$uports" ]; then for uport in $uports; do generate_rules $NFS_FMRI $policy "udp" \ $ip $uport $file done fi else # # Handle the client services here # restarter=`svcprop -p general/restarter $FMRI 2>/dev/null` if [ "$restarter" = "$INETDFMRI" ]; then iana_name=`svcprop -p inetd/name $FMRI` isrpc=`svcprop -p inetd/isrpc $FMRI` else iana_name=`svcprop -p $FW_CONTEXT_PG/name $FMRI` isrpc=`svcprop -p $FW_CONTEXT_PG/isrpc $FMRI` fi if [ "$isrpc" = "true" ]; then tports=`$SERVINFO -R -p -t -s $iana_name 2>/dev/null` uports=`$SERVINFO -R -p -u -s $iana_name 2>/dev/null` else tports=`$SERVINFO -p -t -s $iana_name 2>/dev/null` uports=`$SERVINFO -p -u -s $iana_name 2>/dev/null` fi if [ -n "$tports" ]; then for tport in $tports; do echo "pass in log quick proto tcp from any" \ "to any port = ${tport} flags S " \ "keep state" >>${file} done fi if [ -n "$uports" ]; then for uport in $uports; do echo "pass in log quick proto udp from any" \ "to any port = ${uport}" >>${file} done fi fi ;; *) echo "Usage: $0 { start | stop | refresh }" exit 1 ;; esac exit $SMF_EXIT_OK