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