1 /* $NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $ */
3 * SPDX-License-Identifier: BSD-4-Clause
6 * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed for the FreeBSD project
19 * 4. Neither the name of the author nor the names of any co-contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include <sys/cdefs.h>
39 __RCSID("$NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $");
42 #include <sys/param.h>
43 #include <sys/socket.h>
45 #include <netinet/in.h>
46 #include <arpa/inet.h>
53 #include <netconfig.h>
56 #include <rpcsvc/sm_inter.h>
59 #include <rpcsvc/nlm_prot.h>
60 #include "lockd_lock.h"
63 #define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */
64 #define CLIENT_CACHE_LIFETIME 120 /* In seconds */
66 #define getrpcaddr(rqstp) (struct sockaddr *)(svc_getrpccaller((rqstp)->rq_xprt)->buf)
68 static void log_from_addr(const char *, struct svc_req *);
69 static void log_netobj(netobj *obj);
70 static int addrcmp(struct sockaddr *, struct sockaddr *);
72 /* log_from_addr ----------------------------------------------------------- */
74 * Purpose: Log name of function called and source address
76 * Notes: Extracts the source address from the transport handle
77 * passed in as part of the called procedure specification
80 log_from_addr(const char *fun_name, struct svc_req *req)
82 struct sockaddr *addr;
83 char hostname_buf[NI_MAXHOST];
85 addr = svc_getrpccaller(req->rq_xprt)->buf;
86 if (getnameinfo(addr , addr->sa_len, hostname_buf, sizeof hostname_buf,
90 syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf);
93 /* log_netobj ----------------------------------------------------------- */
95 * Purpose: Log a netobj
97 * Notes: This function should only really be called as part of
101 log_netobj(netobj *obj)
103 char objvalbuffer[(sizeof(char)*2)*MAX_NETOBJ_SZ+2];
104 char objascbuffer[sizeof(char)*MAX_NETOBJ_SZ+1];
105 unsigned int i, maxlen;
108 /* Notify of potential security attacks */
109 if (obj->n_len > MAX_NETOBJ_SZ) {
110 syslog(LOG_DEBUG, "SOMEONE IS TRYING TO DO SOMETHING NASTY!\n");
111 syslog(LOG_DEBUG, "netobj too large! Should be %d was %d\n",
112 MAX_NETOBJ_SZ, obj->n_len);
114 /* Prevent the security hazard from the buffer overflow */
115 maxlen = (obj->n_len < MAX_NETOBJ_SZ ? obj->n_len : MAX_NETOBJ_SZ);
116 for (i=0, tmp1 = objvalbuffer, tmp2 = objascbuffer; i < maxlen;
117 i++, tmp1 +=2, tmp2 +=1) {
118 sprintf(tmp1,"%02X",*(obj->n_bytes+i));
119 sprintf(tmp2,"%c",*(obj->n_bytes+i));
123 syslog(LOG_DEBUG,"netobjvals: %s\n",objvalbuffer);
124 syslog(LOG_DEBUG,"netobjascs: %s\n",objascbuffer);
126 /* get_client -------------------------------------------------------------- */
128 * Purpose: Get a CLIENT* for making RPC calls to lockd on given host
129 * Returns: CLIENT* pointer, from clnt_udp_create, or NULL if error
130 * Notes: Creating a CLIENT* is quite expensive, involving a
131 * conversation with the remote portmapper to get the
132 * port number. Since a given client is quite likely
133 * to make several locking requests in succession, it is
134 * desirable to cache the created CLIENT*.
136 * Since we are using UDP rather than TCP, there is no cost
137 * to the remote system in keeping these cached indefinitely.
138 * Unfortunately there is a snag: if the remote system
139 * reboots, the cached portmapper results will be invalid,
140 * and we will never detect this since all of the xxx_msg()
141 * calls return no result - we just fire off a udp packet
142 * and hope for the best.
144 * We solve this by discarding cached values after two
145 * minutes, regardless of whether they have been used
146 * in the meanwhile (since a bad one might have been used
147 * plenty of times, as the host keeps retrying the request
148 * and we keep sending the reply back to the wrong port).
150 * Given that the entries will always expire in the order
151 * that they were created, there is no point in a LRU
152 * algorithm for when the cache gets full - entries are
153 * always re-used in sequence.
155 static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE];
156 static long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */
157 static struct sockaddr_storage clnt_cache_addr[CLIENT_CACHE_SIZE];
158 static rpcvers_t clnt_cache_vers[CLIENT_CACHE_SIZE];
159 static int clnt_cache_next_to_use = 0;
162 addrcmp(struct sockaddr *sa1, struct sockaddr *sa2)
167 if (sa1->sa_family != sa2->sa_family)
170 switch (sa1->sa_family) {
172 p1 = &((struct sockaddr_in *)sa1)->sin_addr;
173 p2 = &((struct sockaddr_in *)sa2)->sin_addr;
177 p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr;
178 p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr;
185 return memcmp(p1, p2, len);
189 get_client(struct sockaddr *host_addr, rpcvers_t vers)
192 struct timeval retry_time, time_now;
195 struct netconfig *nconf;
196 char host[NI_MAXHOST];
200 gettimeofday(&time_now, NULL);
203 * Search for the given client in the cache, zapping any expired
204 * entries that we happen to notice in passing.
206 for (i = 0; i < CLIENT_CACHE_SIZE; i++) {
207 client = clnt_cache_ptr[i];
208 if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME)
209 < time_now.tv_sec)) {
210 /* Cache entry has expired. */
212 syslog(LOG_DEBUG, "Expired CLIENT* in cache");
213 clnt_cache_time[i] = 0L;
214 clnt_destroy(client);
215 clnt_cache_ptr[i] = NULL;
218 if (client && !addrcmp((struct sockaddr *)&clnt_cache_addr[i],
219 host_addr) && clnt_cache_vers[i] == vers) {
222 syslog(LOG_DEBUG, "Found CLIENT* in cache");
228 syslog(LOG_DEBUG, "CLIENT* not found in cache, creating");
230 /* Not found in cache. Free the next entry if it is in use. */
231 if (clnt_cache_ptr[clnt_cache_next_to_use]) {
232 clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
233 clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
237 * Need a host string for clnt_tp_create. Use NI_NUMERICHOST
238 * to avoid DNS lookups.
240 error = getnameinfo(host_addr, host_addr->sa_len, host, sizeof host,
241 NULL, 0, NI_NUMERICHOST);
243 syslog(LOG_ERR, "unable to get name string for caller: %s",
244 gai_strerror(error));
249 if (host_addr->sa_family == AF_INET6)
254 if (host_addr->sa_family == AF_INET6)
259 nconf = getnetconfigent(netid);
261 syslog(LOG_ERR, "could not get netconfig info for '%s': "
262 "no /etc/netconfig file?", netid);
266 client = clnt_tp_create(host, NLM_PROG, vers, nconf);
267 freenetconfigent(nconf);
270 syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create"));
271 syslog(LOG_ERR, "Unable to return result to %s", host);
275 /* Get the FD of the client, for bindresvport. */
276 clnt_control(client, CLGET_FD, &clnt_fd);
278 /* Regain root privileges, for bindresvport. */
279 old_euid = geteuid();
280 if (seteuid(0) != 0) {
281 syslog(LOG_ERR, "seteuid(0) failed");
286 * Bind the client FD to a reserved port.
287 * Some NFS servers reject any NLM request from a non-reserved port.
289 bindresvport(clnt_fd, NULL);
291 /* Drop root privileges again. */
292 if (seteuid(old_euid) != 0) {
293 syslog(LOG_ERR, "seteuid(%d) failed", old_euid);
297 /* Success - update the cache entry */
298 clnt_cache_ptr[clnt_cache_next_to_use] = client;
299 memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr,
301 clnt_cache_vers[clnt_cache_next_to_use] = vers;
302 clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec;
303 if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE)
304 clnt_cache_next_to_use = 0;
307 * Disable the default timeout, so we can specify our own in calls
308 * to clnt_call(). (Note that the timeout is a different concept
309 * from the retry period set in clnt_udp_create() above.)
311 retry_time.tv_sec = -1;
312 retry_time.tv_usec = -1;
313 clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time);
316 syslog(LOG_DEBUG, "Created CLIENT* for %s", host);
321 /* transmit_result --------------------------------------------------------- */
323 * Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs
324 * Returns: Nothing - we have no idea if the datagram got there
325 * Notes: clnt_call() will always fail (with timeout) as we are
326 * calling it with timeout 0 as a hack to just issue a datagram
327 * without expecting a result
330 transmit_result(int opcode, nlm_res *result, struct sockaddr *addr)
334 struct timeval timeo;
337 if ((cli = get_client(addr, NLM_VERS)) != NULL) {
338 timeo.tv_sec = 0; /* No timeout - not expecting response */
341 success = clnt_call(cli, opcode, (xdrproc_t)xdr_nlm_res, result,
342 (xdrproc_t)xdr_void, &dummy, timeo);
345 syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
346 success, clnt_sperrno(success));
349 /* transmit4_result --------------------------------------------------------- */
351 * Purpose: Transmit result for nlm4_xxx_msg pseudo-RPCs
352 * Returns: Nothing - we have no idea if the datagram got there
353 * Notes: clnt_call() will always fail (with timeout) as we are
354 * calling it with timeout 0 as a hack to just issue a datagram
355 * without expecting a result
358 transmit4_result(int opcode, nlm4_res *result, struct sockaddr *addr)
362 struct timeval timeo;
365 if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
366 timeo.tv_sec = 0; /* No timeout - not expecting response */
369 success = clnt_call(cli, opcode,
370 (xdrproc_t)xdr_nlm4_res, result,
371 (xdrproc_t)xdr_void, &dummy, timeo);
374 syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
375 success, clnt_sperrno(success));
380 * converts a struct nlm_lock to struct nlm4_lock
383 nlmtonlm4(struct nlm_lock *arg, struct nlm4_lock *arg4)
385 arg4->caller_name = arg->caller_name;
388 arg4->svid = arg->svid;
389 arg4->l_offset = arg->l_offset;
390 arg4->l_len = arg->l_len;
392 /* ------------------------------------------------------------------------- */
394 * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
395 * involved to ensure reclaim of locks after a crash of the "stateless"
398 * These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
399 * The first are standard RPCs with argument and result.
400 * The nlm_xxx_msg() calls implement exactly the same functions, but
401 * use two pseudo-RPCs (one in each direction). These calls are NOT
402 * standard use of the RPC protocol in that they do not return a result
403 * at all (NB. this is quite different from returning a void result).
404 * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
405 * datagrams, requiring higher-level code to perform retries.
407 * Despite the disadvantages of the nlm_xxx_msg() approach (some of which
408 * are documented in the comments to get_client() above), this is the
409 * interface used by all current commercial NFS implementations
410 * [Solaris, SCO, AIX etc.]. This is presumed to be because these allow
411 * implementations to continue using the standard RPC libraries, while
412 * avoiding the block-until-result nature of the library interface.
414 * No client implementations have been identified so far that make use
415 * of the true RPC version (early SunOS releases would be a likely candidate
419 /* nlm_test ---------------------------------------------------------------- */
421 * Purpose: Test whether a specified lock would be granted if requested
422 * Returns: nlm_granted (or error code)
426 nlm_test_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
428 static nlm_testres res;
429 struct nlm4_lock arg4;
430 struct nlm4_holder *holder;
431 nlmtonlm4(&arg->alock, &arg4);
434 log_from_addr("nlm_test", rqstp);
436 holder = testlock(&arg4, arg->exclusive, 0);
438 * Copy the cookie from the argument into the result. Note that this
439 * is slightly hazardous, as the structure contains a pointer to a
440 * malloc()ed buffer that will get freed by the caller. However, the
441 * main function transmits the result before freeing the argument
442 * so it is in fact safe.
444 res.cookie = arg->cookie;
445 if (holder == NULL) {
446 res.stat.stat = nlm_granted;
448 res.stat.stat = nlm_denied;
449 memcpy(&res.stat.nlm_testrply_u.holder, holder,
450 sizeof(struct nlm_holder));
451 res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
452 res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
458 nlm_test_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
462 struct sockaddr *addr;
465 struct timeval timeo;
466 struct nlm4_lock arg4;
467 struct nlm4_holder *holder;
469 nlmtonlm4(&arg->alock, &arg4);
472 log_from_addr("nlm_test_msg", rqstp);
474 holder = testlock(&arg4, arg->exclusive, 0);
476 res.cookie = arg->cookie;
477 if (holder == NULL) {
478 res.stat.stat = nlm_granted;
480 res.stat.stat = nlm_denied;
481 memcpy(&res.stat.nlm_testrply_u.holder, holder,
482 sizeof(struct nlm_holder));
483 res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
484 res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
488 * nlm_test has different result type to the other operations, so
489 * can't use transmit_result() in this case
491 addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
492 if ((cli = get_client(addr, NLM_VERS)) != NULL) {
493 timeo.tv_sec = 0; /* No timeout - not expecting response */
496 success = clnt_call(cli, NLM_TEST_RES,
497 (xdrproc_t)xdr_nlm_testres, &res,
498 (xdrproc_t)xdr_void, &dummy, timeo);
501 syslog(LOG_DEBUG, "clnt_call returns %d", success);
506 /* nlm_lock ---------------------------------------------------------------- */
508 * Purposes: Establish a lock
509 * Returns: granted, denied or blocked
510 * Notes: *** grace period support missing
513 nlm_lock_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
516 struct nlm4_lockargs arg4;
517 nlmtonlm4(&arg->alock, &arg4.alock);
518 arg4.cookie = arg->cookie;
519 arg4.block = arg->block;
520 arg4.exclusive = arg->exclusive;
521 arg4.reclaim = arg->reclaim;
522 arg4.state = arg->state;
525 log_from_addr("nlm_lock", rqstp);
527 /* copy cookie from arg to result. See comment in nlm_test_1() */
528 res.cookie = arg->cookie;
530 res.stat.stat = getlock(&arg4, rqstp, LOCK_MON);
535 nlm_lock_msg_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
538 struct nlm4_lockargs arg4;
540 nlmtonlm4(&arg->alock, &arg4.alock);
541 arg4.cookie = arg->cookie;
542 arg4.block = arg->block;
543 arg4.exclusive = arg->exclusive;
544 arg4.reclaim = arg->reclaim;
545 arg4.state = arg->state;
548 log_from_addr("nlm_lock_msg", rqstp);
550 res.cookie = arg->cookie;
551 res.stat.stat = getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON);
552 transmit_result(NLM_LOCK_RES, &res, getrpcaddr(rqstp));
557 /* nlm_cancel -------------------------------------------------------------- */
559 * Purpose: Cancel a blocked lock request
560 * Returns: granted or denied
564 nlm_cancel_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
567 struct nlm4_lock arg4;
569 nlmtonlm4(&arg->alock, &arg4);
572 log_from_addr("nlm_cancel", rqstp);
574 /* copy cookie from arg to result. See comment in nlm_test_1() */
575 res.cookie = arg->cookie;
578 * Since at present we never return 'nlm_blocked', there can never be
579 * a lock to cancel, so this call always fails.
581 res.stat.stat = unlock(&arg4, LOCK_CANCEL);
586 nlm_cancel_msg_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
589 struct nlm4_lock arg4;
591 nlmtonlm4(&arg->alock, &arg4);
594 log_from_addr("nlm_cancel_msg", rqstp);
596 res.cookie = arg->cookie;
598 * Since at present we never return 'nlm_blocked', there can never be
599 * a lock to cancel, so this call always fails.
601 res.stat.stat = unlock(&arg4, LOCK_CANCEL);
602 transmit_result(NLM_CANCEL_RES, &res, getrpcaddr(rqstp));
606 /* nlm_unlock -------------------------------------------------------------- */
608 * Purpose: Release an existing lock
609 * Returns: Always granted, unless during grace period
610 * Notes: "no such lock" error condition is ignored, as the
611 * protocol uses unreliable UDP datagrams, and may well
612 * re-try an unlock that has already succeeded.
615 nlm_unlock_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
618 struct nlm4_lock arg4;
620 nlmtonlm4(&arg->alock, &arg4);
623 log_from_addr("nlm_unlock", rqstp);
625 res.stat.stat = unlock(&arg4, 0);
626 res.cookie = arg->cookie;
632 nlm_unlock_msg_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
635 struct nlm4_lock arg4;
637 nlmtonlm4(&arg->alock, &arg4);
640 log_from_addr("nlm_unlock_msg", rqstp);
642 res.stat.stat = unlock(&arg4, 0);
643 res.cookie = arg->cookie;
645 transmit_result(NLM_UNLOCK_RES, &res, getrpcaddr(rqstp));
649 /* ------------------------------------------------------------------------- */
651 * Client-side pseudo-RPCs for results. Note that for the client there
652 * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
653 * version returns the results in the RPC result, and so the client
654 * does not normally receive incoming RPCs.
656 * The exception to this is nlm_granted(), which is genuinely an RPC
657 * call from the server to the client - a 'call-back' in normal procedure
661 /* nlm_granted ------------------------------------------------------------- */
663 * Purpose: Receive notification that formerly blocked lock now granted
664 * Returns: always success ('granted')
668 nlm_granted_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
673 log_from_addr("nlm_granted", rqstp);
675 res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
676 nlm_granted, NULL, NLM_VERS) == 0 ?
677 nlm_granted : nlm_denied;
679 /* copy cookie from arg to result. See comment in nlm_test_1() */
680 res.cookie = arg->cookie;
686 nlm_granted_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
691 log_from_addr("nlm_granted_msg", rqstp);
693 res.cookie = arg->cookie;
694 res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
695 nlm_granted, NULL, NLM_VERS) == 0 ?
696 nlm_granted : nlm_denied;
698 transmit_result(NLM_GRANTED_RES, &res, getrpcaddr(rqstp));
702 /* nlm_test_res ------------------------------------------------------------ */
704 * Purpose: Accept result from earlier nlm_test_msg() call
708 nlm_test_res_1_svc(nlm_testres *arg, struct svc_req *rqstp)
711 log_from_addr("nlm_test_res", rqstp);
712 (void)lock_answer(-1, &arg->cookie, arg->stat.stat,
713 &arg->stat.nlm_testrply_u.holder.svid, NLM_VERS);
717 /* nlm_lock_res ------------------------------------------------------------ */
719 * Purpose: Accept result from earlier nlm_lock_msg() call
723 nlm_lock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
726 log_from_addr("nlm_lock_res", rqstp);
728 (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS);
733 /* nlm_cancel_res ---------------------------------------------------------- */
735 * Purpose: Accept result from earlier nlm_cancel_msg() call
739 nlm_cancel_res_1_svc(nlm_res *arg __unused, struct svc_req *rqstp)
742 log_from_addr("nlm_cancel_res", rqstp);
746 /* nlm_unlock_res ---------------------------------------------------------- */
748 * Purpose: Accept result from earlier nlm_unlock_msg() call
752 nlm_unlock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
755 log_from_addr("nlm_unlock_res", rqstp);
757 lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS);
762 /* nlm_granted_res --------------------------------------------------------- */
764 * Purpose: Accept result from earlier nlm_granted_msg() call
768 nlm_granted_res_1_svc(nlm_res *arg __unused, struct svc_req *rqstp)
771 log_from_addr("nlm_granted_res", rqstp);
775 /* ------------------------------------------------------------------------- */
777 * Calls for PCNFS locking (aka non-monitored locking, no involvement
780 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
783 /* nlm_share --------------------------------------------------------------- */
785 * Purpose: Establish a DOS-style lock
786 * Returns: success or failure
787 * Notes: Blocking locks are not supported - client is expected
788 * to retry if required.
791 nlm_share_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
793 static nlm_shareres res;
796 log_from_addr("nlm_share", rqstp);
798 res.cookie = arg->cookie;
799 res.stat = nlm_granted;
800 res.sequence = 1234356; /* X/Open says this field is ignored? */
804 /* nlm_unshare ------------------------------------------------------------ */
806 * Purpose: Release a DOS-style lock
807 * Returns: nlm_granted, unless in grace period
811 nlm_unshare_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
813 static nlm_shareres res;
816 log_from_addr("nlm_unshare", rqstp);
818 res.cookie = arg->cookie;
819 res.stat = nlm_granted;
820 res.sequence = 1234356; /* X/Open says this field is ignored? */
824 /* nlm_nm_lock ------------------------------------------------------------ */
826 * Purpose: non-monitored version of nlm_lock()
827 * Returns: as for nlm_lock()
828 * Notes: These locks are in the same style as the standard nlm_lock,
829 * but the rpc.statd should not be called to establish a
830 * monitor for the client machine, since that machine is
831 * declared not to be running a rpc.statd, and so would not
832 * respond to the statd protocol.
835 nlm_nm_lock_3_svc(nlm_lockargs *arg, struct svc_req *rqstp)
840 log_from_addr("nlm_nm_lock", rqstp);
842 /* copy cookie from arg to result. See comment in nlm_test_1() */
843 res.cookie = arg->cookie;
844 res.stat.stat = nlm_granted;
848 /* nlm_free_all ------------------------------------------------------------ */
850 * Purpose: Release all locks held by a named client
852 * Notes: Potential denial of service security problem here - the
853 * locks to be released are specified by a host name, independent
854 * of the address from which the request has arrived.
855 * Should probably be rejected if the named host has been
856 * using monitored locks.
859 nlm_free_all_3_svc(nlm_notify *arg __unused, struct svc_req *rqstp)
864 log_from_addr("nlm_free_all", rqstp);
868 /* calls for nlm version 4 (NFSv3) */
869 /* nlm_test ---------------------------------------------------------------- */
871 * Purpose: Test whether a specified lock would be granted if requested
872 * Returns: nlm_granted (or error code)
876 nlm4_test_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
878 static nlm4_testres res;
879 struct nlm4_holder *holder;
882 log_from_addr("nlm4_test", rqstp);
883 if (debug_level > 5) {
884 syslog(LOG_DEBUG, "Locking arguments:\n");
885 log_netobj(&(arg->cookie));
886 syslog(LOG_DEBUG, "Alock arguments:\n");
887 syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name);
888 syslog(LOG_DEBUG, "File Handle:\n");
889 log_netobj(&(arg->alock.fh));
890 syslog(LOG_DEBUG, "Owner Handle:\n");
891 log_netobj(&(arg->alock.oh));
892 syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid);
893 syslog(LOG_DEBUG, "Lock Offset: %llu\n",
894 (unsigned long long)arg->alock.l_offset);
895 syslog(LOG_DEBUG, "Lock Length: %llu\n",
896 (unsigned long long)arg->alock.l_len);
897 syslog(LOG_DEBUG, "Exclusive: %s\n",
898 (arg->exclusive ? "true" : "false"));
901 holder = testlock(&arg->alock, arg->exclusive, LOCK_V4);
904 * Copy the cookie from the argument into the result. Note that this
905 * is slightly hazardous, as the structure contains a pointer to a
906 * malloc()ed buffer that will get freed by the caller. However, the
907 * main function transmits the result before freeing the argument
908 * so it is in fact safe.
910 res.cookie = arg->cookie;
911 if (holder == NULL) {
912 res.stat.stat = nlm4_granted;
914 res.stat.stat = nlm4_denied;
915 memcpy(&res.stat.nlm4_testrply_u.holder, holder,
916 sizeof(struct nlm4_holder));
922 nlm4_test_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
926 struct sockaddr *addr;
929 struct timeval timeo;
930 struct nlm4_holder *holder;
933 log_from_addr("nlm4_test_msg", rqstp);
935 holder = testlock(&arg->alock, arg->exclusive, LOCK_V4);
937 res.cookie = arg->cookie;
938 if (holder == NULL) {
939 res.stat.stat = nlm4_granted;
941 res.stat.stat = nlm4_denied;
942 memcpy(&res.stat.nlm4_testrply_u.holder, holder,
943 sizeof(struct nlm4_holder));
947 * nlm_test has different result type to the other operations, so
948 * can't use transmit4_result() in this case
950 addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
951 if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
952 timeo.tv_sec = 0; /* No timeout - not expecting response */
955 success = clnt_call(cli, NLM4_TEST_RES,
956 (xdrproc_t)xdr_nlm4_testres, &res,
957 (xdrproc_t)xdr_void, &dummy, timeo);
960 syslog(LOG_DEBUG, "clnt_call returns %d", success);
965 /* nlm_lock ---------------------------------------------------------------- */
967 * Purposes: Establish a lock
968 * Returns: granted, denied or blocked
969 * Notes: *** grace period support missing
972 nlm4_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
977 log_from_addr("nlm4_lock", rqstp);
978 if (debug_level > 5) {
979 syslog(LOG_DEBUG, "Locking arguments:\n");
980 log_netobj(&(arg->cookie));
981 syslog(LOG_DEBUG, "Alock arguments:\n");
982 syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name);
983 syslog(LOG_DEBUG, "File Handle:\n");
984 log_netobj(&(arg->alock.fh));
985 syslog(LOG_DEBUG, "Owner Handle:\n");
986 log_netobj(&(arg->alock.oh));
987 syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid);
988 syslog(LOG_DEBUG, "Lock Offset: %llu\n",
989 (unsigned long long)arg->alock.l_offset);
990 syslog(LOG_DEBUG, "Lock Length: %llu\n",
991 (unsigned long long)arg->alock.l_len);
992 syslog(LOG_DEBUG, "Block: %s\n", (arg->block ? "true" : "false"));
993 syslog(LOG_DEBUG, "Exclusive: %s\n", (arg->exclusive ? "true" : "false"));
994 syslog(LOG_DEBUG, "Reclaim: %s\n", (arg->reclaim ? "true" : "false"));
995 syslog(LOG_DEBUG, "State num: %d\n", arg->state);
998 /* copy cookie from arg to result. See comment in nlm_test_4() */
999 res.cookie = arg->cookie;
1001 res.stat.stat = (enum nlm4_stats)getlock(arg, rqstp, LOCK_MON | LOCK_V4);
1006 nlm4_lock_msg_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
1008 static nlm4_res res;
1011 log_from_addr("nlm4_lock_msg", rqstp);
1013 res.cookie = arg->cookie;
1014 res.stat.stat = (enum nlm4_stats)getlock(arg, rqstp, LOCK_MON | LOCK_ASYNC | LOCK_V4);
1015 transmit4_result(NLM4_LOCK_RES, &res, getrpcaddr(rqstp));
1020 /* nlm_cancel -------------------------------------------------------------- */
1022 * Purpose: Cancel a blocked lock request
1023 * Returns: granted or denied
1027 nlm4_cancel_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
1029 static nlm4_res res;
1032 log_from_addr("nlm4_cancel", rqstp);
1034 /* copy cookie from arg to result. See comment in nlm_test_1() */
1035 res.cookie = arg->cookie;
1038 * Since at present we never return 'nlm_blocked', there can never be
1039 * a lock to cancel, so this call always fails.
1041 res.stat.stat = (enum nlm4_stats)unlock(&arg->alock, LOCK_CANCEL);
1046 nlm4_cancel_msg_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
1048 static nlm4_res res;
1051 log_from_addr("nlm4_cancel_msg", rqstp);
1053 res.cookie = arg->cookie;
1055 * Since at present we never return 'nlm_blocked', there can never be
1056 * a lock to cancel, so this call always fails.
1058 res.stat.stat = (enum nlm4_stats)unlock(&arg->alock, LOCK_CANCEL | LOCK_V4);
1059 transmit4_result(NLM4_CANCEL_RES, &res, getrpcaddr(rqstp));
1063 /* nlm_unlock -------------------------------------------------------------- */
1065 * Purpose: Release an existing lock
1066 * Returns: Always granted, unless during grace period
1067 * Notes: "no such lock" error condition is ignored, as the
1068 * protocol uses unreliable UDP datagrams, and may well
1069 * re-try an unlock that has already succeeded.
1072 nlm4_unlock_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
1074 static nlm4_res res;
1077 log_from_addr("nlm4_unlock", rqstp);
1079 res.stat.stat = (enum nlm4_stats)unlock(&arg->alock, LOCK_V4);
1080 res.cookie = arg->cookie;
1086 nlm4_unlock_msg_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
1088 static nlm4_res res;
1091 log_from_addr("nlm4_unlock_msg", rqstp);
1093 res.stat.stat = (enum nlm4_stats)unlock(&arg->alock, LOCK_V4);
1094 res.cookie = arg->cookie;
1096 transmit4_result(NLM4_UNLOCK_RES, &res, getrpcaddr(rqstp));
1100 /* ------------------------------------------------------------------------- */
1102 * Client-side pseudo-RPCs for results. Note that for the client there
1103 * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
1104 * version returns the results in the RPC result, and so the client
1105 * does not normally receive incoming RPCs.
1107 * The exception to this is nlm_granted(), which is genuinely an RPC
1108 * call from the server to the client - a 'call-back' in normal procedure
1112 /* nlm_granted ------------------------------------------------------------- */
1114 * Purpose: Receive notification that formerly blocked lock now granted
1115 * Returns: always success ('granted')
1119 nlm4_granted_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
1121 static nlm4_res res;
1124 log_from_addr("nlm4_granted", rqstp);
1126 res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
1127 nlm4_granted, NULL, NLM_VERS4) == 0 ?
1128 nlm4_granted : nlm4_denied;
1130 /* copy cookie from arg to result. See comment in nlm_test_1() */
1131 res.cookie = arg->cookie;
1137 nlm4_granted_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
1139 static nlm4_res res;
1142 log_from_addr("nlm4_granted_msg", rqstp);
1144 res.cookie = arg->cookie;
1145 res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
1146 nlm4_granted, NULL, NLM_VERS4) == 0 ?
1147 nlm4_granted : nlm4_denied;
1148 transmit4_result(NLM4_GRANTED_RES, &res, getrpcaddr(rqstp));
1152 /* nlm_test_res ------------------------------------------------------------ */
1154 * Purpose: Accept result from earlier nlm_test_msg() call
1158 nlm4_test_res_4_svc(nlm4_testres *arg, struct svc_req *rqstp)
1161 log_from_addr("nlm4_test_res", rqstp);
1163 (void)lock_answer(-1, &arg->cookie, arg->stat.stat,
1164 (int *)&arg->stat.nlm4_testrply_u.holder.svid,
1169 /* nlm_lock_res ------------------------------------------------------------ */
1171 * Purpose: Accept result from earlier nlm_lock_msg() call
1175 nlm4_lock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
1178 log_from_addr("nlm4_lock_res", rqstp);
1180 (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS4);
1185 /* nlm_cancel_res ---------------------------------------------------------- */
1187 * Purpose: Accept result from earlier nlm_cancel_msg() call
1191 nlm4_cancel_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp)
1194 log_from_addr("nlm4_cancel_res", rqstp);
1198 /* nlm_unlock_res ---------------------------------------------------------- */
1200 * Purpose: Accept result from earlier nlm_unlock_msg() call
1204 nlm4_unlock_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp)
1207 log_from_addr("nlm4_unlock_res", rqstp);
1211 /* nlm_granted_res --------------------------------------------------------- */
1213 * Purpose: Accept result from earlier nlm_granted_msg() call
1217 nlm4_granted_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp)
1220 log_from_addr("nlm4_granted_res", rqstp);
1224 /* ------------------------------------------------------------------------- */
1226 * Calls for PCNFS locking (aka non-monitored locking, no involvement
1229 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
1232 /* nlm_share --------------------------------------------------------------- */
1234 * Purpose: Establish a DOS-style lock
1235 * Returns: success or failure
1236 * Notes: Blocking locks are not supported - client is expected
1237 * to retry if required.
1240 nlm4_share_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
1242 static nlm4_shareres res;
1245 log_from_addr("nlm4_share", rqstp);
1247 res.cookie = arg->cookie;
1248 res.stat = nlm4_granted;
1249 res.sequence = 1234356; /* X/Open says this field is ignored? */
1253 /* nlm4_unshare ------------------------------------------------------------ */
1255 * Purpose: Release a DOS-style lock
1256 * Returns: nlm_granted, unless in grace period
1260 nlm4_unshare_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
1262 static nlm4_shareres res;
1265 log_from_addr("nlm_unshare", rqstp);
1267 res.cookie = arg->cookie;
1268 res.stat = nlm4_granted;
1269 res.sequence = 1234356; /* X/Open says this field is ignored? */
1273 /* nlm4_nm_lock ------------------------------------------------------------ */
1275 * Purpose: non-monitored version of nlm4_lock()
1276 * Returns: as for nlm4_lock()
1277 * Notes: These locks are in the same style as the standard nlm4_lock,
1278 * but the rpc.statd should not be called to establish a
1279 * monitor for the client machine, since that machine is
1280 * declared not to be running a rpc.statd, and so would not
1281 * respond to the statd protocol.
1284 nlm4_nm_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
1286 static nlm4_res res;
1289 log_from_addr("nlm4_nm_lock", rqstp);
1291 /* copy cookie from arg to result. See comment in nlm4_test_1() */
1292 res.cookie = arg->cookie;
1293 res.stat.stat = nlm4_granted;
1297 /* nlm4_free_all ------------------------------------------------------------ */
1299 * Purpose: Release all locks held by a named client
1301 * Notes: Potential denial of service security problem here - the
1302 * locks to be released are specified by a host name, independent
1303 * of the address from which the request has arrived.
1304 * Should probably be rejected if the named host has been
1305 * using monitored locks.
1308 nlm4_free_all_4_svc(struct nlm4_notify *arg __unused, struct svc_req *rqstp)
1313 log_from_addr("nlm4_free_all", rqstp);
1317 /* nlm_sm_notify --------------------------------------------------------- */
1319 * Purpose: called by rpc.statd when a monitored host state changes.
1323 nlm_sm_notify_0_svc(struct nlm_sm_status *arg, struct svc_req *rqstp __unused)
1326 notify(arg->mon_name, arg->state);