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