1/* 2 * Copyright (c) 2002-2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* $NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $ */ 24/* $FreeBSD: src/usr.sbin/rpc.lockd/lock_proc.c,v 1.10 2002/03/22 20:00:10 alfred Exp $ */ 25/* 26 * Copyright (c) 1995 27 * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. 28 * 29 * Redistribution and use in source and binary forms, with or without 30 * modification, are permitted provided that the following conditions 31 * are met: 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions and the following disclaimer. 34 * 2. Redistributions in binary form must reproduce the above copyright 35 * notice, this list of conditions and the following disclaimer in the 36 * documentation and/or other materials provided with the distribution. 37 * 3. All advertising materials mentioning features or use of this software 38 * must display the following acknowledgement: 39 * This product includes software developed for the FreeBSD project 40 * 4. Neither the name of the author nor the names of any co-contributors 41 * may be used to endorse or promote products derived from this software 42 * without specific prior written permission. 43 * 44 * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND 45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 47 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 54 * SUCH DAMAGE. 55 * 56 */ 57 58#include <sys/cdefs.h> 59#ifndef lint 60__RCSID("$NetBSD: lock_proc.c,v 1.7 2000/10/11 20:23:56 is Exp $"); 61#endif 62 63#include <sys/param.h> 64#include <sys/socket.h> 65 66#include <netinet/in.h> 67#include <arpa/inet.h> 68 69#include <netdb.h> 70#include <stdio.h> 71#include <string.h> 72#include <syslog.h> 73#include <stdlib.h> 74#include <sys/queue.h> 75 76#include <oncrpc/rpc.h> 77#include "sm_inter.h" 78#include "nlm_prot.h" 79 80#include "lockd.h" 81#include "lockd_lock.h" 82 83 84#define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */ 85#define CLIENT_CACHE_LIFETIME 120 /* In seconds */ 86 87#define AOK (void *) // assert alignment is OK 88 89static void log_from_addr(const char *, struct svc_req *); 90static void log_netobj(netobj *obj); 91 92/* log_from_addr ----------------------------------------------------------- */ 93/* 94 * Purpose: Log name of function called and source address 95 * Returns: Nothing 96 * Notes: Extracts the source address from the transport handle 97 * passed in as part of the called procedure specification 98 */ 99static void 100log_from_addr(fun_name, req) 101 const char *fun_name; 102 struct svc_req *req; 103{ 104 struct sockaddr *addr; 105 char hostname_buf[NI_MAXHOST]; 106 107 addr = svc_getcaller_sa(req->rq_xprt); 108 if (getnameinfo(addr, addr->sa_len, hostname_buf, sizeof hostname_buf, NULL, 0, 0) != 0) 109 return; 110 111 syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf); 112} 113 114/* log_netobj ----------------------------------------------------------- */ 115/* 116 * Purpose: Log a netobj 117 * Returns: Nothing 118 * Notes: This function should only really be called as part of 119 * a debug subsystem. 120*/ 121static void 122log_netobj(obj) 123 netobj *obj; 124{ 125 char objvalbuffer[(sizeof(char)*2)*MAX_NETOBJ_SZ+2]; 126 char objascbuffer[sizeof(char)*MAX_NETOBJ_SZ+1]; 127 unsigned int i, maxlen; 128 char *tmp1, *tmp2; 129 130 /* Notify of potential security attacks */ 131 if (obj->n_len > MAX_NETOBJ_SZ) { 132 syslog(LOG_DEBUG, "SOMEONE IS TRYING TO DO SOMETHING NASTY!\n"); 133 syslog(LOG_DEBUG, "netobj too large! Should be %d was %d\n", 134 MAX_NETOBJ_SZ, obj->n_len); 135 } 136 /* Prevent the security hazard from the buffer overflow */ 137 maxlen = (obj->n_len < MAX_NETOBJ_SZ ? obj->n_len : MAX_NETOBJ_SZ); 138 for (i=0, tmp1 = objvalbuffer, tmp2 = objascbuffer; i < maxlen; 139 i++, tmp1 +=2, tmp2 +=1) { 140 snprintf(tmp1, 2+1, "%02X", *(obj->n_bytes+i)); 141 snprintf(tmp2, 1+1, "%c", *(obj->n_bytes+i)); 142 } 143 *tmp1 = '\0'; 144 *tmp2 = '\0'; 145 syslog(LOG_DEBUG,"netobjvals: %s\n",objvalbuffer); 146 syslog(LOG_DEBUG,"netobjascs: %s\n",objascbuffer); 147} 148/* get_client -------------------------------------------------------------- */ 149/* 150 * Purpose: Get a CLIENT* for making RPC calls to lockd on given host 151 * Returns: CLIENT* pointer, from clnt(udp|tcp)_create, or NULL if error 152 * Notes: Creating a CLIENT* is quite expensive, involving a 153 * conversation with the remote portmapper to get the 154 * port number. Since a given client is quite likely 155 * to make several locking requests in succession, it is 156 * desirable to cache the created CLIENT*. 157 * 158 * Since we are using UDP by default (rather than TCP), there is no 159 * cost to the remote system in keeping these cached indefinitely. 160 * Unfortunately there is a snag: if the remote system 161 * reboots, the cached portmapper results will be invalid, 162 * and we will never detect this since all of the xxx_msg() 163 * calls return no result - we just fire off a UDP packet 164 * and hope for the best. 165 * 166 * We solve this by discarding cached values after two 167 * minutes, regardless of whether they have been used 168 * in the meanwhile (since a bad one might have been used 169 * plenty of times, as the host keeps retrying the request 170 * and we keep sending the reply back to the wrong port). 171 * 172 * Given that the entries will always expire in the order 173 * that they were created, there is no point in a LRU 174 * algorithm for when the cache gets full - entries are 175 * always re-used in sequence. 176 */ 177static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE]; 178static long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */ 179static struct sockaddr_storage clnt_cache_addr[CLIENT_CACHE_SIZE]; 180static rpcvers_t clnt_cache_vers[CLIENT_CACHE_SIZE]; 181static int clnt_cache_next_to_use = 0; 182 183/* 184 * Because lockd is single-threaded, slow/unresponsive portmappers on 185 * clients can cause serious performance issues. So, we keep a list of 186 * these bad hosts, and limit how often we try to get_client() for those hosts. 187 */ 188struct badhost { 189 TAILQ_ENTRY(badhost) list; 190 struct sockaddr_storage addr; /* host address */ 191 int count; /* # of occurences */ 192 time_t timelast; /* last attempted */ 193 time_t timenext; /* next allowed */ 194}; 195TAILQ_HEAD(badhostlist_head, badhost); 196static struct badhostlist_head badhostlist_head = TAILQ_HEAD_INITIALIZER(badhostlist_head); 197#define BADHOST_CLIENT_TOOK_TOO_LONG 5 /* In seconds */ 198#define BADHOST_NFS_CLIENT_SIDE_DELAY 60 /* In seconds */ 199#define BADHOST_INITIAL_DELAY 120 /* In seconds */ 200#define BADHOST_MAXIMUM_DELAY 3600 /* In seconds */ 201#define BADHOST_DELAY_INCREMENT 300 /* In seconds */ 202 203int 204addrcmp(const struct sockaddr *sa1, const struct sockaddr *sa2) 205{ 206 int len; 207 void *p1, *p2; 208 209 if (sa1->sa_family != sa2->sa_family) 210 return -1; 211 212 switch (sa1->sa_family) { 213 case AF_INET: 214 p1 = &((struct sockaddr_in *) AOK sa1)->sin_addr; 215 p2 = &((struct sockaddr_in *) AOK sa2)->sin_addr; 216 len = 4; 217 break; 218 case AF_INET6: 219 p1 = &((struct sockaddr_in6 *) AOK sa1)->sin6_addr; 220 p2 = &((struct sockaddr_in6 *) AOK sa2)->sin6_addr; 221 len = 16; 222 break; 223 default: 224 return -1; 225 } 226 227 return memcmp(p1, p2, len); 228} 229 230CLIENT * 231get_client(host_addr, vers, client_request, use_tcp) 232 struct sockaddr *host_addr; 233 rpcvers_t vers; 234 int client_request; 235 int use_tcp; 236{ 237 CLIENT *client, *cached_client; 238 struct timeval retry_time, time_now; 239 int i; 240 int sock_no, cache_ttl; 241 time_t time_start, cache_time = 0; 242 struct badhost *badhost, *nextbadhost; 243 char addrbuf[2*INET6_ADDRSTRLEN]; 244 245 if (config.send_using_mnt_transport == 0) 246 use_tcp = 0; 247 248 if (!use_tcp && config.send_using_tcp) 249 use_tcp = config.send_using_tcp; 250 251 gettimeofday(&time_now, NULL); 252 253 /* use an extremely short TTL when reclaims are being sent */ 254 cache_ttl = (client_request > 1) ? 4 : CLIENT_CACHE_LIFETIME; 255 256 /* 257 * Search for the given client in the cache. 258 */ 259 cached_client = NULL; 260 for (i = 0; i < CLIENT_CACHE_SIZE; i++) { 261 client = clnt_cache_ptr[i]; 262 if (!client) 263 continue; 264 if (clnt_cache_vers[i] != vers) 265 continue; 266 if (addrcmp((struct sockaddr *)&clnt_cache_addr[i], host_addr)) 267 continue; 268 /* Found it! */ 269 if (((clnt_cache_time[i] + cache_ttl) > time_now.tv_sec)) { 270 if (config.verbose > 3) 271 syslog(LOG_DEBUG, "Found CLIENT* in cache"); 272 return (client); 273 } 274 if (config.verbose) 275 syslog(LOG_DEBUG, "Found expired CLIENT* in cache"); 276 cached_client = client; 277 /* if we end up reusing this guy, make sure we keep the same timestamp */ 278 cache_time = clnt_cache_time[i]; 279 clnt_cache_time[i] = 0L; 280 clnt_cache_ptr[i] = NULL; 281 client = NULL; 282 break; 283 } 284 285 /* 286 * Search for the given client in the badhost list. 287 */ 288 badhost = TAILQ_FIRST(&badhostlist_head); 289 while (badhost) { 290 nextbadhost = TAILQ_NEXT(badhost, list); 291 if (!addrcmp(host_addr, (struct sockaddr *)&badhost->addr)) 292 break; 293 if ((badhost->timelast + BADHOST_MAXIMUM_DELAY) < time_now.tv_sec) { 294 /* cleanup entries we haven't heard from in a while */ 295 TAILQ_REMOVE(&badhostlist_head, badhost, list); 296 free(badhost); 297 } 298 badhost = nextbadhost; 299 } 300 301 /* 302 * If we're getting this "CLIENT*" to send an NFS client side message to 303 * an NFS server's lockd, then limit the badhost delay to 60 seconds. 304 */ 305 if (badhost && client_request && ((time_now.tv_sec - badhost->timelast) >= BADHOST_NFS_CLIENT_SIDE_DELAY)) 306 badhost->timenext = time_now.tv_sec; 307 if (badhost && (time_now.tv_sec < badhost->timenext)) { 308 /* 309 * We've got a badhost, and we don't want to try 310 * consulting it again yet. If we've got a stale 311 * cached CLIENT*, go ahead and try to use that. 312 */ 313 if (cached_client) { 314 if (config.verbose) 315 syslog(LOG_DEBUG, "badhost delayed: stale CLIENT* found in cache"); 316 /* Free the next entry if it is in use. */ 317 if (clnt_cache_ptr[clnt_cache_next_to_use]) { 318 clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]); 319 clnt_cache_ptr[clnt_cache_next_to_use] = NULL; 320 } 321 client = cached_client; 322 goto update_cache_entry; 323 } 324 if (config.verbose) 325 syslog(LOG_DEBUG, "badhost delayed: valid CLIENT* not found in cache"); 326 return NULL; 327 } 328 329 if (config.verbose > 3) { 330 if (!cached_client) 331 syslog(LOG_DEBUG, "CLIENT* not found in cache, creating"); 332 else 333 syslog(LOG_DEBUG, "stale CLIENT* found in cache, updating"); 334 } 335 336 /* Free the next entry if it is in use. */ 337 if (clnt_cache_ptr[clnt_cache_next_to_use]) { 338 clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]); 339 clnt_cache_ptr[clnt_cache_next_to_use] = NULL; 340 } 341 342 /* Create the new client handle */ 343 time_start = time_now.tv_sec; 344 345 sock_no = RPC_ANYSOCK; 346 retry_time.tv_sec = 5; 347 retry_time.tv_usec = 0; 348 if (host_addr->sa_family == AF_INET) /* Force consultation with portmapper */ 349 ((struct sockaddr_in *) AOK host_addr)->sin_port = 0; 350 else 351 ((struct sockaddr_in6 *) AOK host_addr)->sin6_port = 0; 352 if (use_tcp) 353 client = clnttcp_create_sa(host_addr, NLM_PROG, vers, &sock_no, 0, 0); 354 if (!use_tcp || !client) 355 client = clntudp_create_sa(host_addr, NLM_PROG, vers, retry_time, &sock_no); 356 357 gettimeofday(&time_now, NULL); 358 if (time_now.tv_sec - time_start >= BADHOST_CLIENT_TOOK_TOO_LONG) { 359 /* 360 * The client create took a long time! (slow/unresponsive portmapper?) 361 * Add/update an entry in the badhost list. 362 */ 363 if (!badhost && (badhost = malloc(sizeof(struct badhost)))) { 364 /* allocate new badhost */ 365 memcpy(&badhost->addr, host_addr, host_addr->sa_len); 366 badhost->count = 0; 367 TAILQ_INSERT_TAIL(&badhostlist_head, badhost, list); 368 } 369 if (badhost) { 370 /* update count and times */ 371 badhost->count++; 372 badhost->timelast = time_now.tv_sec; 373 if (client_request) { 374 /* limit NFS client side badhost delay */ 375 badhost->timenext = time_now.tv_sec + BADHOST_NFS_CLIENT_SIDE_DELAY; 376 } else if (badhost->count == 1) { 377 /* first timers get a shorter initial delay */ 378 badhost->timenext = time_now.tv_sec + BADHOST_INITIAL_DELAY; 379 } else { 380 /* multiple offenders get an increasingly larger delay */ 381 int delay = (badhost->count - 1) * BADHOST_DELAY_INCREMENT; 382 if (delay > BADHOST_MAXIMUM_DELAY) 383 delay = BADHOST_MAXIMUM_DELAY; 384 badhost->timenext = time_now.tv_sec + delay; 385 } 386 /* move to end of list */ 387 TAILQ_REMOVE(&badhostlist_head, badhost, list); 388 TAILQ_INSERT_TAIL(&badhostlist_head, badhost, list); 389 } 390 } else if (badhost) { 391 /* host seems good now, remove it from list */ 392 TAILQ_REMOVE(&badhostlist_head, badhost, list); 393 free(badhost); 394 badhost = NULL; 395 } 396 397 if (!client) { 398 /* We couldn't get a new CLIENT* */ 399 if (!cached_client) { 400 getnameinfo(host_addr, host_addr->sa_len, addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST); 401 syslog(LOG_WARNING, "Unable to contact %s: %s", addrbuf, 402 clnt_spcreateerror(use_tcp ? "clnttcp_create" : "clntudp_create")); 403 return NULL; 404 } 405 /* 406 * We couldn't get updated info from portmapper, but we did 407 * still have the stale cached data. So we might as well try 408 * to use it. 409 */ 410 client = cached_client; 411 getnameinfo(host_addr, host_addr->sa_len, addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST); 412 syslog(LOG_WARNING, "Unable to update contact info for %s: %s", addrbuf, 413 clnt_spcreateerror(use_tcp ? "clnttcp_create" : "clntudp_create")); 414 } else { 415 /* 416 * We've got a new/updated CLIENT* for this host. 417 * So, destroy any previously cached CLIENT*. 418 */ 419 if (cached_client) 420 clnt_destroy(cached_client); 421 422 /* 423 * Disable the default timeout, so we can specify our own in calls 424 * to clnt_call(). (Note that the timeout is a different concept 425 * from the retry period set in clnt(udp|tcp)_create() above.) 426 */ 427 retry_time.tv_sec = -1; 428 retry_time.tv_usec = -1; 429 clnt_control(client, CLSET_TIMEOUT, (char *)&retry_time); 430 431 if (config.verbose > 3) { 432 getnameinfo(host_addr, host_addr->sa_len, addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST); 433 syslog(LOG_DEBUG, "Created CLIENT* for %s", addrbuf); 434 } 435 436 /* make sure the new entry gets the current timestamp */ 437 cache_time = time_now.tv_sec; 438 } 439 440update_cache_entry: 441 /* Success (of some sort) - update the cache entry */ 442 clnt_cache_ptr[clnt_cache_next_to_use] = client; 443 memcpy(&clnt_cache_addr[clnt_cache_next_to_use], host_addr, 444 host_addr->sa_len); 445 clnt_cache_vers[clnt_cache_next_to_use] = vers; 446 clnt_cache_time[clnt_cache_next_to_use] = cache_time; 447 if (++clnt_cache_next_to_use >= CLIENT_CACHE_SIZE) 448 clnt_cache_next_to_use = 0; 449 450 return client; 451} 452 453 454/* transmit_result --------------------------------------------------------- */ 455/* 456 * Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs 457 * Returns: success (0) or failure (-1) at sending the datagram 458 * Notes: clnt_call() will always fail (with timeout) as we are 459 * calling it with timeout 0 as a hack to just issue a datagram 460 * without expecting a result 461 */ 462int 463transmit_result(opcode, result, addr, client_request) 464 int opcode; 465 nlm_res *result; 466 struct sockaddr *addr; 467 int client_request; 468{ 469 static char dummy; 470 CLIENT *cli; 471 struct timeval timeo; 472 int success; 473 474 if ((cli = get_client(addr, NLM_VERS, client_request, 0)) != NULL) { 475 timeo.tv_sec = 0; /* No timeout - not expecting response */ 476 timeo.tv_usec = 0; 477 478 success = clnt_call(cli, opcode, (xdrproc_t)xdr_nlm_res, result, (xdrproc_t)xdr_void, 479 &dummy, timeo); 480 481 if (config.verbose > 2) 482 syslog(LOG_DEBUG, "clnt_call returns %d(%s)", 483 success, clnt_sperrno(success)); 484 return (0); 485 } 486 return (-1); 487} 488/* transmit4_result --------------------------------------------------------- */ 489/* 490 * Purpose: Transmit result for nlm4_xxx_msg pseudo-RPCs 491 * Returns: success (0) or failure (-1) at sending the datagram 492 * Notes: clnt_call() will always fail (with timeout) as we are 493 * calling it with timeout 0 as a hack to just issue a datagram 494 * without expecting a result 495 */ 496int 497transmit4_result(opcode, result, addr, client_request) 498 int opcode; 499 nlm4_res *result; 500 struct sockaddr *addr; 501 int client_request; 502{ 503 static char dummy; 504 CLIENT *cli; 505 struct timeval timeo; 506 int success; 507 508 if ((cli = get_client(addr, NLM_VERS4, client_request, 0)) != NULL) { 509 timeo.tv_sec = 0; /* No timeout - not expecting response */ 510 timeo.tv_usec = 0; 511 512 success = clnt_call(cli, opcode, (xdrproc_t)xdr_nlm4_res, result, (xdrproc_t)xdr_void, 513 &dummy, timeo); 514 515 if (config.verbose > 2) 516 syslog(LOG_DEBUG, "clnt_call returns %d(%s)", 517 success, clnt_sperrno(success)); 518 return (0); 519 } 520 return (-1); 521} 522 523/* 524 * converts a struct nlm_lock to struct nlm4_lock 525 */ 526static void nlmtonlm4(struct nlm_lock *, struct nlm4_lock *); 527static void 528nlmtonlm4(arg, arg4) 529 struct nlm_lock *arg; 530 struct nlm4_lock *arg4; 531{ 532 arg4->caller_name = arg->caller_name; 533 arg4->fh = arg->fh; 534 arg4->oh = arg->oh; 535 arg4->svid = arg->svid; 536 arg4->l_offset = arg->l_offset; 537 arg4->l_len = arg->l_len; 538} 539/* ------------------------------------------------------------------------- */ 540/* 541 * Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd 542 * involved to ensure reclaim of locks after a crash of the "stateless" 543 * server. 544 * 545 * These all come in two flavours - nlm_xxx() and nlm_xxx_msg(). 546 * The first are standard RPCs with argument and result. 547 * The nlm_xxx_msg() calls implement exactly the same functions, but 548 * use two pseudo-RPCs (one in each direction). These calls are NOT 549 * standard use of the RPC protocol in that they do not return a result 550 * at all (NB. this is quite different from returning a void result). 551 * The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged 552 * datagrams, requiring higher-level code to perform retries. 553 * 554 * Despite the disadvantages of the nlm_xxx_msg() approach (some of which 555 * are documented in the comments to get_client() above), this is the 556 * interface used by all current commercial NFS implementations 557 * [Solaris, SCO, AIX etc.]. This is presumed to be because these allow 558 * implementations to continue using the standard RPC libraries, while 559 * avoiding the block-until-result nature of the library interface. 560 * 561 * No client implementations have been identified so far that make use 562 * of the true RPC version (early SunOS releases would be a likely candidate 563 * for testing). 564 */ 565 566/* nlm_test ---------------------------------------------------------------- */ 567/* 568 * Purpose: Test whether a specified lock would be granted if requested 569 * Returns: nlm_granted (or error code) 570 * Notes: 571 */ 572nlm_testres * 573nlm_test_1_svc(arg, rqstp) 574 nlm_testargs *arg; 575 struct svc_req *rqstp; 576{ 577 static nlm_testres res; 578 struct nlm4_lock arg4; 579 struct nlm4_holder *holder; 580 nlmtonlm4(&arg->alock, &arg4); 581 582 if (config.verbose) 583 log_from_addr("nlm_test", rqstp); 584 585 holder = testlock(&arg4, arg->exclusive, 0); 586 /* 587 * Copy the cookie from the argument into the result. Note that this 588 * is slightly hazardous, as the structure contains a pointer to a 589 * malloc()ed buffer that will get freed by the caller. However, the 590 * main function transmits the result before freeing the argument 591 * so it is in fact safe. 592 */ 593 res.cookie = arg->cookie; 594 if (holder == NULL) { 595 res.stat.stat = nlm_granted; 596 } else { 597 res.stat.stat = nlm_denied; 598 memcpy(&res.stat.nlm_testrply_u.holder, holder, 599 sizeof(struct nlm_holder)); 600 res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset; 601 res.stat.nlm_testrply_u.holder.l_len = holder->l_len; 602 } 603 return (&res); 604} 605 606void * 607nlm_test_msg_1_svc(arg, rqstp) 608 nlm_testargs *arg; 609 struct svc_req *rqstp; 610{ 611 nlm_testres res; 612 static char dummy; 613 CLIENT *cli; 614 int success; 615 struct timeval timeo; 616 struct nlm4_lock arg4; 617 struct nlm4_holder *holder; 618 619 nlmtonlm4(&arg->alock, &arg4); 620 621 if (config.verbose) 622 log_from_addr("nlm_test_msg", rqstp); 623 624 holder = testlock(&arg4, arg->exclusive, 0); 625 626 res.cookie = arg->cookie; 627 if (holder == NULL) { 628 res.stat.stat = nlm_granted; 629 } else { 630 res.stat.stat = nlm_denied; 631 memcpy(&res.stat.nlm_testrply_u.holder, holder, 632 sizeof(struct nlm_holder)); 633 res.stat.nlm_testrply_u.holder.l_offset = holder->l_offset; 634 res.stat.nlm_testrply_u.holder.l_len = holder->l_len; 635 } 636 637 /* 638 * nlm_test has different result type to the other operations, so 639 * can't use transmit_result() in this case 640 */ 641 if ((cli = get_client(svc_getcaller_sa(rqstp->rq_xprt), NLM_VERS, 0, 0)) != NULL) { 642 timeo.tv_sec = 0; /* No timeout - not expecting response */ 643 timeo.tv_usec = 0; 644 645 success = clnt_call(cli, NLM_TEST_RES, (xdrproc_t)xdr_nlm_testres, 646 &res, (xdrproc_t)xdr_void, &dummy, timeo); 647 648 if (config.verbose > 2) 649 syslog(LOG_DEBUG, "clnt_call returns %d", success); 650 } 651 return (NULL); 652} 653 654/* nlm_lock ---------------------------------------------------------------- */ 655/* 656 * Purposes: Establish a lock 657 * Returns: granted, denied or blocked 658 * Notes: *** grace period support missing 659 */ 660nlm_res * 661nlm_lock_1_svc(arg, rqstp) 662 nlm_lockargs *arg; 663 struct svc_req *rqstp; 664{ 665 static nlm_res res; 666 struct nlm4_lockargs arg4; 667 nlmtonlm4(&arg->alock, &arg4.alock); 668 arg4.cookie = arg->cookie; 669 arg4.block = arg->block; 670 arg4.exclusive = arg->exclusive; 671 arg4.reclaim = arg->reclaim; 672 arg4.state = arg->state; 673 674 if (config.verbose) 675 log_from_addr("nlm_lock", rqstp); 676 677 /* copy cookie from arg to result. See comment in nlm_test_1() */ 678 res.cookie = arg->cookie; 679 680 res.stat.stat = (nlm_stats) getlock(&arg4, rqstp, LOCK_MON); 681 return (&res); 682} 683 684void * 685nlm_lock_msg_1_svc(arg, rqstp) 686 nlm_lockargs *arg; 687 struct svc_req *rqstp; 688{ 689 static nlm_res res; 690 struct nlm4_lockargs arg4; 691 692 nlmtonlm4(&arg->alock, &arg4.alock); 693 arg4.cookie = arg->cookie; 694 arg4.block = arg->block; 695 arg4.exclusive = arg->exclusive; 696 arg4.reclaim = arg->reclaim; 697 arg4.state = arg->state; 698 699 if (config.verbose) 700 log_from_addr("nlm_lock_msg", rqstp); 701 702 res.cookie = arg->cookie; 703 res.stat.stat = (nlm_stats) getlock(&arg4, rqstp, LOCK_ASYNC | LOCK_MON); 704 if (transmit_result(NLM_LOCK_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 0) < 0) { 705 /* if res.stat.stat was success/blocked, then unlock/cancel */ 706 if (res.stat.stat == nlm_granted) 707 unlock(&arg4.alock, LOCK_V4); 708 else if (res.stat.stat == nlm_blocked) { 709 nlm4_cancargs carg; 710 carg.cookie = arg4.cookie; 711 carg.block = arg4.block; 712 carg.exclusive = arg4.exclusive; 713 carg.alock = arg4.alock; 714 cancellock(&carg, 0); 715 } 716 } 717 718 return (NULL); 719} 720 721/* nlm_cancel -------------------------------------------------------------- */ 722/* 723 * Purpose: Cancel a blocked lock request 724 * Returns: granted or denied 725 * Notes: 726 */ 727nlm_res * 728nlm_cancel_1_svc(arg, rqstp) 729 nlm_cancargs *arg; 730 struct svc_req *rqstp; 731{ 732 static nlm_res res; 733 struct nlm4_cancargs arg4; 734 735 arg4.cookie = arg->cookie; 736 arg4.block = arg->block; 737 arg4.exclusive = arg->exclusive; 738 nlmtonlm4(&arg->alock, &arg4.alock); 739 740 if (config.verbose) 741 log_from_addr("nlm_cancel", rqstp); 742 743 /* copy cookie from arg to result. See comment in nlm_test_1() */ 744 res.cookie = arg->cookie; 745 746 res.stat.stat = (nlm_stats) cancellock(&arg4, 0); 747 return (&res); 748} 749 750void * 751nlm_cancel_msg_1_svc(arg, rqstp) 752 nlm_cancargs *arg; 753 struct svc_req *rqstp; 754{ 755 static nlm_res res; 756 struct nlm4_cancargs arg4; 757 758 arg4.cookie = arg->cookie; 759 arg4.block = arg->block; 760 arg4.exclusive = arg->exclusive; 761 nlmtonlm4(&arg->alock, &arg4.alock); 762 763 if (config.verbose) 764 log_from_addr("nlm_cancel_msg", rqstp); 765 766 res.cookie = arg->cookie; 767 res.stat.stat = (nlm_stats) cancellock(&arg4, 0); 768 if (transmit_result(NLM_CANCEL_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 0) < 0) { 769 /* XXX do we need to (un)do anything if this fails? */ 770 } 771 return (NULL); 772} 773 774/* nlm_unlock -------------------------------------------------------------- */ 775/* 776 * Purpose: Release an existing lock 777 * Returns: Always granted, unless during grace period 778 * Notes: "no such lock" error condition is ignored, as the 779 * protocol uses unreliable UDP datagrams, and may well 780 * re-try an unlock that has already succeeded. 781 */ 782nlm_res * 783nlm_unlock_1_svc(arg, rqstp) 784 nlm_unlockargs *arg; 785 struct svc_req *rqstp; 786{ 787 static nlm_res res; 788 struct nlm4_lock arg4; 789 790 nlmtonlm4(&arg->alock, &arg4); 791 792 if (config.verbose) 793 log_from_addr("nlm_unlock", rqstp); 794 795 res.stat.stat = (nlm_stats) unlock(&arg4, 0); 796 res.cookie = arg->cookie; 797 798 return (&res); 799} 800 801void * 802nlm_unlock_msg_1_svc(arg, rqstp) 803 nlm_unlockargs *arg; 804 struct svc_req *rqstp; 805{ 806 static nlm_res res; 807 struct nlm4_lock arg4; 808 809 nlmtonlm4(&arg->alock, &arg4); 810 811 if (config.verbose) 812 log_from_addr("nlm_unlock_msg", rqstp); 813 814 res.stat.stat = (nlm_stats) unlock(&arg4, 0); 815 res.cookie = arg->cookie; 816 817 if (transmit_result(NLM_UNLOCK_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 0) < 0) { 818 /* XXX do we need to (un)do anything if this fails? */ 819 } 820 return (NULL); 821} 822 823/* ------------------------------------------------------------------------- */ 824/* 825 * Client-side pseudo-RPCs for results. Note that for the client there 826 * are only nlm_xxx_msg() versions of each call, since the 'real RPC' 827 * version returns the results in the RPC result, and so the client 828 * does not normally receive incoming RPCs. 829 * 830 * The exception to this is nlm_granted(), which is genuinely an RPC 831 * call from the server to the client - a 'call-back' in normal procedure 832 * call terms. 833 */ 834 835/* nlm_granted ------------------------------------------------------------- */ 836/* 837 * Purpose: Receive notification that formerly blocked lock now granted 838 * Returns: always success ('granted') 839 * Notes: 840 */ 841nlm_res * 842nlm_granted_1_svc(arg, rqstp) 843 nlm_testargs *arg; 844 struct svc_req *rqstp; 845{ 846 static nlm_res res; 847 nlm4_lock lock4; 848 int flags; 849 850 if (config.verbose) 851 log_from_addr("nlm_granted", rqstp); 852 853 lock4.fh = arg->alock.fh; 854 lock4.svid = arg->alock.svid; 855 lock4.l_offset = arg->alock.l_offset; 856 lock4.l_len = arg->alock.l_len; 857 858 flags = LOCK_ANSWER_GRANTED; 859 if (arg->exclusive) 860 flags |= LOCK_ANSWER_LOCK_EXCL; 861 862 if (lock_answer(NLM_VERS, &arg->cookie, &lock4, flags, nlm_granted)) 863 res.stat.stat = nlm_denied; 864 else 865 res.stat.stat = nlm_granted; 866 867 /* copy cookie from arg to result. See comment in nlm_test_1() */ 868 res.cookie = arg->cookie; 869 870 return (&res); 871} 872 873void * 874nlm_granted_msg_1_svc(arg, rqstp) 875 nlm_testargs *arg; 876 struct svc_req *rqstp; 877{ 878 static nlm_res res; 879 nlm4_lock lock4; 880 int flags; 881 882 if (config.verbose) 883 log_from_addr("nlm_granted_msg", rqstp); 884 885 lock4.fh = arg->alock.fh; 886 lock4.svid = arg->alock.svid; 887 lock4.l_offset = arg->alock.l_offset; 888 lock4.l_len = arg->alock.l_len; 889 890 flags = LOCK_ANSWER_GRANTED; 891 if (arg->exclusive) 892 flags |= LOCK_ANSWER_LOCK_EXCL; 893 894 if (lock_answer(NLM_VERS, &arg->cookie, &lock4, flags, nlm_granted)) 895 res.stat.stat = nlm_denied; 896 else 897 res.stat.stat = nlm_granted; 898 899 res.cookie = arg->cookie; 900 901 if (transmit_result(NLM_GRANTED_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 1) < 0) { 902 /* XXX do we need to (un)do anything if this fails? */ 903 } 904 return (NULL); 905} 906 907/* nlm_test_res ------------------------------------------------------------ */ 908/* 909 * Purpose: Accept result from earlier nlm_test_msg() call 910 * Returns: Nothing 911 */ 912void * 913nlm_test_res_1_svc(arg, rqstp) 914 nlm_testres *arg; 915 struct svc_req *rqstp; 916{ 917 nlm4_lock lock4; 918 int flags = 0; 919 920 if (config.verbose) 921 log_from_addr("nlm_test_res", rqstp); 922 923 if (arg->stat.stat == nlm_denied) { 924 lock4.fh.n_len = 0; 925 lock4.svid = arg->stat.nlm_testrply_u.holder.svid; 926 lock4.l_offset = arg->stat.nlm_testrply_u.holder.l_offset; 927 lock4.l_len = arg->stat.nlm_testrply_u.holder.l_len; 928 if (arg->stat.nlm_testrply_u.holder.exclusive) 929 flags |= LOCK_ANSWER_LOCK_EXCL; 930 lock_answer(NLM_VERS, &arg->cookie, &lock4, flags, arg->stat.stat); 931 } else 932 lock_answer(NLM_VERS, &arg->cookie, NULL, 0, arg->stat.stat); 933 934 return (NULL); 935} 936 937/* nlm_lock_res ------------------------------------------------------------ */ 938/* 939 * Purpose: Accept result from earlier nlm_lock_msg() call 940 * Returns: Nothing 941 */ 942void * 943nlm_lock_res_1_svc(arg, rqstp) 944 nlm_res *arg; 945 struct svc_req *rqstp; 946{ 947 if (config.verbose) 948 log_from_addr("nlm_lock_res", rqstp); 949 950 lock_answer(NLM_VERS, &arg->cookie, NULL, 0, arg->stat.stat); 951 952 return (NULL); 953} 954 955/* nlm_cancel_res ---------------------------------------------------------- */ 956/* 957 * Purpose: Accept result from earlier nlm_cancel_msg() call 958 * Returns: Nothing 959 */ 960void * 961nlm_cancel_res_1_svc(arg, rqstp) 962 nlm_res *arg; 963 struct svc_req *rqstp; 964{ 965 if (config.verbose) 966 log_from_addr("nlm_cancel_res", rqstp); 967 968 lock_answer(NLM_VERS, &arg->cookie, NULL, 0, arg->stat.stat); 969 970 return (NULL); 971} 972 973/* nlm_unlock_res ---------------------------------------------------------- */ 974/* 975 * Purpose: Accept result from earlier nlm_unlock_msg() call 976 * Returns: Nothing 977 */ 978void * 979nlm_unlock_res_1_svc(arg, rqstp) 980 nlm_res *arg; 981 struct svc_req *rqstp; 982{ 983 if (config.verbose) 984 log_from_addr("nlm_unlock_res", rqstp); 985 986 lock_answer(NLM_VERS, &arg->cookie, NULL, 0, arg->stat.stat); 987 988 return (NULL); 989} 990 991/* nlm_granted_res --------------------------------------------------------- */ 992/* 993 * Purpose: Accept result from earlier nlm_granted_msg() call 994 * Returns: Nothing 995 */ 996void * 997nlm_granted_res_1_svc(arg, rqstp) 998 nlm_res *arg; 999 struct svc_req *rqstp; 1000{ 1001 if (config.verbose) 1002 log_from_addr("nlm_granted_res", rqstp); 1003 /* need to undo lock if granted msg wasn't accepted! */ 1004 if (arg->stat.stat != nlm_granted) { 1005 nlm4_res arg4; 1006 arg4.cookie = arg->cookie; 1007 arg4.stat.stat = (nlm4_stats) arg->stat.stat; 1008 granted_failed(&arg4); 1009 } 1010 return (NULL); 1011} 1012 1013/* ------------------------------------------------------------------------- */ 1014/* 1015 * Calls for PCNFS locking (aka non-monitored locking, no involvement 1016 * of rpc.statd). 1017 * 1018 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here. 1019 */ 1020 1021/* nlm_share --------------------------------------------------------------- */ 1022/* 1023 * Purpose: Establish a DOS-style lock 1024 * Returns: success or failure 1025 * Notes: Blocking locks are not supported - client is expected 1026 * to retry if required. 1027 */ 1028nlm_shareres * 1029nlm_share_3_svc(arg, rqstp) 1030 nlm_shareargs *arg; 1031 struct svc_req *rqstp; 1032{ 1033 static nlm_shareres res; 1034 1035 if (config.verbose) 1036 log_from_addr("nlm_share", rqstp); 1037 1038 /* copy cookie from arg to result. See comment in nlm_test_1() */ 1039 res.cookie = arg->cookie; 1040 res.sequence = 0; /* X/Open says this field is ignored? */ 1041 1042 res.stat = (nlm_stats) getshare(arg, rqstp, 0); 1043 return (&res); 1044} 1045 1046/* nlm_unshare ------------------------------------------------------------ */ 1047/* 1048 * Purpose: Release a DOS-style lock 1049 * Returns: nlm_granted, unless in grace period 1050 * Notes: 1051 */ 1052nlm_shareres * 1053nlm_unshare_3_svc(arg, rqstp) 1054 nlm_shareargs *arg; 1055 struct svc_req *rqstp; 1056{ 1057 static nlm_shareres res; 1058 1059 if (config.verbose) 1060 log_from_addr("nlm_unshare", rqstp); 1061 1062 res.cookie = arg->cookie; 1063 res.sequence = 0; /* X/Open says this field is ignored? */ 1064 1065 res.stat = (nlm_stats) unshare(arg, rqstp, 0); 1066 return (&res); 1067} 1068 1069/* nlm_nm_lock ------------------------------------------------------------ */ 1070/* 1071 * Purpose: non-monitored version of nlm_lock() 1072 * Returns: as for nlm_lock() 1073 * Notes: These locks are in the same style as the standard nlm_lock, 1074 * but the rpc.statd should not be called to establish a 1075 * monitor for the client machine, since that machine is 1076 * declared not to be running a rpc.statd, and so would not 1077 * respond to the statd protocol. 1078 */ 1079nlm_res * 1080nlm_nm_lock_3_svc(arg, rqstp) 1081 nlm_lockargs *arg; 1082 struct svc_req *rqstp; 1083{ 1084 static nlm_res res; 1085 struct nlm4_lockargs arg4; 1086 nlmtonlm4(&arg->alock, &arg4.alock); 1087 arg4.cookie = arg->cookie; 1088 arg4.block = arg->block; 1089 arg4.exclusive = arg->exclusive; 1090 arg4.reclaim = arg->reclaim; 1091 arg4.state = arg->state; 1092 1093 if (config.verbose) 1094 log_from_addr("nlm_nm_lock", rqstp); 1095 1096 /* copy cookie from arg to result. See comment in nlm_test_1() */ 1097 res.cookie = arg->cookie; 1098 1099 res.stat.stat = (nlm_stats) getlock(&arg4, rqstp, 0); 1100 return (&res); 1101} 1102 1103/* nlm_free_all ------------------------------------------------------------ */ 1104/* 1105 * Purpose: Release all locks held by a named client 1106 * Returns: Nothing 1107 * Notes: Potential denial of service security problem here - the 1108 * locks to be released are specified by a host name, independent 1109 * of the address from which the request has arrived. 1110 * Should probably be rejected if the named host has been 1111 * using monitored locks. 1112 */ 1113void * 1114nlm_free_all_3_svc(arg, rqstp) 1115 nlm_notify *arg; 1116 struct svc_req *rqstp; 1117{ 1118 static char dummy; 1119 1120 if (config.verbose) 1121 log_from_addr("nlm_free_all", rqstp); 1122 1123 /* free all non-monitored locks/shares for specified host */ 1124 do_free_all(arg->name); 1125 1126 return (&dummy); 1127} 1128 1129/* calls for nlm version 4 (NFSv3) */ 1130/* nlm_test ---------------------------------------------------------------- */ 1131/* 1132 * Purpose: Test whether a specified lock would be granted if requested 1133 * Returns: nlm_granted (or error code) 1134 * Notes: 1135 */ 1136nlm4_testres * 1137nlm4_test_4_svc(arg, rqstp) 1138 nlm4_testargs *arg; 1139 struct svc_req *rqstp; 1140{ 1141 static nlm4_testres res; 1142 struct nlm4_holder *holder; 1143 1144 if (config.verbose) 1145 log_from_addr("nlm4_test", rqstp); 1146 if (config.verbose > 5) { 1147 syslog(LOG_DEBUG, "Locking arguments:\n"); 1148 log_netobj(&(arg->cookie)); 1149 syslog(LOG_DEBUG, "Alock arguments:\n"); 1150 syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name); 1151 syslog(LOG_DEBUG, "File Handle:\n"); 1152 log_netobj(&(arg->alock.fh)); 1153 syslog(LOG_DEBUG, "Owner Handle:\n"); 1154 log_netobj(&(arg->alock.oh)); 1155 syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid); 1156 syslog(LOG_DEBUG, "Lock Offset: %llu\n", 1157 (unsigned long long)arg->alock.l_offset); 1158 syslog(LOG_DEBUG, "Lock Length: %llu\n", 1159 (unsigned long long)arg->alock.l_len); 1160 syslog(LOG_DEBUG, "Exclusive: %s\n", 1161 (arg->exclusive ? "true" : "false")); 1162 } 1163 1164 holder = testlock(&arg->alock, arg->exclusive, LOCK_V4); 1165 1166 /* 1167 * Copy the cookie from the argument into the result. Note that this 1168 * is slightly hazardous, as the structure contains a pointer to a 1169 * malloc()ed buffer that will get freed by the caller. However, the 1170 * main function transmits the result before freeing the argument 1171 * so it is in fact safe. 1172 */ 1173 res.cookie = arg->cookie; 1174 if (holder == NULL) { 1175 res.stat.stat = nlm4_granted; 1176 } else { 1177 res.stat.stat = nlm4_denied; 1178 memcpy(&res.stat.nlm4_testrply_u.holder, holder, 1179 sizeof(struct nlm4_holder)); 1180 } 1181 return (&res); 1182} 1183 1184void * 1185nlm4_test_msg_4_svc(arg, rqstp) 1186 nlm4_testargs *arg; 1187 struct svc_req *rqstp; 1188{ 1189 nlm4_testres res; 1190 static char dummy; 1191 CLIENT *cli; 1192 int success; 1193 struct timeval timeo; 1194 struct nlm4_holder *holder; 1195 1196 if (config.verbose) 1197 log_from_addr("nlm4_test_msg", rqstp); 1198 1199 holder = testlock(&arg->alock, arg->exclusive, LOCK_V4); 1200 1201 res.cookie = arg->cookie; 1202 if (holder == NULL) { 1203 res.stat.stat = nlm4_granted; 1204 } else { 1205 res.stat.stat = nlm4_denied; 1206 memcpy(&res.stat.nlm4_testrply_u.holder, holder, 1207 sizeof(struct nlm4_holder)); 1208 } 1209 1210 /* 1211 * nlm_test has different result type to the other operations, so 1212 * can't use transmit4_result() in this case 1213 */ 1214 if ((cli = get_client(svc_getcaller_sa(rqstp->rq_xprt), NLM_VERS4, 0, 0)) != NULL) { 1215 timeo.tv_sec = 0; /* No timeout - not expecting response */ 1216 timeo.tv_usec = 0; 1217 1218 success = clnt_call(cli, NLM4_TEST_RES, (xdrproc_t)xdr_nlm4_testres, 1219 &res, (xdrproc_t)xdr_void, &dummy, timeo); 1220 1221 if (config.verbose > 2) 1222 syslog(LOG_DEBUG, "clnt_call returns %d", success); 1223 } 1224 return (NULL); 1225} 1226 1227/* nlm_lock ---------------------------------------------------------------- */ 1228/* 1229 * Purposes: Establish a lock 1230 * Returns: granted, denied or blocked 1231 * Notes: *** grace period support missing 1232 */ 1233nlm4_res * 1234nlm4_lock_4_svc(arg, rqstp) 1235 nlm4_lockargs *arg; 1236 struct svc_req *rqstp; 1237{ 1238 static nlm4_res res; 1239 1240 if (config.verbose) 1241 log_from_addr("nlm4_lock", rqstp); 1242 if (config.verbose > 5) { 1243 syslog(LOG_DEBUG, "Locking arguments:\n"); 1244 log_netobj(&(arg->cookie)); 1245 syslog(LOG_DEBUG, "Alock arguments:\n"); 1246 syslog(LOG_DEBUG, "Caller Name: %s\n",arg->alock.caller_name); 1247 syslog(LOG_DEBUG, "File Handle:\n"); 1248 log_netobj(&(arg->alock.fh)); 1249 syslog(LOG_DEBUG, "Owner Handle:\n"); 1250 log_netobj(&(arg->alock.oh)); 1251 syslog(LOG_DEBUG, "SVID: %d\n", arg->alock.svid); 1252 syslog(LOG_DEBUG, "Lock Offset: %llu\n", 1253 (unsigned long long)arg->alock.l_offset); 1254 syslog(LOG_DEBUG, "Lock Length: %llu\n", 1255 (unsigned long long)arg->alock.l_len); 1256 syslog(LOG_DEBUG, "Block: %s\n", (arg->block ? "true" : "false")); 1257 syslog(LOG_DEBUG, "Exclusive: %s\n", (arg->exclusive ? "true" : "false")); 1258 syslog(LOG_DEBUG, "Reclaim: %s\n", (arg->reclaim ? "true" : "false")); 1259 syslog(LOG_DEBUG, "State num: %d\n", arg->state); 1260 } 1261 1262 /* copy cookie from arg to result. See comment in nlm_test_4() */ 1263 res.cookie = arg->cookie; 1264 1265 res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_V4); 1266 return (&res); 1267} 1268 1269void * 1270nlm4_lock_msg_4_svc(arg, rqstp) 1271 nlm4_lockargs *arg; 1272 struct svc_req *rqstp; 1273{ 1274 static nlm4_res res; 1275 1276 if (config.verbose) 1277 log_from_addr("nlm4_lock_msg", rqstp); 1278 1279 res.cookie = arg->cookie; 1280 res.stat.stat = getlock(arg, rqstp, LOCK_MON | LOCK_ASYNC | LOCK_V4); 1281 if (transmit4_result(NLM4_LOCK_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 0) < 0) { 1282 /* if res.stat.stat was success/blocked, then unlock/cancel */ 1283 if (res.stat.stat == nlm4_granted) 1284 unlock(&arg->alock, LOCK_V4); 1285 else if (res.stat.stat == nlm4_blocked) { 1286 nlm4_cancargs carg; 1287 carg.cookie = arg->cookie; 1288 carg.block = arg->block; 1289 carg.exclusive = arg->exclusive; 1290 carg.alock = arg->alock; 1291 cancellock(&carg, LOCK_V4); 1292 } 1293 } 1294 1295 return (NULL); 1296} 1297 1298/* nlm_cancel -------------------------------------------------------------- */ 1299/* 1300 * Purpose: Cancel a blocked lock request 1301 * Returns: granted or denied 1302 * Notes: 1303 */ 1304nlm4_res * 1305nlm4_cancel_4_svc(arg, rqstp) 1306 nlm4_cancargs *arg; 1307 struct svc_req *rqstp; 1308{ 1309 static nlm4_res res; 1310 1311 if (config.verbose) 1312 log_from_addr("nlm4_cancel", rqstp); 1313 1314 /* copy cookie from arg to result. See comment in nlm_test_1() */ 1315 res.cookie = arg->cookie; 1316 1317 res.stat.stat = cancellock(arg, LOCK_V4); 1318 return (&res); 1319} 1320 1321void * 1322nlm4_cancel_msg_4_svc(arg, rqstp) 1323 nlm4_cancargs *arg; 1324 struct svc_req *rqstp; 1325{ 1326 static nlm4_res res; 1327 1328 if (config.verbose) 1329 log_from_addr("nlm4_cancel_msg", rqstp); 1330 1331 res.cookie = arg->cookie; 1332 res.stat.stat = cancellock(arg, LOCK_V4); 1333 if (transmit4_result(NLM4_CANCEL_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 0) < 0) { 1334 /* XXX do we need to (un)do anything if this fails? */ 1335 } 1336 return (NULL); 1337} 1338 1339/* nlm_unlock -------------------------------------------------------------- */ 1340/* 1341 * Purpose: Release an existing lock 1342 * Returns: Always granted, unless during grace period 1343 * Notes: "no such lock" error condition is ignored, as the 1344 * protocol uses unreliable UDP datagrams, and may well 1345 * re-try an unlock that has already succeeded. 1346 */ 1347nlm4_res * 1348nlm4_unlock_4_svc(arg, rqstp) 1349 nlm4_unlockargs *arg; 1350 struct svc_req *rqstp; 1351{ 1352 static nlm4_res res; 1353 1354 if (config.verbose) 1355 log_from_addr("nlm4_unlock", rqstp); 1356 1357 res.stat.stat = unlock(&arg->alock, LOCK_V4); 1358 res.cookie = arg->cookie; 1359 1360 return (&res); 1361} 1362 1363void * 1364nlm4_unlock_msg_4_svc(arg, rqstp) 1365 nlm4_unlockargs *arg; 1366 struct svc_req *rqstp; 1367{ 1368 static nlm4_res res; 1369 1370 if (config.verbose) 1371 log_from_addr("nlm4_unlock_msg", rqstp); 1372 1373 res.stat.stat = unlock(&arg->alock, LOCK_V4); 1374 res.cookie = arg->cookie; 1375 1376 if (transmit4_result(NLM4_UNLOCK_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 0) < 0) { 1377 /* XXX do we need to (un)do anything if this fails? */ 1378 } 1379 return (NULL); 1380} 1381 1382/* ------------------------------------------------------------------------- */ 1383/* 1384 * Client-side pseudo-RPCs for results. Note that for the client there 1385 * are only nlm_xxx_msg() versions of each call, since the 'real RPC' 1386 * version returns the results in the RPC result, and so the client 1387 * does not normally receive incoming RPCs. 1388 * 1389 * The exception to this is nlm_granted(), which is genuinely an RPC 1390 * call from the server to the client - a 'call-back' in normal procedure 1391 * call terms. 1392 */ 1393 1394/* nlm_granted ------------------------------------------------------------- */ 1395/* 1396 * Purpose: Receive notification that formerly blocked lock now granted 1397 * Returns: always success ('granted') 1398 * Notes: 1399 */ 1400nlm4_res * 1401nlm4_granted_4_svc(arg, rqstp) 1402 nlm4_testargs *arg; 1403 struct svc_req *rqstp; 1404{ 1405 static nlm4_res res; 1406 int flags; 1407 1408 if (config.verbose) 1409 log_from_addr("nlm4_granted", rqstp); 1410 1411 flags = LOCK_ANSWER_GRANTED; 1412 if (arg->exclusive) 1413 flags |= LOCK_ANSWER_LOCK_EXCL; 1414 1415 if (lock_answer(NLM_VERS4, &arg->cookie, &arg->alock, flags, nlm4_granted)) 1416 res.stat.stat = nlm4_denied; 1417 else 1418 res.stat.stat = nlm4_granted; 1419 1420 /* copy cookie from arg to result. See comment in nlm_test_1() */ 1421 res.cookie = arg->cookie; 1422 1423 return (&res); 1424} 1425 1426void * 1427nlm4_granted_msg_4_svc(arg, rqstp) 1428 nlm4_testargs *arg; 1429 struct svc_req *rqstp; 1430{ 1431 static nlm4_res res; 1432 int flags; 1433 1434 if (config.verbose) 1435 log_from_addr("nlm4_granted_msg", rqstp); 1436 1437 flags = LOCK_ANSWER_GRANTED; 1438 if (arg->exclusive) 1439 flags |= LOCK_ANSWER_LOCK_EXCL; 1440 1441 if (lock_answer(NLM_VERS4, &arg->cookie, &arg->alock, flags, nlm4_granted)) 1442 res.stat.stat = nlm4_denied; 1443 else 1444 res.stat.stat = nlm4_granted; 1445 1446 res.cookie = arg->cookie; 1447 1448 if (transmit4_result(NLM4_GRANTED_RES, &res, svc_getcaller_sa(rqstp->rq_xprt), 1) < 0) { 1449 /* XXX do we need to (un)do anything if this fails? */ 1450 } 1451 return (NULL); 1452} 1453 1454/* nlm_test_res ------------------------------------------------------------ */ 1455/* 1456 * Purpose: Accept result from earlier nlm_test_msg() call 1457 * Returns: Nothing 1458 */ 1459void * 1460nlm4_test_res_4_svc(arg, rqstp) 1461 nlm4_testres *arg; 1462 struct svc_req *rqstp; 1463{ 1464 nlm4_lock lock4; 1465 int flags = 0; 1466 1467 if (config.verbose) 1468 log_from_addr("nlm4_test_res", rqstp); 1469 1470 if (arg->stat.stat == nlm4_denied) { 1471 lock4.fh.n_len = 0; 1472 lock4.svid = arg->stat.nlm4_testrply_u.holder.svid; 1473 lock4.l_offset = arg->stat.nlm4_testrply_u.holder.l_offset; 1474 lock4.l_len = arg->stat.nlm4_testrply_u.holder.l_len; 1475 if (arg->stat.nlm4_testrply_u.holder.exclusive) 1476 flags |= LOCK_ANSWER_LOCK_EXCL; 1477 lock_answer(NLM_VERS4, &arg->cookie, &lock4, flags, arg->stat.stat); 1478 } else 1479 lock_answer(NLM_VERS4, &arg->cookie, NULL, 0, arg->stat.stat); 1480 1481 return (NULL); 1482} 1483 1484/* nlm_lock_res ------------------------------------------------------------ */ 1485/* 1486 * Purpose: Accept result from earlier nlm_lock_msg() call 1487 * Returns: Nothing 1488 */ 1489void * 1490nlm4_lock_res_4_svc(arg, rqstp) 1491 nlm4_res *arg; 1492 struct svc_req *rqstp; 1493{ 1494 if (config.verbose) 1495 log_from_addr("nlm4_lock_res", rqstp); 1496 1497 lock_answer(NLM_VERS4, &arg->cookie, NULL, 0, arg->stat.stat); 1498 1499 return (NULL); 1500} 1501 1502/* nlm_cancel_res ---------------------------------------------------------- */ 1503/* 1504 * Purpose: Accept result from earlier nlm_cancel_msg() call 1505 * Returns: Nothing 1506 */ 1507void * 1508nlm4_cancel_res_4_svc(arg, rqstp) 1509 nlm4_res *arg; 1510 struct svc_req *rqstp; 1511{ 1512 if (config.verbose) 1513 log_from_addr("nlm4_cancel_res", rqstp); 1514 1515 lock_answer(NLM_VERS4, &arg->cookie, NULL, 0, arg->stat.stat); 1516 1517 return (NULL); 1518} 1519 1520/* nlm_unlock_res ---------------------------------------------------------- */ 1521/* 1522 * Purpose: Accept result from earlier nlm_unlock_msg() call 1523 * Returns: Nothing 1524 */ 1525void * 1526nlm4_unlock_res_4_svc(arg, rqstp) 1527 nlm4_res *arg __unused; 1528 struct svc_req *rqstp; 1529{ 1530 if (config.verbose) 1531 log_from_addr("nlm4_unlock_res", rqstp); 1532 1533 lock_answer(NLM_VERS4, &arg->cookie, NULL, 0, arg->stat.stat); 1534 1535 return (NULL); 1536} 1537 1538/* nlm_granted_res --------------------------------------------------------- */ 1539/* 1540 * Purpose: Accept result from earlier nlm_granted_msg() call 1541 * Returns: Nothing 1542 */ 1543void * 1544nlm4_granted_res_4_svc(arg, rqstp) 1545 nlm4_res *arg __unused; 1546 struct svc_req *rqstp; 1547{ 1548 if (config.verbose) 1549 log_from_addr("nlm4_granted_res", rqstp); 1550 /* need to undo lock if granted msg wasn't accepted! */ 1551 if (arg->stat.stat != nlm4_granted) 1552 granted_failed(arg); 1553 return (NULL); 1554} 1555 1556/* ------------------------------------------------------------------------- */ 1557/* 1558 * Calls for PCNFS locking (aka non-monitored locking, no involvement 1559 * of rpc.statd). 1560 * 1561 * These are all genuine RPCs - no nlm_xxx_msg() nonsense here. 1562 */ 1563 1564/* nlm_share --------------------------------------------------------------- */ 1565/* 1566 * Purpose: Establish a DOS-style lock 1567 * Returns: success or failure 1568 * Notes: Blocking locks are not supported - client is expected 1569 * to retry if required. 1570 */ 1571nlm4_shareres * 1572nlm4_share_4_svc(arg, rqstp) 1573 nlm4_shareargs *arg; 1574 struct svc_req *rqstp; 1575{ 1576 static nlm4_shareres res; 1577 1578 if (config.verbose) 1579 log_from_addr("nlm4_share", rqstp); 1580 1581 res.cookie = arg->cookie; 1582 res.sequence = 0; /* X/Open says this field is ignored? */ 1583 1584 res.stat = getshare((nlm_shareargs*)arg, rqstp, LOCK_V4); 1585 return (&res); 1586} 1587 1588/* nlm4_unshare ------------------------------------------------------------ */ 1589/* 1590 * Purpose: Release a DOS-style lock 1591 * Returns: nlm_granted, unless in grace period 1592 * Notes: 1593 */ 1594nlm4_shareres * 1595nlm4_unshare_4_svc(arg, rqstp) 1596 nlm4_shareargs *arg; 1597 struct svc_req *rqstp; 1598{ 1599 static nlm4_shareres res; 1600 1601 if (config.verbose) 1602 log_from_addr("nlm4_unshare", rqstp); 1603 1604 res.cookie = arg->cookie; 1605 res.sequence = 0; /* X/Open says this field is ignored? */ 1606 1607 res.stat = unshare((nlm_shareargs*)arg, rqstp, LOCK_V4); 1608 return (&res); 1609} 1610 1611/* nlm4_nm_lock ------------------------------------------------------------ */ 1612/* 1613 * Purpose: non-monitored version of nlm4_lock() 1614 * Returns: as for nlm4_lock() 1615 * Notes: These locks are in the same style as the standard nlm4_lock, 1616 * but the rpc.statd should not be called to establish a 1617 * monitor for the client machine, since that machine is 1618 * declared not to be running a rpc.statd, and so would not 1619 * respond to the statd protocol. 1620 */ 1621nlm4_res * 1622nlm4_nm_lock_4_svc(arg, rqstp) 1623 nlm4_lockargs *arg; 1624 struct svc_req *rqstp; 1625{ 1626 static nlm4_res res; 1627 1628 if (config.verbose) 1629 log_from_addr("nlm4_nm_lock", rqstp); 1630 1631 /* copy cookie from arg to result. See comment in nlm_test_4() */ 1632 res.cookie = arg->cookie; 1633 1634 res.stat.stat = getlock(arg, rqstp, LOCK_V4); 1635 return (&res); 1636} 1637 1638/* nlm4_free_all ------------------------------------------------------------ */ 1639/* 1640 * Purpose: Release all locks held by a named client 1641 * Returns: Nothing 1642 * Notes: Potential denial of service security problem here - the 1643 * locks to be released are specified by a host name, independent 1644 * of the address from which the request has arrived. 1645 * Should probably be rejected if the named host has been 1646 * using monitored locks. 1647 */ 1648void * 1649nlm4_free_all_4_svc(arg, rqstp) 1650 struct nlm4_notify *arg; 1651 struct svc_req *rqstp; 1652{ 1653 static char dummy; 1654 1655 if (config.verbose) 1656 log_from_addr("nlm4_free_all", rqstp); 1657 1658 /* free all non-monitored locks/shares for specified host */ 1659 do_free_all(arg->name); 1660 1661 return (&dummy); 1662} 1663 1664/* nlm_sm_notify --------------------------------------------------------- */ 1665/* 1666 * Purpose: called by rpc.statd when a monitored host state changes. 1667 * Returns: Nothing 1668 */ 1669void * 1670nlm_sm_notify_0_svc(arg, rqstp) 1671 struct nlm_sm_status *arg; 1672 struct svc_req *rqstp __unused; 1673{ 1674 static char dummy; 1675 notify(arg->mon_name, arg->state); 1676 return (&dummy); 1677} 1678