xref: /openbsd/usr.sbin/rpc.lockd/procs.c (revision 5b133f3f)
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  */
63 static void
log_from_addr(char * fun_name,struct svc_req * req)64 log_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  */
110 static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE];
111 static long clnt_cache_time[CLIENT_CACHE_SIZE];	/* time entry created */
112 static struct in_addr clnt_cache_addr[CLIENT_CACHE_SIZE];
113 static int clnt_cache_next_to_use = 0;
114 
115 CLIENT *
get_client(struct sockaddr_in * host_addr,u_long vers)116 get_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  */
198 void
transmit_result(int opcode,nlm_res * result,struct sockaddr_in * addr)199 transmit_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  */
226 void
transmit4_result(int opcode,nlm4_res * result,struct sockaddr_in * addr)227 transmit4_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  */
250 static void
nlmtonlm4(struct nlm_lock * arg,struct nlm4_lock * arg4)251 nlmtonlm4(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  */
291 nlm_testres *
nlm_test_1_svc(nlm_testargs * arg,struct svc_req * rqstp)292 nlm_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 
325 void *
nlm_test_msg_1_svc(nlm_testargs * arg,struct svc_req * rqstp)326 nlm_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  */
381 nlm_res *
nlm_lock_1_svc(nlm_lockargs * arg,struct svc_req * rqstp)382 nlm_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 
403 void *
nlm_lock_msg_1_svc(nlm_lockargs * arg,struct svc_req * rqstp)404 nlm_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  */
432 nlm_res *
nlm_cancel_1_svc(nlm_cancargs * arg,struct svc_req * rqstp)433 nlm_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 
454 void *
nlm_cancel_msg_1_svc(nlm_cancargs * arg,struct svc_req * rqstp)455 nlm_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  */
483 nlm_res *
nlm_unlock_1_svc(nlm_unlockargs * arg,struct svc_req * rqstp)484 nlm_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 
500 void *
nlm_unlock_msg_1_svc(nlm_unlockargs * arg,struct svc_req * rqstp)501 nlm_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  */
536 nlm_res *
nlm_granted_1_svc(nlm_testargs * arg,struct svc_req * rqstp)537 nlm_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 
551 void *
nlm_granted_msg_1_svc(nlm_testargs * arg,struct svc_req * rqstp)552 nlm_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  */
570 void *
nlm_test_res_1_svc(nlm_testres * arg,struct svc_req * rqstp)571 nlm_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  */
583 void *
nlm_lock_res_1_svc(nlm_res * arg,struct svc_req * rqstp)584 nlm_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  */
597 void *
nlm_cancel_res_1_svc(nlm_res * arg,struct svc_req * rqstp)598 nlm_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  */
610 void *
nlm_unlock_res_1_svc(nlm_res * arg,struct svc_req * rqstp)611 nlm_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  */
623 void *
nlm_granted_res_1_svc(nlm_res * arg,struct svc_req * rqstp)624 nlm_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  */
646 nlm_shareres *
nlm_share_3_svc(nlm_shareargs * arg,struct svc_req * rqstp)647 nlm_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  */
666 nlm_shareres *
nlm_unshare_3_svc(nlm_shareargs * arg,struct svc_req * rqstp)667 nlm_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  */
690 nlm_res *
nlm_nm_lock_3_svc(nlm_lockargs * arg,struct svc_req * rqstp)691 nlm_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  */
714 void *
nlm_free_all_3_svc(nlm_notify * arg,struct svc_req * rqstp)715 nlm_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  */
731 nlm4_testres *
nlm4_test_4_svc(nlm4_testargs * arg,struct svc_req * rqstp)732 nlm4_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 
760 void *
nlm4_test_msg_4_svc(nlm4_testargs * arg,struct svc_req * rqstp)761 nlm4_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  */
809 nlm4_res *
nlm4_lock_4_svc(nlm4_lockargs * arg,struct svc_req * rqstp)810 nlm4_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 
824 void *
nlm4_lock_msg_4_svc(nlm4_lockargs * arg,struct svc_req * rqstp)825 nlm4_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  */
845 nlm4_res *
nlm4_cancel_4_svc(nlm4_cancargs * arg,struct svc_req * rqstp)846 nlm4_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 
864 void *
nlm4_cancel_msg_4_svc(nlm4_cancargs * arg,struct svc_req * rqstp)865 nlm4_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  */
891 nlm4_res *
nlm4_unlock_4_svc(nlm4_unlockargs * arg,struct svc_req * rqstp)892 nlm4_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 
905 void *
nlm4_unlock_msg_4_svc(nlm4_unlockargs * arg,struct svc_req * rqstp)906 nlm4_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  */
938 nlm4_res *
nlm4_granted_4_svc(nlm4_testargs * arg,struct svc_req * rqstp)939 nlm4_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 
953 void *
nlm4_granted_msg_4_svc(nlm4_testargs * arg,struct svc_req * rqstp)954 nlm4_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  */
972 void *
nlm4_test_res_4_svc(nlm4_testres * arg,struct svc_req * rqstp)973 nlm4_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  */
985 void *
nlm4_lock_res_4_svc(nlm4_res * arg,struct svc_req * rqstp)986 nlm4_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  */
999 void *
nlm4_cancel_res_4_svc(nlm4_res * arg,struct svc_req * rqstp)1000 nlm4_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  */
1012 void *
nlm4_unlock_res_4_svc(nlm4_res * arg,struct svc_req * rqstp)1013 nlm4_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  */
1025 void *
nlm4_granted_res_4_svc(nlm4_res * arg,struct svc_req * rqstp)1026 nlm4_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  */
1048 nlm4_shareres *
nlm4_share_4_svc(nlm4_shareargs * arg,struct svc_req * rqstp)1049 nlm4_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  */
1068 nlm4_shareres *
nlm4_unshare_4_svc(nlm4_shareargs * arg,struct svc_req * rqstp)1069 nlm4_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  */
1092 nlm4_res *
nlm4_nm_lock_4_svc(nlm4_lockargs * arg,struct svc_req * rqstp)1093 nlm4_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  */
1116 void *
nlm4_free_all_4_svc(nlm_notify * arg,struct svc_req * rqstp)1117 nlm4_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  */
1131 void *
nlm_sm_notify_0_svc(struct nlm_sm_status * arg,struct svc_req * rqstp)1132 nlm_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