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