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>
52 #include <sys/queue.h>
55 #include <rpcsvc/sm_inter.h>
56 #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 static void log_from_addr(const char *, struct svc_req
*);
66 static void log_netobj(netobj
*obj
);
68 /* log_from_addr ----------------------------------------------------------- */
70 * Purpose: Log name of function called and source address
72 * Notes: Extracts the source address from the transport handle
73 * passed in as part of the called procedure specification
76 log_from_addr(fun_name
, req
)
80 struct sockaddr_in
*addr
;
81 char hostname_buf
[NI_MAXHOST
];
83 addr
= svc_getcaller(req
->rq_xprt
);
84 if (getnameinfo((struct sockaddr
*)addr
, sizeof(*addr
), hostname_buf
, sizeof hostname_buf
,
88 syslog(LOG_DEBUG
, "%s from %s", fun_name
, hostname_buf
);
91 /* log_netobj ----------------------------------------------------------- */
93 * Purpose: Log a netobj
95 * Notes: This function should only really be called as part of
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
< obj
->n_len
;
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 * Because lockd is single-threaded, slow/unresponsive portmappers on
162 * clients can cause serious performance issues. So, we keep a list of
163 * these bad hosts, and limit how often we try to get_client() for those hosts.
166 TAILQ_ENTRY(badhost
) list
;
167 struct sockaddr_storage addr
; /* host address */
168 int count
; /* # of occurences */
169 time_t timelast
; /* last attempted */
170 time_t timenext
; /* next allowed */
172 TAILQ_HEAD(badhostlist_head
, badhost
);
173 static struct badhostlist_head badhostlist_head
= TAILQ_HEAD_INITIALIZER(badhostlist_head
);
174 #define BADHOST_CLIENT_TOOK_TOO_LONG 5 /* In seconds */
175 #define BADHOST_INITIAL_DELAY 120 /* In seconds */
176 #define BADHOST_MAXIMUM_DELAY 3600 /* In seconds */
177 #define BADHOST_DELAY_INCREMENT 300 /* In seconds */
180 addrcmp(const struct sockaddr
*sa1
, const struct sockaddr
*sa2
)
185 if (sa1
->sa_family
!= sa2
->sa_family
)
188 switch (sa1
->sa_family
) {
190 p1
= &((struct sockaddr_in
*)sa1
)->sin_addr
;
191 p2
= &((struct sockaddr_in
*)sa2
)->sin_addr
;
195 p1
= &((struct sockaddr_in6
*)sa1
)->sin6_addr
;
196 p2
= &((struct sockaddr_in6
*)sa2
)->sin6_addr
;
203 return memcmp(p1
, p2
, len
);
207 get_client(host_addr
, vers
)
208 struct sockaddr
*host_addr
;
211 CLIENT
*client
, *cached_client
;
212 struct timeval retry_time
, time_now
;
215 time_t time_start
, cache_time
= 0;
216 struct badhost
*badhost
, *nextbadhost
;
218 gettimeofday(&time_now
, NULL
);
221 * Search for the given client in the cache.
223 cached_client
= NULL
;
224 for (i
= 0; i
< CLIENT_CACHE_SIZE
; i
++) {
225 client
= clnt_cache_ptr
[i
];
228 if (clnt_cache_vers
[i
] != vers
)
230 if (addrcmp((struct sockaddr
*)&clnt_cache_addr
[i
], host_addr
))
233 if (((clnt_cache_time
[i
] + CLIENT_CACHE_LIFETIME
) > time_now
.tv_sec
)) {
235 syslog(LOG_DEBUG
, "Found CLIENT* in cache");
238 syslog(LOG_DEBUG
, "Found expired CLIENT* in cache");
239 cached_client
= client
;
240 /* if we end up reusing this guy, make sure we keep the same timestamp */
241 cache_time
= clnt_cache_time
[i
];
242 clnt_cache_time
[i
] = 0L;
243 clnt_cache_ptr
[i
] = NULL
;
249 * Search for the given client in the badhost list.
251 badhost
= TAILQ_FIRST(&badhostlist_head
);
253 nextbadhost
= TAILQ_NEXT(badhost
, list
);
254 if (!addrcmp(host_addr
, (struct sockaddr
*)&badhost
->addr
))
256 if ((badhost
->timelast
+ BADHOST_MAXIMUM_DELAY
) < time_now
.tv_sec
) {
257 /* cleanup entries we haven't heard from in a while */
258 TAILQ_REMOVE(&badhostlist_head
, badhost
, list
);
261 badhost
= nextbadhost
;
264 if (badhost
&& (time_now
.tv_sec
< badhost
->timenext
)) {
266 * We've got a badhost, and we don't want to try
267 * consulting it again yet. If we've got a stale
268 * cached CLIENT*, go ahead and try to use that.
271 syslog(LOG_DEBUG
, "badhost delayed: stale CLIENT* found in cache");
272 /* Free the next entry if it is in use. */
273 if (clnt_cache_ptr
[clnt_cache_next_to_use
]) {
274 clnt_destroy(clnt_cache_ptr
[clnt_cache_next_to_use
]);
275 clnt_cache_ptr
[clnt_cache_next_to_use
] = NULL
;
277 client
= cached_client
;
278 goto update_cache_entry
;
280 syslog(LOG_DEBUG
, "badhost delayed: valid CLIENT* not found in cache");
284 if (debug_level
> 3) {
286 syslog(LOG_DEBUG
, "CLIENT* not found in cache, creating");
288 syslog(LOG_DEBUG
, "stale CLIENT* found in cache, updating");
291 /* Free the next entry if it is in use. */
292 if (clnt_cache_ptr
[clnt_cache_next_to_use
]) {
293 clnt_destroy(clnt_cache_ptr
[clnt_cache_next_to_use
]);
294 clnt_cache_ptr
[clnt_cache_next_to_use
] = NULL
;
297 /* Create the new client handle */
298 time_start
= time_now
.tv_sec
;
300 sock_no
= RPC_ANYSOCK
;
301 retry_time
.tv_sec
= 5;
302 retry_time
.tv_usec
= 0;
303 ((struct sockaddr_in
*)host_addr
)->sin_port
= 0; /* Force consultation with portmapper */
304 client
= clntudp_create((struct sockaddr_in
*)host_addr
, NLM_PROG
, vers
, retry_time
, &sock_no
);
306 gettimeofday(&time_now
, NULL
);
307 if (time_now
.tv_sec
- time_start
>= BADHOST_CLIENT_TOOK_TOO_LONG
) {
309 * The client create took a long time! (slow/unresponsive portmapper?)
310 * Add/update an entry in the badhost list.
312 if (!badhost
&& (badhost
= malloc(sizeof(struct badhost
)))) {
313 /* allocate new badhost */
314 memcpy(&badhost
->addr
, host_addr
, host_addr
->sa_len
);
316 TAILQ_INSERT_TAIL(&badhostlist_head
, badhost
, list
);
319 /* update count and times */
321 badhost
->timelast
= time_now
.tv_sec
;
322 if (badhost
->count
== 1) {
323 /* first timers get a shorter initial delay */
324 badhost
->timenext
= time_now
.tv_sec
+ BADHOST_INITIAL_DELAY
;
326 /* multiple offenders get an increasingly larger delay */
327 int delay
= (badhost
->count
- 1) * BADHOST_DELAY_INCREMENT
;
328 if (delay
> BADHOST_MAXIMUM_DELAY
)
329 delay
= BADHOST_MAXIMUM_DELAY
;
330 badhost
->timenext
= time_now
.tv_sec
+ delay
;
332 /* move to end of list */
333 TAILQ_REMOVE(&badhostlist_head
, badhost
, list
);
334 TAILQ_INSERT_TAIL(&badhostlist_head
, badhost
, list
);
336 } else if (badhost
) {
337 /* host seems good now, remove it from list */
338 TAILQ_REMOVE(&badhostlist_head
, badhost
, list
);
344 /* We couldn't get a new CLIENT* */
345 if (!cached_client
) {
346 syslog(LOG_WARNING
, "Unable to contact %s: %s",
347 inet_ntoa(((struct sockaddr_in
*)host_addr
)->sin_addr
),
348 clnt_spcreateerror("clntudp_create"));
352 * We couldn't get updated info from portmapper, but we did
353 * still have the stale cached data. So we might as well try
356 client
= cached_client
;
357 syslog(LOG_WARNING
, "Unable to update contact info for %s: %s",
358 inet_ntoa(((struct sockaddr_in
*)host_addr
)->sin_addr
),
359 clnt_spcreateerror("clntudp_create"));
362 * We've got a new/updated CLIENT* for this host.
363 * So, destroy any previously cached CLIENT*.
366 clnt_destroy(cached_client
);
369 * Disable the default timeout, so we can specify our own in calls
370 * to clnt_call(). (Note that the timeout is a different concept
371 * from the retry period set in clnt_udp_create() above.)
373 retry_time
.tv_sec
= -1;
374 retry_time
.tv_usec
= -1;
375 clnt_control(client
, CLSET_TIMEOUT
, (char *)&retry_time
);
378 syslog(LOG_DEBUG
, "Created CLIENT* for %s",
379 inet_ntoa(((struct sockaddr_in
*)host_addr
)->sin_addr
));
381 /* make sure the new entry gets the current timestamp */
382 cache_time
= time_now
.tv_sec
;
386 /* Success (of some sort) - update the cache entry */
387 clnt_cache_ptr
[clnt_cache_next_to_use
] = client
;
388 memcpy(&clnt_cache_addr
[clnt_cache_next_to_use
], host_addr
,
390 clnt_cache_vers
[clnt_cache_next_to_use
] = vers
;
391 clnt_cache_time
[clnt_cache_next_to_use
] = cache_time
;
392 if (++clnt_cache_next_to_use
>= CLIENT_CACHE_SIZE
)
393 clnt_cache_next_to_use
= 0;
399 /* transmit_result --------------------------------------------------------- */
401 * Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs
402 * Returns: success (0) or failure (-1) at sending the datagram
403 * Notes: clnt_call() will always fail (with timeout) as we are
404 * calling it with timeout 0 as a hack to just issue a datagram
405 * without expecting a result
408 transmit_result(opcode
, result
, addr
)
411 struct sockaddr
*addr
;
415 struct timeval timeo
;
418 if ((cli
= get_client(addr
, NLM_VERS
)) != NULL
) {
419 timeo
.tv_sec
= 0; /* No timeout - not expecting response */
422 success
= clnt_call(cli
, opcode
, xdr_nlm_res
, result
, xdr_void
,
426 syslog(LOG_DEBUG
, "clnt_call returns %d(%s)",
427 success
, clnt_sperrno(success
));
432 /* transmit4_result --------------------------------------------------------- */
434 * Purpose: Transmit result for nlm4_xxx_msg pseudo-RPCs
435 * Returns: success (0) or failure (-1) at sending the datagram
436 * Notes: clnt_call() will always fail (with timeout) as we are
437 * calling it with timeout 0 as a hack to just issue a datagram
438 * without expecting a result
441 transmit4_result(opcode
, result
, addr
)
444 struct sockaddr
*addr
;
448 struct timeval timeo
;
451 if ((cli
= get_client(addr
, NLM_VERS4
)) != NULL
) {
452 timeo
.tv_sec
= 0; /* No timeout - not expecting response */
455 success
= clnt_call(cli
, opcode
, xdr_nlm4_res
, result
, xdr_void
,
459 syslog(LOG_DEBUG
, "clnt_call returns %d(%s)",
460 success
, clnt_sperrno(success
));
467 * converts a struct nlm_lock to struct nlm4_lock
469 static void nlmtonlm4(struct nlm_lock
*, struct nlm4_lock
*);
472 struct nlm_lock
*arg
;
473 struct nlm4_lock
*arg4
;
475 arg4
->caller_name
= arg
->caller_name
;
478 arg4
->svid
= arg
->svid
;
479 arg4
->l_offset
= arg
->l_offset
;
480 arg4
->l_len
= arg
->l_len
;
482 /* ------------------------------------------------------------------------- */
484 * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
485 * involved to ensure reclaim of locks after a crash of the "stateless"
488 * These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
489 * The first are standard RPCs with argument and result.
490 * The nlm_xxx_msg() calls implement exactly the same functions, but
491 * use two pseudo-RPCs (one in each direction). These calls are NOT
492 * standard use of the RPC protocol in that they do not return a result
493 * at all (NB. this is quite different from returning a void result).
494 * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
495 * datagrams, requiring higher-level code to perform retries.
497 * Despite the disadvantages of the nlm_xxx_msg() approach (some of which
498 * are documented in the comments to get_client() above), this is the
499 * interface used by all current commercial NFS implementations
500 * [Solaris, SCO, AIX etc.]. This is presumed to be because these allow
501 * implementations to continue using the standard RPC libraries, while
502 * avoiding the block-until-result nature of the library interface.
504 * No client implementations have been identified so far that make use
505 * of the true RPC version (early SunOS releases would be a likely candidate
509 /* nlm_test ---------------------------------------------------------------- */
511 * Purpose: Test whether a specified lock would be granted if requested
512 * Returns: nlm_granted (or error code)
516 nlm_test_1_svc(arg
, rqstp
)
518 struct svc_req
*rqstp
;
520 static nlm_testres res
;
521 struct nlm4_lock arg4
;
522 struct nlm4_holder
*holder
;
523 nlmtonlm4(&arg
->alock
, &arg4
);
526 log_from_addr("nlm_test", rqstp
);
528 holder
= testlock(&arg4
, arg
->exclusive
, 0);
530 * Copy the cookie from the argument into the result. Note that this
531 * is slightly hazardous, as the structure contains a pointer to a
532 * malloc()ed buffer that will get freed by the caller. However, the
533 * main function transmits the result before freeing the argument
534 * so it is in fact safe.
536 res
.cookie
= arg
->cookie
;
537 if (holder
== NULL
) {
538 res
.stat
.stat
= nlm_granted
;
540 res
.stat
.stat
= nlm_denied
;
541 memcpy(&res
.stat
.nlm_testrply_u
.holder
, holder
,
542 sizeof(struct nlm_holder
));
543 res
.stat
.nlm_testrply_u
.holder
.l_offset
= holder
->l_offset
;
544 res
.stat
.nlm_testrply_u
.holder
.l_len
= holder
->l_len
;
550 nlm_test_msg_1_svc(arg
, rqstp
)
552 struct svc_req
*rqstp
;
556 struct sockaddr
*addr
;
559 struct timeval timeo
;
560 struct nlm4_lock arg4
;
561 struct nlm4_holder
*holder
;
563 nlmtonlm4(&arg
->alock
, &arg4
);
566 log_from_addr("nlm_test_msg", rqstp
);
568 holder
= testlock(&arg4
, arg
->exclusive
, 0);
570 res
.cookie
= arg
->cookie
;
571 if (holder
== NULL
) {
572 res
.stat
.stat
= nlm_granted
;
574 res
.stat
.stat
= nlm_denied
;
575 memcpy(&res
.stat
.nlm_testrply_u
.holder
, holder
,
576 sizeof(struct nlm_holder
));
577 res
.stat
.nlm_testrply_u
.holder
.l_offset
= holder
->l_offset
;
578 res
.stat
.nlm_testrply_u
.holder
.l_len
= holder
->l_len
;
582 * nlm_test has different result type to the other operations, so
583 * can't use transmit_result() in this case
585 addr
= (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
);
586 if ((cli
= get_client(addr
, NLM_VERS
)) != NULL
) {
587 timeo
.tv_sec
= 0; /* No timeout - not expecting response */
590 success
= clnt_call(cli
, NLM_TEST_RES
, xdr_nlm_testres
,
591 &res
, xdr_void
, &dummy
, timeo
);
594 syslog(LOG_DEBUG
, "clnt_call returns %d", success
);
599 /* nlm_lock ---------------------------------------------------------------- */
601 * Purposes: Establish a lock
602 * Returns: granted, denied or blocked
603 * Notes: *** grace period support missing
606 nlm_lock_1_svc(arg
, rqstp
)
608 struct svc_req
*rqstp
;
611 struct nlm4_lockargs arg4
;
612 nlmtonlm4(&arg
->alock
, &arg4
.alock
);
613 arg4
.cookie
= arg
->cookie
;
614 arg4
.block
= arg
->block
;
615 arg4
.exclusive
= arg
->exclusive
;
616 arg4
.reclaim
= arg
->reclaim
;
617 arg4
.state
= arg
->state
;
620 log_from_addr("nlm_lock", rqstp
);
622 /* copy cookie from arg to result. See comment in nlm_test_1() */
623 res
.cookie
= arg
->cookie
;
625 res
.stat
.stat
= getlock(&arg4
, rqstp
, LOCK_MON
);
630 nlm_lock_msg_1_svc(arg
, rqstp
)
632 struct svc_req
*rqstp
;
635 struct nlm4_lockargs arg4
;
637 nlmtonlm4(&arg
->alock
, &arg4
.alock
);
638 arg4
.cookie
= arg
->cookie
;
639 arg4
.block
= arg
->block
;
640 arg4
.exclusive
= arg
->exclusive
;
641 arg4
.reclaim
= arg
->reclaim
;
642 arg4
.state
= arg
->state
;
645 log_from_addr("nlm_lock_msg", rqstp
);
647 res
.cookie
= arg
->cookie
;
648 res
.stat
.stat
= getlock(&arg4
, rqstp
, LOCK_ASYNC
| LOCK_MON
);
649 if (transmit_result(NLM_LOCK_RES
, &res
,
650 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
)) < 0) {
651 /* if res.stat.stat was success/blocked, then unlock/cancel */
652 if (res
.stat
.stat
== nlm_granted
)
653 unlock(&arg4
.alock
, LOCK_V4
);
654 else if (res
.stat
.stat
== nlm_blocked
) {
656 carg
.cookie
= arg4
.cookie
;
657 carg
.block
= arg4
.block
;
658 carg
.exclusive
= arg4
.exclusive
;
659 carg
.alock
= arg4
.alock
;
660 cancellock(&carg
, 0);
667 /* nlm_cancel -------------------------------------------------------------- */
669 * Purpose: Cancel a blocked lock request
670 * Returns: granted or denied
674 nlm_cancel_1_svc(arg
, rqstp
)
676 struct svc_req
*rqstp
;
679 struct nlm4_cancargs arg4
;
681 arg4
.cookie
= arg
->cookie
;
682 arg4
.block
= arg
->block
;
683 arg4
.exclusive
= arg
->exclusive
;
684 nlmtonlm4(&arg
->alock
, &arg4
.alock
);
687 log_from_addr("nlm_cancel", rqstp
);
689 /* copy cookie from arg to result. See comment in nlm_test_1() */
690 res
.cookie
= arg
->cookie
;
692 res
.stat
.stat
= cancellock(&arg4
, 0);
697 nlm_cancel_msg_1_svc(arg
, rqstp
)
699 struct svc_req
*rqstp
;
702 struct nlm4_cancargs arg4
;
704 arg4
.cookie
= arg
->cookie
;
705 arg4
.block
= arg
->block
;
706 arg4
.exclusive
= arg
->exclusive
;
707 nlmtonlm4(&arg
->alock
, &arg4
.alock
);
710 log_from_addr("nlm_cancel_msg", rqstp
);
712 res
.cookie
= arg
->cookie
;
713 res
.stat
.stat
= cancellock(&arg4
, 0);
714 if (transmit_result(NLM_CANCEL_RES
, &res
,
715 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
)) < 0) {
716 /* XXX do we need to (un)do anything if this fails? */
721 /* nlm_unlock -------------------------------------------------------------- */
723 * Purpose: Release an existing lock
724 * Returns: Always granted, unless during grace period
725 * Notes: "no such lock" error condition is ignored, as the
726 * protocol uses unreliable UDP datagrams, and may well
727 * re-try an unlock that has already succeeded.
730 nlm_unlock_1_svc(arg
, rqstp
)
732 struct svc_req
*rqstp
;
735 struct nlm4_lock arg4
;
737 nlmtonlm4(&arg
->alock
, &arg4
);
740 log_from_addr("nlm_unlock", rqstp
);
742 res
.stat
.stat
= unlock(&arg4
, 0);
743 res
.cookie
= arg
->cookie
;
749 nlm_unlock_msg_1_svc(arg
, rqstp
)
751 struct svc_req
*rqstp
;
754 struct nlm4_lock arg4
;
756 nlmtonlm4(&arg
->alock
, &arg4
);
759 log_from_addr("nlm_unlock_msg", rqstp
);
761 res
.stat
.stat
= unlock(&arg4
, 0);
762 res
.cookie
= arg
->cookie
;
764 if (transmit_result(NLM_UNLOCK_RES
, &res
,
765 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
)) < 0) {
766 /* XXX do we need to (un)do anything if this fails? */
771 /* ------------------------------------------------------------------------- */
773 * Client-side pseudo-RPCs for results. Note that for the client there
774 * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
775 * version returns the results in the RPC result, and so the client
776 * does not normally receive incoming RPCs.
778 * The exception to this is nlm_granted(), which is genuinely an RPC
779 * call from the server to the client - a 'call-back' in normal procedure
783 /* nlm_granted ------------------------------------------------------------- */
785 * Purpose: Receive notification that formerly blocked lock now granted
786 * Returns: always success ('granted')
790 nlm_granted_1_svc(arg
, rqstp
)
792 struct svc_req
*rqstp
;
799 log_from_addr("nlm_granted", rqstp
);
801 lock4
.fh
= arg
->alock
.fh
;
802 lock4
.svid
= arg
->alock
.svid
;
803 lock4
.l_offset
= arg
->alock
.l_offset
;
804 lock4
.l_len
= arg
->alock
.l_len
;
806 flags
= LOCK_ANSWER_GRANTED
;
808 flags
|= LOCK_ANSWER_LOCK_EXCL
;
810 if (lock_answer(NLM_VERS
, &arg
->cookie
, &lock4
, flags
, nlm_granted
))
811 res
.stat
.stat
= nlm_denied
;
813 res
.stat
.stat
= nlm_granted
;
815 /* copy cookie from arg to result. See comment in nlm_test_1() */
816 res
.cookie
= arg
->cookie
;
822 nlm_granted_msg_1_svc(arg
, rqstp
)
824 struct svc_req
*rqstp
;
831 log_from_addr("nlm_granted_msg", rqstp
);
833 lock4
.fh
= arg
->alock
.fh
;
834 lock4
.svid
= arg
->alock
.svid
;
835 lock4
.l_offset
= arg
->alock
.l_offset
;
836 lock4
.l_len
= arg
->alock
.l_len
;
838 flags
= LOCK_ANSWER_GRANTED
;
840 flags
|= LOCK_ANSWER_LOCK_EXCL
;
842 if (lock_answer(NLM_VERS
, &arg
->cookie
, &lock4
, flags
, nlm_granted
))
843 res
.stat
.stat
= nlm_denied
;
845 res
.stat
.stat
= nlm_granted
;
847 res
.cookie
= arg
->cookie
;
849 if (transmit_result(NLM_GRANTED_RES
, &res
,
850 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
)) < 0) {
851 /* XXX do we need to (un)do anything if this fails? */
856 /* nlm_test_res ------------------------------------------------------------ */
858 * Purpose: Accept result from earlier nlm_test_msg() call
862 nlm_test_res_1_svc(arg
, rqstp
)
864 struct svc_req
*rqstp
;
870 log_from_addr("nlm_test_res", rqstp
);
872 if (arg
->stat
.stat
== nlm_denied
) {
874 lock4
.svid
= arg
->stat
.nlm_testrply_u
.holder
.svid
;
875 lock4
.l_offset
= arg
->stat
.nlm_testrply_u
.holder
.l_offset
;
876 lock4
.l_len
= arg
->stat
.nlm_testrply_u
.holder
.l_len
;
877 if (arg
->stat
.nlm_testrply_u
.holder
.exclusive
)
878 flags
|= LOCK_ANSWER_LOCK_EXCL
;
879 lock_answer(NLM_VERS
, &arg
->cookie
, &lock4
, flags
, arg
->stat
.stat
);
881 lock_answer(NLM_VERS
, &arg
->cookie
, NULL
, 0, arg
->stat
.stat
);
886 /* nlm_lock_res ------------------------------------------------------------ */
888 * Purpose: Accept result from earlier nlm_lock_msg() call
892 nlm_lock_res_1_svc(arg
, rqstp
)
894 struct svc_req
*rqstp
;
897 log_from_addr("nlm_lock_res", rqstp
);
899 lock_answer(NLM_VERS
, &arg
->cookie
, NULL
, 0, arg
->stat
.stat
);
904 /* nlm_cancel_res ---------------------------------------------------------- */
906 * Purpose: Accept result from earlier nlm_cancel_msg() call
910 nlm_cancel_res_1_svc(arg
, rqstp
)
912 struct svc_req
*rqstp
;
915 log_from_addr("nlm_cancel_res", rqstp
);
917 lock_answer(NLM_VERS
, &arg
->cookie
, NULL
, 0, arg
->stat
.stat
);
922 /* nlm_unlock_res ---------------------------------------------------------- */
924 * Purpose: Accept result from earlier nlm_unlock_msg() call
928 nlm_unlock_res_1_svc(arg
, rqstp
)
930 struct svc_req
*rqstp
;
933 log_from_addr("nlm_unlock_res", rqstp
);
935 lock_answer(NLM_VERS
, &arg
->cookie
, NULL
, 0, arg
->stat
.stat
);
940 /* nlm_granted_res --------------------------------------------------------- */
942 * Purpose: Accept result from earlier nlm_granted_msg() call
946 nlm_granted_res_1_svc(arg
, rqstp
)
948 struct svc_req
*rqstp
;
951 log_from_addr("nlm_granted_res", rqstp
);
952 /* need to undo lock if granted msg wasn't accepted! */
953 if (arg
->stat
.stat
!= nlm_granted
) {
955 arg4
.cookie
= arg
->cookie
;
956 arg4
.stat
.stat
= arg
->stat
.stat
;
957 granted_failed(&arg4
);
962 /* ------------------------------------------------------------------------- */
964 * Calls for PCNFS locking (aka non-monitored locking, no involvement
967 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
970 /* nlm_share --------------------------------------------------------------- */
972 * Purpose: Establish a DOS-style lock
973 * Returns: success or failure
974 * Notes: Blocking locks are not supported - client is expected
975 * to retry if required.
978 nlm_share_3_svc(arg
, rqstp
)
980 struct svc_req
*rqstp
;
982 static nlm_shareres res
;
985 log_from_addr("nlm_share", rqstp
);
987 /* copy cookie from arg to result. See comment in nlm_test_1() */
988 res
.cookie
= arg
->cookie
;
989 res
.sequence
= 0; /* X/Open says this field is ignored? */
991 res
.stat
= getshare(arg
, rqstp
, 0);
995 /* nlm_unshare ------------------------------------------------------------ */
997 * Purpose: Release a DOS-style lock
998 * Returns: nlm_granted, unless in grace period
1002 nlm_unshare_3_svc(arg
, rqstp
)
1004 struct svc_req
*rqstp
;
1006 static nlm_shareres res
;
1009 log_from_addr("nlm_unshare", rqstp
);
1011 res
.cookie
= arg
->cookie
;
1012 res
.sequence
= 0; /* X/Open says this field is ignored? */
1014 res
.stat
= unshare(arg
, rqstp
);
1018 /* nlm_nm_lock ------------------------------------------------------------ */
1020 * Purpose: non-monitored version of nlm_lock()
1021 * Returns: as for nlm_lock()
1022 * Notes: These locks are in the same style as the standard nlm_lock,
1023 * but the rpc.statd should not be called to establish a
1024 * monitor for the client machine, since that machine is
1025 * declared not to be running a rpc.statd, and so would not
1026 * respond to the statd protocol.
1029 nlm_nm_lock_3_svc(arg
, rqstp
)
1031 struct svc_req
*rqstp
;
1034 struct nlm4_lockargs arg4
;
1035 nlmtonlm4(&arg
->alock
, &arg4
.alock
);
1036 arg4
.cookie
= arg
->cookie
;
1037 arg4
.block
= arg
->block
;
1038 arg4
.exclusive
= arg
->exclusive
;
1039 arg4
.reclaim
= arg
->reclaim
;
1040 arg4
.state
= arg
->state
;
1043 log_from_addr("nlm_nm_lock", rqstp
);
1045 /* copy cookie from arg to result. See comment in nlm_test_1() */
1046 res
.cookie
= arg
->cookie
;
1048 res
.stat
.stat
= getlock(&arg4
, rqstp
, 0);
1052 /* nlm_free_all ------------------------------------------------------------ */
1054 * Purpose: Release all locks held by a named client
1056 * Notes: Potential denial of service security problem here - the
1057 * locks to be released are specified by a host name, independent
1058 * of the address from which the request has arrived.
1059 * Should probably be rejected if the named host has been
1060 * using monitored locks.
1063 nlm_free_all_3_svc(arg
, rqstp
)
1065 struct svc_req
*rqstp
;
1070 log_from_addr("nlm_free_all", rqstp
);
1072 /* free all non-monitored locks/shares for specified host */
1073 do_free_all(arg
->name
);
1078 /* calls for nlm version 4 (NFSv3) */
1079 /* nlm_test ---------------------------------------------------------------- */
1081 * Purpose: Test whether a specified lock would be granted if requested
1082 * Returns: nlm_granted (or error code)
1086 nlm4_test_4_svc(arg
, rqstp
)
1088 struct svc_req
*rqstp
;
1090 static nlm4_testres res
;
1091 struct nlm4_holder
*holder
;
1094 log_from_addr("nlm4_test", rqstp
);
1095 if (debug_level
> 5) {
1096 syslog(LOG_DEBUG
, "Locking arguments:\n");
1097 log_netobj(&(arg
->cookie
));
1098 syslog(LOG_DEBUG
, "Alock arguments:\n");
1099 syslog(LOG_DEBUG
, "Caller Name: %s\n",arg
->alock
.caller_name
);
1100 syslog(LOG_DEBUG
, "File Handle:\n");
1101 log_netobj(&(arg
->alock
.fh
));
1102 syslog(LOG_DEBUG
, "Owner Handle:\n");
1103 log_netobj(&(arg
->alock
.oh
));
1104 syslog(LOG_DEBUG
, "SVID: %d\n", arg
->alock
.svid
);
1105 syslog(LOG_DEBUG
, "Lock Offset: %llu\n",
1106 (unsigned long long)arg
->alock
.l_offset
);
1107 syslog(LOG_DEBUG
, "Lock Length: %llu\n",
1108 (unsigned long long)arg
->alock
.l_len
);
1109 syslog(LOG_DEBUG
, "Exclusive: %s\n",
1110 (arg
->exclusive
? "true" : "false"));
1113 holder
= testlock(&arg
->alock
, arg
->exclusive
, LOCK_V4
);
1116 * Copy the cookie from the argument into the result. Note that this
1117 * is slightly hazardous, as the structure contains a pointer to a
1118 * malloc()ed buffer that will get freed by the caller. However, the
1119 * main function transmits the result before freeing the argument
1120 * so it is in fact safe.
1122 res
.cookie
= arg
->cookie
;
1123 if (holder
== NULL
) {
1124 res
.stat
.stat
= nlm4_granted
;
1126 res
.stat
.stat
= nlm4_denied
;
1127 memcpy(&res
.stat
.nlm4_testrply_u
.holder
, holder
,
1128 sizeof(struct nlm4_holder
));
1134 nlm4_test_msg_4_svc(arg
, rqstp
)
1136 struct svc_req
*rqstp
;
1140 struct sockaddr
*addr
;
1143 struct timeval timeo
;
1144 struct nlm4_holder
*holder
;
1147 log_from_addr("nlm4_test_msg", rqstp
);
1149 holder
= testlock(&arg
->alock
, arg
->exclusive
, LOCK_V4
);
1151 res
.cookie
= arg
->cookie
;
1152 if (holder
== NULL
) {
1153 res
.stat
.stat
= nlm4_granted
;
1155 res
.stat
.stat
= nlm4_denied
;
1156 memcpy(&res
.stat
.nlm4_testrply_u
.holder
, holder
,
1157 sizeof(struct nlm4_holder
));
1161 * nlm_test has different result type to the other operations, so
1162 * can't use transmit4_result() in this case
1164 addr
= (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
);
1165 if ((cli
= get_client(addr
, NLM_VERS4
)) != NULL
) {
1166 timeo
.tv_sec
= 0; /* No timeout - not expecting response */
1169 success
= clnt_call(cli
, NLM4_TEST_RES
, xdr_nlm4_testres
,
1170 &res
, xdr_void
, &dummy
, timeo
);
1172 if (debug_level
> 2)
1173 syslog(LOG_DEBUG
, "clnt_call returns %d", success
);
1178 /* nlm_lock ---------------------------------------------------------------- */
1180 * Purposes: Establish a lock
1181 * Returns: granted, denied or blocked
1182 * Notes: *** grace period support missing
1185 nlm4_lock_4_svc(arg
, rqstp
)
1187 struct svc_req
*rqstp
;
1189 static nlm4_res res
;
1192 log_from_addr("nlm4_lock", rqstp
);
1193 if (debug_level
> 5) {
1194 syslog(LOG_DEBUG
, "Locking arguments:\n");
1195 log_netobj(&(arg
->cookie
));
1196 syslog(LOG_DEBUG
, "Alock arguments:\n");
1197 syslog(LOG_DEBUG
, "Caller Name: %s\n",arg
->alock
.caller_name
);
1198 syslog(LOG_DEBUG
, "File Handle:\n");
1199 log_netobj(&(arg
->alock
.fh
));
1200 syslog(LOG_DEBUG
, "Owner Handle:\n");
1201 log_netobj(&(arg
->alock
.oh
));
1202 syslog(LOG_DEBUG
, "SVID: %d\n", arg
->alock
.svid
);
1203 syslog(LOG_DEBUG
, "Lock Offset: %llu\n",
1204 (unsigned long long)arg
->alock
.l_offset
);
1205 syslog(LOG_DEBUG
, "Lock Length: %llu\n",
1206 (unsigned long long)arg
->alock
.l_len
);
1207 syslog(LOG_DEBUG
, "Block: %s\n", (arg
->block
? "true" : "false"));
1208 syslog(LOG_DEBUG
, "Exclusive: %s\n", (arg
->exclusive
? "true" : "false"));
1209 syslog(LOG_DEBUG
, "Reclaim: %s\n", (arg
->reclaim
? "true" : "false"));
1210 syslog(LOG_DEBUG
, "State num: %d\n", arg
->state
);
1213 /* copy cookie from arg to result. See comment in nlm_test_4() */
1214 res
.cookie
= arg
->cookie
;
1216 res
.stat
.stat
= getlock(arg
, rqstp
, LOCK_MON
| LOCK_V4
);
1221 nlm4_lock_msg_4_svc(arg
, rqstp
)
1223 struct svc_req
*rqstp
;
1225 static nlm4_res res
;
1228 log_from_addr("nlm4_lock_msg", rqstp
);
1230 res
.cookie
= arg
->cookie
;
1231 res
.stat
.stat
= getlock(arg
, rqstp
, LOCK_MON
| LOCK_ASYNC
| LOCK_V4
);
1232 if (transmit4_result(NLM4_LOCK_RES
, &res
,
1233 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
)) < 0) {
1234 /* if res.stat.stat was success/blocked, then unlock/cancel */
1235 if (res
.stat
.stat
== nlm4_granted
)
1236 unlock(&arg
->alock
, LOCK_V4
);
1237 else if (res
.stat
.stat
== nlm4_blocked
) {
1239 carg
.cookie
= arg
->cookie
;
1240 carg
.block
= arg
->block
;
1241 carg
.exclusive
= arg
->exclusive
;
1242 carg
.alock
= arg
->alock
;
1243 cancellock(&carg
, LOCK_V4
);
1250 /* nlm_cancel -------------------------------------------------------------- */
1252 * Purpose: Cancel a blocked lock request
1253 * Returns: granted or denied
1257 nlm4_cancel_4_svc(arg
, rqstp
)
1259 struct svc_req
*rqstp
;
1261 static nlm4_res res
;
1264 log_from_addr("nlm4_cancel", rqstp
);
1266 /* copy cookie from arg to result. See comment in nlm_test_1() */
1267 res
.cookie
= arg
->cookie
;
1269 res
.stat
.stat
= cancellock(arg
, LOCK_V4
);
1274 nlm4_cancel_msg_4_svc(arg
, rqstp
)
1276 struct svc_req
*rqstp
;
1278 static nlm4_res res
;
1281 log_from_addr("nlm4_cancel_msg", rqstp
);
1283 res
.cookie
= arg
->cookie
;
1284 res
.stat
.stat
= cancellock(arg
, LOCK_V4
);
1285 if (transmit4_result(NLM4_CANCEL_RES
, &res
,
1286 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
)) < 0) {
1287 /* XXX do we need to (un)do anything if this fails? */
1292 /* nlm_unlock -------------------------------------------------------------- */
1294 * Purpose: Release an existing lock
1295 * Returns: Always granted, unless during grace period
1296 * Notes: "no such lock" error condition is ignored, as the
1297 * protocol uses unreliable UDP datagrams, and may well
1298 * re-try an unlock that has already succeeded.
1301 nlm4_unlock_4_svc(arg
, rqstp
)
1302 nlm4_unlockargs
*arg
;
1303 struct svc_req
*rqstp
;
1305 static nlm4_res res
;
1308 log_from_addr("nlm4_unlock", rqstp
);
1310 res
.stat
.stat
= unlock(&arg
->alock
, LOCK_V4
);
1311 res
.cookie
= arg
->cookie
;
1317 nlm4_unlock_msg_4_svc(arg
, rqstp
)
1318 nlm4_unlockargs
*arg
;
1319 struct svc_req
*rqstp
;
1321 static nlm4_res res
;
1324 log_from_addr("nlm4_unlock_msg", rqstp
);
1326 res
.stat
.stat
= unlock(&arg
->alock
, LOCK_V4
);
1327 res
.cookie
= arg
->cookie
;
1329 if (transmit4_result(NLM4_UNLOCK_RES
, &res
,
1330 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
)) < 0) {
1331 /* XXX do we need to (un)do anything if this fails? */
1336 /* ------------------------------------------------------------------------- */
1338 * Client-side pseudo-RPCs for results. Note that for the client there
1339 * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
1340 * version returns the results in the RPC result, and so the client
1341 * does not normally receive incoming RPCs.
1343 * The exception to this is nlm_granted(), which is genuinely an RPC
1344 * call from the server to the client - a 'call-back' in normal procedure
1348 /* nlm_granted ------------------------------------------------------------- */
1350 * Purpose: Receive notification that formerly blocked lock now granted
1351 * Returns: always success ('granted')
1355 nlm4_granted_4_svc(arg
, rqstp
)
1357 struct svc_req
*rqstp
;
1359 static nlm4_res res
;
1363 log_from_addr("nlm4_granted", rqstp
);
1365 flags
= LOCK_ANSWER_GRANTED
;
1367 flags
|= LOCK_ANSWER_LOCK_EXCL
;
1369 if (lock_answer(NLM_VERS4
, &arg
->cookie
, &arg
->alock
, flags
, nlm4_granted
))
1370 res
.stat
.stat
= nlm4_denied
;
1372 res
.stat
.stat
= nlm4_granted
;
1374 /* copy cookie from arg to result. See comment in nlm_test_1() */
1375 res
.cookie
= arg
->cookie
;
1381 nlm4_granted_msg_4_svc(arg
, rqstp
)
1383 struct svc_req
*rqstp
;
1385 static nlm4_res res
;
1389 log_from_addr("nlm4_granted_msg", rqstp
);
1391 flags
= LOCK_ANSWER_GRANTED
;
1393 flags
|= LOCK_ANSWER_LOCK_EXCL
;
1395 if (lock_answer(NLM_VERS4
, &arg
->cookie
, &arg
->alock
, flags
, nlm4_granted
))
1396 res
.stat
.stat
= nlm4_denied
;
1398 res
.stat
.stat
= nlm4_granted
;
1400 res
.cookie
= arg
->cookie
;
1402 if (transmit4_result(NLM4_GRANTED_RES
, &res
,
1403 (struct sockaddr
*)svc_getcaller(rqstp
->rq_xprt
)) < 0) {
1404 /* XXX do we need to (un)do anything if this fails? */
1409 /* nlm_test_res ------------------------------------------------------------ */
1411 * Purpose: Accept result from earlier nlm_test_msg() call
1415 nlm4_test_res_4_svc(arg
, rqstp
)
1417 struct svc_req
*rqstp
;
1423 log_from_addr("nlm4_test_res", rqstp
);
1425 if (arg
->stat
.stat
== nlm4_denied
) {
1427 lock4
.svid
= arg
->stat
.nlm4_testrply_u
.holder
.svid
;
1428 lock4
.l_offset
= arg
->stat
.nlm4_testrply_u
.holder
.l_offset
;
1429 lock4
.l_len
= arg
->stat
.nlm4_testrply_u
.holder
.l_len
;
1430 if (arg
->stat
.nlm4_testrply_u
.holder
.exclusive
)
1431 flags
|= LOCK_ANSWER_LOCK_EXCL
;
1432 lock_answer(NLM_VERS4
, &arg
->cookie
, &lock4
, flags
, arg
->stat
.stat
);
1434 lock_answer(NLM_VERS4
, &arg
->cookie
, NULL
, 0, arg
->stat
.stat
);
1439 /* nlm_lock_res ------------------------------------------------------------ */
1441 * Purpose: Accept result from earlier nlm_lock_msg() call
1445 nlm4_lock_res_4_svc(arg
, rqstp
)
1447 struct svc_req
*rqstp
;
1450 log_from_addr("nlm4_lock_res", rqstp
);
1452 lock_answer(NLM_VERS4
, &arg
->cookie
, NULL
, 0, arg
->stat
.stat
);
1457 /* nlm_cancel_res ---------------------------------------------------------- */
1459 * Purpose: Accept result from earlier nlm_cancel_msg() call
1463 nlm4_cancel_res_4_svc(arg
, rqstp
)
1465 struct svc_req
*rqstp
;
1468 log_from_addr("nlm4_cancel_res", rqstp
);
1470 lock_answer(NLM_VERS4
, &arg
->cookie
, NULL
, 0, arg
->stat
.stat
);
1475 /* nlm_unlock_res ---------------------------------------------------------- */
1477 * Purpose: Accept result from earlier nlm_unlock_msg() call
1481 nlm4_unlock_res_4_svc(arg
, rqstp
)
1482 nlm4_res
*arg __unused
;
1483 struct svc_req
*rqstp
;
1486 log_from_addr("nlm4_unlock_res", rqstp
);
1488 lock_answer(NLM_VERS4
, &arg
->cookie
, NULL
, 0, arg
->stat
.stat
);
1493 /* nlm_granted_res --------------------------------------------------------- */
1495 * Purpose: Accept result from earlier nlm_granted_msg() call
1499 nlm4_granted_res_4_svc(arg
, rqstp
)
1500 nlm4_res
*arg __unused
;
1501 struct svc_req
*rqstp
;
1504 log_from_addr("nlm4_granted_res", rqstp
);
1505 /* need to undo lock if granted msg wasn't accepted! */
1506 if (arg
->stat
.stat
!= nlm4_granted
)
1507 granted_failed(arg
);
1511 /* ------------------------------------------------------------------------- */
1513 * Calls for PCNFS locking (aka non-monitored locking, no involvement
1516 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
1519 /* nlm_share --------------------------------------------------------------- */
1521 * Purpose: Establish a DOS-style lock
1522 * Returns: success or failure
1523 * Notes: Blocking locks are not supported - client is expected
1524 * to retry if required.
1527 nlm4_share_4_svc(arg
, rqstp
)
1528 nlm4_shareargs
*arg
;
1529 struct svc_req
*rqstp
;
1531 static nlm4_shareres res
;
1534 log_from_addr("nlm4_share", rqstp
);
1536 res
.cookie
= arg
->cookie
;
1537 res
.sequence
= 0; /* X/Open says this field is ignored? */
1539 res
.stat
= getshare((nlm_shareargs
*)arg
, rqstp
, LOCK_V4
);
1543 /* nlm4_unshare ------------------------------------------------------------ */
1545 * Purpose: Release a DOS-style lock
1546 * Returns: nlm_granted, unless in grace period
1550 nlm4_unshare_4_svc(arg
, rqstp
)
1551 nlm4_shareargs
*arg
;
1552 struct svc_req
*rqstp
;
1554 static nlm4_shareres res
;
1557 log_from_addr("nlm4_unshare", rqstp
);
1559 res
.cookie
= arg
->cookie
;
1560 res
.sequence
= 0; /* X/Open says this field is ignored? */
1562 res
.stat
= unshare((nlm_shareargs
*)arg
, rqstp
);
1566 /* nlm4_nm_lock ------------------------------------------------------------ */
1568 * Purpose: non-monitored version of nlm4_lock()
1569 * Returns: as for nlm4_lock()
1570 * Notes: These locks are in the same style as the standard nlm4_lock,
1571 * but the rpc.statd should not be called to establish a
1572 * monitor for the client machine, since that machine is
1573 * declared not to be running a rpc.statd, and so would not
1574 * respond to the statd protocol.
1577 nlm4_nm_lock_4_svc(arg
, rqstp
)
1579 struct svc_req
*rqstp
;
1581 static nlm4_res res
;
1584 log_from_addr("nlm4_nm_lock", rqstp
);
1586 /* copy cookie from arg to result. See comment in nlm_test_4() */
1587 res
.cookie
= arg
->cookie
;
1589 res
.stat
.stat
= getlock(arg
, rqstp
, LOCK_V4
);
1593 /* nlm4_free_all ------------------------------------------------------------ */
1595 * Purpose: Release all locks held by a named client
1597 * Notes: Potential denial of service security problem here - the
1598 * locks to be released are specified by a host name, independent
1599 * of the address from which the request has arrived.
1600 * Should probably be rejected if the named host has been
1601 * using monitored locks.
1604 nlm4_free_all_4_svc(arg
, rqstp
)
1605 struct nlm4_notify
*arg
;
1606 struct svc_req
*rqstp
;
1611 log_from_addr("nlm4_free_all", rqstp
);
1613 /* free all non-monitored locks/shares for specified host */
1614 do_free_all(arg
->name
);
1619 /* nlm_sm_notify --------------------------------------------------------- */
1621 * Purpose: called by rpc.statd when a monitored host state changes.
1625 nlm_sm_notify_0_svc(arg
, rqstp
)
1626 struct nlm_sm_status
*arg
;
1627 struct svc_req
*rqstp __unused
;
1630 notify(arg
->mon_name
, arg
->state
);