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