Home | History | Annotate | Line # | Download | only in rpc.lockd
lock_proc.c revision 1.7.8.1
      1  1.7.8.1   bouyer /*	$NetBSD: lock_proc.c,v 1.7.8.1 2007/11/19 21:11:52 bouyer 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.8.1   bouyer __RCSID("$NetBSD: lock_proc.c,v 1.7.8.1 2007/11/19 21:11:52 bouyer 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.8.1   bouyer 	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