Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / usr.sbin / rpc.lockd / procs.c
1 /*
2  * Copyright (c) 1995
3  *      A.R. Gordon (andrew.gordon@net-tel.co.uk).  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
19  *
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
30  * SUCH DAMAGE.
31  *
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 $
34  */
35
36 #include <string.h>
37 #include "lockd.h"
38
39 #include <sys/param.h>  /* for MAXHOSTNAMELEN   */
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
43 #include <netdb.h>
44
45
46 #define CLIENT_CACHE_SIZE       64      /* No. of client sockets cached */
47 #define CLIENT_CACHE_LIFETIME   120     /* In seconds                   */
48
49 #if 0
50 #undef LOG_DEBUG
51 #undef LOG_ERR
52 #define LOG_DEBUG stderr
53 #define LOG_ERR stderr
54 #define syslog fprintf
55 #endif
56
57 /* log_from_addr ----------------------------------------------------------- */
58 /*
59    Purpose:     Log name of function called and source address
60    Returns:     Nothing
61    Notes:       Extracts the source address from the transport handle
62                 passed in as part of the called procedure specification
63 */
64
65 static void log_from_addr(char *fun_name, struct svc_req *req)
66 {
67   struct sockaddr_in *addr;
68   struct hostent *host;
69   char hostname_buf[40];
70
71   addr = svc_getcaller(req->rq_xprt);
72   host = gethostbyaddr((char *)&(addr->sin_addr), addr->sin_len, AF_INET);
73   if (host)
74   {
75     strncpy(hostname_buf, host->h_name, sizeof(hostname_buf));
76     hostname_buf[sizeof(hostname_buf) -1] = '\0';
77   }
78   else  /* No hostname available - print raw address    */
79   {
80     strcpy(hostname_buf, inet_ntoa(addr->sin_addr));
81   }
82
83   syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf);
84 }
85
86
87 /* get_client -------------------------------------------------------------- */
88 /*
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*.
96
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.
104
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).
110
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.
115 */
116
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;
121
122 static CLIENT *get_client(struct sockaddr_in *host_addr)
123 {
124   CLIENT *client;
125   int sock_no;
126   struct timeval retry_time, time_now;
127   int i;
128
129   gettimeofday(&time_now, NULL);
130
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++)
134   {
135     client = clnt_cache_ptr[i];
136     if (client &&
137       ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME) < time_now.tv_sec))
138     {
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;
144       client = NULL;
145     }
146
147     if (client && !memcmp(&clnt_cache_addr[i], &host_addr->sin_addr,
148       sizeof(struct in_addr)))
149     {
150       /* Found it!                                                      */
151       if (debug_level > 3) syslog(LOG_DEBUG, "Found CLIENT* in cache");
152       return (client);
153     }
154   }
155
156   /* Not found in cache.  Free the next entry if it is in use           */
157   if (clnt_cache_ptr[clnt_cache_next_to_use])
158   {
159     clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
160     clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
161   }
162
163   /* Create the new client handle                                       */
164
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);
170   if (!client)
171   {
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));
175     return NULL;
176   }
177
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;
184
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);
191
192   if (debug_level > 3) syslog(LOG_DEBUG, "Created CLIENT* for %s",
193       inet_ntoa(host_addr->sin_addr));
194   return client;
195 }
196
197
198 /* transmit_result --------------------------------------------------------- */
199 /*
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
205 */
206
207 static void transmit_result(int opcode, void *result, struct svc_req *req)
208 {
209   static char dummy;
210   struct sockaddr_in *addr;
211   CLIENT *cli;
212   int success;
213   struct timeval timeo;
214
215   addr = svc_getcaller(req->rq_xprt);
216   if ((cli = get_client(addr)))
217   {
218     timeo.tv_sec = 0;           /* No timeout - not expecting response  */
219     timeo.tv_usec = 0;
220
221     success = clnt_call(cli, opcode, xdr_nlm_res, result, xdr_void,
222       &dummy, timeo);
223
224     if (debug_level > 2) syslog(LOG_DEBUG, "clnt_call returns %d", success);
225   }
226 }
227
228 /* ------------------------------------------------------------------------- */
229 /*
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"
232    server.
233
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.
242
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.
249
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
252    for testing).
253 */
254
255
256 /* nlm_test ---------------------------------------------------------------- */
257 /*
258    Purpose:     Test whether a specified lock would be granted if requested
259    Returns:     nlm_granted (or error code)
260    Notes:
261 */
262
263 nlm_testres *nlm_test_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
264 {
265   static nlm_testres res;
266   if (debug_level) log_from_addr("nlm_test", rqstp);
267
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;
275   return (&res);
276 }
277
278 nlm4_testres *nlmproc4_test_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
279 {
280   static nlm4_testres res;
281   if (debug_level) log_from_addr("nlm_test", rqstp);
282
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;
290   return (&res);
291 }
292
293 void *nlm_test_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
294 {
295   nlm_testres res;
296   static char dummy;
297   struct sockaddr_in *addr;
298   CLIENT *cli;
299   int success;
300   struct timeval timeo;
301
302   if (debug_level) log_from_addr("nlm_test_msg", rqstp);
303
304   res.cookie = arg->cookie;
305   res.stat.stat = nlm_granted;
306
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)))
311   {
312     timeo.tv_sec = 0;           /* No timeout - not expecting response  */
313     timeo.tv_usec = 0;
314
315     success = clnt_call(cli, NLM_TEST_RES, xdr_nlm_testres, &res, xdr_void,
316       &dummy, timeo);
317
318     if (debug_level > 2) syslog(LOG_DEBUG, "clnt_call returns %d", success);
319   }
320   return (NULL);
321 }
322
323 void *nlmproc4_test_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
324 {
325   nlm4_testres res;
326   static char dummy;
327   struct sockaddr_in *addr;
328   CLIENT *cli;
329   int success;
330   struct timeval timeo;
331
332   if (debug_level) log_from_addr("nlm_test_msg", rqstp);
333
334   res.cookie = arg->cookie;
335   res.stat.stat = nlm4_granted;
336
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)))
341   {
342     timeo.tv_sec = 0;           /* No timeout - not expecting response  */
343     timeo.tv_usec = 0;
344
345     success = clnt_call(cli, NLMPROC4_TEST_RES, xdr_nlm_testres, &res, xdr_void,
346       &dummy, timeo);
347
348     if (debug_level > 2) syslog(LOG_DEBUG, "clnt_call returns %d", success);
349   }
350   return (NULL);
351 }
352
353
354
355 /* nlm_lock ---------------------------------------------------------------- */
356 /*
357    Purposes:    Establish a lock
358    Returns:     granted, denied or blocked
359    Notes:       *** grace period support missing
360 */
361
362 nlm_res *nlm_lock_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
363 {
364   static nlm_res res;
365   if (debug_level) log_from_addr("nlm_lock", rqstp);
366
367   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
368   res.cookie = arg->cookie;
369
370   res.stat.stat = nlm_granted;
371   return (&res);
372 }
373
374 nlm4_res *nlmproc4_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
375 {
376   static nlm4_res res;
377
378   if (debug_level) log_from_addr("nlm_lock", rqstp);
379
380   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
381   res.cookie = arg->cookie;
382
383   res.stat.stat = nlm4_granted;
384   return (&res);
385 }
386
387 void *nlm_lock_msg_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
388 {
389   static nlm_res res;
390
391   if (debug_level) log_from_addr("nlm_lock_msg", rqstp);
392
393   res.cookie = arg->cookie;
394   res.stat.stat = nlm_granted;
395   transmit_result(NLM_LOCK_RES, &res, rqstp);
396
397   return (NULL);
398 }
399
400 void *nlmproc4_lock_msg_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
401 {
402   static nlm4_res res;
403
404   if (debug_level) log_from_addr("nlm_lock_msg", rqstp);
405
406   res.cookie = arg->cookie;
407   res.stat.stat = nlm4_granted;
408   transmit_result(NLMPROC4_LOCK_RES, &res, rqstp);
409
410   return (NULL);
411 }
412
413
414 /* nlm_cancel -------------------------------------------------------------- */
415 /*
416    Purpose:     Cancel a blocked lock request
417    Returns:     granted or denied
418    Notes:
419 */
420
421 nlm_res *nlm_cancel_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
422 {
423   static nlm_res res;
424   if (debug_level) log_from_addr("nlm_cancel", rqstp);
425
426   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
427   res.cookie = arg->cookie;
428
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;
432   return (&res);
433 }
434
435 nlm4_res *nlmproc4_cancel_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
436 {
437   static nlm4_res res;
438   if (debug_level) log_from_addr("nlm_cancel", rqstp);
439
440   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
441   res.cookie = arg->cookie;
442
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;
446   return (&res);
447 }
448
449 void *nlm_cancel_msg_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
450 {
451   static nlm_res res;
452   if (debug_level) log_from_addr("nlm_cancel_msg", rqstp);
453
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);
459   return (NULL);
460 }
461
462 void *nlmproc4_cancel_msg_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
463 {
464   static nlm4_res res;
465   if (debug_level) log_from_addr("nlm_cancel_msg", rqstp);
466
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);
472   return (NULL);
473 }
474
475 /* nlm_unlock -------------------------------------------------------------- */
476 /*
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.
482 */
483
484 nlm_res *nlm_unlock_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
485 {
486   static nlm_res res;
487   if (debug_level) log_from_addr("nlm_unlock", rqstp);
488
489   res.stat.stat= nlm_granted;
490   res.cookie = arg->cookie;
491
492   return (&res);
493 }
494
495 nlm4_res *nlmproc4_unlock_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
496 {
497   static nlm4_res res;
498   if (debug_level) log_from_addr("nlm_unlock", rqstp);
499
500   res.stat.stat= nlm4_granted;
501   res.cookie = arg->cookie;
502
503   return (&res);
504 }
505
506 void *nlm_unlock_msg_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
507 {
508   static nlm_res res;
509   if (debug_level) log_from_addr("nlm_unlock_msg", rqstp);
510
511   res.stat.stat = nlm_granted;
512   res.cookie = arg->cookie;
513
514   transmit_result(NLM_UNLOCK_RES, &res, rqstp);
515   return (NULL);
516 }
517
518 void *nlmproc4_unlock_msg_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
519 {
520   static nlm4_res res;
521   if (debug_level) log_from_addr("nlm_unlock_msg", rqstp);
522
523   res.stat.stat = nlm4_granted;
524   res.cookie = arg->cookie;
525
526   transmit_result(NLMPROC4_UNLOCK_RES, &res, rqstp);
527   return (NULL);
528 }
529
530 /* ------------------------------------------------------------------------- */
531 /*
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.
536
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
539    call terms.
540 */
541
542 /* nlm_granted ------------------------------------------------------------- */
543 /*
544    Purpose:     Receive notification that formerly blocked lock now granted
545    Returns:     always success ('granted')
546    Notes:       
547 */
548
549 nlm_res *nlm_granted_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
550 {
551   static nlm_res res;
552   if (debug_level) log_from_addr("nlm_granted", rqstp);
553
554   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
555   res.cookie = arg->cookie;
556
557   res.stat.stat = nlm_granted;
558   return (&res);
559 }
560
561 nlm4_res *nlmproc4_granted_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
562 {
563   static nlm4_res res;
564   if (debug_level) log_from_addr("nlm_granted", rqstp);
565
566   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
567   res.cookie = arg->cookie;
568
569   res.stat.stat = nlm4_granted;
570   return (&res);
571 }
572
573 void *nlm_granted_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
574 {
575   nlm_res res;
576   if (debug_level) log_from_addr("nlm_granted_msg", rqstp);
577
578   res.cookie = arg->cookie;
579   res.stat.stat = nlm_granted;
580   transmit_result(NLM_GRANTED_RES, &res, rqstp);
581   return (NULL);
582 }
583
584 void *nlmproc4_granted_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
585 {
586   nlm4_res res;
587   if (debug_level) log_from_addr("nlm_granted_msg", rqstp);
588
589   res.cookie = arg->cookie;
590   res.stat.stat = nlm4_granted;
591   transmit_result(NLMPROC4_GRANTED_RES, &res, rqstp);
592   return (NULL);
593 }
594
595 /* nlm_test_res ------------------------------------------------------------ */
596 /*
597    Purpose:     Accept result from earlier nlm_test_msg() call
598    Returns:     Nothing
599 */
600
601 void *nlm_test_res_1_svc(nlm_testres *arg, struct svc_req *rqstp)
602 {
603   if (debug_level) log_from_addr("nlm_test_res", rqstp);
604   return (NULL);
605 }
606
607 void *nlmproc4_test_res_4_svc(nlm4_testres *arg, struct svc_req *rqstp)
608 {
609   if (debug_level) log_from_addr("nlm_test_res", rqstp);
610   return (NULL);
611 }
612
613 /* nlm_lock_res ------------------------------------------------------------ */
614 /*
615    Purpose:     Accept result from earlier nlm_lock_msg() call
616    Returns:     Nothing
617 */
618
619 void *nlm_lock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
620 {
621   if (debug_level) log_from_addr("nlm_lock_res", rqstp);
622
623   return (NULL);
624 }
625
626 void *nlmproc4_lock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
627 {
628   if (debug_level) log_from_addr("nlm_lock_res", rqstp);
629
630   return (NULL);
631 }
632
633 /* nlm_cancel_res ---------------------------------------------------------- */
634 /*
635    Purpose:     Accept result from earlier nlm_cancel_msg() call
636    Returns:     Nothing
637 */
638
639 void *nlm_cancel_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
640 {
641   if (debug_level) log_from_addr("nlm_cancel_res", rqstp);
642   return (NULL);
643 }
644
645 void *nlmproc4_cancel_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
646 {
647   if (debug_level) log_from_addr("nlm_cancel_res", rqstp);
648   return (NULL);
649 }
650
651 /* nlm_unlock_res ---------------------------------------------------------- */
652 /*
653    Purpose:     Accept result from earlier nlm_unlock_msg() call
654    Returns:     Nothing
655 */
656
657 void *nlm_unlock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
658 {
659   if (debug_level) log_from_addr("nlm_unlock_res", rqstp);
660   return (NULL);
661 }
662
663 void *nlmproc4_unlock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
664 {
665   if (debug_level) log_from_addr("nlm_unlock_res", rqstp);
666   return (NULL);
667 }
668
669 /* nlm_granted_res --------------------------------------------------------- */
670 /*
671    Purpose:     Accept result from earlier nlm_granted_msg() call
672    Returns:     Nothing
673 */
674
675 void *nlm_granted_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
676 {
677   if (debug_level) log_from_addr("nlm_granted_res", rqstp);
678   return (NULL);
679 }
680
681 void *nlmproc4_granted_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
682 {
683   if (debug_level) log_from_addr("nlm_granted_res", rqstp);
684   return (NULL);
685 }
686
687 /* ------------------------------------------------------------------------- */
688 /*
689    Calls for PCNFS locking (aka non-monitored locking, no involvement
690    of rpc.statd).
691
692    These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
693 */
694
695
696 /* nlm_share --------------------------------------------------------------- */
697 /*
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.
702 */
703
704 nlm_shareres *nlm_share_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
705 {
706   static nlm_shareres res;
707   if (debug_level) log_from_addr("nlm_share", rqstp);
708
709   res.cookie = arg->cookie;
710   res.stat = nlm_granted;
711   res.sequence = 1234356;       /* X/Open says this field is ignored?   */
712   return (&res);
713 }
714
715 nlm4_shareres *nlmproc4_share_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
716 {
717   static nlm4_shareres res;
718   if (debug_level) log_from_addr("nlm_share", rqstp);
719
720   res.cookie = arg->cookie;
721   res.stat = nlm4_granted;
722   res.sequence = 1234356;       /* X/Open says this field is ignored?   */
723   return (&res);
724 }
725
726 /* nlm_unshare ------------------------------------------------------------ */
727 /*
728    Purpose:     Release a DOS-style lock
729    Returns:     nlm_granted, unless in grace period
730    Notes:
731 */
732
733 nlm_shareres *nlm_unshare_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
734 {
735   static nlm_shareres res;
736   if (debug_level) log_from_addr("nlm_unshare", rqstp);
737
738   res.cookie = arg->cookie;
739   res.stat = nlm_granted;
740   res.sequence = 1234356;       /* X/Open says this field is ignored?   */
741   return (&res);
742 }
743
744 nlm4_shareres *nlmproc4_unshare_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
745 {
746   static nlm4_shareres res;
747   if (debug_level) log_from_addr("nlm_unshare", rqstp);
748
749   res.cookie = arg->cookie;
750   res.stat = nlm4_granted;
751   res.sequence = 1234356;       /* X/Open says this field is ignored?   */
752   return (&res);
753 }
754
755 /* nlm_nm_lock ------------------------------------------------------------ */
756 /*
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.
764 */
765
766 nlm_res *nlm_nm_lock_3_svc(nlm_lockargs *arg, struct svc_req *rqstp)
767 {
768   static nlm_res res;
769   if (debug_level) log_from_addr("nlm_nm_lock", rqstp);
770
771   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
772   res.cookie = arg->cookie;
773   res.stat.stat = nlm_granted;
774   return (&res);
775 }
776
777 nlm4_res *nlmproc4_nm_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
778 {
779   static nlm4_res res;
780   if (debug_level) log_from_addr("nlm_nm_lock", rqstp);
781
782   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
783   res.cookie = arg->cookie;
784   res.stat.stat = nlm4_granted;
785   return (&res);
786 }
787
788 /* nlm_free_all ------------------------------------------------------------ */
789 /*
790    Purpose:     Release all locks held by a named client
791    Returns:     Nothing
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.
797 */
798
799 void *nlm_free_all_3_svc(nlm_notify *arg, struct svc_req *rqstp)
800 {
801   static char dummy;
802
803   if (debug_level) log_from_addr("nlm_free_all", rqstp);
804   return (&dummy);
805 }
806
807 void *nlmproc4_free_all_4_svc(nlm4_notify *arg, struct svc_req *rqstp)
808 {
809   static char dummy;
810
811   if (debug_level) log_from_addr("nlm_free_all", rqstp);
812   return (&dummy);
813 }
814
815 void *nlmproc4_null_4_svc(void *arg, struct svc_req *rqstp)
816 {
817   static char dummy;
818
819   if (debug_level) log_from_addr("nlm_free_all", rqstp);
820   return (&dummy);
821 }
822
823