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