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