xref: /netbsd-src/usr.sbin/rpc.lockd/lock_proc.c (revision dd5f61399d8292c60bedeaf06cc0c149f026ff45)
1*dd5f6139Stron /*	$NetBSD: lock_proc.c,v 1.10 2012/06/18 20:30:32 tron Exp $	*/
2a6fdc939Sscottr 
3a6fdc939Sscottr /*
4a6fdc939Sscottr  * Copyright (c) 1995
5a6fdc939Sscottr  *	A.R. Gordon (andrew.gordon@net-tel.co.uk).  All rights reserved.
6a6fdc939Sscottr  *
7a6fdc939Sscottr  * Redistribution and use in source and binary forms, with or without
8a6fdc939Sscottr  * modification, are permitted provided that the following conditions
9a6fdc939Sscottr  * are met:
10a6fdc939Sscottr  * 1. Redistributions of source code must retain the above copyright
11a6fdc939Sscottr  *    notice, this list of conditions and the following disclaimer.
12a6fdc939Sscottr  * 2. Redistributions in binary form must reproduce the above copyright
13a6fdc939Sscottr  *    notice, this list of conditions and the following disclaimer in the
14a6fdc939Sscottr  *    documentation and/or other materials provided with the distribution.
15a6fdc939Sscottr  * 3. All advertising materials mentioning features or use of this software
16a6fdc939Sscottr  *    must display the following acknowledgement:
17a6fdc939Sscottr  *	This product includes software developed for the FreeBSD project
18a6fdc939Sscottr  * 4. Neither the name of the author nor the names of any co-contributors
19a6fdc939Sscottr  *    may be used to endorse or promote products derived from this software
20a6fdc939Sscottr  *    without specific prior written permission.
21a6fdc939Sscottr  *
22a6fdc939Sscottr  * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND
23a6fdc939Sscottr  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24a6fdc939Sscottr  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25a6fdc939Sscottr  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26a6fdc939Sscottr  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27a6fdc939Sscottr  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28a6fdc939Sscottr  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29a6fdc939Sscottr  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30a6fdc939Sscottr  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31a6fdc939Sscottr  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32a6fdc939Sscottr  * SUCH DAMAGE.
33a6fdc939Sscottr  *
34a6fdc939Sscottr  */
35a6fdc939Sscottr 
361b318768Slukem #include <sys/cdefs.h>
371b318768Slukem #ifndef lint
38*dd5f6139Stron __RCSID("$NetBSD: lock_proc.c,v 1.10 2012/06/18 20:30:32 tron Exp $");
391b318768Slukem #endif
401b318768Slukem 
41a6fdc939Sscottr #include <sys/param.h>
42a6fdc939Sscottr #include <sys/socket.h>
43a6fdc939Sscottr 
44a6fdc939Sscottr #include <netinet/in.h>
45a6fdc939Sscottr #include <arpa/inet.h>
46a6fdc939Sscottr 
471b318768Slukem #include <netdb.h>
481b318768Slukem #include <stdio.h>
491b318768Slukem #include <string.h>
501b318768Slukem #include <syslog.h>
5177044250Sfvdl #include <netconfig.h>
521b318768Slukem 
53a6fdc939Sscottr #include <rpc/rpc.h>
54a6fdc939Sscottr #include <rpcsvc/sm_inter.h>
55a6fdc939Sscottr 
56a6fdc939Sscottr #include "lockd.h"
578521dd16Sthorpej #include <rpcsvc/nlm_prot.h>
58227ed983Sbouyer #include "lockd_lock.h"
59a6fdc939Sscottr 
60a6fdc939Sscottr 
61a6fdc939Sscottr #define	CLIENT_CACHE_SIZE	64	/* No. of client sockets cached */
62a6fdc939Sscottr #define	CLIENT_CACHE_LIFETIME	120	/* In seconds */
63a6fdc939Sscottr 
64ceaa3a4fSchristos static void	log_from_addr(const char *, struct svc_req *);
65ceaa3a4fSchristos static int	addrcmp(const struct sockaddr *, const struct sockaddr *);
66ceaa3a4fSchristos static void	nlmtonlm4(struct nlm_lock *, struct nlm4_lock *);
671b318768Slukem 
68a6fdc939Sscottr /* log_from_addr ----------------------------------------------------------- */
69a6fdc939Sscottr /*
70a6fdc939Sscottr  * Purpose:	Log name of function called and source address
71a6fdc939Sscottr  * Returns:	Nothing
72a6fdc939Sscottr  * Notes:	Extracts the source address from the transport handle
73a6fdc939Sscottr  *		passed in as part of the called procedure specification
74a6fdc939Sscottr  */
75a6fdc939Sscottr static void
log_from_addr(const char * fun_name,struct svc_req * req)76ceaa3a4fSchristos log_from_addr(const char *fun_name, struct svc_req *req)
77a6fdc939Sscottr {
7877044250Sfvdl 	struct sockaddr *addr;
7977044250Sfvdl 	char hostname_buf[NI_MAXHOST];
80a6fdc939Sscottr 
8177044250Sfvdl 	addr = svc_getrpccaller(req->rq_xprt)->buf;
82ceaa3a4fSchristos 	if (getnameinfo(addr, (socklen_t)addr->sa_len, hostname_buf,
83ceaa3a4fSchristos 	    sizeof(hostname_buf), NULL, 0, 0) != 0)
8477044250Sfvdl 		return;
85a6fdc939Sscottr 
86a6fdc939Sscottr 	syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf);
87a6fdc939Sscottr }
88a6fdc939Sscottr 
89a6fdc939Sscottr /* get_client -------------------------------------------------------------- */
90a6fdc939Sscottr /*
91a6fdc939Sscottr  * Purpose:	Get a CLIENT* for making RPC calls to lockd on given host
92a6fdc939Sscottr  * Returns:	CLIENT* pointer, from clnt_udp_create, or NULL if error
93a6fdc939Sscottr  * Notes:	Creating a CLIENT* is quite expensive, involving a
94a6fdc939Sscottr  *		conversation with the remote portmapper to get the
95a6fdc939Sscottr  *		port number.  Since a given client is quite likely
96a6fdc939Sscottr  *		to make several locking requests in succession, it is
97a6fdc939Sscottr  *		desirable to cache the created CLIENT*.
98a6fdc939Sscottr  *
99a6fdc939Sscottr  *		Since we are using UDP rather than TCP, there is no cost
100a6fdc939Sscottr  *		to the remote system in keeping these cached indefinitely.
101a6fdc939Sscottr  *		Unfortunately there is a snag: if the remote system
102a6fdc939Sscottr  *		reboots, the cached portmapper results will be invalid,
103a6fdc939Sscottr  *		and we will never detect this since all of the xxx_msg()
104a6fdc939Sscottr  *		calls return no result - we just fire off a udp packet
105a6fdc939Sscottr  *		and hope for the best.
106a6fdc939Sscottr  *
107a6fdc939Sscottr  *		We solve this by discarding cached values after two
108a6fdc939Sscottr  *		minutes, regardless of whether they have been used
109a6fdc939Sscottr  *		in the meanwhile (since a bad one might have been used
110a6fdc939Sscottr  *		plenty of times, as the host keeps retrying the request
111a6fdc939Sscottr  *		and we keep sending the reply back to the wrong port).
112a6fdc939Sscottr  *
113a6fdc939Sscottr  *		Given that the entries will always expire in the order
114a6fdc939Sscottr  *		that they were created, there is no point in a LRU
115a6fdc939Sscottr  *		algorithm for when the cache gets full - entries are
116a6fdc939Sscottr  *		always re-used in sequence.
117a6fdc939Sscottr  */
118a6fdc939Sscottr static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE];
119a6fdc939Sscottr static long clnt_cache_time[CLIENT_CACHE_SIZE];	/* time entry created */
12077044250Sfvdl static struct sockaddr_storage clnt_cache_addr[CLIENT_CACHE_SIZE];
121a6fdc939Sscottr static int clnt_cache_next_to_use = 0;
122a6fdc939Sscottr 
12377044250Sfvdl static int
addrcmp(const struct sockaddr * sa1,const struct sockaddr * sa2)124ceaa3a4fSchristos addrcmp(const struct sockaddr *sa1, const struct sockaddr *sa2)
12577044250Sfvdl {
126ceaa3a4fSchristos 	size_t len;
127ceaa3a4fSchristos 	const void *p1, *p2;
12877044250Sfvdl 
12977044250Sfvdl 	if (sa1->sa_family != sa2->sa_family)
13077044250Sfvdl 		return -1;
13177044250Sfvdl 
13277044250Sfvdl 	switch (sa1->sa_family) {
13377044250Sfvdl 	case AF_INET:
134ceaa3a4fSchristos 		p1 = &((const struct sockaddr_in *)(const void *)sa1)->sin_addr;
135ceaa3a4fSchristos 		p2 = &((const struct sockaddr_in *)(const void *)sa2)->sin_addr;
13677044250Sfvdl 		len = 4;
13777044250Sfvdl 		break;
13877044250Sfvdl 	case AF_INET6:
139ceaa3a4fSchristos 		p1 = &((const struct sockaddr_in6 *)(const void *)sa1)->sin6_addr;
140ceaa3a4fSchristos 		p2 = &((const struct sockaddr_in6 *)(const void *)sa2)->sin6_addr;
14177044250Sfvdl 		len = 16;
14277044250Sfvdl 		break;
14377044250Sfvdl 	default:
14477044250Sfvdl 		return -1;
14577044250Sfvdl 	}
14677044250Sfvdl 
14777044250Sfvdl 	return memcmp(p1, p2, len);
14877044250Sfvdl }
14977044250Sfvdl 
150227ed983Sbouyer CLIENT *
get_client(struct sockaddr * host_addr,rpcvers_t vers)151ceaa3a4fSchristos get_client(struct sockaddr *host_addr, rpcvers_t vers)
152a6fdc939Sscottr {
153a6fdc939Sscottr 	CLIENT *client;
154a6fdc939Sscottr 	struct timeval retry_time, time_now;
15577044250Sfvdl 	int i;
156ceaa3a4fSchristos 	const char *netid;
15777044250Sfvdl 	struct netconfig *nconf;
15877044250Sfvdl 	char host[NI_MAXHOST];
159*dd5f6139Stron 	int error;
160a6fdc939Sscottr 
161ceaa3a4fSchristos 	(void)gettimeofday(&time_now, NULL);
162a6fdc939Sscottr 
163a6fdc939Sscottr 	/*
164a6fdc939Sscottr 	 * Search for the given client in the cache, zapping any expired
165a6fdc939Sscottr 	 * entries that we happen to notice in passing.
166a6fdc939Sscottr 	 */
167a6fdc939Sscottr 	for (i = 0; i < CLIENT_CACHE_SIZE; i++) {
168a6fdc939Sscottr 		client = clnt_cache_ptr[i];
169a6fdc939Sscottr 		if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME)
170a6fdc939Sscottr 		    < time_now.tv_sec)) {
171a6fdc939Sscottr 			/* Cache entry has expired. */
172a6fdc939Sscottr 			if (debug_level > 3)
173a6fdc939Sscottr 				syslog(LOG_DEBUG, "Expired CLIENT* in cache");
174a6fdc939Sscottr 			clnt_cache_time[i] = 0L;
175a6fdc939Sscottr 			clnt_destroy(client);
176a6fdc939Sscottr 			clnt_cache_ptr[i] = NULL;
177a6fdc939Sscottr 			client = NULL;
178a6fdc939Sscottr 		}
179ceaa3a4fSchristos 		if (client && !addrcmp((const struct sockaddr *)(const void *)
180ceaa3a4fSchristos 		    &clnt_cache_addr[i], host_addr)) {
181a6fdc939Sscottr 			/* Found it! */
182a6fdc939Sscottr 			if (debug_level > 3)
183a6fdc939Sscottr 				syslog(LOG_DEBUG, "Found CLIENT* in cache");
184ceaa3a4fSchristos 			return client;
185a6fdc939Sscottr 		}
186a6fdc939Sscottr 	}
187a6fdc939Sscottr 
188a6fdc939Sscottr 	/* Not found in cache.  Free the next entry if it is in use. */
189a6fdc939Sscottr 	if (clnt_cache_ptr[clnt_cache_next_to_use]) {
190a6fdc939Sscottr 		clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
191a6fdc939Sscottr 		clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
192a6fdc939Sscottr 	}
193a6fdc939Sscottr 
19477044250Sfvdl 	/*
19577044250Sfvdl 	 * Need a host string for clnt_tp_create. Use NI_NUMERICHOST
19677044250Sfvdl 	 * to avoid DNS lookups.
19777044250Sfvdl 	 */
198*dd5f6139Stron 	error = getnameinfo(host_addr, (socklen_t)host_addr->sa_len, host,
199*dd5f6139Stron 	    sizeof(host), NULL, 0, NI_NUMERICHOST);
200*dd5f6139Stron 	if (error != 0) {
201*dd5f6139Stron 		syslog(LOG_ERR, "unable to get name string for caller: %s",
202*dd5f6139Stron 		    gai_strerror(error));
20377044250Sfvdl 		return NULL;
20477044250Sfvdl 	}
20577044250Sfvdl 
206227ed983Sbouyer #if 1
20777044250Sfvdl 	if (host_addr->sa_family == AF_INET6)
20877044250Sfvdl 		netid = "udp6";
20977044250Sfvdl 	else
21077044250Sfvdl 		netid = "udp";
211227ed983Sbouyer #else
21277044250Sfvdl 	if (host_addr->sa_family == AF_INET6)
21377044250Sfvdl 		netid = "tcp6";
21477044250Sfvdl 	else
21577044250Sfvdl 		netid = "tcp";
216227ed983Sbouyer #endif
21777044250Sfvdl 	nconf = getnetconfigent(netid);
21877044250Sfvdl 	if (nconf == NULL) {
21977044250Sfvdl 		syslog(LOG_ERR, "could not get netconfig info for '%s': "
22077044250Sfvdl 				"no /etc/netconfig file?", netid);
22177044250Sfvdl 		return NULL;
22277044250Sfvdl 	}
22377044250Sfvdl 
22477044250Sfvdl 	client = clnt_tp_create(host, NLM_PROG, vers, nconf);
22577044250Sfvdl 	freenetconfigent(nconf);
22677044250Sfvdl 
227a6fdc939Sscottr 	if (!client) {
228d8302e2dSis 		syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create"));
22977044250Sfvdl 		syslog(LOG_ERR, "Unable to return result to %s", host);
230a6fdc939Sscottr 		return NULL;
231a6fdc939Sscottr 	}
232a6fdc939Sscottr 
233a6fdc939Sscottr 	/* Success - update the cache entry */
234a6fdc939Sscottr 	clnt_cache_ptr[clnt_cache_next_to_use] = client;
235ceaa3a4fSchristos 	(void)memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr,
236ceaa3a4fSchristos 	    (size_t)host_addr->sa_len);
237a6fdc939Sscottr 	clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec;
238e6cd63ecStron 	if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE)
239a6fdc939Sscottr 		clnt_cache_next_to_use = 0;
240a6fdc939Sscottr 
241a6fdc939Sscottr 	/*
242a6fdc939Sscottr 	 * Disable the default timeout, so we can specify our own in calls
243a6fdc939Sscottr 	 * to clnt_call().  (Note that the timeout is a different concept
244a6fdc939Sscottr 	 * from the retry period set in clnt_udp_create() above.)
245a6fdc939Sscottr 	 */
246a6fdc939Sscottr 	retry_time.tv_sec = -1;
247a6fdc939Sscottr 	retry_time.tv_usec = -1;
248ceaa3a4fSchristos 	clnt_control(client, CLSET_TIMEOUT, (char *)(void *)&retry_time);
249a6fdc939Sscottr 
250a6fdc939Sscottr 	if (debug_level > 3)
25177044250Sfvdl 		syslog(LOG_DEBUG, "Created CLIENT* for %s", host);
252a6fdc939Sscottr 	return client;
253a6fdc939Sscottr }
254a6fdc939Sscottr 
255a6fdc939Sscottr 
256a6fdc939Sscottr /* transmit_result --------------------------------------------------------- */
257a6fdc939Sscottr /*
258a6fdc939Sscottr  * Purpose:	Transmit result for nlm_xxx_msg pseudo-RPCs
259a6fdc939Sscottr  * Returns:	Nothing - we have no idea if the datagram got there
260a6fdc939Sscottr  * Notes:	clnt_call() will always fail (with timeout) as we are
261a6fdc939Sscottr  *		calling it with timeout 0 as a hack to just issue a datagram
262a6fdc939Sscottr  *		without expecting a result
263a6fdc939Sscottr  */
264227ed983Sbouyer void
transmit_result(int opcode,nlm_res * result,struct sockaddr * addr)265ceaa3a4fSchristos transmit_result(int opcode, nlm_res *result, struct sockaddr *addr)
266a6fdc939Sscottr {
267a6fdc939Sscottr 	static char dummy;
268a6fdc939Sscottr 	CLIENT *cli;
269a6fdc939Sscottr 	struct timeval timeo;
270a6fdc939Sscottr 	int success;
271a6fdc939Sscottr 
27277044250Sfvdl 	if ((cli = get_client(addr, NLM_VERS)) != NULL) {
273a6fdc939Sscottr 		timeo.tv_sec = 0; /* No timeout - not expecting response */
274a6fdc939Sscottr 		timeo.tv_usec = 0;
275a6fdc939Sscottr 
276ceaa3a4fSchristos 		success = clnt_call(cli, (rpcproc_t)opcode, xdr_nlm_res,
277ceaa3a4fSchristos 		    result, xdr_void, &dummy, timeo);
278a6fdc939Sscottr 
279a6fdc939Sscottr 		if (debug_level > 2)
280227ed983Sbouyer 			syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
281227ed983Sbouyer 			    success, clnt_sperrno(success));
282a6fdc939Sscottr 	}
283a6fdc939Sscottr }
284a3bc666fSbouyer /* transmit4_result --------------------------------------------------------- */
285a3bc666fSbouyer /*
286a3bc666fSbouyer  * Purpose:	Transmit result for nlm4_xxx_msg pseudo-RPCs
287a3bc666fSbouyer  * Returns:	Nothing - we have no idea if the datagram got there
288a3bc666fSbouyer  * Notes:	clnt_call() will always fail (with timeout) as we are
289a3bc666fSbouyer  *		calling it with timeout 0 as a hack to just issue a datagram
290a3bc666fSbouyer  *		without expecting a result
291a3bc666fSbouyer  */
292227ed983Sbouyer void
transmit4_result(int opcode,nlm4_res * result,struct sockaddr * addr)293ceaa3a4fSchristos transmit4_result(int opcode, nlm4_res *result, struct sockaddr *addr)
294a3bc666fSbouyer {
295a3bc666fSbouyer 	static char dummy;
296a3bc666fSbouyer 	CLIENT *cli;
297a3bc666fSbouyer 	struct timeval timeo;
298a3bc666fSbouyer 	int success;
299a3bc666fSbouyer 
30077044250Sfvdl 	if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
301a3bc666fSbouyer 		timeo.tv_sec = 0; /* No timeout - not expecting response */
302a3bc666fSbouyer 		timeo.tv_usec = 0;
303a3bc666fSbouyer 
304ceaa3a4fSchristos 		success = clnt_call(cli, (rpcproc_t)opcode, xdr_nlm4_res,
305ceaa3a4fSchristos 		    result, xdr_void, &dummy, timeo);
306a3bc666fSbouyer 
307a3bc666fSbouyer 		if (debug_level > 2)
308227ed983Sbouyer 			syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
309227ed983Sbouyer 			    success, clnt_sperrno(success));
310a3bc666fSbouyer 	}
311a3bc666fSbouyer }
312227ed983Sbouyer 
313227ed983Sbouyer /*
314227ed983Sbouyer  * converts a struct nlm_lock to struct nlm4_lock
315227ed983Sbouyer  */
316227ed983Sbouyer static void
nlmtonlm4(struct nlm_lock * arg,struct nlm4_lock * arg4)317ceaa3a4fSchristos nlmtonlm4(struct nlm_lock *arg, struct nlm4_lock *arg4)
318227ed983Sbouyer {
319ceaa3a4fSchristos 	(void)memcpy(arg4, arg, sizeof(nlm_lock));
320227ed983Sbouyer 	arg4->l_offset = arg->l_offset;
321227ed983Sbouyer 	arg4->l_len = arg->l_len;
322227ed983Sbouyer }
323ceaa3a4fSchristos 
324a6fdc939Sscottr /* ------------------------------------------------------------------------- */
325a6fdc939Sscottr /*
326a6fdc939Sscottr  * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
327a6fdc939Sscottr  * involved to ensure reclaim of locks after a crash of the "stateless"
328a6fdc939Sscottr  * server.
329a6fdc939Sscottr  *
330a6fdc939Sscottr  * These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
331a6fdc939Sscottr  * The first are standard RPCs with argument and result.
332a6fdc939Sscottr  * The nlm_xxx_msg() calls implement exactly the same functions, but
333a6fdc939Sscottr  * use two pseudo-RPCs (one in each direction).  These calls are NOT
334a6fdc939Sscottr  * standard use of the RPC protocol in that they do not return a result
335a6fdc939Sscottr  * at all (NB. this is quite different from returning a void result).
336a6fdc939Sscottr  * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
337a6fdc939Sscottr  * datagrams, requiring higher-level code to perform retries.
338a6fdc939Sscottr  *
339a6fdc939Sscottr  * Despite the disadvantages of the nlm_xxx_msg() approach (some of which
340a6fdc939Sscottr  * are documented in the comments to get_client() above), this is the
341a6fdc939Sscottr  * interface used by all current commercial NFS implementations
342a6fdc939Sscottr  * [Solaris, SCO, AIX etc.].  This is presumed to be because these allow
343a6fdc939Sscottr  * implementations to continue using the standard RPC libraries, while
344a6fdc939Sscottr  * avoiding the block-until-result nature of the library interface.
345a6fdc939Sscottr  *
346a6fdc939Sscottr  * No client implementations have been identified so far that make use
347a6fdc939Sscottr  * of the true RPC version (early SunOS releases would be a likely candidate
348a6fdc939Sscottr  * for testing).
349a6fdc939Sscottr  */
350a6fdc939Sscottr 
351a6fdc939Sscottr /* nlm_test ---------------------------------------------------------------- */
352a6fdc939Sscottr /*
353a6fdc939Sscottr  * Purpose:	Test whether a specified lock would be granted if requested
354a6fdc939Sscottr  * Returns:	nlm_granted (or error code)
355a6fdc939Sscottr  * Notes:
356a6fdc939Sscottr  */
357a6fdc939Sscottr nlm_testres *
nlm_test_1_svc(nlm_testargs * arg,struct svc_req * rqstp)358ceaa3a4fSchristos nlm_test_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
359a6fdc939Sscottr {
360ceaa3a4fSchristos 	static nlm_testres result;
361227ed983Sbouyer 	struct nlm4_lock arg4;
362227ed983Sbouyer 	struct nlm4_holder *holder;
363227ed983Sbouyer 	nlmtonlm4(&arg->alock, &arg4);
364a6fdc939Sscottr 
365a6fdc939Sscottr 	if (debug_level)
366a6fdc939Sscottr 		log_from_addr("nlm_test", rqstp);
367a6fdc939Sscottr 
368227ed983Sbouyer 	holder = testlock(&arg4, 0);
369a6fdc939Sscottr 	/*
370a6fdc939Sscottr 	 * Copy the cookie from the argument into the result.  Note that this
371a6fdc939Sscottr 	 * is slightly hazardous, as the structure contains a pointer to a
372a6fdc939Sscottr 	 * malloc()ed buffer that will get freed by the caller.  However, the
373a6fdc939Sscottr 	 * main function transmits the result before freeing the argument
374a6fdc939Sscottr 	 * so it is in fact safe.
375a6fdc939Sscottr 	 */
376ceaa3a4fSchristos 	result.cookie = arg->cookie;
377227ed983Sbouyer 	if (holder == NULL) {
378ceaa3a4fSchristos 		result.stat.stat = nlm_granted;
379227ed983Sbouyer 	} else {
380ceaa3a4fSchristos 		result.stat.stat = nlm_denied;
381ceaa3a4fSchristos 		(void)memcpy(&result.stat.nlm_testrply_u.holder, holder,
382227ed983Sbouyer 		    sizeof(struct nlm_holder));
383ceaa3a4fSchristos 		result.stat.nlm_testrply_u.holder.l_offset =
384ceaa3a4fSchristos 		    (unsigned int)holder->l_offset;
385ceaa3a4fSchristos 		result.stat.nlm_testrply_u.holder.l_len =
386ceaa3a4fSchristos 		    (unsigned int)holder->l_len;
387227ed983Sbouyer 	}
388ceaa3a4fSchristos 	return &result;
389a6fdc939Sscottr }
390a6fdc939Sscottr 
391a6fdc939Sscottr void *
nlm_test_msg_1_svc(nlm_testargs * arg,struct svc_req * rqstp)392ceaa3a4fSchristos nlm_test_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
393a6fdc939Sscottr {
394ceaa3a4fSchristos 	nlm_testres result;
395a6fdc939Sscottr 	static char dummy;
39677044250Sfvdl 	struct sockaddr *addr;
397a6fdc939Sscottr 	CLIENT *cli;
398a6fdc939Sscottr 	int success;
399a6fdc939Sscottr 	struct timeval timeo;
400227ed983Sbouyer 	struct nlm4_lock arg4;
401227ed983Sbouyer 	struct nlm4_holder *holder;
402227ed983Sbouyer 
403227ed983Sbouyer 	nlmtonlm4(&arg->alock, &arg4);
404a6fdc939Sscottr 
405a6fdc939Sscottr 	if (debug_level)
406a6fdc939Sscottr 		log_from_addr("nlm_test_msg", rqstp);
407a6fdc939Sscottr 
408227ed983Sbouyer 	holder = testlock(&arg4, 0);
409227ed983Sbouyer 
410ceaa3a4fSchristos 	result.cookie = arg->cookie;
411227ed983Sbouyer 	if (holder == NULL) {
412ceaa3a4fSchristos 		result.stat.stat = nlm_granted;
413227ed983Sbouyer 	} else {
414ceaa3a4fSchristos 		result.stat.stat = nlm_denied;
415ceaa3a4fSchristos 		(void)memcpy(&result.stat.nlm_testrply_u.holder, holder,
416227ed983Sbouyer 		    sizeof(struct nlm_holder));
417ceaa3a4fSchristos 		result.stat.nlm_testrply_u.holder.l_offset =
418ceaa3a4fSchristos 		    (unsigned int)holder->l_offset;
419ceaa3a4fSchristos 		result.stat.nlm_testrply_u.holder.l_len =
420ceaa3a4fSchristos 		    (unsigned int)holder->l_len;
421227ed983Sbouyer 	}
422a6fdc939Sscottr 
423a6fdc939Sscottr 	/*
424a6fdc939Sscottr 	 * nlm_test has different result type to the other operations, so
425a6fdc939Sscottr 	 * can't use transmit_result() in this case
426a6fdc939Sscottr 	 */
42777044250Sfvdl 	addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
428227ed983Sbouyer 	if ((cli = get_client(addr, NLM_VERS)) != NULL) {
429a6fdc939Sscottr 		timeo.tv_sec = 0; /* No timeout - not expecting response */
430a6fdc939Sscottr 		timeo.tv_usec = 0;
431a6fdc939Sscottr 
432a6fdc939Sscottr 		success = clnt_call(cli, NLM_TEST_RES, xdr_nlm_testres,
433ceaa3a4fSchristos 		    &result, xdr_void, &dummy, timeo);
434a6fdc939Sscottr 
435a6fdc939Sscottr 		if (debug_level > 2)
436227ed983Sbouyer 			syslog(LOG_DEBUG, "clnt_call returns %d", success);
437a6fdc939Sscottr 	}
438ceaa3a4fSchristos 	return NULL;
439a6fdc939Sscottr }
440a6fdc939Sscottr 
441a6fdc939Sscottr /* nlm_lock ---------------------------------------------------------------- */
442a6fdc939Sscottr /*
443a6fdc939Sscottr  * Purposes:	Establish a lock
444a6fdc939Sscottr  * Returns:	granted, denied or blocked
445a6fdc939Sscottr  * Notes:	*** grace period support missing
446a6fdc939Sscottr  */
447a6fdc939Sscottr nlm_res *
nlm_lock_1_svc(nlm_lockargs * arg,struct svc_req * rqstp)448ceaa3a4fSchristos nlm_lock_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
449a6fdc939Sscottr {
450ceaa3a4fSchristos 	static nlm_res result;
451227ed983Sbouyer 	struct nlm4_lockargs arg4;
452227ed983Sbouyer 	nlmtonlm4(&arg->alock, &arg4.alock);
453227ed983Sbouyer 	arg4.cookie = arg->cookie;
454227ed983Sbouyer 	arg4.block = arg->block;
455227ed983Sbouyer 	arg4.exclusive = arg->exclusive;
456227ed983Sbouyer 	arg4.reclaim = arg->reclaim;
457227ed983Sbouyer 	arg4.state = arg->state;
458a6fdc939Sscottr 
459a6fdc939Sscottr 	if (debug_level)
460a6fdc939Sscottr 		log_from_addr("nlm_lock", rqstp);
461a6fdc939Sscottr 
462a6fdc939Sscottr 	/* copy cookie from arg to result.  See comment in nlm_test_1() */
463ceaa3a4fSchristos 	result.cookie = arg->cookie;
464a6fdc939Sscottr 
465ceaa3a4fSchristos 	result.stat.stat = getlock(&arg4, rqstp, LOCK_MON);
466ceaa3a4fSchristos 	return &result;
467a6fdc939Sscottr }
468a6fdc939Sscottr 
469a6fdc939Sscottr void *
nlm_lock_msg_1_svc(nlm_lockargs * arg,struct svc_req * rqstp)470ceaa3a4fSchristos nlm_lock_msg_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
471a6fdc939Sscottr {
472ceaa3a4fSchristos 	static nlm_res result;
473227ed983Sbouyer 	struct nlm4_lockargs arg4;
474227ed983Sbouyer 
475227ed983Sbouyer 	nlmtonlm4(&arg->alock, &arg4.alock);
476227ed983Sbouyer 	arg4.cookie = arg->cookie;
477227ed983Sbouyer 	arg4.block = arg->block;
478227ed983Sbouyer 	arg4.exclusive = arg->exclusive;
479227ed983Sbouyer 	arg4.reclaim = arg->reclaim;
480227ed983Sbouyer 	arg4.state = arg->state;
481a6fdc939Sscottr 
482a6fdc939Sscottr 	if (debug_level)
483a6fdc939Sscottr 		log_from_addr("nlm_lock_msg", rqstp);
484a6fdc939Sscottr 
485ceaa3a4fSchristos 	result.cookie = arg->cookie;
486ceaa3a4fSchristos 	result.stat.stat = getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON);
487ceaa3a4fSchristos 	transmit_result(NLM_LOCK_RES, &result,
488*dd5f6139Stron 	    (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf);
489a6fdc939Sscottr 
490ceaa3a4fSchristos 	return NULL;
491a6fdc939Sscottr }
492a6fdc939Sscottr 
493a6fdc939Sscottr /* nlm_cancel -------------------------------------------------------------- */
494a6fdc939Sscottr /*
495a6fdc939Sscottr  * Purpose:	Cancel a blocked lock request
496a6fdc939Sscottr  * Returns:	granted or denied
497a6fdc939Sscottr  * Notes:
498a6fdc939Sscottr  */
499a6fdc939Sscottr nlm_res *
nlm_cancel_1_svc(nlm_cancargs * arg,struct svc_req * rqstp)500ceaa3a4fSchristos nlm_cancel_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
501a6fdc939Sscottr {
502ceaa3a4fSchristos 	static nlm_res result;
503227ed983Sbouyer 	struct nlm4_lock arg4;
504227ed983Sbouyer 
505227ed983Sbouyer 	nlmtonlm4(&arg->alock, &arg4);
506a6fdc939Sscottr 
507a6fdc939Sscottr 	if (debug_level)
508a6fdc939Sscottr 		log_from_addr("nlm_cancel", rqstp);
509a6fdc939Sscottr 
510a6fdc939Sscottr 	/* copy cookie from arg to result.  See comment in nlm_test_1() */
511ceaa3a4fSchristos 	result.cookie = arg->cookie;
512a6fdc939Sscottr 
513a6fdc939Sscottr 	/*
514a6fdc939Sscottr 	 * Since at present we never return 'nlm_blocked', there can never be
515a6fdc939Sscottr 	 * a lock to cancel, so this call always fails.
516a6fdc939Sscottr 	 */
517ceaa3a4fSchristos 	result.stat.stat = unlock(&arg4, LOCK_CANCEL);
518ceaa3a4fSchristos 	return &result;
519a6fdc939Sscottr }
520a6fdc939Sscottr 
521a6fdc939Sscottr void *
nlm_cancel_msg_1_svc(nlm_cancargs * arg,struct svc_req * rqstp)522ceaa3a4fSchristos nlm_cancel_msg_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
523a6fdc939Sscottr {
524ceaa3a4fSchristos 	static nlm_res result;
525227ed983Sbouyer 	struct nlm4_lock arg4;
526227ed983Sbouyer 
527227ed983Sbouyer 	nlmtonlm4(&arg->alock, &arg4);
528a6fdc939Sscottr 
529a6fdc939Sscottr 	if (debug_level)
530a6fdc939Sscottr 		log_from_addr("nlm_cancel_msg", rqstp);
531a6fdc939Sscottr 
532ceaa3a4fSchristos 	result.cookie = arg->cookie;
533a6fdc939Sscottr 	/*
534a6fdc939Sscottr 	 * Since at present we never return 'nlm_blocked', there can never be
535a6fdc939Sscottr 	 * a lock to cancel, so this call always fails.
536a6fdc939Sscottr 	 */
537ceaa3a4fSchristos 	result.stat.stat = unlock(&arg4, LOCK_CANCEL);
538ceaa3a4fSchristos 	transmit_result(NLM_CANCEL_RES, &result,
539*dd5f6139Stron 	    (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf);
540ceaa3a4fSchristos 	return NULL;
541a6fdc939Sscottr }
542a6fdc939Sscottr 
543a6fdc939Sscottr /* nlm_unlock -------------------------------------------------------------- */
544a6fdc939Sscottr /*
545a6fdc939Sscottr  * Purpose:	Release an existing lock
546a6fdc939Sscottr  * Returns:	Always granted, unless during grace period
547a6fdc939Sscottr  * Notes:	"no such lock" error condition is ignored, as the
548a6fdc939Sscottr  *		protocol uses unreliable UDP datagrams, and may well
549a6fdc939Sscottr  *		re-try an unlock that has already succeeded.
550a6fdc939Sscottr  */
551a6fdc939Sscottr nlm_res *
nlm_unlock_1_svc(nlm_unlockargs * arg,struct svc_req * rqstp)552ceaa3a4fSchristos nlm_unlock_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
553a6fdc939Sscottr {
554ceaa3a4fSchristos 	static nlm_res result;
555227ed983Sbouyer 	struct nlm4_lock arg4;
556227ed983Sbouyer 
557227ed983Sbouyer 	nlmtonlm4(&arg->alock, &arg4);
558a6fdc939Sscottr 
559a6fdc939Sscottr 	if (debug_level)
560a6fdc939Sscottr 		log_from_addr("nlm_unlock", rqstp);
561a6fdc939Sscottr 
562ceaa3a4fSchristos 	result.stat.stat = unlock(&arg4, 0);
563ceaa3a4fSchristos 	result.cookie = arg->cookie;
564a6fdc939Sscottr 
565ceaa3a4fSchristos 	return &result;
566a6fdc939Sscottr }
567a6fdc939Sscottr 
568a6fdc939Sscottr void *
nlm_unlock_msg_1_svc(nlm_unlockargs * arg,struct svc_req * rqstp)569ceaa3a4fSchristos nlm_unlock_msg_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
570a6fdc939Sscottr {
571ceaa3a4fSchristos 	static nlm_res result;
572227ed983Sbouyer 	struct nlm4_lock arg4;
573227ed983Sbouyer 
574227ed983Sbouyer 	nlmtonlm4(&arg->alock, &arg4);
575a6fdc939Sscottr 
576a6fdc939Sscottr 	if (debug_level)
577a6fdc939Sscottr 		log_from_addr("nlm_unlock_msg", rqstp);
578a6fdc939Sscottr 
579ceaa3a4fSchristos 	result.stat.stat = unlock(&arg4, 0);
580ceaa3a4fSchristos 	result.cookie = arg->cookie;
581a6fdc939Sscottr 
582ceaa3a4fSchristos 	transmit_result(NLM_UNLOCK_RES, &result,
583*dd5f6139Stron 	    (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf);
584ceaa3a4fSchristos 	return NULL;
585a6fdc939Sscottr }
586a6fdc939Sscottr 
587a6fdc939Sscottr /* ------------------------------------------------------------------------- */
588a6fdc939Sscottr /*
589a6fdc939Sscottr  * Client-side pseudo-RPCs for results.  Note that for the client there
590a6fdc939Sscottr  * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
591a6fdc939Sscottr  * version returns the results in the RPC result, and so the client
592a6fdc939Sscottr  * does not normally receive incoming RPCs.
593a6fdc939Sscottr  *
594a6fdc939Sscottr  * The exception to this is nlm_granted(), which is genuinely an RPC
595a6fdc939Sscottr  * call from the server to the client - a 'call-back' in normal procedure
596a6fdc939Sscottr  * call terms.
597a6fdc939Sscottr  */
598a6fdc939Sscottr 
599a6fdc939Sscottr /* nlm_granted ------------------------------------------------------------- */
600a6fdc939Sscottr /*
601a6fdc939Sscottr  * Purpose:	Receive notification that formerly blocked lock now granted
602a6fdc939Sscottr  * Returns:	always success ('granted')
603a6fdc939Sscottr  * Notes:
604a6fdc939Sscottr  */
605a6fdc939Sscottr nlm_res *
nlm_granted_1_svc(nlm_testargs * arg,struct svc_req * rqstp)606ceaa3a4fSchristos nlm_granted_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
607a6fdc939Sscottr {
608ceaa3a4fSchristos 	static nlm_res result;
609a6fdc939Sscottr 
610a6fdc939Sscottr 	if (debug_level)
611a6fdc939Sscottr 		log_from_addr("nlm_granted", rqstp);
612a6fdc939Sscottr 
613a6fdc939Sscottr 	/* copy cookie from arg to result.  See comment in nlm_test_1() */
614ceaa3a4fSchristos 	result.cookie = arg->cookie;
615a6fdc939Sscottr 
616ceaa3a4fSchristos 	result.stat.stat = nlm_granted;
617ceaa3a4fSchristos 	return &result;
618a6fdc939Sscottr }
619a6fdc939Sscottr 
620a6fdc939Sscottr void *
nlm_granted_msg_1_svc(nlm_testargs * arg,struct svc_req * rqstp)621ceaa3a4fSchristos nlm_granted_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
622a6fdc939Sscottr {
623ceaa3a4fSchristos 	static nlm_res result;
624a6fdc939Sscottr 
625a6fdc939Sscottr 	if (debug_level)
626a6fdc939Sscottr 		log_from_addr("nlm_granted_msg", rqstp);
627a6fdc939Sscottr 
628ceaa3a4fSchristos 	result.cookie = arg->cookie;
629ceaa3a4fSchristos 	result.stat.stat = nlm_granted;
630ceaa3a4fSchristos 	transmit_result(NLM_GRANTED_RES, &result,
631*dd5f6139Stron 	    (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf);
632ceaa3a4fSchristos 	return NULL;
633a6fdc939Sscottr }
634a6fdc939Sscottr 
635a6fdc939Sscottr /* nlm_test_res ------------------------------------------------------------ */
636a6fdc939Sscottr /*
637a6fdc939Sscottr  * Purpose:	Accept result from earlier nlm_test_msg() call
638a6fdc939Sscottr  * Returns:	Nothing
639a6fdc939Sscottr  */
640a6fdc939Sscottr void *
641ceaa3a4fSchristos /*ARGSUSED*/
nlm_test_res_1_svc(nlm_testres * arg,struct svc_req * rqstp)642ceaa3a4fSchristos nlm_test_res_1_svc(nlm_testres *arg, struct svc_req *rqstp)
643a6fdc939Sscottr {
644a6fdc939Sscottr 	if (debug_level)
645a6fdc939Sscottr 		log_from_addr("nlm_test_res", rqstp);
646ceaa3a4fSchristos 	return NULL;
647a6fdc939Sscottr }
648a6fdc939Sscottr 
649a6fdc939Sscottr /* nlm_lock_res ------------------------------------------------------------ */
650a6fdc939Sscottr /*
651a6fdc939Sscottr  * Purpose:	Accept result from earlier nlm_lock_msg() call
652a6fdc939Sscottr  * Returns:	Nothing
653a6fdc939Sscottr  */
654a6fdc939Sscottr void *
655ceaa3a4fSchristos /*ARGSUSED*/
nlm_lock_res_1_svc(nlm_res * arg,struct svc_req * rqstp)656ceaa3a4fSchristos nlm_lock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
657a6fdc939Sscottr {
658a6fdc939Sscottr 	if (debug_level)
659a6fdc939Sscottr 		log_from_addr("nlm_lock_res", rqstp);
660a6fdc939Sscottr 
661ceaa3a4fSchristos 	return NULL;
662a6fdc939Sscottr }
663a6fdc939Sscottr 
664a6fdc939Sscottr /* nlm_cancel_res ---------------------------------------------------------- */
665a6fdc939Sscottr /*
666a6fdc939Sscottr  * Purpose:	Accept result from earlier nlm_cancel_msg() call
667a6fdc939Sscottr  * Returns:	Nothing
668a6fdc939Sscottr  */
669a6fdc939Sscottr void *
670ceaa3a4fSchristos /*ARGSUSED*/
nlm_cancel_res_1_svc(nlm_res * arg,struct svc_req * rqstp)671ceaa3a4fSchristos nlm_cancel_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
672a6fdc939Sscottr {
673a6fdc939Sscottr 	if (debug_level)
674a6fdc939Sscottr 		log_from_addr("nlm_cancel_res", rqstp);
675ceaa3a4fSchristos 	return NULL;
676a6fdc939Sscottr }
677a6fdc939Sscottr 
678a6fdc939Sscottr /* nlm_unlock_res ---------------------------------------------------------- */
679a6fdc939Sscottr /*
680a6fdc939Sscottr  * Purpose:	Accept result from earlier nlm_unlock_msg() call
681a6fdc939Sscottr  * Returns:	Nothing
682a6fdc939Sscottr  */
683a6fdc939Sscottr void *
684ceaa3a4fSchristos /*ARGSUSED*/
nlm_unlock_res_1_svc(nlm_res * arg,struct svc_req * rqstp)685ceaa3a4fSchristos nlm_unlock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
686a6fdc939Sscottr {
687a6fdc939Sscottr 	if (debug_level)
688a6fdc939Sscottr 		log_from_addr("nlm_unlock_res", rqstp);
689ceaa3a4fSchristos 	return NULL;
690a6fdc939Sscottr }
691a6fdc939Sscottr 
692a6fdc939Sscottr /* nlm_granted_res --------------------------------------------------------- */
693a6fdc939Sscottr /*
694a6fdc939Sscottr  * Purpose:	Accept result from earlier nlm_granted_msg() call
695a6fdc939Sscottr  * Returns:	Nothing
696a6fdc939Sscottr  */
697a6fdc939Sscottr void *
698ceaa3a4fSchristos /*ARGSUSED*/
nlm_granted_res_1_svc(nlm_res * arg,struct svc_req * rqstp)699ceaa3a4fSchristos nlm_granted_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
700a6fdc939Sscottr {
701a6fdc939Sscottr 	if (debug_level)
702a6fdc939Sscottr 		log_from_addr("nlm_granted_res", rqstp);
703ceaa3a4fSchristos 	return NULL;
704a6fdc939Sscottr }
705a6fdc939Sscottr 
706a6fdc939Sscottr /* ------------------------------------------------------------------------- */
707a6fdc939Sscottr /*
708a6fdc939Sscottr  * Calls for PCNFS locking (aka non-monitored locking, no involvement
709a6fdc939Sscottr  * of rpc.statd).
710a6fdc939Sscottr  *
711a6fdc939Sscottr  * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
712a6fdc939Sscottr  */
713a6fdc939Sscottr 
714a6fdc939Sscottr /* nlm_share --------------------------------------------------------------- */
715a6fdc939Sscottr /*
716a6fdc939Sscottr  * Purpose:	Establish a DOS-style lock
717a6fdc939Sscottr  * Returns:	success or failure
718a6fdc939Sscottr  * Notes:	Blocking locks are not supported - client is expected
719a6fdc939Sscottr  *		to retry if required.
720a6fdc939Sscottr  */
721a6fdc939Sscottr nlm_shareres *
nlm_share_3_svc(nlm_shareargs * arg,struct svc_req * rqstp)722ceaa3a4fSchristos nlm_share_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
723a6fdc939Sscottr {
724ceaa3a4fSchristos 	static nlm_shareres result;
725a6fdc939Sscottr 
726a6fdc939Sscottr 	if (debug_level)
727a6fdc939Sscottr 		log_from_addr("nlm_share", rqstp);
728a6fdc939Sscottr 
729ceaa3a4fSchristos 	result.cookie = arg->cookie;
730ceaa3a4fSchristos 	result.stat = nlm_granted;
731ceaa3a4fSchristos 	result.sequence = 1234356;	/* X/Open says this field is ignored? */
732ceaa3a4fSchristos 	return &result;
733a6fdc939Sscottr }
734a6fdc939Sscottr 
735a6fdc939Sscottr /* nlm_unshare ------------------------------------------------------------ */
736a6fdc939Sscottr /*
737a6fdc939Sscottr  * Purpose:	Release a DOS-style lock
738a6fdc939Sscottr  * Returns:	nlm_granted, unless in grace period
739a6fdc939Sscottr  * Notes:
740a6fdc939Sscottr  */
741a6fdc939Sscottr nlm_shareres *
nlm_unshare_3_svc(nlm_shareargs * arg,struct svc_req * rqstp)742ceaa3a4fSchristos nlm_unshare_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
743a6fdc939Sscottr {
744ceaa3a4fSchristos 	static nlm_shareres result;
745a6fdc939Sscottr 
746a6fdc939Sscottr 	if (debug_level)
747a6fdc939Sscottr 		log_from_addr("nlm_unshare", rqstp);
748a6fdc939Sscottr 
749ceaa3a4fSchristos 	result.cookie = arg->cookie;
750ceaa3a4fSchristos 	result.stat = nlm_granted;
751ceaa3a4fSchristos 	result.sequence = 1234356;	/* X/Open says this field is ignored? */
752ceaa3a4fSchristos 	return &result;
753a6fdc939Sscottr }
754a6fdc939Sscottr 
755a6fdc939Sscottr /* nlm_nm_lock ------------------------------------------------------------ */
756a6fdc939Sscottr /*
757a6fdc939Sscottr  * Purpose:	non-monitored version of nlm_lock()
758a6fdc939Sscottr  * Returns:	as for nlm_lock()
759a6fdc939Sscottr  * Notes:	These locks are in the same style as the standard nlm_lock,
760a6fdc939Sscottr  *		but the rpc.statd should not be called to establish a
761a6fdc939Sscottr  *		monitor for the client machine, since that machine is
762a6fdc939Sscottr  *		declared not to be running a rpc.statd, and so would not
763a6fdc939Sscottr  *		respond to the statd protocol.
764a6fdc939Sscottr  */
765a6fdc939Sscottr nlm_res *
nlm_nm_lock_3_svc(nlm_lockargs * arg,struct svc_req * rqstp)766ceaa3a4fSchristos nlm_nm_lock_3_svc(nlm_lockargs *arg, struct svc_req *rqstp)
767a6fdc939Sscottr {
768ceaa3a4fSchristos 	static nlm_res result;
769a6fdc939Sscottr 
770a6fdc939Sscottr 	if (debug_level)
771a6fdc939Sscottr 		log_from_addr("nlm_nm_lock", rqstp);
772a6fdc939Sscottr 
773a6fdc939Sscottr 	/* copy cookie from arg to result.  See comment in nlm_test_1() */
774ceaa3a4fSchristos 	result.cookie = arg->cookie;
775ceaa3a4fSchristos 	result.stat.stat = nlm_granted;
776ceaa3a4fSchristos 	return &result;
777a6fdc939Sscottr }
778a6fdc939Sscottr 
779a6fdc939Sscottr /* nlm_free_all ------------------------------------------------------------ */
780a6fdc939Sscottr /*
781a6fdc939Sscottr  * Purpose:	Release all locks held by a named client
782a6fdc939Sscottr  * Returns:	Nothing
783a6fdc939Sscottr  * Notes:	Potential denial of service security problem here - the
784a6fdc939Sscottr  *		locks to be released are specified by a host name, independent
785a6fdc939Sscottr  *		of the address from which the request has arrived.
786a6fdc939Sscottr  *		Should probably be rejected if the named host has been
787a6fdc939Sscottr  *		using monitored locks.
788a6fdc939Sscottr  */
789a6fdc939Sscottr void *
790ceaa3a4fSchristos /*ARGSUSED*/
nlm_free_all_3_svc(nlm_notify * arg,struct svc_req * rqstp)791ceaa3a4fSchristos nlm_free_all_3_svc(nlm_notify *arg, struct svc_req *rqstp)
792a6fdc939Sscottr {
793a6fdc939Sscottr 	static char dummy;
794a6fdc939Sscottr 
795a6fdc939Sscottr 	if (debug_level)
796a6fdc939Sscottr 		log_from_addr("nlm_free_all", rqstp);
797ceaa3a4fSchristos 	return &dummy;
798a6fdc939Sscottr }
799a3bc666fSbouyer 
800a3bc666fSbouyer /* calls for nlm version 4 (NFSv3) */
801a3bc666fSbouyer /* nlm_test ---------------------------------------------------------------- */
802a3bc666fSbouyer /*
803a3bc666fSbouyer  * Purpose:	Test whether a specified lock would be granted if requested
804a3bc666fSbouyer  * Returns:	nlm_granted (or error code)
805a3bc666fSbouyer  * Notes:
806a3bc666fSbouyer  */
807a3bc666fSbouyer nlm4_testres *
nlm4_test_4_svc(nlm4_testargs * arg,struct svc_req * rqstp)808ceaa3a4fSchristos nlm4_test_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
809a3bc666fSbouyer {
810ceaa3a4fSchristos 	static nlm4_testres result;
811227ed983Sbouyer 	struct nlm4_holder *holder;
812a3bc666fSbouyer 
813a3bc666fSbouyer 	if (debug_level)
814a3bc666fSbouyer 		log_from_addr("nlm4_test", rqstp);
815a3bc666fSbouyer 
816227ed983Sbouyer 	holder = testlock(&arg->alock, LOCK_V4);
817227ed983Sbouyer 
818a3bc666fSbouyer 	/*
819a3bc666fSbouyer 	 * Copy the cookie from the argument into the result.  Note that this
820a3bc666fSbouyer 	 * is slightly hazardous, as the structure contains a pointer to a
821a3bc666fSbouyer 	 * malloc()ed buffer that will get freed by the caller.  However, the
822a3bc666fSbouyer 	 * main function transmits the result before freeing the argument
823a3bc666fSbouyer 	 * so it is in fact safe.
824a3bc666fSbouyer 	 */
825ceaa3a4fSchristos 	result.cookie = arg->cookie;
826227ed983Sbouyer 	if (holder == NULL) {
827ceaa3a4fSchristos 		result.stat.stat = nlm4_granted;
828227ed983Sbouyer 	} else {
829ceaa3a4fSchristos 		result.stat.stat = nlm4_denied;
830ceaa3a4fSchristos 		(void)memcpy(&result.stat.nlm4_testrply_u.holder, holder,
831227ed983Sbouyer 		    sizeof(struct nlm4_holder));
832227ed983Sbouyer 	}
833ceaa3a4fSchristos 	return &result;
834a3bc666fSbouyer }
835a3bc666fSbouyer 
836a3bc666fSbouyer void *
nlm4_test_msg_4_svc(nlm4_testargs * arg,struct svc_req * rqstp)837ceaa3a4fSchristos nlm4_test_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
838a3bc666fSbouyer {
839ceaa3a4fSchristos 	nlm4_testres result;
840a3bc666fSbouyer 	static char dummy;
84177044250Sfvdl 	struct sockaddr *addr;
842a3bc666fSbouyer 	CLIENT *cli;
843a3bc666fSbouyer 	int success;
844a3bc666fSbouyer 	struct timeval timeo;
845227ed983Sbouyer 	struct nlm4_holder *holder;
846a3bc666fSbouyer 
847a3bc666fSbouyer 	if (debug_level)
848a3bc666fSbouyer 		log_from_addr("nlm4_test_msg", rqstp);
849a3bc666fSbouyer 
850227ed983Sbouyer 	holder = testlock(&arg->alock, LOCK_V4);
851227ed983Sbouyer 
852ceaa3a4fSchristos 	result.cookie = arg->cookie;
853227ed983Sbouyer 	if (holder == NULL) {
854ceaa3a4fSchristos 		result.stat.stat = nlm4_granted;
855227ed983Sbouyer 	} else {
856ceaa3a4fSchristos 		result.stat.stat = nlm4_denied;
857ceaa3a4fSchristos 		(void)memcpy(&result.stat.nlm4_testrply_u.holder, holder,
858227ed983Sbouyer 		    sizeof(struct nlm4_holder));
859227ed983Sbouyer 	}
860a3bc666fSbouyer 
861a3bc666fSbouyer 	/*
862a3bc666fSbouyer 	 * nlm_test has different result type to the other operations, so
863a3bc666fSbouyer 	 * can't use transmit4_result() in this case
864a3bc666fSbouyer 	 */
86577044250Sfvdl 	addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
866227ed983Sbouyer 	if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
867a3bc666fSbouyer 		timeo.tv_sec = 0; /* No timeout - not expecting response */
868a3bc666fSbouyer 		timeo.tv_usec = 0;
869a3bc666fSbouyer 
870a3bc666fSbouyer 		success = clnt_call(cli, NLM4_TEST_RES, xdr_nlm4_testres,
871ceaa3a4fSchristos 		    &result, xdr_void, &dummy, timeo);
872a3bc666fSbouyer 
873a3bc666fSbouyer 		if (debug_level > 2)
874227ed983Sbouyer 			syslog(LOG_DEBUG, "clnt_call returns %d", success);
875a3bc666fSbouyer 	}
876ceaa3a4fSchristos 	return NULL;
877a3bc666fSbouyer }
878a3bc666fSbouyer 
879a3bc666fSbouyer /* nlm_lock ---------------------------------------------------------------- */
880a3bc666fSbouyer /*
881a3bc666fSbouyer  * Purposes:	Establish a lock
882a3bc666fSbouyer  * Returns:	granted, denied or blocked
883a3bc666fSbouyer  * Notes:	*** grace period support missing
884a3bc666fSbouyer  */
885a3bc666fSbouyer nlm4_res *
nlm4_lock_4_svc(nlm4_lockargs * arg,struct svc_req * rqstp)886ceaa3a4fSchristos nlm4_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
887a3bc666fSbouyer {
888ceaa3a4fSchristos 	static nlm4_res result;
889a3bc666fSbouyer 
890a3bc666fSbouyer 	if (debug_level)
891a3bc666fSbouyer 		log_from_addr("nlm4_lock", rqstp);
892a3bc666fSbouyer 
893a3bc666fSbouyer 	/* copy cookie from arg to result.  See comment in nlm_test_4() */
894ceaa3a4fSchristos 	result.cookie = arg->cookie;
895a3bc666fSbouyer 
896ceaa3a4fSchristos 	result.stat.stat = (enum nlm4_stats)getlock(arg, rqstp,
897ceaa3a4fSchristos 	    LOCK_MON | LOCK_V4);
898ceaa3a4fSchristos 	return &result;
899a3bc666fSbouyer }
900a3bc666fSbouyer 
901a3bc666fSbouyer void *
nlm4_lock_msg_4_svc(nlm4_lockargs * arg,struct svc_req * rqstp)902ceaa3a4fSchristos nlm4_lock_msg_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
903a3bc666fSbouyer {
904ceaa3a4fSchristos 	static nlm4_res result;
905a3bc666fSbouyer 
906a3bc666fSbouyer 	if (debug_level)
907a3bc666fSbouyer 		log_from_addr("nlm4_lock_msg", rqstp);
908a3bc666fSbouyer 
909ceaa3a4fSchristos 	result.cookie = arg->cookie;
910ceaa3a4fSchristos 	result.stat.stat = (enum nlm4_stats)getlock(arg, rqstp,
911ceaa3a4fSchristos 	    LOCK_MON | LOCK_ASYNC | LOCK_V4);
912ceaa3a4fSchristos 	transmit4_result(NLM4_LOCK_RES, &result,
913*dd5f6139Stron 	    (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf);
914a3bc666fSbouyer 
915ceaa3a4fSchristos 	return NULL;
916a3bc666fSbouyer }
917a3bc666fSbouyer 
918a3bc666fSbouyer /* nlm_cancel -------------------------------------------------------------- */
919a3bc666fSbouyer /*
920a3bc666fSbouyer  * Purpose:	Cancel a blocked lock request
921a3bc666fSbouyer  * Returns:	granted or denied
922a3bc666fSbouyer  * Notes:
923a3bc666fSbouyer  */
924a3bc666fSbouyer nlm4_res *
nlm4_cancel_4_svc(nlm4_cancargs * arg,struct svc_req * rqstp)925ceaa3a4fSchristos nlm4_cancel_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
926a3bc666fSbouyer {
927ceaa3a4fSchristos 	static nlm4_res result;
928a3bc666fSbouyer 
929a3bc666fSbouyer 	if (debug_level)
930a3bc666fSbouyer 		log_from_addr("nlm4_cancel", rqstp);
931a3bc666fSbouyer 
932a3bc666fSbouyer 	/* copy cookie from arg to result.  See comment in nlm_test_1() */
933ceaa3a4fSchristos 	result.cookie = arg->cookie;
934a3bc666fSbouyer 
935a3bc666fSbouyer 	/*
936a3bc666fSbouyer 	 * Since at present we never return 'nlm_blocked', there can never be
937a3bc666fSbouyer 	 * a lock to cancel, so this call always fails.
938a3bc666fSbouyer 	 */
939ceaa3a4fSchristos 	result.stat.stat = (enum nlm4_stats)unlock(&arg->alock, LOCK_CANCEL);
940ceaa3a4fSchristos 	return &result;
941a3bc666fSbouyer }
942a3bc666fSbouyer 
943a3bc666fSbouyer void *
nlm4_cancel_msg_4_svc(nlm4_cancargs * arg,struct svc_req * rqstp)944ceaa3a4fSchristos nlm4_cancel_msg_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
945a3bc666fSbouyer {
946ceaa3a4fSchristos 	static nlm4_res result;
947a3bc666fSbouyer 
948a3bc666fSbouyer 	if (debug_level)
949a3bc666fSbouyer 		log_from_addr("nlm4_cancel_msg", rqstp);
950a3bc666fSbouyer 
951ceaa3a4fSchristos 	result.cookie = arg->cookie;
952a3bc666fSbouyer 	/*
953a3bc666fSbouyer 	 * Since at present we never return 'nlm_blocked', there can never be
954a3bc666fSbouyer 	 * a lock to cancel, so this call always fails.
955a3bc666fSbouyer 	 */
956ceaa3a4fSchristos 	result.stat.stat = (enum nlm4_stats)unlock(&arg->alock,
957ceaa3a4fSchristos 	    LOCK_CANCEL | LOCK_V4);
958ceaa3a4fSchristos 	transmit4_result(NLM4_CANCEL_RES, &result,
959*dd5f6139Stron 	    (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf);
960ceaa3a4fSchristos 	return NULL;
961a3bc666fSbouyer }
962a3bc666fSbouyer 
963a3bc666fSbouyer /* nlm_unlock -------------------------------------------------------------- */
964a3bc666fSbouyer /*
965a3bc666fSbouyer  * Purpose:	Release an existing lock
966a3bc666fSbouyer  * Returns:	Always granted, unless during grace period
967a3bc666fSbouyer  * Notes:	"no such lock" error condition is ignored, as the
968a3bc666fSbouyer  *		protocol uses unreliable UDP datagrams, and may well
969a3bc666fSbouyer  *		re-try an unlock that has already succeeded.
970a3bc666fSbouyer  */
971a3bc666fSbouyer nlm4_res *
nlm4_unlock_4_svc(nlm4_unlockargs * arg,struct svc_req * rqstp)972ceaa3a4fSchristos nlm4_unlock_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
973a3bc666fSbouyer {
974ceaa3a4fSchristos 	static nlm4_res result;
975a3bc666fSbouyer 
976a3bc666fSbouyer 	if (debug_level)
977a3bc666fSbouyer 		log_from_addr("nlm4_unlock", rqstp);
978a3bc666fSbouyer 
979ceaa3a4fSchristos 	result.stat.stat = (enum nlm4_stats)unlock(&arg->alock, LOCK_V4);
980ceaa3a4fSchristos 	result.cookie = arg->cookie;
981a3bc666fSbouyer 
982ceaa3a4fSchristos 	return &result;
983a3bc666fSbouyer }
984a3bc666fSbouyer 
985a3bc666fSbouyer void *
nlm4_unlock_msg_4_svc(nlm4_unlockargs * arg,struct svc_req * rqstp)986ceaa3a4fSchristos nlm4_unlock_msg_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
987a3bc666fSbouyer {
988ceaa3a4fSchristos 	static nlm4_res result;
989a3bc666fSbouyer 
990a3bc666fSbouyer 	if (debug_level)
991a3bc666fSbouyer 		log_from_addr("nlm4_unlock_msg", rqstp);
992a3bc666fSbouyer 
993ceaa3a4fSchristos 	result.stat.stat = (enum nlm4_stats)unlock(&arg->alock, LOCK_V4);
994ceaa3a4fSchristos 	result.cookie = arg->cookie;
995a3bc666fSbouyer 
996ceaa3a4fSchristos 	transmit4_result(NLM4_UNLOCK_RES, &result,
997*dd5f6139Stron 	    (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf);
998ceaa3a4fSchristos 	return NULL;
999a3bc666fSbouyer }
1000a3bc666fSbouyer 
1001a3bc666fSbouyer /* ------------------------------------------------------------------------- */
1002a3bc666fSbouyer /*
1003a3bc666fSbouyer  * Client-side pseudo-RPCs for results.  Note that for the client there
1004a3bc666fSbouyer  * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
1005a3bc666fSbouyer  * version returns the results in the RPC result, and so the client
1006a3bc666fSbouyer  * does not normally receive incoming RPCs.
1007a3bc666fSbouyer  *
1008a3bc666fSbouyer  * The exception to this is nlm_granted(), which is genuinely an RPC
1009a3bc666fSbouyer  * call from the server to the client - a 'call-back' in normal procedure
1010a3bc666fSbouyer  * call terms.
1011a3bc666fSbouyer  */
1012a3bc666fSbouyer 
1013a3bc666fSbouyer /* nlm_granted ------------------------------------------------------------- */
1014a3bc666fSbouyer /*
1015a3bc666fSbouyer  * Purpose:	Receive notification that formerly blocked lock now granted
1016a3bc666fSbouyer  * Returns:	always success ('granted')
1017a3bc666fSbouyer  * Notes:
1018a3bc666fSbouyer  */
1019a3bc666fSbouyer nlm4_res *
nlm4_granted_4_svc(nlm4_testargs * arg,struct svc_req * rqstp)1020ceaa3a4fSchristos nlm4_granted_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
1021a3bc666fSbouyer {
1022ceaa3a4fSchristos 	static nlm4_res result;
1023a3bc666fSbouyer 
1024a3bc666fSbouyer 	if (debug_level)
1025a3bc666fSbouyer 		log_from_addr("nlm4_granted", rqstp);
1026a3bc666fSbouyer 
1027a3bc666fSbouyer 	/* copy cookie from arg to result.  See comment in nlm_test_1() */
1028ceaa3a4fSchristos 	result.cookie = arg->cookie;
1029a3bc666fSbouyer 
1030ceaa3a4fSchristos 	result.stat.stat = nlm4_granted;
1031ceaa3a4fSchristos 	return &result;
1032a3bc666fSbouyer }
1033a3bc666fSbouyer 
1034a3bc666fSbouyer void *
nlm4_granted_msg_4_svc(nlm4_testargs * arg,struct svc_req * rqstp)1035ceaa3a4fSchristos nlm4_granted_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
1036a3bc666fSbouyer {
1037ceaa3a4fSchristos 	static nlm4_res result;
1038a3bc666fSbouyer 
1039a3bc666fSbouyer 	if (debug_level)
1040a3bc666fSbouyer 		log_from_addr("nlm4_granted_msg", rqstp);
1041a3bc666fSbouyer 
1042ceaa3a4fSchristos 	result.cookie = arg->cookie;
1043ceaa3a4fSchristos 	result.stat.stat = nlm4_granted;
1044ceaa3a4fSchristos 	transmit4_result(NLM4_GRANTED_RES, &result,
104577044250Sfvdl 	    (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf);
1046ceaa3a4fSchristos 	return NULL;
1047a3bc666fSbouyer }
1048a3bc666fSbouyer 
1049a3bc666fSbouyer /* nlm_test_res ------------------------------------------------------------ */
1050a3bc666fSbouyer /*
1051a3bc666fSbouyer  * Purpose:	Accept result from earlier nlm_test_msg() call
1052a3bc666fSbouyer  * Returns:	Nothing
1053a3bc666fSbouyer  */
1054a3bc666fSbouyer void *
1055ceaa3a4fSchristos /*ARGSUSED*/
nlm4_test_res_4_svc(nlm4_testres * arg,struct svc_req * rqstp)1056ceaa3a4fSchristos nlm4_test_res_4_svc(nlm4_testres *arg, struct svc_req *rqstp)
1057a3bc666fSbouyer {
1058a3bc666fSbouyer 	if (debug_level)
1059a3bc666fSbouyer 		log_from_addr("nlm4_test_res", rqstp);
1060ceaa3a4fSchristos 	return NULL;
1061a3bc666fSbouyer }
1062a3bc666fSbouyer 
1063a3bc666fSbouyer /* nlm_lock_res ------------------------------------------------------------ */
1064a3bc666fSbouyer /*
1065a3bc666fSbouyer  * Purpose:	Accept result from earlier nlm_lock_msg() call
1066a3bc666fSbouyer  * Returns:	Nothing
1067a3bc666fSbouyer  */
1068a3bc666fSbouyer void *
1069ceaa3a4fSchristos /*ARGSUSED*/
nlm4_lock_res_4_svc(nlm4_res * arg,struct svc_req * rqstp)1070ceaa3a4fSchristos nlm4_lock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
1071a3bc666fSbouyer {
1072a3bc666fSbouyer 	if (debug_level)
1073a3bc666fSbouyer 		log_from_addr("nlm4_lock_res", rqstp);
1074a3bc666fSbouyer 
1075ceaa3a4fSchristos 	return NULL;
1076a3bc666fSbouyer }
1077a3bc666fSbouyer 
1078a3bc666fSbouyer /* nlm_cancel_res ---------------------------------------------------------- */
1079a3bc666fSbouyer /*
1080a3bc666fSbouyer  * Purpose:	Accept result from earlier nlm_cancel_msg() call
1081a3bc666fSbouyer  * Returns:	Nothing
1082a3bc666fSbouyer  */
1083a3bc666fSbouyer void *
1084ceaa3a4fSchristos /*ARGSUSED*/
nlm4_cancel_res_4_svc(nlm4_res * arg,struct svc_req * rqstp)1085ceaa3a4fSchristos nlm4_cancel_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
1086a3bc666fSbouyer {
1087a3bc666fSbouyer 	if (debug_level)
1088a3bc666fSbouyer 		log_from_addr("nlm4_cancel_res", rqstp);
1089ceaa3a4fSchristos 	return NULL;
1090a3bc666fSbouyer }
1091a3bc666fSbouyer 
1092a3bc666fSbouyer /* nlm_unlock_res ---------------------------------------------------------- */
1093a3bc666fSbouyer /*
1094a3bc666fSbouyer  * Purpose:	Accept result from earlier nlm_unlock_msg() call
1095a3bc666fSbouyer  * Returns:	Nothing
1096a3bc666fSbouyer  */
1097a3bc666fSbouyer void *
1098ceaa3a4fSchristos /*ARGSUSED*/
nlm4_unlock_res_4_svc(nlm4_res * arg,struct svc_req * rqstp)1099ceaa3a4fSchristos nlm4_unlock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
1100a3bc666fSbouyer {
1101a3bc666fSbouyer 	if (debug_level)
1102a3bc666fSbouyer 		log_from_addr("nlm4_unlock_res", rqstp);
1103ceaa3a4fSchristos 	return NULL;
1104a3bc666fSbouyer }
1105a3bc666fSbouyer 
1106a3bc666fSbouyer /* nlm_granted_res --------------------------------------------------------- */
1107a3bc666fSbouyer /*
1108a3bc666fSbouyer  * Purpose:	Accept result from earlier nlm_granted_msg() call
1109a3bc666fSbouyer  * Returns:	Nothing
1110a3bc666fSbouyer  */
1111a3bc666fSbouyer void *
1112ceaa3a4fSchristos /*ARGSUSED*/
nlm4_granted_res_4_svc(nlm4_res * arg,struct svc_req * rqstp)1113ceaa3a4fSchristos nlm4_granted_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
1114a3bc666fSbouyer {
1115a3bc666fSbouyer 	if (debug_level)
1116a3bc666fSbouyer 		log_from_addr("nlm4_granted_res", rqstp);
1117ceaa3a4fSchristos 	return NULL;
1118a3bc666fSbouyer }
1119a3bc666fSbouyer 
1120a3bc666fSbouyer /* ------------------------------------------------------------------------- */
1121a3bc666fSbouyer /*
1122a3bc666fSbouyer  * Calls for PCNFS locking (aka non-monitored locking, no involvement
1123a3bc666fSbouyer  * of rpc.statd).
1124a3bc666fSbouyer  *
1125a3bc666fSbouyer  * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
1126a3bc666fSbouyer  */
1127a3bc666fSbouyer 
1128a3bc666fSbouyer /* nlm_share --------------------------------------------------------------- */
1129a3bc666fSbouyer /*
1130a3bc666fSbouyer  * Purpose:	Establish a DOS-style lock
1131a3bc666fSbouyer  * Returns:	success or failure
1132a3bc666fSbouyer  * Notes:	Blocking locks are not supported - client is expected
1133a3bc666fSbouyer  *		to retry if required.
1134a3bc666fSbouyer  */
1135a3bc666fSbouyer nlm4_shareres *
nlm4_share_4_svc(nlm4_shareargs * arg,struct svc_req * rqstp)1136ceaa3a4fSchristos nlm4_share_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
1137a3bc666fSbouyer {
1138ceaa3a4fSchristos 	static nlm4_shareres result;
1139a3bc666fSbouyer 
1140a3bc666fSbouyer 	if (debug_level)
1141a3bc666fSbouyer 		log_from_addr("nlm4_share", rqstp);
1142a3bc666fSbouyer 
1143ceaa3a4fSchristos 	result.cookie = arg->cookie;
1144ceaa3a4fSchristos 	result.stat = nlm4_granted;
1145ceaa3a4fSchristos 	result.sequence = 1234356;	/* X/Open says this field is ignored? */
1146ceaa3a4fSchristos 	return &result;
1147a3bc666fSbouyer }
1148a3bc666fSbouyer 
1149a3bc666fSbouyer /* nlm4_unshare ------------------------------------------------------------ */
1150a3bc666fSbouyer /*
1151a3bc666fSbouyer  * Purpose:	Release a DOS-style lock
1152a3bc666fSbouyer  * Returns:	nlm_granted, unless in grace period
1153a3bc666fSbouyer  * Notes:
1154a3bc666fSbouyer  */
1155a3bc666fSbouyer nlm4_shareres *
nlm4_unshare_4_svc(nlm4_shareargs * arg,struct svc_req * rqstp)1156ceaa3a4fSchristos nlm4_unshare_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
1157a3bc666fSbouyer {
1158ceaa3a4fSchristos 	static nlm4_shareres result;
1159a3bc666fSbouyer 
1160a3bc666fSbouyer 	if (debug_level)
1161a3bc666fSbouyer 		log_from_addr("nlm_unshare", rqstp);
1162a3bc666fSbouyer 
1163ceaa3a4fSchristos 	result.cookie = arg->cookie;
1164ceaa3a4fSchristos 	result.stat = nlm4_granted;
1165ceaa3a4fSchristos 	result.sequence = 1234356;	/* X/Open says this field is ignored? */
1166ceaa3a4fSchristos 	return &result;
1167a3bc666fSbouyer }
1168a3bc666fSbouyer 
1169a3bc666fSbouyer /* nlm4_nm_lock ------------------------------------------------------------ */
1170a3bc666fSbouyer /*
1171a3bc666fSbouyer  * Purpose:	non-monitored version of nlm4_lock()
1172a3bc666fSbouyer  * Returns:	as for nlm4_lock()
1173a3bc666fSbouyer  * Notes:	These locks are in the same style as the standard nlm4_lock,
1174a3bc666fSbouyer  *		but the rpc.statd should not be called to establish a
1175a3bc666fSbouyer  *		monitor for the client machine, since that machine is
1176a3bc666fSbouyer  *		declared not to be running a rpc.statd, and so would not
1177a3bc666fSbouyer  *		respond to the statd protocol.
1178a3bc666fSbouyer  */
1179a3bc666fSbouyer nlm4_res *
nlm4_nm_lock_4_svc(nlm4_lockargs * arg,struct svc_req * rqstp)1180ceaa3a4fSchristos nlm4_nm_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
1181a3bc666fSbouyer {
1182ceaa3a4fSchristos 	static nlm4_res result;
1183a3bc666fSbouyer 
1184a3bc666fSbouyer 	if (debug_level)
1185a3bc666fSbouyer 		log_from_addr("nlm4_nm_lock", rqstp);
1186a3bc666fSbouyer 
1187a3bc666fSbouyer 	/* copy cookie from arg to result.  See comment in nlm4_test_1() */
1188ceaa3a4fSchristos 	result.cookie = arg->cookie;
1189ceaa3a4fSchristos 	result.stat.stat = nlm4_granted;
1190ceaa3a4fSchristos 	return &result;
1191a3bc666fSbouyer }
1192a3bc666fSbouyer 
1193a3bc666fSbouyer /* nlm4_free_all ------------------------------------------------------------ */
1194a3bc666fSbouyer /*
1195a3bc666fSbouyer  * Purpose:	Release all locks held by a named client
1196a3bc666fSbouyer  * Returns:	Nothing
1197a3bc666fSbouyer  * Notes:	Potential denial of service security problem here - the
1198a3bc666fSbouyer  *		locks to be released are specified by a host name, independent
1199a3bc666fSbouyer  *		of the address from which the request has arrived.
1200a3bc666fSbouyer  *		Should probably be rejected if the named host has been
1201a3bc666fSbouyer  *		using monitored locks.
1202a3bc666fSbouyer  */
1203a3bc666fSbouyer void *
1204ceaa3a4fSchristos /*ARGSUSED*/
nlm4_free_all_4_svc(nlm_notify * arg,struct svc_req * rqstp)1205ceaa3a4fSchristos nlm4_free_all_4_svc(nlm_notify *arg, struct svc_req *rqstp)
1206a3bc666fSbouyer {
1207a3bc666fSbouyer 	static char dummy;
1208a3bc666fSbouyer 
1209a3bc666fSbouyer 	if (debug_level)
1210a3bc666fSbouyer 		log_from_addr("nlm4_free_all", rqstp);
1211ceaa3a4fSchristos 	return &dummy;
1212a3bc666fSbouyer }
1213a3bc666fSbouyer 
1214227ed983Sbouyer /* nlm_sm_notify --------------------------------------------------------- */
1215227ed983Sbouyer /*
1216227ed983Sbouyer  * Purpose:	called by rpc.statd when a monitored host state changes.
1217227ed983Sbouyer  * Returns:	Nothing
1218227ed983Sbouyer  */
1219227ed983Sbouyer void *
1220ceaa3a4fSchristos /*ARGSUSED*/
nlm_sm_notify_0_svc(struct nlm_sm_status * arg,struct svc_req * rqstp)1221ceaa3a4fSchristos nlm_sm_notify_0_svc(struct nlm_sm_status *arg, struct svc_req *rqstp)
1222227ed983Sbouyer {
1223227ed983Sbouyer 	static char dummy;
1224227ed983Sbouyer 	notify(arg->mon_name, arg->state);
1225ceaa3a4fSchristos 	return &dummy;
1226227ed983Sbouyer }
1227