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