1 /* $NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $ */
2 /* $FreeBSD: src/usr.sbin/rpc.lockd/lock_proc.c,v 1.10 2002/03/22 20:00:10 alfred 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>
53 #include <rpcsvc/sm_inter.h>
54 #include <rpcsvc/nlm_prot.h>
57 #include "lockd_lock.h"
60 #define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */
61 #define CLIENT_CACHE_LIFETIME 120 /* In seconds */
63 static void log_from_addr(const char *, struct svc_req
*);
64 static void log_netobj(netobj
*obj
);
65 static int addrcmp(struct sockaddr
*, struct sockaddr
*);
67 /* log_from_addr ----------------------------------------------------------- */
69 * Purpose: Log name of function called and source address
71 * Notes: Extracts the source address from the transport handle
72 * passed in as part of the called procedure specification
75 log_from_addr(fun_name
, req
)
79 struct sockaddr_in
*addr
;
80 char hostname_buf
[NI_MAXHOST
];
82 addr
= svc_getcaller(req
->rq_xprt
);
83 if (getnameinfo((struct sockaddr
*)addr
, sizeof(*addr
), hostname_buf
, sizeof hostname_buf
,
87 syslog(LOG_DEBUG
, "%s from %s", fun_name
, hostname_buf
);
90 /* log_netobj ----------------------------------------------------------- */
92 * Purpose: Log a netobj
94 * Notes: This function should only really be called as part of
101 char objvalbuffer
[(sizeof(char)*2)*MAX_NETOBJ_SZ
+2];
102 char objascbuffer
[sizeof(char)*MAX_NETOBJ_SZ
+1];
103 unsigned int i
, maxlen
;
106 /* Notify of potential security attacks */
107 if (obj
->n_len
> MAX_NETOBJ_SZ
) {
108 syslog(LOG_DEBUG
, "SOMEONE IS TRYING TO DO SOMETHING NASTY!\n");
109 syslog(LOG_DEBUG
, "netobj too large! Should be %d was %d\n",
110 MAX_NETOBJ_SZ
, obj
->n_len
);
112 /* Prevent the security hazard from the buffer overflow */
113 maxlen
= (obj
->n_len
< MAX_NETOBJ_SZ
? obj
->n_len
: MAX_NETOBJ_SZ
);
114 for (i
=0, tmp1
= objvalbuffer
, tmp2
= objascbuffer
; i
< obj
->n_len
;
115 i
++, tmp1
+=2, tmp2
+=1) {
116 sprintf(tmp1
,"%02X",*(obj
->n_bytes
+i
));
117 sprintf(tmp2
,"%c",*(obj
->n_bytes
+i
));
121 syslog(LOG_DEBUG
,"netobjvals: %s\n",objvalbuffer
);
122 syslog(LOG_DEBUG
,"netobjascs: %s\n",objascbuffer
);
124 /* get_client -------------------------------------------------------------- */
126 * Purpose: Get a CLIENT* for making RPC calls to lockd on given host
127 * Returns: CLIENT* pointer, from clnt_udp_create, or NULL if error
128 * Notes: Creating a CLIENT* is quite expensive, involving a
129 * conversation with the remote portmapper to get the
130 * port number. Since a given client is quite likely
131 * to make several locking requests in succession, it is
132 * desirable to cache the created CLIENT*.
134 * Since we are using UDP rather than TCP, there is no cost
135 * to the remote system in keeping these cached indefinitely.
136 * Unfortunately there is a snag: if the remote system
137 * reboots, the cached portmapper results will be invalid,
138 * and we will never detect this since all of the xxx_msg()
139 * calls return no result - we just fire off a udp packet
140 * and hope for the best.
142 * We solve this by discarding cached values after two
143 * minutes, regardless of whether they have been used
144 * in the meanwhile (since a bad one might have been used
145 * plenty of times, as the host keeps retrying the request
146 * and we keep sending the reply back to the wrong port).
148 * Given that the entries will always expire in the order
149 * that they were created, there is no point in a LRU
150 * algorithm for when the cache gets full - entries are
151 * always re-used in sequence.
153 static CLIENT
*clnt_cache_ptr
[CLIENT_CACHE_SIZE
];
154 static long clnt_cache_time
[CLIENT_CACHE_SIZE
]; /* time entry created */
155 static struct sockaddr_storage clnt_cache_addr
[CLIENT_CACHE_SIZE
];
156 static rpcvers_t clnt_cache_vers
[CLIENT_CACHE_SIZE
];
157 static int clnt_cache_next_to_use
= 0;
161 struct sockaddr
*sa1
;
162 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(host_addr
, vers
)
190 struct sockaddr
*host_addr
;
194 struct timeval retry_time
, time_now
;
197 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
;
235 /* Create the new client handle */
237 sock_no
= RPC_ANYSOCK
;
238 retry_time
.tv_sec
= 5;
239 retry_time
.tv_usec
= 0;
240 ((struct sockaddr_in
*)host_addr
)->sin_port
= 0; /* Force consultation with portmapper */
241 client
= clntudp_create((struct sockaddr_in
*)host_addr
, NLM_PROG
, vers
, retry_time
, &sock_no
);
243 syslog(LOG_DEBUG
, "%s", clnt_spcreateerror("clntudp_create"));
244 syslog(LOG_DEBUG
, "Unable to contact %s",
245 inet_ntoa(((struct sockaddr_in
*)host_addr
)->sin_addr
));
249 /* Success - update the cache entry */
250 clnt_cache_ptr
[clnt_cache_next_to_use
] = client
;
251 memcpy(&clnt_cache_addr
[clnt_cache_next_to_use
], host_addr
,
253 clnt_cache_vers
[clnt_cache_next_to_use
] = vers
;
254 clnt_cache_time
[clnt_cache_next_to_use
] = time_now
.tv_sec
;
255 if (++clnt_cache_next_to_use
> CLIENT_CACHE_SIZE
)
256 clnt_cache_next_to_use
= 0;
259 * Disable the default timeout, so we can specify our own in calls
260 * to clnt_call(). (Note that the timeout is a different concept
261 * from the retry period set in clnt_udp_create() above.)
263 retry_time
.tv_sec
= -1;
264 retry_time
.tv_usec
= -1;
265 clnt_control(client
, CLSET_TIMEOUT
, (char *)&retry_time
);
268 syslog(LOG_DEBUG
, "Created CLIENT* for %s", host
);
273 /* transmit_result --------------------------------------------------------- */
275 * Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs
276 * Returns: Nothing - we have no idea if the datagram got there
277 * Notes: clnt_call() will always fail (with timeout) as we are
278 * calling it with timeout 0 as a hack to just issue a datagram
279 * without expecting a result
282 transmit_result(opcode
, result
, addr
)
285 struct sockaddr
*addr
;
289 struct timeval timeo
;
292 if ((cli
= get_client(addr
, NLM_VERS
)) != NULL
) {
293 timeo
.tv_sec
= 0; /* No timeout - not expecting response */
296 success
= clnt_call(cli
, opcode
, xdr_nlm_res
, result
, xdr_void
,
300 syslog(LOG_DEBUG
, "clnt_call returns %d(%s)",
301 success
, clnt_sperrno(success
));
304 /* transmit4_result --------------------------------------------------------- */
306 * Purpose: Transmit result for nlm4_xxx_msg pseudo-RPCs
307 * Returns: Nothing - we have no idea if the datagram got there
308 * Notes: clnt_call() will always fail (with timeout) as we are
309 * calling it with timeout 0 as a hack to just issue a datagram
310 * without expecting a result
313 transmit4_result(opcode
, result
, addr
)
316 struct sockaddr
*addr
;
320 struct timeval timeo
;
323 if ((cli
= get_client(addr
, NLM_VERS4
)) != NULL
) {
324 timeo
.tv_sec
= 0; /* No timeout - not expecting response */
327 success
= clnt_call(cli
, opcode
, xdr_nlm4_res
, result
, xdr_void
,
331 syslog(LOG_DEBUG
, "clnt_call returns %d(%s)",
332 success
, clnt_sperrno(success
));
337 * converts a struct nlm_lock to struct nlm4_lock
339 static void nlmtonlm4(struct nlm_lock
*, struct nlm4_lock
*);
342 struct nlm_lock
*arg
;
343 struct nlm4_lock
*arg4
;
345 memcpy(arg4
, arg
, sizeof(nlm_lock
));
346 arg4
->l_offset
= arg
->l_offset
;
347 arg4
->l_len
= arg
->l_len
;
349 /* ------------------------------------------------------------------------- */
351 * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
352 * involved to ensure reclaim of locks after a crash of the "stateless"
355 * These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
356 * The first are standard RPCs with argument and result.
357 * The nlm_xxx_msg() calls implement exactly the same functions, but
358 * use two pseudo-RPCs (one in each direction). These calls are NOT
359 * standard use of the RPC protocol in that they do not return a result
360 * at all (NB. this is quite different from returning a void result).
361 * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
362 * datagrams, requiring higher-level code to perform retries.
364 * Despite the disadvantages of the nlm_xxx_msg() approach (some of which
365 * are documented in the comments to get_client() above), this is the
366 * interface used by all current commercial NFS implementations
367 * [Solaris, SCO, AIX etc.]. This is presumed to be because these allow
368 * implementations to continue using the standard RPC libraries, while
369 * avoiding the block-until-result nature of the library interface.
371 * No client implementations have been identified so far that make use
372 * of the true RPC version (early SunOS releases would be a likely candidate
376 /* nlm_test ---------------------------------------------------------------- */
378 * Purpose: Test whether a specified lock would be granted if requested
379 * Returns: nlm_granted (or error code)
383 nlm_test_1_svc(arg
, rqstp
)
385 struct svc_req
*rqstp
;
387 static nlm_testres res
;
388 struct nlm4_lock arg4
;
389 struct nlm4_holder
*holder
;
390 nlmtonlm4(&arg
->alock
, &arg4
);
393 log_from_addr("nlm_test", rqstp
);
395 holder
= testlock(&arg4
, arg
->exclusive
, 0);
397 * Copy the cookie from the argument into the result. Note that this
398 * is slightly hazardous, as the structure contains a pointer to a
399 * malloc()ed buffer that will get freed by the caller. However, the
400 * main function transmits the result before freeing the argument
401 * so it is in fact safe.
403 res
.cookie
= arg
->cookie
;
404 if (holder
== NULL
) {
405 res
.stat
.stat
= nlm_granted
;
407 res
.stat
.stat
= nlm_denied
;
408 memcpy(&res
.stat
.nlm_testrply_u
.holder
, holder
,
409 sizeof(struct nlm_holder
));
410 res
.stat
.nlm_testrply_u
.holder
.l_offset
= holder
->l_offset
;
411 res
.stat
.nlm_testrply_u
.holder
.l_len
= holder
->l_len
;
417 nlm_test_msg_1_svc(arg
, rqstp
)
419 struct svc_req
*rqstp
;
423 struct sockaddr
*addr
;
426 struct timeval timeo
;
427 struct nlm4_lock arg4
;
428 struct nlm4_holder
*holder
;
430 nlmtonlm4(&arg
->alock
, &arg4
);
433 log_from_addr("nlm_test_msg", rqstp
);
435 holder
= testlock(&arg4
, arg
->exclusive
, 0);
437 res
.cookie
= arg
->cookie
;
438 if (holder
== NULL
) {
439 res
.stat
.stat
= nlm_granted
;
441 res
.stat
.stat
= nlm_denied
;
442 memcpy(&res
.stat
.nlm_testrply_u
.holder
, holder
,
443 sizeof(struct nlm_holder
));
444 res
.stat
.nlm_testrply_u
.holder
.l_offset
= holder
->l_offset
;
445 res
.stat
.nlm_testrply_u
.holder
.l_len
= holder
->l_len
;
449 * nlm_test has different result type to the other operations, so
450 * can't use transmit_result() in this case
452 addr
= (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
);
453 if ((cli
= get_client(addr
, NLM_VERS
)) != NULL
) {
454 timeo
.tv_sec
= 0; /* No timeout - not expecting response */
457 success
= clnt_call(cli
, NLM_TEST_RES
, xdr_nlm_testres
,
458 &res
, xdr_void
, &dummy
, timeo
);
461 syslog(LOG_DEBUG
, "clnt_call returns %d", success
);
466 /* nlm_lock ---------------------------------------------------------------- */
468 * Purposes: Establish a lock
469 * Returns: granted, denied or blocked
470 * Notes: *** grace period support missing
473 nlm_lock_1_svc(arg
, rqstp
)
475 struct svc_req
*rqstp
;
478 struct nlm4_lockargs arg4
;
479 nlmtonlm4(&arg
->alock
, &arg4
.alock
);
480 arg4
.cookie
= arg
->cookie
;
481 arg4
.block
= arg
->block
;
482 arg4
.exclusive
= arg
->exclusive
;
483 arg4
.reclaim
= arg
->reclaim
;
484 arg4
.state
= arg
->state
;
487 log_from_addr("nlm_lock", rqstp
);
489 /* copy cookie from arg to result. See comment in nlm_test_1() */
490 res
.cookie
= arg
->cookie
;
492 res
.stat
.stat
= getlock(&arg4
, rqstp
, LOCK_MON
);
497 nlm_lock_msg_1_svc(arg
, rqstp
)
499 struct svc_req
*rqstp
;
502 struct nlm4_lockargs arg4
;
504 nlmtonlm4(&arg
->alock
, &arg4
.alock
);
505 arg4
.cookie
= arg
->cookie
;
506 arg4
.block
= arg
->block
;
507 arg4
.exclusive
= arg
->exclusive
;
508 arg4
.reclaim
= arg
->reclaim
;
509 arg4
.state
= arg
->state
;
512 log_from_addr("nlm_lock_msg", rqstp
);
514 res
.cookie
= arg
->cookie
;
515 res
.stat
.stat
= getlock(&arg4
, rqstp
, LOCK_ASYNC
| LOCK_MON
);
516 transmit_result(NLM_LOCK_RES
, &res
,
517 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
));
522 /* nlm_cancel -------------------------------------------------------------- */
524 * Purpose: Cancel a blocked lock request
525 * Returns: granted or denied
529 nlm_cancel_1_svc(arg
, rqstp
)
531 struct svc_req
*rqstp
;
534 struct nlm4_lock arg4
;
536 nlmtonlm4(&arg
->alock
, &arg4
);
539 log_from_addr("nlm_cancel", rqstp
);
541 /* copy cookie from arg to result. See comment in nlm_test_1() */
542 res
.cookie
= arg
->cookie
;
545 * Since at present we never return 'nlm_blocked', there can never be
546 * a lock to cancel, so this call always fails.
548 res
.stat
.stat
= unlock(&arg4
, LOCK_CANCEL
);
553 nlm_cancel_msg_1_svc(arg
, rqstp
)
555 struct svc_req
*rqstp
;
558 struct nlm4_lock arg4
;
560 nlmtonlm4(&arg
->alock
, &arg4
);
563 log_from_addr("nlm_cancel_msg", rqstp
);
565 res
.cookie
= arg
->cookie
;
567 * Since at present we never return 'nlm_blocked', there can never be
568 * a lock to cancel, so this call always fails.
570 res
.stat
.stat
= unlock(&arg4
, LOCK_CANCEL
);
571 transmit_result(NLM_CANCEL_RES
, &res
,
572 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
));
576 /* nlm_unlock -------------------------------------------------------------- */
578 * Purpose: Release an existing lock
579 * Returns: Always granted, unless during grace period
580 * Notes: "no such lock" error condition is ignored, as the
581 * protocol uses unreliable UDP datagrams, and may well
582 * re-try an unlock that has already succeeded.
585 nlm_unlock_1_svc(arg
, rqstp
)
587 struct svc_req
*rqstp
;
590 struct nlm4_lock arg4
;
592 nlmtonlm4(&arg
->alock
, &arg4
);
595 log_from_addr("nlm_unlock", rqstp
);
597 res
.stat
.stat
= unlock(&arg4
, 0);
598 res
.cookie
= arg
->cookie
;
604 nlm_unlock_msg_1_svc(arg
, rqstp
)
606 struct svc_req
*rqstp
;
609 struct nlm4_lock arg4
;
611 nlmtonlm4(&arg
->alock
, &arg4
);
614 log_from_addr("nlm_unlock_msg", rqstp
);
616 res
.stat
.stat
= unlock(&arg4
, 0);
617 res
.cookie
= arg
->cookie
;
619 transmit_result(NLM_UNLOCK_RES
, &res
,
620 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
));
624 /* ------------------------------------------------------------------------- */
626 * Client-side pseudo-RPCs for results. Note that for the client there
627 * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
628 * version returns the results in the RPC result, and so the client
629 * does not normally receive incoming RPCs.
631 * The exception to this is nlm_granted(), which is genuinely an RPC
632 * call from the server to the client - a 'call-back' in normal procedure
636 /* nlm_granted ------------------------------------------------------------- */
638 * Purpose: Receive notification that formerly blocked lock now granted
639 * Returns: always success ('granted')
643 nlm_granted_1_svc(arg
, rqstp
)
645 struct svc_req
*rqstp
;
650 log_from_addr("nlm_granted", rqstp
);
652 res
.stat
.stat
= lock_answer(arg
->alock
.svid
, &arg
->cookie
,
653 nlm_granted
, NLM_VERS
, NULL
, 0, 0) == 0 ?
654 nlm_granted
: nlm_denied
;
656 /* copy cookie from arg to result. See comment in nlm_test_1() */
657 res
.cookie
= arg
->cookie
;
663 nlm_granted_msg_1_svc(arg
, rqstp
)
665 struct svc_req
*rqstp
;
670 log_from_addr("nlm_granted_msg", rqstp
);
672 res
.stat
.stat
= lock_answer(arg
->alock
.svid
, &arg
->cookie
,
673 nlm_granted
, NLM_VERS
, NULL
, 0, 0) == 0 ?
674 nlm_granted
: nlm_denied
;
676 res
.cookie
= arg
->cookie
;
678 transmit_result(NLM_GRANTED_RES
, &res
,
679 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
));
683 /* nlm_test_res ------------------------------------------------------------ */
685 * Purpose: Accept result from earlier nlm_test_msg() call
689 nlm_test_res_1_svc(arg
, rqstp
)
691 struct svc_req
*rqstp
;
694 log_from_addr("nlm_test_res", rqstp
);
695 (void)lock_answer(-1, &arg
->cookie
, arg
->stat
.stat
, NLM_VERS
,
696 &arg
->stat
.nlm_testrply_u
.holder
.svid
,
697 arg
->stat
.nlm_testrply_u
.holder
.l_offset
,
698 arg
->stat
.nlm_testrply_u
.holder
.l_len
);
702 /* nlm_lock_res ------------------------------------------------------------ */
704 * Purpose: Accept result from earlier nlm_lock_msg() call
708 nlm_lock_res_1_svc(arg
, rqstp
)
710 struct svc_req
*rqstp
;
713 log_from_addr("nlm_lock_res", rqstp
);
715 (void)lock_answer(-1, &arg
->cookie
, arg
->stat
.stat
, NLM_VERS
, NULL
, 0, 0);
720 /* nlm_cancel_res ---------------------------------------------------------- */
722 * Purpose: Accept result from earlier nlm_cancel_msg() call
726 nlm_cancel_res_1_svc(arg
, rqstp
)
727 nlm_res
*arg __unused
;
728 struct svc_req
*rqstp
;
731 log_from_addr("nlm_cancel_res", rqstp
);
735 /* nlm_unlock_res ---------------------------------------------------------- */
737 * Purpose: Accept result from earlier nlm_unlock_msg() call
741 nlm_unlock_res_1_svc(arg
, rqstp
)
743 struct svc_req
*rqstp
;
746 log_from_addr("nlm_unlock_res", rqstp
);
748 lock_answer(-1, &arg
->cookie
, arg
->stat
.stat
, NLM_VERS
, NULL
, 0, 0);
753 /* nlm_granted_res --------------------------------------------------------- */
755 * Purpose: Accept result from earlier nlm_granted_msg() call
759 nlm_granted_res_1_svc(arg
, rqstp
)
760 nlm_res
*arg __unused
;
761 struct svc_req
*rqstp
;
764 log_from_addr("nlm_granted_res", rqstp
);
765 /* XXX should undo lock if granted msg wasn't accepted! */
769 /* ------------------------------------------------------------------------- */
771 * Calls for PCNFS locking (aka non-monitored locking, no involvement
774 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
777 /* nlm_share --------------------------------------------------------------- */
779 * Purpose: Establish a DOS-style lock
780 * Returns: success or failure
781 * Notes: Blocking locks are not supported - client is expected
782 * to retry if required.
785 nlm_share_3_svc(arg
, rqstp
)
787 struct svc_req
*rqstp
;
789 static nlm_shareres res
;
792 log_from_addr("nlm_share", rqstp
);
794 /* copy cookie from arg to result. See comment in nlm_test_1() */
795 res
.cookie
= arg
->cookie
;
796 res
.sequence
= 0; /* X/Open says this field is ignored? */
798 res
.stat
= getshare(arg
, rqstp
, 0);
802 /* nlm_unshare ------------------------------------------------------------ */
804 * Purpose: Release a DOS-style lock
805 * Returns: nlm_granted, unless in grace period
809 nlm_unshare_3_svc(arg
, rqstp
)
811 struct svc_req
*rqstp
;
813 static nlm_shareres res
;
816 log_from_addr("nlm_unshare", rqstp
);
818 res
.cookie
= arg
->cookie
;
819 res
.sequence
= 0; /* X/Open says this field is ignored? */
821 res
.stat
= unshare(arg
, rqstp
);
825 /* nlm_nm_lock ------------------------------------------------------------ */
827 * Purpose: non-monitored version of nlm_lock()
828 * Returns: as for nlm_lock()
829 * Notes: These locks are in the same style as the standard nlm_lock,
830 * but the rpc.statd should not be called to establish a
831 * monitor for the client machine, since that machine is
832 * declared not to be running a rpc.statd, and so would not
833 * respond to the statd protocol.
836 nlm_nm_lock_3_svc(arg
, rqstp
)
838 struct svc_req
*rqstp
;
841 struct nlm4_lockargs arg4
;
842 nlmtonlm4(&arg
->alock
, &arg4
.alock
);
843 arg4
.cookie
= arg
->cookie
;
844 arg4
.block
= arg
->block
;
845 arg4
.exclusive
= arg
->exclusive
;
846 arg4
.reclaim
= arg
->reclaim
;
847 arg4
.state
= arg
->state
;
850 log_from_addr("nlm_nm_lock", rqstp
);
852 /* copy cookie from arg to result. See comment in nlm_test_1() */
853 res
.cookie
= arg
->cookie
;
855 res
.stat
.stat
= getlock(&arg4
, rqstp
, 0);
859 /* nlm_free_all ------------------------------------------------------------ */
861 * Purpose: Release all locks held by a named client
863 * Notes: Potential denial of service security problem here - the
864 * locks to be released are specified by a host name, independent
865 * of the address from which the request has arrived.
866 * Should probably be rejected if the named host has been
867 * using monitored locks.
870 nlm_free_all_3_svc(arg
, rqstp
)
872 struct svc_req
*rqstp
;
877 log_from_addr("nlm_free_all", rqstp
);
879 /* free all non-monitored locks/shares for specified host */
880 do_free_all(arg
->name
);
885 /* calls for nlm version 4 (NFSv3) */
886 /* nlm_test ---------------------------------------------------------------- */
888 * Purpose: Test whether a specified lock would be granted if requested
889 * Returns: nlm_granted (or error code)
893 nlm4_test_4_svc(arg
, rqstp
)
895 struct svc_req
*rqstp
;
897 static nlm4_testres res
;
898 struct nlm4_holder
*holder
;
901 log_from_addr("nlm4_test", rqstp
);
902 if (debug_level
> 5) {
903 syslog(LOG_DEBUG
, "Locking arguments:\n");
904 log_netobj(&(arg
->cookie
));
905 syslog(LOG_DEBUG
, "Alock arguments:\n");
906 syslog(LOG_DEBUG
, "Caller Name: %s\n",arg
->alock
.caller_name
);
907 syslog(LOG_DEBUG
, "File Handle:\n");
908 log_netobj(&(arg
->alock
.fh
));
909 syslog(LOG_DEBUG
, "Owner Handle:\n");
910 log_netobj(&(arg
->alock
.oh
));
911 syslog(LOG_DEBUG
, "SVID: %d\n", arg
->alock
.svid
);
912 syslog(LOG_DEBUG
, "Lock Offset: %llu\n",
913 (unsigned long long)arg
->alock
.l_offset
);
914 syslog(LOG_DEBUG
, "Lock Length: %llu\n",
915 (unsigned long long)arg
->alock
.l_len
);
916 syslog(LOG_DEBUG
, "Exclusive: %s\n",
917 (arg
->exclusive
? "true" : "false"));
920 holder
= testlock(&arg
->alock
, arg
->exclusive
, LOCK_V4
);
923 * Copy the cookie from the argument into the result. Note that this
924 * is slightly hazardous, as the structure contains a pointer to a
925 * malloc()ed buffer that will get freed by the caller. However, the
926 * main function transmits the result before freeing the argument
927 * so it is in fact safe.
929 res
.cookie
= arg
->cookie
;
930 if (holder
== NULL
) {
931 res
.stat
.stat
= nlm4_granted
;
933 res
.stat
.stat
= nlm4_denied
;
934 memcpy(&res
.stat
.nlm4_testrply_u
.holder
, holder
,
935 sizeof(struct nlm4_holder
));
941 nlm4_test_msg_4_svc(arg
, rqstp
)
943 struct svc_req
*rqstp
;
947 struct sockaddr
*addr
;
950 struct timeval timeo
;
951 struct nlm4_holder
*holder
;
954 log_from_addr("nlm4_test_msg", rqstp
);
956 holder
= testlock(&arg
->alock
, arg
->exclusive
, LOCK_V4
);
958 res
.cookie
= arg
->cookie
;
959 if (holder
== NULL
) {
960 res
.stat
.stat
= nlm4_granted
;
962 res
.stat
.stat
= nlm4_denied
;
963 memcpy(&res
.stat
.nlm4_testrply_u
.holder
, holder
,
964 sizeof(struct nlm4_holder
));
968 * nlm_test has different result type to the other operations, so
969 * can't use transmit4_result() in this case
971 addr
= (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
);
972 if ((cli
= get_client(addr
, NLM_VERS4
)) != NULL
) {
973 timeo
.tv_sec
= 0; /* No timeout - not expecting response */
976 success
= clnt_call(cli
, NLM4_TEST_RES
, xdr_nlm4_testres
,
977 &res
, xdr_void
, &dummy
, timeo
);
980 syslog(LOG_DEBUG
, "clnt_call returns %d", success
);
985 /* nlm_lock ---------------------------------------------------------------- */
987 * Purposes: Establish a lock
988 * Returns: granted, denied or blocked
989 * Notes: *** grace period support missing
992 nlm4_lock_4_svc(arg
, rqstp
)
994 struct svc_req
*rqstp
;
999 log_from_addr("nlm4_lock", rqstp
);
1000 if (debug_level
> 5) {
1001 syslog(LOG_DEBUG
, "Locking arguments:\n");
1002 log_netobj(&(arg
->cookie
));
1003 syslog(LOG_DEBUG
, "Alock arguments:\n");
1004 syslog(LOG_DEBUG
, "Caller Name: %s\n",arg
->alock
.caller_name
);
1005 syslog(LOG_DEBUG
, "File Handle:\n");
1006 log_netobj(&(arg
->alock
.fh
));
1007 syslog(LOG_DEBUG
, "Owner Handle:\n");
1008 log_netobj(&(arg
->alock
.oh
));
1009 syslog(LOG_DEBUG
, "SVID: %d\n", arg
->alock
.svid
);
1010 syslog(LOG_DEBUG
, "Lock Offset: %llu\n",
1011 (unsigned long long)arg
->alock
.l_offset
);
1012 syslog(LOG_DEBUG
, "Lock Length: %llu\n",
1013 (unsigned long long)arg
->alock
.l_len
);
1014 syslog(LOG_DEBUG
, "Block: %s\n", (arg
->block
? "true" : "false"));
1015 syslog(LOG_DEBUG
, "Exclusive: %s\n", (arg
->exclusive
? "true" : "false"));
1016 syslog(LOG_DEBUG
, "Reclaim: %s\n", (arg
->reclaim
? "true" : "false"));
1017 syslog(LOG_DEBUG
, "State num: %d\n", arg
->state
);
1020 /* copy cookie from arg to result. See comment in nlm_test_4() */
1021 res
.cookie
= arg
->cookie
;
1023 res
.stat
.stat
= getlock(arg
, rqstp
, LOCK_MON
| LOCK_V4
);
1028 nlm4_lock_msg_4_svc(arg
, rqstp
)
1030 struct svc_req
*rqstp
;
1032 static nlm4_res res
;
1035 log_from_addr("nlm4_lock_msg", rqstp
);
1037 res
.cookie
= arg
->cookie
;
1038 res
.stat
.stat
= getlock(arg
, rqstp
, LOCK_MON
| LOCK_ASYNC
| LOCK_V4
);
1039 transmit4_result(NLM4_LOCK_RES
, &res
,
1040 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
));
1045 /* nlm_cancel -------------------------------------------------------------- */
1047 * Purpose: Cancel a blocked lock request
1048 * Returns: granted or denied
1052 nlm4_cancel_4_svc(arg
, rqstp
)
1054 struct svc_req
*rqstp
;
1056 static nlm4_res res
;
1059 log_from_addr("nlm4_cancel", rqstp
);
1061 /* copy cookie from arg to result. See comment in nlm_test_1() */
1062 res
.cookie
= arg
->cookie
;
1065 * Since at present we never return 'nlm_blocked', there can never be
1066 * a lock to cancel, so this call always fails.
1068 res
.stat
.stat
= unlock(&arg
->alock
, LOCK_CANCEL
);
1073 nlm4_cancel_msg_4_svc(arg
, rqstp
)
1075 struct svc_req
*rqstp
;
1077 static nlm4_res res
;
1080 log_from_addr("nlm4_cancel_msg", rqstp
);
1082 res
.cookie
= arg
->cookie
;
1084 * Since at present we never return 'nlm_blocked', there can never be
1085 * a lock to cancel, so this call always fails.
1087 res
.stat
.stat
= unlock(&arg
->alock
, LOCK_CANCEL
| LOCK_V4
);
1088 transmit4_result(NLM4_CANCEL_RES
, &res
,
1089 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
));
1093 /* nlm_unlock -------------------------------------------------------------- */
1095 * Purpose: Release an existing lock
1096 * Returns: Always granted, unless during grace period
1097 * Notes: "no such lock" error condition is ignored, as the
1098 * protocol uses unreliable UDP datagrams, and may well
1099 * re-try an unlock that has already succeeded.
1102 nlm4_unlock_4_svc(arg
, rqstp
)
1103 nlm4_unlockargs
*arg
;
1104 struct svc_req
*rqstp
;
1106 static nlm4_res res
;
1109 log_from_addr("nlm4_unlock", rqstp
);
1111 res
.stat
.stat
= unlock(&arg
->alock
, LOCK_V4
);
1112 res
.cookie
= arg
->cookie
;
1118 nlm4_unlock_msg_4_svc(arg
, rqstp
)
1119 nlm4_unlockargs
*arg
;
1120 struct svc_req
*rqstp
;
1122 static nlm4_res res
;
1125 log_from_addr("nlm4_unlock_msg", rqstp
);
1127 res
.stat
.stat
= unlock(&arg
->alock
, LOCK_V4
);
1128 res
.cookie
= arg
->cookie
;
1130 transmit4_result(NLM4_UNLOCK_RES
, &res
,
1131 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
));
1135 /* ------------------------------------------------------------------------- */
1137 * Client-side pseudo-RPCs for results. Note that for the client there
1138 * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
1139 * version returns the results in the RPC result, and so the client
1140 * does not normally receive incoming RPCs.
1142 * The exception to this is nlm_granted(), which is genuinely an RPC
1143 * call from the server to the client - a 'call-back' in normal procedure
1147 /* nlm_granted ------------------------------------------------------------- */
1149 * Purpose: Receive notification that formerly blocked lock now granted
1150 * Returns: always success ('granted')
1154 nlm4_granted_4_svc(arg
, rqstp
)
1156 struct svc_req
*rqstp
;
1158 static nlm4_res res
;
1161 log_from_addr("nlm4_granted", rqstp
);
1163 res
.stat
.stat
= lock_answer(arg
->alock
.svid
, &arg
->cookie
,
1164 nlm4_granted
, NLM_VERS4
, NULL
, 0, 0) == 0 ?
1165 nlm4_granted
: nlm4_denied
;
1167 /* copy cookie from arg to result. See comment in nlm_test_1() */
1168 res
.cookie
= arg
->cookie
;
1174 nlm4_granted_msg_4_svc(arg
, rqstp
)
1176 struct svc_req
*rqstp
;
1178 static nlm4_res res
;
1181 log_from_addr("nlm4_granted_msg", rqstp
);
1183 res
.stat
.stat
= lock_answer(arg
->alock
.svid
, &arg
->cookie
,
1184 nlm4_granted
, NLM_VERS4
, NULL
, 0, 0) == 0 ?
1185 nlm4_granted
: nlm4_denied
;
1187 res
.cookie
= arg
->cookie
;
1189 transmit4_result(NLM4_GRANTED_RES
, &res
,
1190 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
));
1194 /* nlm_test_res ------------------------------------------------------------ */
1196 * Purpose: Accept result from earlier nlm_test_msg() call
1200 nlm4_test_res_4_svc(arg
, rqstp
)
1202 struct svc_req
*rqstp
;
1205 log_from_addr("nlm4_test_res", rqstp
);
1207 (void)lock_answer(-1, &arg
->cookie
, arg
->stat
.stat
, NLM_VERS4
,
1208 (int *)&arg
->stat
.nlm4_testrply_u
.holder
.svid
,
1209 arg
->stat
.nlm4_testrply_u
.holder
.l_offset
,
1210 arg
->stat
.nlm4_testrply_u
.holder
.l_len
);
1214 /* nlm_lock_res ------------------------------------------------------------ */
1216 * Purpose: Accept result from earlier nlm_lock_msg() call
1220 nlm4_lock_res_4_svc(arg
, rqstp
)
1222 struct svc_req
*rqstp
;
1225 log_from_addr("nlm4_lock_res", rqstp
);
1227 (void)lock_answer(-1, &arg
->cookie
, arg
->stat
.stat
, NLM_VERS4
, NULL
, 0, 0);
1232 /* nlm_cancel_res ---------------------------------------------------------- */
1234 * Purpose: Accept result from earlier nlm_cancel_msg() call
1238 nlm4_cancel_res_4_svc(arg
, rqstp
)
1239 nlm4_res
*arg __unused
;
1240 struct svc_req
*rqstp
;
1243 log_from_addr("nlm4_cancel_res", rqstp
);
1247 /* nlm_unlock_res ---------------------------------------------------------- */
1249 * Purpose: Accept result from earlier nlm_unlock_msg() call
1253 nlm4_unlock_res_4_svc(arg
, rqstp
)
1254 nlm4_res
*arg __unused
;
1255 struct svc_req
*rqstp
;
1258 log_from_addr("nlm4_unlock_res", rqstp
);
1262 /* nlm_granted_res --------------------------------------------------------- */
1264 * Purpose: Accept result from earlier nlm_granted_msg() call
1268 nlm4_granted_res_4_svc(arg
, rqstp
)
1269 nlm4_res
*arg __unused
;
1270 struct svc_req
*rqstp
;
1273 log_from_addr("nlm4_granted_res", rqstp
);
1274 /* XXX should undo lock if granted msg wasn't accepted! */
1278 /* ------------------------------------------------------------------------- */
1280 * Calls for PCNFS locking (aka non-monitored locking, no involvement
1283 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
1286 /* nlm_share --------------------------------------------------------------- */
1288 * Purpose: Establish a DOS-style lock
1289 * Returns: success or failure
1290 * Notes: Blocking locks are not supported - client is expected
1291 * to retry if required.
1294 nlm4_share_4_svc(arg
, rqstp
)
1295 nlm4_shareargs
*arg
;
1296 struct svc_req
*rqstp
;
1298 static nlm4_shareres res
;
1301 log_from_addr("nlm4_share", rqstp
);
1303 res
.cookie
= arg
->cookie
;
1304 res
.sequence
= 0; /* X/Open says this field is ignored? */
1306 res
.stat
= getshare((nlm_shareargs
*)arg
, rqstp
, LOCK_V4
);
1310 /* nlm4_unshare ------------------------------------------------------------ */
1312 * Purpose: Release a DOS-style lock
1313 * Returns: nlm_granted, unless in grace period
1317 nlm4_unshare_4_svc(arg
, rqstp
)
1318 nlm4_shareargs
*arg
;
1319 struct svc_req
*rqstp
;
1321 static nlm4_shareres res
;
1324 log_from_addr("nlm4_unshare", rqstp
);
1326 res
.cookie
= arg
->cookie
;
1327 res
.sequence
= 0; /* X/Open says this field is ignored? */
1329 res
.stat
= unshare((nlm_shareargs
*)arg
, rqstp
);
1333 /* nlm4_nm_lock ------------------------------------------------------------ */
1335 * Purpose: non-monitored version of nlm4_lock()
1336 * Returns: as for nlm4_lock()
1337 * Notes: These locks are in the same style as the standard nlm4_lock,
1338 * but the rpc.statd should not be called to establish a
1339 * monitor for the client machine, since that machine is
1340 * declared not to be running a rpc.statd, and so would not
1341 * respond to the statd protocol.
1344 nlm4_nm_lock_4_svc(arg
, rqstp
)
1346 struct svc_req
*rqstp
;
1348 static nlm4_res res
;
1351 log_from_addr("nlm4_nm_lock", rqstp
);
1353 /* copy cookie from arg to result. See comment in nlm_test_4() */
1354 res
.cookie
= arg
->cookie
;
1356 res
.stat
.stat
= getlock(arg
, rqstp
, LOCK_V4
);
1360 /* nlm4_free_all ------------------------------------------------------------ */
1362 * Purpose: Release all locks held by a named client
1364 * Notes: Potential denial of service security problem here - the
1365 * locks to be released are specified by a host name, independent
1366 * of the address from which the request has arrived.
1367 * Should probably be rejected if the named host has been
1368 * using monitored locks.
1371 nlm4_free_all_4_svc(arg
, rqstp
)
1372 struct nlm4_notify
*arg
;
1373 struct svc_req
*rqstp
;
1378 log_from_addr("nlm4_free_all", rqstp
);
1380 /* free all non-monitored locks/shares for specified host */
1381 do_free_all(arg
->name
);
1386 /* nlm_sm_notify --------------------------------------------------------- */
1388 * Purpose: called by rpc.statd when a monitored host state changes.
1392 nlm_sm_notify_0_svc(arg
, rqstp
)
1393 struct nlm_sm_status
*arg
;
1394 struct svc_req
*rqstp __unused
;
1397 notify(arg
->mon_name
, arg
->state
);