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