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