GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/rpc.lockd/procs.c Lines: 0 314 0.0 %
Date: 2017-11-13 Branches: 0 122 0.0 %

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