lock_proc.c revision 114993
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 114993 2003-05-14 13:50:40Z rwatson $ */ 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 6492969Salfredstatic void log_from_addr(const char *, struct svc_req *); 6592909Salfredstatic void log_netobj(netobj *obj); 6692909Salfredstatic int addrcmp(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) 7792969Salfred const 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; 19792977Salfred const 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 */ 36492909Salfredstatic void nlmtonlm4(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; 698114993Srwatson res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 699114993Srwatson nlm_granted, NULL, NLM_VERS) == 0 ? 700114993Srwatson nlm_granted : nlm_denied; 701114993Srwatson 70274462Salfred transmit_result(NLM_GRANTED_RES, &res, 70374462Salfred (struct sockaddr *)svc_getcaller(rqstp->rq_xprt)); 70474462Salfred return (NULL); 70574462Salfred} 70674462Salfred 70774462Salfred/* nlm_test_res ------------------------------------------------------------ */ 70874462Salfred/* 70974462Salfred * Purpose: Accept result from earlier nlm_test_msg() call 71074462Salfred * Returns: Nothing 71174462Salfred */ 71274462Salfredvoid * 71374462Salfrednlm_test_res_1_svc(arg, rqstp) 71474462Salfred nlm_testres *arg; 71574462Salfred struct svc_req *rqstp; 71674462Salfred{ 71774462Salfred if (debug_level) 71874462Salfred log_from_addr("nlm_test_res", rqstp); 71975631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, 72075631Salfred &arg->stat.nlm_testrply_u.holder.svid, NLM_VERS); 72174462Salfred return (NULL); 72274462Salfred} 72374462Salfred 72474462Salfred/* nlm_lock_res ------------------------------------------------------------ */ 72574462Salfred/* 72674462Salfred * Purpose: Accept result from earlier nlm_lock_msg() call 72774462Salfred * Returns: Nothing 72874462Salfred */ 72974462Salfredvoid * 73074462Salfrednlm_lock_res_1_svc(arg, rqstp) 73174462Salfred nlm_res *arg; 73274462Salfred struct svc_req *rqstp; 73374462Salfred{ 73474462Salfred if (debug_level) 73574462Salfred log_from_addr("nlm_lock_res", rqstp); 73674462Salfred 73775631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS); 73875631Salfred 73974462Salfred return (NULL); 74074462Salfred} 74174462Salfred 74274462Salfred/* nlm_cancel_res ---------------------------------------------------------- */ 74374462Salfred/* 74474462Salfred * Purpose: Accept result from earlier nlm_cancel_msg() call 74574462Salfred * Returns: Nothing 74674462Salfred */ 74774462Salfredvoid * 74874462Salfrednlm_cancel_res_1_svc(arg, rqstp) 74992911Salfred nlm_res *arg __unused; 75074462Salfred struct svc_req *rqstp; 75174462Salfred{ 75274462Salfred if (debug_level) 75374462Salfred log_from_addr("nlm_cancel_res", rqstp); 75474462Salfred return (NULL); 75574462Salfred} 75674462Salfred 75774462Salfred/* nlm_unlock_res ---------------------------------------------------------- */ 75874462Salfred/* 75974462Salfred * Purpose: Accept result from earlier nlm_unlock_msg() call 76074462Salfred * Returns: Nothing 76174462Salfred */ 76274462Salfredvoid * 76374462Salfrednlm_unlock_res_1_svc(arg, rqstp) 76474462Salfred nlm_res *arg; 76574462Salfred struct svc_req *rqstp; 76674462Salfred{ 76774462Salfred if (debug_level) 76874462Salfred log_from_addr("nlm_unlock_res", rqstp); 76975631Salfred 77086300Salfred lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS); 77175631Salfred 77274462Salfred return (NULL); 77374462Salfred} 77474462Salfred 77574462Salfred/* nlm_granted_res --------------------------------------------------------- */ 77674462Salfred/* 77774462Salfred * Purpose: Accept result from earlier nlm_granted_msg() call 77874462Salfred * Returns: Nothing 77974462Salfred */ 78074462Salfredvoid * 78174462Salfrednlm_granted_res_1_svc(arg, rqstp) 78292911Salfred nlm_res *arg __unused; 78374462Salfred struct svc_req *rqstp; 78474462Salfred{ 78574462Salfred if (debug_level) 78674462Salfred log_from_addr("nlm_granted_res", rqstp); 78774462Salfred return (NULL); 78874462Salfred} 78974462Salfred 79074462Salfred/* ------------------------------------------------------------------------- */ 79174462Salfred/* 79274462Salfred * Calls for PCNFS locking (aka non-monitored locking, no involvement 79374462Salfred * of rpc.statd). 79474462Salfred * 79574462Salfred * These are all genuine RPCs - no nlm_xxx_msg() nonsense here. 79674462Salfred */ 79774462Salfred 79874462Salfred/* nlm_share --------------------------------------------------------------- */ 79974462Salfred/* 80074462Salfred * Purpose: Establish a DOS-style lock 80174462Salfred * Returns: success or failure 80274462Salfred * Notes: Blocking locks are not supported - client is expected 80374462Salfred * to retry if required. 80474462Salfred */ 80574462Salfrednlm_shareres * 80674462Salfrednlm_share_3_svc(arg, rqstp) 80774462Salfred nlm_shareargs *arg; 80874462Salfred struct svc_req *rqstp; 80974462Salfred{ 81074462Salfred static nlm_shareres res; 81174462Salfred 81274462Salfred if (debug_level) 81374462Salfred log_from_addr("nlm_share", rqstp); 81474462Salfred 81574462Salfred res.cookie = arg->cookie; 81674462Salfred res.stat = nlm_granted; 81774462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 81874462Salfred return (&res); 81974462Salfred} 82074462Salfred 82174462Salfred/* nlm_unshare ------------------------------------------------------------ */ 82274462Salfred/* 82374462Salfred * Purpose: Release a DOS-style lock 82474462Salfred * Returns: nlm_granted, unless in grace period 82574462Salfred * Notes: 82674462Salfred */ 82774462Salfrednlm_shareres * 82874462Salfrednlm_unshare_3_svc(arg, rqstp) 82974462Salfred nlm_shareargs *arg; 83074462Salfred struct svc_req *rqstp; 83174462Salfred{ 83274462Salfred static nlm_shareres res; 83374462Salfred 83474462Salfred if (debug_level) 83574462Salfred log_from_addr("nlm_unshare", rqstp); 83674462Salfred 83774462Salfred res.cookie = arg->cookie; 83874462Salfred res.stat = nlm_granted; 83974462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 84074462Salfred return (&res); 84174462Salfred} 84274462Salfred 84374462Salfred/* nlm_nm_lock ------------------------------------------------------------ */ 84474462Salfred/* 84574462Salfred * Purpose: non-monitored version of nlm_lock() 84674462Salfred * Returns: as for nlm_lock() 84774462Salfred * Notes: These locks are in the same style as the standard nlm_lock, 84874462Salfred * but the rpc.statd should not be called to establish a 84974462Salfred * monitor for the client machine, since that machine is 85074462Salfred * declared not to be running a rpc.statd, and so would not 85174462Salfred * respond to the statd protocol. 85274462Salfred */ 85374462Salfrednlm_res * 85474462Salfrednlm_nm_lock_3_svc(arg, rqstp) 85574462Salfred nlm_lockargs *arg; 85674462Salfred struct svc_req *rqstp; 85774462Salfred{ 85874462Salfred static nlm_res res; 85974462Salfred 86074462Salfred if (debug_level) 86174462Salfred log_from_addr("nlm_nm_lock", rqstp); 86274462Salfred 86374462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 86474462Salfred res.cookie = arg->cookie; 86574462Salfred res.stat.stat = nlm_granted; 86674462Salfred return (&res); 86774462Salfred} 86874462Salfred 86974462Salfred/* nlm_free_all ------------------------------------------------------------ */ 87074462Salfred/* 87174462Salfred * Purpose: Release all locks held by a named client 87274462Salfred * Returns: Nothing 87374462Salfred * Notes: Potential denial of service security problem here - the 87474462Salfred * locks to be released are specified by a host name, independent 87574462Salfred * of the address from which the request has arrived. 87674462Salfred * Should probably be rejected if the named host has been 87774462Salfred * using monitored locks. 87874462Salfred */ 87974462Salfredvoid * 88074462Salfrednlm_free_all_3_svc(arg, rqstp) 88192911Salfred nlm_notify *arg __unused; 88274462Salfred struct svc_req *rqstp; 88374462Salfred{ 88474462Salfred static char dummy; 88574462Salfred 88674462Salfred if (debug_level) 88774462Salfred log_from_addr("nlm_free_all", rqstp); 88874462Salfred return (&dummy); 88974462Salfred} 89074462Salfred 89174462Salfred/* calls for nlm version 4 (NFSv3) */ 89274462Salfred/* nlm_test ---------------------------------------------------------------- */ 89374462Salfred/* 89474462Salfred * Purpose: Test whether a specified lock would be granted if requested 89574462Salfred * Returns: nlm_granted (or error code) 89674462Salfred * Notes: 89774462Salfred */ 89874462Salfrednlm4_testres * 89974462Salfrednlm4_test_4_svc(arg, rqstp) 90074462Salfred nlm4_testargs *arg; 90174462Salfred struct svc_req *rqstp; 90274462Salfred{ 90374462Salfred static nlm4_testres res; 90474462Salfred struct nlm4_holder *holder; 90574462Salfred 90674462Salfred if (debug_level) 90774462Salfred log_from_addr("nlm4_test", rqstp); 90884923Salfred if (debug_level > 5) { 90984923Salfred syslog(LOG_DEBUG, "Locking arguments:\n"); 91084923Salfred log_netobj(&(arg->cookie)); 91184923Salfred syslog(LOG_DEBUG, "Alock arguments:\n"); 91284923Salfred syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name); 91384923Salfred syslog(LOG_DEBUG, "File Handle:\n"); 91484923Salfred log_netobj(&(arg->alock.fh)); 91584923Salfred syslog(LOG_DEBUG, "Owner Handle:\n"); 91684923Salfred log_netobj(&(arg->alock.oh)); 91784923Salfred syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid); 91886319Salfred syslog(LOG_DEBUG, "Lock Offset: %llu\n", 91986319Salfred (unsigned long long)arg->alock.l_offset); 92086319Salfred syslog(LOG_DEBUG, "Lock Length: %llu\n", 92186319Salfred (unsigned long long)arg->alock.l_len); 92284923Salfred syslog(LOG_DEBUG, "Exclusive: %s\n", 92384923Salfred (arg->exclusive ? "true" : "false")); 92484923Salfred } 92574462Salfred 92684923Salfred holder = testlock(&arg->alock, arg->exclusive, LOCK_V4); 92774462Salfred 92874462Salfred /* 92974462Salfred * Copy the cookie from the argument into the result. Note that this 93074462Salfred * is slightly hazardous, as the structure contains a pointer to a 93174462Salfred * malloc()ed buffer that will get freed by the caller. However, the 93274462Salfred * main function transmits the result before freeing the argument 93374462Salfred * so it is in fact safe. 93474462Salfred */ 93574462Salfred res.cookie = arg->cookie; 93674462Salfred if (holder == NULL) { 93774462Salfred res.stat.stat = nlm4_granted; 93874462Salfred } else { 93974462Salfred res.stat.stat = nlm4_denied; 94074462Salfred memcpy(&res.stat.nlm4_testrply_u.holder, holder, 94174462Salfred sizeof(struct nlm4_holder)); 94274462Salfred } 94374462Salfred return (&res); 94474462Salfred} 94574462Salfred 94674462Salfredvoid * 94774462Salfrednlm4_test_msg_4_svc(arg, rqstp) 94874462Salfred nlm4_testargs *arg; 94974462Salfred struct svc_req *rqstp; 95074462Salfred{ 95174462Salfred nlm4_testres res; 95274462Salfred static char dummy; 95374462Salfred struct sockaddr *addr; 95474462Salfred CLIENT *cli; 95574462Salfred int success; 95674462Salfred struct timeval timeo; 95774462Salfred struct nlm4_holder *holder; 95874462Salfred 95974462Salfred if (debug_level) 96074462Salfred log_from_addr("nlm4_test_msg", rqstp); 96174462Salfred 96284923Salfred holder = testlock(&arg->alock, arg->exclusive, LOCK_V4); 96374462Salfred 96474462Salfred res.cookie = arg->cookie; 96574462Salfred if (holder == NULL) { 96674462Salfred res.stat.stat = nlm4_granted; 96774462Salfred } else { 96874462Salfred res.stat.stat = nlm4_denied; 96974462Salfred memcpy(&res.stat.nlm4_testrply_u.holder, holder, 97074462Salfred sizeof(struct nlm4_holder)); 97174462Salfred } 97274462Salfred 97374462Salfred /* 97474462Salfred * nlm_test has different result type to the other operations, so 97574462Salfred * can't use transmit4_result() in this case 97674462Salfred */ 97774462Salfred addr = svc_getrpccaller(rqstp->rq_xprt)->buf; 97874462Salfred if ((cli = get_client(addr, NLM_VERS4)) != NULL) { 97974462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 98074462Salfred timeo.tv_usec = 0; 98174462Salfred 98274462Salfred success = clnt_call(cli, NLM4_TEST_RES, xdr_nlm4_testres, 98374462Salfred &res, xdr_void, &dummy, timeo); 98474462Salfred 98574462Salfred if (debug_level > 2) 98674462Salfred syslog(LOG_DEBUG, "clnt_call returns %d", success); 98774462Salfred } 98874462Salfred return (NULL); 98974462Salfred} 99074462Salfred 99174462Salfred/* nlm_lock ---------------------------------------------------------------- */ 99274462Salfred/* 99374462Salfred * Purposes: Establish a lock 99474462Salfred * Returns: granted, denied or blocked 99574462Salfred * Notes: *** grace period support missing 99674462Salfred */ 99774462Salfrednlm4_res * 99874462Salfrednlm4_lock_4_svc(arg, rqstp) 99974462Salfred nlm4_lockargs *arg; 100074462Salfred struct svc_req *rqstp; 100174462Salfred{ 100274462Salfred static nlm4_res res; 100374462Salfred 100474462Salfred if (debug_level) 100574462Salfred log_from_addr("nlm4_lock", rqstp); 100684923Salfred if (debug_level > 5) { 100784923Salfred syslog(LOG_DEBUG, "Locking arguments:\n"); 100884923Salfred log_netobj(&(arg->cookie)); 100984923Salfred syslog(LOG_DEBUG, "Alock arguments:\n"); 101084923Salfred syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name); 101184923Salfred syslog(LOG_DEBUG, "File Handle:\n"); 101284923Salfred log_netobj(&(arg->alock.fh)); 101384923Salfred syslog(LOG_DEBUG, "Owner Handle:\n"); 101484923Salfred log_netobj(&(arg->alock.oh)); 101584923Salfred syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid); 101686319Salfred syslog(LOG_DEBUG, "Lock Offset: %llu\n", 101786319Salfred (unsigned long long)arg->alock.l_offset); 101886319Salfred syslog(LOG_DEBUG, "Lock Length: %llu\n", 101986319Salfred (unsigned long long)arg->alock.l_len); 102084923Salfred syslog(LOG_DEBUG, "Block: %s\n", (arg->block ? "true" : "false")); 102184923Salfred syslog(LOG_DEBUG, "Exclusive: %s\n", (arg->exclusive ? "true" : "false")); 102284923Salfred syslog(LOG_DEBUG, "Reclaim: %s\n", (arg->reclaim ? "true" : "false")); 102384923Salfred syslog(LOG_DEBUG, "State num: %d\n", arg->state); 102484923Salfred } 102574462Salfred 102674462Salfred /* copy cookie from arg to result. See comment in nlm_test_4() */ 102774462Salfred res.cookie = arg->cookie; 102874462Salfred 102974462Salfred res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_V4); 103074462Salfred return (&res); 103174462Salfred} 103274462Salfred 103374462Salfredvoid * 103474462Salfrednlm4_lock_msg_4_svc(arg, rqstp) 103574462Salfred nlm4_lockargs *arg; 103674462Salfred struct svc_req *rqstp; 103774462Salfred{ 103874462Salfred static nlm4_res res; 103974462Salfred 104074462Salfred if (debug_level) 104174462Salfred log_from_addr("nlm4_lock_msg", rqstp); 104274462Salfred 104374462Salfred res.cookie = arg->cookie; 104474462Salfred res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_ASYNC | LOCK_V4); 104574462Salfred transmit4_result(NLM4_LOCK_RES, &res, 104674462Salfred (struct sockaddr *)svc_getcaller(rqstp->rq_xprt)); 104774462Salfred 104874462Salfred return (NULL); 104974462Salfred} 105074462Salfred 105174462Salfred/* nlm_cancel -------------------------------------------------------------- */ 105274462Salfred/* 105374462Salfred * Purpose: Cancel a blocked lock request 105474462Salfred * Returns: granted or denied 105574462Salfred * Notes: 105674462Salfred */ 105774462Salfrednlm4_res * 105874462Salfrednlm4_cancel_4_svc(arg, rqstp) 105974462Salfred nlm4_cancargs *arg; 106074462Salfred struct svc_req *rqstp; 106174462Salfred{ 106274462Salfred static nlm4_res res; 106374462Salfred 106474462Salfred if (debug_level) 106574462Salfred log_from_addr("nlm4_cancel", rqstp); 106674462Salfred 106774462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 106874462Salfred res.cookie = arg->cookie; 106974462Salfred 107074462Salfred /* 107174462Salfred * Since at present we never return 'nlm_blocked', there can never be 107274462Salfred * a lock to cancel, so this call always fails. 107374462Salfred */ 107474462Salfred res.stat.stat = unlock(&arg->alock, LOCK_CANCEL); 107574462Salfred return (&res); 107674462Salfred} 107774462Salfred 107874462Salfredvoid * 107974462Salfrednlm4_cancel_msg_4_svc(arg, rqstp) 108074462Salfred nlm4_cancargs *arg; 108174462Salfred struct svc_req *rqstp; 108274462Salfred{ 108374462Salfred static nlm4_res res; 108474462Salfred 108574462Salfred if (debug_level) 108674462Salfred log_from_addr("nlm4_cancel_msg", rqstp); 108774462Salfred 108874462Salfred res.cookie = arg->cookie; 108974462Salfred /* 109074462Salfred * Since at present we never return 'nlm_blocked', there can never be 109174462Salfred * a lock to cancel, so this call always fails. 109274462Salfred */ 109374462Salfred res.stat.stat = unlock(&arg->alock, LOCK_CANCEL | LOCK_V4); 109474462Salfred transmit4_result(NLM4_CANCEL_RES, &res, 109574462Salfred (struct sockaddr *)svc_getcaller(rqstp->rq_xprt)); 109674462Salfred return (NULL); 109774462Salfred} 109874462Salfred 109974462Salfred/* nlm_unlock -------------------------------------------------------------- */ 110074462Salfred/* 110174462Salfred * Purpose: Release an existing lock 110274462Salfred * Returns: Always granted, unless during grace period 110374462Salfred * Notes: "no such lock" error condition is ignored, as the 110474462Salfred * protocol uses unreliable UDP datagrams, and may well 110574462Salfred * re-try an unlock that has already succeeded. 110674462Salfred */ 110774462Salfrednlm4_res * 110874462Salfrednlm4_unlock_4_svc(arg, rqstp) 110974462Salfred nlm4_unlockargs *arg; 111074462Salfred struct svc_req *rqstp; 111174462Salfred{ 111274462Salfred static nlm4_res res; 111374462Salfred 111474462Salfred if (debug_level) 111574462Salfred log_from_addr("nlm4_unlock", rqstp); 111674462Salfred 111774462Salfred res.stat.stat = unlock(&arg->alock, LOCK_V4); 111874462Salfred res.cookie = arg->cookie; 111974462Salfred 112074462Salfred return (&res); 112174462Salfred} 112274462Salfred 112374462Salfredvoid * 112474462Salfrednlm4_unlock_msg_4_svc(arg, rqstp) 112574462Salfred nlm4_unlockargs *arg; 112674462Salfred struct svc_req *rqstp; 112774462Salfred{ 112874462Salfred static nlm4_res res; 112974462Salfred 113074462Salfred if (debug_level) 113174462Salfred log_from_addr("nlm4_unlock_msg", rqstp); 113274462Salfred 113374462Salfred res.stat.stat = unlock(&arg->alock, LOCK_V4); 113474462Salfred res.cookie = arg->cookie; 113574462Salfred 113674462Salfred transmit4_result(NLM4_UNLOCK_RES, &res, 113774462Salfred (struct sockaddr *)svc_getcaller(rqstp->rq_xprt)); 113874462Salfred return (NULL); 113974462Salfred} 114074462Salfred 114174462Salfred/* ------------------------------------------------------------------------- */ 114274462Salfred/* 114374462Salfred * Client-side pseudo-RPCs for results. Note that for the client there 114474462Salfred * are only nlm_xxx_msg() versions of each call, since the 'real RPC' 114574462Salfred * version returns the results in the RPC result, and so the client 114674462Salfred * does not normally receive incoming RPCs. 114774462Salfred * 114874462Salfred * The exception to this is nlm_granted(), which is genuinely an RPC 114974462Salfred * call from the server to the client - a 'call-back' in normal procedure 115074462Salfred * call terms. 115174462Salfred */ 115274462Salfred 115374462Salfred/* nlm_granted ------------------------------------------------------------- */ 115474462Salfred/* 115574462Salfred * Purpose: Receive notification that formerly blocked lock now granted 115674462Salfred * Returns: always success ('granted') 115774462Salfred * Notes: 115874462Salfred */ 115974462Salfrednlm4_res * 116074462Salfrednlm4_granted_4_svc(arg, rqstp) 116174462Salfred nlm4_testargs *arg; 116274462Salfred struct svc_req *rqstp; 116374462Salfred{ 116474462Salfred static nlm4_res res; 116574462Salfred 116674462Salfred if (debug_level) 116774462Salfred log_from_addr("nlm4_granted", rqstp); 116874462Salfred 116975631Salfred res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 117075631Salfred nlm4_granted, NULL, NLM_VERS4) == 0 ? 117175631Salfred nlm4_granted : nlm4_denied; 117275631Salfred 117374462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 117474462Salfred res.cookie = arg->cookie; 117574462Salfred 117674462Salfred return (&res); 117774462Salfred} 117874462Salfred 117974462Salfredvoid * 118074462Salfrednlm4_granted_msg_4_svc(arg, rqstp) 118174462Salfred nlm4_testargs *arg; 118274462Salfred struct svc_req *rqstp; 118374462Salfred{ 118474462Salfred static nlm4_res res; 118574462Salfred 118674462Salfred if (debug_level) 118774462Salfred log_from_addr("nlm4_granted_msg", rqstp); 118874462Salfred 118974462Salfred res.cookie = arg->cookie; 1190114993Srwatson res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 1191114993Srwatson nlm4_granted, NULL, NLM_VERS4) == 0 ? 1192114993Srwatson nlm4_granted : nlm4_denied; 119374462Salfred transmit4_result(NLM4_GRANTED_RES, &res, 119474462Salfred (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf); 119574462Salfred return (NULL); 119674462Salfred} 119774462Salfred 119874462Salfred/* nlm_test_res ------------------------------------------------------------ */ 119974462Salfred/* 120074462Salfred * Purpose: Accept result from earlier nlm_test_msg() call 120174462Salfred * Returns: Nothing 120274462Salfred */ 120374462Salfredvoid * 120474462Salfrednlm4_test_res_4_svc(arg, rqstp) 120574462Salfred nlm4_testres *arg; 120674462Salfred struct svc_req *rqstp; 120774462Salfred{ 120874462Salfred if (debug_level) 120974462Salfred log_from_addr("nlm4_test_res", rqstp); 121075631Salfred 121175631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, 121275631Salfred (int *)&arg->stat.nlm4_testrply_u.holder.svid, 121375631Salfred NLM_VERS4); 121474462Salfred return (NULL); 121574462Salfred} 121674462Salfred 121774462Salfred/* nlm_lock_res ------------------------------------------------------------ */ 121874462Salfred/* 121974462Salfred * Purpose: Accept result from earlier nlm_lock_msg() call 122074462Salfred * Returns: Nothing 122174462Salfred */ 122274462Salfredvoid * 122374462Salfrednlm4_lock_res_4_svc(arg, rqstp) 122474462Salfred nlm4_res *arg; 122574462Salfred struct svc_req *rqstp; 122674462Salfred{ 122774462Salfred if (debug_level) 122874462Salfred log_from_addr("nlm4_lock_res", rqstp); 122974462Salfred 123075631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS4); 123175631Salfred 123274462Salfred return (NULL); 123374462Salfred} 123474462Salfred 123574462Salfred/* nlm_cancel_res ---------------------------------------------------------- */ 123674462Salfred/* 123774462Salfred * Purpose: Accept result from earlier nlm_cancel_msg() call 123874462Salfred * Returns: Nothing 123974462Salfred */ 124074462Salfredvoid * 124174462Salfrednlm4_cancel_res_4_svc(arg, rqstp) 124292911Salfred nlm4_res *arg __unused; 124374462Salfred struct svc_req *rqstp; 124474462Salfred{ 124574462Salfred if (debug_level) 124674462Salfred log_from_addr("nlm4_cancel_res", rqstp); 124774462Salfred return (NULL); 124874462Salfred} 124974462Salfred 125074462Salfred/* nlm_unlock_res ---------------------------------------------------------- */ 125174462Salfred/* 125274462Salfred * Purpose: Accept result from earlier nlm_unlock_msg() call 125374462Salfred * Returns: Nothing 125474462Salfred */ 125574462Salfredvoid * 125674462Salfrednlm4_unlock_res_4_svc(arg, rqstp) 125792911Salfred nlm4_res *arg __unused; 125874462Salfred struct svc_req *rqstp; 125974462Salfred{ 126074462Salfred if (debug_level) 126174462Salfred log_from_addr("nlm4_unlock_res", rqstp); 126274462Salfred return (NULL); 126374462Salfred} 126474462Salfred 126574462Salfred/* nlm_granted_res --------------------------------------------------------- */ 126674462Salfred/* 126774462Salfred * Purpose: Accept result from earlier nlm_granted_msg() call 126874462Salfred * Returns: Nothing 126974462Salfred */ 127074462Salfredvoid * 127174462Salfrednlm4_granted_res_4_svc(arg, rqstp) 127292911Salfred nlm4_res *arg __unused; 127374462Salfred struct svc_req *rqstp; 127474462Salfred{ 127574462Salfred if (debug_level) 127674462Salfred log_from_addr("nlm4_granted_res", rqstp); 127774462Salfred return (NULL); 127874462Salfred} 127974462Salfred 128074462Salfred/* ------------------------------------------------------------------------- */ 128174462Salfred/* 128274462Salfred * Calls for PCNFS locking (aka non-monitored locking, no involvement 128374462Salfred * of rpc.statd). 128474462Salfred * 128574462Salfred * These are all genuine RPCs - no nlm_xxx_msg() nonsense here. 128674462Salfred */ 128774462Salfred 128874462Salfred/* nlm_share --------------------------------------------------------------- */ 128974462Salfred/* 129074462Salfred * Purpose: Establish a DOS-style lock 129174462Salfred * Returns: success or failure 129274462Salfred * Notes: Blocking locks are not supported - client is expected 129374462Salfred * to retry if required. 129474462Salfred */ 129574462Salfrednlm4_shareres * 129674462Salfrednlm4_share_4_svc(arg, rqstp) 129774462Salfred nlm4_shareargs *arg; 129874462Salfred struct svc_req *rqstp; 129974462Salfred{ 130074462Salfred static nlm4_shareres res; 130174462Salfred 130274462Salfred if (debug_level) 130374462Salfred log_from_addr("nlm4_share", rqstp); 130474462Salfred 130574462Salfred res.cookie = arg->cookie; 130674462Salfred res.stat = nlm4_granted; 130774462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 130874462Salfred return (&res); 130974462Salfred} 131074462Salfred 131174462Salfred/* nlm4_unshare ------------------------------------------------------------ */ 131274462Salfred/* 131374462Salfred * Purpose: Release a DOS-style lock 131474462Salfred * Returns: nlm_granted, unless in grace period 131574462Salfred * Notes: 131674462Salfred */ 131774462Salfrednlm4_shareres * 131874462Salfrednlm4_unshare_4_svc(arg, rqstp) 131974462Salfred nlm4_shareargs *arg; 132074462Salfred struct svc_req *rqstp; 132174462Salfred{ 132274462Salfred static nlm4_shareres res; 132374462Salfred 132474462Salfred if (debug_level) 132574462Salfred log_from_addr("nlm_unshare", rqstp); 132674462Salfred 132774462Salfred res.cookie = arg->cookie; 132874462Salfred res.stat = nlm4_granted; 132974462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 133074462Salfred return (&res); 133174462Salfred} 133274462Salfred 133374462Salfred/* nlm4_nm_lock ------------------------------------------------------------ */ 133474462Salfred/* 133574462Salfred * Purpose: non-monitored version of nlm4_lock() 133674462Salfred * Returns: as for nlm4_lock() 133774462Salfred * Notes: These locks are in the same style as the standard nlm4_lock, 133874462Salfred * but the rpc.statd should not be called to establish a 133974462Salfred * monitor for the client machine, since that machine is 134074462Salfred * declared not to be running a rpc.statd, and so would not 134174462Salfred * respond to the statd protocol. 134274462Salfred */ 134374462Salfrednlm4_res * 134474462Salfrednlm4_nm_lock_4_svc(arg, rqstp) 134574462Salfred nlm4_lockargs *arg; 134674462Salfred struct svc_req *rqstp; 134774462Salfred{ 134874462Salfred static nlm4_res res; 134974462Salfred 135074462Salfred if (debug_level) 135174462Salfred log_from_addr("nlm4_nm_lock", rqstp); 135274462Salfred 135374462Salfred /* copy cookie from arg to result. See comment in nlm4_test_1() */ 135474462Salfred res.cookie = arg->cookie; 135574462Salfred res.stat.stat = nlm4_granted; 135674462Salfred return (&res); 135774462Salfred} 135874462Salfred 135974462Salfred/* nlm4_free_all ------------------------------------------------------------ */ 136074462Salfred/* 136174462Salfred * Purpose: Release all locks held by a named client 136274462Salfred * Returns: Nothing 136374462Salfred * Notes: Potential denial of service security problem here - the 136474462Salfred * locks to be released are specified by a host name, independent 136574462Salfred * of the address from which the request has arrived. 136674462Salfred * Should probably be rejected if the named host has been 136774462Salfred * using monitored locks. 136874462Salfred */ 136974462Salfredvoid * 137074462Salfrednlm4_free_all_4_svc(arg, rqstp) 137192911Salfred struct nlm4_notify *arg __unused; 137274462Salfred struct svc_req *rqstp; 137374462Salfred{ 137474462Salfred static char dummy; 137574462Salfred 137674462Salfred if (debug_level) 137774462Salfred log_from_addr("nlm4_free_all", rqstp); 137874462Salfred return (&dummy); 137974462Salfred} 138074462Salfred 138174462Salfred/* nlm_sm_notify --------------------------------------------------------- */ 138274462Salfred/* 138374462Salfred * Purpose: called by rpc.statd when a monitored host state changes. 138474462Salfred * Returns: Nothing 138574462Salfred */ 138674462Salfredvoid * 138774462Salfrednlm_sm_notify_0_svc(arg, rqstp) 138874462Salfred struct nlm_sm_status *arg; 138992911Salfred struct svc_req *rqstp __unused; 139074462Salfred{ 139174462Salfred static char dummy; 139274462Salfred notify(arg->mon_name, arg->state); 139374462Salfred return (&dummy); 139474462Salfred} 1395