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