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