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