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