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