lock_proc.c revision 86300
174462Salfred/* $NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $ */ 274462Salfred/* $FreeBSD: head/usr.sbin/rpc.lockd/lock_proc.c 86300 2001-11-12 16:34:59Z alfred $ */ 374462Salfred/* 474462Salfred * Copyright (c) 1995 574462Salfred * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. 674462Salfred * 774462Salfred * Redistribution and use in source and binary forms, with or without 874462Salfred * modification, are permitted provided that the following conditions 974462Salfred * are met: 1074462Salfred * 1. Redistributions of source code must retain the above copyright 1174462Salfred * notice, this list of conditions and the following disclaimer. 1274462Salfred * 2. Redistributions in binary form must reproduce the above copyright 1374462Salfred * notice, this list of conditions and the following disclaimer in the 1474462Salfred * documentation and/or other materials provided with the distribution. 1574462Salfred * 3. All advertising materials mentioning features or use of this software 1674462Salfred * must display the following acknowledgement: 1774462Salfred * This product includes software developed for the FreeBSD project 1874462Salfred * 4. Neither the name of the author nor the names of any co-contributors 1974462Salfred * may be used to endorse or promote products derived from this software 2074462Salfred * without specific prior written permission. 2174462Salfred * 2274462Salfred * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND 2374462Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2474462Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2574462Salfred * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2674462Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2774462Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2874462Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2974462Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3074462Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3174462Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3274462Salfred * SUCH DAMAGE. 3374462Salfred * 3474462Salfred */ 3574462Salfred 3674462Salfred#include <sys/cdefs.h> 3774462Salfred#ifndef lint 3874462Salfred__RCSID("$NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $"); 3974462Salfred#endif 4074462Salfred 4174462Salfred#include <sys/param.h> 4274462Salfred#include <sys/socket.h> 4374462Salfred 4474462Salfred#include <netinet/in.h> 4574462Salfred#include <arpa/inet.h> 4674462Salfred 4774462Salfred#include <netdb.h> 4874462Salfred#include <stdio.h> 4974462Salfred#include <string.h> 5074462Salfred#include <syslog.h> 5174462Salfred#include <netconfig.h> 5274462Salfred 5374462Salfred#include <rpc/rpc.h> 5474462Salfred#include <rpcsvc/sm_inter.h> 5574462Salfred 5674462Salfred#include "lockd.h" 5774462Salfred#include <rpcsvc/nlm_prot.h> 5874462Salfred#include "lockd_lock.h" 5974462Salfred 6074462Salfred 6174462Salfred#define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */ 6274462Salfred#define CLIENT_CACHE_LIFETIME 120 /* In seconds */ 6374462Salfred 6474462Salfredstatic void log_from_addr __P((char *, struct svc_req *)); 6574462Salfredstatic int addrcmp __P((struct sockaddr *, struct sockaddr *)); 6674462Salfred 6774462Salfred/* log_from_addr ----------------------------------------------------------- */ 6874462Salfred/* 6974462Salfred * Purpose: Log name of function called and source address 7074462Salfred * Returns: Nothing 7174462Salfred * Notes: Extracts the source address from the transport handle 7274462Salfred * passed in as part of the called procedure specification 7374462Salfred */ 7474462Salfredstatic void 7574462Salfredlog_from_addr(fun_name, req) 7674462Salfred char *fun_name; 7774462Salfred struct svc_req *req; 7874462Salfred{ 7974462Salfred struct sockaddr *addr; 8074462Salfred char hostname_buf[NI_MAXHOST]; 8174462Salfred 8274462Salfred addr = svc_getrpccaller(req->rq_xprt)->buf; 8374462Salfred if (getnameinfo(addr , addr->sa_len, hostname_buf, sizeof hostname_buf, 8474462Salfred NULL, 0, 0) != 0) 8574462Salfred return; 8674462Salfred 8774462Salfred syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf); 8874462Salfred} 8974462Salfred 9084923Salfred/* log_netobj ----------------------------------------------------------- */ 9184923Salfred/* 9284923Salfred * Purpose: Log a netobj 9384923Salfred * Returns: Nothing 9484923Salfred * Notes: This function should only really be called as part of 9584923Salfred * a debug subsystem. 9684923Salfred*/ 9784923Salfredstatic void 9884923Salfredlog_netobj(obj) 9984923Salfred netobj *obj; 10084923Salfred{ 10184923Salfred char objvalbuffer[(sizeof(char)*2)*MAX_NETOBJ_SZ+2]; 10284923Salfred char objascbuffer[sizeof(char)*MAX_NETOBJ_SZ+1]; 10384923Salfred int i, maxlen; 10484923Salfred char *tmp1, *tmp2; 10584923Salfred 10684923Salfred /* Notify of potential security attacks */ 10784923Salfred if (obj->n_len > MAX_NETOBJ_SZ) { 10884923Salfred syslog(LOG_DEBUG, "SOMEONE IS TRYING TO DO SOMETHING NASTY!\n"); 10984923Salfred syslog(LOG_DEBUG, "netobj too large! Should be %d was %d\n", 11084923Salfred MAX_NETOBJ_SZ, obj->n_len); 11184923Salfred } 11284923Salfred /* Prevent the security hazard from the buffer overflow */ 11384923Salfred maxlen = (obj->n_len < MAX_NETOBJ_SZ ? obj->n_len : MAX_NETOBJ_SZ); 11484923Salfred for (i=0, tmp1 = objvalbuffer, tmp2 = objascbuffer; i < obj->n_len; 11584923Salfred i++, tmp1 +=2, tmp2 +=1) { 11684923Salfred sprintf(tmp1,"%02X",*(obj->n_bytes+i)); 11784923Salfred sprintf(tmp2,"%c",*(obj->n_bytes+i)); 11884923Salfred } 11984923Salfred *tmp1 = '\0'; 12084923Salfred *tmp2 = '\0'; 12184923Salfred syslog(LOG_DEBUG,"netobjvals: %s\n",objvalbuffer); 12284923Salfred syslog(LOG_DEBUG,"netobjascs: %s\n",objascbuffer); 12384923Salfred} 12474462Salfred/* get_client -------------------------------------------------------------- */ 12574462Salfred/* 12674462Salfred * Purpose: Get a CLIENT* for making RPC calls to lockd on given host 12774462Salfred * Returns: CLIENT* pointer, from clnt_udp_create, or NULL if error 12874462Salfred * Notes: Creating a CLIENT* is quite expensive, involving a 12974462Salfred * conversation with the remote portmapper to get the 13074462Salfred * port number. Since a given client is quite likely 13174462Salfred * to make several locking requests in succession, it is 13274462Salfred * desirable to cache the created CLIENT*. 13374462Salfred * 13474462Salfred * Since we are using UDP rather than TCP, there is no cost 13574462Salfred * to the remote system in keeping these cached indefinitely. 13674462Salfred * Unfortunately there is a snag: if the remote system 13774462Salfred * reboots, the cached portmapper results will be invalid, 13874462Salfred * and we will never detect this since all of the xxx_msg() 13974462Salfred * calls return no result - we just fire off a udp packet 14074462Salfred * and hope for the best. 14174462Salfred * 14274462Salfred * We solve this by discarding cached values after two 14374462Salfred * minutes, regardless of whether they have been used 14474462Salfred * in the meanwhile (since a bad one might have been used 14574462Salfred * plenty of times, as the host keeps retrying the request 14674462Salfred * and we keep sending the reply back to the wrong port). 14774462Salfred * 14874462Salfred * Given that the entries will always expire in the order 14974462Salfred * that they were created, there is no point in a LRU 15074462Salfred * algorithm for when the cache gets full - entries are 15174462Salfred * always re-used in sequence. 15274462Salfred */ 15374462Salfredstatic CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE]; 15474462Salfredstatic long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */ 15574462Salfredstatic struct sockaddr_storage clnt_cache_addr[CLIENT_CACHE_SIZE]; 15676093Salfredstatic rpcvers_t clnt_cache_vers[CLIENT_CACHE_SIZE]; 15774462Salfredstatic int clnt_cache_next_to_use = 0; 15874462Salfred 15974462Salfredstatic int 16074462Salfredaddrcmp(sa1, sa2) 16174462Salfred struct sockaddr *sa1; 16274462Salfred struct sockaddr *sa2; 16374462Salfred{ 16474462Salfred int len; 16574462Salfred void *p1, *p2; 16674462Salfred 16774462Salfred if (sa1->sa_family != sa2->sa_family) 16874462Salfred return -1; 16974462Salfred 17074462Salfred switch (sa1->sa_family) { 17174462Salfred case AF_INET: 17274462Salfred p1 = &((struct sockaddr_in *)sa1)->sin_addr; 17374462Salfred p2 = &((struct sockaddr_in *)sa2)->sin_addr; 17474462Salfred len = 4; 17574462Salfred break; 17674462Salfred case AF_INET6: 17774462Salfred p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr; 17874462Salfred p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr; 17974462Salfred len = 16; 18074462Salfred break; 18174462Salfred default: 18274462Salfred return -1; 18374462Salfred } 18474462Salfred 18574462Salfred return memcmp(p1, p2, len); 18674462Salfred} 18774462Salfred 18874462SalfredCLIENT * 18974462Salfredget_client(host_addr, vers) 19074462Salfred struct sockaddr *host_addr; 19174462Salfred rpcvers_t vers; 19274462Salfred{ 19374462Salfred CLIENT *client; 19474462Salfred struct timeval retry_time, time_now; 19574462Salfred int i; 19674462Salfred char *netid; 19774462Salfred struct netconfig *nconf; 19874462Salfred char host[NI_MAXHOST]; 19974462Salfred 20074462Salfred gettimeofday(&time_now, NULL); 20174462Salfred 20274462Salfred /* 20374462Salfred * Search for the given client in the cache, zapping any expired 20474462Salfred * entries that we happen to notice in passing. 20574462Salfred */ 20674462Salfred for (i = 0; i < CLIENT_CACHE_SIZE; i++) { 20774462Salfred client = clnt_cache_ptr[i]; 20874462Salfred if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME) 20974462Salfred < time_now.tv_sec)) { 21074462Salfred /* Cache entry has expired. */ 21174462Salfred if (debug_level > 3) 21274462Salfred syslog(LOG_DEBUG, "Expired CLIENT* in cache"); 21374462Salfred clnt_cache_time[i] = 0L; 21474462Salfred clnt_destroy(client); 21574462Salfred clnt_cache_ptr[i] = NULL; 21674462Salfred client = NULL; 21774462Salfred } 21874462Salfred if (client && !addrcmp((struct sockaddr *)&clnt_cache_addr[i], 21976093Salfred host_addr) && clnt_cache_vers[i] == vers) { 22074462Salfred /* Found it! */ 22174462Salfred if (debug_level > 3) 22274462Salfred syslog(LOG_DEBUG, "Found CLIENT* in cache"); 22374462Salfred return (client); 22474462Salfred } 22574462Salfred } 22674462Salfred 22776093Salfred if (debug_level > 3) 22876093Salfred syslog(LOG_DEBUG, "CLIENT* not found in cache, creating"); 22976093Salfred 23074462Salfred /* Not found in cache. Free the next entry if it is in use. */ 23174462Salfred if (clnt_cache_ptr[clnt_cache_next_to_use]) { 23274462Salfred clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]); 23374462Salfred clnt_cache_ptr[clnt_cache_next_to_use] = NULL; 23474462Salfred } 23574462Salfred 23674462Salfred /* 23774462Salfred * Need a host string for clnt_tp_create. Use NI_NUMERICHOST 23874462Salfred * to avoid DNS lookups. 23974462Salfred */ 24074462Salfred if (getnameinfo(host_addr, host_addr->sa_len, host, sizeof host, 24174462Salfred NULL, 0, NI_NUMERICHOST) != 0) { 24274462Salfred syslog(LOG_ERR, "unable to get name string for caller"); 24374462Salfred return NULL; 24474462Salfred } 24574462Salfred 24674462Salfred#if 1 24774462Salfred if (host_addr->sa_family == AF_INET6) 24874462Salfred netid = "udp6"; 24974462Salfred else 25074462Salfred netid = "udp"; 25174462Salfred#else 25274462Salfred if (host_addr->sa_family == AF_INET6) 25374462Salfred netid = "tcp6"; 25474462Salfred else 25574462Salfred netid = "tcp"; 25674462Salfred#endif 25774462Salfred nconf = getnetconfigent(netid); 25874462Salfred if (nconf == NULL) { 25974462Salfred syslog(LOG_ERR, "could not get netconfig info for '%s': " 26074462Salfred "no /etc/netconfig file?", netid); 26174462Salfred return NULL; 26274462Salfred } 26374462Salfred 26474462Salfred client = clnt_tp_create(host, NLM_PROG, vers, nconf); 26574462Salfred freenetconfigent(nconf); 26674462Salfred 26774462Salfred if (!client) { 26874462Salfred syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create")); 26974462Salfred syslog(LOG_ERR, "Unable to return result to %s", host); 27074462Salfred return NULL; 27174462Salfred } 27274462Salfred 27374462Salfred /* Success - update the cache entry */ 27474462Salfred clnt_cache_ptr[clnt_cache_next_to_use] = client; 27574462Salfred memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr, 27674462Salfred host_addr->sa_len); 27776093Salfred clnt_cache_vers[clnt_cache_next_to_use] = vers; 27874462Salfred clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec; 27974462Salfred if (++clnt_cache_next_to_use > CLIENT_CACHE_SIZE) 28074462Salfred clnt_cache_next_to_use = 0; 28174462Salfred 28274462Salfred /* 28374462Salfred * Disable the default timeout, so we can specify our own in calls 28474462Salfred * to clnt_call(). (Note that the timeout is a different concept 28574462Salfred * from the retry period set in clnt_udp_create() above.) 28674462Salfred */ 28774462Salfred retry_time.tv_sec = -1; 28874462Salfred retry_time.tv_usec = -1; 28974462Salfred clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time); 29074462Salfred 29174462Salfred if (debug_level > 3) 29274462Salfred syslog(LOG_DEBUG, "Created CLIENT* for %s", host); 29374462Salfred return client; 29474462Salfred} 29574462Salfred 29674462Salfred 29774462Salfred/* transmit_result --------------------------------------------------------- */ 29874462Salfred/* 29974462Salfred * Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs 30074462Salfred * Returns: Nothing - we have no idea if the datagram got there 30174462Salfred * Notes: clnt_call() will always fail (with timeout) as we are 30274462Salfred * calling it with timeout 0 as a hack to just issue a datagram 30374462Salfred * without expecting a result 30474462Salfred */ 30574462Salfredvoid 30674462Salfredtransmit_result(opcode, result, addr) 30774462Salfred int opcode; 30874462Salfred nlm_res *result; 30974462Salfred struct sockaddr *addr; 31074462Salfred{ 31174462Salfred static char dummy; 31274462Salfred CLIENT *cli; 31374462Salfred struct timeval timeo; 31474462Salfred int success; 31574462Salfred 31674462Salfred if ((cli = get_client(addr, NLM_VERS)) != NULL) { 31774462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 31874462Salfred timeo.tv_usec = 0; 31974462Salfred 32074462Salfred success = clnt_call(cli, opcode, xdr_nlm_res, result, xdr_void, 32174462Salfred &dummy, timeo); 32274462Salfred 32374462Salfred if (debug_level > 2) 32474462Salfred syslog(LOG_DEBUG, "clnt_call returns %d(%s)", 32574462Salfred success, clnt_sperrno(success)); 32674462Salfred } 32774462Salfred} 32874462Salfred/* transmit4_result --------------------------------------------------------- */ 32974462Salfred/* 33074462Salfred * Purpose: Transmit result for nlm4_xxx_msg pseudo-RPCs 33174462Salfred * Returns: Nothing - we have no idea if the datagram got there 33274462Salfred * Notes: clnt_call() will always fail (with timeout) as we are 33374462Salfred * calling it with timeout 0 as a hack to just issue a datagram 33474462Salfred * without expecting a result 33574462Salfred */ 33674462Salfredvoid 33774462Salfredtransmit4_result(opcode, result, addr) 33874462Salfred int opcode; 33974462Salfred nlm4_res *result; 34074462Salfred struct sockaddr *addr; 34174462Salfred{ 34274462Salfred static char dummy; 34374462Salfred CLIENT *cli; 34474462Salfred struct timeval timeo; 34574462Salfred int success; 34674462Salfred 34774462Salfred if ((cli = get_client(addr, NLM_VERS4)) != NULL) { 34874462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 34974462Salfred timeo.tv_usec = 0; 35074462Salfred 35174462Salfred success = clnt_call(cli, opcode, xdr_nlm4_res, result, xdr_void, 35274462Salfred &dummy, timeo); 35374462Salfred 35474462Salfred if (debug_level > 2) 35574462Salfred syslog(LOG_DEBUG, "clnt_call returns %d(%s)", 35674462Salfred success, clnt_sperrno(success)); 35774462Salfred } 35874462Salfred} 35974462Salfred 36074462Salfred/* 36174462Salfred * converts a struct nlm_lock to struct nlm4_lock 36274462Salfred */ 36374462Salfredstatic void nlmtonlm4 __P((struct nlm_lock *, struct nlm4_lock *)); 36474462Salfredstatic void 36574462Salfrednlmtonlm4(arg, arg4) 36674462Salfred struct nlm_lock *arg; 36774462Salfred struct nlm4_lock *arg4; 36874462Salfred{ 36974462Salfred memcpy(arg4, arg, sizeof(nlm_lock)); 37074462Salfred arg4->l_offset = arg->l_offset; 37174462Salfred arg4->l_len = arg->l_len; 37274462Salfred} 37374462Salfred/* ------------------------------------------------------------------------- */ 37474462Salfred/* 37574462Salfred * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd 37674462Salfred * involved to ensure reclaim of locks after a crash of the "stateless" 37774462Salfred * server. 37874462Salfred * 37974462Salfred * These all come in two flavours - nlm_xxx() and nlm_xxx_msg(). 38074462Salfred * The first are standard RPCs with argument and result. 38174462Salfred * The nlm_xxx_msg() calls implement exactly the same functions, but 38274462Salfred * use two pseudo-RPCs (one in each direction). These calls are NOT 38374462Salfred * standard use of the RPC protocol in that they do not return a result 38474462Salfred * at all (NB. this is quite different from returning a void result). 38574462Salfred * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged 38674462Salfred * datagrams, requiring higher-level code to perform retries. 38774462Salfred * 38874462Salfred * Despite the disadvantages of the nlm_xxx_msg() approach (some of which 38974462Salfred * are documented in the comments to get_client() above), this is the 39074462Salfred * interface used by all current commercial NFS implementations 39174462Salfred * [Solaris, SCO, AIX etc.]. This is presumed to be because these allow 39274462Salfred * implementations to continue using the standard RPC libraries, while 39374462Salfred * avoiding the block-until-result nature of the library interface. 39474462Salfred * 39574462Salfred * No client implementations have been identified so far that make use 39674462Salfred * of the true RPC version (early SunOS releases would be a likely candidate 39774462Salfred * for testing). 39874462Salfred */ 39974462Salfred 40074462Salfred/* nlm_test ---------------------------------------------------------------- */ 40174462Salfred/* 40274462Salfred * Purpose: Test whether a specified lock would be granted if requested 40374462Salfred * Returns: nlm_granted (or error code) 40474462Salfred * Notes: 40574462Salfred */ 40674462Salfrednlm_testres * 40774462Salfrednlm_test_1_svc(arg, rqstp) 40874462Salfred nlm_testargs *arg; 40974462Salfred struct svc_req *rqstp; 41074462Salfred{ 41174462Salfred static nlm_testres res; 41274462Salfred struct nlm4_lock arg4; 41374462Salfred struct nlm4_holder *holder; 41474462Salfred nlmtonlm4(&arg->alock, &arg4); 41574462Salfred 41674462Salfred if (debug_level) 41774462Salfred log_from_addr("nlm_test", rqstp); 41874462Salfred 41984923Salfred holder = testlock(&arg4, arg->exclusive, 0); 42074462Salfred /* 42174462Salfred * Copy the cookie from the argument into the result. Note that this 42274462Salfred * is slightly hazardous, as the structure contains a pointer to a 42374462Salfred * malloc()ed buffer that will get freed by the caller. However, the 42474462Salfred * main function transmits the result before freeing the argument 42574462Salfred * so it is in fact safe. 42674462Salfred */ 42774462Salfred res.cookie = arg->cookie; 42874462Salfred if (holder == NULL) { 42974462Salfred res.stat.stat = nlm_granted; 43074462Salfred } else { 43174462Salfred res.stat.stat = nlm_denied; 43274462Salfred memcpy(&res.stat.nlm_testrply_u.holder, holder, 43374462Salfred sizeof(struct nlm_holder)); 43474462Salfred res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset; 43574462Salfred res.stat.nlm_testrply_u.holder.l_len = holder->l_len; 43674462Salfred } 43774462Salfred return (&res); 43874462Salfred} 43974462Salfred 44074462Salfredvoid * 44174462Salfrednlm_test_msg_1_svc(arg, rqstp) 44274462Salfred nlm_testargs *arg; 44374462Salfred struct svc_req *rqstp; 44474462Salfred{ 44574462Salfred nlm_testres res; 44674462Salfred static char dummy; 44774462Salfred struct sockaddr *addr; 44874462Salfred CLIENT *cli; 44974462Salfred int success; 45074462Salfred struct timeval timeo; 45174462Salfred struct nlm4_lock arg4; 45274462Salfred struct nlm4_holder *holder; 45374462Salfred 45474462Salfred nlmtonlm4(&arg->alock, &arg4); 45574462Salfred 45674462Salfred if (debug_level) 45774462Salfred log_from_addr("nlm_test_msg", rqstp); 45874462Salfred 45984923Salfred holder = testlock(&arg4, arg->exclusive, 0); 46074462Salfred 46174462Salfred res.cookie = arg->cookie; 46274462Salfred if (holder == NULL) { 46374462Salfred res.stat.stat = nlm_granted; 46474462Salfred } else { 46574462Salfred res.stat.stat = nlm_denied; 46674462Salfred memcpy(&res.stat.nlm_testrply_u.holder, holder, 46774462Salfred sizeof(struct nlm_holder)); 46874462Salfred res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset; 46974462Salfred res.stat.nlm_testrply_u.holder.l_len = holder->l_len; 47074462Salfred } 47174462Salfred 47274462Salfred /* 47374462Salfred * nlm_test has different result type to the other operations, so 47474462Salfred * can't use transmit_result() in this case 47574462Salfred */ 47674462Salfred addr = svc_getrpccaller(rqstp->rq_xprt)->buf; 47774462Salfred if ((cli = get_client(addr, NLM_VERS)) != NULL) { 47874462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 47974462Salfred timeo.tv_usec = 0; 48074462Salfred 48174462Salfred success = clnt_call(cli, NLM_TEST_RES, xdr_nlm_testres, 48274462Salfred &res, xdr_void, &dummy, timeo); 48374462Salfred 48474462Salfred if (debug_level > 2) 48574462Salfred syslog(LOG_DEBUG, "clnt_call returns %d", success); 48674462Salfred } 48774462Salfred return (NULL); 48874462Salfred} 48974462Salfred 49074462Salfred/* nlm_lock ---------------------------------------------------------------- */ 49174462Salfred/* 49274462Salfred * Purposes: Establish a lock 49374462Salfred * Returns: granted, denied or blocked 49474462Salfred * Notes: *** grace period support missing 49574462Salfred */ 49674462Salfrednlm_res * 49774462Salfrednlm_lock_1_svc(arg, rqstp) 49874462Salfred nlm_lockargs *arg; 49974462Salfred struct svc_req *rqstp; 50074462Salfred{ 50174462Salfred static nlm_res res; 50274462Salfred struct nlm4_lockargs arg4; 50374462Salfred nlmtonlm4(&arg->alock, &arg4.alock); 50474462Salfred arg4.cookie = arg->cookie; 50574462Salfred arg4.block = arg->block; 50674462Salfred arg4.exclusive = arg->exclusive; 50774462Salfred arg4.reclaim = arg->reclaim; 50874462Salfred arg4.state = arg->state; 50974462Salfred 51074462Salfred if (debug_level) 51174462Salfred log_from_addr("nlm_lock", rqstp); 51274462Salfred 51374462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 51474462Salfred res.cookie = arg->cookie; 51574462Salfred 51674462Salfred res.stat.stat = getlock(&arg4, rqstp, LOCK_MON); 51774462Salfred return (&res); 51874462Salfred} 51974462Salfred 52074462Salfredvoid * 52174462Salfrednlm_lock_msg_1_svc(arg, rqstp) 52274462Salfred nlm_lockargs *arg; 52374462Salfred struct svc_req *rqstp; 52474462Salfred{ 52574462Salfred static nlm_res res; 52674462Salfred struct nlm4_lockargs arg4; 52774462Salfred 52874462Salfred nlmtonlm4(&arg->alock, &arg4.alock); 52974462Salfred arg4.cookie = arg->cookie; 53074462Salfred arg4.block = arg->block; 53174462Salfred arg4.exclusive = arg->exclusive; 53274462Salfred arg4.reclaim = arg->reclaim; 53374462Salfred arg4.state = arg->state; 53474462Salfred 53574462Salfred if (debug_level) 53674462Salfred log_from_addr("nlm_lock_msg", rqstp); 53774462Salfred 53874462Salfred res.cookie = arg->cookie; 53974462Salfred res.stat.stat = getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON); 54074462Salfred transmit_result(NLM_LOCK_RES, &res, 54174462Salfred (struct sockaddr *)svc_getcaller(rqstp->rq_xprt)); 54274462Salfred 54374462Salfred return (NULL); 54474462Salfred} 54574462Salfred 54674462Salfred/* nlm_cancel -------------------------------------------------------------- */ 54774462Salfred/* 54874462Salfred * Purpose: Cancel a blocked lock request 54974462Salfred * Returns: granted or denied 55074462Salfred * Notes: 55174462Salfred */ 55274462Salfrednlm_res * 55374462Salfrednlm_cancel_1_svc(arg, rqstp) 55474462Salfred nlm_cancargs *arg; 55574462Salfred struct svc_req *rqstp; 55674462Salfred{ 55774462Salfred static nlm_res res; 55874462Salfred struct nlm4_lock arg4; 55974462Salfred 56074462Salfred nlmtonlm4(&arg->alock, &arg4); 56174462Salfred 56274462Salfred if (debug_level) 56374462Salfred log_from_addr("nlm_cancel", rqstp); 56474462Salfred 56574462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 56674462Salfred res.cookie = arg->cookie; 56774462Salfred 56874462Salfred /* 56974462Salfred * Since at present we never return 'nlm_blocked', there can never be 57074462Salfred * a lock to cancel, so this call always fails. 57174462Salfred */ 57274462Salfred res.stat.stat = unlock(&arg4, LOCK_CANCEL); 57374462Salfred return (&res); 57474462Salfred} 57574462Salfred 57674462Salfredvoid * 57774462Salfrednlm_cancel_msg_1_svc(arg, rqstp) 57874462Salfred nlm_cancargs *arg; 57974462Salfred struct svc_req *rqstp; 58074462Salfred{ 58174462Salfred static nlm_res res; 58274462Salfred struct nlm4_lock arg4; 58374462Salfred 58474462Salfred nlmtonlm4(&arg->alock, &arg4); 58574462Salfred 58674462Salfred if (debug_level) 58774462Salfred log_from_addr("nlm_cancel_msg", rqstp); 58874462Salfred 58974462Salfred res.cookie = arg->cookie; 59074462Salfred /* 59174462Salfred * Since at present we never return 'nlm_blocked', there can never be 59274462Salfred * a lock to cancel, so this call always fails. 59374462Salfred */ 59474462Salfred res.stat.stat = unlock(&arg4, LOCK_CANCEL); 59574462Salfred transmit_result(NLM_CANCEL_RES, &res, 59674462Salfred (struct sockaddr *)svc_getcaller(rqstp->rq_xprt)); 59774462Salfred return (NULL); 59874462Salfred} 59974462Salfred 60074462Salfred/* nlm_unlock -------------------------------------------------------------- */ 60174462Salfred/* 60274462Salfred * Purpose: Release an existing lock 60374462Salfred * Returns: Always granted, unless during grace period 60474462Salfred * Notes: "no such lock" error condition is ignored, as the 60574462Salfred * protocol uses unreliable UDP datagrams, and may well 60674462Salfred * re-try an unlock that has already succeeded. 60774462Salfred */ 60874462Salfrednlm_res * 60974462Salfrednlm_unlock_1_svc(arg, rqstp) 61074462Salfred nlm_unlockargs *arg; 61174462Salfred struct svc_req *rqstp; 61274462Salfred{ 61374462Salfred static nlm_res res; 61474462Salfred struct nlm4_lock arg4; 61574462Salfred 61674462Salfred nlmtonlm4(&arg->alock, &arg4); 61774462Salfred 61874462Salfred if (debug_level) 61974462Salfred log_from_addr("nlm_unlock", rqstp); 62074462Salfred 62174462Salfred res.stat.stat = unlock(&arg4, 0); 62274462Salfred res.cookie = arg->cookie; 62374462Salfred 62474462Salfred return (&res); 62574462Salfred} 62674462Salfred 62774462Salfredvoid * 62874462Salfrednlm_unlock_msg_1_svc(arg, rqstp) 62974462Salfred nlm_unlockargs *arg; 63074462Salfred struct svc_req *rqstp; 63174462Salfred{ 63274462Salfred static nlm_res res; 63374462Salfred struct nlm4_lock arg4; 63474462Salfred 63574462Salfred nlmtonlm4(&arg->alock, &arg4); 63674462Salfred 63774462Salfred if (debug_level) 63874462Salfred log_from_addr("nlm_unlock_msg", rqstp); 63974462Salfred 64074462Salfred res.stat.stat = unlock(&arg4, 0); 64174462Salfred res.cookie = arg->cookie; 64274462Salfred 64374462Salfred transmit_result(NLM_UNLOCK_RES, &res, 64474462Salfred (struct sockaddr *)svc_getcaller(rqstp->rq_xprt)); 64574462Salfred return (NULL); 64674462Salfred} 64774462Salfred 64874462Salfred/* ------------------------------------------------------------------------- */ 64974462Salfred/* 65074462Salfred * Client-side pseudo-RPCs for results. Note that for the client there 65174462Salfred * are only nlm_xxx_msg() versions of each call, since the 'real RPC' 65274462Salfred * version returns the results in the RPC result, and so the client 65374462Salfred * does not normally receive incoming RPCs. 65474462Salfred * 65574462Salfred * The exception to this is nlm_granted(), which is genuinely an RPC 65674462Salfred * call from the server to the client - a 'call-back' in normal procedure 65774462Salfred * call terms. 65874462Salfred */ 65974462Salfred 66074462Salfred/* nlm_granted ------------------------------------------------------------- */ 66174462Salfred/* 66274462Salfred * Purpose: Receive notification that formerly blocked lock now granted 66374462Salfred * Returns: always success ('granted') 66474462Salfred * Notes: 66574462Salfred */ 66674462Salfrednlm_res * 66774462Salfrednlm_granted_1_svc(arg, rqstp) 66874462Salfred nlm_testargs *arg; 66974462Salfred struct svc_req *rqstp; 67074462Salfred{ 67174462Salfred static nlm_res res; 67274462Salfred 67374462Salfred if (debug_level) 67474462Salfred log_from_addr("nlm_granted", rqstp); 67574462Salfred 67675631Salfred res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 67775631Salfred nlm_granted, NULL, NLM_VERS) == 0 ? 67875631Salfred nlm_granted : nlm_denied; 67975631Salfred 68074462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 68174462Salfred res.cookie = arg->cookie; 68274462Salfred 68374462Salfred return (&res); 68474462Salfred} 68574462Salfred 68674462Salfredvoid * 68774462Salfrednlm_granted_msg_1_svc(arg, rqstp) 68874462Salfred nlm_testargs *arg; 68974462Salfred struct svc_req *rqstp; 69074462Salfred{ 69174462Salfred static nlm_res res; 69274462Salfred 69374462Salfred if (debug_level) 69474462Salfred log_from_addr("nlm_granted_msg", rqstp); 69574462Salfred 69674462Salfred res.cookie = arg->cookie; 69774462Salfred res.stat.stat = nlm_granted; 69874462Salfred transmit_result(NLM_GRANTED_RES, &res, 69974462Salfred (struct sockaddr *)svc_getcaller(rqstp->rq_xprt)); 70074462Salfred return (NULL); 70174462Salfred} 70274462Salfred 70374462Salfred/* nlm_test_res ------------------------------------------------------------ */ 70474462Salfred/* 70574462Salfred * Purpose: Accept result from earlier nlm_test_msg() call 70674462Salfred * Returns: Nothing 70774462Salfred */ 70874462Salfredvoid * 70974462Salfrednlm_test_res_1_svc(arg, rqstp) 71074462Salfred nlm_testres *arg; 71174462Salfred struct svc_req *rqstp; 71274462Salfred{ 71374462Salfred if (debug_level) 71474462Salfred log_from_addr("nlm_test_res", rqstp); 71575631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, 71675631Salfred &arg->stat.nlm_testrply_u.holder.svid, NLM_VERS); 71774462Salfred return (NULL); 71874462Salfred} 71974462Salfred 72074462Salfred/* nlm_lock_res ------------------------------------------------------------ */ 72174462Salfred/* 72274462Salfred * Purpose: Accept result from earlier nlm_lock_msg() call 72374462Salfred * Returns: Nothing 72474462Salfred */ 72574462Salfredvoid * 72674462Salfrednlm_lock_res_1_svc(arg, rqstp) 72774462Salfred nlm_res *arg; 72874462Salfred struct svc_req *rqstp; 72974462Salfred{ 73074462Salfred if (debug_level) 73174462Salfred log_from_addr("nlm_lock_res", rqstp); 73274462Salfred 73375631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS); 73475631Salfred 73574462Salfred return (NULL); 73674462Salfred} 73774462Salfred 73874462Salfred/* nlm_cancel_res ---------------------------------------------------------- */ 73974462Salfred/* 74074462Salfred * Purpose: Accept result from earlier nlm_cancel_msg() call 74174462Salfred * Returns: Nothing 74274462Salfred */ 74374462Salfredvoid * 74474462Salfrednlm_cancel_res_1_svc(arg, rqstp) 74574462Salfred nlm_res *arg; 74674462Salfred struct svc_req *rqstp; 74774462Salfred{ 74874462Salfred if (debug_level) 74974462Salfred log_from_addr("nlm_cancel_res", rqstp); 75074462Salfred return (NULL); 75174462Salfred} 75274462Salfred 75374462Salfred/* nlm_unlock_res ---------------------------------------------------------- */ 75474462Salfred/* 75574462Salfred * Purpose: Accept result from earlier nlm_unlock_msg() call 75674462Salfred * Returns: Nothing 75774462Salfred */ 75874462Salfredvoid * 75974462Salfrednlm_unlock_res_1_svc(arg, rqstp) 76074462Salfred nlm_res *arg; 76174462Salfred struct svc_req *rqstp; 76274462Salfred{ 76374462Salfred if (debug_level) 76474462Salfred log_from_addr("nlm_unlock_res", rqstp); 76575631Salfred 76686300Salfred lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS); 76775631Salfred 76874462Salfred return (NULL); 76974462Salfred} 77074462Salfred 77174462Salfred/* nlm_granted_res --------------------------------------------------------- */ 77274462Salfred/* 77374462Salfred * Purpose: Accept result from earlier nlm_granted_msg() call 77474462Salfred * Returns: Nothing 77574462Salfred */ 77674462Salfredvoid * 77774462Salfrednlm_granted_res_1_svc(arg, rqstp) 77874462Salfred nlm_res *arg; 77974462Salfred struct svc_req *rqstp; 78074462Salfred{ 78174462Salfred if (debug_level) 78274462Salfred log_from_addr("nlm_granted_res", rqstp); 78374462Salfred return (NULL); 78474462Salfred} 78574462Salfred 78674462Salfred/* ------------------------------------------------------------------------- */ 78774462Salfred/* 78874462Salfred * Calls for PCNFS locking (aka non-monitored locking, no involvement 78974462Salfred * of rpc.statd). 79074462Salfred * 79174462Salfred * These are all genuine RPCs - no nlm_xxx_msg() nonsense here. 79274462Salfred */ 79374462Salfred 79474462Salfred/* nlm_share --------------------------------------------------------------- */ 79574462Salfred/* 79674462Salfred * Purpose: Establish a DOS-style lock 79774462Salfred * Returns: success or failure 79874462Salfred * Notes: Blocking locks are not supported - client is expected 79974462Salfred * to retry if required. 80074462Salfred */ 80174462Salfrednlm_shareres * 80274462Salfrednlm_share_3_svc(arg, rqstp) 80374462Salfred nlm_shareargs *arg; 80474462Salfred struct svc_req *rqstp; 80574462Salfred{ 80674462Salfred static nlm_shareres res; 80774462Salfred 80874462Salfred if (debug_level) 80974462Salfred log_from_addr("nlm_share", rqstp); 81074462Salfred 81174462Salfred res.cookie = arg->cookie; 81274462Salfred res.stat = nlm_granted; 81374462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 81474462Salfred return (&res); 81574462Salfred} 81674462Salfred 81774462Salfred/* nlm_unshare ------------------------------------------------------------ */ 81874462Salfred/* 81974462Salfred * Purpose: Release a DOS-style lock 82074462Salfred * Returns: nlm_granted, unless in grace period 82174462Salfred * Notes: 82274462Salfred */ 82374462Salfrednlm_shareres * 82474462Salfrednlm_unshare_3_svc(arg, rqstp) 82574462Salfred nlm_shareargs *arg; 82674462Salfred struct svc_req *rqstp; 82774462Salfred{ 82874462Salfred static nlm_shareres res; 82974462Salfred 83074462Salfred if (debug_level) 83174462Salfred log_from_addr("nlm_unshare", rqstp); 83274462Salfred 83374462Salfred res.cookie = arg->cookie; 83474462Salfred res.stat = nlm_granted; 83574462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 83674462Salfred return (&res); 83774462Salfred} 83874462Salfred 83974462Salfred/* nlm_nm_lock ------------------------------------------------------------ */ 84074462Salfred/* 84174462Salfred * Purpose: non-monitored version of nlm_lock() 84274462Salfred * Returns: as for nlm_lock() 84374462Salfred * Notes: These locks are in the same style as the standard nlm_lock, 84474462Salfred * but the rpc.statd should not be called to establish a 84574462Salfred * monitor for the client machine, since that machine is 84674462Salfred * declared not to be running a rpc.statd, and so would not 84774462Salfred * respond to the statd protocol. 84874462Salfred */ 84974462Salfrednlm_res * 85074462Salfrednlm_nm_lock_3_svc(arg, rqstp) 85174462Salfred nlm_lockargs *arg; 85274462Salfred struct svc_req *rqstp; 85374462Salfred{ 85474462Salfred static nlm_res res; 85574462Salfred 85674462Salfred if (debug_level) 85774462Salfred log_from_addr("nlm_nm_lock", rqstp); 85874462Salfred 85974462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 86074462Salfred res.cookie = arg->cookie; 86174462Salfred res.stat.stat = nlm_granted; 86274462Salfred return (&res); 86374462Salfred} 86474462Salfred 86574462Salfred/* nlm_free_all ------------------------------------------------------------ */ 86674462Salfred/* 86774462Salfred * Purpose: Release all locks held by a named client 86874462Salfred * Returns: Nothing 86974462Salfred * Notes: Potential denial of service security problem here - the 87074462Salfred * locks to be released are specified by a host name, independent 87174462Salfred * of the address from which the request has arrived. 87274462Salfred * Should probably be rejected if the named host has been 87374462Salfred * using monitored locks. 87474462Salfred */ 87574462Salfredvoid * 87674462Salfrednlm_free_all_3_svc(arg, rqstp) 87774462Salfred nlm_notify *arg; 87874462Salfred struct svc_req *rqstp; 87974462Salfred{ 88074462Salfred static char dummy; 88174462Salfred 88274462Salfred if (debug_level) 88374462Salfred log_from_addr("nlm_free_all", rqstp); 88474462Salfred return (&dummy); 88574462Salfred} 88674462Salfred 88774462Salfred/* calls for nlm version 4 (NFSv3) */ 88874462Salfred/* nlm_test ---------------------------------------------------------------- */ 88974462Salfred/* 89074462Salfred * Purpose: Test whether a specified lock would be granted if requested 89174462Salfred * Returns: nlm_granted (or error code) 89274462Salfred * Notes: 89374462Salfred */ 89474462Salfrednlm4_testres * 89574462Salfrednlm4_test_4_svc(arg, rqstp) 89674462Salfred nlm4_testargs *arg; 89774462Salfred struct svc_req *rqstp; 89874462Salfred{ 89974462Salfred static nlm4_testres res; 90074462Salfred struct nlm4_holder *holder; 90174462Salfred 90274462Salfred if (debug_level) 90374462Salfred log_from_addr("nlm4_test", rqstp); 90484923Salfred if (debug_level > 5) { 90584923Salfred syslog(LOG_DEBUG, "Locking arguments:\n"); 90684923Salfred log_netobj(&(arg->cookie)); 90784923Salfred syslog(LOG_DEBUG, "Alock arguments:\n"); 90884923Salfred syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name); 90984923Salfred syslog(LOG_DEBUG, "File Handle:\n"); 91084923Salfred log_netobj(&(arg->alock.fh)); 91184923Salfred syslog(LOG_DEBUG, "Owner Handle:\n"); 91284923Salfred log_netobj(&(arg->alock.oh)); 91384923Salfred syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid); 91484923Salfred syslog(LOG_DEBUG, "Lock Offset: %d\n", arg->alock.l_offset); 91584923Salfred syslog(LOG_DEBUG, "Lock Length: %d\n", arg->alock.l_len); 91684923Salfred syslog(LOG_DEBUG, "Exclusive: %s\n", 91784923Salfred (arg->exclusive ? "true" : "false")); 91884923Salfred } 91974462Salfred 92084923Salfred holder = testlock(&arg->alock, arg->exclusive, LOCK_V4); 92174462Salfred 92274462Salfred /* 92374462Salfred * Copy the cookie from the argument into the result. Note that this 92474462Salfred * is slightly hazardous, as the structure contains a pointer to a 92574462Salfred * malloc()ed buffer that will get freed by the caller. However, the 92674462Salfred * main function transmits the result before freeing the argument 92774462Salfred * so it is in fact safe. 92874462Salfred */ 92974462Salfred res.cookie = arg->cookie; 93074462Salfred if (holder == NULL) { 93174462Salfred res.stat.stat = nlm4_granted; 93274462Salfred } else { 93374462Salfred res.stat.stat = nlm4_denied; 93474462Salfred memcpy(&res.stat.nlm4_testrply_u.holder, holder, 93574462Salfred sizeof(struct nlm4_holder)); 93674462Salfred } 93774462Salfred return (&res); 93874462Salfred} 93974462Salfred 94074462Salfredvoid * 94174462Salfrednlm4_test_msg_4_svc(arg, rqstp) 94274462Salfred nlm4_testargs *arg; 94374462Salfred struct svc_req *rqstp; 94474462Salfred{ 94574462Salfred nlm4_testres res; 94674462Salfred static char dummy; 94774462Salfred struct sockaddr *addr; 94874462Salfred CLIENT *cli; 94974462Salfred int success; 95074462Salfred struct timeval timeo; 95174462Salfred struct nlm4_holder *holder; 95274462Salfred 95374462Salfred if (debug_level) 95474462Salfred log_from_addr("nlm4_test_msg", rqstp); 95574462Salfred 95684923Salfred holder = testlock(&arg->alock, arg->exclusive, LOCK_V4); 95774462Salfred 95874462Salfred res.cookie = arg->cookie; 95974462Salfred if (holder == NULL) { 96074462Salfred res.stat.stat = nlm4_granted; 96174462Salfred } else { 96274462Salfred res.stat.stat = nlm4_denied; 96374462Salfred memcpy(&res.stat.nlm4_testrply_u.holder, holder, 96474462Salfred sizeof(struct nlm4_holder)); 96574462Salfred } 96674462Salfred 96774462Salfred /* 96874462Salfred * nlm_test has different result type to the other operations, so 96974462Salfred * can't use transmit4_result() in this case 97074462Salfred */ 97174462Salfred addr = svc_getrpccaller(rqstp->rq_xprt)->buf; 97274462Salfred if ((cli = get_client(addr, NLM_VERS4)) != NULL) { 97374462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 97474462Salfred timeo.tv_usec = 0; 97574462Salfred 97674462Salfred success = clnt_call(cli, NLM4_TEST_RES, xdr_nlm4_testres, 97774462Salfred &res, xdr_void, &dummy, timeo); 97874462Salfred 97974462Salfred if (debug_level > 2) 98074462Salfred syslog(LOG_DEBUG, "clnt_call returns %d", success); 98174462Salfred } 98274462Salfred return (NULL); 98374462Salfred} 98474462Salfred 98574462Salfred/* nlm_lock ---------------------------------------------------------------- */ 98674462Salfred/* 98774462Salfred * Purposes: Establish a lock 98874462Salfred * Returns: granted, denied or blocked 98974462Salfred * Notes: *** grace period support missing 99074462Salfred */ 99174462Salfrednlm4_res * 99274462Salfrednlm4_lock_4_svc(arg, rqstp) 99374462Salfred nlm4_lockargs *arg; 99474462Salfred struct svc_req *rqstp; 99574462Salfred{ 99674462Salfred static nlm4_res res; 99774462Salfred 99874462Salfred if (debug_level) 99974462Salfred log_from_addr("nlm4_lock", rqstp); 100084923Salfred if (debug_level > 5) { 100184923Salfred syslog(LOG_DEBUG, "Locking arguments:\n"); 100284923Salfred log_netobj(&(arg->cookie)); 100384923Salfred syslog(LOG_DEBUG, "Alock arguments:\n"); 100484923Salfred syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name); 100584923Salfred syslog(LOG_DEBUG, "File Handle:\n"); 100684923Salfred log_netobj(&(arg->alock.fh)); 100784923Salfred syslog(LOG_DEBUG, "Owner Handle:\n"); 100884923Salfred log_netobj(&(arg->alock.oh)); 100984923Salfred syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid); 101084923Salfred syslog(LOG_DEBUG, "Lock Offset: %d\n", arg->alock.l_offset); 101184923Salfred syslog(LOG_DEBUG, "Lock Length: %d\n", arg->alock.l_len); 101284923Salfred syslog(LOG_DEBUG, "Block: %s\n", (arg->block ? "true" : "false")); 101384923Salfred syslog(LOG_DEBUG, "Exclusive: %s\n", (arg->exclusive ? "true" : "false")); 101484923Salfred syslog(LOG_DEBUG, "Reclaim: %s\n", (arg->reclaim ? "true" : "false")); 101584923Salfred syslog(LOG_DEBUG, "State num: %d\n", arg->state); 101684923Salfred } 101774462Salfred 101874462Salfred /* copy cookie from arg to result. See comment in nlm_test_4() */ 101974462Salfred res.cookie = arg->cookie; 102074462Salfred 102174462Salfred res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_V4); 102274462Salfred return (&res); 102374462Salfred} 102474462Salfred 102574462Salfredvoid * 102674462Salfrednlm4_lock_msg_4_svc(arg, rqstp) 102774462Salfred nlm4_lockargs *arg; 102874462Salfred struct svc_req *rqstp; 102974462Salfred{ 103074462Salfred static nlm4_res res; 103174462Salfred 103274462Salfred if (debug_level) 103374462Salfred log_from_addr("nlm4_lock_msg", rqstp); 103474462Salfred 103574462Salfred res.cookie = arg->cookie; 103674462Salfred res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_ASYNC | LOCK_V4); 103774462Salfred transmit4_result(NLM4_LOCK_RES, &res, 103874462Salfred (struct sockaddr *)svc_getcaller(rqstp->rq_xprt)); 103974462Salfred 104074462Salfred return (NULL); 104174462Salfred} 104274462Salfred 104374462Salfred/* nlm_cancel -------------------------------------------------------------- */ 104474462Salfred/* 104574462Salfred * Purpose: Cancel a blocked lock request 104674462Salfred * Returns: granted or denied 104774462Salfred * Notes: 104874462Salfred */ 104974462Salfrednlm4_res * 105074462Salfrednlm4_cancel_4_svc(arg, rqstp) 105174462Salfred nlm4_cancargs *arg; 105274462Salfred struct svc_req *rqstp; 105374462Salfred{ 105474462Salfred static nlm4_res res; 105574462Salfred 105674462Salfred if (debug_level) 105774462Salfred log_from_addr("nlm4_cancel", rqstp); 105874462Salfred 105974462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 106074462Salfred res.cookie = arg->cookie; 106174462Salfred 106274462Salfred /* 106374462Salfred * Since at present we never return 'nlm_blocked', there can never be 106474462Salfred * a lock to cancel, so this call always fails. 106574462Salfred */ 106674462Salfred res.stat.stat = unlock(&arg->alock, LOCK_CANCEL); 106774462Salfred return (&res); 106874462Salfred} 106974462Salfred 107074462Salfredvoid * 107174462Salfrednlm4_cancel_msg_4_svc(arg, rqstp) 107274462Salfred nlm4_cancargs *arg; 107374462Salfred struct svc_req *rqstp; 107474462Salfred{ 107574462Salfred static nlm4_res res; 107674462Salfred 107774462Salfred if (debug_level) 107874462Salfred log_from_addr("nlm4_cancel_msg", rqstp); 107974462Salfred 108074462Salfred res.cookie = arg->cookie; 108174462Salfred /* 108274462Salfred * Since at present we never return 'nlm_blocked', there can never be 108374462Salfred * a lock to cancel, so this call always fails. 108474462Salfred */ 108574462Salfred res.stat.stat = unlock(&arg->alock, LOCK_CANCEL | LOCK_V4); 108674462Salfred transmit4_result(NLM4_CANCEL_RES, &res, 108774462Salfred (struct sockaddr *)svc_getcaller(rqstp->rq_xprt)); 108874462Salfred return (NULL); 108974462Salfred} 109074462Salfred 109174462Salfred/* nlm_unlock -------------------------------------------------------------- */ 109274462Salfred/* 109374462Salfred * Purpose: Release an existing lock 109474462Salfred * Returns: Always granted, unless during grace period 109574462Salfred * Notes: "no such lock" error condition is ignored, as the 109674462Salfred * protocol uses unreliable UDP datagrams, and may well 109774462Salfred * re-try an unlock that has already succeeded. 109874462Salfred */ 109974462Salfrednlm4_res * 110074462Salfrednlm4_unlock_4_svc(arg, rqstp) 110174462Salfred nlm4_unlockargs *arg; 110274462Salfred struct svc_req *rqstp; 110374462Salfred{ 110474462Salfred static nlm4_res res; 110574462Salfred 110674462Salfred if (debug_level) 110774462Salfred log_from_addr("nlm4_unlock", rqstp); 110874462Salfred 110974462Salfred res.stat.stat = unlock(&arg->alock, LOCK_V4); 111074462Salfred res.cookie = arg->cookie; 111174462Salfred 111274462Salfred return (&res); 111374462Salfred} 111474462Salfred 111574462Salfredvoid * 111674462Salfrednlm4_unlock_msg_4_svc(arg, rqstp) 111774462Salfred nlm4_unlockargs *arg; 111874462Salfred struct svc_req *rqstp; 111974462Salfred{ 112074462Salfred static nlm4_res res; 112174462Salfred 112274462Salfred if (debug_level) 112374462Salfred log_from_addr("nlm4_unlock_msg", rqstp); 112474462Salfred 112574462Salfred res.stat.stat = unlock(&arg->alock, LOCK_V4); 112674462Salfred res.cookie = arg->cookie; 112774462Salfred 112874462Salfred transmit4_result(NLM4_UNLOCK_RES, &res, 112974462Salfred (struct sockaddr *)svc_getcaller(rqstp->rq_xprt)); 113074462Salfred return (NULL); 113174462Salfred} 113274462Salfred 113374462Salfred/* ------------------------------------------------------------------------- */ 113474462Salfred/* 113574462Salfred * Client-side pseudo-RPCs for results. Note that for the client there 113674462Salfred * are only nlm_xxx_msg() versions of each call, since the 'real RPC' 113774462Salfred * version returns the results in the RPC result, and so the client 113874462Salfred * does not normally receive incoming RPCs. 113974462Salfred * 114074462Salfred * The exception to this is nlm_granted(), which is genuinely an RPC 114174462Salfred * call from the server to the client - a 'call-back' in normal procedure 114274462Salfred * call terms. 114374462Salfred */ 114474462Salfred 114574462Salfred/* nlm_granted ------------------------------------------------------------- */ 114674462Salfred/* 114774462Salfred * Purpose: Receive notification that formerly blocked lock now granted 114874462Salfred * Returns: always success ('granted') 114974462Salfred * Notes: 115074462Salfred */ 115174462Salfrednlm4_res * 115274462Salfrednlm4_granted_4_svc(arg, rqstp) 115374462Salfred nlm4_testargs *arg; 115474462Salfred struct svc_req *rqstp; 115574462Salfred{ 115674462Salfred static nlm4_res res; 115774462Salfred 115874462Salfred if (debug_level) 115974462Salfred log_from_addr("nlm4_granted", rqstp); 116074462Salfred 116175631Salfred res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 116275631Salfred nlm4_granted, NULL, NLM_VERS4) == 0 ? 116375631Salfred nlm4_granted : nlm4_denied; 116475631Salfred 116574462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 116674462Salfred res.cookie = arg->cookie; 116774462Salfred 116874462Salfred return (&res); 116974462Salfred} 117074462Salfred 117174462Salfredvoid * 117274462Salfrednlm4_granted_msg_4_svc(arg, rqstp) 117374462Salfred nlm4_testargs *arg; 117474462Salfred struct svc_req *rqstp; 117574462Salfred{ 117674462Salfred static nlm4_res res; 117774462Salfred 117874462Salfred if (debug_level) 117974462Salfred log_from_addr("nlm4_granted_msg", rqstp); 118074462Salfred 118174462Salfred res.cookie = arg->cookie; 118274462Salfred res.stat.stat = nlm4_granted; 118374462Salfred transmit4_result(NLM4_GRANTED_RES, &res, 118474462Salfred (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf); 118574462Salfred return (NULL); 118674462Salfred} 118774462Salfred 118874462Salfred/* nlm_test_res ------------------------------------------------------------ */ 118974462Salfred/* 119074462Salfred * Purpose: Accept result from earlier nlm_test_msg() call 119174462Salfred * Returns: Nothing 119274462Salfred */ 119374462Salfredvoid * 119474462Salfrednlm4_test_res_4_svc(arg, rqstp) 119574462Salfred nlm4_testres *arg; 119674462Salfred struct svc_req *rqstp; 119774462Salfred{ 119874462Salfred if (debug_level) 119974462Salfred log_from_addr("nlm4_test_res", rqstp); 120075631Salfred 120175631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, 120275631Salfred (int *)&arg->stat.nlm4_testrply_u.holder.svid, 120375631Salfred NLM_VERS4); 120474462Salfred return (NULL); 120574462Salfred} 120674462Salfred 120774462Salfred/* nlm_lock_res ------------------------------------------------------------ */ 120874462Salfred/* 120974462Salfred * Purpose: Accept result from earlier nlm_lock_msg() call 121074462Salfred * Returns: Nothing 121174462Salfred */ 121274462Salfredvoid * 121374462Salfrednlm4_lock_res_4_svc(arg, rqstp) 121474462Salfred nlm4_res *arg; 121574462Salfred struct svc_req *rqstp; 121674462Salfred{ 121774462Salfred if (debug_level) 121874462Salfred log_from_addr("nlm4_lock_res", rqstp); 121974462Salfred 122075631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS4); 122175631Salfred 122274462Salfred return (NULL); 122374462Salfred} 122474462Salfred 122574462Salfred/* nlm_cancel_res ---------------------------------------------------------- */ 122674462Salfred/* 122774462Salfred * Purpose: Accept result from earlier nlm_cancel_msg() call 122874462Salfred * Returns: Nothing 122974462Salfred */ 123074462Salfredvoid * 123174462Salfrednlm4_cancel_res_4_svc(arg, rqstp) 123274462Salfred nlm4_res *arg; 123374462Salfred struct svc_req *rqstp; 123474462Salfred{ 123574462Salfred if (debug_level) 123674462Salfred log_from_addr("nlm4_cancel_res", rqstp); 123774462Salfred return (NULL); 123874462Salfred} 123974462Salfred 124074462Salfred/* nlm_unlock_res ---------------------------------------------------------- */ 124174462Salfred/* 124274462Salfred * Purpose: Accept result from earlier nlm_unlock_msg() call 124374462Salfred * Returns: Nothing 124474462Salfred */ 124574462Salfredvoid * 124674462Salfrednlm4_unlock_res_4_svc(arg, rqstp) 124774462Salfred nlm4_res *arg; 124874462Salfred struct svc_req *rqstp; 124974462Salfred{ 125074462Salfred if (debug_level) 125174462Salfred log_from_addr("nlm4_unlock_res", rqstp); 125274462Salfred return (NULL); 125374462Salfred} 125474462Salfred 125574462Salfred/* nlm_granted_res --------------------------------------------------------- */ 125674462Salfred/* 125774462Salfred * Purpose: Accept result from earlier nlm_granted_msg() call 125874462Salfred * Returns: Nothing 125974462Salfred */ 126074462Salfredvoid * 126174462Salfrednlm4_granted_res_4_svc(arg, rqstp) 126274462Salfred nlm4_res *arg; 126374462Salfred struct svc_req *rqstp; 126474462Salfred{ 126574462Salfred if (debug_level) 126674462Salfred log_from_addr("nlm4_granted_res", rqstp); 126774462Salfred return (NULL); 126874462Salfred} 126974462Salfred 127074462Salfred/* ------------------------------------------------------------------------- */ 127174462Salfred/* 127274462Salfred * Calls for PCNFS locking (aka non-monitored locking, no involvement 127374462Salfred * of rpc.statd). 127474462Salfred * 127574462Salfred * These are all genuine RPCs - no nlm_xxx_msg() nonsense here. 127674462Salfred */ 127774462Salfred 127874462Salfred/* nlm_share --------------------------------------------------------------- */ 127974462Salfred/* 128074462Salfred * Purpose: Establish a DOS-style lock 128174462Salfred * Returns: success or failure 128274462Salfred * Notes: Blocking locks are not supported - client is expected 128374462Salfred * to retry if required. 128474462Salfred */ 128574462Salfrednlm4_shareres * 128674462Salfrednlm4_share_4_svc(arg, rqstp) 128774462Salfred nlm4_shareargs *arg; 128874462Salfred struct svc_req *rqstp; 128974462Salfred{ 129074462Salfred static nlm4_shareres res; 129174462Salfred 129274462Salfred if (debug_level) 129374462Salfred log_from_addr("nlm4_share", rqstp); 129474462Salfred 129574462Salfred res.cookie = arg->cookie; 129674462Salfred res.stat = nlm4_granted; 129774462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 129874462Salfred return (&res); 129974462Salfred} 130074462Salfred 130174462Salfred/* nlm4_unshare ------------------------------------------------------------ */ 130274462Salfred/* 130374462Salfred * Purpose: Release a DOS-style lock 130474462Salfred * Returns: nlm_granted, unless in grace period 130574462Salfred * Notes: 130674462Salfred */ 130774462Salfrednlm4_shareres * 130874462Salfrednlm4_unshare_4_svc(arg, rqstp) 130974462Salfred nlm4_shareargs *arg; 131074462Salfred struct svc_req *rqstp; 131174462Salfred{ 131274462Salfred static nlm4_shareres res; 131374462Salfred 131474462Salfred if (debug_level) 131574462Salfred log_from_addr("nlm_unshare", rqstp); 131674462Salfred 131774462Salfred res.cookie = arg->cookie; 131874462Salfred res.stat = nlm4_granted; 131974462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 132074462Salfred return (&res); 132174462Salfred} 132274462Salfred 132374462Salfred/* nlm4_nm_lock ------------------------------------------------------------ */ 132474462Salfred/* 132574462Salfred * Purpose: non-monitored version of nlm4_lock() 132674462Salfred * Returns: as for nlm4_lock() 132774462Salfred * Notes: These locks are in the same style as the standard nlm4_lock, 132874462Salfred * but the rpc.statd should not be called to establish a 132974462Salfred * monitor for the client machine, since that machine is 133074462Salfred * declared not to be running a rpc.statd, and so would not 133174462Salfred * respond to the statd protocol. 133274462Salfred */ 133374462Salfrednlm4_res * 133474462Salfrednlm4_nm_lock_4_svc(arg, rqstp) 133574462Salfred nlm4_lockargs *arg; 133674462Salfred struct svc_req *rqstp; 133774462Salfred{ 133874462Salfred static nlm4_res res; 133974462Salfred 134074462Salfred if (debug_level) 134174462Salfred log_from_addr("nlm4_nm_lock", rqstp); 134274462Salfred 134374462Salfred /* copy cookie from arg to result. See comment in nlm4_test_1() */ 134474462Salfred res.cookie = arg->cookie; 134574462Salfred res.stat.stat = nlm4_granted; 134674462Salfred return (&res); 134774462Salfred} 134874462Salfred 134974462Salfred/* nlm4_free_all ------------------------------------------------------------ */ 135074462Salfred/* 135174462Salfred * Purpose: Release all locks held by a named client 135274462Salfred * Returns: Nothing 135374462Salfred * Notes: Potential denial of service security problem here - the 135474462Salfred * locks to be released are specified by a host name, independent 135574462Salfred * of the address from which the request has arrived. 135674462Salfred * Should probably be rejected if the named host has been 135774462Salfred * using monitored locks. 135874462Salfred */ 135974462Salfredvoid * 136074462Salfrednlm4_free_all_4_svc(arg, rqstp) 136175631Salfred struct nlm4_notify *arg; 136274462Salfred struct svc_req *rqstp; 136374462Salfred{ 136474462Salfred static char dummy; 136574462Salfred 136674462Salfred if (debug_level) 136774462Salfred log_from_addr("nlm4_free_all", rqstp); 136874462Salfred return (&dummy); 136974462Salfred} 137074462Salfred 137174462Salfred/* nlm_sm_notify --------------------------------------------------------- */ 137274462Salfred/* 137374462Salfred * Purpose: called by rpc.statd when a monitored host state changes. 137474462Salfred * Returns: Nothing 137574462Salfred */ 137674462Salfredvoid * 137774462Salfrednlm_sm_notify_0_svc(arg, rqstp) 137874462Salfred struct nlm_sm_status *arg; 137974462Salfred struct svc_req *rqstp; 138074462Salfred{ 138174462Salfred static char dummy; 138274462Salfred notify(arg->mon_name, arg->state); 138374462Salfred return (&dummy); 138474462Salfred} 1385