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 */ 63static void 64log_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 */ 110static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE]; 111static long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */ 112static struct in_addr clnt_cache_addr[CLIENT_CACHE_SIZE]; 113static int clnt_cache_next_to_use = 0; 114 115CLIENT * 116get_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 */ 198void 199transmit_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 */ 226void 227transmit4_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 */ 250static void 251nlmtonlm4(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 */ 291nlm_testres * 292nlm_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 325void * 326nlm_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 */ 381nlm_res * 382nlm_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 403void * 404nlm_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 */ 432nlm_res * 433nlm_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 454void * 455nlm_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 */ 483nlm_res * 484nlm_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 500void * 501nlm_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 */ 536nlm_res * 537nlm_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 551void * 552nlm_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 */ 570void * 571nlm_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 */ 583void * 584nlm_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 */ 597void * 598nlm_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 */ 610void * 611nlm_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 */ 623void * 624nlm_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 */ 646nlm_shareres * 647nlm_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 */ 666nlm_shareres * 667nlm_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 */ 690nlm_res * 691nlm_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 */ 714void * 715nlm_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 */ 731nlm4_testres * 732nlm4_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 760void * 761nlm4_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 */ 809nlm4_res * 810nlm4_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 824void * 825nlm4_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 */ 845nlm4_res * 846nlm4_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 864void * 865nlm4_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 */ 891nlm4_res * 892nlm4_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 905void * 906nlm4_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 */ 938nlm4_res * 939nlm4_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 953void * 954nlm4_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 */ 972void * 973nlm4_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 */ 985void * 986nlm4_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 */ 999void * 1000nlm4_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 */ 1012void * 1013nlm4_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 */ 1025void * 1026nlm4_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 */ 1048nlm4_shareres * 1049nlm4_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 */ 1068nlm4_shareres * 1069nlm4_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 */ 1092nlm4_res * 1093nlm4_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 */ 1116void * 1117nlm4_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 */ 1131void * 1132nlm_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