1/*
2 * Copyright (c) 2002-2010 Apple Inc.  All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*	$NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $	*/
24/*	$FreeBSD: src/usr.sbin/rpc.lockd/lock_proc.c,v 1.10 2002/03/22 20:00:10 alfred Exp $ */
25/*
26 * Copyright (c) 1995
27 *	A.R. Gordon (andrew.gordon@net-tel.co.uk).  All rights reserved.
28 *
29 * Redistribution and use in source and binary forms, with or without
30 * modification, are permitted provided that the following conditions
31 * are met:
32 * 1. Redistributions of source code must retain the above copyright
33 *    notice, this list of conditions and the following disclaimer.
34 * 2. Redistributions in binary form must reproduce the above copyright
35 *    notice, this list of conditions and the following disclaimer in the
36 *    documentation and/or other materials provided with the distribution.
37 * 3. All advertising materials mentioning features or use of this software
38 *    must display the following acknowledgement:
39 *	This product includes software developed for the FreeBSD project
40 * 4. Neither the name of the author nor the names of any co-contributors
41 *    may be used to endorse or promote products derived from this software
42 *    without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 *
56 */
57
58#include <sys/cdefs.h>
59#ifndef lint
60__RCSID("$NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $");
61#endif
62
63#include <sys/param.h>
64#include <sys/socket.h>
65
66#include <netinet/in.h>
67#include <arpa/inet.h>
68
69#include <netdb.h>
70#include <stdio.h>
71#include <string.h>
72#include <syslog.h>
73#include <stdlib.h>
74#include <sys/queue.h>
75
76#include <oncrpc/rpc.h>
77#include "sm_inter.h"
78#include "nlm_prot.h"
79
80#include "lockd.h"
81#include "lockd_lock.h"
82
83
84#define	CLIENT_CACHE_SIZE	64	/* No. of client sockets cached */
85#define	CLIENT_CACHE_LIFETIME	120	/* In seconds */
86
87#define AOK	(void *)	// assert alignment is OK
88
89static void	log_from_addr(const char *, struct svc_req *);
90static void	log_netobj(netobj *obj);
91
92/* log_from_addr ----------------------------------------------------------- */
93/*
94 * Purpose:	Log name of function called and source address
95 * Returns:	Nothing
96 * Notes:	Extracts the source address from the transport handle
97 *		passed in as part of the called procedure specification
98 */
99static void
100log_from_addr(fun_name, req)
101	const char *fun_name;
102	struct svc_req *req;
103{
104	struct sockaddr *addr;
105	char hostname_buf[NI_MAXHOST];
106
107	addr = svc_getcaller_sa(req->rq_xprt);
108	if (getnameinfo(addr, addr->sa_len, hostname_buf, sizeof hostname_buf, NULL, 0, 0) != 0)
109		return;
110
111	syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf);
112}
113
114/* log_netobj ----------------------------------------------------------- */
115/*
116 * Purpose:	Log a netobj
117 * Returns:	Nothing
118 * Notes:	This function should only really be called as part of
119 *  		a debug subsystem.
120*/
121static void
122log_netobj(obj)
123	netobj *obj;
124{
125	char objvalbuffer[(sizeof(char)*2)*MAX_NETOBJ_SZ+2];
126	char objascbuffer[sizeof(char)*MAX_NETOBJ_SZ+1];
127	unsigned int i, maxlen;
128	char *tmp1, *tmp2;
129
130	/* Notify of potential security attacks */
131	if (obj->n_len > MAX_NETOBJ_SZ)	{
132		syslog(LOG_DEBUG, "SOMEONE IS TRYING TO DO SOMETHING NASTY!\n");
133		syslog(LOG_DEBUG, "netobj too large! Should be %d was %d\n",
134		    MAX_NETOBJ_SZ, obj->n_len);
135	}
136	/* Prevent the security hazard from the buffer overflow */
137	maxlen = (obj->n_len < MAX_NETOBJ_SZ ? obj->n_len : MAX_NETOBJ_SZ);
138	for (i=0, tmp1 = objvalbuffer, tmp2 = objascbuffer; i < maxlen;
139	    i++, tmp1 +=2, tmp2 +=1) {
140		snprintf(tmp1, 2+1, "%02X", *(obj->n_bytes+i));
141		snprintf(tmp2, 1+1, "%c", *(obj->n_bytes+i));
142	}
143	*tmp1 = '\0';
144	*tmp2 = '\0';
145	syslog(LOG_DEBUG,"netobjvals: %s\n",objvalbuffer);
146	syslog(LOG_DEBUG,"netobjascs: %s\n",objascbuffer);
147}
148/* get_client -------------------------------------------------------------- */
149/*
150 * Purpose:	Get a CLIENT* for making RPC calls to lockd on given host
151 * Returns:	CLIENT* pointer, from clnt(udp|tcp)_create, or NULL if error
152 * Notes:	Creating a CLIENT* is quite expensive, involving a
153 *		conversation with the remote portmapper to get the
154 *		port number.  Since a given client is quite likely
155 *		to make several locking requests in succession, it is
156 *		desirable to cache the created CLIENT*.
157 *
158 *		Since we are using UDP by default (rather than TCP), there is no
159 *		cost to the remote system in keeping these cached indefinitely.
160 *		Unfortunately there is a snag: if the remote system
161 *		reboots, the cached portmapper results will be invalid,
162 *		and we will never detect this since all of the xxx_msg()
163 *		calls return no result - we just fire off a UDP packet
164 *		and hope for the best.
165 *
166 *		We solve this by discarding cached values after two
167 *		minutes, regardless of whether they have been used
168 *		in the meanwhile (since a bad one might have been used
169 *		plenty of times, as the host keeps retrying the request
170 *		and we keep sending the reply back to the wrong port).
171 *
172 *		Given that the entries will always expire in the order
173 *		that they were created, there is no point in a LRU
174 *		algorithm for when the cache gets full - entries are
175 *		always re-used in sequence.
176 */
177static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE];
178static long clnt_cache_time[CLIENT_CACHE_SIZE];	/* time entry created */
179static struct sockaddr_storage clnt_cache_addr[CLIENT_CACHE_SIZE];
180static rpcvers_t clnt_cache_vers[CLIENT_CACHE_SIZE];
181static int clnt_cache_next_to_use = 0;
182
183/*
184 * Because lockd is single-threaded, slow/unresponsive portmappers on
185 * clients can cause serious performance issues.  So, we keep a list of
186 * these bad hosts, and limit how often we try to get_client() for those hosts.
187 */
188struct badhost {
189	TAILQ_ENTRY(badhost) list;
190	struct sockaddr_storage addr;	/* host address */
191	int count;			/* # of occurences */
192	time_t timelast;		/* last attempted */
193	time_t timenext;		/* next allowed */
194};
195TAILQ_HEAD(badhostlist_head, badhost);
196static struct badhostlist_head badhostlist_head = TAILQ_HEAD_INITIALIZER(badhostlist_head);
197#define	BADHOST_CLIENT_TOOK_TOO_LONG	5	/* In seconds */
198#define	BADHOST_NFS_CLIENT_SIDE_DELAY	60	/* In seconds */
199#define	BADHOST_INITIAL_DELAY		120	/* In seconds */
200#define	BADHOST_MAXIMUM_DELAY		3600	/* In seconds */
201#define	BADHOST_DELAY_INCREMENT		300	/* In seconds */
202
203int
204addrcmp(const struct sockaddr *sa1, const struct sockaddr *sa2)
205{
206	int len;
207	void *p1, *p2;
208
209	if (sa1->sa_family != sa2->sa_family)
210		return -1;
211
212	switch (sa1->sa_family) {
213	case AF_INET:
214		p1 = &((struct sockaddr_in *) AOK sa1)->sin_addr;
215		p2 = &((struct sockaddr_in *) AOK sa2)->sin_addr;
216		len = 4;
217		break;
218	case AF_INET6:
219		p1 = &((struct sockaddr_in6 *) AOK sa1)->sin6_addr;
220		p2 = &((struct sockaddr_in6 *) AOK sa2)->sin6_addr;
221		len = 16;
222		break;
223	default:
224		return -1;
225	}
226
227	return memcmp(p1, p2, len);
228}
229
230CLIENT *
231get_client(host_addr, vers, client_request, use_tcp)
232	struct sockaddr *host_addr;
233	rpcvers_t vers;
234	int client_request;
235	int use_tcp;
236{
237	CLIENT *client, *cached_client;
238	struct timeval retry_time, time_now;
239	int i;
240	int sock_no, cache_ttl;
241	time_t time_start, cache_time = 0;
242	struct badhost *badhost, *nextbadhost;
243	char addrbuf[2*INET6_ADDRSTRLEN];
244
245	if (config.send_using_mnt_transport == 0)
246		use_tcp = 0;
247
248	if (!use_tcp && config.send_using_tcp)
249		use_tcp = config.send_using_tcp;
250
251	gettimeofday(&time_now, NULL);
252
253	/* use an extremely short TTL when reclaims are being sent */
254	cache_ttl = (client_request > 1) ? 4 : CLIENT_CACHE_LIFETIME;
255
256	/*
257	 * Search for the given client in the cache.
258	 */
259	cached_client = NULL;
260	for (i = 0; i < CLIENT_CACHE_SIZE; i++) {
261		client = clnt_cache_ptr[i];
262		if (!client)
263			continue;
264		if (clnt_cache_vers[i] != vers)
265			continue;
266		if (addrcmp((struct sockaddr *)&clnt_cache_addr[i], host_addr))
267			continue;
268		/* Found it! */
269		if (((clnt_cache_time[i] + cache_ttl) > time_now.tv_sec)) {
270			if (config.verbose > 3)
271				syslog(LOG_DEBUG, "Found CLIENT* in cache");
272			return (client);
273		}
274		if (config.verbose)
275			syslog(LOG_DEBUG, "Found expired CLIENT* in cache");
276		cached_client = client;
277		/* if we end up reusing this guy, make sure we keep the same timestamp */
278		cache_time = clnt_cache_time[i];
279		clnt_cache_time[i] = 0L;
280		clnt_cache_ptr[i] = NULL;
281		client = NULL;
282		break;
283	}
284
285	/*
286	 * Search for the given client in the badhost list.
287	 */
288	badhost = TAILQ_FIRST(&badhostlist_head);
289	while (badhost) {
290		nextbadhost = TAILQ_NEXT(badhost, list);
291		if (!addrcmp(host_addr, (struct sockaddr *)&badhost->addr))
292			break;
293		if ((badhost->timelast + BADHOST_MAXIMUM_DELAY) < time_now.tv_sec) {
294			/* cleanup entries we haven't heard from in a while */
295			TAILQ_REMOVE(&badhostlist_head, badhost, list);
296			free(badhost);
297		}
298		badhost = nextbadhost;
299	}
300
301	/*
302	 * If we're getting this "CLIENT*" to send an NFS client side message to
303	 * an NFS server's lockd, then limit the badhost delay to 60 seconds.
304	 */
305	if (badhost && client_request && ((time_now.tv_sec - badhost->timelast) >= BADHOST_NFS_CLIENT_SIDE_DELAY))
306		badhost->timenext = time_now.tv_sec;
307	if (badhost && (time_now.tv_sec < badhost->timenext)) {
308		/*
309		 * We've got a badhost, and we don't want to try
310		 * consulting it again yet.  If we've got a stale
311		 * cached CLIENT*, go ahead and try to use that.
312		 */
313		if (cached_client) {
314			if (config.verbose)
315				syslog(LOG_DEBUG, "badhost delayed: stale CLIENT* found in cache");
316			/* Free the next entry if it is in use. */
317			if (clnt_cache_ptr[clnt_cache_next_to_use]) {
318				clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
319				clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
320			}
321			client = cached_client;
322			goto update_cache_entry;
323		}
324		if (config.verbose)
325			syslog(LOG_DEBUG, "badhost delayed: valid CLIENT* not found in cache");
326		return NULL;
327	}
328
329	if (config.verbose > 3) {
330		if (!cached_client)
331			syslog(LOG_DEBUG, "CLIENT* not found in cache, creating");
332		else
333			syslog(LOG_DEBUG, "stale CLIENT* found in cache, updating");
334	}
335
336	/* Free the next entry if it is in use. */
337	if (clnt_cache_ptr[clnt_cache_next_to_use]) {
338		clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
339		clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
340	}
341
342	/* Create the new client handle                                       */
343	time_start = time_now.tv_sec;
344
345	sock_no = RPC_ANYSOCK;
346	retry_time.tv_sec = 5;
347	retry_time.tv_usec = 0;
348	if (host_addr->sa_family == AF_INET)	/* Force consultation with portmapper   */
349		((struct sockaddr_in *) AOK host_addr)->sin_port = 0;
350	else
351		((struct sockaddr_in6 *) AOK host_addr)->sin6_port = 0;
352	if (use_tcp)
353		client = clnttcp_create_sa(host_addr, NLM_PROG, vers, &sock_no, 0, 0);
354	if (!use_tcp || !client)
355		client = clntudp_create_sa(host_addr, NLM_PROG, vers, retry_time, &sock_no);
356
357	gettimeofday(&time_now, NULL);
358	if (time_now.tv_sec - time_start >= BADHOST_CLIENT_TOOK_TOO_LONG) {
359		/*
360		 * The client create took a long time!  (slow/unresponsive portmapper?)
361		 * Add/update an entry in the badhost list.
362		 */
363		if (!badhost && (badhost = malloc(sizeof(struct badhost)))) {
364			/* allocate new badhost */
365			memcpy(&badhost->addr, host_addr, host_addr->sa_len);
366			badhost->count = 0;
367			TAILQ_INSERT_TAIL(&badhostlist_head, badhost, list);
368		}
369		if (badhost) {
370			/* update count and times */
371			badhost->count++;
372			badhost->timelast = time_now.tv_sec;
373			if (client_request) {
374				/* limit NFS client side badhost delay */
375				badhost->timenext = time_now.tv_sec + BADHOST_NFS_CLIENT_SIDE_DELAY;
376			} else if (badhost->count == 1) {
377				/* first timers get a shorter initial delay */
378				badhost->timenext = time_now.tv_sec + BADHOST_INITIAL_DELAY;
379			} else {
380				/* multiple offenders get an increasingly larger delay */
381				int delay = (badhost->count - 1) * BADHOST_DELAY_INCREMENT;
382				if (delay > BADHOST_MAXIMUM_DELAY)
383					delay = BADHOST_MAXIMUM_DELAY;
384				badhost->timenext = time_now.tv_sec + delay;
385			}
386			/* move to end of list */
387			TAILQ_REMOVE(&badhostlist_head, badhost, list);
388			TAILQ_INSERT_TAIL(&badhostlist_head, badhost, list);
389		}
390	} else if (badhost) {
391		/* host seems good now, remove it from list */
392		TAILQ_REMOVE(&badhostlist_head, badhost, list);
393		free(badhost);
394		badhost = NULL;
395	}
396
397	if (!client) {
398		/* We couldn't get a new CLIENT* */
399		if (!cached_client) {
400			getnameinfo(host_addr, host_addr->sa_len, addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
401			syslog(LOG_WARNING, "Unable to contact %s: %s", addrbuf,
402				clnt_spcreateerror(use_tcp ? "clnttcp_create" : "clntudp_create"));
403			return NULL;
404		}
405		/*
406		 * We couldn't get updated info from portmapper, but we did
407		 * still have the stale cached data.  So we might as well try
408		 * to use it.
409		 */
410		client = cached_client;
411		getnameinfo(host_addr, host_addr->sa_len, addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
412		syslog(LOG_WARNING, "Unable to update contact info for %s: %s", addrbuf,
413			clnt_spcreateerror(use_tcp ? "clnttcp_create" : "clntudp_create"));
414	} else {
415		/*
416		 * We've got a new/updated CLIENT* for this host.
417		 * So, destroy any previously cached CLIENT*.
418		 */
419		if (cached_client)
420			clnt_destroy(cached_client);
421
422		/*
423		 * Disable the default timeout, so we can specify our own in calls
424		 * to clnt_call().  (Note that the timeout is a different concept
425		 * from the retry period set in clnt(udp|tcp)_create() above.)
426		 */
427		retry_time.tv_sec = -1;
428		retry_time.tv_usec = -1;
429		clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time);
430
431		if (config.verbose > 3) {
432			getnameinfo(host_addr, host_addr->sa_len, addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
433			syslog(LOG_DEBUG, "Created CLIENT* for %s", addrbuf);
434		}
435
436		/* make sure the new entry gets the current timestamp */
437		cache_time = time_now.tv_sec;
438	}
439
440update_cache_entry:
441	/* Success (of some sort) - update the cache entry */
442	clnt_cache_ptr[clnt_cache_next_to_use] = client;
443	memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr,
444	    host_addr->sa_len);
445	clnt_cache_vers[clnt_cache_next_to_use] = vers;
446	clnt_cache_time[clnt_cache_next_to_use] = cache_time;
447	if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE)
448		clnt_cache_next_to_use = 0;
449
450	return client;
451}
452
453
454/* transmit_result --------------------------------------------------------- */
455/*
456 * Purpose:	Transmit result for nlm_xxx_msg pseudo-RPCs
457 * Returns:	success (0) or failure (-1) at sending the datagram
458 * Notes:	clnt_call() will always fail (with timeout) as we are
459 *		calling it with timeout 0 as a hack to just issue a datagram
460 *		without expecting a result
461 */
462int
463transmit_result(opcode, result, addr, client_request)
464	int opcode;
465	nlm_res *result;
466	struct sockaddr *addr;
467	int client_request;
468{
469	static char dummy;
470	CLIENT *cli;
471	struct timeval timeo;
472	int success;
473
474	if ((cli = get_client(addr, NLM_VERS, client_request, 0)) != NULL) {
475		timeo.tv_sec = 0; /* No timeout - not expecting response */
476		timeo.tv_usec = 0;
477
478		success = clnt_call(cli, opcode, (xdrproc_t)xdr_nlm_res, result, (xdrproc_t)xdr_void,
479		    &dummy, timeo);
480
481		if (config.verbose > 2)
482			syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
483			    success, clnt_sperrno(success));
484		return (0);
485	}
486	return (-1);
487}
488/* transmit4_result --------------------------------------------------------- */
489/*
490 * Purpose:	Transmit result for nlm4_xxx_msg pseudo-RPCs
491 * Returns:	success (0) or failure (-1) at sending the datagram
492 * Notes:	clnt_call() will always fail (with timeout) as we are
493 *		calling it with timeout 0 as a hack to just issue a datagram
494 *		without expecting a result
495 */
496int
497transmit4_result(opcode, result, addr, client_request)
498	int opcode;
499	nlm4_res *result;
500	struct sockaddr *addr;
501	int client_request;
502{
503	static char dummy;
504	CLIENT *cli;
505	struct timeval timeo;
506	int success;
507
508	if ((cli = get_client(addr, NLM_VERS4, client_request, 0)) != NULL) {
509		timeo.tv_sec = 0; /* No timeout - not expecting response */
510		timeo.tv_usec = 0;
511
512		success = clnt_call(cli, opcode, (xdrproc_t)xdr_nlm4_res, result, (xdrproc_t)xdr_void,
513		    &dummy, timeo);
514
515		if (config.verbose > 2)
516			syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
517			    success, clnt_sperrno(success));
518		return (0);
519	}
520	return (-1);
521}
522
523/*
524 * converts a struct nlm_lock to struct nlm4_lock
525 */
526static void nlmtonlm4(struct nlm_lock *, struct nlm4_lock *);
527static void
528nlmtonlm4(arg, arg4)
529	struct nlm_lock *arg;
530	struct nlm4_lock *arg4;
531{
532	arg4->caller_name = arg->caller_name;
533	arg4->fh = arg->fh;
534	arg4->oh = arg->oh;
535	arg4->svid = arg->svid;
536	arg4->l_offset = arg->l_offset;
537	arg4->l_len = arg->l_len;
538}
539/* ------------------------------------------------------------------------- */
540/*
541 * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
542 * involved to ensure reclaim of locks after a crash of the "stateless"
543 * server.
544 *
545 * These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
546 * The first are standard RPCs with argument and result.
547 * The nlm_xxx_msg() calls implement exactly the same functions, but
548 * use two pseudo-RPCs (one in each direction).  These calls are NOT
549 * standard use of the RPC protocol in that they do not return a result
550 * at all (NB. this is quite different from returning a void result).
551 * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
552 * datagrams, requiring higher-level code to perform retries.
553 *
554 * Despite the disadvantages of the nlm_xxx_msg() approach (some of which
555 * are documented in the comments to get_client() above), this is the
556 * interface used by all current commercial NFS implementations
557 * [Solaris, SCO, AIX etc.].  This is presumed to be because these allow
558 * implementations to continue using the standard RPC libraries, while
559 * avoiding the block-until-result nature of the library interface.
560 *
561 * No client implementations have been identified so far that make use
562 * of the true RPC version (early SunOS releases would be a likely candidate
563 * for testing).
564 */
565
566/* nlm_test ---------------------------------------------------------------- */
567/*
568 * Purpose:	Test whether a specified lock would be granted if requested
569 * Returns:	nlm_granted (or error code)
570 * Notes:
571 */
572nlm_testres *
573nlm_test_1_svc(arg, rqstp)
574	nlm_testargs *arg;
575	struct svc_req *rqstp;
576{
577	static nlm_testres res;
578	struct nlm4_lock arg4;
579	struct nlm4_holder *holder;
580	nlmtonlm4(&arg->alock, &arg4);
581
582	if (config.verbose)
583		log_from_addr("nlm_test", rqstp);
584
585	holder = testlock(&arg4, arg->exclusive, 0);
586	/*
587	 * Copy the cookie from the argument into the result.  Note that this
588	 * is slightly hazardous, as the structure contains a pointer to a
589	 * malloc()ed buffer that will get freed by the caller.  However, the
590	 * main function transmits the result before freeing the argument
591	 * so it is in fact safe.
592	 */
593	res.cookie = arg->cookie;
594	if (holder == NULL) {
595		res.stat.stat = nlm_granted;
596	} else {
597		res.stat.stat = nlm_denied;
598		memcpy(&res.stat.nlm_testrply_u.holder, holder,
599		    sizeof(struct nlm_holder));
600		res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
601		res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
602	}
603	return (&res);
604}
605
606void *
607nlm_test_msg_1_svc(arg, rqstp)
608	nlm_testargs *arg;
609	struct svc_req *rqstp;
610{
611	nlm_testres res;
612	static char dummy;
613	CLIENT *cli;
614	int success;
615	struct timeval timeo;
616	struct nlm4_lock arg4;
617	struct nlm4_holder *holder;
618
619	nlmtonlm4(&arg->alock, &arg4);
620
621	if (config.verbose)
622		log_from_addr("nlm_test_msg", rqstp);
623
624	holder = testlock(&arg4, arg->exclusive, 0);
625
626	res.cookie = arg->cookie;
627	if (holder == NULL) {
628		res.stat.stat = nlm_granted;
629	} else {
630		res.stat.stat = nlm_denied;
631		memcpy(&res.stat.nlm_testrply_u.holder, holder,
632		    sizeof(struct nlm_holder));
633		res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
634		res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
635	}
636
637	/*
638	 * nlm_test has different result type to the other operations, so
639	 * can't use transmit_result() in this case
640	 */
641	if ((cli = get_client(svc_getcaller_sa(rqstp->rq_xprt), NLM_VERS, 0, 0)) != NULL) {
642		timeo.tv_sec = 0; /* No timeout - not expecting response */
643		timeo.tv_usec = 0;
644
645		success = clnt_call(cli, NLM_TEST_RES, (xdrproc_t)xdr_nlm_testres,
646		    &res, (xdrproc_t)xdr_void, &dummy, timeo);
647
648		if (config.verbose > 2)
649			syslog(LOG_DEBUG, "clnt_call returns %d", success);
650	}
651	return (NULL);
652}
653
654/* nlm_lock ---------------------------------------------------------------- */
655/*
656 * Purposes:	Establish a lock
657 * Returns:	granted, denied or blocked
658 * Notes:	*** grace period support missing
659 */
660nlm_res *
661nlm_lock_1_svc(arg, rqstp)
662	nlm_lockargs *arg;
663	struct svc_req *rqstp;
664{
665	static nlm_res res;
666	struct nlm4_lockargs arg4;
667	nlmtonlm4(&arg->alock, &arg4.alock);
668	arg4.cookie = arg->cookie;
669	arg4.block = arg->block;
670	arg4.exclusive = arg->exclusive;
671	arg4.reclaim = arg->reclaim;
672	arg4.state = arg->state;
673
674	if (config.verbose)
675		log_from_addr("nlm_lock", rqstp);
676
677	/* copy cookie from arg to result.  See comment in nlm_test_1() */
678	res.cookie = arg->cookie;
679
680	res.stat.stat = (nlm_stats) getlock(&arg4, rqstp, LOCK_MON);
681	return (&res);
682}
683
684void *
685nlm_lock_msg_1_svc(arg, rqstp)
686	nlm_lockargs *arg;
687	struct svc_req *rqstp;
688{
689	static nlm_res res;
690	struct nlm4_lockargs arg4;
691
692	nlmtonlm4(&arg->alock, &arg4.alock);
693	arg4.cookie = arg->cookie;
694	arg4.block = arg->block;
695	arg4.exclusive = arg->exclusive;
696	arg4.reclaim = arg->reclaim;
697	arg4.state = arg->state;
698
699	if (config.verbose)
700		log_from_addr("nlm_lock_msg", rqstp);
701
702	res.cookie = arg->cookie;
703	res.stat.stat = (nlm_stats) getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON);
704	if (transmit_result(NLM_LOCK_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 0) < 0) {
705		/* if res.stat.stat was success/blocked, then unlock/cancel */
706		if (res.stat.stat == nlm_granted)
707			unlock(&arg4.alock, LOCK_V4);
708		else if (res.stat.stat == nlm_blocked) {
709			nlm4_cancargs carg;
710			carg.cookie = arg4.cookie;
711			carg.block = arg4.block;
712			carg.exclusive = arg4.exclusive;
713			carg.alock = arg4.alock;
714			cancellock(&carg, 0);
715		}
716	}
717
718	return (NULL);
719}
720
721/* nlm_cancel -------------------------------------------------------------- */
722/*
723 * Purpose:	Cancel a blocked lock request
724 * Returns:	granted or denied
725 * Notes:
726 */
727nlm_res *
728nlm_cancel_1_svc(arg, rqstp)
729	nlm_cancargs *arg;
730	struct svc_req *rqstp;
731{
732	static nlm_res res;
733	struct nlm4_cancargs arg4;
734
735	arg4.cookie = arg->cookie;
736	arg4.block = arg->block;
737	arg4.exclusive = arg->exclusive;
738	nlmtonlm4(&arg->alock, &arg4.alock);
739
740	if (config.verbose)
741		log_from_addr("nlm_cancel", rqstp);
742
743	/* copy cookie from arg to result.  See comment in nlm_test_1() */
744	res.cookie = arg->cookie;
745
746	res.stat.stat = (nlm_stats) cancellock(&arg4, 0);
747	return (&res);
748}
749
750void *
751nlm_cancel_msg_1_svc(arg, rqstp)
752	nlm_cancargs *arg;
753	struct svc_req *rqstp;
754{
755	static nlm_res res;
756	struct nlm4_cancargs arg4;
757
758	arg4.cookie = arg->cookie;
759	arg4.block = arg->block;
760	arg4.exclusive = arg->exclusive;
761	nlmtonlm4(&arg->alock, &arg4.alock);
762
763	if (config.verbose)
764		log_from_addr("nlm_cancel_msg", rqstp);
765
766	res.cookie = arg->cookie;
767	res.stat.stat = (nlm_stats) cancellock(&arg4, 0);
768	if (transmit_result(NLM_CANCEL_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 0) < 0) {
769		/* XXX do we need to (un)do anything if this fails? */
770	}
771	return (NULL);
772}
773
774/* nlm_unlock -------------------------------------------------------------- */
775/*
776 * Purpose:	Release an existing lock
777 * Returns:	Always granted, unless during grace period
778 * Notes:	"no such lock" error condition is ignored, as the
779 *		protocol uses unreliable UDP datagrams, and may well
780 *		re-try an unlock that has already succeeded.
781 */
782nlm_res *
783nlm_unlock_1_svc(arg, rqstp)
784	nlm_unlockargs *arg;
785	struct svc_req *rqstp;
786{
787	static nlm_res res;
788	struct nlm4_lock arg4;
789
790	nlmtonlm4(&arg->alock, &arg4);
791
792	if (config.verbose)
793		log_from_addr("nlm_unlock", rqstp);
794
795	res.stat.stat = (nlm_stats) unlock(&arg4, 0);
796	res.cookie = arg->cookie;
797
798	return (&res);
799}
800
801void *
802nlm_unlock_msg_1_svc(arg, rqstp)
803	nlm_unlockargs *arg;
804	struct svc_req *rqstp;
805{
806	static nlm_res res;
807	struct nlm4_lock arg4;
808
809	nlmtonlm4(&arg->alock, &arg4);
810
811	if (config.verbose)
812		log_from_addr("nlm_unlock_msg", rqstp);
813
814	res.stat.stat = (nlm_stats) unlock(&arg4, 0);
815	res.cookie = arg->cookie;
816
817	if (transmit_result(NLM_UNLOCK_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 0) < 0) {
818		/* XXX do we need to (un)do anything if this fails? */
819	}
820	return (NULL);
821}
822
823/* ------------------------------------------------------------------------- */
824/*
825 * Client-side pseudo-RPCs for results.  Note that for the client there
826 * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
827 * version returns the results in the RPC result, and so the client
828 * does not normally receive incoming RPCs.
829 *
830 * The exception to this is nlm_granted(), which is genuinely an RPC
831 * call from the server to the client - a 'call-back' in normal procedure
832 * call terms.
833 */
834
835/* nlm_granted ------------------------------------------------------------- */
836/*
837 * Purpose:	Receive notification that formerly blocked lock now granted
838 * Returns:	always success ('granted')
839 * Notes:
840 */
841nlm_res *
842nlm_granted_1_svc(arg, rqstp)
843	nlm_testargs *arg;
844	struct svc_req *rqstp;
845{
846	static nlm_res res;
847	nlm4_lock lock4;
848	int flags;
849
850	if (config.verbose)
851		log_from_addr("nlm_granted", rqstp);
852
853	lock4.fh = arg->alock.fh;
854	lock4.svid = arg->alock.svid;
855	lock4.l_offset = arg->alock.l_offset;
856	lock4.l_len = arg->alock.l_len;
857
858	flags = LOCK_ANSWER_GRANTED;
859	if (arg->exclusive)
860		flags |= LOCK_ANSWER_LOCK_EXCL;
861
862	if (lock_answer(NLM_VERS, &arg->cookie, &lock4, flags, nlm_granted))
863		res.stat.stat = nlm_denied;
864	else
865		res.stat.stat = nlm_granted;
866
867	/* copy cookie from arg to result.  See comment in nlm_test_1() */
868	res.cookie = arg->cookie;
869
870	return (&res);
871}
872
873void *
874nlm_granted_msg_1_svc(arg, rqstp)
875	nlm_testargs *arg;
876	struct svc_req *rqstp;
877{
878	static nlm_res res;
879	nlm4_lock lock4;
880	int flags;
881
882	if (config.verbose)
883		log_from_addr("nlm_granted_msg", rqstp);
884
885	lock4.fh = arg->alock.fh;
886	lock4.svid = arg->alock.svid;
887	lock4.l_offset = arg->alock.l_offset;
888	lock4.l_len = arg->alock.l_len;
889
890	flags = LOCK_ANSWER_GRANTED;
891	if (arg->exclusive)
892		flags |= LOCK_ANSWER_LOCK_EXCL;
893
894	if (lock_answer(NLM_VERS, &arg->cookie, &lock4, flags, nlm_granted))
895		res.stat.stat = nlm_denied;
896	else
897		res.stat.stat = nlm_granted;
898
899	res.cookie = arg->cookie;
900
901	if (transmit_result(NLM_GRANTED_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 1) < 0) {
902		/* XXX do we need to (un)do anything if this fails? */
903	}
904	return (NULL);
905}
906
907/* nlm_test_res ------------------------------------------------------------ */
908/*
909 * Purpose:	Accept result from earlier nlm_test_msg() call
910 * Returns:	Nothing
911 */
912void *
913nlm_test_res_1_svc(arg, rqstp)
914	nlm_testres *arg;
915	struct svc_req *rqstp;
916{
917	nlm4_lock lock4;
918	int flags = 0;
919
920	if (config.verbose)
921		log_from_addr("nlm_test_res", rqstp);
922
923	if (arg->stat.stat == nlm_denied) {
924		lock4.fh.n_len = 0;
925		lock4.svid = arg->stat.nlm_testrply_u.holder.svid;
926		lock4.l_offset = arg->stat.nlm_testrply_u.holder.l_offset;
927		lock4.l_len = arg->stat.nlm_testrply_u.holder.l_len;
928		if (arg->stat.nlm_testrply_u.holder.exclusive)
929			flags |= LOCK_ANSWER_LOCK_EXCL;
930		lock_answer(NLM_VERS, &arg->cookie, &lock4, flags, arg->stat.stat);
931	} else
932		lock_answer(NLM_VERS, &arg->cookie, NULL, 0, arg->stat.stat);
933
934	return (NULL);
935}
936
937/* nlm_lock_res ------------------------------------------------------------ */
938/*
939 * Purpose:	Accept result from earlier nlm_lock_msg() call
940 * Returns:	Nothing
941 */
942void *
943nlm_lock_res_1_svc(arg, rqstp)
944	nlm_res *arg;
945	struct svc_req *rqstp;
946{
947	if (config.verbose)
948		log_from_addr("nlm_lock_res", rqstp);
949
950	lock_answer(NLM_VERS, &arg->cookie, NULL, 0, arg->stat.stat);
951
952	return (NULL);
953}
954
955/* nlm_cancel_res ---------------------------------------------------------- */
956/*
957 * Purpose:	Accept result from earlier nlm_cancel_msg() call
958 * Returns:	Nothing
959 */
960void *
961nlm_cancel_res_1_svc(arg, rqstp)
962	nlm_res *arg;
963	struct svc_req *rqstp;
964{
965	if (config.verbose)
966		log_from_addr("nlm_cancel_res", rqstp);
967
968	lock_answer(NLM_VERS, &arg->cookie, NULL, 0, arg->stat.stat);
969
970	return (NULL);
971}
972
973/* nlm_unlock_res ---------------------------------------------------------- */
974/*
975 * Purpose:	Accept result from earlier nlm_unlock_msg() call
976 * Returns:	Nothing
977 */
978void *
979nlm_unlock_res_1_svc(arg, rqstp)
980	nlm_res *arg;
981	struct svc_req *rqstp;
982{
983	if (config.verbose)
984		log_from_addr("nlm_unlock_res", rqstp);
985
986	lock_answer(NLM_VERS, &arg->cookie, NULL, 0, arg->stat.stat);
987
988	return (NULL);
989}
990
991/* nlm_granted_res --------------------------------------------------------- */
992/*
993 * Purpose:	Accept result from earlier nlm_granted_msg() call
994 * Returns:	Nothing
995 */
996void *
997nlm_granted_res_1_svc(arg, rqstp)
998	nlm_res *arg;
999	struct svc_req *rqstp;
1000{
1001	if (config.verbose)
1002		log_from_addr("nlm_granted_res", rqstp);
1003	/* need to undo lock if granted msg wasn't accepted! */
1004	if (arg->stat.stat != nlm_granted) {
1005		nlm4_res arg4;
1006		arg4.cookie = arg->cookie;
1007		arg4.stat.stat = (nlm4_stats) arg->stat.stat;
1008		granted_failed(&arg4);
1009	}
1010	return (NULL);
1011}
1012
1013/* ------------------------------------------------------------------------- */
1014/*
1015 * Calls for PCNFS locking (aka non-monitored locking, no involvement
1016 * of rpc.statd).
1017 *
1018 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
1019 */
1020
1021/* nlm_share --------------------------------------------------------------- */
1022/*
1023 * Purpose:	Establish a DOS-style lock
1024 * Returns:	success or failure
1025 * Notes:	Blocking locks are not supported - client is expected
1026 *		to retry if required.
1027 */
1028nlm_shareres *
1029nlm_share_3_svc(arg, rqstp)
1030	nlm_shareargs *arg;
1031	struct svc_req *rqstp;
1032{
1033	static nlm_shareres res;
1034
1035	if (config.verbose)
1036		log_from_addr("nlm_share", rqstp);
1037
1038	/* copy cookie from arg to result.  See comment in nlm_test_1() */
1039	res.cookie = arg->cookie;
1040	res.sequence = 0;	/* X/Open says this field is ignored? */
1041
1042	res.stat = (nlm_stats) getshare(arg, rqstp, 0);
1043	return (&res);
1044}
1045
1046/* nlm_unshare ------------------------------------------------------------ */
1047/*
1048 * Purpose:	Release a DOS-style lock
1049 * Returns:	nlm_granted, unless in grace period
1050 * Notes:
1051 */
1052nlm_shareres *
1053nlm_unshare_3_svc(arg, rqstp)
1054	nlm_shareargs *arg;
1055	struct svc_req *rqstp;
1056{
1057	static nlm_shareres res;
1058
1059	if (config.verbose)
1060		log_from_addr("nlm_unshare", rqstp);
1061
1062	res.cookie = arg->cookie;
1063	res.sequence = 0;	/* X/Open says this field is ignored? */
1064
1065	res.stat = (nlm_stats) unshare(arg, rqstp, 0);
1066	return (&res);
1067}
1068
1069/* nlm_nm_lock ------------------------------------------------------------ */
1070/*
1071 * Purpose:	non-monitored version of nlm_lock()
1072 * Returns:	as for nlm_lock()
1073 * Notes:	These locks are in the same style as the standard nlm_lock,
1074 *		but the rpc.statd should not be called to establish a
1075 *		monitor for the client machine, since that machine is
1076 *		declared not to be running a rpc.statd, and so would not
1077 *		respond to the statd protocol.
1078 */
1079nlm_res *
1080nlm_nm_lock_3_svc(arg, rqstp)
1081	nlm_lockargs *arg;
1082	struct svc_req *rqstp;
1083{
1084	static nlm_res res;
1085	struct nlm4_lockargs arg4;
1086	nlmtonlm4(&arg->alock, &arg4.alock);
1087	arg4.cookie = arg->cookie;
1088	arg4.block = arg->block;
1089	arg4.exclusive = arg->exclusive;
1090	arg4.reclaim = arg->reclaim;
1091	arg4.state = arg->state;
1092
1093	if (config.verbose)
1094		log_from_addr("nlm_nm_lock", rqstp);
1095
1096	/* copy cookie from arg to result.  See comment in nlm_test_1() */
1097	res.cookie = arg->cookie;
1098
1099	res.stat.stat = (nlm_stats) getlock(&arg4, rqstp, 0);
1100	return (&res);
1101}
1102
1103/* nlm_free_all ------------------------------------------------------------ */
1104/*
1105 * Purpose:	Release all locks held by a named client
1106 * Returns:	Nothing
1107 * Notes:	Potential denial of service security problem here - the
1108 *		locks to be released are specified by a host name, independent
1109 *		of the address from which the request has arrived.
1110 *		Should probably be rejected if the named host has been
1111 *		using monitored locks.
1112 */
1113void *
1114nlm_free_all_3_svc(arg, rqstp)
1115	nlm_notify *arg;
1116	struct svc_req *rqstp;
1117{
1118	static char dummy;
1119
1120	if (config.verbose)
1121		log_from_addr("nlm_free_all", rqstp);
1122
1123	/* free all non-monitored locks/shares for specified host */
1124	do_free_all(arg->name);
1125
1126	return (&dummy);
1127}
1128
1129/* calls for nlm version 4 (NFSv3) */
1130/* nlm_test ---------------------------------------------------------------- */
1131/*
1132 * Purpose:	Test whether a specified lock would be granted if requested
1133 * Returns:	nlm_granted (or error code)
1134 * Notes:
1135 */
1136nlm4_testres *
1137nlm4_test_4_svc(arg, rqstp)
1138	nlm4_testargs *arg;
1139	struct svc_req *rqstp;
1140{
1141	static nlm4_testres res;
1142	struct nlm4_holder *holder;
1143
1144	if (config.verbose)
1145		log_from_addr("nlm4_test", rqstp);
1146	if (config.verbose > 5) {
1147		syslog(LOG_DEBUG, "Locking arguments:\n");
1148		log_netobj(&(arg->cookie));
1149		syslog(LOG_DEBUG, "Alock arguments:\n");
1150		syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name);
1151		syslog(LOG_DEBUG, "File Handle:\n");
1152		log_netobj(&(arg->alock.fh));
1153		syslog(LOG_DEBUG, "Owner Handle:\n");
1154		log_netobj(&(arg->alock.oh));
1155		syslog(LOG_DEBUG, "SVID:        %d\n", arg->alock.svid);
1156		syslog(LOG_DEBUG, "Lock Offset: %llu\n",
1157		    (unsigned long long)arg->alock.l_offset);
1158		syslog(LOG_DEBUG, "Lock Length: %llu\n",
1159		    (unsigned long long)arg->alock.l_len);
1160		syslog(LOG_DEBUG, "Exclusive:   %s\n",
1161		    (arg->exclusive ? "true" : "false"));
1162	}
1163
1164	holder = testlock(&arg->alock, arg->exclusive, LOCK_V4);
1165
1166	/*
1167	 * Copy the cookie from the argument into the result.  Note that this
1168	 * is slightly hazardous, as the structure contains a pointer to a
1169	 * malloc()ed buffer that will get freed by the caller.  However, the
1170	 * main function transmits the result before freeing the argument
1171	 * so it is in fact safe.
1172	 */
1173	res.cookie = arg->cookie;
1174	if (holder == NULL) {
1175		res.stat.stat = nlm4_granted;
1176	} else {
1177		res.stat.stat = nlm4_denied;
1178		memcpy(&res.stat.nlm4_testrply_u.holder, holder,
1179		    sizeof(struct nlm4_holder));
1180	}
1181	return (&res);
1182}
1183
1184void *
1185nlm4_test_msg_4_svc(arg, rqstp)
1186	nlm4_testargs *arg;
1187	struct svc_req *rqstp;
1188{
1189	nlm4_testres res;
1190	static char dummy;
1191	CLIENT *cli;
1192	int success;
1193	struct timeval timeo;
1194	struct nlm4_holder *holder;
1195
1196	if (config.verbose)
1197		log_from_addr("nlm4_test_msg", rqstp);
1198
1199	holder = testlock(&arg->alock, arg->exclusive, LOCK_V4);
1200
1201	res.cookie = arg->cookie;
1202	if (holder == NULL) {
1203		res.stat.stat = nlm4_granted;
1204	} else {
1205		res.stat.stat = nlm4_denied;
1206		memcpy(&res.stat.nlm4_testrply_u.holder, holder,
1207		    sizeof(struct nlm4_holder));
1208	}
1209
1210	/*
1211	 * nlm_test has different result type to the other operations, so
1212	 * can't use transmit4_result() in this case
1213	 */
1214	if ((cli = get_client(svc_getcaller_sa(rqstp->rq_xprt), NLM_VERS4, 0, 0)) != NULL) {
1215		timeo.tv_sec = 0; /* No timeout - not expecting response */
1216		timeo.tv_usec = 0;
1217
1218		success = clnt_call(cli, NLM4_TEST_RES, (xdrproc_t)xdr_nlm4_testres,
1219		    &res, (xdrproc_t)xdr_void, &dummy, timeo);
1220
1221		if (config.verbose > 2)
1222			syslog(LOG_DEBUG, "clnt_call returns %d", success);
1223	}
1224	return (NULL);
1225}
1226
1227/* nlm_lock ---------------------------------------------------------------- */
1228/*
1229 * Purposes:	Establish a lock
1230 * Returns:	granted, denied or blocked
1231 * Notes:	*** grace period support missing
1232 */
1233nlm4_res *
1234nlm4_lock_4_svc(arg, rqstp)
1235	nlm4_lockargs *arg;
1236	struct svc_req *rqstp;
1237{
1238	static nlm4_res res;
1239
1240	if (config.verbose)
1241		log_from_addr("nlm4_lock", rqstp);
1242	if (config.verbose > 5) {
1243		syslog(LOG_DEBUG, "Locking arguments:\n");
1244		log_netobj(&(arg->cookie));
1245		syslog(LOG_DEBUG, "Alock arguments:\n");
1246		syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name);
1247		syslog(LOG_DEBUG, "File Handle:\n");
1248		log_netobj(&(arg->alock.fh));
1249		syslog(LOG_DEBUG, "Owner Handle:\n");
1250		log_netobj(&(arg->alock.oh));
1251		syslog(LOG_DEBUG, "SVID:        %d\n", arg->alock.svid);
1252		syslog(LOG_DEBUG, "Lock Offset: %llu\n",
1253		    (unsigned long long)arg->alock.l_offset);
1254		syslog(LOG_DEBUG, "Lock Length: %llu\n",
1255		    (unsigned long long)arg->alock.l_len);
1256		syslog(LOG_DEBUG, "Block:       %s\n", (arg->block ? "true" : "false"));
1257		syslog(LOG_DEBUG, "Exclusive:   %s\n", (arg->exclusive ? "true" : "false"));
1258		syslog(LOG_DEBUG, "Reclaim:     %s\n", (arg->reclaim ? "true" : "false"));
1259		syslog(LOG_DEBUG, "State num:   %d\n", arg->state);
1260	}
1261
1262	/* copy cookie from arg to result.  See comment in nlm_test_4() */
1263	res.cookie = arg->cookie;
1264
1265	res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_V4);
1266	return (&res);
1267}
1268
1269void *
1270nlm4_lock_msg_4_svc(arg, rqstp)
1271	nlm4_lockargs *arg;
1272	struct svc_req *rqstp;
1273{
1274	static nlm4_res res;
1275
1276	if (config.verbose)
1277		log_from_addr("nlm4_lock_msg", rqstp);
1278
1279	res.cookie = arg->cookie;
1280	res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_ASYNC | LOCK_V4);
1281	if (transmit4_result(NLM4_LOCK_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 0) < 0) {
1282		/* if res.stat.stat was success/blocked, then unlock/cancel */
1283		if (res.stat.stat == nlm4_granted)
1284			unlock(&arg->alock, LOCK_V4);
1285		else if (res.stat.stat == nlm4_blocked) {
1286			nlm4_cancargs carg;
1287			carg.cookie = arg->cookie;
1288			carg.block = arg->block;
1289			carg.exclusive = arg->exclusive;
1290			carg.alock = arg->alock;
1291			cancellock(&carg, LOCK_V4);
1292		}
1293	}
1294
1295	return (NULL);
1296}
1297
1298/* nlm_cancel -------------------------------------------------------------- */
1299/*
1300 * Purpose:	Cancel a blocked lock request
1301 * Returns:	granted or denied
1302 * Notes:
1303 */
1304nlm4_res *
1305nlm4_cancel_4_svc(arg, rqstp)
1306	nlm4_cancargs *arg;
1307	struct svc_req *rqstp;
1308{
1309	static nlm4_res res;
1310
1311	if (config.verbose)
1312		log_from_addr("nlm4_cancel", rqstp);
1313
1314	/* copy cookie from arg to result.  See comment in nlm_test_1() */
1315	res.cookie = arg->cookie;
1316
1317	res.stat.stat = cancellock(arg, LOCK_V4);
1318	return (&res);
1319}
1320
1321void *
1322nlm4_cancel_msg_4_svc(arg, rqstp)
1323	nlm4_cancargs *arg;
1324	struct svc_req *rqstp;
1325{
1326	static nlm4_res res;
1327
1328	if (config.verbose)
1329		log_from_addr("nlm4_cancel_msg", rqstp);
1330
1331	res.cookie = arg->cookie;
1332	res.stat.stat = cancellock(arg, LOCK_V4);
1333	if (transmit4_result(NLM4_CANCEL_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 0) < 0) {
1334		/* XXX do we need to (un)do anything if this fails? */
1335	}
1336	return (NULL);
1337}
1338
1339/* nlm_unlock -------------------------------------------------------------- */
1340/*
1341 * Purpose:	Release an existing lock
1342 * Returns:	Always granted, unless during grace period
1343 * Notes:	"no such lock" error condition is ignored, as the
1344 *		protocol uses unreliable UDP datagrams, and may well
1345 *		re-try an unlock that has already succeeded.
1346 */
1347nlm4_res *
1348nlm4_unlock_4_svc(arg, rqstp)
1349	nlm4_unlockargs *arg;
1350	struct svc_req *rqstp;
1351{
1352	static nlm4_res res;
1353
1354	if (config.verbose)
1355		log_from_addr("nlm4_unlock", rqstp);
1356
1357	res.stat.stat = unlock(&arg->alock, LOCK_V4);
1358	res.cookie = arg->cookie;
1359
1360	return (&res);
1361}
1362
1363void *
1364nlm4_unlock_msg_4_svc(arg, rqstp)
1365	nlm4_unlockargs *arg;
1366	struct svc_req *rqstp;
1367{
1368	static nlm4_res res;
1369
1370	if (config.verbose)
1371		log_from_addr("nlm4_unlock_msg", rqstp);
1372
1373	res.stat.stat = unlock(&arg->alock, LOCK_V4);
1374	res.cookie = arg->cookie;
1375
1376	if (transmit4_result(NLM4_UNLOCK_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 0) < 0) {
1377		/* XXX do we need to (un)do anything if this fails? */
1378	}
1379	return (NULL);
1380}
1381
1382/* ------------------------------------------------------------------------- */
1383/*
1384 * Client-side pseudo-RPCs for results.  Note that for the client there
1385 * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
1386 * version returns the results in the RPC result, and so the client
1387 * does not normally receive incoming RPCs.
1388 *
1389 * The exception to this is nlm_granted(), which is genuinely an RPC
1390 * call from the server to the client - a 'call-back' in normal procedure
1391 * call terms.
1392 */
1393
1394/* nlm_granted ------------------------------------------------------------- */
1395/*
1396 * Purpose:	Receive notification that formerly blocked lock now granted
1397 * Returns:	always success ('granted')
1398 * Notes:
1399 */
1400nlm4_res *
1401nlm4_granted_4_svc(arg, rqstp)
1402	nlm4_testargs *arg;
1403	struct svc_req *rqstp;
1404{
1405	static nlm4_res res;
1406	int flags;
1407
1408	if (config.verbose)
1409		log_from_addr("nlm4_granted", rqstp);
1410
1411	flags = LOCK_ANSWER_GRANTED;
1412	if (arg->exclusive)
1413		flags |= LOCK_ANSWER_LOCK_EXCL;
1414
1415	if (lock_answer(NLM_VERS4, &arg->cookie, &arg->alock, flags, nlm4_granted))
1416		res.stat.stat = nlm4_denied;
1417	else
1418		res.stat.stat = nlm4_granted;
1419
1420	/* copy cookie from arg to result.  See comment in nlm_test_1() */
1421	res.cookie = arg->cookie;
1422
1423	return (&res);
1424}
1425
1426void *
1427nlm4_granted_msg_4_svc(arg, rqstp)
1428	nlm4_testargs *arg;
1429	struct svc_req *rqstp;
1430{
1431	static nlm4_res res;
1432	int flags;
1433
1434	if (config.verbose)
1435		log_from_addr("nlm4_granted_msg", rqstp);
1436
1437	flags = LOCK_ANSWER_GRANTED;
1438	if (arg->exclusive)
1439		flags |= LOCK_ANSWER_LOCK_EXCL;
1440
1441	if (lock_answer(NLM_VERS4, &arg->cookie, &arg->alock, flags, nlm4_granted))
1442		res.stat.stat = nlm4_denied;
1443	else
1444		res.stat.stat = nlm4_granted;
1445
1446	res.cookie = arg->cookie;
1447
1448	if (transmit4_result(NLM4_GRANTED_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 1) < 0) {
1449		/* XXX do we need to (un)do anything if this fails? */
1450	}
1451	return (NULL);
1452}
1453
1454/* nlm_test_res ------------------------------------------------------------ */
1455/*
1456 * Purpose:	Accept result from earlier nlm_test_msg() call
1457 * Returns:	Nothing
1458 */
1459void *
1460nlm4_test_res_4_svc(arg, rqstp)
1461	nlm4_testres *arg;
1462	struct svc_req *rqstp;
1463{
1464	nlm4_lock lock4;
1465	int flags = 0;
1466
1467	if (config.verbose)
1468		log_from_addr("nlm4_test_res", rqstp);
1469
1470	if (arg->stat.stat == nlm4_denied) {
1471		lock4.fh.n_len = 0;
1472		lock4.svid = arg->stat.nlm4_testrply_u.holder.svid;
1473		lock4.l_offset = arg->stat.nlm4_testrply_u.holder.l_offset;
1474		lock4.l_len = arg->stat.nlm4_testrply_u.holder.l_len;
1475		if (arg->stat.nlm4_testrply_u.holder.exclusive)
1476			flags |= LOCK_ANSWER_LOCK_EXCL;
1477		lock_answer(NLM_VERS4, &arg->cookie, &lock4, flags, arg->stat.stat);
1478	} else
1479		lock_answer(NLM_VERS4, &arg->cookie, NULL, 0, arg->stat.stat);
1480
1481	return (NULL);
1482}
1483
1484/* nlm_lock_res ------------------------------------------------------------ */
1485/*
1486 * Purpose:	Accept result from earlier nlm_lock_msg() call
1487 * Returns:	Nothing
1488 */
1489void *
1490nlm4_lock_res_4_svc(arg, rqstp)
1491	nlm4_res *arg;
1492	struct svc_req *rqstp;
1493{
1494	if (config.verbose)
1495		log_from_addr("nlm4_lock_res", rqstp);
1496
1497	lock_answer(NLM_VERS4, &arg->cookie, NULL, 0, arg->stat.stat);
1498
1499	return (NULL);
1500}
1501
1502/* nlm_cancel_res ---------------------------------------------------------- */
1503/*
1504 * Purpose:	Accept result from earlier nlm_cancel_msg() call
1505 * Returns:	Nothing
1506 */
1507void *
1508nlm4_cancel_res_4_svc(arg, rqstp)
1509	nlm4_res *arg;
1510	struct svc_req *rqstp;
1511{
1512	if (config.verbose)
1513		log_from_addr("nlm4_cancel_res", rqstp);
1514
1515	lock_answer(NLM_VERS4, &arg->cookie, NULL, 0, arg->stat.stat);
1516
1517	return (NULL);
1518}
1519
1520/* nlm_unlock_res ---------------------------------------------------------- */
1521/*
1522 * Purpose:	Accept result from earlier nlm_unlock_msg() call
1523 * Returns:	Nothing
1524 */
1525void *
1526nlm4_unlock_res_4_svc(arg, rqstp)
1527	nlm4_res *arg __unused;
1528	struct svc_req *rqstp;
1529{
1530	if (config.verbose)
1531		log_from_addr("nlm4_unlock_res", rqstp);
1532
1533	lock_answer(NLM_VERS4, &arg->cookie, NULL, 0, arg->stat.stat);
1534
1535	return (NULL);
1536}
1537
1538/* nlm_granted_res --------------------------------------------------------- */
1539/*
1540 * Purpose:	Accept result from earlier nlm_granted_msg() call
1541 * Returns:	Nothing
1542 */
1543void *
1544nlm4_granted_res_4_svc(arg, rqstp)
1545	nlm4_res *arg __unused;
1546	struct svc_req *rqstp;
1547{
1548	if (config.verbose)
1549		log_from_addr("nlm4_granted_res", rqstp);
1550	/* need to undo lock if granted msg wasn't accepted! */
1551	if (arg->stat.stat != nlm4_granted)
1552		granted_failed(arg);
1553	return (NULL);
1554}
1555
1556/* ------------------------------------------------------------------------- */
1557/*
1558 * Calls for PCNFS locking (aka non-monitored locking, no involvement
1559 * of rpc.statd).
1560 *
1561 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
1562 */
1563
1564/* nlm_share --------------------------------------------------------------- */
1565/*
1566 * Purpose:	Establish a DOS-style lock
1567 * Returns:	success or failure
1568 * Notes:	Blocking locks are not supported - client is expected
1569 *		to retry if required.
1570 */
1571nlm4_shareres *
1572nlm4_share_4_svc(arg, rqstp)
1573	nlm4_shareargs *arg;
1574	struct svc_req *rqstp;
1575{
1576	static nlm4_shareres res;
1577
1578	if (config.verbose)
1579		log_from_addr("nlm4_share", rqstp);
1580
1581	res.cookie = arg->cookie;
1582	res.sequence = 0;	/* X/Open says this field is ignored? */
1583
1584	res.stat = getshare((nlm_shareargs*)arg, rqstp, LOCK_V4);
1585	return (&res);
1586}
1587
1588/* nlm4_unshare ------------------------------------------------------------ */
1589/*
1590 * Purpose:	Release a DOS-style lock
1591 * Returns:	nlm_granted, unless in grace period
1592 * Notes:
1593 */
1594nlm4_shareres *
1595nlm4_unshare_4_svc(arg, rqstp)
1596	nlm4_shareargs *arg;
1597	struct svc_req *rqstp;
1598{
1599	static nlm4_shareres res;
1600
1601	if (config.verbose)
1602		log_from_addr("nlm4_unshare", rqstp);
1603
1604	res.cookie = arg->cookie;
1605	res.sequence = 0;	/* X/Open says this field is ignored? */
1606
1607	res.stat = unshare((nlm_shareargs*)arg, rqstp, LOCK_V4);
1608	return (&res);
1609}
1610
1611/* nlm4_nm_lock ------------------------------------------------------------ */
1612/*
1613 * Purpose:	non-monitored version of nlm4_lock()
1614 * Returns:	as for nlm4_lock()
1615 * Notes:	These locks are in the same style as the standard nlm4_lock,
1616 *		but the rpc.statd should not be called to establish a
1617 *		monitor for the client machine, since that machine is
1618 *		declared not to be running a rpc.statd, and so would not
1619 *		respond to the statd protocol.
1620 */
1621nlm4_res *
1622nlm4_nm_lock_4_svc(arg, rqstp)
1623	nlm4_lockargs *arg;
1624	struct svc_req *rqstp;
1625{
1626	static nlm4_res res;
1627
1628	if (config.verbose)
1629		log_from_addr("nlm4_nm_lock", rqstp);
1630
1631	/* copy cookie from arg to result.  See comment in nlm_test_4() */
1632	res.cookie = arg->cookie;
1633
1634	res.stat.stat = getlock(arg, rqstp, LOCK_V4);
1635	return (&res);
1636}
1637
1638/* nlm4_free_all ------------------------------------------------------------ */
1639/*
1640 * Purpose:	Release all locks held by a named client
1641 * Returns:	Nothing
1642 * Notes:	Potential denial of service security problem here - the
1643 *		locks to be released are specified by a host name, independent
1644 *		of the address from which the request has arrived.
1645 *		Should probably be rejected if the named host has been
1646 *		using monitored locks.
1647 */
1648void *
1649nlm4_free_all_4_svc(arg, rqstp)
1650	struct nlm4_notify *arg;
1651	struct svc_req *rqstp;
1652{
1653	static char dummy;
1654
1655	if (config.verbose)
1656		log_from_addr("nlm4_free_all", rqstp);
1657
1658	/* free all non-monitored locks/shares for specified host */
1659	do_free_all(arg->name);
1660
1661	return (&dummy);
1662}
1663
1664/* nlm_sm_notify --------------------------------------------------------- */
1665/*
1666 * Purpose:	called by rpc.statd when a monitored host state changes.
1667 * Returns:	Nothing
1668 */
1669void *
1670nlm_sm_notify_0_svc(arg, rqstp)
1671	struct nlm_sm_status *arg;
1672	struct svc_req *rqstp __unused;
1673{
1674	static char dummy;
1675	notify(arg->mon_name, arg->state);
1676	return (&dummy);
1677}
1678