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