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