1 /* $NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $ */
5 * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed for the FreeBSD project
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include <sys/cdefs.h>
38 __RCSID("$NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $");
41 #include <sys/param.h>
42 #include <sys/socket.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
52 #include <netconfig.h>
55 #include <rpcsvc/sm_inter.h>
58 #include <rpcsvc/nlm_prot.h>
59 #include "lockd_lock.h"
62 #define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */
63 #define CLIENT_CACHE_LIFETIME 120 /* In seconds */
65 #define getrpcaddr(rqstp) (struct sockaddr *)(svc_getrpccaller((rqstp)->rq_xprt)->buf)
67 static void log_from_addr(const char *, struct svc_req *);
68 static void log_netobj(netobj *obj);
69 static int addrcmp(struct sockaddr *, struct sockaddr *);
71 /* log_from_addr ----------------------------------------------------------- */
73 * Purpose: Log name of function called and source address
75 * Notes: Extracts the source address from the transport handle
76 * passed in as part of the called procedure specification
79 log_from_addr(fun_name, req)
83 struct sockaddr *addr;
84 char hostname_buf[NI_MAXHOST];
86 addr = svc_getrpccaller(req->rq_xprt)->buf;
87 if (getnameinfo(addr , addr->sa_len, hostname_buf, sizeof hostname_buf,
91 syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf);
94 /* log_netobj ----------------------------------------------------------- */
96 * Purpose: Log a netobj
98 * Notes: This function should only really be called as part of
105 char objvalbuffer[(sizeof(char)*2)*MAX_NETOBJ_SZ+2];
106 char objascbuffer[sizeof(char)*MAX_NETOBJ_SZ+1];
107 unsigned int i, maxlen;
110 /* Notify of potential security attacks */
111 if (obj->n_len > MAX_NETOBJ_SZ) {
112 syslog(LOG_DEBUG, "SOMEONE IS TRYING TO DO SOMETHING NASTY!\n");
113 syslog(LOG_DEBUG, "netobj too large! Should be %d was %d\n",
114 MAX_NETOBJ_SZ, obj->n_len);
116 /* Prevent the security hazard from the buffer overflow */
117 maxlen = (obj->n_len < MAX_NETOBJ_SZ ? obj->n_len : MAX_NETOBJ_SZ);
118 for (i=0, tmp1 = objvalbuffer, tmp2 = objascbuffer; i < maxlen;
119 i++, tmp1 +=2, tmp2 +=1) {
120 sprintf(tmp1,"%02X",*(obj->n_bytes+i));
121 sprintf(tmp2,"%c",*(obj->n_bytes+i));
125 syslog(LOG_DEBUG,"netobjvals: %s\n",objvalbuffer);
126 syslog(LOG_DEBUG,"netobjascs: %s\n",objascbuffer);
128 /* get_client -------------------------------------------------------------- */
130 * Purpose: Get a CLIENT* for making RPC calls to lockd on given host
131 * Returns: CLIENT* pointer, from clnt_udp_create, or NULL if error
132 * Notes: Creating a CLIENT* is quite expensive, involving a
133 * conversation with the remote portmapper to get the
134 * port number. Since a given client is quite likely
135 * to make several locking requests in succession, it is
136 * desirable to cache the created CLIENT*.
138 * Since we are using UDP rather than TCP, there is no cost
139 * to the remote system in keeping these cached indefinitely.
140 * Unfortunately there is a snag: if the remote system
141 * reboots, the cached portmapper results will be invalid,
142 * and we will never detect this since all of the xxx_msg()
143 * calls return no result - we just fire off a udp packet
144 * and hope for the best.
146 * We solve this by discarding cached values after two
147 * minutes, regardless of whether they have been used
148 * in the meanwhile (since a bad one might have been used
149 * plenty of times, as the host keeps retrying the request
150 * and we keep sending the reply back to the wrong port).
152 * Given that the entries will always expire in the order
153 * that they were created, there is no point in a LRU
154 * algorithm for when the cache gets full - entries are
155 * always re-used in sequence.
157 static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE];
158 static long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */
159 static struct sockaddr_storage clnt_cache_addr[CLIENT_CACHE_SIZE];
160 static rpcvers_t clnt_cache_vers[CLIENT_CACHE_SIZE];
161 static int clnt_cache_next_to_use = 0;
165 struct sockaddr *sa1;
166 struct sockaddr *sa2;
171 if (sa1->sa_family != sa2->sa_family)
174 switch (sa1->sa_family) {
176 p1 = &((struct sockaddr_in *)sa1)->sin_addr;
177 p2 = &((struct sockaddr_in *)sa2)->sin_addr;
181 p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr;
182 p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr;
189 return memcmp(p1, p2, len);
193 get_client(host_addr, vers)
194 struct sockaddr *host_addr;
198 struct timeval retry_time, time_now;
201 struct netconfig *nconf;
202 char host[NI_MAXHOST];
206 gettimeofday(&time_now, NULL);
209 * Search for the given client in the cache, zapping any expired
210 * entries that we happen to notice in passing.
212 for (i = 0; i < CLIENT_CACHE_SIZE; i++) {
213 client = clnt_cache_ptr[i];
214 if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME)
215 < time_now.tv_sec)) {
216 /* Cache entry has expired. */
218 syslog(LOG_DEBUG, "Expired CLIENT* in cache");
219 clnt_cache_time[i] = 0L;
220 clnt_destroy(client);
221 clnt_cache_ptr[i] = NULL;
224 if (client && !addrcmp((struct sockaddr *)&clnt_cache_addr[i],
225 host_addr) && clnt_cache_vers[i] == vers) {
228 syslog(LOG_DEBUG, "Found CLIENT* in cache");
234 syslog(LOG_DEBUG, "CLIENT* not found in cache, creating");
236 /* Not found in cache. Free the next entry if it is in use. */
237 if (clnt_cache_ptr[clnt_cache_next_to_use]) {
238 clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
239 clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
243 * Need a host string for clnt_tp_create. Use NI_NUMERICHOST
244 * to avoid DNS lookups.
246 error = getnameinfo(host_addr, host_addr->sa_len, host, sizeof host,
247 NULL, 0, NI_NUMERICHOST);
249 syslog(LOG_ERR, "unable to get name string for caller: %s",
250 gai_strerror(error));
255 if (host_addr->sa_family == AF_INET6)
260 if (host_addr->sa_family == AF_INET6)
265 nconf = getnetconfigent(netid);
267 syslog(LOG_ERR, "could not get netconfig info for '%s': "
268 "no /etc/netconfig file?", netid);
272 client = clnt_tp_create(host, NLM_PROG, vers, nconf);
273 freenetconfigent(nconf);
276 syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create"));
277 syslog(LOG_ERR, "Unable to return result to %s", host);
281 /* Get the FD of the client, for bindresvport. */
282 clnt_control(client, CLGET_FD, &clnt_fd);
284 /* Regain root privileges, for bindresvport. */
285 old_euid = geteuid();
286 if (seteuid(0) != 0) {
287 syslog(LOG_ERR, "seteuid(0) failed");
292 * Bind the client FD to a reserved port.
293 * Some NFS servers reject any NLM request from a non-reserved port.
295 bindresvport(clnt_fd, NULL);
297 /* Drop root privileges again. */
298 if (seteuid(old_euid) != 0) {
299 syslog(LOG_ERR, "seteuid(%d) failed", old_euid);
303 /* Success - update the cache entry */
304 clnt_cache_ptr[clnt_cache_next_to_use] = client;
305 memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr,
307 clnt_cache_vers[clnt_cache_next_to_use] = vers;
308 clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec;
309 if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE)
310 clnt_cache_next_to_use = 0;
313 * Disable the default timeout, so we can specify our own in calls
314 * to clnt_call(). (Note that the timeout is a different concept
315 * from the retry period set in clnt_udp_create() above.)
317 retry_time.tv_sec = -1;
318 retry_time.tv_usec = -1;
319 clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time);
322 syslog(LOG_DEBUG, "Created CLIENT* for %s", host);
327 /* transmit_result --------------------------------------------------------- */
329 * Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs
330 * Returns: Nothing - we have no idea if the datagram got there
331 * Notes: clnt_call() will always fail (with timeout) as we are
332 * calling it with timeout 0 as a hack to just issue a datagram
333 * without expecting a result
336 transmit_result(opcode, result, addr)
339 struct sockaddr *addr;
343 struct timeval timeo;
346 if ((cli = get_client(addr, NLM_VERS)) != NULL) {
347 timeo.tv_sec = 0; /* No timeout - not expecting response */
350 success = clnt_call(cli, opcode, (xdrproc_t)xdr_nlm_res, result,
351 (xdrproc_t)xdr_void, &dummy, timeo);
354 syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
355 success, clnt_sperrno(success));
358 /* transmit4_result --------------------------------------------------------- */
360 * Purpose: Transmit result for nlm4_xxx_msg pseudo-RPCs
361 * Returns: Nothing - we have no idea if the datagram got there
362 * Notes: clnt_call() will always fail (with timeout) as we are
363 * calling it with timeout 0 as a hack to just issue a datagram
364 * without expecting a result
367 transmit4_result(opcode, result, addr)
370 struct sockaddr *addr;
374 struct timeval timeo;
377 if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
378 timeo.tv_sec = 0; /* No timeout - not expecting response */
381 success = clnt_call(cli, opcode,
382 (xdrproc_t)xdr_nlm4_res, result,
383 (xdrproc_t)xdr_void, &dummy, timeo);
386 syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
387 success, clnt_sperrno(success));
392 * converts a struct nlm_lock to struct nlm4_lock
394 static void nlmtonlm4(struct nlm_lock *, struct nlm4_lock *);
397 struct nlm_lock *arg;
398 struct nlm4_lock *arg4;
400 arg4->caller_name = arg->caller_name;
403 arg4->svid = arg->svid;
404 arg4->l_offset = arg->l_offset;
405 arg4->l_len = arg->l_len;
407 /* ------------------------------------------------------------------------- */
409 * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
410 * involved to ensure reclaim of locks after a crash of the "stateless"
413 * These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
414 * The first are standard RPCs with argument and result.
415 * The nlm_xxx_msg() calls implement exactly the same functions, but
416 * use two pseudo-RPCs (one in each direction). These calls are NOT
417 * standard use of the RPC protocol in that they do not return a result
418 * at all (NB. this is quite different from returning a void result).
419 * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
420 * datagrams, requiring higher-level code to perform retries.
422 * Despite the disadvantages of the nlm_xxx_msg() approach (some of which
423 * are documented in the comments to get_client() above), this is the
424 * interface used by all current commercial NFS implementations
425 * [Solaris, SCO, AIX etc.]. This is presumed to be because these allow
426 * implementations to continue using the standard RPC libraries, while
427 * avoiding the block-until-result nature of the library interface.
429 * No client implementations have been identified so far that make use
430 * of the true RPC version (early SunOS releases would be a likely candidate
434 /* nlm_test ---------------------------------------------------------------- */
436 * Purpose: Test whether a specified lock would be granted if requested
437 * Returns: nlm_granted (or error code)
441 nlm_test_1_svc(arg, rqstp)
443 struct svc_req *rqstp;
445 static nlm_testres res;
446 struct nlm4_lock arg4;
447 struct nlm4_holder *holder;
448 nlmtonlm4(&arg->alock, &arg4);
451 log_from_addr("nlm_test", rqstp);
453 holder = testlock(&arg4, arg->exclusive, 0);
455 * Copy the cookie from the argument into the result. Note that this
456 * is slightly hazardous, as the structure contains a pointer to a
457 * malloc()ed buffer that will get freed by the caller. However, the
458 * main function transmits the result before freeing the argument
459 * so it is in fact safe.
461 res.cookie = arg->cookie;
462 if (holder == NULL) {
463 res.stat.stat = nlm_granted;
465 res.stat.stat = nlm_denied;
466 memcpy(&res.stat.nlm_testrply_u.holder, holder,
467 sizeof(struct nlm_holder));
468 res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
469 res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
475 nlm_test_msg_1_svc(arg, rqstp)
477 struct svc_req *rqstp;
481 struct sockaddr *addr;
484 struct timeval timeo;
485 struct nlm4_lock arg4;
486 struct nlm4_holder *holder;
488 nlmtonlm4(&arg->alock, &arg4);
491 log_from_addr("nlm_test_msg", rqstp);
493 holder = testlock(&arg4, arg->exclusive, 0);
495 res.cookie = arg->cookie;
496 if (holder == NULL) {
497 res.stat.stat = nlm_granted;
499 res.stat.stat = nlm_denied;
500 memcpy(&res.stat.nlm_testrply_u.holder, holder,
501 sizeof(struct nlm_holder));
502 res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
503 res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
507 * nlm_test has different result type to the other operations, so
508 * can't use transmit_result() in this case
510 addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
511 if ((cli = get_client(addr, NLM_VERS)) != NULL) {
512 timeo.tv_sec = 0; /* No timeout - not expecting response */
515 success = clnt_call(cli, NLM_TEST_RES,
516 (xdrproc_t)xdr_nlm_testres, &res,
517 (xdrproc_t)xdr_void, &dummy, timeo);
520 syslog(LOG_DEBUG, "clnt_call returns %d", success);
525 /* nlm_lock ---------------------------------------------------------------- */
527 * Purposes: Establish a lock
528 * Returns: granted, denied or blocked
529 * Notes: *** grace period support missing
532 nlm_lock_1_svc(arg, rqstp)
534 struct svc_req *rqstp;
537 struct nlm4_lockargs arg4;
538 nlmtonlm4(&arg->alock, &arg4.alock);
539 arg4.cookie = arg->cookie;
540 arg4.block = arg->block;
541 arg4.exclusive = arg->exclusive;
542 arg4.reclaim = arg->reclaim;
543 arg4.state = arg->state;
546 log_from_addr("nlm_lock", rqstp);
548 /* copy cookie from arg to result. See comment in nlm_test_1() */
549 res.cookie = arg->cookie;
551 res.stat.stat = getlock(&arg4, rqstp, LOCK_MON);
556 nlm_lock_msg_1_svc(arg, rqstp)
558 struct svc_req *rqstp;
561 struct nlm4_lockargs arg4;
563 nlmtonlm4(&arg->alock, &arg4.alock);
564 arg4.cookie = arg->cookie;
565 arg4.block = arg->block;
566 arg4.exclusive = arg->exclusive;
567 arg4.reclaim = arg->reclaim;
568 arg4.state = arg->state;
571 log_from_addr("nlm_lock_msg", rqstp);
573 res.cookie = arg->cookie;
574 res.stat.stat = getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON);
575 transmit_result(NLM_LOCK_RES, &res, getrpcaddr(rqstp));
580 /* nlm_cancel -------------------------------------------------------------- */
582 * Purpose: Cancel a blocked lock request
583 * Returns: granted or denied
587 nlm_cancel_1_svc(arg, rqstp)
589 struct svc_req *rqstp;
592 struct nlm4_lock arg4;
594 nlmtonlm4(&arg->alock, &arg4);
597 log_from_addr("nlm_cancel", rqstp);
599 /* copy cookie from arg to result. See comment in nlm_test_1() */
600 res.cookie = arg->cookie;
603 * Since at present we never return 'nlm_blocked', there can never be
604 * a lock to cancel, so this call always fails.
606 res.stat.stat = unlock(&arg4, LOCK_CANCEL);
611 nlm_cancel_msg_1_svc(arg, rqstp)
613 struct svc_req *rqstp;
616 struct nlm4_lock arg4;
618 nlmtonlm4(&arg->alock, &arg4);
621 log_from_addr("nlm_cancel_msg", rqstp);
623 res.cookie = arg->cookie;
625 * Since at present we never return 'nlm_blocked', there can never be
626 * a lock to cancel, so this call always fails.
628 res.stat.stat = unlock(&arg4, LOCK_CANCEL);
629 transmit_result(NLM_CANCEL_RES, &res, getrpcaddr(rqstp));
633 /* nlm_unlock -------------------------------------------------------------- */
635 * Purpose: Release an existing lock
636 * Returns: Always granted, unless during grace period
637 * Notes: "no such lock" error condition is ignored, as the
638 * protocol uses unreliable UDP datagrams, and may well
639 * re-try an unlock that has already succeeded.
642 nlm_unlock_1_svc(arg, rqstp)
644 struct svc_req *rqstp;
647 struct nlm4_lock arg4;
649 nlmtonlm4(&arg->alock, &arg4);
652 log_from_addr("nlm_unlock", rqstp);
654 res.stat.stat = unlock(&arg4, 0);
655 res.cookie = arg->cookie;
661 nlm_unlock_msg_1_svc(arg, rqstp)
663 struct svc_req *rqstp;
666 struct nlm4_lock arg4;
668 nlmtonlm4(&arg->alock, &arg4);
671 log_from_addr("nlm_unlock_msg", rqstp);
673 res.stat.stat = unlock(&arg4, 0);
674 res.cookie = arg->cookie;
676 transmit_result(NLM_UNLOCK_RES, &res, getrpcaddr(rqstp));
680 /* ------------------------------------------------------------------------- */
682 * Client-side pseudo-RPCs for results. Note that for the client there
683 * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
684 * version returns the results in the RPC result, and so the client
685 * does not normally receive incoming RPCs.
687 * The exception to this is nlm_granted(), which is genuinely an RPC
688 * call from the server to the client - a 'call-back' in normal procedure
692 /* nlm_granted ------------------------------------------------------------- */
694 * Purpose: Receive notification that formerly blocked lock now granted
695 * Returns: always success ('granted')
699 nlm_granted_1_svc(arg, rqstp)
701 struct svc_req *rqstp;
706 log_from_addr("nlm_granted", rqstp);
708 res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
709 nlm_granted, NULL, NLM_VERS) == 0 ?
710 nlm_granted : nlm_denied;
712 /* copy cookie from arg to result. See comment in nlm_test_1() */
713 res.cookie = arg->cookie;
719 nlm_granted_msg_1_svc(arg, rqstp)
721 struct svc_req *rqstp;
726 log_from_addr("nlm_granted_msg", rqstp);
728 res.cookie = arg->cookie;
729 res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
730 nlm_granted, NULL, NLM_VERS) == 0 ?
731 nlm_granted : nlm_denied;
733 transmit_result(NLM_GRANTED_RES, &res, getrpcaddr(rqstp));
737 /* nlm_test_res ------------------------------------------------------------ */
739 * Purpose: Accept result from earlier nlm_test_msg() call
743 nlm_test_res_1_svc(arg, rqstp)
745 struct svc_req *rqstp;
748 log_from_addr("nlm_test_res", rqstp);
749 (void)lock_answer(-1, &arg->cookie, arg->stat.stat,
750 &arg->stat.nlm_testrply_u.holder.svid, NLM_VERS);
754 /* nlm_lock_res ------------------------------------------------------------ */
756 * Purpose: Accept result from earlier nlm_lock_msg() call
760 nlm_lock_res_1_svc(arg, rqstp)
762 struct svc_req *rqstp;
765 log_from_addr("nlm_lock_res", rqstp);
767 (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS);
772 /* nlm_cancel_res ---------------------------------------------------------- */
774 * Purpose: Accept result from earlier nlm_cancel_msg() call
778 nlm_cancel_res_1_svc(arg, rqstp)
779 nlm_res *arg __unused;
780 struct svc_req *rqstp;
783 log_from_addr("nlm_cancel_res", rqstp);
787 /* nlm_unlock_res ---------------------------------------------------------- */
789 * Purpose: Accept result from earlier nlm_unlock_msg() call
793 nlm_unlock_res_1_svc(arg, rqstp)
795 struct svc_req *rqstp;
798 log_from_addr("nlm_unlock_res", rqstp);
800 lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS);
805 /* nlm_granted_res --------------------------------------------------------- */
807 * Purpose: Accept result from earlier nlm_granted_msg() call
811 nlm_granted_res_1_svc(arg, rqstp)
812 nlm_res *arg __unused;
813 struct svc_req *rqstp;
816 log_from_addr("nlm_granted_res", rqstp);
820 /* ------------------------------------------------------------------------- */
822 * Calls for PCNFS locking (aka non-monitored locking, no involvement
825 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
828 /* nlm_share --------------------------------------------------------------- */
830 * Purpose: Establish a DOS-style lock
831 * Returns: success or failure
832 * Notes: Blocking locks are not supported - client is expected
833 * to retry if required.
836 nlm_share_3_svc(arg, rqstp)
838 struct svc_req *rqstp;
840 static nlm_shareres res;
843 log_from_addr("nlm_share", rqstp);
845 res.cookie = arg->cookie;
846 res.stat = nlm_granted;
847 res.sequence = 1234356; /* X/Open says this field is ignored? */
851 /* nlm_unshare ------------------------------------------------------------ */
853 * Purpose: Release a DOS-style lock
854 * Returns: nlm_granted, unless in grace period
858 nlm_unshare_3_svc(arg, rqstp)
860 struct svc_req *rqstp;
862 static nlm_shareres res;
865 log_from_addr("nlm_unshare", rqstp);
867 res.cookie = arg->cookie;
868 res.stat = nlm_granted;
869 res.sequence = 1234356; /* X/Open says this field is ignored? */
873 /* nlm_nm_lock ------------------------------------------------------------ */
875 * Purpose: non-monitored version of nlm_lock()
876 * Returns: as for nlm_lock()
877 * Notes: These locks are in the same style as the standard nlm_lock,
878 * but the rpc.statd should not be called to establish a
879 * monitor for the client machine, since that machine is
880 * declared not to be running a rpc.statd, and so would not
881 * respond to the statd protocol.
884 nlm_nm_lock_3_svc(arg, rqstp)
886 struct svc_req *rqstp;
891 log_from_addr("nlm_nm_lock", rqstp);
893 /* copy cookie from arg to result. See comment in nlm_test_1() */
894 res.cookie = arg->cookie;
895 res.stat.stat = nlm_granted;
899 /* nlm_free_all ------------------------------------------------------------ */
901 * Purpose: Release all locks held by a named client
903 * Notes: Potential denial of service security problem here - the
904 * locks to be released are specified by a host name, independent
905 * of the address from which the request has arrived.
906 * Should probably be rejected if the named host has been
907 * using monitored locks.
910 nlm_free_all_3_svc(arg, rqstp)
911 nlm_notify *arg __unused;
912 struct svc_req *rqstp;
917 log_from_addr("nlm_free_all", rqstp);
921 /* calls for nlm version 4 (NFSv3) */
922 /* nlm_test ---------------------------------------------------------------- */
924 * Purpose: Test whether a specified lock would be granted if requested
925 * Returns: nlm_granted (or error code)
929 nlm4_test_4_svc(arg, rqstp)
931 struct svc_req *rqstp;
933 static nlm4_testres res;
934 struct nlm4_holder *holder;
937 log_from_addr("nlm4_test", rqstp);
938 if (debug_level > 5) {
939 syslog(LOG_DEBUG, "Locking arguments:\n");
940 log_netobj(&(arg->cookie));
941 syslog(LOG_DEBUG, "Alock arguments:\n");
942 syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name);
943 syslog(LOG_DEBUG, "File Handle:\n");
944 log_netobj(&(arg->alock.fh));
945 syslog(LOG_DEBUG, "Owner Handle:\n");
946 log_netobj(&(arg->alock.oh));
947 syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid);
948 syslog(LOG_DEBUG, "Lock Offset: %llu\n",
949 (unsigned long long)arg->alock.l_offset);
950 syslog(LOG_DEBUG, "Lock Length: %llu\n",
951 (unsigned long long)arg->alock.l_len);
952 syslog(LOG_DEBUG, "Exclusive: %s\n",
953 (arg->exclusive ? "true" : "false"));
956 holder = testlock(&arg->alock, arg->exclusive, LOCK_V4);
959 * Copy the cookie from the argument into the result. Note that this
960 * is slightly hazardous, as the structure contains a pointer to a
961 * malloc()ed buffer that will get freed by the caller. However, the
962 * main function transmits the result before freeing the argument
963 * so it is in fact safe.
965 res.cookie = arg->cookie;
966 if (holder == NULL) {
967 res.stat.stat = nlm4_granted;
969 res.stat.stat = nlm4_denied;
970 memcpy(&res.stat.nlm4_testrply_u.holder, holder,
971 sizeof(struct nlm4_holder));
977 nlm4_test_msg_4_svc(arg, rqstp)
979 struct svc_req *rqstp;
983 struct sockaddr *addr;
986 struct timeval timeo;
987 struct nlm4_holder *holder;
990 log_from_addr("nlm4_test_msg", rqstp);
992 holder = testlock(&arg->alock, arg->exclusive, LOCK_V4);
994 res.cookie = arg->cookie;
995 if (holder == NULL) {
996 res.stat.stat = nlm4_granted;
998 res.stat.stat = nlm4_denied;
999 memcpy(&res.stat.nlm4_testrply_u.holder, holder,
1000 sizeof(struct nlm4_holder));
1004 * nlm_test has different result type to the other operations, so
1005 * can't use transmit4_result() in this case
1007 addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
1008 if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
1009 timeo.tv_sec = 0; /* No timeout - not expecting response */
1012 success = clnt_call(cli, NLM4_TEST_RES,
1013 (xdrproc_t)xdr_nlm4_testres, &res,
1014 (xdrproc_t)xdr_void, &dummy, timeo);
1016 if (debug_level > 2)
1017 syslog(LOG_DEBUG, "clnt_call returns %d", success);
1022 /* nlm_lock ---------------------------------------------------------------- */
1024 * Purposes: Establish a lock
1025 * Returns: granted, denied or blocked
1026 * Notes: *** grace period support missing
1029 nlm4_lock_4_svc(arg, rqstp)
1031 struct svc_req *rqstp;
1033 static nlm4_res res;
1036 log_from_addr("nlm4_lock", rqstp);
1037 if (debug_level > 5) {
1038 syslog(LOG_DEBUG, "Locking arguments:\n");
1039 log_netobj(&(arg->cookie));
1040 syslog(LOG_DEBUG, "Alock arguments:\n");
1041 syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name);
1042 syslog(LOG_DEBUG, "File Handle:\n");
1043 log_netobj(&(arg->alock.fh));
1044 syslog(LOG_DEBUG, "Owner Handle:\n");
1045 log_netobj(&(arg->alock.oh));
1046 syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid);
1047 syslog(LOG_DEBUG, "Lock Offset: %llu\n",
1048 (unsigned long long)arg->alock.l_offset);
1049 syslog(LOG_DEBUG, "Lock Length: %llu\n",
1050 (unsigned long long)arg->alock.l_len);
1051 syslog(LOG_DEBUG, "Block: %s\n", (arg->block ? "true" : "false"));
1052 syslog(LOG_DEBUG, "Exclusive: %s\n", (arg->exclusive ? "true" : "false"));
1053 syslog(LOG_DEBUG, "Reclaim: %s\n", (arg->reclaim ? "true" : "false"));
1054 syslog(LOG_DEBUG, "State num: %d\n", arg->state);
1057 /* copy cookie from arg to result. See comment in nlm_test_4() */
1058 res.cookie = arg->cookie;
1060 res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_V4);
1065 nlm4_lock_msg_4_svc(arg, rqstp)
1067 struct svc_req *rqstp;
1069 static nlm4_res res;
1072 log_from_addr("nlm4_lock_msg", rqstp);
1074 res.cookie = arg->cookie;
1075 res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_ASYNC | LOCK_V4);
1076 transmit4_result(NLM4_LOCK_RES, &res, getrpcaddr(rqstp));
1081 /* nlm_cancel -------------------------------------------------------------- */
1083 * Purpose: Cancel a blocked lock request
1084 * Returns: granted or denied
1088 nlm4_cancel_4_svc(arg, rqstp)
1090 struct svc_req *rqstp;
1092 static nlm4_res res;
1095 log_from_addr("nlm4_cancel", rqstp);
1097 /* copy cookie from arg to result. See comment in nlm_test_1() */
1098 res.cookie = arg->cookie;
1101 * Since at present we never return 'nlm_blocked', there can never be
1102 * a lock to cancel, so this call always fails.
1104 res.stat.stat = unlock(&arg->alock, LOCK_CANCEL);
1109 nlm4_cancel_msg_4_svc(arg, rqstp)
1111 struct svc_req *rqstp;
1113 static nlm4_res res;
1116 log_from_addr("nlm4_cancel_msg", rqstp);
1118 res.cookie = arg->cookie;
1120 * Since at present we never return 'nlm_blocked', there can never be
1121 * a lock to cancel, so this call always fails.
1123 res.stat.stat = unlock(&arg->alock, LOCK_CANCEL | LOCK_V4);
1124 transmit4_result(NLM4_CANCEL_RES, &res, getrpcaddr(rqstp));
1128 /* nlm_unlock -------------------------------------------------------------- */
1130 * Purpose: Release an existing lock
1131 * Returns: Always granted, unless during grace period
1132 * Notes: "no such lock" error condition is ignored, as the
1133 * protocol uses unreliable UDP datagrams, and may well
1134 * re-try an unlock that has already succeeded.
1137 nlm4_unlock_4_svc(arg, rqstp)
1138 nlm4_unlockargs *arg;
1139 struct svc_req *rqstp;
1141 static nlm4_res res;
1144 log_from_addr("nlm4_unlock", rqstp);
1146 res.stat.stat = unlock(&arg->alock, LOCK_V4);
1147 res.cookie = arg->cookie;
1153 nlm4_unlock_msg_4_svc(arg, rqstp)
1154 nlm4_unlockargs *arg;
1155 struct svc_req *rqstp;
1157 static nlm4_res res;
1160 log_from_addr("nlm4_unlock_msg", rqstp);
1162 res.stat.stat = unlock(&arg->alock, LOCK_V4);
1163 res.cookie = arg->cookie;
1165 transmit4_result(NLM4_UNLOCK_RES, &res, getrpcaddr(rqstp));
1169 /* ------------------------------------------------------------------------- */
1171 * Client-side pseudo-RPCs for results. Note that for the client there
1172 * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
1173 * version returns the results in the RPC result, and so the client
1174 * does not normally receive incoming RPCs.
1176 * The exception to this is nlm_granted(), which is genuinely an RPC
1177 * call from the server to the client - a 'call-back' in normal procedure
1181 /* nlm_granted ------------------------------------------------------------- */
1183 * Purpose: Receive notification that formerly blocked lock now granted
1184 * Returns: always success ('granted')
1188 nlm4_granted_4_svc(arg, rqstp)
1190 struct svc_req *rqstp;
1192 static nlm4_res res;
1195 log_from_addr("nlm4_granted", rqstp);
1197 res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
1198 nlm4_granted, NULL, NLM_VERS4) == 0 ?
1199 nlm4_granted : nlm4_denied;
1201 /* copy cookie from arg to result. See comment in nlm_test_1() */
1202 res.cookie = arg->cookie;
1208 nlm4_granted_msg_4_svc(arg, rqstp)
1210 struct svc_req *rqstp;
1212 static nlm4_res res;
1215 log_from_addr("nlm4_granted_msg", rqstp);
1217 res.cookie = arg->cookie;
1218 res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
1219 nlm4_granted, NULL, NLM_VERS4) == 0 ?
1220 nlm4_granted : nlm4_denied;
1221 transmit4_result(NLM4_GRANTED_RES, &res, getrpcaddr(rqstp));
1225 /* nlm_test_res ------------------------------------------------------------ */
1227 * Purpose: Accept result from earlier nlm_test_msg() call
1231 nlm4_test_res_4_svc(arg, rqstp)
1233 struct svc_req *rqstp;
1236 log_from_addr("nlm4_test_res", rqstp);
1238 (void)lock_answer(-1, &arg->cookie, arg->stat.stat,
1239 (int *)&arg->stat.nlm4_testrply_u.holder.svid,
1244 /* nlm_lock_res ------------------------------------------------------------ */
1246 * Purpose: Accept result from earlier nlm_lock_msg() call
1250 nlm4_lock_res_4_svc(arg, rqstp)
1252 struct svc_req *rqstp;
1255 log_from_addr("nlm4_lock_res", rqstp);
1257 (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS4);
1262 /* nlm_cancel_res ---------------------------------------------------------- */
1264 * Purpose: Accept result from earlier nlm_cancel_msg() call
1268 nlm4_cancel_res_4_svc(arg, rqstp)
1269 nlm4_res *arg __unused;
1270 struct svc_req *rqstp;
1273 log_from_addr("nlm4_cancel_res", rqstp);
1277 /* nlm_unlock_res ---------------------------------------------------------- */
1279 * Purpose: Accept result from earlier nlm_unlock_msg() call
1283 nlm4_unlock_res_4_svc(arg, rqstp)
1284 nlm4_res *arg __unused;
1285 struct svc_req *rqstp;
1288 log_from_addr("nlm4_unlock_res", rqstp);
1292 /* nlm_granted_res --------------------------------------------------------- */
1294 * Purpose: Accept result from earlier nlm_granted_msg() call
1298 nlm4_granted_res_4_svc(arg, rqstp)
1299 nlm4_res *arg __unused;
1300 struct svc_req *rqstp;
1303 log_from_addr("nlm4_granted_res", rqstp);
1307 /* ------------------------------------------------------------------------- */
1309 * Calls for PCNFS locking (aka non-monitored locking, no involvement
1312 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
1315 /* nlm_share --------------------------------------------------------------- */
1317 * Purpose: Establish a DOS-style lock
1318 * Returns: success or failure
1319 * Notes: Blocking locks are not supported - client is expected
1320 * to retry if required.
1323 nlm4_share_4_svc(arg, rqstp)
1324 nlm4_shareargs *arg;
1325 struct svc_req *rqstp;
1327 static nlm4_shareres res;
1330 log_from_addr("nlm4_share", rqstp);
1332 res.cookie = arg->cookie;
1333 res.stat = nlm4_granted;
1334 res.sequence = 1234356; /* X/Open says this field is ignored? */
1338 /* nlm4_unshare ------------------------------------------------------------ */
1340 * Purpose: Release a DOS-style lock
1341 * Returns: nlm_granted, unless in grace period
1345 nlm4_unshare_4_svc(arg, rqstp)
1346 nlm4_shareargs *arg;
1347 struct svc_req *rqstp;
1349 static nlm4_shareres res;
1352 log_from_addr("nlm_unshare", rqstp);
1354 res.cookie = arg->cookie;
1355 res.stat = nlm4_granted;
1356 res.sequence = 1234356; /* X/Open says this field is ignored? */
1360 /* nlm4_nm_lock ------------------------------------------------------------ */
1362 * Purpose: non-monitored version of nlm4_lock()
1363 * Returns: as for nlm4_lock()
1364 * Notes: These locks are in the same style as the standard nlm4_lock,
1365 * but the rpc.statd should not be called to establish a
1366 * monitor for the client machine, since that machine is
1367 * declared not to be running a rpc.statd, and so would not
1368 * respond to the statd protocol.
1371 nlm4_nm_lock_4_svc(arg, rqstp)
1373 struct svc_req *rqstp;
1375 static nlm4_res res;
1378 log_from_addr("nlm4_nm_lock", rqstp);
1380 /* copy cookie from arg to result. See comment in nlm4_test_1() */
1381 res.cookie = arg->cookie;
1382 res.stat.stat = nlm4_granted;
1386 /* nlm4_free_all ------------------------------------------------------------ */
1388 * Purpose: Release all locks held by a named client
1390 * Notes: Potential denial of service security problem here - the
1391 * locks to be released are specified by a host name, independent
1392 * of the address from which the request has arrived.
1393 * Should probably be rejected if the named host has been
1394 * using monitored locks.
1397 nlm4_free_all_4_svc(arg, rqstp)
1398 struct nlm4_notify *arg __unused;
1399 struct svc_req *rqstp;
1404 log_from_addr("nlm4_free_all", rqstp);
1408 /* nlm_sm_notify --------------------------------------------------------- */
1410 * Purpose: called by rpc.statd when a monitored host state changes.
1414 nlm_sm_notify_0_svc(arg, rqstp)
1415 struct nlm_sm_status *arg;
1416 struct svc_req *rqstp __unused;
1419 notify(arg->mon_name, arg->state);