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