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