3 * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed for the FreeBSD project
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $FreeBSD: src/usr.sbin/rpc.lockd/procs.c,v 1.4.2.2 2001/08/01 06:39:36 alfred Exp $
33 * $DragonFly: src/usr.sbin/rpc.lockd/procs.c,v 1.2 2003/06/17 04:30:02 dillon Exp $
39 #include <sys/param.h> /* for MAXHOSTNAMELEN */
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
46 #define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */
47 #define CLIENT_CACHE_LIFETIME 120 /* In seconds */
52 #define LOG_DEBUG stderr
53 #define LOG_ERR stderr
54 #define syslog fprintf
57 /* log_from_addr ----------------------------------------------------------- */
59 Purpose: Log name of function called and source address
61 Notes: Extracts the source address from the transport handle
62 passed in as part of the called procedure specification
65 static void log_from_addr(char *fun_name, struct svc_req *req)
67 struct sockaddr_in *addr;
69 char hostname_buf[40];
71 addr = svc_getcaller(req->rq_xprt);
72 host = gethostbyaddr((char *)&(addr->sin_addr), addr->sin_len, AF_INET);
75 strncpy(hostname_buf, host->h_name, sizeof(hostname_buf));
76 hostname_buf[sizeof(hostname_buf) -1] = '\0';
78 else /* No hostname available - print raw address */
80 strcpy(hostname_buf, inet_ntoa(addr->sin_addr));
83 syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf);
87 /* get_client -------------------------------------------------------------- */
89 Purpose: Get a CLIENT* for making RPC calls to lockd on given host
90 Returns: CLIENT* pointer, from clnt_udp_create, or NULL if error
91 Notes: Creating a CLIENT* is quite expensive, involving a
92 conversation with the remote portmapper to get the
93 port number. Since a given client is quite likely
94 to make several locking requests in succession, it is
95 desirable to cache the created CLIENT*.
97 Since we are using UDP rather than TCP, there is no cost
98 to the remote system in keeping these cached indefinitely.
99 Unfortunately there is a snag: if the remote system
100 reboots, the cached portmapper results will be invalid,
101 and we will never detect this since all of the xxx_msg()
102 calls return no result - we just fire off a udp packet
103 and hope for the best.
105 We solve this by discarding cached values after two
106 minutes, regardless of whether they have been used
107 in the meanwhile (since a bad one might have been used
108 plenty of times, as the host keeps retrying the request
109 and we keep sending the reply back to the wrong port).
111 Given that the entries will always expire in the order
112 that they were created, there is no point in a LRU
113 algorithm for when the cache gets full - entries are
114 always re-used in sequence.
117 static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE];
118 static long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */
119 static struct in_addr clnt_cache_addr[CLIENT_CACHE_SIZE];
120 static int clnt_cache_next_to_use = 0;
122 static CLIENT *get_client(struct sockaddr_in *host_addr)
126 struct timeval retry_time, time_now;
129 gettimeofday(&time_now, NULL);
131 /* Search for the given client in the cache, zapping any expired */
132 /* entries that we happen to notice in passing. */
133 for (i = 0; i < CLIENT_CACHE_SIZE; i++)
135 client = clnt_cache_ptr[i];
137 ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME) < time_now.tv_sec))
139 /* Cache entry has expired. */
140 if (debug_level > 3) syslog(LOG_DEBUG, "Expired CLIENT* in cache");
141 clnt_cache_time[i] = 0L;
142 clnt_destroy(client);
143 clnt_cache_ptr[i] = NULL;
147 if (client && !memcmp(&clnt_cache_addr[i], &host_addr->sin_addr,
148 sizeof(struct in_addr)))
151 if (debug_level > 3) syslog(LOG_DEBUG, "Found CLIENT* in cache");
156 /* Not found in cache. Free the next entry if it is in use */
157 if (clnt_cache_ptr[clnt_cache_next_to_use])
159 clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
160 clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
163 /* Create the new client handle */
165 sock_no = RPC_ANYSOCK;
166 retry_time.tv_sec = 5;
167 retry_time.tv_usec = 0;
168 host_addr->sin_port = 0; /* Force consultation with portmapper */
169 client = clntudp_create(host_addr, NLM_PROG, NLM_VERS, retry_time, &sock_no);
172 syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create"));
173 syslog(LOG_ERR, "Unable to return result to %s",
174 inet_ntoa(host_addr->sin_addr));
178 /* Success - update the cache entry */
179 clnt_cache_ptr[clnt_cache_next_to_use] = client;
180 clnt_cache_addr[clnt_cache_next_to_use] = host_addr->sin_addr;
181 clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec;
182 if (++clnt_cache_next_to_use > CLIENT_CACHE_SIZE)
183 clnt_cache_next_to_use = 0;
185 /* Disable the default timeout, so we can specify our own in calls */
186 /* to clnt_call(). [note that the timeout is a different concept */
187 /* from the retry period set in clnt_udp_create() above.] */
188 retry_time.tv_sec = -1;
189 retry_time.tv_usec = -1;
190 clnt_control(client, CLSET_TIMEOUT, &retry_time);
192 if (debug_level > 3) syslog(LOG_DEBUG, "Created CLIENT* for %s",
193 inet_ntoa(host_addr->sin_addr));
198 /* transmit_result --------------------------------------------------------- */
200 Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs
201 Returns: Nothing - we have no idea if the datagram got there
202 Notes: clnt_call() will always fail (with timeout) as we are
203 calling it with timeout 0 as a hack to just issue a datagram
204 without expecting a result
207 static void transmit_result(int opcode, void *result, struct svc_req *req)
210 struct sockaddr_in *addr;
213 struct timeval timeo;
215 addr = svc_getcaller(req->rq_xprt);
216 if ((cli = get_client(addr)))
218 timeo.tv_sec = 0; /* No timeout - not expecting response */
221 success = clnt_call(cli, opcode, xdr_nlm_res, result, xdr_void,
224 if (debug_level > 2) syslog(LOG_DEBUG, "clnt_call returns %d", success);
228 /* ------------------------------------------------------------------------- */
230 Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
231 involved to ensure reclaim of locks after a crash of the "stateless"
234 These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
235 The first are standard RPCs with argument and result.
236 The nlm_xxx_msg() calls implement exactly the same functions, but
237 use two pseudo-RPCs (one in each direction). These calls are NOT
238 standard use of the RPC protocol in that they do not return a result
239 at all (NB. this is quite different from returning a void result).
240 The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
241 datagrams, requiring higher-level code to perform retries.
243 Despite the disadvantages of the nlm_xxx_msg() approach (some of which
244 are documented in the comments to get_client() above), this is the
245 interface used by all current commercial NFS implementations
246 [Solaris, SCO, AIX etc.]. This is presumed to be because these allow
247 implementations to continue using the standard RPC libraries, while
248 avoiding the block-until-result nature of the library interface.
250 No client implementations have been identified so far that make use
251 of the true RPC version (early SunOS releases would be a likely candidate
256 /* nlm_test ---------------------------------------------------------------- */
258 Purpose: Test whether a specified lock would be granted if requested
259 Returns: nlm_granted (or error code)
263 nlm_testres *nlm_test_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
265 static nlm_testres res;
266 if (debug_level) log_from_addr("nlm_test", rqstp);
268 /* Copy the cookie from the argument into the result. Note that this */
269 /* is slightly hazardous, as the structure contains a pointer to a */
270 /* malloc()ed buffer that will get freed by the caller. However, the */
271 /* main function transmits the result before freeing the argument */
272 /* so it is in fact safe. */
273 res.cookie = arg->cookie;
274 res.stat.stat = nlm_granted;
278 nlm4_testres *nlmproc4_test_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
280 static nlm4_testres res;
281 if (debug_level) log_from_addr("nlm_test", rqstp);
283 /* Copy the cookie from the argument into the result. Note that this */
284 /* is slightly hazardous, as the structure contains a pointer to a */
285 /* malloc()ed buffer that will get freed by the caller. However, the */
286 /* main function transmits the result before freeing the argument */
287 /* so it is in fact safe. */
288 res.cookie = arg->cookie;
289 res.stat.stat = nlm4_granted;
293 void *nlm_test_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
297 struct sockaddr_in *addr;
300 struct timeval timeo;
302 if (debug_level) log_from_addr("nlm_test_msg", rqstp);
304 res.cookie = arg->cookie;
305 res.stat.stat = nlm_granted;
307 /* nlm_test has different result type to the other operations, so */
308 /* can't use transmit_result() in this case */
309 addr = svc_getcaller(rqstp->rq_xprt);
310 if ((cli = get_client(addr)))
312 timeo.tv_sec = 0; /* No timeout - not expecting response */
315 success = clnt_call(cli, NLM_TEST_RES, xdr_nlm_testres, &res, xdr_void,
318 if (debug_level > 2) syslog(LOG_DEBUG, "clnt_call returns %d", success);
323 void *nlmproc4_test_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
327 struct sockaddr_in *addr;
330 struct timeval timeo;
332 if (debug_level) log_from_addr("nlm_test_msg", rqstp);
334 res.cookie = arg->cookie;
335 res.stat.stat = nlm4_granted;
337 /* nlm_test has different result type to the other operations, so */
338 /* can't use transmit_result() in this case */
339 addr = svc_getcaller(rqstp->rq_xprt);
340 if ((cli = get_client(addr)))
342 timeo.tv_sec = 0; /* No timeout - not expecting response */
345 success = clnt_call(cli, NLMPROC4_TEST_RES, xdr_nlm_testres, &res, xdr_void,
348 if (debug_level > 2) syslog(LOG_DEBUG, "clnt_call returns %d", success);
355 /* nlm_lock ---------------------------------------------------------------- */
357 Purposes: Establish a lock
358 Returns: granted, denied or blocked
359 Notes: *** grace period support missing
362 nlm_res *nlm_lock_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
365 if (debug_level) log_from_addr("nlm_lock", rqstp);
367 /* copy cookie from arg to result. See comment in nlm_test_1() */
368 res.cookie = arg->cookie;
370 res.stat.stat = nlm_granted;
374 nlm4_res *nlmproc4_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
378 if (debug_level) log_from_addr("nlm_lock", rqstp);
380 /* copy cookie from arg to result. See comment in nlm_test_1() */
381 res.cookie = arg->cookie;
383 res.stat.stat = nlm4_granted;
387 void *nlm_lock_msg_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
391 if (debug_level) log_from_addr("nlm_lock_msg", rqstp);
393 res.cookie = arg->cookie;
394 res.stat.stat = nlm_granted;
395 transmit_result(NLM_LOCK_RES, &res, rqstp);
400 void *nlmproc4_lock_msg_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
404 if (debug_level) log_from_addr("nlm_lock_msg", rqstp);
406 res.cookie = arg->cookie;
407 res.stat.stat = nlm4_granted;
408 transmit_result(NLMPROC4_LOCK_RES, &res, rqstp);
414 /* nlm_cancel -------------------------------------------------------------- */
416 Purpose: Cancel a blocked lock request
417 Returns: granted or denied
421 nlm_res *nlm_cancel_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
424 if (debug_level) log_from_addr("nlm_cancel", rqstp);
426 /* copy cookie from arg to result. See comment in nlm_test_1() */
427 res.cookie = arg->cookie;
429 /* Since at present we never return 'nlm_blocked', there can never be */
430 /* a lock to cancel, so this call always fails. */
431 res.stat.stat = nlm_denied;
435 nlm4_res *nlmproc4_cancel_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
438 if (debug_level) log_from_addr("nlm_cancel", rqstp);
440 /* copy cookie from arg to result. See comment in nlm_test_1() */
441 res.cookie = arg->cookie;
443 /* Since at present we never return 'nlm_blocked', there can never be */
444 /* a lock to cancel, so this call always fails. */
445 res.stat.stat = nlm4_denied;
449 void *nlm_cancel_msg_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
452 if (debug_level) log_from_addr("nlm_cancel_msg", rqstp);
454 res.cookie = arg->cookie;
455 /* Since at present we never return 'nlm_blocked', there can never be */
456 /* a lock to cancel, so this call always fails. */
457 res.stat.stat = nlm_denied;
458 transmit_result(NLM_CANCEL_RES, &res, rqstp);
462 void *nlmproc4_cancel_msg_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
465 if (debug_level) log_from_addr("nlm_cancel_msg", rqstp);
467 res.cookie = arg->cookie;
468 /* Since at present we never return 'nlm_blocked', there can never be */
469 /* a lock to cancel, so this call always fails. */
470 res.stat.stat = nlm4_denied;
471 transmit_result(NLMPROC4_CANCEL_RES, &res, rqstp);
475 /* nlm_unlock -------------------------------------------------------------- */
477 Purpose: Release an existing lock
478 Returns: Always granted, unless during grace period
479 Notes: "no such lock" error condition is ignored, as the
480 protocol uses unreliable UDP datagrams, and may well
481 re-try an unlock that has already succeeded.
484 nlm_res *nlm_unlock_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
487 if (debug_level) log_from_addr("nlm_unlock", rqstp);
489 res.stat.stat= nlm_granted;
490 res.cookie = arg->cookie;
495 nlm4_res *nlmproc4_unlock_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
498 if (debug_level) log_from_addr("nlm_unlock", rqstp);
500 res.stat.stat= nlm4_granted;
501 res.cookie = arg->cookie;
506 void *nlm_unlock_msg_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
509 if (debug_level) log_from_addr("nlm_unlock_msg", rqstp);
511 res.stat.stat = nlm_granted;
512 res.cookie = arg->cookie;
514 transmit_result(NLM_UNLOCK_RES, &res, rqstp);
518 void *nlmproc4_unlock_msg_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
521 if (debug_level) log_from_addr("nlm_unlock_msg", rqstp);
523 res.stat.stat = nlm4_granted;
524 res.cookie = arg->cookie;
526 transmit_result(NLMPROC4_UNLOCK_RES, &res, rqstp);
530 /* ------------------------------------------------------------------------- */
532 Client-side pseudo-RPCs for results. Note that for the client there
533 are only nlm_xxx_msg() versions of each call, since the 'real RPC'
534 version returns the results in the RPC result, and so the client
535 does not normally receive incoming RPCs.
537 The exception to this is nlm_granted(), which is genuinely an RPC
538 call from the server to the client - a 'call-back' in normal procedure
542 /* nlm_granted ------------------------------------------------------------- */
544 Purpose: Receive notification that formerly blocked lock now granted
545 Returns: always success ('granted')
549 nlm_res *nlm_granted_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
552 if (debug_level) log_from_addr("nlm_granted", rqstp);
554 /* copy cookie from arg to result. See comment in nlm_test_1() */
555 res.cookie = arg->cookie;
557 res.stat.stat = nlm_granted;
561 nlm4_res *nlmproc4_granted_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
564 if (debug_level) log_from_addr("nlm_granted", rqstp);
566 /* copy cookie from arg to result. See comment in nlm_test_1() */
567 res.cookie = arg->cookie;
569 res.stat.stat = nlm4_granted;
573 void *nlm_granted_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
576 if (debug_level) log_from_addr("nlm_granted_msg", rqstp);
578 res.cookie = arg->cookie;
579 res.stat.stat = nlm_granted;
580 transmit_result(NLM_GRANTED_RES, &res, rqstp);
584 void *nlmproc4_granted_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
587 if (debug_level) log_from_addr("nlm_granted_msg", rqstp);
589 res.cookie = arg->cookie;
590 res.stat.stat = nlm4_granted;
591 transmit_result(NLMPROC4_GRANTED_RES, &res, rqstp);
595 /* nlm_test_res ------------------------------------------------------------ */
597 Purpose: Accept result from earlier nlm_test_msg() call
601 void *nlm_test_res_1_svc(nlm_testres *arg, struct svc_req *rqstp)
603 if (debug_level) log_from_addr("nlm_test_res", rqstp);
607 void *nlmproc4_test_res_4_svc(nlm4_testres *arg, struct svc_req *rqstp)
609 if (debug_level) log_from_addr("nlm_test_res", rqstp);
613 /* nlm_lock_res ------------------------------------------------------------ */
615 Purpose: Accept result from earlier nlm_lock_msg() call
619 void *nlm_lock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
621 if (debug_level) log_from_addr("nlm_lock_res", rqstp);
626 void *nlmproc4_lock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
628 if (debug_level) log_from_addr("nlm_lock_res", rqstp);
633 /* nlm_cancel_res ---------------------------------------------------------- */
635 Purpose: Accept result from earlier nlm_cancel_msg() call
639 void *nlm_cancel_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
641 if (debug_level) log_from_addr("nlm_cancel_res", rqstp);
645 void *nlmproc4_cancel_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
647 if (debug_level) log_from_addr("nlm_cancel_res", rqstp);
651 /* nlm_unlock_res ---------------------------------------------------------- */
653 Purpose: Accept result from earlier nlm_unlock_msg() call
657 void *nlm_unlock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
659 if (debug_level) log_from_addr("nlm_unlock_res", rqstp);
663 void *nlmproc4_unlock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
665 if (debug_level) log_from_addr("nlm_unlock_res", rqstp);
669 /* nlm_granted_res --------------------------------------------------------- */
671 Purpose: Accept result from earlier nlm_granted_msg() call
675 void *nlm_granted_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
677 if (debug_level) log_from_addr("nlm_granted_res", rqstp);
681 void *nlmproc4_granted_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
683 if (debug_level) log_from_addr("nlm_granted_res", rqstp);
687 /* ------------------------------------------------------------------------- */
689 Calls for PCNFS locking (aka non-monitored locking, no involvement
692 These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
696 /* nlm_share --------------------------------------------------------------- */
698 Purpose: Establish a DOS-style lock
699 Returns: success or failure
700 Notes: Blocking locks are not supported - client is expected
701 to retry if required.
704 nlm_shareres *nlm_share_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
706 static nlm_shareres res;
707 if (debug_level) log_from_addr("nlm_share", rqstp);
709 res.cookie = arg->cookie;
710 res.stat = nlm_granted;
711 res.sequence = 1234356; /* X/Open says this field is ignored? */
715 nlm4_shareres *nlmproc4_share_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
717 static nlm4_shareres res;
718 if (debug_level) log_from_addr("nlm_share", rqstp);
720 res.cookie = arg->cookie;
721 res.stat = nlm4_granted;
722 res.sequence = 1234356; /* X/Open says this field is ignored? */
726 /* nlm_unshare ------------------------------------------------------------ */
728 Purpose: Release a DOS-style lock
729 Returns: nlm_granted, unless in grace period
733 nlm_shareres *nlm_unshare_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
735 static nlm_shareres res;
736 if (debug_level) log_from_addr("nlm_unshare", rqstp);
738 res.cookie = arg->cookie;
739 res.stat = nlm_granted;
740 res.sequence = 1234356; /* X/Open says this field is ignored? */
744 nlm4_shareres *nlmproc4_unshare_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
746 static nlm4_shareres res;
747 if (debug_level) log_from_addr("nlm_unshare", rqstp);
749 res.cookie = arg->cookie;
750 res.stat = nlm4_granted;
751 res.sequence = 1234356; /* X/Open says this field is ignored? */
755 /* nlm_nm_lock ------------------------------------------------------------ */
757 Purpose: non-monitored version of nlm_lock()
758 Returns: as for nlm_lock()
759 Notes: These locks are in the same style as the standard nlm_lock,
760 but the rpc.statd should not be called to establish a
761 monitor for the client machine, since that machine is
762 declared not to be running a rpc.statd, and so would not
763 respond to the statd protocol.
766 nlm_res *nlm_nm_lock_3_svc(nlm_lockargs *arg, struct svc_req *rqstp)
769 if (debug_level) log_from_addr("nlm_nm_lock", rqstp);
771 /* copy cookie from arg to result. See comment in nlm_test_1() */
772 res.cookie = arg->cookie;
773 res.stat.stat = nlm_granted;
777 nlm4_res *nlmproc4_nm_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
780 if (debug_level) log_from_addr("nlm_nm_lock", rqstp);
782 /* copy cookie from arg to result. See comment in nlm_test_1() */
783 res.cookie = arg->cookie;
784 res.stat.stat = nlm4_granted;
788 /* nlm_free_all ------------------------------------------------------------ */
790 Purpose: Release all locks held by a named client
792 Notes: Potential denial of service security problem here - the
793 locks to be released are specified by a host name, independent
794 of the address from which the request has arrived.
795 Should probably be rejected if the named host has been
796 using monitored locks.
799 void *nlm_free_all_3_svc(nlm_notify *arg, struct svc_req *rqstp)
803 if (debug_level) log_from_addr("nlm_free_all", rqstp);
807 void *nlmproc4_free_all_4_svc(nlm4_notify *arg, struct svc_req *rqstp)
811 if (debug_level) log_from_addr("nlm_free_all", rqstp);
815 void *nlmproc4_null_4_svc(void *arg, struct svc_req *rqstp)
819 if (debug_level) log_from_addr("nlm_free_all", rqstp);