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