174462Salfred/* $NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $ */ 274462Salfred/* $FreeBSD: releng/11.0/usr.sbin/rpc.lockd/lock_proc.c 299986 2016-05-16 23:00:48Z truckman $ */ 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> 51136320Sstefanf#include <unistd.h> 5274462Salfred#include <netconfig.h> 5374462Salfred 5474462Salfred#include <rpc/rpc.h> 5574462Salfred#include <rpcsvc/sm_inter.h> 5674462Salfred 5774462Salfred#include "lockd.h" 5874462Salfred#include <rpcsvc/nlm_prot.h> 5974462Salfred#include "lockd_lock.h" 6074462Salfred 6174462Salfred 6274462Salfred#define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */ 6374462Salfred#define CLIENT_CACHE_LIFETIME 120 /* In seconds */ 6474462Salfred 65141217Skuriyama#define getrpcaddr(rqstp) (struct sockaddr *)(svc_getrpccaller((rqstp)->rq_xprt)->buf) 66141217Skuriyama 6792969Salfredstatic void log_from_addr(const char *, struct svc_req *); 6892909Salfredstatic void log_netobj(netobj *obj); 6992909Salfredstatic int addrcmp(struct sockaddr *, struct sockaddr *); 7074462Salfred 7174462Salfred/* log_from_addr ----------------------------------------------------------- */ 7274462Salfred/* 7374462Salfred * Purpose: Log name of function called and source address 7474462Salfred * Returns: Nothing 7574462Salfred * Notes: Extracts the source address from the transport handle 7674462Salfred * passed in as part of the called procedure specification 7774462Salfred */ 7874462Salfredstatic void 79260250Sdelphijlog_from_addr(const char *fun_name, struct svc_req *req) 8074462Salfred{ 8174462Salfred struct sockaddr *addr; 8274462Salfred char hostname_buf[NI_MAXHOST]; 8374462Salfred 8474462Salfred addr = svc_getrpccaller(req->rq_xprt)->buf; 8574462Salfred if (getnameinfo(addr , addr->sa_len, hostname_buf, sizeof hostname_buf, 8674462Salfred NULL, 0, 0) != 0) 8774462Salfred return; 8874462Salfred 8974462Salfred syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf); 9074462Salfred} 9174462Salfred 9284923Salfred/* log_netobj ----------------------------------------------------------- */ 9384923Salfred/* 9484923Salfred * Purpose: Log a netobj 9584923Salfred * Returns: Nothing 9684923Salfred * Notes: This function should only really be called as part of 9784923Salfred * a debug subsystem. 9884923Salfred*/ 9984923Salfredstatic void 100260250Sdelphijlog_netobj(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); 115299986Struckman for (i=0, tmp1 = objvalbuffer, tmp2 = objascbuffer; i < maxlen; 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 161260250Sdelphijaddrcmp(struct sockaddr *sa1, struct sockaddr *sa2) 16274462Salfred{ 16374462Salfred int len; 16474462Salfred void *p1, *p2; 16574462Salfred 16674462Salfred if (sa1->sa_family != sa2->sa_family) 16774462Salfred return -1; 16874462Salfred 16974462Salfred switch (sa1->sa_family) { 17074462Salfred case AF_INET: 17174462Salfred p1 = &((struct sockaddr_in *)sa1)->sin_addr; 17274462Salfred p2 = &((struct sockaddr_in *)sa2)->sin_addr; 17374462Salfred len = 4; 17474462Salfred break; 17574462Salfred case AF_INET6: 17674462Salfred p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr; 17774462Salfred p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr; 17874462Salfred len = 16; 17974462Salfred break; 18074462Salfred default: 18174462Salfred return -1; 18274462Salfred } 18374462Salfred 18474462Salfred return memcmp(p1, p2, len); 18574462Salfred} 18674462Salfred 18774462SalfredCLIENT * 188260250Sdelphijget_client(struct sockaddr *host_addr, rpcvers_t vers) 18974462Salfred{ 19074462Salfred CLIENT *client; 19174462Salfred struct timeval retry_time, time_now; 192141217Skuriyama int error, i; 19392977Salfred const char *netid; 19474462Salfred struct netconfig *nconf; 19574462Salfred char host[NI_MAXHOST]; 196126606Sroam uid_t old_euid; 197126606Sroam int clnt_fd; 19874462Salfred 19974462Salfred gettimeofday(&time_now, NULL); 20074462Salfred 20174462Salfred /* 20274462Salfred * Search for the given client in the cache, zapping any expired 20374462Salfred * entries that we happen to notice in passing. 20474462Salfred */ 20574462Salfred for (i = 0; i < CLIENT_CACHE_SIZE; i++) { 20674462Salfred client = clnt_cache_ptr[i]; 20774462Salfred if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME) 20874462Salfred < time_now.tv_sec)) { 20974462Salfred /* Cache entry has expired. */ 21074462Salfred if (debug_level > 3) 21174462Salfred syslog(LOG_DEBUG, "Expired CLIENT* in cache"); 21274462Salfred clnt_cache_time[i] = 0L; 21374462Salfred clnt_destroy(client); 21474462Salfred clnt_cache_ptr[i] = NULL; 21574462Salfred client = NULL; 21674462Salfred } 21774462Salfred if (client && !addrcmp((struct sockaddr *)&clnt_cache_addr[i], 21876093Salfred host_addr) && clnt_cache_vers[i] == vers) { 21974462Salfred /* Found it! */ 22074462Salfred if (debug_level > 3) 22174462Salfred syslog(LOG_DEBUG, "Found CLIENT* in cache"); 22274462Salfred return (client); 22374462Salfred } 22474462Salfred } 22574462Salfred 22676093Salfred if (debug_level > 3) 22776093Salfred syslog(LOG_DEBUG, "CLIENT* not found in cache, creating"); 22876093Salfred 22974462Salfred /* Not found in cache. Free the next entry if it is in use. */ 23074462Salfred if (clnt_cache_ptr[clnt_cache_next_to_use]) { 23174462Salfred clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]); 23274462Salfred clnt_cache_ptr[clnt_cache_next_to_use] = NULL; 23374462Salfred } 23474462Salfred 23574462Salfred /* 23674462Salfred * Need a host string for clnt_tp_create. Use NI_NUMERICHOST 23774462Salfred * to avoid DNS lookups. 23874462Salfred */ 239141217Skuriyama error = getnameinfo(host_addr, host_addr->sa_len, host, sizeof host, 240141217Skuriyama NULL, 0, NI_NUMERICHOST); 241141217Skuriyama if (error != 0) { 242141217Skuriyama syslog(LOG_ERR, "unable to get name string for caller: %s", 243141217Skuriyama gai_strerror(error)); 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 274126606Sroam /* Get the FD of the client, for bindresvport. */ 275126606Sroam clnt_control(client, CLGET_FD, &clnt_fd); 276126606Sroam 277126606Sroam /* Regain root privileges, for bindresvport. */ 278126606Sroam old_euid = geteuid(); 279126606Sroam seteuid(0); 280126606Sroam 281126606Sroam /* 282126606Sroam * Bind the client FD to a reserved port. 283126606Sroam * Some NFS servers reject any NLM request from a non-reserved port. 284126606Sroam */ 285126606Sroam bindresvport(clnt_fd, NULL); 286126606Sroam 287126606Sroam /* Drop root privileges again. */ 288126606Sroam seteuid(old_euid); 289126606Sroam 29074462Salfred /* Success - update the cache entry */ 29174462Salfred clnt_cache_ptr[clnt_cache_next_to_use] = client; 29274462Salfred memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr, 29374462Salfred host_addr->sa_len); 29476093Salfred clnt_cache_vers[clnt_cache_next_to_use] = vers; 29574462Salfred clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec; 296132254Smr if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE) 29774462Salfred clnt_cache_next_to_use = 0; 29874462Salfred 29974462Salfred /* 30074462Salfred * Disable the default timeout, so we can specify our own in calls 30174462Salfred * to clnt_call(). (Note that the timeout is a different concept 30274462Salfred * from the retry period set in clnt_udp_create() above.) 30374462Salfred */ 30474462Salfred retry_time.tv_sec = -1; 30574462Salfred retry_time.tv_usec = -1; 30674462Salfred clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time); 30774462Salfred 30874462Salfred if (debug_level > 3) 30974462Salfred syslog(LOG_DEBUG, "Created CLIENT* for %s", host); 31074462Salfred return client; 31174462Salfred} 31274462Salfred 31374462Salfred 31474462Salfred/* transmit_result --------------------------------------------------------- */ 31574462Salfred/* 31674462Salfred * Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs 31774462Salfred * Returns: Nothing - we have no idea if the datagram got there 31874462Salfred * Notes: clnt_call() will always fail (with timeout) as we are 31974462Salfred * calling it with timeout 0 as a hack to just issue a datagram 32074462Salfred * without expecting a result 32174462Salfred */ 32274462Salfredvoid 323260250Sdelphijtransmit_result(int opcode, nlm_res *result, struct sockaddr *addr) 32474462Salfred{ 32574462Salfred static char dummy; 32674462Salfred CLIENT *cli; 32774462Salfred struct timeval timeo; 32874462Salfred int success; 32974462Salfred 33074462Salfred if ((cli = get_client(addr, NLM_VERS)) != NULL) { 33174462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 33274462Salfred timeo.tv_usec = 0; 33374462Salfred 334121558Speter success = clnt_call(cli, opcode, (xdrproc_t)xdr_nlm_res, result, 335121558Speter (xdrproc_t)xdr_void, &dummy, timeo); 33674462Salfred 33774462Salfred if (debug_level > 2) 33874462Salfred syslog(LOG_DEBUG, "clnt_call returns %d(%s)", 33974462Salfred success, clnt_sperrno(success)); 34074462Salfred } 34174462Salfred} 34274462Salfred/* transmit4_result --------------------------------------------------------- */ 34374462Salfred/* 34474462Salfred * Purpose: Transmit result for nlm4_xxx_msg pseudo-RPCs 34574462Salfred * Returns: Nothing - we have no idea if the datagram got there 34674462Salfred * Notes: clnt_call() will always fail (with timeout) as we are 34774462Salfred * calling it with timeout 0 as a hack to just issue a datagram 34874462Salfred * without expecting a result 34974462Salfred */ 35074462Salfredvoid 351260250Sdelphijtransmit4_result(int opcode, nlm4_res *result, struct sockaddr *addr) 35274462Salfred{ 35374462Salfred static char dummy; 35474462Salfred CLIENT *cli; 35574462Salfred struct timeval timeo; 35674462Salfred int success; 35774462Salfred 35874462Salfred if ((cli = get_client(addr, NLM_VERS4)) != NULL) { 35974462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 36074462Salfred timeo.tv_usec = 0; 36174462Salfred 362121558Speter success = clnt_call(cli, opcode, 363121558Speter (xdrproc_t)xdr_nlm4_res, result, 364121558Speter (xdrproc_t)xdr_void, &dummy, timeo); 36574462Salfred 36674462Salfred if (debug_level > 2) 36774462Salfred syslog(LOG_DEBUG, "clnt_call returns %d(%s)", 36874462Salfred success, clnt_sperrno(success)); 36974462Salfred } 37074462Salfred} 37174462Salfred 37274462Salfred/* 37374462Salfred * converts a struct nlm_lock to struct nlm4_lock 37474462Salfred */ 37574462Salfredstatic void 376260250Sdelphijnlmtonlm4(struct nlm_lock *arg, struct nlm4_lock *arg4) 37774462Salfred{ 378132254Smr arg4->caller_name = arg->caller_name; 379132254Smr arg4->fh = arg->fh; 380132254Smr arg4->oh = arg->oh; 381132254Smr arg4->svid = arg->svid; 38274462Salfred arg4->l_offset = arg->l_offset; 38374462Salfred arg4->l_len = arg->l_len; 38474462Salfred} 38574462Salfred/* ------------------------------------------------------------------------- */ 38674462Salfred/* 38774462Salfred * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd 38874462Salfred * involved to ensure reclaim of locks after a crash of the "stateless" 38974462Salfred * server. 39074462Salfred * 39174462Salfred * These all come in two flavours - nlm_xxx() and nlm_xxx_msg(). 39274462Salfred * The first are standard RPCs with argument and result. 39374462Salfred * The nlm_xxx_msg() calls implement exactly the same functions, but 39474462Salfred * use two pseudo-RPCs (one in each direction). These calls are NOT 39574462Salfred * standard use of the RPC protocol in that they do not return a result 39674462Salfred * at all (NB. this is quite different from returning a void result). 39774462Salfred * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged 39874462Salfred * datagrams, requiring higher-level code to perform retries. 39974462Salfred * 40074462Salfred * Despite the disadvantages of the nlm_xxx_msg() approach (some of which 40174462Salfred * are documented in the comments to get_client() above), this is the 40274462Salfred * interface used by all current commercial NFS implementations 40374462Salfred * [Solaris, SCO, AIX etc.]. This is presumed to be because these allow 40474462Salfred * implementations to continue using the standard RPC libraries, while 40574462Salfred * avoiding the block-until-result nature of the library interface. 40674462Salfred * 40774462Salfred * No client implementations have been identified so far that make use 40874462Salfred * of the true RPC version (early SunOS releases would be a likely candidate 40974462Salfred * for testing). 41074462Salfred */ 41174462Salfred 41274462Salfred/* nlm_test ---------------------------------------------------------------- */ 41374462Salfred/* 41474462Salfred * Purpose: Test whether a specified lock would be granted if requested 41574462Salfred * Returns: nlm_granted (or error code) 41674462Salfred * Notes: 41774462Salfred */ 41874462Salfrednlm_testres * 419260250Sdelphijnlm_test_1_svc(nlm_testargs *arg, struct svc_req *rqstp) 42074462Salfred{ 42174462Salfred static nlm_testres res; 42274462Salfred struct nlm4_lock arg4; 42374462Salfred struct nlm4_holder *holder; 42474462Salfred nlmtonlm4(&arg->alock, &arg4); 42574462Salfred 42674462Salfred if (debug_level) 42774462Salfred log_from_addr("nlm_test", rqstp); 42874462Salfred 42984923Salfred holder = testlock(&arg4, arg->exclusive, 0); 43074462Salfred /* 43174462Salfred * Copy the cookie from the argument into the result. Note that this 43274462Salfred * is slightly hazardous, as the structure contains a pointer to a 43374462Salfred * malloc()ed buffer that will get freed by the caller. However, the 43474462Salfred * main function transmits the result before freeing the argument 43574462Salfred * so it is in fact safe. 43674462Salfred */ 43774462Salfred res.cookie = arg->cookie; 43874462Salfred if (holder == NULL) { 43974462Salfred res.stat.stat = nlm_granted; 44074462Salfred } else { 44174462Salfred res.stat.stat = nlm_denied; 44274462Salfred memcpy(&res.stat.nlm_testrply_u.holder, holder, 44374462Salfred sizeof(struct nlm_holder)); 44474462Salfred res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset; 44574462Salfred res.stat.nlm_testrply_u.holder.l_len = holder->l_len; 44674462Salfred } 44774462Salfred return (&res); 44874462Salfred} 44974462Salfred 45074462Salfredvoid * 451260250Sdelphijnlm_test_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp) 45274462Salfred{ 45374462Salfred nlm_testres res; 45474462Salfred static char dummy; 45574462Salfred struct sockaddr *addr; 45674462Salfred CLIENT *cli; 45774462Salfred int success; 45874462Salfred struct timeval timeo; 45974462Salfred struct nlm4_lock arg4; 46074462Salfred struct nlm4_holder *holder; 46174462Salfred 46274462Salfred nlmtonlm4(&arg->alock, &arg4); 46374462Salfred 46474462Salfred if (debug_level) 46574462Salfred log_from_addr("nlm_test_msg", rqstp); 46674462Salfred 46784923Salfred holder = testlock(&arg4, arg->exclusive, 0); 46874462Salfred 46974462Salfred res.cookie = arg->cookie; 47074462Salfred if (holder == NULL) { 47174462Salfred res.stat.stat = nlm_granted; 47274462Salfred } else { 47374462Salfred res.stat.stat = nlm_denied; 47474462Salfred memcpy(&res.stat.nlm_testrply_u.holder, holder, 47574462Salfred sizeof(struct nlm_holder)); 47674462Salfred res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset; 47774462Salfred res.stat.nlm_testrply_u.holder.l_len = holder->l_len; 47874462Salfred } 47974462Salfred 48074462Salfred /* 48174462Salfred * nlm_test has different result type to the other operations, so 48274462Salfred * can't use transmit_result() in this case 48374462Salfred */ 48474462Salfred addr = svc_getrpccaller(rqstp->rq_xprt)->buf; 48574462Salfred if ((cli = get_client(addr, NLM_VERS)) != NULL) { 48674462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 48774462Salfred timeo.tv_usec = 0; 48874462Salfred 489121558Speter success = clnt_call(cli, NLM_TEST_RES, 490121558Speter (xdrproc_t)xdr_nlm_testres, &res, 491121558Speter (xdrproc_t)xdr_void, &dummy, timeo); 49274462Salfred 49374462Salfred if (debug_level > 2) 49474462Salfred syslog(LOG_DEBUG, "clnt_call returns %d", success); 49574462Salfred } 49674462Salfred return (NULL); 49774462Salfred} 49874462Salfred 49974462Salfred/* nlm_lock ---------------------------------------------------------------- */ 50074462Salfred/* 50174462Salfred * Purposes: Establish a lock 50274462Salfred * Returns: granted, denied or blocked 50374462Salfred * Notes: *** grace period support missing 50474462Salfred */ 50574462Salfrednlm_res * 506260250Sdelphijnlm_lock_1_svc(nlm_lockargs *arg, struct svc_req *rqstp) 50774462Salfred{ 50874462Salfred static nlm_res res; 50974462Salfred struct nlm4_lockargs arg4; 51074462Salfred nlmtonlm4(&arg->alock, &arg4.alock); 51174462Salfred arg4.cookie = arg->cookie; 51274462Salfred arg4.block = arg->block; 51374462Salfred arg4.exclusive = arg->exclusive; 51474462Salfred arg4.reclaim = arg->reclaim; 51574462Salfred arg4.state = arg->state; 51674462Salfred 51774462Salfred if (debug_level) 51874462Salfred log_from_addr("nlm_lock", rqstp); 51974462Salfred 52074462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 52174462Salfred res.cookie = arg->cookie; 52274462Salfred 52374462Salfred res.stat.stat = getlock(&arg4, rqstp, LOCK_MON); 52474462Salfred return (&res); 52574462Salfred} 52674462Salfred 52774462Salfredvoid * 528260250Sdelphijnlm_lock_msg_1_svc(nlm_lockargs *arg, struct svc_req *rqstp) 52974462Salfred{ 53074462Salfred static nlm_res res; 53174462Salfred struct nlm4_lockargs arg4; 53274462Salfred 53374462Salfred nlmtonlm4(&arg->alock, &arg4.alock); 53474462Salfred arg4.cookie = arg->cookie; 53574462Salfred arg4.block = arg->block; 53674462Salfred arg4.exclusive = arg->exclusive; 53774462Salfred arg4.reclaim = arg->reclaim; 53874462Salfred arg4.state = arg->state; 53974462Salfred 54074462Salfred if (debug_level) 54174462Salfred log_from_addr("nlm_lock_msg", rqstp); 54274462Salfred 54374462Salfred res.cookie = arg->cookie; 54474462Salfred res.stat.stat = getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON); 545141217Skuriyama transmit_result(NLM_LOCK_RES, &res, getrpcaddr(rqstp)); 54674462Salfred 54774462Salfred return (NULL); 54874462Salfred} 54974462Salfred 55074462Salfred/* nlm_cancel -------------------------------------------------------------- */ 55174462Salfred/* 55274462Salfred * Purpose: Cancel a blocked lock request 55374462Salfred * Returns: granted or denied 55474462Salfred * Notes: 55574462Salfred */ 55674462Salfrednlm_res * 557260250Sdelphijnlm_cancel_1_svc(nlm_cancargs *arg, struct svc_req *rqstp) 55874462Salfred{ 55974462Salfred static nlm_res res; 56074462Salfred struct nlm4_lock arg4; 56174462Salfred 56274462Salfred nlmtonlm4(&arg->alock, &arg4); 56374462Salfred 56474462Salfred if (debug_level) 56574462Salfred log_from_addr("nlm_cancel", rqstp); 56674462Salfred 56774462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 56874462Salfred res.cookie = arg->cookie; 56974462Salfred 57074462Salfred /* 57174462Salfred * Since at present we never return 'nlm_blocked', there can never be 57274462Salfred * a lock to cancel, so this call always fails. 57374462Salfred */ 57474462Salfred res.stat.stat = unlock(&arg4, LOCK_CANCEL); 57574462Salfred return (&res); 57674462Salfred} 57774462Salfred 57874462Salfredvoid * 579260250Sdelphijnlm_cancel_msg_1_svc(nlm_cancargs *arg, 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); 595141217Skuriyama transmit_result(NLM_CANCEL_RES, &res, getrpcaddr(rqstp)); 59674462Salfred return (NULL); 59774462Salfred} 59874462Salfred 59974462Salfred/* nlm_unlock -------------------------------------------------------------- */ 60074462Salfred/* 60174462Salfred * Purpose: Release an existing lock 60274462Salfred * Returns: Always granted, unless during grace period 60374462Salfred * Notes: "no such lock" error condition is ignored, as the 60474462Salfred * protocol uses unreliable UDP datagrams, and may well 60574462Salfred * re-try an unlock that has already succeeded. 60674462Salfred */ 60774462Salfrednlm_res * 608260250Sdelphijnlm_unlock_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp) 60974462Salfred{ 61074462Salfred static nlm_res res; 61174462Salfred struct nlm4_lock arg4; 61274462Salfred 61374462Salfred nlmtonlm4(&arg->alock, &arg4); 61474462Salfred 61574462Salfred if (debug_level) 61674462Salfred log_from_addr("nlm_unlock", rqstp); 61774462Salfred 61874462Salfred res.stat.stat = unlock(&arg4, 0); 61974462Salfred res.cookie = arg->cookie; 62074462Salfred 62174462Salfred return (&res); 62274462Salfred} 62374462Salfred 62474462Salfredvoid * 625260250Sdelphijnlm_unlock_msg_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp) 62674462Salfred{ 62774462Salfred static nlm_res res; 62874462Salfred struct nlm4_lock arg4; 62974462Salfred 63074462Salfred nlmtonlm4(&arg->alock, &arg4); 63174462Salfred 63274462Salfred if (debug_level) 63374462Salfred log_from_addr("nlm_unlock_msg", rqstp); 63474462Salfred 63574462Salfred res.stat.stat = unlock(&arg4, 0); 63674462Salfred res.cookie = arg->cookie; 63774462Salfred 638141217Skuriyama transmit_result(NLM_UNLOCK_RES, &res, getrpcaddr(rqstp)); 63974462Salfred return (NULL); 64074462Salfred} 64174462Salfred 64274462Salfred/* ------------------------------------------------------------------------- */ 64374462Salfred/* 64474462Salfred * Client-side pseudo-RPCs for results. Note that for the client there 64574462Salfred * are only nlm_xxx_msg() versions of each call, since the 'real RPC' 64674462Salfred * version returns the results in the RPC result, and so the client 64774462Salfred * does not normally receive incoming RPCs. 64874462Salfred * 64974462Salfred * The exception to this is nlm_granted(), which is genuinely an RPC 65074462Salfred * call from the server to the client - a 'call-back' in normal procedure 65174462Salfred * call terms. 65274462Salfred */ 65374462Salfred 65474462Salfred/* nlm_granted ------------------------------------------------------------- */ 65574462Salfred/* 65674462Salfred * Purpose: Receive notification that formerly blocked lock now granted 65774462Salfred * Returns: always success ('granted') 65874462Salfred * Notes: 65974462Salfred */ 66074462Salfrednlm_res * 661260250Sdelphijnlm_granted_1_svc(nlm_testargs *arg, struct svc_req *rqstp) 66274462Salfred{ 66374462Salfred static nlm_res res; 66474462Salfred 66574462Salfred if (debug_level) 66674462Salfred log_from_addr("nlm_granted", rqstp); 66774462Salfred 66875631Salfred res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 66975631Salfred nlm_granted, NULL, NLM_VERS) == 0 ? 67075631Salfred nlm_granted : nlm_denied; 67175631Salfred 67274462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 67374462Salfred res.cookie = arg->cookie; 67474462Salfred 67574462Salfred return (&res); 67674462Salfred} 67774462Salfred 67874462Salfredvoid * 679260250Sdelphijnlm_granted_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp) 68074462Salfred{ 68174462Salfred static nlm_res res; 68274462Salfred 68374462Salfred if (debug_level) 68474462Salfred log_from_addr("nlm_granted_msg", rqstp); 68574462Salfred 68674462Salfred res.cookie = arg->cookie; 687114993Srwatson res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 688114993Srwatson nlm_granted, NULL, NLM_VERS) == 0 ? 689114993Srwatson nlm_granted : nlm_denied; 690114993Srwatson 691141217Skuriyama transmit_result(NLM_GRANTED_RES, &res, getrpcaddr(rqstp)); 69274462Salfred return (NULL); 69374462Salfred} 69474462Salfred 69574462Salfred/* nlm_test_res ------------------------------------------------------------ */ 69674462Salfred/* 69774462Salfred * Purpose: Accept result from earlier nlm_test_msg() call 69874462Salfred * Returns: Nothing 69974462Salfred */ 70074462Salfredvoid * 701260250Sdelphijnlm_test_res_1_svc(nlm_testres *arg, struct svc_req *rqstp) 70274462Salfred{ 70374462Salfred if (debug_level) 70474462Salfred log_from_addr("nlm_test_res", rqstp); 70575631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, 70675631Salfred &arg->stat.nlm_testrply_u.holder.svid, NLM_VERS); 70774462Salfred return (NULL); 70874462Salfred} 70974462Salfred 71074462Salfred/* nlm_lock_res ------------------------------------------------------------ */ 71174462Salfred/* 71274462Salfred * Purpose: Accept result from earlier nlm_lock_msg() call 71374462Salfred * Returns: Nothing 71474462Salfred */ 71574462Salfredvoid * 716260250Sdelphijnlm_lock_res_1_svc(nlm_res *arg, struct svc_req *rqstp) 71774462Salfred{ 71874462Salfred if (debug_level) 71974462Salfred log_from_addr("nlm_lock_res", rqstp); 72074462Salfred 72175631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS); 72275631Salfred 72374462Salfred return (NULL); 72474462Salfred} 72574462Salfred 72674462Salfred/* nlm_cancel_res ---------------------------------------------------------- */ 72774462Salfred/* 72874462Salfred * Purpose: Accept result from earlier nlm_cancel_msg() call 72974462Salfred * Returns: Nothing 73074462Salfred */ 73174462Salfredvoid * 732260250Sdelphijnlm_cancel_res_1_svc(nlm_res *arg __unused, struct svc_req *rqstp) 73374462Salfred{ 73474462Salfred if (debug_level) 73574462Salfred log_from_addr("nlm_cancel_res", rqstp); 73674462Salfred return (NULL); 73774462Salfred} 73874462Salfred 73974462Salfred/* nlm_unlock_res ---------------------------------------------------------- */ 74074462Salfred/* 74174462Salfred * Purpose: Accept result from earlier nlm_unlock_msg() call 74274462Salfred * Returns: Nothing 74374462Salfred */ 74474462Salfredvoid * 745260250Sdelphijnlm_unlock_res_1_svc(nlm_res *arg, struct svc_req *rqstp) 74674462Salfred{ 74774462Salfred if (debug_level) 74874462Salfred log_from_addr("nlm_unlock_res", rqstp); 74975631Salfred 75086300Salfred lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS); 75175631Salfred 75274462Salfred return (NULL); 75374462Salfred} 75474462Salfred 75574462Salfred/* nlm_granted_res --------------------------------------------------------- */ 75674462Salfred/* 75774462Salfred * Purpose: Accept result from earlier nlm_granted_msg() call 75874462Salfred * Returns: Nothing 75974462Salfred */ 76074462Salfredvoid * 761260250Sdelphijnlm_granted_res_1_svc(nlm_res *arg __unused, struct svc_req *rqstp) 76274462Salfred{ 76374462Salfred if (debug_level) 76474462Salfred log_from_addr("nlm_granted_res", rqstp); 76574462Salfred return (NULL); 76674462Salfred} 76774462Salfred 76874462Salfred/* ------------------------------------------------------------------------- */ 76974462Salfred/* 77074462Salfred * Calls for PCNFS locking (aka non-monitored locking, no involvement 77174462Salfred * of rpc.statd). 77274462Salfred * 77374462Salfred * These are all genuine RPCs - no nlm_xxx_msg() nonsense here. 77474462Salfred */ 77574462Salfred 77674462Salfred/* nlm_share --------------------------------------------------------------- */ 77774462Salfred/* 77874462Salfred * Purpose: Establish a DOS-style lock 77974462Salfred * Returns: success or failure 78074462Salfred * Notes: Blocking locks are not supported - client is expected 78174462Salfred * to retry if required. 78274462Salfred */ 78374462Salfrednlm_shareres * 784260250Sdelphijnlm_share_3_svc(nlm_shareargs *arg, struct svc_req *rqstp) 78574462Salfred{ 78674462Salfred static nlm_shareres res; 78774462Salfred 78874462Salfred if (debug_level) 78974462Salfred log_from_addr("nlm_share", rqstp); 79074462Salfred 79174462Salfred res.cookie = arg->cookie; 79274462Salfred res.stat = nlm_granted; 79374462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 79474462Salfred return (&res); 79574462Salfred} 79674462Salfred 79774462Salfred/* nlm_unshare ------------------------------------------------------------ */ 79874462Salfred/* 79974462Salfred * Purpose: Release a DOS-style lock 80074462Salfred * Returns: nlm_granted, unless in grace period 80174462Salfred * Notes: 80274462Salfred */ 80374462Salfrednlm_shareres * 804260250Sdelphijnlm_unshare_3_svc(nlm_shareargs *arg, struct svc_req *rqstp) 80574462Salfred{ 80674462Salfred static nlm_shareres res; 80774462Salfred 80874462Salfred if (debug_level) 80974462Salfred log_from_addr("nlm_unshare", 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_nm_lock ------------------------------------------------------------ */ 81874462Salfred/* 81974462Salfred * Purpose: non-monitored version of nlm_lock() 82074462Salfred * Returns: as for nlm_lock() 82174462Salfred * Notes: These locks are in the same style as the standard nlm_lock, 82274462Salfred * but the rpc.statd should not be called to establish a 82374462Salfred * monitor for the client machine, since that machine is 82474462Salfred * declared not to be running a rpc.statd, and so would not 82574462Salfred * respond to the statd protocol. 82674462Salfred */ 82774462Salfrednlm_res * 828260250Sdelphijnlm_nm_lock_3_svc(nlm_lockargs *arg, struct svc_req *rqstp) 82974462Salfred{ 83074462Salfred static nlm_res res; 83174462Salfred 83274462Salfred if (debug_level) 83374462Salfred log_from_addr("nlm_nm_lock", rqstp); 83474462Salfred 83574462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 83674462Salfred res.cookie = arg->cookie; 83774462Salfred res.stat.stat = nlm_granted; 83874462Salfred return (&res); 83974462Salfred} 84074462Salfred 84174462Salfred/* nlm_free_all ------------------------------------------------------------ */ 84274462Salfred/* 84374462Salfred * Purpose: Release all locks held by a named client 84474462Salfred * Returns: Nothing 84574462Salfred * Notes: Potential denial of service security problem here - the 84674462Salfred * locks to be released are specified by a host name, independent 84774462Salfred * of the address from which the request has arrived. 84874462Salfred * Should probably be rejected if the named host has been 84974462Salfred * using monitored locks. 85074462Salfred */ 85174462Salfredvoid * 852260250Sdelphijnlm_free_all_3_svc(nlm_notify *arg __unused, struct svc_req *rqstp) 85374462Salfred{ 85474462Salfred static char dummy; 85574462Salfred 85674462Salfred if (debug_level) 85774462Salfred log_from_addr("nlm_free_all", rqstp); 85874462Salfred return (&dummy); 85974462Salfred} 86074462Salfred 86174462Salfred/* calls for nlm version 4 (NFSv3) */ 86274462Salfred/* nlm_test ---------------------------------------------------------------- */ 86374462Salfred/* 86474462Salfred * Purpose: Test whether a specified lock would be granted if requested 86574462Salfred * Returns: nlm_granted (or error code) 86674462Salfred * Notes: 86774462Salfred */ 86874462Salfrednlm4_testres * 869260250Sdelphijnlm4_test_4_svc(nlm4_testargs *arg, struct svc_req *rqstp) 87074462Salfred{ 87174462Salfred static nlm4_testres res; 87274462Salfred struct nlm4_holder *holder; 87374462Salfred 87474462Salfred if (debug_level) 87574462Salfred log_from_addr("nlm4_test", rqstp); 87684923Salfred if (debug_level > 5) { 87784923Salfred syslog(LOG_DEBUG, "Locking arguments:\n"); 87884923Salfred log_netobj(&(arg->cookie)); 87984923Salfred syslog(LOG_DEBUG, "Alock arguments:\n"); 88084923Salfred syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name); 88184923Salfred syslog(LOG_DEBUG, "File Handle:\n"); 88284923Salfred log_netobj(&(arg->alock.fh)); 88384923Salfred syslog(LOG_DEBUG, "Owner Handle:\n"); 88484923Salfred log_netobj(&(arg->alock.oh)); 88584923Salfred syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid); 88686319Salfred syslog(LOG_DEBUG, "Lock Offset: %llu\n", 88786319Salfred (unsigned long long)arg->alock.l_offset); 88886319Salfred syslog(LOG_DEBUG, "Lock Length: %llu\n", 88986319Salfred (unsigned long long)arg->alock.l_len); 89084923Salfred syslog(LOG_DEBUG, "Exclusive: %s\n", 89184923Salfred (arg->exclusive ? "true" : "false")); 89284923Salfred } 89374462Salfred 89484923Salfred holder = testlock(&arg->alock, arg->exclusive, LOCK_V4); 89574462Salfred 89674462Salfred /* 89774462Salfred * Copy the cookie from the argument into the result. Note that this 89874462Salfred * is slightly hazardous, as the structure contains a pointer to a 89974462Salfred * malloc()ed buffer that will get freed by the caller. However, the 90074462Salfred * main function transmits the result before freeing the argument 90174462Salfred * so it is in fact safe. 90274462Salfred */ 90374462Salfred res.cookie = arg->cookie; 90474462Salfred if (holder == NULL) { 90574462Salfred res.stat.stat = nlm4_granted; 90674462Salfred } else { 90774462Salfred res.stat.stat = nlm4_denied; 90874462Salfred memcpy(&res.stat.nlm4_testrply_u.holder, holder, 90974462Salfred sizeof(struct nlm4_holder)); 91074462Salfred } 91174462Salfred return (&res); 91274462Salfred} 91374462Salfred 91474462Salfredvoid * 915260250Sdelphijnlm4_test_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp) 91674462Salfred{ 91774462Salfred nlm4_testres res; 91874462Salfred static char dummy; 91974462Salfred struct sockaddr *addr; 92074462Salfred CLIENT *cli; 92174462Salfred int success; 92274462Salfred struct timeval timeo; 92374462Salfred struct nlm4_holder *holder; 92474462Salfred 92574462Salfred if (debug_level) 92674462Salfred log_from_addr("nlm4_test_msg", rqstp); 92774462Salfred 92884923Salfred holder = testlock(&arg->alock, arg->exclusive, LOCK_V4); 92974462Salfred 93074462Salfred res.cookie = arg->cookie; 93174462Salfred if (holder == NULL) { 93274462Salfred res.stat.stat = nlm4_granted; 93374462Salfred } else { 93474462Salfred res.stat.stat = nlm4_denied; 93574462Salfred memcpy(&res.stat.nlm4_testrply_u.holder, holder, 93674462Salfred sizeof(struct nlm4_holder)); 93774462Salfred } 93874462Salfred 93974462Salfred /* 94074462Salfred * nlm_test has different result type to the other operations, so 94174462Salfred * can't use transmit4_result() in this case 94274462Salfred */ 94374462Salfred addr = svc_getrpccaller(rqstp->rq_xprt)->buf; 94474462Salfred if ((cli = get_client(addr, NLM_VERS4)) != NULL) { 94574462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 94674462Salfred timeo.tv_usec = 0; 94774462Salfred 948121558Speter success = clnt_call(cli, NLM4_TEST_RES, 949121558Speter (xdrproc_t)xdr_nlm4_testres, &res, 950121558Speter (xdrproc_t)xdr_void, &dummy, timeo); 95174462Salfred 95274462Salfred if (debug_level > 2) 95374462Salfred syslog(LOG_DEBUG, "clnt_call returns %d", success); 95474462Salfred } 95574462Salfred return (NULL); 95674462Salfred} 95774462Salfred 95874462Salfred/* nlm_lock ---------------------------------------------------------------- */ 95974462Salfred/* 96074462Salfred * Purposes: Establish a lock 96174462Salfred * Returns: granted, denied or blocked 96274462Salfred * Notes: *** grace period support missing 96374462Salfred */ 96474462Salfrednlm4_res * 965260250Sdelphijnlm4_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp) 96674462Salfred{ 96774462Salfred static nlm4_res res; 96874462Salfred 96974462Salfred if (debug_level) 97074462Salfred log_from_addr("nlm4_lock", rqstp); 97184923Salfred if (debug_level > 5) { 97284923Salfred syslog(LOG_DEBUG, "Locking arguments:\n"); 97384923Salfred log_netobj(&(arg->cookie)); 97484923Salfred syslog(LOG_DEBUG, "Alock arguments:\n"); 97584923Salfred syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name); 97684923Salfred syslog(LOG_DEBUG, "File Handle:\n"); 97784923Salfred log_netobj(&(arg->alock.fh)); 97884923Salfred syslog(LOG_DEBUG, "Owner Handle:\n"); 97984923Salfred log_netobj(&(arg->alock.oh)); 98084923Salfred syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid); 98186319Salfred syslog(LOG_DEBUG, "Lock Offset: %llu\n", 98286319Salfred (unsigned long long)arg->alock.l_offset); 98386319Salfred syslog(LOG_DEBUG, "Lock Length: %llu\n", 98486319Salfred (unsigned long long)arg->alock.l_len); 98584923Salfred syslog(LOG_DEBUG, "Block: %s\n", (arg->block ? "true" : "false")); 98684923Salfred syslog(LOG_DEBUG, "Exclusive: %s\n", (arg->exclusive ? "true" : "false")); 98784923Salfred syslog(LOG_DEBUG, "Reclaim: %s\n", (arg->reclaim ? "true" : "false")); 98884923Salfred syslog(LOG_DEBUG, "State num: %d\n", arg->state); 98984923Salfred } 99074462Salfred 99174462Salfred /* copy cookie from arg to result. See comment in nlm_test_4() */ 99274462Salfred res.cookie = arg->cookie; 99374462Salfred 99474462Salfred res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_V4); 99574462Salfred return (&res); 99674462Salfred} 99774462Salfred 99874462Salfredvoid * 999260250Sdelphijnlm4_lock_msg_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp) 100074462Salfred{ 100174462Salfred static nlm4_res res; 100274462Salfred 100374462Salfred if (debug_level) 100474462Salfred log_from_addr("nlm4_lock_msg", rqstp); 100574462Salfred 100674462Salfred res.cookie = arg->cookie; 100774462Salfred res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_ASYNC | LOCK_V4); 1008141217Skuriyama transmit4_result(NLM4_LOCK_RES, &res, getrpcaddr(rqstp)); 100974462Salfred 101074462Salfred return (NULL); 101174462Salfred} 101274462Salfred 101374462Salfred/* nlm_cancel -------------------------------------------------------------- */ 101474462Salfred/* 101574462Salfred * Purpose: Cancel a blocked lock request 101674462Salfred * Returns: granted or denied 101774462Salfred * Notes: 101874462Salfred */ 101974462Salfrednlm4_res * 1020260250Sdelphijnlm4_cancel_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp) 102174462Salfred{ 102274462Salfred static nlm4_res res; 102374462Salfred 102474462Salfred if (debug_level) 102574462Salfred log_from_addr("nlm4_cancel", rqstp); 102674462Salfred 102774462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 102874462Salfred res.cookie = arg->cookie; 102974462Salfred 103074462Salfred /* 103174462Salfred * Since at present we never return 'nlm_blocked', there can never be 103274462Salfred * a lock to cancel, so this call always fails. 103374462Salfred */ 103474462Salfred res.stat.stat = unlock(&arg->alock, LOCK_CANCEL); 103574462Salfred return (&res); 103674462Salfred} 103774462Salfred 103874462Salfredvoid * 1039260250Sdelphijnlm4_cancel_msg_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp) 104074462Salfred{ 104174462Salfred static nlm4_res res; 104274462Salfred 104374462Salfred if (debug_level) 104474462Salfred log_from_addr("nlm4_cancel_msg", rqstp); 104574462Salfred 104674462Salfred res.cookie = arg->cookie; 104774462Salfred /* 104874462Salfred * Since at present we never return 'nlm_blocked', there can never be 104974462Salfred * a lock to cancel, so this call always fails. 105074462Salfred */ 105174462Salfred res.stat.stat = unlock(&arg->alock, LOCK_CANCEL | LOCK_V4); 1052141217Skuriyama transmit4_result(NLM4_CANCEL_RES, &res, getrpcaddr(rqstp)); 105374462Salfred return (NULL); 105474462Salfred} 105574462Salfred 105674462Salfred/* nlm_unlock -------------------------------------------------------------- */ 105774462Salfred/* 105874462Salfred * Purpose: Release an existing lock 105974462Salfred * Returns: Always granted, unless during grace period 106074462Salfred * Notes: "no such lock" error condition is ignored, as the 106174462Salfred * protocol uses unreliable UDP datagrams, and may well 106274462Salfred * re-try an unlock that has already succeeded. 106374462Salfred */ 106474462Salfrednlm4_res * 1065260250Sdelphijnlm4_unlock_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp) 106674462Salfred{ 106774462Salfred static nlm4_res res; 106874462Salfred 106974462Salfred if (debug_level) 107074462Salfred log_from_addr("nlm4_unlock", rqstp); 107174462Salfred 107274462Salfred res.stat.stat = unlock(&arg->alock, LOCK_V4); 107374462Salfred res.cookie = arg->cookie; 107474462Salfred 107574462Salfred return (&res); 107674462Salfred} 107774462Salfred 107874462Salfredvoid * 1079260250Sdelphijnlm4_unlock_msg_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp) 108074462Salfred{ 108174462Salfred static nlm4_res res; 108274462Salfred 108374462Salfred if (debug_level) 108474462Salfred log_from_addr("nlm4_unlock_msg", rqstp); 108574462Salfred 108674462Salfred res.stat.stat = unlock(&arg->alock, LOCK_V4); 108774462Salfred res.cookie = arg->cookie; 108874462Salfred 1089141217Skuriyama transmit4_result(NLM4_UNLOCK_RES, &res, getrpcaddr(rqstp)); 109074462Salfred return (NULL); 109174462Salfred} 109274462Salfred 109374462Salfred/* ------------------------------------------------------------------------- */ 109474462Salfred/* 109574462Salfred * Client-side pseudo-RPCs for results. Note that for the client there 109674462Salfred * are only nlm_xxx_msg() versions of each call, since the 'real RPC' 109774462Salfred * version returns the results in the RPC result, and so the client 109874462Salfred * does not normally receive incoming RPCs. 109974462Salfred * 110074462Salfred * The exception to this is nlm_granted(), which is genuinely an RPC 110174462Salfred * call from the server to the client - a 'call-back' in normal procedure 110274462Salfred * call terms. 110374462Salfred */ 110474462Salfred 110574462Salfred/* nlm_granted ------------------------------------------------------------- */ 110674462Salfred/* 110774462Salfred * Purpose: Receive notification that formerly blocked lock now granted 110874462Salfred * Returns: always success ('granted') 110974462Salfred * Notes: 111074462Salfred */ 111174462Salfrednlm4_res * 1112260250Sdelphijnlm4_granted_4_svc(nlm4_testargs *arg, struct svc_req *rqstp) 111374462Salfred{ 111474462Salfred static nlm4_res res; 111574462Salfred 111674462Salfred if (debug_level) 111774462Salfred log_from_addr("nlm4_granted", rqstp); 111874462Salfred 111975631Salfred res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 112075631Salfred nlm4_granted, NULL, NLM_VERS4) == 0 ? 112175631Salfred nlm4_granted : nlm4_denied; 112275631Salfred 112374462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 112474462Salfred res.cookie = arg->cookie; 112574462Salfred 112674462Salfred return (&res); 112774462Salfred} 112874462Salfred 112974462Salfredvoid * 1130260250Sdelphijnlm4_granted_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp) 113174462Salfred{ 113274462Salfred static nlm4_res res; 113374462Salfred 113474462Salfred if (debug_level) 113574462Salfred log_from_addr("nlm4_granted_msg", rqstp); 113674462Salfred 113774462Salfred res.cookie = arg->cookie; 1138114993Srwatson res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 1139114993Srwatson nlm4_granted, NULL, NLM_VERS4) == 0 ? 1140114993Srwatson nlm4_granted : nlm4_denied; 1141141217Skuriyama transmit4_result(NLM4_GRANTED_RES, &res, getrpcaddr(rqstp)); 114274462Salfred return (NULL); 114374462Salfred} 114474462Salfred 114574462Salfred/* nlm_test_res ------------------------------------------------------------ */ 114674462Salfred/* 114774462Salfred * Purpose: Accept result from earlier nlm_test_msg() call 114874462Salfred * Returns: Nothing 114974462Salfred */ 115074462Salfredvoid * 1151260250Sdelphijnlm4_test_res_4_svc(nlm4_testres *arg, struct svc_req *rqstp) 115274462Salfred{ 115374462Salfred if (debug_level) 115474462Salfred log_from_addr("nlm4_test_res", rqstp); 115575631Salfred 115675631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, 115775631Salfred (int *)&arg->stat.nlm4_testrply_u.holder.svid, 115875631Salfred NLM_VERS4); 115974462Salfred return (NULL); 116074462Salfred} 116174462Salfred 116274462Salfred/* nlm_lock_res ------------------------------------------------------------ */ 116374462Salfred/* 116474462Salfred * Purpose: Accept result from earlier nlm_lock_msg() call 116574462Salfred * Returns: Nothing 116674462Salfred */ 116774462Salfredvoid * 1168260250Sdelphijnlm4_lock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp) 116974462Salfred{ 117074462Salfred if (debug_level) 117174462Salfred log_from_addr("nlm4_lock_res", rqstp); 117274462Salfred 117375631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS4); 117475631Salfred 117574462Salfred return (NULL); 117674462Salfred} 117774462Salfred 117874462Salfred/* nlm_cancel_res ---------------------------------------------------------- */ 117974462Salfred/* 118074462Salfred * Purpose: Accept result from earlier nlm_cancel_msg() call 118174462Salfred * Returns: Nothing 118274462Salfred */ 118374462Salfredvoid * 1184260250Sdelphijnlm4_cancel_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp) 118574462Salfred{ 118674462Salfred if (debug_level) 118774462Salfred log_from_addr("nlm4_cancel_res", rqstp); 118874462Salfred return (NULL); 118974462Salfred} 119074462Salfred 119174462Salfred/* nlm_unlock_res ---------------------------------------------------------- */ 119274462Salfred/* 119374462Salfred * Purpose: Accept result from earlier nlm_unlock_msg() call 119474462Salfred * Returns: Nothing 119574462Salfred */ 119674462Salfredvoid * 1197260250Sdelphijnlm4_unlock_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp) 119874462Salfred{ 119974462Salfred if (debug_level) 120074462Salfred log_from_addr("nlm4_unlock_res", rqstp); 120174462Salfred return (NULL); 120274462Salfred} 120374462Salfred 120474462Salfred/* nlm_granted_res --------------------------------------------------------- */ 120574462Salfred/* 120674462Salfred * Purpose: Accept result from earlier nlm_granted_msg() call 120774462Salfred * Returns: Nothing 120874462Salfred */ 120974462Salfredvoid * 1210260250Sdelphijnlm4_granted_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp) 121174462Salfred{ 121274462Salfred if (debug_level) 121374462Salfred log_from_addr("nlm4_granted_res", rqstp); 121474462Salfred return (NULL); 121574462Salfred} 121674462Salfred 121774462Salfred/* ------------------------------------------------------------------------- */ 121874462Salfred/* 121974462Salfred * Calls for PCNFS locking (aka non-monitored locking, no involvement 122074462Salfred * of rpc.statd). 122174462Salfred * 122274462Salfred * These are all genuine RPCs - no nlm_xxx_msg() nonsense here. 122374462Salfred */ 122474462Salfred 122574462Salfred/* nlm_share --------------------------------------------------------------- */ 122674462Salfred/* 122774462Salfred * Purpose: Establish a DOS-style lock 122874462Salfred * Returns: success or failure 122974462Salfred * Notes: Blocking locks are not supported - client is expected 123074462Salfred * to retry if required. 123174462Salfred */ 123274462Salfrednlm4_shareres * 1233260250Sdelphijnlm4_share_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp) 123474462Salfred{ 123574462Salfred static nlm4_shareres res; 123674462Salfred 123774462Salfred if (debug_level) 123874462Salfred log_from_addr("nlm4_share", rqstp); 123974462Salfred 124074462Salfred res.cookie = arg->cookie; 124174462Salfred res.stat = nlm4_granted; 124274462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 124374462Salfred return (&res); 124474462Salfred} 124574462Salfred 124674462Salfred/* nlm4_unshare ------------------------------------------------------------ */ 124774462Salfred/* 124874462Salfred * Purpose: Release a DOS-style lock 124974462Salfred * Returns: nlm_granted, unless in grace period 125074462Salfred * Notes: 125174462Salfred */ 125274462Salfrednlm4_shareres * 1253260250Sdelphijnlm4_unshare_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp) 125474462Salfred{ 125574462Salfred static nlm4_shareres res; 125674462Salfred 125774462Salfred if (debug_level) 125874462Salfred log_from_addr("nlm_unshare", rqstp); 125974462Salfred 126074462Salfred res.cookie = arg->cookie; 126174462Salfred res.stat = nlm4_granted; 126274462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 126374462Salfred return (&res); 126474462Salfred} 126574462Salfred 126674462Salfred/* nlm4_nm_lock ------------------------------------------------------------ */ 126774462Salfred/* 126874462Salfred * Purpose: non-monitored version of nlm4_lock() 126974462Salfred * Returns: as for nlm4_lock() 127074462Salfred * Notes: These locks are in the same style as the standard nlm4_lock, 127174462Salfred * but the rpc.statd should not be called to establish a 127274462Salfred * monitor for the client machine, since that machine is 127374462Salfred * declared not to be running a rpc.statd, and so would not 127474462Salfred * respond to the statd protocol. 127574462Salfred */ 127674462Salfrednlm4_res * 1277260250Sdelphijnlm4_nm_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp) 127874462Salfred{ 127974462Salfred static nlm4_res res; 128074462Salfred 128174462Salfred if (debug_level) 128274462Salfred log_from_addr("nlm4_nm_lock", rqstp); 128374462Salfred 128474462Salfred /* copy cookie from arg to result. See comment in nlm4_test_1() */ 128574462Salfred res.cookie = arg->cookie; 128674462Salfred res.stat.stat = nlm4_granted; 128774462Salfred return (&res); 128874462Salfred} 128974462Salfred 129074462Salfred/* nlm4_free_all ------------------------------------------------------------ */ 129174462Salfred/* 129274462Salfred * Purpose: Release all locks held by a named client 129374462Salfred * Returns: Nothing 129474462Salfred * Notes: Potential denial of service security problem here - the 129574462Salfred * locks to be released are specified by a host name, independent 129674462Salfred * of the address from which the request has arrived. 129774462Salfred * Should probably be rejected if the named host has been 129874462Salfred * using monitored locks. 129974462Salfred */ 130074462Salfredvoid * 1301260250Sdelphijnlm4_free_all_4_svc(struct nlm4_notify *arg __unused, struct svc_req *rqstp) 130274462Salfred{ 130374462Salfred static char dummy; 130474462Salfred 130574462Salfred if (debug_level) 130674462Salfred log_from_addr("nlm4_free_all", rqstp); 130774462Salfred return (&dummy); 130874462Salfred} 130974462Salfred 131074462Salfred/* nlm_sm_notify --------------------------------------------------------- */ 131174462Salfred/* 131274462Salfred * Purpose: called by rpc.statd when a monitored host state changes. 131374462Salfred * Returns: Nothing 131474462Salfred */ 131574462Salfredvoid * 1316260250Sdelphijnlm_sm_notify_0_svc(struct nlm_sm_status *arg, struct svc_req *rqstp __unused) 131774462Salfred{ 131874462Salfred static char dummy; 131974462Salfred notify(arg->mon_name, arg->state); 132074462Salfred return (&dummy); 132174462Salfred} 1322