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