174462Salfred/* $NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $ */ 274462Salfred/* $FreeBSD$ */ 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 7974462Salfredlog_from_addr(fun_name, req) 8092969Salfred const char *fun_name; 8174462Salfred struct svc_req *req; 8274462Salfred{ 8374462Salfred struct sockaddr *addr; 8474462Salfred char hostname_buf[NI_MAXHOST]; 8574462Salfred 8674462Salfred addr = svc_getrpccaller(req->rq_xprt)->buf; 8774462Salfred if (getnameinfo(addr , addr->sa_len, hostname_buf, sizeof hostname_buf, 8874462Salfred NULL, 0, 0) != 0) 8974462Salfred return; 9074462Salfred 9174462Salfred syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf); 9274462Salfred} 9374462Salfred 9484923Salfred/* log_netobj ----------------------------------------------------------- */ 9584923Salfred/* 9684923Salfred * Purpose: Log a netobj 9784923Salfred * Returns: Nothing 9884923Salfred * Notes: This function should only really be called as part of 9984923Salfred * a debug subsystem. 10084923Salfred*/ 10184923Salfredstatic void 10284923Salfredlog_netobj(obj) 10384923Salfred netobj *obj; 10484923Salfred{ 10584923Salfred char objvalbuffer[(sizeof(char)*2)*MAX_NETOBJ_SZ+2]; 10684923Salfred char objascbuffer[sizeof(char)*MAX_NETOBJ_SZ+1]; 10786319Salfred unsigned int i, maxlen; 10884923Salfred char *tmp1, *tmp2; 10984923Salfred 11084923Salfred /* Notify of potential security attacks */ 11184923Salfred if (obj->n_len > MAX_NETOBJ_SZ) { 11284923Salfred syslog(LOG_DEBUG, "SOMEONE IS TRYING TO DO SOMETHING NASTY!\n"); 11384923Salfred syslog(LOG_DEBUG, "netobj too large! Should be %d was %d\n", 11484923Salfred MAX_NETOBJ_SZ, obj->n_len); 11584923Salfred } 11684923Salfred /* Prevent the security hazard from the buffer overflow */ 11784923Salfred maxlen = (obj->n_len < MAX_NETOBJ_SZ ? obj->n_len : MAX_NETOBJ_SZ); 11884923Salfred for (i=0, tmp1 = objvalbuffer, tmp2 = objascbuffer; i < obj->n_len; 11984923Salfred i++, tmp1 +=2, tmp2 +=1) { 12084923Salfred sprintf(tmp1,"%02X",*(obj->n_bytes+i)); 12184923Salfred sprintf(tmp2,"%c",*(obj->n_bytes+i)); 12284923Salfred } 12384923Salfred *tmp1 = '\0'; 12484923Salfred *tmp2 = '\0'; 12584923Salfred syslog(LOG_DEBUG,"netobjvals: %s\n",objvalbuffer); 12684923Salfred syslog(LOG_DEBUG,"netobjascs: %s\n",objascbuffer); 12784923Salfred} 12874462Salfred/* get_client -------------------------------------------------------------- */ 12974462Salfred/* 13074462Salfred * Purpose: Get a CLIENT* for making RPC calls to lockd on given host 13174462Salfred * Returns: CLIENT* pointer, from clnt_udp_create, or NULL if error 13274462Salfred * Notes: Creating a CLIENT* is quite expensive, involving a 13374462Salfred * conversation with the remote portmapper to get the 13474462Salfred * port number. Since a given client is quite likely 13574462Salfred * to make several locking requests in succession, it is 13674462Salfred * desirable to cache the created CLIENT*. 13774462Salfred * 13874462Salfred * Since we are using UDP rather than TCP, there is no cost 13974462Salfred * to the remote system in keeping these cached indefinitely. 14074462Salfred * Unfortunately there is a snag: if the remote system 14174462Salfred * reboots, the cached portmapper results will be invalid, 14274462Salfred * and we will never detect this since all of the xxx_msg() 14374462Salfred * calls return no result - we just fire off a udp packet 14474462Salfred * and hope for the best. 14574462Salfred * 14674462Salfred * We solve this by discarding cached values after two 14774462Salfred * minutes, regardless of whether they have been used 14874462Salfred * in the meanwhile (since a bad one might have been used 14974462Salfred * plenty of times, as the host keeps retrying the request 15074462Salfred * and we keep sending the reply back to the wrong port). 15174462Salfred * 15274462Salfred * Given that the entries will always expire in the order 15374462Salfred * that they were created, there is no point in a LRU 15474462Salfred * algorithm for when the cache gets full - entries are 15574462Salfred * always re-used in sequence. 15674462Salfred */ 15774462Salfredstatic CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE]; 15874462Salfredstatic long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */ 15974462Salfredstatic struct sockaddr_storage clnt_cache_addr[CLIENT_CACHE_SIZE]; 16076093Salfredstatic rpcvers_t clnt_cache_vers[CLIENT_CACHE_SIZE]; 16174462Salfredstatic int clnt_cache_next_to_use = 0; 16274462Salfred 16374462Salfredstatic int 16474462Salfredaddrcmp(sa1, sa2) 16574462Salfred struct sockaddr *sa1; 16674462Salfred struct sockaddr *sa2; 16774462Salfred{ 16874462Salfred int len; 16974462Salfred void *p1, *p2; 17074462Salfred 17174462Salfred if (sa1->sa_family != sa2->sa_family) 17274462Salfred return -1; 17374462Salfred 17474462Salfred switch (sa1->sa_family) { 17574462Salfred case AF_INET: 17674462Salfred p1 = &((struct sockaddr_in *)sa1)->sin_addr; 17774462Salfred p2 = &((struct sockaddr_in *)sa2)->sin_addr; 17874462Salfred len = 4; 17974462Salfred break; 18074462Salfred case AF_INET6: 18174462Salfred p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr; 18274462Salfred p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr; 18374462Salfred len = 16; 18474462Salfred break; 18574462Salfred default: 18674462Salfred return -1; 18774462Salfred } 18874462Salfred 18974462Salfred return memcmp(p1, p2, len); 19074462Salfred} 19174462Salfred 19274462SalfredCLIENT * 19374462Salfredget_client(host_addr, vers) 19474462Salfred struct sockaddr *host_addr; 19574462Salfred rpcvers_t vers; 19674462Salfred{ 19774462Salfred CLIENT *client; 19874462Salfred struct timeval retry_time, time_now; 199141217Skuriyama int error, i; 20092977Salfred const char *netid; 20174462Salfred struct netconfig *nconf; 20274462Salfred char host[NI_MAXHOST]; 203126606Sroam uid_t old_euid; 204126606Sroam int clnt_fd; 20574462Salfred 20674462Salfred gettimeofday(&time_now, NULL); 20774462Salfred 20874462Salfred /* 20974462Salfred * Search for the given client in the cache, zapping any expired 21074462Salfred * entries that we happen to notice in passing. 21174462Salfred */ 21274462Salfred for (i = 0; i < CLIENT_CACHE_SIZE; i++) { 21374462Salfred client = clnt_cache_ptr[i]; 21474462Salfred if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME) 21574462Salfred < time_now.tv_sec)) { 21674462Salfred /* Cache entry has expired. */ 21774462Salfred if (debug_level > 3) 21874462Salfred syslog(LOG_DEBUG, "Expired CLIENT* in cache"); 21974462Salfred clnt_cache_time[i] = 0L; 22074462Salfred clnt_destroy(client); 22174462Salfred clnt_cache_ptr[i] = NULL; 22274462Salfred client = NULL; 22374462Salfred } 22474462Salfred if (client && !addrcmp((struct sockaddr *)&clnt_cache_addr[i], 22576093Salfred host_addr) && clnt_cache_vers[i] == vers) { 22674462Salfred /* Found it! */ 22774462Salfred if (debug_level > 3) 22874462Salfred syslog(LOG_DEBUG, "Found CLIENT* in cache"); 22974462Salfred return (client); 23074462Salfred } 23174462Salfred } 23274462Salfred 23376093Salfred if (debug_level > 3) 23476093Salfred syslog(LOG_DEBUG, "CLIENT* not found in cache, creating"); 23576093Salfred 23674462Salfred /* Not found in cache. Free the next entry if it is in use. */ 23774462Salfred if (clnt_cache_ptr[clnt_cache_next_to_use]) { 23874462Salfred clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]); 23974462Salfred clnt_cache_ptr[clnt_cache_next_to_use] = NULL; 24074462Salfred } 24174462Salfred 24274462Salfred /* 24374462Salfred * Need a host string for clnt_tp_create. Use NI_NUMERICHOST 24474462Salfred * to avoid DNS lookups. 24574462Salfred */ 246141217Skuriyama error = getnameinfo(host_addr, host_addr->sa_len, host, sizeof host, 247141217Skuriyama NULL, 0, NI_NUMERICHOST); 248141217Skuriyama if (error != 0) { 249141217Skuriyama syslog(LOG_ERR, "unable to get name string for caller: %s", 250141217Skuriyama gai_strerror(error)); 25174462Salfred return NULL; 25274462Salfred } 25374462Salfred 25474462Salfred#if 1 25574462Salfred if (host_addr->sa_family == AF_INET6) 25674462Salfred netid = "udp6"; 25774462Salfred else 25874462Salfred netid = "udp"; 25974462Salfred#else 26074462Salfred if (host_addr->sa_family == AF_INET6) 26174462Salfred netid = "tcp6"; 26274462Salfred else 26374462Salfred netid = "tcp"; 26474462Salfred#endif 26574462Salfred nconf = getnetconfigent(netid); 26674462Salfred if (nconf == NULL) { 26774462Salfred syslog(LOG_ERR, "could not get netconfig info for '%s': " 26874462Salfred "no /etc/netconfig file?", netid); 26974462Salfred return NULL; 27074462Salfred } 27174462Salfred 27274462Salfred client = clnt_tp_create(host, NLM_PROG, vers, nconf); 27374462Salfred freenetconfigent(nconf); 27474462Salfred 27574462Salfred if (!client) { 27674462Salfred syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create")); 27774462Salfred syslog(LOG_ERR, "Unable to return result to %s", host); 27874462Salfred return NULL; 27974462Salfred } 28074462Salfred 281126606Sroam /* Get the FD of the client, for bindresvport. */ 282126606Sroam clnt_control(client, CLGET_FD, &clnt_fd); 283126606Sroam 284126606Sroam /* Regain root privileges, for bindresvport. */ 285126606Sroam old_euid = geteuid(); 286126606Sroam seteuid(0); 287126606Sroam 288126606Sroam /* 289126606Sroam * Bind the client FD to a reserved port. 290126606Sroam * Some NFS servers reject any NLM request from a non-reserved port. 291126606Sroam */ 292126606Sroam bindresvport(clnt_fd, NULL); 293126606Sroam 294126606Sroam /* Drop root privileges again. */ 295126606Sroam seteuid(old_euid); 296126606Sroam 29774462Salfred /* Success - update the cache entry */ 29874462Salfred clnt_cache_ptr[clnt_cache_next_to_use] = client; 29974462Salfred memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr, 30074462Salfred host_addr->sa_len); 30176093Salfred clnt_cache_vers[clnt_cache_next_to_use] = vers; 30274462Salfred clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec; 303132254Smr if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE) 30474462Salfred clnt_cache_next_to_use = 0; 30574462Salfred 30674462Salfred /* 30774462Salfred * Disable the default timeout, so we can specify our own in calls 30874462Salfred * to clnt_call(). (Note that the timeout is a different concept 30974462Salfred * from the retry period set in clnt_udp_create() above.) 31074462Salfred */ 31174462Salfred retry_time.tv_sec = -1; 31274462Salfred retry_time.tv_usec = -1; 31374462Salfred clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time); 31474462Salfred 31574462Salfred if (debug_level > 3) 31674462Salfred syslog(LOG_DEBUG, "Created CLIENT* for %s", host); 31774462Salfred return client; 31874462Salfred} 31974462Salfred 32074462Salfred 32174462Salfred/* transmit_result --------------------------------------------------------- */ 32274462Salfred/* 32374462Salfred * Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs 32474462Salfred * Returns: Nothing - we have no idea if the datagram got there 32574462Salfred * Notes: clnt_call() will always fail (with timeout) as we are 32674462Salfred * calling it with timeout 0 as a hack to just issue a datagram 32774462Salfred * without expecting a result 32874462Salfred */ 32974462Salfredvoid 33074462Salfredtransmit_result(opcode, result, addr) 33174462Salfred int opcode; 33274462Salfred nlm_res *result; 33374462Salfred struct sockaddr *addr; 33474462Salfred{ 33574462Salfred static char dummy; 33674462Salfred CLIENT *cli; 33774462Salfred struct timeval timeo; 33874462Salfred int success; 33974462Salfred 34074462Salfred if ((cli = get_client(addr, NLM_VERS)) != NULL) { 34174462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 34274462Salfred timeo.tv_usec = 0; 34374462Salfred 344121558Speter success = clnt_call(cli, opcode, (xdrproc_t)xdr_nlm_res, result, 345121558Speter (xdrproc_t)xdr_void, &dummy, timeo); 34674462Salfred 34774462Salfred if (debug_level > 2) 34874462Salfred syslog(LOG_DEBUG, "clnt_call returns %d(%s)", 34974462Salfred success, clnt_sperrno(success)); 35074462Salfred } 35174462Salfred} 35274462Salfred/* transmit4_result --------------------------------------------------------- */ 35374462Salfred/* 35474462Salfred * Purpose: Transmit result for nlm4_xxx_msg pseudo-RPCs 35574462Salfred * Returns: Nothing - we have no idea if the datagram got there 35674462Salfred * Notes: clnt_call() will always fail (with timeout) as we are 35774462Salfred * calling it with timeout 0 as a hack to just issue a datagram 35874462Salfred * without expecting a result 35974462Salfred */ 36074462Salfredvoid 36174462Salfredtransmit4_result(opcode, result, addr) 36274462Salfred int opcode; 36374462Salfred nlm4_res *result; 36474462Salfred struct sockaddr *addr; 36574462Salfred{ 36674462Salfred static char dummy; 36774462Salfred CLIENT *cli; 36874462Salfred struct timeval timeo; 36974462Salfred int success; 37074462Salfred 37174462Salfred if ((cli = get_client(addr, NLM_VERS4)) != NULL) { 37274462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 37374462Salfred timeo.tv_usec = 0; 37474462Salfred 375121558Speter success = clnt_call(cli, opcode, 376121558Speter (xdrproc_t)xdr_nlm4_res, result, 377121558Speter (xdrproc_t)xdr_void, &dummy, timeo); 37874462Salfred 37974462Salfred if (debug_level > 2) 38074462Salfred syslog(LOG_DEBUG, "clnt_call returns %d(%s)", 38174462Salfred success, clnt_sperrno(success)); 38274462Salfred } 38374462Salfred} 38474462Salfred 38574462Salfred/* 38674462Salfred * converts a struct nlm_lock to struct nlm4_lock 38774462Salfred */ 38892909Salfredstatic void nlmtonlm4(struct nlm_lock *, struct nlm4_lock *); 38974462Salfredstatic void 39074462Salfrednlmtonlm4(arg, arg4) 39174462Salfred struct nlm_lock *arg; 39274462Salfred struct nlm4_lock *arg4; 39374462Salfred{ 394132254Smr arg4->caller_name = arg->caller_name; 395132254Smr arg4->fh = arg->fh; 396132254Smr arg4->oh = arg->oh; 397132254Smr arg4->svid = arg->svid; 39874462Salfred arg4->l_offset = arg->l_offset; 39974462Salfred arg4->l_len = arg->l_len; 40074462Salfred} 40174462Salfred/* ------------------------------------------------------------------------- */ 40274462Salfred/* 40374462Salfred * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd 40474462Salfred * involved to ensure reclaim of locks after a crash of the "stateless" 40574462Salfred * server. 40674462Salfred * 40774462Salfred * These all come in two flavours - nlm_xxx() and nlm_xxx_msg(). 40874462Salfred * The first are standard RPCs with argument and result. 40974462Salfred * The nlm_xxx_msg() calls implement exactly the same functions, but 41074462Salfred * use two pseudo-RPCs (one in each direction). These calls are NOT 41174462Salfred * standard use of the RPC protocol in that they do not return a result 41274462Salfred * at all (NB. this is quite different from returning a void result). 41374462Salfred * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged 41474462Salfred * datagrams, requiring higher-level code to perform retries. 41574462Salfred * 41674462Salfred * Despite the disadvantages of the nlm_xxx_msg() approach (some of which 41774462Salfred * are documented in the comments to get_client() above), this is the 41874462Salfred * interface used by all current commercial NFS implementations 41974462Salfred * [Solaris, SCO, AIX etc.]. This is presumed to be because these allow 42074462Salfred * implementations to continue using the standard RPC libraries, while 42174462Salfred * avoiding the block-until-result nature of the library interface. 42274462Salfred * 42374462Salfred * No client implementations have been identified so far that make use 42474462Salfred * of the true RPC version (early SunOS releases would be a likely candidate 42574462Salfred * for testing). 42674462Salfred */ 42774462Salfred 42874462Salfred/* nlm_test ---------------------------------------------------------------- */ 42974462Salfred/* 43074462Salfred * Purpose: Test whether a specified lock would be granted if requested 43174462Salfred * Returns: nlm_granted (or error code) 43274462Salfred * Notes: 43374462Salfred */ 43474462Salfrednlm_testres * 43574462Salfrednlm_test_1_svc(arg, rqstp) 43674462Salfred nlm_testargs *arg; 43774462Salfred struct svc_req *rqstp; 43874462Salfred{ 43974462Salfred static nlm_testres res; 44074462Salfred struct nlm4_lock arg4; 44174462Salfred struct nlm4_holder *holder; 44274462Salfred nlmtonlm4(&arg->alock, &arg4); 44374462Salfred 44474462Salfred if (debug_level) 44574462Salfred log_from_addr("nlm_test", rqstp); 44674462Salfred 44784923Salfred holder = testlock(&arg4, arg->exclusive, 0); 44874462Salfred /* 44974462Salfred * Copy the cookie from the argument into the result. Note that this 45074462Salfred * is slightly hazardous, as the structure contains a pointer to a 45174462Salfred * malloc()ed buffer that will get freed by the caller. However, the 45274462Salfred * main function transmits the result before freeing the argument 45374462Salfred * so it is in fact safe. 45474462Salfred */ 45574462Salfred res.cookie = arg->cookie; 45674462Salfred if (holder == NULL) { 45774462Salfred res.stat.stat = nlm_granted; 45874462Salfred } else { 45974462Salfred res.stat.stat = nlm_denied; 46074462Salfred memcpy(&res.stat.nlm_testrply_u.holder, holder, 46174462Salfred sizeof(struct nlm_holder)); 46274462Salfred res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset; 46374462Salfred res.stat.nlm_testrply_u.holder.l_len = holder->l_len; 46474462Salfred } 46574462Salfred return (&res); 46674462Salfred} 46774462Salfred 46874462Salfredvoid * 46974462Salfrednlm_test_msg_1_svc(arg, rqstp) 47074462Salfred nlm_testargs *arg; 47174462Salfred struct svc_req *rqstp; 47274462Salfred{ 47374462Salfred nlm_testres res; 47474462Salfred static char dummy; 47574462Salfred struct sockaddr *addr; 47674462Salfred CLIENT *cli; 47774462Salfred int success; 47874462Salfred struct timeval timeo; 47974462Salfred struct nlm4_lock arg4; 48074462Salfred struct nlm4_holder *holder; 48174462Salfred 48274462Salfred nlmtonlm4(&arg->alock, &arg4); 48374462Salfred 48474462Salfred if (debug_level) 48574462Salfred log_from_addr("nlm_test_msg", rqstp); 48674462Salfred 48784923Salfred holder = testlock(&arg4, arg->exclusive, 0); 48874462Salfred 48974462Salfred res.cookie = arg->cookie; 49074462Salfred if (holder == NULL) { 49174462Salfred res.stat.stat = nlm_granted; 49274462Salfred } else { 49374462Salfred res.stat.stat = nlm_denied; 49474462Salfred memcpy(&res.stat.nlm_testrply_u.holder, holder, 49574462Salfred sizeof(struct nlm_holder)); 49674462Salfred res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset; 49774462Salfred res.stat.nlm_testrply_u.holder.l_len = holder->l_len; 49874462Salfred } 49974462Salfred 50074462Salfred /* 50174462Salfred * nlm_test has different result type to the other operations, so 50274462Salfred * can't use transmit_result() in this case 50374462Salfred */ 50474462Salfred addr = svc_getrpccaller(rqstp->rq_xprt)->buf; 50574462Salfred if ((cli = get_client(addr, NLM_VERS)) != NULL) { 50674462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 50774462Salfred timeo.tv_usec = 0; 50874462Salfred 509121558Speter success = clnt_call(cli, NLM_TEST_RES, 510121558Speter (xdrproc_t)xdr_nlm_testres, &res, 511121558Speter (xdrproc_t)xdr_void, &dummy, timeo); 51274462Salfred 51374462Salfred if (debug_level > 2) 51474462Salfred syslog(LOG_DEBUG, "clnt_call returns %d", success); 51574462Salfred } 51674462Salfred return (NULL); 51774462Salfred} 51874462Salfred 51974462Salfred/* nlm_lock ---------------------------------------------------------------- */ 52074462Salfred/* 52174462Salfred * Purposes: Establish a lock 52274462Salfred * Returns: granted, denied or blocked 52374462Salfred * Notes: *** grace period support missing 52474462Salfred */ 52574462Salfrednlm_res * 52674462Salfrednlm_lock_1_svc(arg, rqstp) 52774462Salfred nlm_lockargs *arg; 52874462Salfred struct svc_req *rqstp; 52974462Salfred{ 53074462Salfred static nlm_res res; 53174462Salfred struct nlm4_lockargs arg4; 53274462Salfred nlmtonlm4(&arg->alock, &arg4.alock); 53374462Salfred arg4.cookie = arg->cookie; 53474462Salfred arg4.block = arg->block; 53574462Salfred arg4.exclusive = arg->exclusive; 53674462Salfred arg4.reclaim = arg->reclaim; 53774462Salfred arg4.state = arg->state; 53874462Salfred 53974462Salfred if (debug_level) 54074462Salfred log_from_addr("nlm_lock", rqstp); 54174462Salfred 54274462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 54374462Salfred res.cookie = arg->cookie; 54474462Salfred 54574462Salfred res.stat.stat = getlock(&arg4, rqstp, LOCK_MON); 54674462Salfred return (&res); 54774462Salfred} 54874462Salfred 54974462Salfredvoid * 55074462Salfrednlm_lock_msg_1_svc(arg, rqstp) 55174462Salfred nlm_lockargs *arg; 55274462Salfred struct svc_req *rqstp; 55374462Salfred{ 55474462Salfred static nlm_res res; 55574462Salfred struct nlm4_lockargs arg4; 55674462Salfred 55774462Salfred nlmtonlm4(&arg->alock, &arg4.alock); 55874462Salfred arg4.cookie = arg->cookie; 55974462Salfred arg4.block = arg->block; 56074462Salfred arg4.exclusive = arg->exclusive; 56174462Salfred arg4.reclaim = arg->reclaim; 56274462Salfred arg4.state = arg->state; 56374462Salfred 56474462Salfred if (debug_level) 56574462Salfred log_from_addr("nlm_lock_msg", rqstp); 56674462Salfred 56774462Salfred res.cookie = arg->cookie; 56874462Salfred res.stat.stat = getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON); 569141217Skuriyama transmit_result(NLM_LOCK_RES, &res, getrpcaddr(rqstp)); 57074462Salfred 57174462Salfred return (NULL); 57274462Salfred} 57374462Salfred 57474462Salfred/* nlm_cancel -------------------------------------------------------------- */ 57574462Salfred/* 57674462Salfred * Purpose: Cancel a blocked lock request 57774462Salfred * Returns: granted or denied 57874462Salfred * Notes: 57974462Salfred */ 58074462Salfrednlm_res * 58174462Salfrednlm_cancel_1_svc(arg, rqstp) 58274462Salfred nlm_cancargs *arg; 58374462Salfred struct svc_req *rqstp; 58474462Salfred{ 58574462Salfred static nlm_res res; 58674462Salfred struct nlm4_lock arg4; 58774462Salfred 58874462Salfred nlmtonlm4(&arg->alock, &arg4); 58974462Salfred 59074462Salfred if (debug_level) 59174462Salfred log_from_addr("nlm_cancel", rqstp); 59274462Salfred 59374462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 59474462Salfred res.cookie = arg->cookie; 59574462Salfred 59674462Salfred /* 59774462Salfred * Since at present we never return 'nlm_blocked', there can never be 59874462Salfred * a lock to cancel, so this call always fails. 59974462Salfred */ 60074462Salfred res.stat.stat = unlock(&arg4, LOCK_CANCEL); 60174462Salfred return (&res); 60274462Salfred} 60374462Salfred 60474462Salfredvoid * 60574462Salfrednlm_cancel_msg_1_svc(arg, rqstp) 60674462Salfred nlm_cancargs *arg; 60774462Salfred struct svc_req *rqstp; 60874462Salfred{ 60974462Salfred static nlm_res res; 61074462Salfred struct nlm4_lock arg4; 61174462Salfred 61274462Salfred nlmtonlm4(&arg->alock, &arg4); 61374462Salfred 61474462Salfred if (debug_level) 61574462Salfred log_from_addr("nlm_cancel_msg", rqstp); 61674462Salfred 61774462Salfred res.cookie = arg->cookie; 61874462Salfred /* 61974462Salfred * Since at present we never return 'nlm_blocked', there can never be 62074462Salfred * a lock to cancel, so this call always fails. 62174462Salfred */ 62274462Salfred res.stat.stat = unlock(&arg4, LOCK_CANCEL); 623141217Skuriyama transmit_result(NLM_CANCEL_RES, &res, getrpcaddr(rqstp)); 62474462Salfred return (NULL); 62574462Salfred} 62674462Salfred 62774462Salfred/* nlm_unlock -------------------------------------------------------------- */ 62874462Salfred/* 62974462Salfred * Purpose: Release an existing lock 63074462Salfred * Returns: Always granted, unless during grace period 63174462Salfred * Notes: "no such lock" error condition is ignored, as the 63274462Salfred * protocol uses unreliable UDP datagrams, and may well 63374462Salfred * re-try an unlock that has already succeeded. 63474462Salfred */ 63574462Salfrednlm_res * 63674462Salfrednlm_unlock_1_svc(arg, rqstp) 63774462Salfred nlm_unlockargs *arg; 63874462Salfred struct svc_req *rqstp; 63974462Salfred{ 64074462Salfred static nlm_res res; 64174462Salfred struct nlm4_lock arg4; 64274462Salfred 64374462Salfred nlmtonlm4(&arg->alock, &arg4); 64474462Salfred 64574462Salfred if (debug_level) 64674462Salfred log_from_addr("nlm_unlock", rqstp); 64774462Salfred 64874462Salfred res.stat.stat = unlock(&arg4, 0); 64974462Salfred res.cookie = arg->cookie; 65074462Salfred 65174462Salfred return (&res); 65274462Salfred} 65374462Salfred 65474462Salfredvoid * 65574462Salfrednlm_unlock_msg_1_svc(arg, rqstp) 65674462Salfred nlm_unlockargs *arg; 65774462Salfred struct svc_req *rqstp; 65874462Salfred{ 65974462Salfred static nlm_res res; 66074462Salfred struct nlm4_lock arg4; 66174462Salfred 66274462Salfred nlmtonlm4(&arg->alock, &arg4); 66374462Salfred 66474462Salfred if (debug_level) 66574462Salfred log_from_addr("nlm_unlock_msg", rqstp); 66674462Salfred 66774462Salfred res.stat.stat = unlock(&arg4, 0); 66874462Salfred res.cookie = arg->cookie; 66974462Salfred 670141217Skuriyama transmit_result(NLM_UNLOCK_RES, &res, getrpcaddr(rqstp)); 67174462Salfred return (NULL); 67274462Salfred} 67374462Salfred 67474462Salfred/* ------------------------------------------------------------------------- */ 67574462Salfred/* 67674462Salfred * Client-side pseudo-RPCs for results. Note that for the client there 67774462Salfred * are only nlm_xxx_msg() versions of each call, since the 'real RPC' 67874462Salfred * version returns the results in the RPC result, and so the client 67974462Salfred * does not normally receive incoming RPCs. 68074462Salfred * 68174462Salfred * The exception to this is nlm_granted(), which is genuinely an RPC 68274462Salfred * call from the server to the client - a 'call-back' in normal procedure 68374462Salfred * call terms. 68474462Salfred */ 68574462Salfred 68674462Salfred/* nlm_granted ------------------------------------------------------------- */ 68774462Salfred/* 68874462Salfred * Purpose: Receive notification that formerly blocked lock now granted 68974462Salfred * Returns: always success ('granted') 69074462Salfred * Notes: 69174462Salfred */ 69274462Salfrednlm_res * 69374462Salfrednlm_granted_1_svc(arg, rqstp) 69474462Salfred nlm_testargs *arg; 69574462Salfred struct svc_req *rqstp; 69674462Salfred{ 69774462Salfred static nlm_res res; 69874462Salfred 69974462Salfred if (debug_level) 70074462Salfred log_from_addr("nlm_granted", rqstp); 70174462Salfred 70275631Salfred res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 70375631Salfred nlm_granted, NULL, NLM_VERS) == 0 ? 70475631Salfred nlm_granted : nlm_denied; 70575631Salfred 70674462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 70774462Salfred res.cookie = arg->cookie; 70874462Salfred 70974462Salfred return (&res); 71074462Salfred} 71174462Salfred 71274462Salfredvoid * 71374462Salfrednlm_granted_msg_1_svc(arg, rqstp) 71474462Salfred nlm_testargs *arg; 71574462Salfred struct svc_req *rqstp; 71674462Salfred{ 71774462Salfred static nlm_res res; 71874462Salfred 71974462Salfred if (debug_level) 72074462Salfred log_from_addr("nlm_granted_msg", rqstp); 72174462Salfred 72274462Salfred res.cookie = arg->cookie; 723114993Srwatson res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 724114993Srwatson nlm_granted, NULL, NLM_VERS) == 0 ? 725114993Srwatson nlm_granted : nlm_denied; 726114993Srwatson 727141217Skuriyama transmit_result(NLM_GRANTED_RES, &res, getrpcaddr(rqstp)); 72874462Salfred return (NULL); 72974462Salfred} 73074462Salfred 73174462Salfred/* nlm_test_res ------------------------------------------------------------ */ 73274462Salfred/* 73374462Salfred * Purpose: Accept result from earlier nlm_test_msg() call 73474462Salfred * Returns: Nothing 73574462Salfred */ 73674462Salfredvoid * 73774462Salfrednlm_test_res_1_svc(arg, rqstp) 73874462Salfred nlm_testres *arg; 73974462Salfred struct svc_req *rqstp; 74074462Salfred{ 74174462Salfred if (debug_level) 74274462Salfred log_from_addr("nlm_test_res", rqstp); 74375631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, 74475631Salfred &arg->stat.nlm_testrply_u.holder.svid, NLM_VERS); 74574462Salfred return (NULL); 74674462Salfred} 74774462Salfred 74874462Salfred/* nlm_lock_res ------------------------------------------------------------ */ 74974462Salfred/* 75074462Salfred * Purpose: Accept result from earlier nlm_lock_msg() call 75174462Salfred * Returns: Nothing 75274462Salfred */ 75374462Salfredvoid * 75474462Salfrednlm_lock_res_1_svc(arg, rqstp) 75574462Salfred nlm_res *arg; 75674462Salfred struct svc_req *rqstp; 75774462Salfred{ 75874462Salfred if (debug_level) 75974462Salfred log_from_addr("nlm_lock_res", rqstp); 76074462Salfred 76175631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS); 76275631Salfred 76374462Salfred return (NULL); 76474462Salfred} 76574462Salfred 76674462Salfred/* nlm_cancel_res ---------------------------------------------------------- */ 76774462Salfred/* 76874462Salfred * Purpose: Accept result from earlier nlm_cancel_msg() call 76974462Salfred * Returns: Nothing 77074462Salfred */ 77174462Salfredvoid * 77274462Salfrednlm_cancel_res_1_svc(arg, rqstp) 77392911Salfred nlm_res *arg __unused; 77474462Salfred struct svc_req *rqstp; 77574462Salfred{ 77674462Salfred if (debug_level) 77774462Salfred log_from_addr("nlm_cancel_res", rqstp); 77874462Salfred return (NULL); 77974462Salfred} 78074462Salfred 78174462Salfred/* nlm_unlock_res ---------------------------------------------------------- */ 78274462Salfred/* 78374462Salfred * Purpose: Accept result from earlier nlm_unlock_msg() call 78474462Salfred * Returns: Nothing 78574462Salfred */ 78674462Salfredvoid * 78774462Salfrednlm_unlock_res_1_svc(arg, rqstp) 78874462Salfred nlm_res *arg; 78974462Salfred struct svc_req *rqstp; 79074462Salfred{ 79174462Salfred if (debug_level) 79274462Salfred log_from_addr("nlm_unlock_res", rqstp); 79375631Salfred 79486300Salfred lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS); 79575631Salfred 79674462Salfred return (NULL); 79774462Salfred} 79874462Salfred 79974462Salfred/* nlm_granted_res --------------------------------------------------------- */ 80074462Salfred/* 80174462Salfred * Purpose: Accept result from earlier nlm_granted_msg() call 80274462Salfred * Returns: Nothing 80374462Salfred */ 80474462Salfredvoid * 80574462Salfrednlm_granted_res_1_svc(arg, rqstp) 80692911Salfred nlm_res *arg __unused; 80774462Salfred struct svc_req *rqstp; 80874462Salfred{ 80974462Salfred if (debug_level) 81074462Salfred log_from_addr("nlm_granted_res", rqstp); 81174462Salfred return (NULL); 81274462Salfred} 81374462Salfred 81474462Salfred/* ------------------------------------------------------------------------- */ 81574462Salfred/* 81674462Salfred * Calls for PCNFS locking (aka non-monitored locking, no involvement 81774462Salfred * of rpc.statd). 81874462Salfred * 81974462Salfred * These are all genuine RPCs - no nlm_xxx_msg() nonsense here. 82074462Salfred */ 82174462Salfred 82274462Salfred/* nlm_share --------------------------------------------------------------- */ 82374462Salfred/* 82474462Salfred * Purpose: Establish a DOS-style lock 82574462Salfred * Returns: success or failure 82674462Salfred * Notes: Blocking locks are not supported - client is expected 82774462Salfred * to retry if required. 82874462Salfred */ 82974462Salfrednlm_shareres * 83074462Salfrednlm_share_3_svc(arg, rqstp) 83174462Salfred nlm_shareargs *arg; 83274462Salfred struct svc_req *rqstp; 83374462Salfred{ 83474462Salfred static nlm_shareres res; 83574462Salfred 83674462Salfred if (debug_level) 83774462Salfred log_from_addr("nlm_share", rqstp); 83874462Salfred 83974462Salfred res.cookie = arg->cookie; 84074462Salfred res.stat = nlm_granted; 84174462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 84274462Salfred return (&res); 84374462Salfred} 84474462Salfred 84574462Salfred/* nlm_unshare ------------------------------------------------------------ */ 84674462Salfred/* 84774462Salfred * Purpose: Release a DOS-style lock 84874462Salfred * Returns: nlm_granted, unless in grace period 84974462Salfred * Notes: 85074462Salfred */ 85174462Salfrednlm_shareres * 85274462Salfrednlm_unshare_3_svc(arg, rqstp) 85374462Salfred nlm_shareargs *arg; 85474462Salfred struct svc_req *rqstp; 85574462Salfred{ 85674462Salfred static nlm_shareres res; 85774462Salfred 85874462Salfred if (debug_level) 85974462Salfred log_from_addr("nlm_unshare", rqstp); 86074462Salfred 86174462Salfred res.cookie = arg->cookie; 86274462Salfred res.stat = nlm_granted; 86374462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 86474462Salfred return (&res); 86574462Salfred} 86674462Salfred 86774462Salfred/* nlm_nm_lock ------------------------------------------------------------ */ 86874462Salfred/* 86974462Salfred * Purpose: non-monitored version of nlm_lock() 87074462Salfred * Returns: as for nlm_lock() 87174462Salfred * Notes: These locks are in the same style as the standard nlm_lock, 87274462Salfred * but the rpc.statd should not be called to establish a 87374462Salfred * monitor for the client machine, since that machine is 87474462Salfred * declared not to be running a rpc.statd, and so would not 87574462Salfred * respond to the statd protocol. 87674462Salfred */ 87774462Salfrednlm_res * 87874462Salfrednlm_nm_lock_3_svc(arg, rqstp) 87974462Salfred nlm_lockargs *arg; 88074462Salfred struct svc_req *rqstp; 88174462Salfred{ 88274462Salfred static nlm_res res; 88374462Salfred 88474462Salfred if (debug_level) 88574462Salfred log_from_addr("nlm_nm_lock", rqstp); 88674462Salfred 88774462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 88874462Salfred res.cookie = arg->cookie; 88974462Salfred res.stat.stat = nlm_granted; 89074462Salfred return (&res); 89174462Salfred} 89274462Salfred 89374462Salfred/* nlm_free_all ------------------------------------------------------------ */ 89474462Salfred/* 89574462Salfred * Purpose: Release all locks held by a named client 89674462Salfred * Returns: Nothing 89774462Salfred * Notes: Potential denial of service security problem here - the 89874462Salfred * locks to be released are specified by a host name, independent 89974462Salfred * of the address from which the request has arrived. 90074462Salfred * Should probably be rejected if the named host has been 90174462Salfred * using monitored locks. 90274462Salfred */ 90374462Salfredvoid * 90474462Salfrednlm_free_all_3_svc(arg, rqstp) 90592911Salfred nlm_notify *arg __unused; 90674462Salfred struct svc_req *rqstp; 90774462Salfred{ 90874462Salfred static char dummy; 90974462Salfred 91074462Salfred if (debug_level) 91174462Salfred log_from_addr("nlm_free_all", rqstp); 91274462Salfred return (&dummy); 91374462Salfred} 91474462Salfred 91574462Salfred/* calls for nlm version 4 (NFSv3) */ 91674462Salfred/* nlm_test ---------------------------------------------------------------- */ 91774462Salfred/* 91874462Salfred * Purpose: Test whether a specified lock would be granted if requested 91974462Salfred * Returns: nlm_granted (or error code) 92074462Salfred * Notes: 92174462Salfred */ 92274462Salfrednlm4_testres * 92374462Salfrednlm4_test_4_svc(arg, rqstp) 92474462Salfred nlm4_testargs *arg; 92574462Salfred struct svc_req *rqstp; 92674462Salfred{ 92774462Salfred static nlm4_testres res; 92874462Salfred struct nlm4_holder *holder; 92974462Salfred 93074462Salfred if (debug_level) 93174462Salfred log_from_addr("nlm4_test", rqstp); 93284923Salfred if (debug_level > 5) { 93384923Salfred syslog(LOG_DEBUG, "Locking arguments:\n"); 93484923Salfred log_netobj(&(arg->cookie)); 93584923Salfred syslog(LOG_DEBUG, "Alock arguments:\n"); 93684923Salfred syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name); 93784923Salfred syslog(LOG_DEBUG, "File Handle:\n"); 93884923Salfred log_netobj(&(arg->alock.fh)); 93984923Salfred syslog(LOG_DEBUG, "Owner Handle:\n"); 94084923Salfred log_netobj(&(arg->alock.oh)); 94184923Salfred syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid); 94286319Salfred syslog(LOG_DEBUG, "Lock Offset: %llu\n", 94386319Salfred (unsigned long long)arg->alock.l_offset); 94486319Salfred syslog(LOG_DEBUG, "Lock Length: %llu\n", 94586319Salfred (unsigned long long)arg->alock.l_len); 94684923Salfred syslog(LOG_DEBUG, "Exclusive: %s\n", 94784923Salfred (arg->exclusive ? "true" : "false")); 94884923Salfred } 94974462Salfred 95084923Salfred holder = testlock(&arg->alock, arg->exclusive, LOCK_V4); 95174462Salfred 95274462Salfred /* 95374462Salfred * Copy the cookie from the argument into the result. Note that this 95474462Salfred * is slightly hazardous, as the structure contains a pointer to a 95574462Salfred * malloc()ed buffer that will get freed by the caller. However, the 95674462Salfred * main function transmits the result before freeing the argument 95774462Salfred * so it is in fact safe. 95874462Salfred */ 95974462Salfred res.cookie = arg->cookie; 96074462Salfred if (holder == NULL) { 96174462Salfred res.stat.stat = nlm4_granted; 96274462Salfred } else { 96374462Salfred res.stat.stat = nlm4_denied; 96474462Salfred memcpy(&res.stat.nlm4_testrply_u.holder, holder, 96574462Salfred sizeof(struct nlm4_holder)); 96674462Salfred } 96774462Salfred return (&res); 96874462Salfred} 96974462Salfred 97074462Salfredvoid * 97174462Salfrednlm4_test_msg_4_svc(arg, rqstp) 97274462Salfred nlm4_testargs *arg; 97374462Salfred struct svc_req *rqstp; 97474462Salfred{ 97574462Salfred nlm4_testres res; 97674462Salfred static char dummy; 97774462Salfred struct sockaddr *addr; 97874462Salfred CLIENT *cli; 97974462Salfred int success; 98074462Salfred struct timeval timeo; 98174462Salfred struct nlm4_holder *holder; 98274462Salfred 98374462Salfred if (debug_level) 98474462Salfred log_from_addr("nlm4_test_msg", rqstp); 98574462Salfred 98684923Salfred holder = testlock(&arg->alock, arg->exclusive, LOCK_V4); 98774462Salfred 98874462Salfred res.cookie = arg->cookie; 98974462Salfred if (holder == NULL) { 99074462Salfred res.stat.stat = nlm4_granted; 99174462Salfred } else { 99274462Salfred res.stat.stat = nlm4_denied; 99374462Salfred memcpy(&res.stat.nlm4_testrply_u.holder, holder, 99474462Salfred sizeof(struct nlm4_holder)); 99574462Salfred } 99674462Salfred 99774462Salfred /* 99874462Salfred * nlm_test has different result type to the other operations, so 99974462Salfred * can't use transmit4_result() in this case 100074462Salfred */ 100174462Salfred addr = svc_getrpccaller(rqstp->rq_xprt)->buf; 100274462Salfred if ((cli = get_client(addr, NLM_VERS4)) != NULL) { 100374462Salfred timeo.tv_sec = 0; /* No timeout - not expecting response */ 100474462Salfred timeo.tv_usec = 0; 100574462Salfred 1006121558Speter success = clnt_call(cli, NLM4_TEST_RES, 1007121558Speter (xdrproc_t)xdr_nlm4_testres, &res, 1008121558Speter (xdrproc_t)xdr_void, &dummy, timeo); 100974462Salfred 101074462Salfred if (debug_level > 2) 101174462Salfred syslog(LOG_DEBUG, "clnt_call returns %d", success); 101274462Salfred } 101374462Salfred return (NULL); 101474462Salfred} 101574462Salfred 101674462Salfred/* nlm_lock ---------------------------------------------------------------- */ 101774462Salfred/* 101874462Salfred * Purposes: Establish a lock 101974462Salfred * Returns: granted, denied or blocked 102074462Salfred * Notes: *** grace period support missing 102174462Salfred */ 102274462Salfrednlm4_res * 102374462Salfrednlm4_lock_4_svc(arg, rqstp) 102474462Salfred nlm4_lockargs *arg; 102574462Salfred struct svc_req *rqstp; 102674462Salfred{ 102774462Salfred static nlm4_res res; 102874462Salfred 102974462Salfred if (debug_level) 103074462Salfred log_from_addr("nlm4_lock", rqstp); 103184923Salfred if (debug_level > 5) { 103284923Salfred syslog(LOG_DEBUG, "Locking arguments:\n"); 103384923Salfred log_netobj(&(arg->cookie)); 103484923Salfred syslog(LOG_DEBUG, "Alock arguments:\n"); 103584923Salfred syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name); 103684923Salfred syslog(LOG_DEBUG, "File Handle:\n"); 103784923Salfred log_netobj(&(arg->alock.fh)); 103884923Salfred syslog(LOG_DEBUG, "Owner Handle:\n"); 103984923Salfred log_netobj(&(arg->alock.oh)); 104084923Salfred syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid); 104186319Salfred syslog(LOG_DEBUG, "Lock Offset: %llu\n", 104286319Salfred (unsigned long long)arg->alock.l_offset); 104386319Salfred syslog(LOG_DEBUG, "Lock Length: %llu\n", 104486319Salfred (unsigned long long)arg->alock.l_len); 104584923Salfred syslog(LOG_DEBUG, "Block: %s\n", (arg->block ? "true" : "false")); 104684923Salfred syslog(LOG_DEBUG, "Exclusive: %s\n", (arg->exclusive ? "true" : "false")); 104784923Salfred syslog(LOG_DEBUG, "Reclaim: %s\n", (arg->reclaim ? "true" : "false")); 104884923Salfred syslog(LOG_DEBUG, "State num: %d\n", arg->state); 104984923Salfred } 105074462Salfred 105174462Salfred /* copy cookie from arg to result. See comment in nlm_test_4() */ 105274462Salfred res.cookie = arg->cookie; 105374462Salfred 105474462Salfred res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_V4); 105574462Salfred return (&res); 105674462Salfred} 105774462Salfred 105874462Salfredvoid * 105974462Salfrednlm4_lock_msg_4_svc(arg, rqstp) 106074462Salfred nlm4_lockargs *arg; 106174462Salfred struct svc_req *rqstp; 106274462Salfred{ 106374462Salfred static nlm4_res res; 106474462Salfred 106574462Salfred if (debug_level) 106674462Salfred log_from_addr("nlm4_lock_msg", rqstp); 106774462Salfred 106874462Salfred res.cookie = arg->cookie; 106974462Salfred res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_ASYNC | LOCK_V4); 1070141217Skuriyama transmit4_result(NLM4_LOCK_RES, &res, getrpcaddr(rqstp)); 107174462Salfred 107274462Salfred return (NULL); 107374462Salfred} 107474462Salfred 107574462Salfred/* nlm_cancel -------------------------------------------------------------- */ 107674462Salfred/* 107774462Salfred * Purpose: Cancel a blocked lock request 107874462Salfred * Returns: granted or denied 107974462Salfred * Notes: 108074462Salfred */ 108174462Salfrednlm4_res * 108274462Salfrednlm4_cancel_4_svc(arg, rqstp) 108374462Salfred nlm4_cancargs *arg; 108474462Salfred struct svc_req *rqstp; 108574462Salfred{ 108674462Salfred static nlm4_res res; 108774462Salfred 108874462Salfred if (debug_level) 108974462Salfred log_from_addr("nlm4_cancel", rqstp); 109074462Salfred 109174462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 109274462Salfred res.cookie = arg->cookie; 109374462Salfred 109474462Salfred /* 109574462Salfred * Since at present we never return 'nlm_blocked', there can never be 109674462Salfred * a lock to cancel, so this call always fails. 109774462Salfred */ 109874462Salfred res.stat.stat = unlock(&arg->alock, LOCK_CANCEL); 109974462Salfred return (&res); 110074462Salfred} 110174462Salfred 110274462Salfredvoid * 110374462Salfrednlm4_cancel_msg_4_svc(arg, rqstp) 110474462Salfred nlm4_cancargs *arg; 110574462Salfred struct svc_req *rqstp; 110674462Salfred{ 110774462Salfred static nlm4_res res; 110874462Salfred 110974462Salfred if (debug_level) 111074462Salfred log_from_addr("nlm4_cancel_msg", rqstp); 111174462Salfred 111274462Salfred res.cookie = arg->cookie; 111374462Salfred /* 111474462Salfred * Since at present we never return 'nlm_blocked', there can never be 111574462Salfred * a lock to cancel, so this call always fails. 111674462Salfred */ 111774462Salfred res.stat.stat = unlock(&arg->alock, LOCK_CANCEL | LOCK_V4); 1118141217Skuriyama transmit4_result(NLM4_CANCEL_RES, &res, getrpcaddr(rqstp)); 111974462Salfred return (NULL); 112074462Salfred} 112174462Salfred 112274462Salfred/* nlm_unlock -------------------------------------------------------------- */ 112374462Salfred/* 112474462Salfred * Purpose: Release an existing lock 112574462Salfred * Returns: Always granted, unless during grace period 112674462Salfred * Notes: "no such lock" error condition is ignored, as the 112774462Salfred * protocol uses unreliable UDP datagrams, and may well 112874462Salfred * re-try an unlock that has already succeeded. 112974462Salfred */ 113074462Salfrednlm4_res * 113174462Salfrednlm4_unlock_4_svc(arg, rqstp) 113274462Salfred nlm4_unlockargs *arg; 113374462Salfred struct svc_req *rqstp; 113474462Salfred{ 113574462Salfred static nlm4_res res; 113674462Salfred 113774462Salfred if (debug_level) 113874462Salfred log_from_addr("nlm4_unlock", rqstp); 113974462Salfred 114074462Salfred res.stat.stat = unlock(&arg->alock, LOCK_V4); 114174462Salfred res.cookie = arg->cookie; 114274462Salfred 114374462Salfred return (&res); 114474462Salfred} 114574462Salfred 114674462Salfredvoid * 114774462Salfrednlm4_unlock_msg_4_svc(arg, rqstp) 114874462Salfred nlm4_unlockargs *arg; 114974462Salfred struct svc_req *rqstp; 115074462Salfred{ 115174462Salfred static nlm4_res res; 115274462Salfred 115374462Salfred if (debug_level) 115474462Salfred log_from_addr("nlm4_unlock_msg", rqstp); 115574462Salfred 115674462Salfred res.stat.stat = unlock(&arg->alock, LOCK_V4); 115774462Salfred res.cookie = arg->cookie; 115874462Salfred 1159141217Skuriyama transmit4_result(NLM4_UNLOCK_RES, &res, getrpcaddr(rqstp)); 116074462Salfred return (NULL); 116174462Salfred} 116274462Salfred 116374462Salfred/* ------------------------------------------------------------------------- */ 116474462Salfred/* 116574462Salfred * Client-side pseudo-RPCs for results. Note that for the client there 116674462Salfred * are only nlm_xxx_msg() versions of each call, since the 'real RPC' 116774462Salfred * version returns the results in the RPC result, and so the client 116874462Salfred * does not normally receive incoming RPCs. 116974462Salfred * 117074462Salfred * The exception to this is nlm_granted(), which is genuinely an RPC 117174462Salfred * call from the server to the client - a 'call-back' in normal procedure 117274462Salfred * call terms. 117374462Salfred */ 117474462Salfred 117574462Salfred/* nlm_granted ------------------------------------------------------------- */ 117674462Salfred/* 117774462Salfred * Purpose: Receive notification that formerly blocked lock now granted 117874462Salfred * Returns: always success ('granted') 117974462Salfred * Notes: 118074462Salfred */ 118174462Salfrednlm4_res * 118274462Salfrednlm4_granted_4_svc(arg, rqstp) 118374462Salfred nlm4_testargs *arg; 118474462Salfred struct svc_req *rqstp; 118574462Salfred{ 118674462Salfred static nlm4_res res; 118774462Salfred 118874462Salfred if (debug_level) 118974462Salfred log_from_addr("nlm4_granted", rqstp); 119074462Salfred 119175631Salfred res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 119275631Salfred nlm4_granted, NULL, NLM_VERS4) == 0 ? 119375631Salfred nlm4_granted : nlm4_denied; 119475631Salfred 119574462Salfred /* copy cookie from arg to result. See comment in nlm_test_1() */ 119674462Salfred res.cookie = arg->cookie; 119774462Salfred 119874462Salfred return (&res); 119974462Salfred} 120074462Salfred 120174462Salfredvoid * 120274462Salfrednlm4_granted_msg_4_svc(arg, rqstp) 120374462Salfred nlm4_testargs *arg; 120474462Salfred struct svc_req *rqstp; 120574462Salfred{ 120674462Salfred static nlm4_res res; 120774462Salfred 120874462Salfred if (debug_level) 120974462Salfred log_from_addr("nlm4_granted_msg", rqstp); 121074462Salfred 121174462Salfred res.cookie = arg->cookie; 1212114993Srwatson res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie, 1213114993Srwatson nlm4_granted, NULL, NLM_VERS4) == 0 ? 1214114993Srwatson nlm4_granted : nlm4_denied; 1215141217Skuriyama transmit4_result(NLM4_GRANTED_RES, &res, getrpcaddr(rqstp)); 121674462Salfred return (NULL); 121774462Salfred} 121874462Salfred 121974462Salfred/* nlm_test_res ------------------------------------------------------------ */ 122074462Salfred/* 122174462Salfred * Purpose: Accept result from earlier nlm_test_msg() call 122274462Salfred * Returns: Nothing 122374462Salfred */ 122474462Salfredvoid * 122574462Salfrednlm4_test_res_4_svc(arg, rqstp) 122674462Salfred nlm4_testres *arg; 122774462Salfred struct svc_req *rqstp; 122874462Salfred{ 122974462Salfred if (debug_level) 123074462Salfred log_from_addr("nlm4_test_res", rqstp); 123175631Salfred 123275631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, 123375631Salfred (int *)&arg->stat.nlm4_testrply_u.holder.svid, 123475631Salfred NLM_VERS4); 123574462Salfred return (NULL); 123674462Salfred} 123774462Salfred 123874462Salfred/* nlm_lock_res ------------------------------------------------------------ */ 123974462Salfred/* 124074462Salfred * Purpose: Accept result from earlier nlm_lock_msg() call 124174462Salfred * Returns: Nothing 124274462Salfred */ 124374462Salfredvoid * 124474462Salfrednlm4_lock_res_4_svc(arg, rqstp) 124574462Salfred nlm4_res *arg; 124674462Salfred struct svc_req *rqstp; 124774462Salfred{ 124874462Salfred if (debug_level) 124974462Salfred log_from_addr("nlm4_lock_res", rqstp); 125074462Salfred 125175631Salfred (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS4); 125275631Salfred 125374462Salfred return (NULL); 125474462Salfred} 125574462Salfred 125674462Salfred/* nlm_cancel_res ---------------------------------------------------------- */ 125774462Salfred/* 125874462Salfred * Purpose: Accept result from earlier nlm_cancel_msg() call 125974462Salfred * Returns: Nothing 126074462Salfred */ 126174462Salfredvoid * 126274462Salfrednlm4_cancel_res_4_svc(arg, rqstp) 126392911Salfred nlm4_res *arg __unused; 126474462Salfred struct svc_req *rqstp; 126574462Salfred{ 126674462Salfred if (debug_level) 126774462Salfred log_from_addr("nlm4_cancel_res", rqstp); 126874462Salfred return (NULL); 126974462Salfred} 127074462Salfred 127174462Salfred/* nlm_unlock_res ---------------------------------------------------------- */ 127274462Salfred/* 127374462Salfred * Purpose: Accept result from earlier nlm_unlock_msg() call 127474462Salfred * Returns: Nothing 127574462Salfred */ 127674462Salfredvoid * 127774462Salfrednlm4_unlock_res_4_svc(arg, rqstp) 127892911Salfred nlm4_res *arg __unused; 127974462Salfred struct svc_req *rqstp; 128074462Salfred{ 128174462Salfred if (debug_level) 128274462Salfred log_from_addr("nlm4_unlock_res", rqstp); 128374462Salfred return (NULL); 128474462Salfred} 128574462Salfred 128674462Salfred/* nlm_granted_res --------------------------------------------------------- */ 128774462Salfred/* 128874462Salfred * Purpose: Accept result from earlier nlm_granted_msg() call 128974462Salfred * Returns: Nothing 129074462Salfred */ 129174462Salfredvoid * 129274462Salfrednlm4_granted_res_4_svc(arg, rqstp) 129392911Salfred nlm4_res *arg __unused; 129474462Salfred struct svc_req *rqstp; 129574462Salfred{ 129674462Salfred if (debug_level) 129774462Salfred log_from_addr("nlm4_granted_res", rqstp); 129874462Salfred return (NULL); 129974462Salfred} 130074462Salfred 130174462Salfred/* ------------------------------------------------------------------------- */ 130274462Salfred/* 130374462Salfred * Calls for PCNFS locking (aka non-monitored locking, no involvement 130474462Salfred * of rpc.statd). 130574462Salfred * 130674462Salfred * These are all genuine RPCs - no nlm_xxx_msg() nonsense here. 130774462Salfred */ 130874462Salfred 130974462Salfred/* nlm_share --------------------------------------------------------------- */ 131074462Salfred/* 131174462Salfred * Purpose: Establish a DOS-style lock 131274462Salfred * Returns: success or failure 131374462Salfred * Notes: Blocking locks are not supported - client is expected 131474462Salfred * to retry if required. 131574462Salfred */ 131674462Salfrednlm4_shareres * 131774462Salfrednlm4_share_4_svc(arg, rqstp) 131874462Salfred nlm4_shareargs *arg; 131974462Salfred struct svc_req *rqstp; 132074462Salfred{ 132174462Salfred static nlm4_shareres res; 132274462Salfred 132374462Salfred if (debug_level) 132474462Salfred log_from_addr("nlm4_share", rqstp); 132574462Salfred 132674462Salfred res.cookie = arg->cookie; 132774462Salfred res.stat = nlm4_granted; 132874462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 132974462Salfred return (&res); 133074462Salfred} 133174462Salfred 133274462Salfred/* nlm4_unshare ------------------------------------------------------------ */ 133374462Salfred/* 133474462Salfred * Purpose: Release a DOS-style lock 133574462Salfred * Returns: nlm_granted, unless in grace period 133674462Salfred * Notes: 133774462Salfred */ 133874462Salfrednlm4_shareres * 133974462Salfrednlm4_unshare_4_svc(arg, rqstp) 134074462Salfred nlm4_shareargs *arg; 134174462Salfred struct svc_req *rqstp; 134274462Salfred{ 134374462Salfred static nlm4_shareres res; 134474462Salfred 134574462Salfred if (debug_level) 134674462Salfred log_from_addr("nlm_unshare", rqstp); 134774462Salfred 134874462Salfred res.cookie = arg->cookie; 134974462Salfred res.stat = nlm4_granted; 135074462Salfred res.sequence = 1234356; /* X/Open says this field is ignored? */ 135174462Salfred return (&res); 135274462Salfred} 135374462Salfred 135474462Salfred/* nlm4_nm_lock ------------------------------------------------------------ */ 135574462Salfred/* 135674462Salfred * Purpose: non-monitored version of nlm4_lock() 135774462Salfred * Returns: as for nlm4_lock() 135874462Salfred * Notes: These locks are in the same style as the standard nlm4_lock, 135974462Salfred * but the rpc.statd should not be called to establish a 136074462Salfred * monitor for the client machine, since that machine is 136174462Salfred * declared not to be running a rpc.statd, and so would not 136274462Salfred * respond to the statd protocol. 136374462Salfred */ 136474462Salfrednlm4_res * 136574462Salfrednlm4_nm_lock_4_svc(arg, rqstp) 136674462Salfred nlm4_lockargs *arg; 136774462Salfred struct svc_req *rqstp; 136874462Salfred{ 136974462Salfred static nlm4_res res; 137074462Salfred 137174462Salfred if (debug_level) 137274462Salfred log_from_addr("nlm4_nm_lock", rqstp); 137374462Salfred 137474462Salfred /* copy cookie from arg to result. See comment in nlm4_test_1() */ 137574462Salfred res.cookie = arg->cookie; 137674462Salfred res.stat.stat = nlm4_granted; 137774462Salfred return (&res); 137874462Salfred} 137974462Salfred 138074462Salfred/* nlm4_free_all ------------------------------------------------------------ */ 138174462Salfred/* 138274462Salfred * Purpose: Release all locks held by a named client 138374462Salfred * Returns: Nothing 138474462Salfred * Notes: Potential denial of service security problem here - the 138574462Salfred * locks to be released are specified by a host name, independent 138674462Salfred * of the address from which the request has arrived. 138774462Salfred * Should probably be rejected if the named host has been 138874462Salfred * using monitored locks. 138974462Salfred */ 139074462Salfredvoid * 139174462Salfrednlm4_free_all_4_svc(arg, rqstp) 139292911Salfred struct nlm4_notify *arg __unused; 139374462Salfred struct svc_req *rqstp; 139474462Salfred{ 139574462Salfred static char dummy; 139674462Salfred 139774462Salfred if (debug_level) 139874462Salfred log_from_addr("nlm4_free_all", rqstp); 139974462Salfred return (&dummy); 140074462Salfred} 140174462Salfred 140274462Salfred/* nlm_sm_notify --------------------------------------------------------- */ 140374462Salfred/* 140474462Salfred * Purpose: called by rpc.statd when a monitored host state changes. 140574462Salfred * Returns: Nothing 140674462Salfred */ 140774462Salfredvoid * 140874462Salfrednlm_sm_notify_0_svc(arg, rqstp) 140974462Salfred struct nlm_sm_status *arg; 141092911Salfred struct svc_req *rqstp __unused; 141174462Salfred{ 141274462Salfred static char dummy; 141374462Salfred notify(arg->mon_name, arg->state); 141474462Salfred return (&dummy); 141574462Salfred} 1416