kern.c revision 101947
1251881Speter/*-
2251881Speter * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
3251881Speter *
4251881Speter * Redistribution and use in source and binary forms, with or without
5251881Speter * modification, are permitted provided that the following conditions
6251881Speter * are met:
7251881Speter * 1. Redistributions of source code must retain the above copyright
8251881Speter *    notice, this list of conditions and the following disclaimer.
9251881Speter * 2. Redistributions in binary form must reproduce the above copyright
10251881Speter *    notice, this list of conditions and the following disclaimer in the
11251881Speter *    documentation and/or other materials provided with the distribution.
12251881Speter * 3. Berkeley Software Design Inc's name may not be used to endorse or
13251881Speter *    promote products derived from this software without specific prior
14251881Speter *    written permission.
15251881Speter *
16251881Speter * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND
17251881Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18251881Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19251881Speter * ARE DISCLAIMED.  IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE
20251881Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21251881Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22251881Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23251881Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24251881Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25251881Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26251881Speter * SUCH DAMAGE.
27251881Speter *
28251881Speter *      from BSDI kern.c,v 1.2 1998/11/25 22:38:27 don Exp
29251881Speter * $FreeBSD: head/usr.sbin/rpc.lockd/kern.c 101947 2002-08-15 21:52:22Z alfred $
30251881Speter */
31251881Speter
32251881Speter#include <sys/param.h>
33251881Speter#include <sys/mount.h>
34251881Speter#include <sys/queue.h>
35251881Speter#include <sys/socket.h>
36251881Speter#include <sys/stat.h>
37251881Speter
38251881Speter#include <netinet/in.h>
39251881Speter#include <arpa/inet.h>
40251881Speter
41251881Speter#include <err.h>
42251881Speter#include <errno.h>
43251881Speter#include <fcntl.h>
44251881Speter#include <pwd.h>
45251881Speter#include <stdio.h>
46251881Speter#include <stdlib.h>
47251881Speter#include <string.h>
48251881Speter#include <syslog.h>
49251881Speter#include <unistd.h>
50251881Speter#include <netdb.h>
51251881Speter
52251881Speter#include "nlm_prot.h"
53251881Speter#include <nfs/rpcv2.h>
54251881Speter#include <nfs/nfsproto.h>
55251881Speter#include <nfsclient/nfs_lock.h>
56251881Speter
57251881Speter#include "lockd.h"
58251881Speter#include "lockd_lock.h"
59251881Speter#include <nfsclient/nfs.h>
60251881Speter
61251881Speter#define DAEMON_USERNAME	"daemon"
62251881Speter
63251881Speter#define nfslockdans(_v, _ansp)	\
64251881Speter	((_ansp)->la_vers = _v, \
65251881Speter	nfsclnt(NFSCLNT_LOCKDANS, _ansp))
66251881Speter
67251881Speter/* Lock request owner. */
68251881Spetertypedef struct __owner {
69251881Speter	pid_t	 pid;				/* Process ID. */
70251881Speter	time_t	 tod;				/* Time-of-day. */
71251881Speter} OWNER;
72251881Speterstatic OWNER owner;
73251881Speter
74251881Speterstatic char hostname[MAXHOSTNAMELEN + 1];	/* Hostname. */
75251881Speter
76251881Speterstatic void	client_cleanup(void);
77251881Speterstatic void	set_auth(CLIENT *cl, struct xucred *ucred);
78251881Speterint	lock_request(LOCKD_MSG *);
79251881Speterint	test_request(LOCKD_MSG *);
80251881Spetervoid	show(LOCKD_MSG *);
81251881Speterint	unlock_request(LOCKD_MSG *);
82251881Speter
83251881Speter/*
84251881Speter * will break because fifo needs to be repopened when EOF'd
85251881Speter */
86251881Speter#define lockd_seteuid(uid)	seteuid(uid)
87251881Speter
88251881Speter#define d_calls (debug_level > 1)
89251881Speter#define d_args (debug_level > 2)
90251881Speter
91251881Speterstatic const char *
92251881Speterfrom_addr(saddr)
93251881Speter	struct sockaddr *saddr;
94251881Speter{
95251881Speter	static char inet_buf[INET6_ADDRSTRLEN];
96251881Speter
97251881Speter	if (getnameinfo(saddr, saddr->sa_len, inet_buf, sizeof(inet_buf),
98251881Speter			NULL, 0, NI_NUMERICHOST) == 0)
99251881Speter		return inet_buf;
100251881Speter	return "???";
101251881Speter}
102251881Speter
103251881Spetervoid
104251881Speterclient_cleanup(void)
105251881Speter{
106251881Speter	(void)lockd_seteuid(0);
107251881Speter	(void)unlink(_PATH_LCKFIFO);
108251881Speter	exit(-1);
109251881Speter}
110251881Speter
111251881Speter/*
112251881Speter * client_request --
113251881Speter *	Loop around messages from the kernel, forwarding them off to
114251881Speter *	NLM servers.
115251881Speter */
116251881Speterpid_t
117251881Speterclient_request(void)
118251881Speter{
119251881Speter	LOCKD_MSG msg;
120251881Speter	fd_set rdset;
121251881Speter	int fd, nr, ret;
122251881Speter	pid_t child;
123251881Speter	uid_t daemon_uid;
124251881Speter	mode_t old_umask;
125251881Speter	struct passwd *pw;
126251881Speter
127251881Speter	/* Recreate the NLM fifo. */
128251881Speter	(void)unlink(_PATH_LCKFIFO);
129251881Speter	old_umask = umask(S_IXGRP|S_IXOTH);
130251881Speter	if (mkfifo(_PATH_LCKFIFO, S_IWUSR | S_IRUSR)) {
131251881Speter		syslog(LOG_ERR, "mkfifo: %s: %m", _PATH_LCKFIFO);
132251881Speter		exit (1);
133251881Speter	}
134251881Speter	umask(old_umask);
135251881Speter
136251881Speter	/*
137251881Speter	 * Create a separate process, the client code is really a separate
138251881Speter	 * daemon that shares a lot of code.
139251881Speter	 */
140251881Speter	switch (child = fork()) {
141251881Speter	case -1:
142251881Speter		err(1, "fork");
143251881Speter	case 0:
144251881Speter		break;
145251881Speter	default:
146251881Speter		return (child);
147251881Speter	}
148251881Speter
149251881Speter	signal(SIGHUP, (sig_t)client_cleanup);
150251881Speter	signal(SIGTERM, (sig_t)client_cleanup);
151251881Speter
152251881Speter	/* Setup. */
153251881Speter	(void)time(&owner.tod);
154251881Speter	owner.pid = getpid();
155251881Speter	(void)gethostname(hostname, sizeof(hostname) - 1);
156251881Speter
157251881Speter	/* Open the fifo for reading. */
158251881Speter	if ((fd = open(_PATH_LCKFIFO, O_RDONLY | O_NONBLOCK)) == -1) {
159251881Speter		syslog(LOG_ERR, "open: %s: %m", _PATH_LCKFIFO);
160251881Speter		goto err;
161251881Speter	}
162251881Speter	pw = getpwnam(DAEMON_USERNAME);
163251881Speter	if (pw == NULL) {
164251881Speter		syslog(LOG_ERR, "getpwnam: %s: %m", DAEMON_USERNAME);
165251881Speter		goto err;
166251881Speter	}
167251881Speter	daemon_uid = pw->pw_uid;
168251881Speter	/* drop our root priviledges */
169251881Speter	(void)lockd_seteuid(daemon_uid);
170251881Speter
171251881Speter	for (;;) {
172251881Speter		/* Wait for contact... fifo's return EAGAIN when read with
173251881Speter		 * no data
174251881Speter		 */
175251881Speter		/* Set up the select. */
176251881Speter		FD_ZERO(&rdset);
177251881Speter		FD_SET(fd, &rdset);
178251881Speter		(void)select(fd + 1, &rdset, NULL, NULL, NULL);
179251881Speter
180251881Speter		/* Read the fixed length message. */
181251881Speter		if ((nr = read(fd, &msg, sizeof(msg))) == sizeof(msg)) {
182251881Speter			if (d_args)
183251881Speter				show(&msg);
184251881Speter
185251881Speter			if (msg.lm_version != LOCKD_MSG_VERSION) {
186251881Speter				syslog(LOG_ERR,
187251881Speter				    "unknown msg type: %d", msg.lm_version);
188251881Speter			}
189251881Speter			/*
190251881Speter			 * Send it to the NLM server and don't grant the lock
191251881Speter			 * if we fail for any reason.
192251881Speter			 */
193251881Speter			switch (msg.lm_fl.l_type) {
194251881Speter			case F_RDLCK:
195251881Speter			case F_WRLCK:
196251881Speter				if (msg.lm_getlk)
197251881Speter					ret = test_request(&msg);
198251881Speter				else
199251881Speter					ret = lock_request(&msg);
200251881Speter				break;
201251881Speter			case F_UNLCK:
202251881Speter				ret = unlock_request(&msg);
203251881Speter				break;
204251881Speter			default:
205251881Speter				ret = 1;
206251881Speter				syslog(LOG_ERR,
207251881Speter				    "unknown lock type: %d", msg.lm_fl.l_type);
208251881Speter				break;
209251881Speter			}
210251881Speter			if (ret) {
211251881Speter				struct lockd_ans ans;
212251881Speter
213251881Speter				ans.la_msg_ident = msg.lm_msg_ident;
214251881Speter				ans.la_errno = EHOSTUNREACH;
215251881Speter
216251881Speter				if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
217251881Speter					syslog((errno == EPIPE ? LOG_INFO :
218251881Speter						LOG_ERR), "process %lu: %m",
219251881Speter						(u_long)msg.lm_msg_ident.pid);
220251881Speter				}
221251881Speter			}
222251881Speter		} else if (nr == -1) {
223251881Speter			if (errno != EAGAIN) {
224251881Speter				syslog(LOG_ERR, "read: %s: %m", _PATH_LCKFIFO);
225251881Speter				goto err;
226251881Speter			}
227251881Speter		} else if (nr != 0) {
228251881Speter			syslog(LOG_ERR,
229251881Speter			    "%s: discard %d bytes", _PATH_LCKFIFO, nr);
230251881Speter		}
231251881Speter	}
232251881Speter
233251881Speter	/* Reached only on error. */
234251881Spetererr:
235251881Speter	(void)lockd_seteuid(0);
236251881Speter	(void)unlink(_PATH_LCKFIFO);
237251881Speter	_exit (1);
238251881Speter}
239251881Speter
240251881Spetervoid
241251881Speterset_auth(cl, xucred)
242251881Speter	CLIENT *cl;
243251881Speter	struct xucred *xucred;
244251881Speter{
245251881Speter        if (cl->cl_auth != NULL)
246251881Speter                cl->cl_auth->ah_ops->ah_destroy(cl->cl_auth);
247251881Speter        cl->cl_auth = authunix_create(hostname,
248251881Speter                        xucred->cr_uid,
249251881Speter                        xucred->cr_groups[0],
250251881Speter                        xucred->cr_ngroups - 1,
251251881Speter                        &xucred->cr_groups[1]);
252251881Speter}
253251881Speter
254251881Speter
255251881Speter/*
256251881Speter * test_request --
257251881Speter *	Convert a lock LOCKD_MSG into an NLM request, and send it off.
258251881Speter */
259251881Speterint
260251881Spetertest_request(LOCKD_MSG *msg)
261251881Speter{
262251881Speter	CLIENT *cli;
263251881Speter	struct timeval timeout = {0, 0};	/* No timeout, no response. */
264251881Speter	char dummy;
265251881Speter
266251881Speter	if (d_calls)
267251881Speter		syslog(LOG_DEBUG, "test request: %s: %s to %s",
268251881Speter		    msg->lm_nfsv3 ? "V4" : "V1/3",
269251881Speter		    msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
270251881Speter		    from_addr((struct sockaddr *)&msg->lm_addr));
271251881Speter
272251881Speter	if (msg->lm_nfsv3) {
273251881Speter		struct nlm4_testargs arg4;
274251881Speter
275251881Speter		arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident;
276251881Speter		arg4.cookie.n_len = sizeof(msg->lm_msg_ident);
277251881Speter		arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
278251881Speter		arg4.alock.caller_name = hostname;
279251881Speter		arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
280251881Speter		arg4.alock.fh.n_len = msg->lm_fh_len;
281251881Speter		arg4.alock.oh.n_bytes = (char *)&owner;
282251881Speter		arg4.alock.oh.n_len = sizeof(owner);
283251881Speter		arg4.alock.svid = msg->lm_msg_ident.pid;
284251881Speter		arg4.alock.l_offset = msg->lm_fl.l_start;
285251881Speter		arg4.alock.l_len = msg->lm_fl.l_len;
286251881Speter
287251881Speter		if ((cli = get_client(
288251881Speter		    (struct sockaddr *)&msg->lm_addr,
289251881Speter		    NLM_VERS4)) == NULL)
290251881Speter			return (1);
291251881Speter
292251881Speter		set_auth(cli, &msg->lm_cred);
293251881Speter		(void)clnt_call(cli, NLM_TEST_MSG,
294251881Speter		    xdr_nlm4_testargs, &arg4, xdr_void, &dummy, timeout);
295251881Speter	} else {
296251881Speter		struct nlm_testargs arg;
297251881Speter
298251881Speter		arg.cookie.n_bytes = (char *)&msg->lm_msg_ident;
299251881Speter		arg.cookie.n_len = sizeof(msg->lm_msg_ident);
300251881Speter		arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
301251881Speter		arg.alock.caller_name = hostname;
302251881Speter		arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
303251881Speter		arg.alock.fh.n_len = msg->lm_fh_len;
304251881Speter		arg.alock.oh.n_bytes = (char *)&owner;
305251881Speter		arg.alock.oh.n_len = sizeof(owner);
306251881Speter		arg.alock.svid = msg->lm_msg_ident.pid;
307251881Speter		arg.alock.l_offset = msg->lm_fl.l_start;
308251881Speter		arg.alock.l_len = msg->lm_fl.l_len;
309251881Speter
310251881Speter		if ((cli = get_client(
311251881Speter		    (struct sockaddr *)&msg->lm_addr,
312251881Speter		    NLM_VERS)) == NULL)
313251881Speter			return (1);
314251881Speter
315251881Speter		set_auth(cli, &msg->lm_cred);
316251881Speter		(void)clnt_call(cli, NLM_TEST_MSG,
317251881Speter		    xdr_nlm_testargs, &arg, xdr_void, &dummy, timeout);
318251881Speter	}
319251881Speter	return (0);
320251881Speter}
321251881Speter
322251881Speter/*
323251881Speter * lock_request --
324251881Speter *	Convert a lock LOCKD_MSG into an NLM request, and send it off.
325251881Speter */
326251881Speterint
327251881Speterlock_request(LOCKD_MSG *msg)
328251881Speter{
329251881Speter	CLIENT *cli;
330251881Speter	struct nlm4_lockargs arg4;
331251881Speter	struct nlm_lockargs arg;
332251881Speter	struct timeval timeout = {0, 0};	/* No timeout, no response. */
333251881Speter	char dummy;
334251881Speter
335251881Speter	if (d_calls)
336251881Speter		syslog(LOG_DEBUG, "lock request: %s: %s to %s",
337251881Speter		    msg->lm_nfsv3 ? "V4" : "V1/3",
338251881Speter		    msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
339251881Speter		    from_addr((struct sockaddr *)&msg->lm_addr));
340251881Speter
341251881Speter	if (msg->lm_nfsv3) {
342251881Speter		arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident;
343251881Speter		arg4.cookie.n_len = sizeof(msg->lm_msg_ident);
344251881Speter		arg4.block = msg->lm_wait ? 1 : 0;
345251881Speter		arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
346251881Speter		arg4.alock.caller_name = hostname;
347251881Speter		arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
348251881Speter		arg4.alock.fh.n_len = msg->lm_fh_len;
349251881Speter		arg4.alock.oh.n_bytes = (char *)&owner;
350251881Speter		arg4.alock.oh.n_len = sizeof(owner);
351251881Speter		arg4.alock.svid = msg->lm_msg_ident.pid;
352251881Speter		arg4.alock.l_offset = msg->lm_fl.l_start;
353251881Speter		arg4.alock.l_len = msg->lm_fl.l_len;
354251881Speter		arg4.reclaim = 0;
355251881Speter		arg4.state = nsm_state;
356251881Speter
357251881Speter		if ((cli = get_client(
358251881Speter		    (struct sockaddr *)&msg->lm_addr,
359251881Speter		    NLM_VERS4)) == NULL)
360251881Speter			return (1);
361251881Speter
362251881Speter		set_auth(cli, &msg->lm_cred);
363251881Speter		(void)clnt_call(cli, NLM_LOCK_MSG,
364251881Speter		    xdr_nlm4_lockargs, &arg4, xdr_void, &dummy, timeout);
365251881Speter	} else {
366251881Speter		arg.cookie.n_bytes = (char *)&msg->lm_msg_ident;
367251881Speter		arg.cookie.n_len = sizeof(msg->lm_msg_ident);
368251881Speter		arg.block = msg->lm_wait ? 1 : 0;
369251881Speter		arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
370251881Speter		arg.alock.caller_name = hostname;
371251881Speter		arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
372251881Speter		arg.alock.fh.n_len = msg->lm_fh_len;
373251881Speter		arg.alock.oh.n_bytes = (char *)&owner;
374251881Speter		arg.alock.oh.n_len = sizeof(owner);
375251881Speter		arg.alock.svid = msg->lm_msg_ident.pid;
376251881Speter		arg.alock.l_offset = msg->lm_fl.l_start;
377251881Speter		arg.alock.l_len = msg->lm_fl.l_len;
378251881Speter		arg.reclaim = 0;
379251881Speter		arg.state = nsm_state;
380251881Speter
381251881Speter		if ((cli = get_client(
382251881Speter		    (struct sockaddr *)&msg->lm_addr,
383251881Speter		    NLM_VERS)) == NULL)
384251881Speter			return (1);
385251881Speter
386251881Speter		set_auth(cli, &msg->lm_cred);
387251881Speter		(void)clnt_call(cli, NLM_LOCK_MSG,
388251881Speter		    xdr_nlm_lockargs, &arg, xdr_void, &dummy, timeout);
389251881Speter	}
390251881Speter	return (0);
391251881Speter}
392251881Speter
393251881Speter/*
394251881Speter * unlock_request --
395251881Speter *	Convert an unlock LOCKD_MSG into an NLM request, and send it off.
396251881Speter */
397251881Speterint
398251881Speterunlock_request(LOCKD_MSG *msg)
399251881Speter{
400251881Speter	CLIENT *cli;
401251881Speter	struct nlm4_unlockargs arg4;
402251881Speter	struct nlm_unlockargs arg;
403251881Speter	struct timeval timeout = {0, 0};	/* No timeout, no response. */
404251881Speter	char dummy;
405251881Speter
406251881Speter	if (d_calls)
407251881Speter		syslog(LOG_DEBUG, "unlock request: %s: to %s",
408251881Speter		    msg->lm_nfsv3 ? "V4" : "V1/3",
409251881Speter		    from_addr((struct sockaddr *)&msg->lm_addr));
410251881Speter
411251881Speter	if (msg->lm_nfsv3) {
412251881Speter		arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident;
413251881Speter		arg4.cookie.n_len = sizeof(msg->lm_msg_ident);
414251881Speter		arg4.alock.caller_name = hostname;
415251881Speter		arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
416251881Speter		arg4.alock.fh.n_len = msg->lm_fh_len;
417251881Speter		arg4.alock.oh.n_bytes = (char *)&owner;
418251881Speter		arg4.alock.oh.n_len = sizeof(owner);
419251881Speter		arg4.alock.svid = msg->lm_msg_ident.pid;
420251881Speter		arg4.alock.l_offset = msg->lm_fl.l_start;
421251881Speter		arg4.alock.l_len = msg->lm_fl.l_len;
422251881Speter
423251881Speter		if ((cli = get_client(
424251881Speter		    (struct sockaddr *)&msg->lm_addr,
425251881Speter		    NLM_VERS4)) == NULL)
426251881Speter			return (1);
427251881Speter
428251881Speter		set_auth(cli, &msg->lm_cred);
429251881Speter		(void)clnt_call(cli, NLM_UNLOCK_MSG,
430251881Speter		    xdr_nlm4_unlockargs, &arg4, xdr_void, &dummy, timeout);
431251881Speter	} else {
432251881Speter		arg.cookie.n_bytes = (char *)&msg->lm_msg_ident;
433251881Speter		arg.cookie.n_len = sizeof(msg->lm_msg_ident);
434251881Speter		arg.alock.caller_name = hostname;
435251881Speter		arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
436251881Speter		arg.alock.fh.n_len = msg->lm_fh_len;
437251881Speter		arg.alock.oh.n_bytes = (char *)&owner;
438251881Speter		arg.alock.oh.n_len = sizeof(owner);
439251881Speter		arg.alock.svid = msg->lm_msg_ident.pid;
440251881Speter		arg.alock.l_offset = msg->lm_fl.l_start;
441251881Speter		arg.alock.l_len = msg->lm_fl.l_len;
442251881Speter
443251881Speter		if ((cli = get_client(
444251881Speter		    (struct sockaddr *)&msg->lm_addr,
445251881Speter		    NLM_VERS)) == NULL)
446251881Speter			return (1);
447251881Speter
448251881Speter		set_auth(cli, &msg->lm_cred);
449251881Speter		(void)clnt_call(cli, NLM_UNLOCK_MSG,
450251881Speter		    xdr_nlm_unlockargs, &arg, xdr_void, &dummy, timeout);
451251881Speter	}
452251881Speter
453251881Speter	return (0);
454251881Speter}
455251881Speter
456251881Speterint
457251881Speterlock_answer(int pid, netobj *netcookie, int result, int *pid_p, int version)
458251881Speter{
459251881Speter	struct lockd_ans ans;
460251881Speter
461251881Speter	if (netcookie->n_len != sizeof(ans.la_msg_ident)) {
462251881Speter		if (pid == -1) {	/* we're screwed */
463251881Speter			syslog(LOG_ERR, "inedible nlm cookie");
464251881Speter			return -1;
465251881Speter		}
466251881Speter		ans.la_msg_ident.pid = pid;
467251881Speter		ans.la_msg_ident.msg_seq = -1;
468251881Speter	} else {
469251881Speter		memcpy(&ans.la_msg_ident, netcookie->n_bytes,
470251881Speter		    sizeof(ans.la_msg_ident));
471251881Speter	}
472251881Speter
473251881Speter	if (d_calls)
474251881Speter		syslog(LOG_DEBUG, "lock answer: pid %lu: %s %d",
475251881Speter		    (unsigned long)ans.la_msg_ident.pid,
476251881Speter		    version == NLM_VERS4 ? "nlmv4" : "nlmv3",
477251881Speter		    result);
478251881Speter
479251881Speter	ans.la_set_getlk_pid = 0;
480251881Speter	if (version == NLM_VERS4)
481251881Speter		switch (result) {
482251881Speter		case nlm4_granted:
483251881Speter			ans.la_errno = 0;
484251881Speter			break;
485251881Speter		default:
486251881Speter			ans.la_errno = EACCES;
487251881Speter			break;
488251881Speter		case nlm4_denied:
489251881Speter			if (pid_p == NULL)
490251881Speter				ans.la_errno = EACCES;
491251881Speter			else {
492251881Speter				/* this is an answer to a nlm_test msg */
493251881Speter				ans.la_set_getlk_pid = 1;
494251881Speter				ans.la_getlk_pid = *pid_p;
495251881Speter				ans.la_errno = 0;
496251881Speter			}
497251881Speter			break;
498251881Speter		case nlm4_denied_nolocks:
499251881Speter			ans.la_errno = EAGAIN;
500251881Speter			break;
501251881Speter		case nlm4_blocked:
502251881Speter			return -1;
503251881Speter			/* NOTREACHED */
504251881Speter		case nlm4_denied_grace_period:
505251881Speter			ans.la_errno = EAGAIN;
506251881Speter			break;
507251881Speter		case nlm4_deadlck:
508251881Speter			ans.la_errno = EDEADLK;
509251881Speter			break;
510251881Speter		case nlm4_rofs:
511251881Speter			ans.la_errno = EROFS;
512251881Speter			break;
513251881Speter		case nlm4_stale_fh:
514251881Speter			ans.la_errno = ESTALE;
515251881Speter			break;
516251881Speter		case nlm4_fbig:
517251881Speter			ans.la_errno = EFBIG;
518251881Speter			break;
519251881Speter		case nlm4_failed:
520251881Speter			ans.la_errno = EACCES;
521251881Speter			break;
522251881Speter		}
523251881Speter	else
524251881Speter		switch (result) {
525251881Speter		case nlm_granted:
526251881Speter			ans.la_errno = 0;
527251881Speter			break;
528251881Speter		default:
529251881Speter			ans.la_errno = EACCES;
530251881Speter			break;
531251881Speter		case nlm_denied:
532251881Speter			if (pid_p == NULL)
533251881Speter				ans.la_errno = EACCES;
534251881Speter			else {
535251881Speter				/* this is an answer to a nlm_test msg */
536251881Speter				ans.la_set_getlk_pid = 1;
537251881Speter				ans.la_getlk_pid = *pid_p;
538251881Speter				ans.la_errno = 0;
539251881Speter			}
540251881Speter			break;
541251881Speter		case nlm_denied_nolocks:
542251881Speter			ans.la_errno = EAGAIN;
543251881Speter			break;
544251881Speter		case nlm_blocked:
545251881Speter			return -1;
546251881Speter			/* NOTREACHED */
547251881Speter		case nlm_denied_grace_period:
548251881Speter			ans.la_errno = EAGAIN;
549251881Speter			break;
550251881Speter		case nlm_deadlck:
551251881Speter			ans.la_errno = EDEADLK;
552251881Speter			break;
553251881Speter		}
554251881Speter
555251881Speter	if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
556251881Speter		syslog(((errno == EPIPE || errno == ESRCH) ?
557251881Speter			LOG_INFO : LOG_ERR),
558251881Speter			"process %lu: %m", (u_long)ans.la_msg_ident.pid);
559251881Speter		return -1;
560251881Speter	}
561251881Speter	return 0;
562251881Speter}
563251881Speter
564251881Speter/*
565251881Speter * show --
566251881Speter *	Display the contents of a kernel LOCKD_MSG structure.
567251881Speter */
568251881Spetervoid
569251881Spetershow(LOCKD_MSG *mp)
570251881Speter{
571251881Speter	static char hex[] = "0123456789abcdef";
572251881Speter	struct fid *fidp;
573251881Speter	fsid_t *fsidp;
574251881Speter	size_t len;
575251881Speter	u_int8_t *p, *t, buf[NFS_SMALLFH*3+1];
576251881Speter
577251881Speter	syslog(LOG_DEBUG, "process ID: %lu\n", (long)mp->lm_msg_ident.pid);
578251881Speter
579251881Speter	fsidp = (fsid_t *)&mp->lm_fh;
580251881Speter	fidp = (struct fid *)((u_int8_t *)&mp->lm_fh + sizeof(fsid_t));
581251881Speter
582251881Speter	for (t = buf, p = (u_int8_t *)mp->lm_fh,
583251881Speter	    len = mp->lm_fh_len;
584251881Speter	    len > 0; ++p, --len) {
585251881Speter		*t++ = '\\';
586251881Speter		*t++ = hex[(*p & 0xf0) >> 4];
587251881Speter		*t++ = hex[*p & 0x0f];
588251881Speter	}
589251881Speter	*t = '\0';
590251881Speter
591251881Speter	syslog(LOG_DEBUG, "fh_len %d, fh %s\n", mp->lm_fh_len, buf);
592251881Speter
593251881Speter	/* Show flock structure. */
594251881Speter	syslog(LOG_DEBUG, "start %qu; len %qu; pid %lu; type %d; whence %d\n",
595251881Speter	    mp->lm_fl.l_start, mp->lm_fl.l_len, (u_long)mp->lm_fl.l_pid,
596251881Speter	    mp->lm_fl.l_type, mp->lm_fl.l_whence);
597251881Speter
598251881Speter	/* Show wait flag. */
599251881Speter	syslog(LOG_DEBUG, "wait was %s\n", mp->lm_wait ? "set" : "not set");
600251881Speter}
601251881Speter