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