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(const char *fun_name, struct svc_req *req)
81 struct sockaddr *addr;
82 char hostname_buf[NI_MAXHOST];
84 addr = svc_getrpccaller(req->rq_xprt)->buf;
85 if (getnameinfo(addr , addr->sa_len, hostname_buf, sizeof hostname_buf,
89 syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf);
92 /* log_netobj ----------------------------------------------------------- */
94 * Purpose: Log a netobj
96 * Notes: This function should only really be called as part of
100 log_netobj(netobj *obj)
102 char objvalbuffer[(sizeof(char)*2)*MAX_NETOBJ_SZ+2];
103 char objascbuffer[sizeof(char)*MAX_NETOBJ_SZ+1];
104 unsigned int i, maxlen;
107 /* Notify of potential security attacks */
108 if (obj->n_len > MAX_NETOBJ_SZ) {
109 syslog(LOG_DEBUG, "SOMEONE IS TRYING TO DO SOMETHING NASTY!\n");
110 syslog(LOG_DEBUG, "netobj too large! Should be %d was %d\n",
111 MAX_NETOBJ_SZ, obj->n_len);
113 /* Prevent the security hazard from the buffer overflow */
114 maxlen = (obj->n_len < MAX_NETOBJ_SZ ? obj->n_len : MAX_NETOBJ_SZ);
115 for (i=0, tmp1 = objvalbuffer, tmp2 = objascbuffer; i < maxlen;
116 i++, tmp1 +=2, tmp2 +=1) {
117 sprintf(tmp1,"%02X",*(obj->n_bytes+i));
118 sprintf(tmp2,"%c",*(obj->n_bytes+i));
122 syslog(LOG_DEBUG,"netobjvals: %s\n",objvalbuffer);
123 syslog(LOG_DEBUG,"netobjascs: %s\n",objascbuffer);
125 /* get_client -------------------------------------------------------------- */
127 * Purpose: Get a CLIENT* for making RPC calls to lockd on given host
128 * Returns: CLIENT* pointer, from clnt_udp_create, or NULL if error
129 * Notes: Creating a CLIENT* is quite expensive, involving a
130 * conversation with the remote portmapper to get the
131 * port number. Since a given client is quite likely
132 * to make several locking requests in succession, it is
133 * desirable to cache the created CLIENT*.
135 * Since we are using UDP rather than TCP, there is no cost
136 * to the remote system in keeping these cached indefinitely.
137 * Unfortunately there is a snag: if the remote system
138 * reboots, the cached portmapper results will be invalid,
139 * and we will never detect this since all of the xxx_msg()
140 * calls return no result - we just fire off a udp packet
141 * and hope for the best.
143 * We solve this by discarding cached values after two
144 * minutes, regardless of whether they have been used
145 * in the meanwhile (since a bad one might have been used
146 * plenty of times, as the host keeps retrying the request
147 * and we keep sending the reply back to the wrong port).
149 * Given that the entries will always expire in the order
150 * that they were created, there is no point in a LRU
151 * algorithm for when the cache gets full - entries are
152 * always re-used in sequence.
154 static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE];
155 static long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */
156 static struct sockaddr_storage clnt_cache_addr[CLIENT_CACHE_SIZE];
157 static rpcvers_t clnt_cache_vers[CLIENT_CACHE_SIZE];
158 static int clnt_cache_next_to_use = 0;
161 addrcmp(struct sockaddr *sa1, struct sockaddr *sa2)
166 if (sa1->sa_family != sa2->sa_family)
169 switch (sa1->sa_family) {
171 p1 = &((struct sockaddr_in *)sa1)->sin_addr;
172 p2 = &((struct sockaddr_in *)sa2)->sin_addr;
176 p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr;
177 p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr;
184 return memcmp(p1, p2, len);
188 get_client(struct sockaddr *host_addr, rpcvers_t vers)
191 struct timeval retry_time, time_now;
194 struct netconfig *nconf;
195 char host[NI_MAXHOST];
199 gettimeofday(&time_now, NULL);
202 * Search for the given client in the cache, zapping any expired
203 * entries that we happen to notice in passing.
205 for (i = 0; i < CLIENT_CACHE_SIZE; i++) {
206 client = clnt_cache_ptr[i];
207 if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME)
208 < time_now.tv_sec)) {
209 /* Cache entry has expired. */
211 syslog(LOG_DEBUG, "Expired CLIENT* in cache");
212 clnt_cache_time[i] = 0L;
213 clnt_destroy(client);
214 clnt_cache_ptr[i] = NULL;
217 if (client && !addrcmp((struct sockaddr *)&clnt_cache_addr[i],
218 host_addr) && clnt_cache_vers[i] == vers) {
221 syslog(LOG_DEBUG, "Found CLIENT* in cache");
227 syslog(LOG_DEBUG, "CLIENT* not found in cache, creating");
229 /* Not found in cache. Free the next entry if it is in use. */
230 if (clnt_cache_ptr[clnt_cache_next_to_use]) {
231 clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
232 clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
236 * Need a host string for clnt_tp_create. Use NI_NUMERICHOST
237 * to avoid DNS lookups.
239 error = getnameinfo(host_addr, host_addr->sa_len, host, sizeof host,
240 NULL, 0, NI_NUMERICHOST);
242 syslog(LOG_ERR, "unable to get name string for caller: %s",
243 gai_strerror(error));
248 if (host_addr->sa_family == AF_INET6)
253 if (host_addr->sa_family == AF_INET6)
258 nconf = getnetconfigent(netid);
260 syslog(LOG_ERR, "could not get netconfig info for '%s': "
261 "no /etc/netconfig file?", netid);
265 client = clnt_tp_create(host, NLM_PROG, vers, nconf);
266 freenetconfigent(nconf);
269 syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create"));
270 syslog(LOG_ERR, "Unable to return result to %s", host);
274 /* Get the FD of the client, for bindresvport. */
275 clnt_control(client, CLGET_FD, &clnt_fd);
277 /* Regain root privileges, for bindresvport. */
278 old_euid = geteuid();
279 if (seteuid(0) != 0) {
280 syslog(LOG_ERR, "seteuid(0) failed");
285 * Bind the client FD to a reserved port.
286 * Some NFS servers reject any NLM request from a non-reserved port.
288 bindresvport(clnt_fd, NULL);
290 /* Drop root privileges again. */
291 if (seteuid(old_euid) != 0) {
292 syslog(LOG_ERR, "seteuid(%d) failed", old_euid);
296 /* Success - update the cache entry */
297 clnt_cache_ptr[clnt_cache_next_to_use] = client;
298 memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr,
300 clnt_cache_vers[clnt_cache_next_to_use] = vers;
301 clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec;
302 if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE)
303 clnt_cache_next_to_use = 0;
306 * Disable the default timeout, so we can specify our own in calls
307 * to clnt_call(). (Note that the timeout is a different concept
308 * from the retry period set in clnt_udp_create() above.)
310 retry_time.tv_sec = -1;
311 retry_time.tv_usec = -1;
312 clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time);
315 syslog(LOG_DEBUG, "Created CLIENT* for %s", host);
320 /* transmit_result --------------------------------------------------------- */
322 * Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs
323 * Returns: Nothing - we have no idea if the datagram got there
324 * Notes: clnt_call() will always fail (with timeout) as we are
325 * calling it with timeout 0 as a hack to just issue a datagram
326 * without expecting a result
329 transmit_result(int opcode, nlm_res *result, struct sockaddr *addr)
333 struct timeval timeo;
336 if ((cli = get_client(addr, NLM_VERS)) != NULL) {
337 timeo.tv_sec = 0; /* No timeout - not expecting response */
340 success = clnt_call(cli, opcode, (xdrproc_t)xdr_nlm_res, result,
341 (xdrproc_t)xdr_void, &dummy, timeo);
344 syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
345 success, clnt_sperrno(success));
348 /* transmit4_result --------------------------------------------------------- */
350 * Purpose: Transmit result for nlm4_xxx_msg pseudo-RPCs
351 * Returns: Nothing - we have no idea if the datagram got there
352 * Notes: clnt_call() will always fail (with timeout) as we are
353 * calling it with timeout 0 as a hack to just issue a datagram
354 * without expecting a result
357 transmit4_result(int opcode, nlm4_res *result, struct sockaddr *addr)
361 struct timeval timeo;
364 if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
365 timeo.tv_sec = 0; /* No timeout - not expecting response */
368 success = clnt_call(cli, opcode,
369 (xdrproc_t)xdr_nlm4_res, result,
370 (xdrproc_t)xdr_void, &dummy, timeo);
373 syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
374 success, clnt_sperrno(success));
379 * converts a struct nlm_lock to struct nlm4_lock
382 nlmtonlm4(struct nlm_lock *arg, struct nlm4_lock *arg4)
384 arg4->caller_name = arg->caller_name;
387 arg4->svid = arg->svid;
388 arg4->l_offset = arg->l_offset;
389 arg4->l_len = arg->l_len;
391 /* ------------------------------------------------------------------------- */
393 * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
394 * involved to ensure reclaim of locks after a crash of the "stateless"
397 * These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
398 * The first are standard RPCs with argument and result.
399 * The nlm_xxx_msg() calls implement exactly the same functions, but
400 * use two pseudo-RPCs (one in each direction). These calls are NOT
401 * standard use of the RPC protocol in that they do not return a result
402 * at all (NB. this is quite different from returning a void result).
403 * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
404 * datagrams, requiring higher-level code to perform retries.
406 * Despite the disadvantages of the nlm_xxx_msg() approach (some of which
407 * are documented in the comments to get_client() above), this is the
408 * interface used by all current commercial NFS implementations
409 * [Solaris, SCO, AIX etc.]. This is presumed to be because these allow
410 * implementations to continue using the standard RPC libraries, while
411 * avoiding the block-until-result nature of the library interface.
413 * No client implementations have been identified so far that make use
414 * of the true RPC version (early SunOS releases would be a likely candidate
418 /* nlm_test ---------------------------------------------------------------- */
420 * Purpose: Test whether a specified lock would be granted if requested
421 * Returns: nlm_granted (or error code)
425 nlm_test_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
427 static nlm_testres res;
428 struct nlm4_lock arg4;
429 struct nlm4_holder *holder;
430 nlmtonlm4(&arg->alock, &arg4);
433 log_from_addr("nlm_test", rqstp);
435 holder = testlock(&arg4, arg->exclusive, 0);
437 * Copy the cookie from the argument into the result. Note that this
438 * is slightly hazardous, as the structure contains a pointer to a
439 * malloc()ed buffer that will get freed by the caller. However, the
440 * main function transmits the result before freeing the argument
441 * so it is in fact safe.
443 res.cookie = arg->cookie;
444 if (holder == NULL) {
445 res.stat.stat = nlm_granted;
447 res.stat.stat = nlm_denied;
448 memcpy(&res.stat.nlm_testrply_u.holder, holder,
449 sizeof(struct nlm_holder));
450 res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
451 res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
457 nlm_test_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
461 struct sockaddr *addr;
464 struct timeval timeo;
465 struct nlm4_lock arg4;
466 struct nlm4_holder *holder;
468 nlmtonlm4(&arg->alock, &arg4);
471 log_from_addr("nlm_test_msg", rqstp);
473 holder = testlock(&arg4, arg->exclusive, 0);
475 res.cookie = arg->cookie;
476 if (holder == NULL) {
477 res.stat.stat = nlm_granted;
479 res.stat.stat = nlm_denied;
480 memcpy(&res.stat.nlm_testrply_u.holder, holder,
481 sizeof(struct nlm_holder));
482 res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
483 res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
487 * nlm_test has different result type to the other operations, so
488 * can't use transmit_result() in this case
490 addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
491 if ((cli = get_client(addr, NLM_VERS)) != NULL) {
492 timeo.tv_sec = 0; /* No timeout - not expecting response */
495 success = clnt_call(cli, NLM_TEST_RES,
496 (xdrproc_t)xdr_nlm_testres, &res,
497 (xdrproc_t)xdr_void, &dummy, timeo);
500 syslog(LOG_DEBUG, "clnt_call returns %d", success);
505 /* nlm_lock ---------------------------------------------------------------- */
507 * Purposes: Establish a lock
508 * Returns: granted, denied or blocked
509 * Notes: *** grace period support missing
512 nlm_lock_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
515 struct nlm4_lockargs arg4;
516 nlmtonlm4(&arg->alock, &arg4.alock);
517 arg4.cookie = arg->cookie;
518 arg4.block = arg->block;
519 arg4.exclusive = arg->exclusive;
520 arg4.reclaim = arg->reclaim;
521 arg4.state = arg->state;
524 log_from_addr("nlm_lock", rqstp);
526 /* copy cookie from arg to result. See comment in nlm_test_1() */
527 res.cookie = arg->cookie;
529 res.stat.stat = getlock(&arg4, rqstp, LOCK_MON);
534 nlm_lock_msg_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
537 struct nlm4_lockargs arg4;
539 nlmtonlm4(&arg->alock, &arg4.alock);
540 arg4.cookie = arg->cookie;
541 arg4.block = arg->block;
542 arg4.exclusive = arg->exclusive;
543 arg4.reclaim = arg->reclaim;
544 arg4.state = arg->state;
547 log_from_addr("nlm_lock_msg", rqstp);
549 res.cookie = arg->cookie;
550 res.stat.stat = getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON);
551 transmit_result(NLM_LOCK_RES, &res, getrpcaddr(rqstp));
556 /* nlm_cancel -------------------------------------------------------------- */
558 * Purpose: Cancel a blocked lock request
559 * Returns: granted or denied
563 nlm_cancel_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
566 struct nlm4_lock arg4;
568 nlmtonlm4(&arg->alock, &arg4);
571 log_from_addr("nlm_cancel", rqstp);
573 /* copy cookie from arg to result. See comment in nlm_test_1() */
574 res.cookie = arg->cookie;
577 * Since at present we never return 'nlm_blocked', there can never be
578 * a lock to cancel, so this call always fails.
580 res.stat.stat = unlock(&arg4, LOCK_CANCEL);
585 nlm_cancel_msg_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
588 struct nlm4_lock arg4;
590 nlmtonlm4(&arg->alock, &arg4);
593 log_from_addr("nlm_cancel_msg", rqstp);
595 res.cookie = arg->cookie;
597 * Since at present we never return 'nlm_blocked', there can never be
598 * a lock to cancel, so this call always fails.
600 res.stat.stat = unlock(&arg4, LOCK_CANCEL);
601 transmit_result(NLM_CANCEL_RES, &res, getrpcaddr(rqstp));
605 /* nlm_unlock -------------------------------------------------------------- */
607 * Purpose: Release an existing lock
608 * Returns: Always granted, unless during grace period
609 * Notes: "no such lock" error condition is ignored, as the
610 * protocol uses unreliable UDP datagrams, and may well
611 * re-try an unlock that has already succeeded.
614 nlm_unlock_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
617 struct nlm4_lock arg4;
619 nlmtonlm4(&arg->alock, &arg4);
622 log_from_addr("nlm_unlock", rqstp);
624 res.stat.stat = unlock(&arg4, 0);
625 res.cookie = arg->cookie;
631 nlm_unlock_msg_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
634 struct nlm4_lock arg4;
636 nlmtonlm4(&arg->alock, &arg4);
639 log_from_addr("nlm_unlock_msg", rqstp);
641 res.stat.stat = unlock(&arg4, 0);
642 res.cookie = arg->cookie;
644 transmit_result(NLM_UNLOCK_RES, &res, getrpcaddr(rqstp));
648 /* ------------------------------------------------------------------------- */
650 * Client-side pseudo-RPCs for results. Note that for the client there
651 * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
652 * version returns the results in the RPC result, and so the client
653 * does not normally receive incoming RPCs.
655 * The exception to this is nlm_granted(), which is genuinely an RPC
656 * call from the server to the client - a 'call-back' in normal procedure
660 /* nlm_granted ------------------------------------------------------------- */
662 * Purpose: Receive notification that formerly blocked lock now granted
663 * Returns: always success ('granted')
667 nlm_granted_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
672 log_from_addr("nlm_granted", rqstp);
674 res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
675 nlm_granted, NULL, NLM_VERS) == 0 ?
676 nlm_granted : nlm_denied;
678 /* copy cookie from arg to result. See comment in nlm_test_1() */
679 res.cookie = arg->cookie;
685 nlm_granted_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
690 log_from_addr("nlm_granted_msg", rqstp);
692 res.cookie = arg->cookie;
693 res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
694 nlm_granted, NULL, NLM_VERS) == 0 ?
695 nlm_granted : nlm_denied;
697 transmit_result(NLM_GRANTED_RES, &res, getrpcaddr(rqstp));
701 /* nlm_test_res ------------------------------------------------------------ */
703 * Purpose: Accept result from earlier nlm_test_msg() call
707 nlm_test_res_1_svc(nlm_testres *arg, struct svc_req *rqstp)
710 log_from_addr("nlm_test_res", rqstp);
711 (void)lock_answer(-1, &arg->cookie, arg->stat.stat,
712 &arg->stat.nlm_testrply_u.holder.svid, NLM_VERS);
716 /* nlm_lock_res ------------------------------------------------------------ */
718 * Purpose: Accept result from earlier nlm_lock_msg() call
722 nlm_lock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
725 log_from_addr("nlm_lock_res", rqstp);
727 (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS);
732 /* nlm_cancel_res ---------------------------------------------------------- */
734 * Purpose: Accept result from earlier nlm_cancel_msg() call
738 nlm_cancel_res_1_svc(nlm_res *arg __unused, struct svc_req *rqstp)
741 log_from_addr("nlm_cancel_res", rqstp);
745 /* nlm_unlock_res ---------------------------------------------------------- */
747 * Purpose: Accept result from earlier nlm_unlock_msg() call
751 nlm_unlock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
754 log_from_addr("nlm_unlock_res", rqstp);
756 lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS);
761 /* nlm_granted_res --------------------------------------------------------- */
763 * Purpose: Accept result from earlier nlm_granted_msg() call
767 nlm_granted_res_1_svc(nlm_res *arg __unused, struct svc_req *rqstp)
770 log_from_addr("nlm_granted_res", rqstp);
774 /* ------------------------------------------------------------------------- */
776 * Calls for PCNFS locking (aka non-monitored locking, no involvement
779 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
782 /* nlm_share --------------------------------------------------------------- */
784 * Purpose: Establish a DOS-style lock
785 * Returns: success or failure
786 * Notes: Blocking locks are not supported - client is expected
787 * to retry if required.
790 nlm_share_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
792 static nlm_shareres res;
795 log_from_addr("nlm_share", rqstp);
797 res.cookie = arg->cookie;
798 res.stat = nlm_granted;
799 res.sequence = 1234356; /* X/Open says this field is ignored? */
803 /* nlm_unshare ------------------------------------------------------------ */
805 * Purpose: Release a DOS-style lock
806 * Returns: nlm_granted, unless in grace period
810 nlm_unshare_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
812 static nlm_shareres res;
815 log_from_addr("nlm_unshare", rqstp);
817 res.cookie = arg->cookie;
818 res.stat = nlm_granted;
819 res.sequence = 1234356; /* X/Open says this field is ignored? */
823 /* nlm_nm_lock ------------------------------------------------------------ */
825 * Purpose: non-monitored version of nlm_lock()
826 * Returns: as for nlm_lock()
827 * Notes: These locks are in the same style as the standard nlm_lock,
828 * but the rpc.statd should not be called to establish a
829 * monitor for the client machine, since that machine is
830 * declared not to be running a rpc.statd, and so would not
831 * respond to the statd protocol.
834 nlm_nm_lock_3_svc(nlm_lockargs *arg, struct svc_req *rqstp)
839 log_from_addr("nlm_nm_lock", rqstp);
841 /* copy cookie from arg to result. See comment in nlm_test_1() */
842 res.cookie = arg->cookie;
843 res.stat.stat = nlm_granted;
847 /* nlm_free_all ------------------------------------------------------------ */
849 * Purpose: Release all locks held by a named client
851 * Notes: Potential denial of service security problem here - the
852 * locks to be released are specified by a host name, independent
853 * of the address from which the request has arrived.
854 * Should probably be rejected if the named host has been
855 * using monitored locks.
858 nlm_free_all_3_svc(nlm_notify *arg __unused, struct svc_req *rqstp)
863 log_from_addr("nlm_free_all", rqstp);
867 /* calls for nlm version 4 (NFSv3) */
868 /* nlm_test ---------------------------------------------------------------- */
870 * Purpose: Test whether a specified lock would be granted if requested
871 * Returns: nlm_granted (or error code)
875 nlm4_test_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
877 static nlm4_testres res;
878 struct nlm4_holder *holder;
881 log_from_addr("nlm4_test", rqstp);
882 if (debug_level > 5) {
883 syslog(LOG_DEBUG, "Locking arguments:\n");
884 log_netobj(&(arg->cookie));
885 syslog(LOG_DEBUG, "Alock arguments:\n");
886 syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name);
887 syslog(LOG_DEBUG, "File Handle:\n");
888 log_netobj(&(arg->alock.fh));
889 syslog(LOG_DEBUG, "Owner Handle:\n");
890 log_netobj(&(arg->alock.oh));
891 syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid);
892 syslog(LOG_DEBUG, "Lock Offset: %llu\n",
893 (unsigned long long)arg->alock.l_offset);
894 syslog(LOG_DEBUG, "Lock Length: %llu\n",
895 (unsigned long long)arg->alock.l_len);
896 syslog(LOG_DEBUG, "Exclusive: %s\n",
897 (arg->exclusive ? "true" : "false"));
900 holder = testlock(&arg->alock, arg->exclusive, LOCK_V4);
903 * Copy the cookie from the argument into the result. Note that this
904 * is slightly hazardous, as the structure contains a pointer to a
905 * malloc()ed buffer that will get freed by the caller. However, the
906 * main function transmits the result before freeing the argument
907 * so it is in fact safe.
909 res.cookie = arg->cookie;
910 if (holder == NULL) {
911 res.stat.stat = nlm4_granted;
913 res.stat.stat = nlm4_denied;
914 memcpy(&res.stat.nlm4_testrply_u.holder, holder,
915 sizeof(struct nlm4_holder));
921 nlm4_test_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
925 struct sockaddr *addr;
928 struct timeval timeo;
929 struct nlm4_holder *holder;
932 log_from_addr("nlm4_test_msg", rqstp);
934 holder = testlock(&arg->alock, arg->exclusive, LOCK_V4);
936 res.cookie = arg->cookie;
937 if (holder == NULL) {
938 res.stat.stat = nlm4_granted;
940 res.stat.stat = nlm4_denied;
941 memcpy(&res.stat.nlm4_testrply_u.holder, holder,
942 sizeof(struct nlm4_holder));
946 * nlm_test has different result type to the other operations, so
947 * can't use transmit4_result() in this case
949 addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
950 if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
951 timeo.tv_sec = 0; /* No timeout - not expecting response */
954 success = clnt_call(cli, NLM4_TEST_RES,
955 (xdrproc_t)xdr_nlm4_testres, &res,
956 (xdrproc_t)xdr_void, &dummy, timeo);
959 syslog(LOG_DEBUG, "clnt_call returns %d", success);
964 /* nlm_lock ---------------------------------------------------------------- */
966 * Purposes: Establish a lock
967 * Returns: granted, denied or blocked
968 * Notes: *** grace period support missing
971 nlm4_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
976 log_from_addr("nlm4_lock", rqstp);
977 if (debug_level > 5) {
978 syslog(LOG_DEBUG, "Locking arguments:\n");
979 log_netobj(&(arg->cookie));
980 syslog(LOG_DEBUG, "Alock arguments:\n");
981 syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name);
982 syslog(LOG_DEBUG, "File Handle:\n");
983 log_netobj(&(arg->alock.fh));
984 syslog(LOG_DEBUG, "Owner Handle:\n");
985 log_netobj(&(arg->alock.oh));
986 syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid);
987 syslog(LOG_DEBUG, "Lock Offset: %llu\n",
988 (unsigned long long)arg->alock.l_offset);
989 syslog(LOG_DEBUG, "Lock Length: %llu\n",
990 (unsigned long long)arg->alock.l_len);
991 syslog(LOG_DEBUG, "Block: %s\n", (arg->block ? "true" : "false"));
992 syslog(LOG_DEBUG, "Exclusive: %s\n", (arg->exclusive ? "true" : "false"));
993 syslog(LOG_DEBUG, "Reclaim: %s\n", (arg->reclaim ? "true" : "false"));
994 syslog(LOG_DEBUG, "State num: %d\n", arg->state);
997 /* copy cookie from arg to result. See comment in nlm_test_4() */
998 res.cookie = arg->cookie;
1000 res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_V4);
1005 nlm4_lock_msg_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
1007 static nlm4_res res;
1010 log_from_addr("nlm4_lock_msg", rqstp);
1012 res.cookie = arg->cookie;
1013 res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_ASYNC | LOCK_V4);
1014 transmit4_result(NLM4_LOCK_RES, &res, getrpcaddr(rqstp));
1019 /* nlm_cancel -------------------------------------------------------------- */
1021 * Purpose: Cancel a blocked lock request
1022 * Returns: granted or denied
1026 nlm4_cancel_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
1028 static nlm4_res res;
1031 log_from_addr("nlm4_cancel", rqstp);
1033 /* copy cookie from arg to result. See comment in nlm_test_1() */
1034 res.cookie = arg->cookie;
1037 * Since at present we never return 'nlm_blocked', there can never be
1038 * a lock to cancel, so this call always fails.
1040 res.stat.stat = unlock(&arg->alock, LOCK_CANCEL);
1045 nlm4_cancel_msg_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
1047 static nlm4_res res;
1050 log_from_addr("nlm4_cancel_msg", rqstp);
1052 res.cookie = arg->cookie;
1054 * Since at present we never return 'nlm_blocked', there can never be
1055 * a lock to cancel, so this call always fails.
1057 res.stat.stat = unlock(&arg->alock, LOCK_CANCEL | LOCK_V4);
1058 transmit4_result(NLM4_CANCEL_RES, &res, getrpcaddr(rqstp));
1062 /* nlm_unlock -------------------------------------------------------------- */
1064 * Purpose: Release an existing lock
1065 * Returns: Always granted, unless during grace period
1066 * Notes: "no such lock" error condition is ignored, as the
1067 * protocol uses unreliable UDP datagrams, and may well
1068 * re-try an unlock that has already succeeded.
1071 nlm4_unlock_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
1073 static nlm4_res res;
1076 log_from_addr("nlm4_unlock", rqstp);
1078 res.stat.stat = unlock(&arg->alock, LOCK_V4);
1079 res.cookie = arg->cookie;
1085 nlm4_unlock_msg_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
1087 static nlm4_res res;
1090 log_from_addr("nlm4_unlock_msg", rqstp);
1092 res.stat.stat = unlock(&arg->alock, LOCK_V4);
1093 res.cookie = arg->cookie;
1095 transmit4_result(NLM4_UNLOCK_RES, &res, getrpcaddr(rqstp));
1099 /* ------------------------------------------------------------------------- */
1101 * Client-side pseudo-RPCs for results. Note that for the client there
1102 * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
1103 * version returns the results in the RPC result, and so the client
1104 * does not normally receive incoming RPCs.
1106 * The exception to this is nlm_granted(), which is genuinely an RPC
1107 * call from the server to the client - a 'call-back' in normal procedure
1111 /* nlm_granted ------------------------------------------------------------- */
1113 * Purpose: Receive notification that formerly blocked lock now granted
1114 * Returns: always success ('granted')
1118 nlm4_granted_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
1120 static nlm4_res res;
1123 log_from_addr("nlm4_granted", rqstp);
1125 res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
1126 nlm4_granted, NULL, NLM_VERS4) == 0 ?
1127 nlm4_granted : nlm4_denied;
1129 /* copy cookie from arg to result. See comment in nlm_test_1() */
1130 res.cookie = arg->cookie;
1136 nlm4_granted_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
1138 static nlm4_res res;
1141 log_from_addr("nlm4_granted_msg", rqstp);
1143 res.cookie = arg->cookie;
1144 res.stat.stat = lock_answer(arg->alock.svid, &arg->cookie,
1145 nlm4_granted, NULL, NLM_VERS4) == 0 ?
1146 nlm4_granted : nlm4_denied;
1147 transmit4_result(NLM4_GRANTED_RES, &res, getrpcaddr(rqstp));
1151 /* nlm_test_res ------------------------------------------------------------ */
1153 * Purpose: Accept result from earlier nlm_test_msg() call
1157 nlm4_test_res_4_svc(nlm4_testres *arg, struct svc_req *rqstp)
1160 log_from_addr("nlm4_test_res", rqstp);
1162 (void)lock_answer(-1, &arg->cookie, arg->stat.stat,
1163 (int *)&arg->stat.nlm4_testrply_u.holder.svid,
1168 /* nlm_lock_res ------------------------------------------------------------ */
1170 * Purpose: Accept result from earlier nlm_lock_msg() call
1174 nlm4_lock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
1177 log_from_addr("nlm4_lock_res", rqstp);
1179 (void)lock_answer(-1, &arg->cookie, arg->stat.stat, NULL, NLM_VERS4);
1184 /* nlm_cancel_res ---------------------------------------------------------- */
1186 * Purpose: Accept result from earlier nlm_cancel_msg() call
1190 nlm4_cancel_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp)
1193 log_from_addr("nlm4_cancel_res", rqstp);
1197 /* nlm_unlock_res ---------------------------------------------------------- */
1199 * Purpose: Accept result from earlier nlm_unlock_msg() call
1203 nlm4_unlock_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp)
1206 log_from_addr("nlm4_unlock_res", rqstp);
1210 /* nlm_granted_res --------------------------------------------------------- */
1212 * Purpose: Accept result from earlier nlm_granted_msg() call
1216 nlm4_granted_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp)
1219 log_from_addr("nlm4_granted_res", rqstp);
1223 /* ------------------------------------------------------------------------- */
1225 * Calls for PCNFS locking (aka non-monitored locking, no involvement
1228 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
1231 /* nlm_share --------------------------------------------------------------- */
1233 * Purpose: Establish a DOS-style lock
1234 * Returns: success or failure
1235 * Notes: Blocking locks are not supported - client is expected
1236 * to retry if required.
1239 nlm4_share_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
1241 static nlm4_shareres res;
1244 log_from_addr("nlm4_share", rqstp);
1246 res.cookie = arg->cookie;
1247 res.stat = nlm4_granted;
1248 res.sequence = 1234356; /* X/Open says this field is ignored? */
1252 /* nlm4_unshare ------------------------------------------------------------ */
1254 * Purpose: Release a DOS-style lock
1255 * Returns: nlm_granted, unless in grace period
1259 nlm4_unshare_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
1261 static nlm4_shareres res;
1264 log_from_addr("nlm_unshare", rqstp);
1266 res.cookie = arg->cookie;
1267 res.stat = nlm4_granted;
1268 res.sequence = 1234356; /* X/Open says this field is ignored? */
1272 /* nlm4_nm_lock ------------------------------------------------------------ */
1274 * Purpose: non-monitored version of nlm4_lock()
1275 * Returns: as for nlm4_lock()
1276 * Notes: These locks are in the same style as the standard nlm4_lock,
1277 * but the rpc.statd should not be called to establish a
1278 * monitor for the client machine, since that machine is
1279 * declared not to be running a rpc.statd, and so would not
1280 * respond to the statd protocol.
1283 nlm4_nm_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
1285 static nlm4_res res;
1288 log_from_addr("nlm4_nm_lock", rqstp);
1290 /* copy cookie from arg to result. See comment in nlm4_test_1() */
1291 res.cookie = arg->cookie;
1292 res.stat.stat = nlm4_granted;
1296 /* nlm4_free_all ------------------------------------------------------------ */
1298 * Purpose: Release all locks held by a named client
1300 * Notes: Potential denial of service security problem here - the
1301 * locks to be released are specified by a host name, independent
1302 * of the address from which the request has arrived.
1303 * Should probably be rejected if the named host has been
1304 * using monitored locks.
1307 nlm4_free_all_4_svc(struct nlm4_notify *arg __unused, struct svc_req *rqstp)
1312 log_from_addr("nlm4_free_all", rqstp);
1316 /* nlm_sm_notify --------------------------------------------------------- */
1318 * Purpose: called by rpc.statd when a monitored host state changes.
1322 nlm_sm_notify_0_svc(struct nlm_sm_status *arg, struct svc_req *rqstp __unused)
1325 notify(arg->mon_name, arg->state);