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.3 2005/11/25 00:32:49 swildner 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
66 log_from_addr(char *fun_name
, struct svc_req
*req
)
68 struct sockaddr_in
*addr
;
70 char hostname_buf
[40];
72 addr
= svc_getcaller(req
->rq_xprt
);
73 host
= gethostbyaddr((char *)&(addr
->sin_addr
), addr
->sin_len
, AF_INET
);
76 strncpy(hostname_buf
, host
->h_name
, sizeof(hostname_buf
));
77 hostname_buf
[sizeof(hostname_buf
) -1] = '\0';
79 else /* No hostname available - print raw address */
81 strcpy(hostname_buf
, inet_ntoa(addr
->sin_addr
));
84 syslog(LOG_DEBUG
, "%s from %s", fun_name
, hostname_buf
);
88 /* get_client -------------------------------------------------------------- */
90 Purpose: Get a CLIENT* for making RPC calls to lockd on given host
91 Returns: CLIENT* pointer, from clnt_udp_create, or NULL if error
92 Notes: Creating a CLIENT* is quite expensive, involving a
93 conversation with the remote portmapper to get the
94 port number. Since a given client is quite likely
95 to make several locking requests in succession, it is
96 desirable to cache the created CLIENT*.
98 Since we are using UDP rather than TCP, there is no cost
99 to the remote system in keeping these cached indefinitely.
100 Unfortunately there is a snag: if the remote system
101 reboots, the cached portmapper results will be invalid,
102 and we will never detect this since all of the xxx_msg()
103 calls return no result - we just fire off a udp packet
104 and hope for the best.
106 We solve this by discarding cached values after two
107 minutes, regardless of whether they have been used
108 in the meanwhile (since a bad one might have been used
109 plenty of times, as the host keeps retrying the request
110 and we keep sending the reply back to the wrong port).
112 Given that the entries will always expire in the order
113 that they were created, there is no point in a LRU
114 algorithm for when the cache gets full - entries are
115 always re-used in sequence.
118 static CLIENT
*clnt_cache_ptr
[CLIENT_CACHE_SIZE
];
119 static long clnt_cache_time
[CLIENT_CACHE_SIZE
]; /* time entry created */
120 static struct in_addr clnt_cache_addr
[CLIENT_CACHE_SIZE
];
121 static int clnt_cache_next_to_use
= 0;
124 get_client(struct sockaddr_in
*host_addr
)
128 struct timeval retry_time
, time_now
;
131 gettimeofday(&time_now
, NULL
);
133 /* Search for the given client in the cache, zapping any expired */
134 /* entries that we happen to notice in passing. */
135 for (i
= 0; i
< CLIENT_CACHE_SIZE
; i
++)
137 client
= clnt_cache_ptr
[i
];
139 ((clnt_cache_time
[i
] + CLIENT_CACHE_LIFETIME
) < time_now
.tv_sec
))
141 /* Cache entry has expired. */
142 if (debug_level
> 3) syslog(LOG_DEBUG
, "Expired CLIENT* in cache");
143 clnt_cache_time
[i
] = 0L;
144 clnt_destroy(client
);
145 clnt_cache_ptr
[i
] = NULL
;
149 if (client
&& !memcmp(&clnt_cache_addr
[i
], &host_addr
->sin_addr
,
150 sizeof(struct in_addr
)))
153 if (debug_level
> 3) syslog(LOG_DEBUG
, "Found CLIENT* in cache");
158 /* Not found in cache. Free the next entry if it is in use */
159 if (clnt_cache_ptr
[clnt_cache_next_to_use
])
161 clnt_destroy(clnt_cache_ptr
[clnt_cache_next_to_use
]);
162 clnt_cache_ptr
[clnt_cache_next_to_use
] = NULL
;
165 /* Create the new client handle */
167 sock_no
= RPC_ANYSOCK
;
168 retry_time
.tv_sec
= 5;
169 retry_time
.tv_usec
= 0;
170 host_addr
->sin_port
= 0; /* Force consultation with portmapper */
171 client
= clntudp_create(host_addr
, NLM_PROG
, NLM_VERS
, retry_time
, &sock_no
);
174 syslog(LOG_ERR
, "%s", clnt_spcreateerror("clntudp_create"));
175 syslog(LOG_ERR
, "Unable to return result to %s",
176 inet_ntoa(host_addr
->sin_addr
));
180 /* Success - update the cache entry */
181 clnt_cache_ptr
[clnt_cache_next_to_use
] = client
;
182 clnt_cache_addr
[clnt_cache_next_to_use
] = host_addr
->sin_addr
;
183 clnt_cache_time
[clnt_cache_next_to_use
] = time_now
.tv_sec
;
184 if (++clnt_cache_next_to_use
> CLIENT_CACHE_SIZE
)
185 clnt_cache_next_to_use
= 0;
187 /* Disable the default timeout, so we can specify our own in calls */
188 /* to clnt_call(). [note that the timeout is a different concept */
189 /* from the retry period set in clnt_udp_create() above.] */
190 retry_time
.tv_sec
= -1;
191 retry_time
.tv_usec
= -1;
192 clnt_control(client
, CLSET_TIMEOUT
, &retry_time
);
194 if (debug_level
> 3) syslog(LOG_DEBUG
, "Created CLIENT* for %s",
195 inet_ntoa(host_addr
->sin_addr
));
200 /* transmit_result --------------------------------------------------------- */
202 Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs
203 Returns: Nothing - we have no idea if the datagram got there
204 Notes: clnt_call() will always fail (with timeout) as we are
205 calling it with timeout 0 as a hack to just issue a datagram
206 without expecting a result
210 transmit_result(int opcode
, void *result
, struct svc_req
*req
)
213 struct sockaddr_in
*addr
;
216 struct timeval timeo
;
218 addr
= svc_getcaller(req
->rq_xprt
);
219 if ((cli
= get_client(addr
)))
221 timeo
.tv_sec
= 0; /* No timeout - not expecting response */
224 success
= clnt_call(cli
, opcode
, xdr_nlm_res
, result
, xdr_void
,
227 if (debug_level
> 2) syslog(LOG_DEBUG
, "clnt_call returns %d", success
);
231 /* ------------------------------------------------------------------------- */
233 Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
234 involved to ensure reclaim of locks after a crash of the "stateless"
237 These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
238 The first are standard RPCs with argument and result.
239 The nlm_xxx_msg() calls implement exactly the same functions, but
240 use two pseudo-RPCs (one in each direction). These calls are NOT
241 standard use of the RPC protocol in that they do not return a result
242 at all (NB. this is quite different from returning a void result).
243 The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
244 datagrams, requiring higher-level code to perform retries.
246 Despite the disadvantages of the nlm_xxx_msg() approach (some of which
247 are documented in the comments to get_client() above), this is the
248 interface used by all current commercial NFS implementations
249 [Solaris, SCO, AIX etc.]. This is presumed to be because these allow
250 implementations to continue using the standard RPC libraries, while
251 avoiding the block-until-result nature of the library interface.
253 No client implementations have been identified so far that make use
254 of the true RPC version (early SunOS releases would be a likely candidate
259 /* nlm_test ---------------------------------------------------------------- */
261 Purpose: Test whether a specified lock would be granted if requested
262 Returns: nlm_granted (or error code)
267 nlm_test_1_svc(nlm_testargs
*arg
, struct svc_req
*rqstp
)
269 static nlm_testres res
;
270 if (debug_level
) log_from_addr("nlm_test", rqstp
);
272 /* Copy the cookie from the argument into the result. Note that this */
273 /* is slightly hazardous, as the structure contains a pointer to a */
274 /* malloc()ed buffer that will get freed by the caller. However, the */
275 /* main function transmits the result before freeing the argument */
276 /* so it is in fact safe. */
277 res
.cookie
= arg
->cookie
;
278 res
.stat
.stat
= nlm_granted
;
283 nlmproc4_test_4_svc(nlm4_testargs
*arg
, struct svc_req
*rqstp
)
285 static nlm4_testres res
;
286 if (debug_level
) log_from_addr("nlm_test", rqstp
);
288 /* Copy the cookie from the argument into the result. Note that this */
289 /* is slightly hazardous, as the structure contains a pointer to a */
290 /* malloc()ed buffer that will get freed by the caller. However, the */
291 /* main function transmits the result before freeing the argument */
292 /* so it is in fact safe. */
293 res
.cookie
= arg
->cookie
;
294 res
.stat
.stat
= nlm4_granted
;
299 nlm_test_msg_1_svc(nlm_testargs
*arg
, struct svc_req
*rqstp
)
303 struct sockaddr_in
*addr
;
306 struct timeval timeo
;
308 if (debug_level
) log_from_addr("nlm_test_msg", rqstp
);
310 res
.cookie
= arg
->cookie
;
311 res
.stat
.stat
= nlm_granted
;
313 /* nlm_test has different result type to the other operations, so */
314 /* can't use transmit_result() in this case */
315 addr
= svc_getcaller(rqstp
->rq_xprt
);
316 if ((cli
= get_client(addr
)))
318 timeo
.tv_sec
= 0; /* No timeout - not expecting response */
321 success
= clnt_call(cli
, NLM_TEST_RES
, xdr_nlm_testres
, &res
, xdr_void
,
324 if (debug_level
> 2) syslog(LOG_DEBUG
, "clnt_call returns %d", success
);
330 nlmproc4_test_msg_4_svc(nlm4_testargs
*arg
, struct svc_req
*rqstp
)
334 struct sockaddr_in
*addr
;
337 struct timeval timeo
;
339 if (debug_level
) log_from_addr("nlm_test_msg", rqstp
);
341 res
.cookie
= arg
->cookie
;
342 res
.stat
.stat
= nlm4_granted
;
344 /* nlm_test has different result type to the other operations, so */
345 /* can't use transmit_result() in this case */
346 addr
= svc_getcaller(rqstp
->rq_xprt
);
347 if ((cli
= get_client(addr
)))
349 timeo
.tv_sec
= 0; /* No timeout - not expecting response */
352 success
= clnt_call(cli
, NLMPROC4_TEST_RES
, xdr_nlm_testres
, &res
, xdr_void
,
355 if (debug_level
> 2) syslog(LOG_DEBUG
, "clnt_call returns %d", success
);
362 /* nlm_lock ---------------------------------------------------------------- */
364 Purposes: Establish a lock
365 Returns: granted, denied or blocked
366 Notes: *** grace period support missing
370 nlm_lock_1_svc(nlm_lockargs
*arg
, struct svc_req
*rqstp
)
373 if (debug_level
) log_from_addr("nlm_lock", rqstp
);
375 /* copy cookie from arg to result. See comment in nlm_test_1() */
376 res
.cookie
= arg
->cookie
;
378 res
.stat
.stat
= nlm_granted
;
383 nlmproc4_lock_4_svc(nlm4_lockargs
*arg
, struct svc_req
*rqstp
)
387 if (debug_level
) log_from_addr("nlm_lock", rqstp
);
389 /* copy cookie from arg to result. See comment in nlm_test_1() */
390 res
.cookie
= arg
->cookie
;
392 res
.stat
.stat
= nlm4_granted
;
397 nlm_lock_msg_1_svc(nlm_lockargs
*arg
, struct svc_req
*rqstp
)
401 if (debug_level
) log_from_addr("nlm_lock_msg", rqstp
);
403 res
.cookie
= arg
->cookie
;
404 res
.stat
.stat
= nlm_granted
;
405 transmit_result(NLM_LOCK_RES
, &res
, rqstp
);
411 nlmproc4_lock_msg_4_svc(nlm4_lockargs
*arg
, struct svc_req
*rqstp
)
415 if (debug_level
) log_from_addr("nlm_lock_msg", rqstp
);
417 res
.cookie
= arg
->cookie
;
418 res
.stat
.stat
= nlm4_granted
;
419 transmit_result(NLMPROC4_LOCK_RES
, &res
, rqstp
);
425 /* nlm_cancel -------------------------------------------------------------- */
427 Purpose: Cancel a blocked lock request
428 Returns: granted or denied
433 nlm_cancel_1_svc(nlm_cancargs
*arg
, struct svc_req
*rqstp
)
436 if (debug_level
) log_from_addr("nlm_cancel", rqstp
);
438 /* copy cookie from arg to result. See comment in nlm_test_1() */
439 res
.cookie
= arg
->cookie
;
441 /* Since at present we never return 'nlm_blocked', there can never be */
442 /* a lock to cancel, so this call always fails. */
443 res
.stat
.stat
= nlm_denied
;
448 nlmproc4_cancel_4_svc(nlm4_cancargs
*arg
, struct svc_req
*rqstp
)
451 if (debug_level
) log_from_addr("nlm_cancel", rqstp
);
453 /* copy cookie from arg to result. See comment in nlm_test_1() */
454 res
.cookie
= arg
->cookie
;
456 /* Since at present we never return 'nlm_blocked', there can never be */
457 /* a lock to cancel, so this call always fails. */
458 res
.stat
.stat
= nlm4_denied
;
463 nlm_cancel_msg_1_svc(nlm_cancargs
*arg
, struct svc_req
*rqstp
)
466 if (debug_level
) log_from_addr("nlm_cancel_msg", rqstp
);
468 res
.cookie
= arg
->cookie
;
469 /* Since at present we never return 'nlm_blocked', there can never be */
470 /* a lock to cancel, so this call always fails. */
471 res
.stat
.stat
= nlm_denied
;
472 transmit_result(NLM_CANCEL_RES
, &res
, rqstp
);
477 nlmproc4_cancel_msg_4_svc(nlm4_cancargs
*arg
, struct svc_req
*rqstp
)
480 if (debug_level
) log_from_addr("nlm_cancel_msg", rqstp
);
482 res
.cookie
= arg
->cookie
;
483 /* Since at present we never return 'nlm_blocked', there can never be */
484 /* a lock to cancel, so this call always fails. */
485 res
.stat
.stat
= nlm4_denied
;
486 transmit_result(NLMPROC4_CANCEL_RES
, &res
, rqstp
);
490 /* nlm_unlock -------------------------------------------------------------- */
492 Purpose: Release an existing lock
493 Returns: Always granted, unless during grace period
494 Notes: "no such lock" error condition is ignored, as the
495 protocol uses unreliable UDP datagrams, and may well
496 re-try an unlock that has already succeeded.
500 nlm_unlock_1_svc(nlm_unlockargs
*arg
, struct svc_req
*rqstp
)
503 if (debug_level
) log_from_addr("nlm_unlock", rqstp
);
505 res
.stat
.stat
= nlm_granted
;
506 res
.cookie
= arg
->cookie
;
512 nlmproc4_unlock_4_svc(nlm4_unlockargs
*arg
, struct svc_req
*rqstp
)
515 if (debug_level
) log_from_addr("nlm_unlock", rqstp
);
517 res
.stat
.stat
= nlm4_granted
;
518 res
.cookie
= arg
->cookie
;
524 nlm_unlock_msg_1_svc(nlm_unlockargs
*arg
, struct svc_req
*rqstp
)
527 if (debug_level
) log_from_addr("nlm_unlock_msg", rqstp
);
529 res
.stat
.stat
= nlm_granted
;
530 res
.cookie
= arg
->cookie
;
532 transmit_result(NLM_UNLOCK_RES
, &res
, rqstp
);
537 nlmproc4_unlock_msg_4_svc(nlm4_unlockargs
*arg
, struct svc_req
*rqstp
)
540 if (debug_level
) log_from_addr("nlm_unlock_msg", rqstp
);
542 res
.stat
.stat
= nlm4_granted
;
543 res
.cookie
= arg
->cookie
;
545 transmit_result(NLMPROC4_UNLOCK_RES
, &res
, rqstp
);
549 /* ------------------------------------------------------------------------- */
551 Client-side pseudo-RPCs for results. Note that for the client there
552 are only nlm_xxx_msg() versions of each call, since the 'real RPC'
553 version returns the results in the RPC result, and so the client
554 does not normally receive incoming RPCs.
556 The exception to this is nlm_granted(), which is genuinely an RPC
557 call from the server to the client - a 'call-back' in normal procedure
561 /* nlm_granted ------------------------------------------------------------- */
563 Purpose: Receive notification that formerly blocked lock now granted
564 Returns: always success ('granted')
569 nlm_granted_1_svc(nlm_testargs
*arg
, struct svc_req
*rqstp
)
572 if (debug_level
) log_from_addr("nlm_granted", rqstp
);
574 /* copy cookie from arg to result. See comment in nlm_test_1() */
575 res
.cookie
= arg
->cookie
;
577 res
.stat
.stat
= nlm_granted
;
582 nlmproc4_granted_4_svc(nlm4_testargs
*arg
, struct svc_req
*rqstp
)
585 if (debug_level
) log_from_addr("nlm_granted", rqstp
);
587 /* copy cookie from arg to result. See comment in nlm_test_1() */
588 res
.cookie
= arg
->cookie
;
590 res
.stat
.stat
= nlm4_granted
;
595 nlm_granted_msg_1_svc(nlm_testargs
*arg
, struct svc_req
*rqstp
)
598 if (debug_level
) log_from_addr("nlm_granted_msg", rqstp
);
600 res
.cookie
= arg
->cookie
;
601 res
.stat
.stat
= nlm_granted
;
602 transmit_result(NLM_GRANTED_RES
, &res
, rqstp
);
607 nlmproc4_granted_msg_4_svc(nlm4_testargs
*arg
, struct svc_req
*rqstp
)
610 if (debug_level
) log_from_addr("nlm_granted_msg", rqstp
);
612 res
.cookie
= arg
->cookie
;
613 res
.stat
.stat
= nlm4_granted
;
614 transmit_result(NLMPROC4_GRANTED_RES
, &res
, rqstp
);
618 /* nlm_test_res ------------------------------------------------------------ */
620 Purpose: Accept result from earlier nlm_test_msg() call
625 nlm_test_res_1_svc(nlm_testres
*arg
, struct svc_req
*rqstp
)
627 if (debug_level
) log_from_addr("nlm_test_res", rqstp
);
632 nlmproc4_test_res_4_svc(nlm4_testres
*arg
, struct svc_req
*rqstp
)
634 if (debug_level
) log_from_addr("nlm_test_res", rqstp
);
638 /* nlm_lock_res ------------------------------------------------------------ */
640 Purpose: Accept result from earlier nlm_lock_msg() call
645 nlm_lock_res_1_svc(nlm_res
*arg
, struct svc_req
*rqstp
)
647 if (debug_level
) log_from_addr("nlm_lock_res", rqstp
);
653 nlmproc4_lock_res_4_svc(nlm4_res
*arg
, struct svc_req
*rqstp
)
655 if (debug_level
) log_from_addr("nlm_lock_res", rqstp
);
660 /* nlm_cancel_res ---------------------------------------------------------- */
662 Purpose: Accept result from earlier nlm_cancel_msg() call
667 nlm_cancel_res_1_svc(nlm_res
*arg
, struct svc_req
*rqstp
)
669 if (debug_level
) log_from_addr("nlm_cancel_res", rqstp
);
674 nlmproc4_cancel_res_4_svc(nlm4_res
*arg
, struct svc_req
*rqstp
)
676 if (debug_level
) log_from_addr("nlm_cancel_res", rqstp
);
680 /* nlm_unlock_res ---------------------------------------------------------- */
682 Purpose: Accept result from earlier nlm_unlock_msg() call
687 nlm_unlock_res_1_svc(nlm_res
*arg
, struct svc_req
*rqstp
)
689 if (debug_level
) log_from_addr("nlm_unlock_res", rqstp
);
694 nlmproc4_unlock_res_4_svc(nlm4_res
*arg
, struct svc_req
*rqstp
)
696 if (debug_level
) log_from_addr("nlm_unlock_res", rqstp
);
700 /* nlm_granted_res --------------------------------------------------------- */
702 Purpose: Accept result from earlier nlm_granted_msg() call
707 nlm_granted_res_1_svc(nlm_res
*arg
, struct svc_req
*rqstp
)
709 if (debug_level
) log_from_addr("nlm_granted_res", rqstp
);
714 nlmproc4_granted_res_4_svc(nlm4_res
*arg
, struct svc_req
*rqstp
)
716 if (debug_level
) log_from_addr("nlm_granted_res", rqstp
);
720 /* ------------------------------------------------------------------------- */
722 Calls for PCNFS locking (aka non-monitored locking, no involvement
725 These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
729 /* nlm_share --------------------------------------------------------------- */
731 Purpose: Establish a DOS-style lock
732 Returns: success or failure
733 Notes: Blocking locks are not supported - client is expected
734 to retry if required.
738 nlm_share_3_svc(nlm_shareargs
*arg
, struct svc_req
*rqstp
)
740 static nlm_shareres res
;
741 if (debug_level
) log_from_addr("nlm_share", rqstp
);
743 res
.cookie
= arg
->cookie
;
744 res
.stat
= nlm_granted
;
745 res
.sequence
= 1234356; /* X/Open says this field is ignored? */
750 nlmproc4_share_4_svc(nlm4_shareargs
*arg
, struct svc_req
*rqstp
)
752 static nlm4_shareres res
;
753 if (debug_level
) log_from_addr("nlm_share", rqstp
);
755 res
.cookie
= arg
->cookie
;
756 res
.stat
= nlm4_granted
;
757 res
.sequence
= 1234356; /* X/Open says this field is ignored? */
761 /* nlm_unshare ------------------------------------------------------------ */
763 Purpose: Release a DOS-style lock
764 Returns: nlm_granted, unless in grace period
769 nlm_unshare_3_svc(nlm_shareargs
*arg
, struct svc_req
*rqstp
)
771 static nlm_shareres res
;
772 if (debug_level
) log_from_addr("nlm_unshare", rqstp
);
774 res
.cookie
= arg
->cookie
;
775 res
.stat
= nlm_granted
;
776 res
.sequence
= 1234356; /* X/Open says this field is ignored? */
781 nlmproc4_unshare_4_svc(nlm4_shareargs
*arg
, struct svc_req
*rqstp
)
783 static nlm4_shareres res
;
784 if (debug_level
) log_from_addr("nlm_unshare", rqstp
);
786 res
.cookie
= arg
->cookie
;
787 res
.stat
= nlm4_granted
;
788 res
.sequence
= 1234356; /* X/Open says this field is ignored? */
792 /* nlm_nm_lock ------------------------------------------------------------ */
794 Purpose: non-monitored version of nlm_lock()
795 Returns: as for nlm_lock()
796 Notes: These locks are in the same style as the standard nlm_lock,
797 but the rpc.statd should not be called to establish a
798 monitor for the client machine, since that machine is
799 declared not to be running a rpc.statd, and so would not
800 respond to the statd protocol.
804 nlm_nm_lock_3_svc(nlm_lockargs
*arg
, struct svc_req
*rqstp
)
807 if (debug_level
) log_from_addr("nlm_nm_lock", rqstp
);
809 /* copy cookie from arg to result. See comment in nlm_test_1() */
810 res
.cookie
= arg
->cookie
;
811 res
.stat
.stat
= nlm_granted
;
816 nlmproc4_nm_lock_4_svc(nlm4_lockargs
*arg
, struct svc_req
*rqstp
)
819 if (debug_level
) log_from_addr("nlm_nm_lock", rqstp
);
821 /* copy cookie from arg to result. See comment in nlm_test_1() */
822 res
.cookie
= arg
->cookie
;
823 res
.stat
.stat
= nlm4_granted
;
827 /* nlm_free_all ------------------------------------------------------------ */
829 Purpose: Release all locks held by a named client
831 Notes: Potential denial of service security problem here - the
832 locks to be released are specified by a host name, independent
833 of the address from which the request has arrived.
834 Should probably be rejected if the named host has been
835 using monitored locks.
839 nlm_free_all_3_svc(nlm_notify
*arg
, struct svc_req
*rqstp
)
843 if (debug_level
) log_from_addr("nlm_free_all", rqstp
);
848 nlmproc4_free_all_4_svc(nlm4_notify
*arg
, struct svc_req
*rqstp
)
852 if (debug_level
) log_from_addr("nlm_free_all", rqstp
);
857 nlmproc4_null_4_svc(void *arg
, struct svc_req
*rqstp
)
861 if (debug_level
) log_from_addr("nlm_free_all", rqstp
);