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