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