7245445a5eb855e20c79dc95097f8ba286a8b497
[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.3 2005/11/25 00:32:49 swildner 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
66 log_from_addr(char *fun_name, struct svc_req *req)
67 {
68   struct sockaddr_in *addr;
69   struct hostent *host;
70   char hostname_buf[40];
71
72   addr = svc_getcaller(req->rq_xprt);
73   host = gethostbyaddr((char *)&(addr->sin_addr), addr->sin_len, AF_INET);
74   if (host)
75   {
76     strncpy(hostname_buf, host->h_name, sizeof(hostname_buf));
77     hostname_buf[sizeof(hostname_buf) -1] = '\0';
78   }
79   else  /* No hostname available - print raw address    */
80   {
81     strcpy(hostname_buf, inet_ntoa(addr->sin_addr));
82   }
83
84   syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf);
85 }
86
87
88 /* get_client -------------------------------------------------------------- */
89 /*
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*.
97
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.
105
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).
111
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.
116 */
117
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;
122
123 static CLIENT *
124 get_client(struct sockaddr_in *host_addr)
125 {
126   CLIENT *client;
127   int sock_no;
128   struct timeval retry_time, time_now;
129   int i;
130
131   gettimeofday(&time_now, NULL);
132
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++)
136   {
137     client = clnt_cache_ptr[i];
138     if (client &&
139       ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME) < time_now.tv_sec))
140     {
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;
146       client = NULL;
147     }
148
149     if (client && !memcmp(&clnt_cache_addr[i], &host_addr->sin_addr,
150       sizeof(struct in_addr)))
151     {
152       /* Found it!                                                      */
153       if (debug_level > 3) syslog(LOG_DEBUG, "Found CLIENT* in cache");
154       return (client);
155     }
156   }
157
158   /* Not found in cache.  Free the next entry if it is in use           */
159   if (clnt_cache_ptr[clnt_cache_next_to_use])
160   {
161     clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
162     clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
163   }
164
165   /* Create the new client handle                                       */
166
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);
172   if (!client)
173   {
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));
177     return NULL;
178   }
179
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;
186
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);
193
194   if (debug_level > 3) syslog(LOG_DEBUG, "Created CLIENT* for %s",
195       inet_ntoa(host_addr->sin_addr));
196   return client;
197 }
198
199
200 /* transmit_result --------------------------------------------------------- */
201 /*
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
207 */
208
209 static void
210 transmit_result(int opcode, void *result, struct svc_req *req)
211 {
212   static char dummy;
213   struct sockaddr_in *addr;
214   CLIENT *cli;
215   int success;
216   struct timeval timeo;
217
218   addr = svc_getcaller(req->rq_xprt);
219   if ((cli = get_client(addr)))
220   {
221     timeo.tv_sec = 0;           /* No timeout - not expecting response  */
222     timeo.tv_usec = 0;
223
224     success = clnt_call(cli, opcode, xdr_nlm_res, result, xdr_void,
225       &dummy, timeo);
226
227     if (debug_level > 2) syslog(LOG_DEBUG, "clnt_call returns %d", success);
228   }
229 }
230
231 /* ------------------------------------------------------------------------- */
232 /*
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"
235    server.
236
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.
245
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.
252
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
255    for testing).
256 */
257
258
259 /* nlm_test ---------------------------------------------------------------- */
260 /*
261    Purpose:     Test whether a specified lock would be granted if requested
262    Returns:     nlm_granted (or error code)
263    Notes:
264 */
265
266 nlm_testres *
267 nlm_test_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
268 {
269   static nlm_testres res;
270   if (debug_level) log_from_addr("nlm_test", rqstp);
271
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;
279   return (&res);
280 }
281
282 nlm4_testres *
283 nlmproc4_test_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
284 {
285   static nlm4_testres res;
286   if (debug_level) log_from_addr("nlm_test", rqstp);
287
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;
295   return (&res);
296 }
297
298 void *
299 nlm_test_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
300 {
301   nlm_testres res;
302   static char dummy;
303   struct sockaddr_in *addr;
304   CLIENT *cli;
305   int success;
306   struct timeval timeo;
307
308   if (debug_level) log_from_addr("nlm_test_msg", rqstp);
309
310   res.cookie = arg->cookie;
311   res.stat.stat = nlm_granted;
312
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)))
317   {
318     timeo.tv_sec = 0;           /* No timeout - not expecting response  */
319     timeo.tv_usec = 0;
320
321     success = clnt_call(cli, NLM_TEST_RES, xdr_nlm_testres, &res, xdr_void,
322       &dummy, timeo);
323
324     if (debug_level > 2) syslog(LOG_DEBUG, "clnt_call returns %d", success);
325   }
326   return (NULL);
327 }
328
329 void *
330 nlmproc4_test_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
331 {
332   nlm4_testres res;
333   static char dummy;
334   struct sockaddr_in *addr;
335   CLIENT *cli;
336   int success;
337   struct timeval timeo;
338
339   if (debug_level) log_from_addr("nlm_test_msg", rqstp);
340
341   res.cookie = arg->cookie;
342   res.stat.stat = nlm4_granted;
343
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)))
348   {
349     timeo.tv_sec = 0;           /* No timeout - not expecting response  */
350     timeo.tv_usec = 0;
351
352     success = clnt_call(cli, NLMPROC4_TEST_RES, xdr_nlm_testres, &res, xdr_void,
353       &dummy, timeo);
354
355     if (debug_level > 2) syslog(LOG_DEBUG, "clnt_call returns %d", success);
356   }
357   return (NULL);
358 }
359
360
361
362 /* nlm_lock ---------------------------------------------------------------- */
363 /*
364    Purposes:    Establish a lock
365    Returns:     granted, denied or blocked
366    Notes:       *** grace period support missing
367 */
368
369 nlm_res *
370 nlm_lock_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
371 {
372   static nlm_res res;
373   if (debug_level) log_from_addr("nlm_lock", rqstp);
374
375   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
376   res.cookie = arg->cookie;
377
378   res.stat.stat = nlm_granted;
379   return (&res);
380 }
381
382 nlm4_res *
383 nlmproc4_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
384 {
385   static nlm4_res res;
386
387   if (debug_level) log_from_addr("nlm_lock", rqstp);
388
389   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
390   res.cookie = arg->cookie;
391
392   res.stat.stat = nlm4_granted;
393   return (&res);
394 }
395
396 void *
397 nlm_lock_msg_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
398 {
399   static nlm_res res;
400
401   if (debug_level) log_from_addr("nlm_lock_msg", rqstp);
402
403   res.cookie = arg->cookie;
404   res.stat.stat = nlm_granted;
405   transmit_result(NLM_LOCK_RES, &res, rqstp);
406
407   return (NULL);
408 }
409
410 void *
411 nlmproc4_lock_msg_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
412 {
413   static nlm4_res res;
414
415   if (debug_level) log_from_addr("nlm_lock_msg", rqstp);
416
417   res.cookie = arg->cookie;
418   res.stat.stat = nlm4_granted;
419   transmit_result(NLMPROC4_LOCK_RES, &res, rqstp);
420
421   return (NULL);
422 }
423
424
425 /* nlm_cancel -------------------------------------------------------------- */
426 /*
427    Purpose:     Cancel a blocked lock request
428    Returns:     granted or denied
429    Notes:
430 */
431
432 nlm_res *
433 nlm_cancel_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
434 {
435   static nlm_res res;
436   if (debug_level) log_from_addr("nlm_cancel", rqstp);
437
438   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
439   res.cookie = arg->cookie;
440
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;
444   return (&res);
445 }
446
447 nlm4_res *
448 nlmproc4_cancel_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
449 {
450   static nlm4_res res;
451   if (debug_level) log_from_addr("nlm_cancel", rqstp);
452
453   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
454   res.cookie = arg->cookie;
455
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;
459   return (&res);
460 }
461
462 void *
463 nlm_cancel_msg_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
464 {
465   static nlm_res res;
466   if (debug_level) log_from_addr("nlm_cancel_msg", rqstp);
467
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);
473   return (NULL);
474 }
475
476 void *
477 nlmproc4_cancel_msg_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
478 {
479   static nlm4_res res;
480   if (debug_level) log_from_addr("nlm_cancel_msg", rqstp);
481
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);
487   return (NULL);
488 }
489
490 /* nlm_unlock -------------------------------------------------------------- */
491 /*
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.
497 */
498
499 nlm_res *
500 nlm_unlock_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
501 {
502   static nlm_res res;
503   if (debug_level) log_from_addr("nlm_unlock", rqstp);
504
505   res.stat.stat= nlm_granted;
506   res.cookie = arg->cookie;
507
508   return (&res);
509 }
510
511 nlm4_res *
512 nlmproc4_unlock_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
513 {
514   static nlm4_res res;
515   if (debug_level) log_from_addr("nlm_unlock", rqstp);
516
517   res.stat.stat= nlm4_granted;
518   res.cookie = arg->cookie;
519
520   return (&res);
521 }
522
523 void *
524 nlm_unlock_msg_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
525 {
526   static nlm_res res;
527   if (debug_level) log_from_addr("nlm_unlock_msg", rqstp);
528
529   res.stat.stat = nlm_granted;
530   res.cookie = arg->cookie;
531
532   transmit_result(NLM_UNLOCK_RES, &res, rqstp);
533   return (NULL);
534 }
535
536 void *
537 nlmproc4_unlock_msg_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
538 {
539   static nlm4_res res;
540   if (debug_level) log_from_addr("nlm_unlock_msg", rqstp);
541
542   res.stat.stat = nlm4_granted;
543   res.cookie = arg->cookie;
544
545   transmit_result(NLMPROC4_UNLOCK_RES, &res, rqstp);
546   return (NULL);
547 }
548
549 /* ------------------------------------------------------------------------- */
550 /*
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.
555
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
558    call terms.
559 */
560
561 /* nlm_granted ------------------------------------------------------------- */
562 /*
563    Purpose:     Receive notification that formerly blocked lock now granted
564    Returns:     always success ('granted')
565    Notes:       
566 */
567
568 nlm_res *
569 nlm_granted_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
570 {
571   static nlm_res res;
572   if (debug_level) log_from_addr("nlm_granted", rqstp);
573
574   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
575   res.cookie = arg->cookie;
576
577   res.stat.stat = nlm_granted;
578   return (&res);
579 }
580
581 nlm4_res *
582 nlmproc4_granted_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
583 {
584   static nlm4_res res;
585   if (debug_level) log_from_addr("nlm_granted", rqstp);
586
587   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
588   res.cookie = arg->cookie;
589
590   res.stat.stat = nlm4_granted;
591   return (&res);
592 }
593
594 void *
595 nlm_granted_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
596 {
597   nlm_res res;
598   if (debug_level) log_from_addr("nlm_granted_msg", rqstp);
599
600   res.cookie = arg->cookie;
601   res.stat.stat = nlm_granted;
602   transmit_result(NLM_GRANTED_RES, &res, rqstp);
603   return (NULL);
604 }
605
606 void *
607 nlmproc4_granted_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
608 {
609   nlm4_res res;
610   if (debug_level) log_from_addr("nlm_granted_msg", rqstp);
611
612   res.cookie = arg->cookie;
613   res.stat.stat = nlm4_granted;
614   transmit_result(NLMPROC4_GRANTED_RES, &res, rqstp);
615   return (NULL);
616 }
617
618 /* nlm_test_res ------------------------------------------------------------ */
619 /*
620    Purpose:     Accept result from earlier nlm_test_msg() call
621    Returns:     Nothing
622 */
623
624 void *
625 nlm_test_res_1_svc(nlm_testres *arg, struct svc_req *rqstp)
626 {
627   if (debug_level) log_from_addr("nlm_test_res", rqstp);
628   return (NULL);
629 }
630
631 void *
632 nlmproc4_test_res_4_svc(nlm4_testres *arg, struct svc_req *rqstp)
633 {
634   if (debug_level) log_from_addr("nlm_test_res", rqstp);
635   return (NULL);
636 }
637
638 /* nlm_lock_res ------------------------------------------------------------ */
639 /*
640    Purpose:     Accept result from earlier nlm_lock_msg() call
641    Returns:     Nothing
642 */
643
644 void *
645 nlm_lock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
646 {
647   if (debug_level) log_from_addr("nlm_lock_res", rqstp);
648
649   return (NULL);
650 }
651
652 void *
653 nlmproc4_lock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
654 {
655   if (debug_level) log_from_addr("nlm_lock_res", rqstp);
656
657   return (NULL);
658 }
659
660 /* nlm_cancel_res ---------------------------------------------------------- */
661 /*
662    Purpose:     Accept result from earlier nlm_cancel_msg() call
663    Returns:     Nothing
664 */
665
666 void *
667 nlm_cancel_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
668 {
669   if (debug_level) log_from_addr("nlm_cancel_res", rqstp);
670   return (NULL);
671 }
672
673 void *
674 nlmproc4_cancel_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
675 {
676   if (debug_level) log_from_addr("nlm_cancel_res", rqstp);
677   return (NULL);
678 }
679
680 /* nlm_unlock_res ---------------------------------------------------------- */
681 /*
682    Purpose:     Accept result from earlier nlm_unlock_msg() call
683    Returns:     Nothing
684 */
685
686 void *
687 nlm_unlock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
688 {
689   if (debug_level) log_from_addr("nlm_unlock_res", rqstp);
690   return (NULL);
691 }
692
693 void *
694 nlmproc4_unlock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
695 {
696   if (debug_level) log_from_addr("nlm_unlock_res", rqstp);
697   return (NULL);
698 }
699
700 /* nlm_granted_res --------------------------------------------------------- */
701 /*
702    Purpose:     Accept result from earlier nlm_granted_msg() call
703    Returns:     Nothing
704 */
705
706 void *
707 nlm_granted_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
708 {
709   if (debug_level) log_from_addr("nlm_granted_res", rqstp);
710   return (NULL);
711 }
712
713 void *
714 nlmproc4_granted_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
715 {
716   if (debug_level) log_from_addr("nlm_granted_res", rqstp);
717   return (NULL);
718 }
719
720 /* ------------------------------------------------------------------------- */
721 /*
722    Calls for PCNFS locking (aka non-monitored locking, no involvement
723    of rpc.statd).
724
725    These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
726 */
727
728
729 /* nlm_share --------------------------------------------------------------- */
730 /*
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.
735 */
736
737 nlm_shareres *
738 nlm_share_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
739 {
740   static nlm_shareres res;
741   if (debug_level) log_from_addr("nlm_share", rqstp);
742
743   res.cookie = arg->cookie;
744   res.stat = nlm_granted;
745   res.sequence = 1234356;       /* X/Open says this field is ignored?   */
746   return (&res);
747 }
748
749 nlm4_shareres *
750 nlmproc4_share_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
751 {
752   static nlm4_shareres res;
753   if (debug_level) log_from_addr("nlm_share", rqstp);
754
755   res.cookie = arg->cookie;
756   res.stat = nlm4_granted;
757   res.sequence = 1234356;       /* X/Open says this field is ignored?   */
758   return (&res);
759 }
760
761 /* nlm_unshare ------------------------------------------------------------ */
762 /*
763    Purpose:     Release a DOS-style lock
764    Returns:     nlm_granted, unless in grace period
765    Notes:
766 */
767
768 nlm_shareres *
769 nlm_unshare_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
770 {
771   static nlm_shareres res;
772   if (debug_level) log_from_addr("nlm_unshare", rqstp);
773
774   res.cookie = arg->cookie;
775   res.stat = nlm_granted;
776   res.sequence = 1234356;       /* X/Open says this field is ignored?   */
777   return (&res);
778 }
779
780 nlm4_shareres *
781 nlmproc4_unshare_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
782 {
783   static nlm4_shareres res;
784   if (debug_level) log_from_addr("nlm_unshare", rqstp);
785
786   res.cookie = arg->cookie;
787   res.stat = nlm4_granted;
788   res.sequence = 1234356;       /* X/Open says this field is ignored?   */
789   return (&res);
790 }
791
792 /* nlm_nm_lock ------------------------------------------------------------ */
793 /*
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.
801 */
802
803 nlm_res *
804 nlm_nm_lock_3_svc(nlm_lockargs *arg, struct svc_req *rqstp)
805 {
806   static nlm_res res;
807   if (debug_level) log_from_addr("nlm_nm_lock", rqstp);
808
809   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
810   res.cookie = arg->cookie;
811   res.stat.stat = nlm_granted;
812   return (&res);
813 }
814
815 nlm4_res *
816 nlmproc4_nm_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
817 {
818   static nlm4_res res;
819   if (debug_level) log_from_addr("nlm_nm_lock", rqstp);
820
821   /* copy cookie from arg to result.  See comment in nlm_test_1()       */
822   res.cookie = arg->cookie;
823   res.stat.stat = nlm4_granted;
824   return (&res);
825 }
826
827 /* nlm_free_all ------------------------------------------------------------ */
828 /*
829    Purpose:     Release all locks held by a named client
830    Returns:     Nothing
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.
836 */
837
838 void *
839 nlm_free_all_3_svc(nlm_notify *arg, struct svc_req *rqstp)
840 {
841   static char dummy;
842
843   if (debug_level) log_from_addr("nlm_free_all", rqstp);
844   return (&dummy);
845 }
846
847 void *
848 nlmproc4_free_all_4_svc(nlm4_notify *arg, struct svc_req *rqstp)
849 {
850   static char dummy;
851
852   if (debug_level) log_from_addr("nlm_free_all", rqstp);
853   return (&dummy);
854 }
855
856 void *
857 nlmproc4_null_4_svc(void *arg, struct svc_req *rqstp)
858 {
859   static char dummy;
860
861   if (debug_level) log_from_addr("nlm_free_all", rqstp);
862   return (&dummy);
863 }
864
865