Merge branch 'vendor/OPENSSH'
[dragonfly.git] / usr.sbin / rpc.lockd / lock_proc.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  * $NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $
33  * $FreeBSD: src/usr.sbin/rpc.lockd/lock_proc.c,v 1.1 2001/03/19 12:50:09 alfred Exp $
34  */
35
36 #include <sys/param.h>
37 #include <sys/socket.h>
38
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41
42 #include <netdb.h>
43 #include <stdio.h>
44 #include <string.h>
45 #include <syslog.h>
46 #include <unistd.h>
47 #include <netconfig.h>
48
49 #include <rpc/rpc.h>
50 #include <rpcsvc/sm_inter.h>
51
52 #include "lockd.h"
53 #include <rpcsvc/nlm_prot.h>
54 #include "lockd_lock.h"
55
56
57 #define CLIENT_CACHE_SIZE       64      /* No. of client sockets cached */
58 #define CLIENT_CACHE_LIFETIME   120     /* In seconds */
59
60 #define getrpcaddr(rqstp)       (struct sockaddr *)(svc_getrpccaller((rqstp)->rq_xprt)->buf)
61
62 static void     log_from_addr(const char *, struct svc_req *);
63 static int      addrcmp(struct sockaddr *, struct sockaddr *);
64
65 /* log_from_addr ----------------------------------------------------------- */
66 /*
67  * Purpose:     Log name of function called and source address
68  * Returns:     Nothing
69  * Notes:       Extracts the source address from the transport handle
70  *              passed in as part of the called procedure specification
71  */
72 static void
73 log_from_addr(const char *fun_name, struct svc_req *req)
74 {
75         struct sockaddr *addr;
76         char hostname_buf[NI_MAXHOST];
77
78         addr = svc_getrpccaller(req->rq_xprt)->buf;
79         if (getnameinfo(addr , addr->sa_len, hostname_buf, sizeof hostname_buf,
80             NULL, 0, 0) != 0)
81                 return;
82
83         syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf);
84 }
85
86 /* get_client -------------------------------------------------------------- */
87 /*
88  * Purpose:     Get a CLIENT* for making RPC calls to lockd on given host
89  * Returns:     CLIENT* pointer, from clnt_udp_create, or NULL if error
90  * Notes:       Creating a CLIENT* is quite expensive, involving a
91  *              conversation with the remote portmapper to get the
92  *              port number.  Since a given client is quite likely
93  *              to make several locking requests in succession, it is
94  *              desirable to cache the created CLIENT*.
95  *
96  *              Since we are using UDP rather than TCP, there is no cost
97  *              to the remote system in keeping these cached indefinitely.
98  *              Unfortunately there is a snag: if the remote system
99  *              reboots, the cached portmapper results will be invalid,
100  *              and we will never detect this since all of the xxx_msg()
101  *              calls return no result - we just fire off a udp packet
102  *              and hope for the best.
103  *
104  *              We solve this by discarding cached values after two
105  *              minutes, regardless of whether they have been used
106  *              in the meanwhile (since a bad one might have been used
107  *              plenty of times, as the host keeps retrying the request
108  *              and we keep sending the reply back to the wrong port).
109  *
110  *              Given that the entries will always expire in the order
111  *              that they were created, there is no point in a LRU
112  *              algorithm for when the cache gets full - entries are
113  *              always re-used in sequence.
114  */
115 static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE];
116 static long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */
117 static struct sockaddr_storage clnt_cache_addr[CLIENT_CACHE_SIZE];
118 static rpcvers_t clnt_cache_vers[CLIENT_CACHE_SIZE];
119 static int clnt_cache_next_to_use = 0;
120
121 static int
122 addrcmp(struct sockaddr *sa1, struct sockaddr *sa2)
123 {
124         int len;
125         void *p1, *p2;
126
127         if (sa1->sa_family != sa2->sa_family)
128                 return -1;
129
130         switch (sa1->sa_family) {
131         case AF_INET:
132                 p1 = &((struct sockaddr_in *)sa1)->sin_addr;
133                 p2 = &((struct sockaddr_in *)sa2)->sin_addr;
134                 len = 4;
135                 break;
136         case AF_INET6:
137                 p1 = &((struct sockaddr_in6 *)sa1)->sin6_addr;
138                 p2 = &((struct sockaddr_in6 *)sa2)->sin6_addr;
139                 len = 16;
140                 break;
141         default:
142                 return -1;
143         }
144
145         return memcmp(p1, p2, len);
146 }
147
148 CLIENT *
149 get_client(struct sockaddr *host_addr, rpcvers_t vers)
150 {
151         CLIENT *client;
152         struct timeval retry_time, time_now;
153         int error, i;
154         const char *netid;
155         struct netconfig *nconf;
156         char host[NI_MAXHOST];
157         uid_t old_euid;
158         int clnt_fd;
159
160         gettimeofday(&time_now, NULL);
161
162         /*
163          * Search for the given client in the cache, zapping any expired
164          * entries that we happen to notice in passing.
165          */
166         for (i = 0; i < CLIENT_CACHE_SIZE; i++) {
167                 client = clnt_cache_ptr[i];
168                 if (client && ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME)
169                     < time_now.tv_sec)) {
170                         /* Cache entry has expired. */
171                         if (debug_level > 3)
172                                 syslog(LOG_DEBUG, "Expired CLIENT* in cache");
173                         clnt_cache_time[i] = 0L;
174                         clnt_destroy(client);
175                         clnt_cache_ptr[i] = NULL;
176                         client = NULL;
177                 }
178                 if (client && !addrcmp((struct sockaddr *)&clnt_cache_addr[i],
179                     host_addr) && clnt_cache_vers[i] == vers) {
180                         /* Found it! */
181                         if (debug_level > 3)
182                                 syslog(LOG_DEBUG, "Found CLIENT* in cache");
183                         return (client);
184                 }
185         }
186
187         if (debug_level > 3)
188                 syslog(LOG_DEBUG, "CLIENT* not found in cache, creating");
189
190         /* Not found in cache.  Free the next entry if it is in use. */
191         if (clnt_cache_ptr[clnt_cache_next_to_use]) {
192                 clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]);
193                 clnt_cache_ptr[clnt_cache_next_to_use] = NULL;
194         }
195
196         /*
197          * Need a host string for clnt_tp_create. Use NI_NUMERICHOST
198          * to avoid DNS lookups.
199          */
200         error = getnameinfo(host_addr, host_addr->sa_len, host, sizeof host,
201                             NULL, 0, NI_NUMERICHOST);
202         if (error != 0) {
203                 syslog(LOG_ERR, "unable to get name string for caller: %s",
204                        gai_strerror(error));
205                 return NULL;
206         }
207
208 #if 1
209         if (host_addr->sa_family == AF_INET6)
210                 netid = "udp6";
211         else
212                 netid = "udp";
213 #else
214         if (host_addr->sa_family == AF_INET6)
215                 netid = "tcp6";
216         else
217                 netid = "tcp";
218 #endif
219         nconf = getnetconfigent(netid);
220         if (nconf == NULL) {
221                 syslog(LOG_ERR, "could not get netconfig info for '%s': "
222                                 "no /etc/netconfig file?", netid);
223                 return NULL;
224         }
225
226         client = clnt_tp_create(host, NLM_PROG, vers, nconf);
227         freenetconfigent(nconf);
228
229         if (!client) {
230                 syslog(LOG_ERR, "%s", clnt_spcreateerror("clntudp_create"));
231                 syslog(LOG_ERR, "Unable to return result to %s", host);
232                 return NULL;
233         }
234
235         /* Get the FD of the client, for bindresvport. */
236         clnt_control(client, CLGET_FD, &clnt_fd);
237
238         /* Regain root privileges, for bindresvport. */
239         old_euid = geteuid();
240         seteuid(0);
241
242         /*
243          * Bind the client FD to a reserved port.
244          * Some NFS servers reject any NLM request from a non-reserved port.
245          */
246         bindresvport(clnt_fd, NULL);
247
248         /* Drop root privileges again. */
249         seteuid(old_euid);
250
251         /* Success - update the cache entry */
252         clnt_cache_ptr[clnt_cache_next_to_use] = client;
253         memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr,
254             host_addr->sa_len);
255         clnt_cache_vers[clnt_cache_next_to_use] = vers;
256         clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec;
257         if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE)
258                 clnt_cache_next_to_use = 0;
259
260         /*
261          * Disable the default timeout, so we can specify our own in calls
262          * to clnt_call().  (Note that the timeout is a different concept
263          * from the retry period set in clnt_udp_create() above.)
264          */
265         retry_time.tv_sec = -1;
266         retry_time.tv_usec = -1;
267         clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time);
268
269         if (debug_level > 3)
270                 syslog(LOG_DEBUG, "Created CLIENT* for %s", host);
271         return client;
272 }
273
274
275 /* transmit_result --------------------------------------------------------- */
276 /*
277  * Purpose:     Transmit result for nlm_xxx_msg pseudo-RPCs
278  * Returns:     Nothing - we have no idea if the datagram got there
279  * Notes:       clnt_call() will always fail (with timeout) as we are
280  *              calling it with timeout 0 as a hack to just issue a datagram
281  *              without expecting a result
282  */
283 void
284 transmit_result(int opcode, nlm_res *result, struct sockaddr *addr)
285 {
286         static char dummy;
287         CLIENT *cli;
288         struct timeval timeo;
289         int success;
290
291         if ((cli = get_client(addr, NLM_VERS)) != NULL) {
292                 timeo.tv_sec = 0; /* No timeout - not expecting response */
293                 timeo.tv_usec = 0;
294
295                 success = clnt_call(cli, opcode, (xdrproc_t)xdr_nlm_res, result,
296                     (xdrproc_t)xdr_void, &dummy, timeo);
297
298                 if (debug_level > 2)
299                         syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
300                             success, clnt_sperrno(success));
301         }
302 }
303 /* transmit4_result --------------------------------------------------------- */
304 /*
305  * Purpose:     Transmit result for nlm4_xxx_msg pseudo-RPCs
306  * Returns:     Nothing - we have no idea if the datagram got there
307  * Notes:       clnt_call() will always fail (with timeout) as we are
308  *              calling it with timeout 0 as a hack to just issue a datagram
309  *              without expecting a result
310  */
311 void
312 transmit4_result(int opcode, nlm4_res *result, struct sockaddr *addr)
313 {
314         static char dummy;
315         CLIENT *cli;
316         struct timeval timeo;
317         int success;
318
319         if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
320                 timeo.tv_sec = 0; /* No timeout - not expecting response */
321                 timeo.tv_usec = 0;
322
323                 success = clnt_call(cli, opcode,
324                     (xdrproc_t)xdr_nlm4_res, result,
325                     (xdrproc_t)xdr_void, &dummy, timeo);
326
327                 if (debug_level > 2)
328                         syslog(LOG_DEBUG, "clnt_call returns %d(%s)",
329                             success, clnt_sperrno(success));
330         }
331 }
332
333 /*
334  * converts a struct nlm_lock to struct nlm4_lock
335  */
336 static void nlmtonlm4(struct nlm_lock *, struct nlm4_lock *);
337 static void
338 nlmtonlm4(struct nlm_lock *arg, struct nlm4_lock *arg4)
339 {
340         arg4->caller_name = arg->caller_name;
341         arg4->fh = arg->fh;
342         arg4->oh = arg->oh;
343         arg4->svid = arg->svid;
344         arg4->l_offset = arg->l_offset;
345         arg4->l_len = arg->l_len;
346 }
347 /* ------------------------------------------------------------------------- */
348 /*
349  * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd
350  * involved to ensure reclaim of locks after a crash of the "stateless"
351  * server.
352  *
353  * These all come in two flavours - nlm_xxx() and nlm_xxx_msg().
354  * The first are standard RPCs with argument and result.
355  * The nlm_xxx_msg() calls implement exactly the same functions, but
356  * use two pseudo-RPCs (one in each direction).  These calls are NOT
357  * standard use of the RPC protocol in that they do not return a result
358  * at all (NB. this is quite different from returning a void result).
359  * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged
360  * datagrams, requiring higher-level code to perform retries.
361  *
362  * Despite the disadvantages of the nlm_xxx_msg() approach (some of which
363  * are documented in the comments to get_client() above), this is the
364  * interface used by all current commercial NFS implementations
365  * [Solaris, SCO, AIX etc.].  This is presumed to be because these allow
366  * implementations to continue using the standard RPC libraries, while
367  * avoiding the block-until-result nature of the library interface.
368  *
369  * No client implementations have been identified so far that make use
370  * of the true RPC version (early SunOS releases would be a likely candidate
371  * for testing).
372  */
373
374 /* nlm_test ---------------------------------------------------------------- */
375 /*
376  * Purpose:     Test whether a specified lock would be granted if requested
377  * Returns:     nlm_granted (or error code)
378  * Notes:
379  */
380 nlm_testres *
381 nlm_test_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
382 {
383         static nlm_testres res;
384         struct nlm4_lock arg4;
385         struct nlm4_holder *holder;
386         nlmtonlm4(&arg->alock, &arg4);
387
388         if (debug_level)
389                 log_from_addr("nlm_test", rqstp);
390
391         holder = testlock(&arg4, 0);
392         /*
393          * Copy the cookie from the argument into the result.  Note that this
394          * is slightly hazardous, as the structure contains a pointer to a
395          * malloc()ed buffer that will get freed by the caller.  However, the
396          * main function transmits the result before freeing the argument
397          * so it is in fact safe.
398          */
399         res.cookie = arg->cookie;
400         if (holder == NULL) {
401                 res.stat.stat = nlm_granted;
402         } else {
403                 res.stat.stat = nlm_denied;
404                 memcpy(&res.stat.nlm_testrply_u.holder, holder,
405                     sizeof(struct nlm_holder));
406                 res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
407                 res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
408         }
409         return (&res);
410 }
411
412 void *
413 nlm_test_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
414 {
415         nlm_testres res;
416         static char dummy;
417         struct sockaddr *addr;
418         CLIENT *cli;
419         int success;
420         struct timeval timeo;
421         struct nlm4_lock arg4;
422         struct nlm4_holder *holder;
423
424         nlmtonlm4(&arg->alock, &arg4);
425
426         if (debug_level)
427                 log_from_addr("nlm_test_msg", rqstp);
428
429         holder = testlock(&arg4, 0);
430
431         res.cookie = arg->cookie;
432         if (holder == NULL) {
433                 res.stat.stat = nlm_granted;
434         } else {
435                 res.stat.stat = nlm_denied;
436                 memcpy(&res.stat.nlm_testrply_u.holder, holder,
437                     sizeof(struct nlm_holder));
438                 res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset;
439                 res.stat.nlm_testrply_u.holder.l_len = holder->l_len;
440         }
441
442         /*
443          * nlm_test has different result type to the other operations, so
444          * can't use transmit_result() in this case
445          */
446         addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
447         if ((cli = get_client(addr, NLM_VERS)) != NULL) {
448                 timeo.tv_sec = 0; /* No timeout - not expecting response */
449                 timeo.tv_usec = 0;
450
451                 success = clnt_call(cli, NLM_TEST_RES,
452                     (xdrproc_t)xdr_nlm_testres, &res,
453                     (xdrproc_t)xdr_void, &dummy, timeo);
454
455                 if (debug_level > 2)
456                         syslog(LOG_DEBUG, "clnt_call returns %d", success);
457         }
458         return (NULL);
459 }
460
461 /* nlm_lock ---------------------------------------------------------------- */
462 /*
463  * Purposes:    Establish a lock
464  * Returns:     granted, denied or blocked
465  * Notes:       *** grace period support missing
466  */
467 nlm_res *
468 nlm_lock_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
469 {
470         static nlm_res res;
471         struct nlm4_lockargs arg4;
472         nlmtonlm4(&arg->alock, &arg4.alock);
473         arg4.cookie = arg->cookie;
474         arg4.block = arg->block;
475         arg4.exclusive = arg->exclusive;
476         arg4.reclaim = arg->reclaim;
477         arg4.state = arg->state;
478
479         if (debug_level)
480                 log_from_addr("nlm_lock", rqstp);
481
482         /* copy cookie from arg to result.  See comment in nlm_test_1() */
483         res.cookie = arg->cookie;
484
485         res.stat.stat = getlock(&arg4, rqstp, LOCK_MON);
486         return (&res);
487 }
488
489 void *
490 nlm_lock_msg_1_svc(nlm_lockargs *arg, struct svc_req *rqstp)
491 {
492         static nlm_res res;
493         struct nlm4_lockargs arg4;
494
495         nlmtonlm4(&arg->alock, &arg4.alock);
496         arg4.cookie = arg->cookie;
497         arg4.block = arg->block;
498         arg4.exclusive = arg->exclusive;
499         arg4.reclaim = arg->reclaim;
500         arg4.state = arg->state;
501
502         if (debug_level)
503                 log_from_addr("nlm_lock_msg", rqstp);
504
505         res.cookie = arg->cookie;
506         res.stat.stat = getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON);
507         transmit_result(NLM_LOCK_RES, &res, getrpcaddr(rqstp));
508
509         return (NULL);
510 }
511
512 /* nlm_cancel -------------------------------------------------------------- */
513 /*
514  * Purpose:     Cancel a blocked lock request
515  * Returns:     granted or denied
516  * Notes:
517  */
518 nlm_res *
519 nlm_cancel_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
520 {
521         static nlm_res res;
522         struct nlm4_lock arg4;
523
524         nlmtonlm4(&arg->alock, &arg4);
525
526         if (debug_level)
527                 log_from_addr("nlm_cancel", rqstp);
528
529         /* copy cookie from arg to result.  See comment in nlm_test_1() */
530         res.cookie = arg->cookie;
531
532         /*
533          * Since at present we never return 'nlm_blocked', there can never be
534          * a lock to cancel, so this call always fails.
535          */
536         res.stat.stat = unlock(&arg4, LOCK_CANCEL);
537         return (&res);
538 }
539
540 void *
541 nlm_cancel_msg_1_svc(nlm_cancargs *arg, struct svc_req *rqstp)
542 {
543         static nlm_res res;
544         struct nlm4_lock arg4;
545
546         nlmtonlm4(&arg->alock, &arg4);
547
548         if (debug_level)
549                 log_from_addr("nlm_cancel_msg", rqstp);
550
551         res.cookie = arg->cookie;
552         /*
553          * Since at present we never return 'nlm_blocked', there can never be
554          * a lock to cancel, so this call always fails.
555          */
556         res.stat.stat = unlock(&arg4, LOCK_CANCEL);
557         transmit_result(NLM_CANCEL_RES, &res, getrpcaddr(rqstp));
558         return (NULL);
559 }
560
561 /* nlm_unlock -------------------------------------------------------------- */
562 /*
563  * Purpose:     Release an existing lock
564  * Returns:     Always granted, unless during grace period
565  * Notes:       "no such lock" error condition is ignored, as the
566  *              protocol uses unreliable UDP datagrams, and may well
567  *              re-try an unlock that has already succeeded.
568  */
569 nlm_res *
570 nlm_unlock_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
571 {
572         static nlm_res res;
573         struct nlm4_lock arg4;
574
575         nlmtonlm4(&arg->alock, &arg4);
576
577         if (debug_level)
578                 log_from_addr("nlm_unlock", rqstp);
579
580         res.stat.stat = unlock(&arg4, 0);
581         res.cookie = arg->cookie;
582
583         return (&res);
584 }
585
586 void *
587 nlm_unlock_msg_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp)
588 {
589         static nlm_res res;
590         struct nlm4_lock arg4;
591
592         nlmtonlm4(&arg->alock, &arg4);
593
594         if (debug_level)
595                 log_from_addr("nlm_unlock_msg", rqstp);
596
597         res.stat.stat = unlock(&arg4, 0);
598         res.cookie = arg->cookie;
599
600         transmit_result(NLM_UNLOCK_RES, &res, getrpcaddr(rqstp));
601         return (NULL);
602 }
603
604 /* ------------------------------------------------------------------------- */
605 /*
606  * Client-side pseudo-RPCs for results.  Note that for the client there
607  * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
608  * version returns the results in the RPC result, and so the client
609  * does not normally receive incoming RPCs.
610  *
611  * The exception to this is nlm_granted(), which is genuinely an RPC
612  * call from the server to the client - a 'call-back' in normal procedure
613  * call terms.
614  */
615
616 /* nlm_granted ------------------------------------------------------------- */
617 /*
618  * Purpose:     Receive notification that formerly blocked lock now granted
619  * Returns:     always success ('granted')
620  * Notes:
621  */
622 nlm_res *
623 nlm_granted_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
624 {
625         static nlm_res res;
626
627         if (debug_level)
628                 log_from_addr("nlm_granted", rqstp);
629
630         /* copy cookie from arg to result.  See comment in nlm_test_1() */
631         res.cookie = arg->cookie;
632
633         res.stat.stat = nlm_granted;
634         return (&res);
635 }
636
637 void *
638 nlm_granted_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp)
639 {
640         static nlm_res res;
641
642         if (debug_level)
643                 log_from_addr("nlm_granted_msg", rqstp);
644
645         res.cookie = arg->cookie;
646         res.stat.stat = nlm_granted;
647         transmit_result(NLM_GRANTED_RES, &res,
648             (struct sockaddr *)svc_getcaller(rqstp->rq_xprt));
649         return (NULL);
650 }
651
652 /* nlm_test_res ------------------------------------------------------------ */
653 /*
654  * Purpose:     Accept result from earlier nlm_test_msg() call
655  * Returns:     Nothing
656  */
657 void *
658 nlm_test_res_1_svc(nlm_testres *arg, struct svc_req *rqstp)
659 {
660         if (debug_level)
661                 log_from_addr("nlm_test_res", rqstp);
662         return (NULL);
663 }
664
665 /* nlm_lock_res ------------------------------------------------------------ */
666 /*
667  * Purpose:     Accept result from earlier nlm_lock_msg() call
668  * Returns:     Nothing
669  */
670 void *
671 nlm_lock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
672 {
673         if (debug_level)
674                 log_from_addr("nlm_lock_res", rqstp);
675
676         return (NULL);
677 }
678
679 /* nlm_cancel_res ---------------------------------------------------------- */
680 /*
681  * Purpose:     Accept result from earlier nlm_cancel_msg() call
682  * Returns:     Nothing
683  */
684 void *
685 nlm_cancel_res_1_svc(nlm_res *arg __unused, struct svc_req *rqstp)
686 {
687         if (debug_level)
688                 log_from_addr("nlm_cancel_res", rqstp);
689         return (NULL);
690 }
691
692 /* nlm_unlock_res ---------------------------------------------------------- */
693 /*
694  * Purpose:     Accept result from earlier nlm_unlock_msg() call
695  * Returns:     Nothing
696  */
697 void *
698 nlm_unlock_res_1_svc(nlm_res *arg, struct svc_req *rqstp)
699 {
700         if (debug_level)
701                 log_from_addr("nlm_unlock_res", rqstp);
702         return (NULL);
703 }
704
705 /* nlm_granted_res --------------------------------------------------------- */
706 /*
707  * Purpose:     Accept result from earlier nlm_granted_msg() call
708  * Returns:     Nothing
709  */
710 void *
711 nlm_granted_res_1_svc(nlm_res *arg __unused, struct svc_req *rqstp)
712 {
713         if (debug_level)
714                 log_from_addr("nlm_granted_res", rqstp);
715         return (NULL);
716 }
717
718 /* ------------------------------------------------------------------------- */
719 /*
720  * Calls for PCNFS locking (aka non-monitored locking, no involvement
721  * of rpc.statd).
722  *
723  * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
724  */
725
726 /* nlm_share --------------------------------------------------------------- */
727 /*
728  * Purpose:     Establish a DOS-style lock
729  * Returns:     success or failure
730  * Notes:       Blocking locks are not supported - client is expected
731  *              to retry if required.
732  */
733 nlm_shareres *
734 nlm_share_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
735 {
736         static nlm_shareres res;
737
738         if (debug_level)
739                 log_from_addr("nlm_share", rqstp);
740
741         res.cookie = arg->cookie;
742         res.stat = nlm_granted;
743         res.sequence = 1234356; /* X/Open says this field is ignored? */
744         return (&res);
745 }
746
747 /* nlm_unshare ------------------------------------------------------------ */
748 /*
749  * Purpose:     Release a DOS-style lock
750  * Returns:     nlm_granted, unless in grace period
751  * Notes:
752  */
753 nlm_shareres *
754 nlm_unshare_3_svc(nlm_shareargs *arg, struct svc_req *rqstp)
755 {
756         static nlm_shareres res;
757
758         if (debug_level)
759                 log_from_addr("nlm_unshare", rqstp);
760
761         res.cookie = arg->cookie;
762         res.stat = nlm_granted;
763         res.sequence = 1234356; /* X/Open says this field is ignored? */
764         return (&res);
765 }
766
767 /* nlm_nm_lock ------------------------------------------------------------ */
768 /*
769  * Purpose:     non-monitored version of nlm_lock()
770  * Returns:     as for nlm_lock()
771  * Notes:       These locks are in the same style as the standard nlm_lock,
772  *              but the rpc.statd should not be called to establish a
773  *              monitor for the client machine, since that machine is
774  *              declared not to be running a rpc.statd, and so would not
775  *              respond to the statd protocol.
776  */
777 nlm_res *
778 nlm_nm_lock_3_svc(nlm_lockargs *arg, struct svc_req *rqstp)
779 {
780         static nlm_res res;
781
782         if (debug_level)
783                 log_from_addr("nlm_nm_lock", rqstp);
784
785         /* copy cookie from arg to result.  See comment in nlm_test_1() */
786         res.cookie = arg->cookie;
787         res.stat.stat = nlm_granted;
788         return (&res);
789 }
790
791 /* nlm_free_all ------------------------------------------------------------ */
792 /*
793  * Purpose:     Release all locks held by a named client
794  * Returns:     Nothing
795  * Notes:       Potential denial of service security problem here - the
796  *              locks to be released are specified by a host name, independent
797  *              of the address from which the request has arrived.
798  *              Should probably be rejected if the named host has been
799  *              using monitored locks.
800  */
801 void *
802 nlm_free_all_3_svc(nlm_notify *arg __unused, struct svc_req *rqstp)
803 {
804         static char dummy;
805
806         if (debug_level)
807                 log_from_addr("nlm_free_all", rqstp);
808         return (&dummy);
809 }
810
811 /* calls for nlm version 4 (NFSv3) */
812 /* nlm_test ---------------------------------------------------------------- */
813 /*
814  * Purpose:     Test whether a specified lock would be granted if requested
815  * Returns:     nlm_granted (or error code)
816  * Notes:
817  */
818 nlm4_testres *
819 nlm4_test_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
820 {
821         static nlm4_testres res;
822         struct nlm4_holder *holder;
823
824         if (debug_level)
825                 log_from_addr("nlm4_test", rqstp);
826
827         holder = testlock(&arg->alock, LOCK_V4);
828
829         /*
830          * Copy the cookie from the argument into the result.  Note that this
831          * is slightly hazardous, as the structure contains a pointer to a
832          * malloc()ed buffer that will get freed by the caller.  However, the
833          * main function transmits the result before freeing the argument
834          * so it is in fact safe.
835          */
836         res.cookie = arg->cookie;
837         if (holder == NULL) {
838                 res.stat.stat = nlm4_granted;
839         } else {
840                 res.stat.stat = nlm4_denied;
841                 memcpy(&res.stat.nlm4_testrply_u.holder, holder,
842                     sizeof(struct nlm4_holder));
843         }
844         return (&res);
845 }
846
847 void *
848 nlm4_test_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
849 {
850         nlm4_testres res;
851         static char dummy;
852         struct sockaddr *addr;
853         CLIENT *cli;
854         int success;
855         struct timeval timeo;
856         struct nlm4_holder *holder;
857
858         if (debug_level)
859                 log_from_addr("nlm4_test_msg", rqstp);
860
861         holder = testlock(&arg->alock, LOCK_V4);
862
863         res.cookie = arg->cookie;
864         if (holder == NULL) {
865                 res.stat.stat = nlm4_granted;
866         } else {
867                 res.stat.stat = nlm4_denied;
868                 memcpy(&res.stat.nlm4_testrply_u.holder, holder,
869                     sizeof(struct nlm4_holder));
870         }
871
872         /*
873          * nlm_test has different result type to the other operations, so
874          * can't use transmit4_result() in this case
875          */
876         addr = svc_getrpccaller(rqstp->rq_xprt)->buf;
877         if ((cli = get_client(addr, NLM_VERS4)) != NULL) {
878                 timeo.tv_sec = 0; /* No timeout - not expecting response */
879                 timeo.tv_usec = 0;
880
881                 success = clnt_call(cli, NLM4_TEST_RES,
882                     (xdrproc_t)xdr_nlm4_testres, &res,
883                     (xdrproc_t)xdr_void, &dummy, timeo);
884
885                 if (debug_level > 2)
886                         syslog(LOG_DEBUG, "clnt_call returns %d", success);
887         }
888         return (NULL);
889 }
890
891 /* nlm_lock ---------------------------------------------------------------- */
892 /*
893  * Purposes:    Establish a lock
894  * Returns:     granted, denied or blocked
895  * Notes:       *** grace period support missing
896  */
897 nlm4_res *
898 nlm4_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
899 {
900         static nlm4_res res;
901
902         if (debug_level)
903                 log_from_addr("nlm4_lock", rqstp);
904
905         /* copy cookie from arg to result.  See comment in nlm_test_4() */
906         res.cookie = arg->cookie;
907
908         res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_V4);
909         return (&res);
910 }
911
912 void *
913 nlm4_lock_msg_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
914 {
915         static nlm4_res res;
916
917         if (debug_level)
918                 log_from_addr("nlm4_lock_msg", rqstp);
919
920         res.cookie = arg->cookie;
921         res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_ASYNC | LOCK_V4);
922         transmit4_result(NLM4_LOCK_RES, &res, getrpcaddr(rqstp));
923
924         return (NULL);
925 }
926
927 /* nlm_cancel -------------------------------------------------------------- */
928 /*
929  * Purpose:     Cancel a blocked lock request
930  * Returns:     granted or denied
931  * Notes:
932  */
933 nlm4_res *
934 nlm4_cancel_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
935 {
936         static nlm4_res res;
937
938         if (debug_level)
939                 log_from_addr("nlm4_cancel", rqstp);
940
941         /* copy cookie from arg to result.  See comment in nlm_test_1() */
942         res.cookie = arg->cookie;
943
944         /*
945          * Since at present we never return 'nlm_blocked', there can never be
946          * a lock to cancel, so this call always fails.
947          */
948         res.stat.stat = unlock(&arg->alock, LOCK_CANCEL);
949         return (&res);
950 }
951
952 void *
953 nlm4_cancel_msg_4_svc(nlm4_cancargs *arg, struct svc_req *rqstp)
954 {
955         static nlm4_res res;
956
957         if (debug_level)
958                 log_from_addr("nlm4_cancel_msg", rqstp);
959
960         res.cookie = arg->cookie;
961         /*
962          * Since at present we never return 'nlm_blocked', there can never be
963          * a lock to cancel, so this call always fails.
964          */
965         res.stat.stat = unlock(&arg->alock, LOCK_CANCEL | LOCK_V4);
966         transmit4_result(NLM4_CANCEL_RES, &res, getrpcaddr(rqstp));
967         return (NULL);
968 }
969
970 /* nlm_unlock -------------------------------------------------------------- */
971 /*
972  * Purpose:     Release an existing lock
973  * Returns:     Always granted, unless during grace period
974  * Notes:       "no such lock" error condition is ignored, as the
975  *              protocol uses unreliable UDP datagrams, and may well
976  *              re-try an unlock that has already succeeded.
977  */
978 nlm4_res *
979 nlm4_unlock_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
980 {
981         static nlm4_res res;
982
983         if (debug_level)
984                 log_from_addr("nlm4_unlock", rqstp);
985
986         res.stat.stat = unlock(&arg->alock, LOCK_V4);
987         res.cookie = arg->cookie;
988
989         return (&res);
990 }
991
992 void *
993 nlm4_unlock_msg_4_svc(nlm4_unlockargs *arg, struct svc_req *rqstp)
994 {
995         static nlm4_res res;
996
997         if (debug_level)
998                 log_from_addr("nlm4_unlock_msg", rqstp);
999
1000         res.stat.stat = unlock(&arg->alock, LOCK_V4);
1001         res.cookie = arg->cookie;
1002
1003         transmit4_result(NLM4_UNLOCK_RES, &res, getrpcaddr(rqstp));
1004         return (NULL);
1005 }
1006
1007 /* ------------------------------------------------------------------------- */
1008 /*
1009  * Client-side pseudo-RPCs for results.  Note that for the client there
1010  * are only nlm_xxx_msg() versions of each call, since the 'real RPC'
1011  * version returns the results in the RPC result, and so the client
1012  * does not normally receive incoming RPCs.
1013  *
1014  * The exception to this is nlm_granted(), which is genuinely an RPC
1015  * call from the server to the client - a 'call-back' in normal procedure
1016  * call terms.
1017  */
1018
1019 /* nlm_granted ------------------------------------------------------------- */
1020 /*
1021  * Purpose:     Receive notification that formerly blocked lock now granted
1022  * Returns:     always success ('granted')
1023  * Notes:
1024  */
1025 nlm4_res *
1026 nlm4_granted_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
1027 {
1028         static nlm4_res res;
1029
1030         if (debug_level)
1031                 log_from_addr("nlm4_granted", rqstp);
1032
1033         /* copy cookie from arg to result.  See comment in nlm_test_1() */
1034         res.cookie = arg->cookie;
1035
1036         res.stat.stat = nlm4_granted;
1037         return (&res);
1038 }
1039
1040 void *
1041 nlm4_granted_msg_4_svc(nlm4_testargs *arg, struct svc_req *rqstp)
1042 {
1043         static nlm4_res res;
1044
1045         if (debug_level)
1046                 log_from_addr("nlm4_granted_msg", rqstp);
1047
1048         res.cookie = arg->cookie;
1049         res.stat.stat = nlm4_granted;
1050         transmit4_result(NLM4_GRANTED_RES, &res,
1051             (struct sockaddr *)svc_getrpccaller(rqstp->rq_xprt)->buf);
1052         return (NULL);
1053 }
1054
1055 /* nlm_test_res ------------------------------------------------------------ */
1056 /*
1057  * Purpose:     Accept result from earlier nlm_test_msg() call
1058  * Returns:     Nothing
1059  */
1060 void *
1061 nlm4_test_res_4_svc(nlm4_testres *arg, struct svc_req *rqstp)
1062 {
1063         if (debug_level)
1064                 log_from_addr("nlm4_test_res", rqstp);
1065         return (NULL);
1066 }
1067
1068 /* nlm_lock_res ------------------------------------------------------------ */
1069 /*
1070  * Purpose:     Accept result from earlier nlm_lock_msg() call
1071  * Returns:     Nothing
1072  */
1073 void *
1074 nlm4_lock_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
1075 {
1076         if (debug_level)
1077                 log_from_addr("nlm4_lock_res", rqstp);
1078
1079         return (NULL);
1080 }
1081
1082 /* nlm_cancel_res ---------------------------------------------------------- */
1083 /*
1084  * Purpose:     Accept result from earlier nlm_cancel_msg() call
1085  * Returns:     Nothing
1086  */
1087 void *
1088 nlm4_cancel_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp)
1089 {
1090         if (debug_level)
1091                 log_from_addr("nlm4_cancel_res", rqstp);
1092         return (NULL);
1093 }
1094
1095 /* nlm_unlock_res ---------------------------------------------------------- */
1096 /*
1097  * Purpose:     Accept result from earlier nlm_unlock_msg() call
1098  * Returns:     Nothing
1099  */
1100 void *
1101 nlm4_unlock_res_4_svc(nlm4_res *arg __unused, struct svc_req *rqstp)
1102 {
1103         if (debug_level)
1104                 log_from_addr("nlm4_unlock_res", rqstp);
1105         return (NULL);
1106 }
1107
1108 /* nlm_granted_res --------------------------------------------------------- */
1109 /*
1110  * Purpose:     Accept result from earlier nlm_granted_msg() call
1111  * Returns:     Nothing
1112  */
1113 void *
1114 nlm4_granted_res_4_svc(nlm4_res *arg, struct svc_req *rqstp)
1115 {
1116         if (debug_level)
1117                 log_from_addr("nlm4_granted_res", rqstp);
1118         return (NULL);
1119 }
1120
1121 /* ------------------------------------------------------------------------- */
1122 /*
1123  * Calls for PCNFS locking (aka non-monitored locking, no involvement
1124  * of rpc.statd).
1125  *
1126  * These are all genuine RPCs - no nlm_xxx_msg() nonsense here.
1127  */
1128
1129 /* nlm_share --------------------------------------------------------------- */
1130 /*
1131  * Purpose:     Establish a DOS-style lock
1132  * Returns:     success or failure
1133  * Notes:       Blocking locks are not supported - client is expected
1134  *              to retry if required.
1135  */
1136 nlm4_shareres *
1137 nlm4_share_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
1138 {
1139         static nlm4_shareres res;
1140
1141         if (debug_level)
1142                 log_from_addr("nlm4_share", rqstp);
1143
1144         res.cookie = arg->cookie;
1145         res.stat = nlm4_granted;
1146         res.sequence = 1234356; /* X/Open says this field is ignored? */
1147         return (&res);
1148 }
1149
1150 /* nlm4_unshare ------------------------------------------------------------ */
1151 /*
1152  * Purpose:     Release a DOS-style lock
1153  * Returns:     nlm_granted, unless in grace period
1154  * Notes:
1155  */
1156 nlm4_shareres *
1157 nlm4_unshare_4_svc(nlm4_shareargs *arg, struct svc_req *rqstp)
1158 {
1159         static nlm4_shareres res;
1160
1161         if (debug_level)
1162                 log_from_addr("nlm_unshare", rqstp);
1163
1164         res.cookie = arg->cookie;
1165         res.stat = nlm4_granted;
1166         res.sequence = 1234356; /* X/Open says this field is ignored? */
1167         return (&res);
1168 }
1169
1170 /* nlm4_nm_lock ------------------------------------------------------------ */
1171 /*
1172  * Purpose:     non-monitored version of nlm4_lock()
1173  * Returns:     as for nlm4_lock()
1174  * Notes:       These locks are in the same style as the standard nlm4_lock,
1175  *              but the rpc.statd should not be called to establish a
1176  *              monitor for the client machine, since that machine is
1177  *              declared not to be running a rpc.statd, and so would not
1178  *              respond to the statd protocol.
1179  */
1180 nlm4_res *
1181 nlm4_nm_lock_4_svc(nlm4_lockargs *arg, struct svc_req *rqstp)
1182 {
1183         static nlm4_res res;
1184
1185         if (debug_level)
1186                 log_from_addr("nlm4_nm_lock", rqstp);
1187
1188         /* copy cookie from arg to result.  See comment in nlm4_test_1() */
1189         res.cookie = arg->cookie;
1190         res.stat.stat = nlm4_granted;
1191         return (&res);
1192 }
1193
1194 /* nlm4_free_all ------------------------------------------------------------ */
1195 /*
1196  * Purpose:     Release all locks held by a named client
1197  * Returns:     Nothing
1198  * Notes:       Potential denial of service security problem here - the
1199  *              locks to be released are specified by a host name, independent
1200  *              of the address from which the request has arrived.
1201  *              Should probably be rejected if the named host has been
1202  *              using monitored locks.
1203  */
1204 void *
1205 nlm4_free_all_4_svc(nlm_notify *arg, struct svc_req *rqstp)
1206 {
1207         static char dummy;
1208
1209         if (debug_level)
1210                 log_from_addr("nlm4_free_all", rqstp);
1211         return (&dummy);
1212 }
1213
1214 /* nlm_sm_notify --------------------------------------------------------- */
1215 /*
1216  * Purpose:     called by rpc.statd when a monitored host state changes.
1217  * Returns:     Nothing
1218  */
1219 void *
1220 nlm_sm_notify_0_svc(struct nlm_sm_status *arg, struct svc_req *rqstp __unused)
1221 {
1222         static char dummy;
1223         notify(arg->mon_name, arg->state);
1224         return (&dummy);
1225 }