]>
git.saurik.com Git - apple/network_cmds.git/blob - rpc_lockd.tproj/kern.c
2 * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. Berkeley Software Design Inc's name may not be used to endorse or
13 * promote products derived from this software without specific prior
16 * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * from BSDI kern.c,v 1.2 1998/11/25 22:38:27 don Exp
29 * $FreeBSD: src/usr.sbin/rpc.lockd/kern.c,v 1.11 2002/08/15 21:52:21 alfred Exp $
32 #include <sys/param.h>
33 #include <sys/mount.h>
34 #include <sys/queue.h>
35 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
52 #include "rpcsvc/nlm_prot.h"
53 #include <nfs/rpcv2.h>
54 #include <nfs/nfsproto.h>
55 #include <nfs/nfs_lock.h>
59 #include "lockd_lock.h"
61 #define nfslockdans(_v, _ansp) \
62 ((_ansp)->la_version = (_v), \
63 nfsclnt(NFSCLNT_LOCKDANS, (_ansp)))
66 /* Lock request owner. */
67 typedef struct __owner
{
68 pid_t pid
; /* Process ID. */
69 time_t tod
; /* Time-of-day. */
73 static char hostname
[MAXHOSTNAMELEN
+ 1]; /* Hostname. */
75 static void client_cleanup(void);
76 static void set_auth(CLIENT
*cl
, struct xucred
*ucred
);
77 int lock_request(LOCKD_MSG
*);
78 int cancel_request(LOCKD_MSG
*);
79 int test_request(LOCKD_MSG
*);
80 void show(LOCKD_MSG
*);
81 int unlock_request(LOCKD_MSG
*);
83 #define d_calls (debug_level > 1)
84 #define d_args (debug_level > 2)
88 struct sockaddr
*saddr
;
90 static char inet_buf
[INET6_ADDRSTRLEN
];
92 if (getnameinfo(saddr
, saddr
->sa_len
, inet_buf
, sizeof(inet_buf
),
93 NULL
, 0, NI_NUMERICHOST
) == 0)
101 * wait for kernel to signal first lock request before starting
104 client_kern_wait(void)
106 if (nfsclnt(NFSCLNT_LOCKDWAIT
, NULL
))
107 warn("nfsclnt_lockdwait");
113 (void) nfsclnt(NFSCLNT_LOCKDFD
, (struct lockd_ans
*)-1);
119 * Loop around messages from the kernel, forwarding them off to
127 * select on FIFOs can currently hang, so we'll use
128 * the nfslockdwait syscall instead for now.
130 #define USE_NFSLOCKDWAIT_INSTEAD_OF_SELECT 1
131 #ifndef USE_NFSLOCKDWAIT_INSTEAD_OF_SELECT
138 /* Recreate the NLM fifo. */
139 (void)unlink(_PATH_LCKFIFO
);
140 old_umask
= umask(S_IXGRP
|S_IXOTH
);
141 if (mkfifo(_PATH_LCKFIFO
, S_IWUSR
| S_IRUSR
)) {
142 syslog(LOG_ERR
, "mkfifo: %s: %m", _PATH_LCKFIFO
);
148 * Create a separate process, the client code is really a separate
149 * daemon that shares a lot of code.
151 switch (child
= fork()) {
160 signal(SIGHUP
, (sig_t
)client_cleanup
);
161 signal(SIGTERM
, (sig_t
)client_cleanup
);
164 (void)time(&owner
.tod
);
165 owner
.pid
= getpid();
166 (void)gethostname(hostname
, sizeof(hostname
) - 1);
168 /* Open the fifo for reading. */
169 if ((fd
= open(_PATH_LCKFIFO
, O_RDONLY
| O_NONBLOCK
)) == -1) {
170 syslog(LOG_ERR
, "open: %s: %m", _PATH_LCKFIFO
);
173 (void)unlink(_PATH_LCKFIFO
);
174 if (nfsclnt(NFSCLNT_LOCKDFD
, (struct lockd_ans
*)fd
)) {
175 syslog(LOG_ERR
, "nfsclnt_fd: %d: %m", fd
);
180 #ifndef USE_NFSLOCKDWAIT_INSTEAD_OF_SELECT
181 /* Wait for contact... fifo's return EAGAIN when read with
184 /* Set up the select. */
187 (void)select(fd
+ 1, &rdset
, NULL
, NULL
, NULL
);
190 /* Read the fixed length message. */
191 if ((nr
= read(fd
, &msg
, sizeof(msg
))) == sizeof(msg
)) {
195 if (msg
.lm_version
!= LOCKD_MSG_VERSION
) {
197 "unknown msg type: %d", msg
.lm_version
);
200 * Send it to the NLM server and don't grant the lock
201 * if we fail for any reason.
203 switch (msg
.lm_fl
.l_type
) {
206 if (msg
.lm_flags
& LOCKD_MSG_TEST
)
207 ret
= test_request(&msg
);
208 else if (msg
.lm_flags
& LOCKD_MSG_CANCEL
)
209 ret
= cancel_request(&msg
);
211 ret
= lock_request(&msg
);
214 ret
= unlock_request(&msg
);
219 "unknown lock type: %d", msg
.lm_fl
.l_type
);
223 struct lockd_ans ans
;
225 ans
.la_xid
= msg
.lm_xid
;
226 ans
.la_errno
= ENOTSUP
;
228 if (nfslockdans(LOCKD_ANS_VERSION
, &ans
)) {
229 syslog(LOG_DEBUG
, "process %lu: %m",
230 (u_long
)msg
.lm_fl
.l_pid
);
233 } else if (nr
== -1) {
234 if (errno
!= EAGAIN
) {
235 syslog(LOG_ERR
, "read: %s: %m", _PATH_LCKFIFO
);
238 #ifdef USE_NFSLOCKDWAIT_INSTEAD_OF_SELECT
240 nfsclnt(NFSCLNT_LOCKDWAIT
, NULL
);
242 } else if (nr
!= 0) {
244 "%s: discard %d bytes", _PATH_LCKFIFO
, nr
);
246 #ifdef USE_NFSLOCKDWAIT_INSTEAD_OF_SELECT
248 nfsclnt(NFSCLNT_LOCKDWAIT
, NULL
);
252 /* Reached only on error. */
254 (void) nfsclnt(NFSCLNT_LOCKDFD
, (struct lockd_ans
*)-1);
262 struct xucred
*xucred
;
264 if (cl
->cl_auth
!= NULL
)
265 cl
->cl_auth
->ah_ops
->ah_destroy(cl
->cl_auth
);
266 cl
->cl_auth
= authunix_create(hostname
,
268 xucred
->cr_groups
[0],
269 xucred
->cr_ngroups
- 1,
270 &xucred
->cr_groups
[1]);
276 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
279 test_request(LOCKD_MSG
*msg
)
282 struct timeval timeout
= {0, 0}; /* No timeout, no response. */
286 syslog(LOG_DEBUG
, "test request: %s: %s to %s",
287 (msg
->lm_flags
& LOCKD_MSG_NFSV3
) ? "V4" : "V1/3",
288 msg
->lm_fl
.l_type
== F_WRLCK
? "write" : "read",
289 from_addr((struct sockaddr
*)&msg
->lm_addr
));
291 if (msg
->lm_flags
& LOCKD_MSG_NFSV3
) {
292 struct nlm4_testargs arg4
;
294 arg4
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
295 arg4
.cookie
.n_len
= sizeof(msg
->lm_xid
);
296 arg4
.exclusive
= msg
->lm_fl
.l_type
== F_WRLCK
? 1 : 0;
297 arg4
.alock
.caller_name
= hostname
;
298 arg4
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
299 arg4
.alock
.fh
.n_len
= msg
->lm_fh_len
;
300 arg4
.alock
.oh
.n_bytes
= (char *)&owner
;
301 arg4
.alock
.oh
.n_len
= sizeof(owner
);
302 arg4
.alock
.svid
= msg
->lm_fl
.l_pid
;
303 arg4
.alock
.l_offset
= msg
->lm_fl
.l_start
;
304 arg4
.alock
.l_len
= msg
->lm_fl
.l_len
;
306 if ((cli
= get_client(
307 (struct sockaddr
*)&msg
->lm_addr
,
311 set_auth(cli
, &msg
->lm_cred
);
312 (void)clnt_call(cli
, NLM4_TEST_MSG
,
313 xdr_nlm4_testargs
, &arg4
, xdr_void
, &dummy
, timeout
);
315 struct nlm_testargs arg
;
317 arg
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
318 arg
.cookie
.n_len
= sizeof(msg
->lm_xid
);
319 arg
.exclusive
= msg
->lm_fl
.l_type
== F_WRLCK
? 1 : 0;
320 arg
.alock
.caller_name
= hostname
;
321 arg
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
322 arg
.alock
.fh
.n_len
= msg
->lm_fh_len
;
323 arg
.alock
.oh
.n_bytes
= (char *)&owner
;
324 arg
.alock
.oh
.n_len
= sizeof(owner
);
325 arg
.alock
.svid
= msg
->lm_fl
.l_pid
;
326 arg
.alock
.l_offset
= msg
->lm_fl
.l_start
;
327 arg
.alock
.l_len
= msg
->lm_fl
.l_len
;
329 if ((cli
= get_client(
330 (struct sockaddr
*)&msg
->lm_addr
,
334 set_auth(cli
, &msg
->lm_cred
);
335 (void)clnt_call(cli
, NLM_TEST_MSG
,
336 xdr_nlm_testargs
, &arg
, xdr_void
, &dummy
, timeout
);
343 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
346 lock_request(LOCKD_MSG
*msg
)
349 struct nlm4_lockargs arg4
;
350 struct nlm_lockargs arg
;
351 struct timeval timeout
= {0, 0}; /* No timeout, no response. */
355 syslog(LOG_DEBUG
, "lock request: %s: %s to %s",
356 (msg
->lm_flags
& LOCKD_MSG_NFSV3
) ? "V4" : "V1/3",
357 msg
->lm_fl
.l_type
== F_WRLCK
? "write" : "read",
358 from_addr((struct sockaddr
*)&msg
->lm_addr
));
360 monitor_lock_host_by_addr((struct sockaddr
*)&msg
->lm_addr
);
362 if (msg
->lm_flags
& LOCKD_MSG_NFSV3
) {
363 arg4
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
364 arg4
.cookie
.n_len
= sizeof(msg
->lm_xid
);
365 arg4
.block
= (msg
->lm_flags
& LOCKD_MSG_BLOCK
) ? 1 : 0;
366 arg4
.exclusive
= msg
->lm_fl
.l_type
== F_WRLCK
? 1 : 0;
367 arg4
.alock
.caller_name
= hostname
;
368 arg4
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
369 arg4
.alock
.fh
.n_len
= msg
->lm_fh_len
;
370 arg4
.alock
.oh
.n_bytes
= (char *)&owner
;
371 arg4
.alock
.oh
.n_len
= sizeof(owner
);
372 arg4
.alock
.svid
= msg
->lm_fl
.l_pid
;
373 arg4
.alock
.l_offset
= msg
->lm_fl
.l_start
;
374 arg4
.alock
.l_len
= msg
->lm_fl
.l_len
;
376 arg4
.state
= nsm_state
;
378 if ((cli
= get_client(
379 (struct sockaddr
*)&msg
->lm_addr
,
383 set_auth(cli
, &msg
->lm_cred
);
384 (void)clnt_call(cli
, NLM4_LOCK_MSG
,
385 xdr_nlm4_lockargs
, &arg4
, xdr_void
, &dummy
, timeout
);
387 arg
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
388 arg
.cookie
.n_len
= sizeof(msg
->lm_xid
);
389 arg
.block
= (msg
->lm_flags
& LOCKD_MSG_BLOCK
) ? 1 : 0;
390 arg
.exclusive
= msg
->lm_fl
.l_type
== F_WRLCK
? 1 : 0;
391 arg
.alock
.caller_name
= hostname
;
392 arg
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
393 arg
.alock
.fh
.n_len
= msg
->lm_fh_len
;
394 arg
.alock
.oh
.n_bytes
= (char *)&owner
;
395 arg
.alock
.oh
.n_len
= sizeof(owner
);
396 arg
.alock
.svid
= msg
->lm_fl
.l_pid
;
397 arg
.alock
.l_offset
= msg
->lm_fl
.l_start
;
398 arg
.alock
.l_len
= msg
->lm_fl
.l_len
;
400 arg
.state
= nsm_state
;
402 if ((cli
= get_client(
403 (struct sockaddr
*)&msg
->lm_addr
,
407 set_auth(cli
, &msg
->lm_cred
);
408 (void)clnt_call(cli
, NLM_LOCK_MSG
,
409 xdr_nlm_lockargs
, &arg
, xdr_void
, &dummy
, timeout
);
416 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
419 cancel_request(LOCKD_MSG
*msg
)
422 struct nlm4_cancargs arg4
;
423 struct nlm_cancargs arg
;
424 struct timeval timeout
= {0, 0}; /* No timeout, no response. */
428 syslog(LOG_DEBUG
, "cancel request: %s: %s to %s",
429 (msg
->lm_flags
& LOCKD_MSG_NFSV3
) ? "V4" : "V1/3",
430 msg
->lm_fl
.l_type
== F_WRLCK
? "write" : "read",
431 from_addr((struct sockaddr
*)&msg
->lm_addr
));
433 if (msg
->lm_flags
& LOCKD_MSG_NFSV3
) {
434 arg4
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
435 arg4
.cookie
.n_len
= sizeof(msg
->lm_xid
);
436 arg4
.block
= (msg
->lm_flags
& LOCKD_MSG_BLOCK
) ? 1 : 0;
437 arg4
.exclusive
= msg
->lm_fl
.l_type
== F_WRLCK
? 1 : 0;
438 arg4
.alock
.caller_name
= hostname
;
439 arg4
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
440 arg4
.alock
.fh
.n_len
= msg
->lm_fh_len
;
441 arg4
.alock
.oh
.n_bytes
= (char *)&owner
;
442 arg4
.alock
.oh
.n_len
= sizeof(owner
);
443 arg4
.alock
.svid
= msg
->lm_fl
.l_pid
;
444 arg4
.alock
.l_offset
= msg
->lm_fl
.l_start
;
445 arg4
.alock
.l_len
= msg
->lm_fl
.l_len
;
447 if ((cli
= get_client(
448 (struct sockaddr
*)&msg
->lm_addr
, NLM_VERS4
)) == NULL
)
451 set_auth(cli
, &msg
->lm_cred
);
452 (void)clnt_call(cli
, NLM4_CANCEL_MSG
,
453 xdr_nlm4_cancargs
, &arg4
, xdr_void
, &dummy
, timeout
);
455 arg
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
456 arg
.cookie
.n_len
= sizeof(msg
->lm_xid
);
457 arg
.block
= (msg
->lm_flags
& LOCKD_MSG_BLOCK
) ? 1 : 0;
458 arg
.exclusive
= msg
->lm_fl
.l_type
== F_WRLCK
? 1 : 0;
459 arg
.alock
.caller_name
= hostname
;
460 arg
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
461 arg
.alock
.fh
.n_len
= msg
->lm_fh_len
;
462 arg
.alock
.oh
.n_bytes
= (char *)&owner
;
463 arg
.alock
.oh
.n_len
= sizeof(owner
);
464 arg
.alock
.svid
= msg
->lm_fl
.l_pid
;
465 arg
.alock
.l_offset
= msg
->lm_fl
.l_start
;
466 arg
.alock
.l_len
= msg
->lm_fl
.l_len
;
468 if ((cli
= get_client(
469 (struct sockaddr
*)&msg
->lm_addr
, NLM_VERS
)) == NULL
)
472 set_auth(cli
, &msg
->lm_cred
);
473 (void)clnt_call(cli
, NLM_CANCEL_MSG
,
474 xdr_nlm_cancargs
, &arg
, xdr_void
, &dummy
, timeout
);
481 * Convert an unlock LOCKD_MSG into an NLM request, and send it off.
484 unlock_request(LOCKD_MSG
*msg
)
487 struct nlm4_unlockargs arg4
;
488 struct nlm_unlockargs arg
;
489 struct timeval timeout
= {0, 0}; /* No timeout, no response. */
493 syslog(LOG_DEBUG
, "unlock request: %s: to %s",
494 (msg
->lm_flags
& LOCKD_MSG_NFSV3
) ? "V4" : "V1/3",
495 from_addr((struct sockaddr
*)&msg
->lm_addr
));
497 if (msg
->lm_flags
& LOCKD_MSG_NFSV3
) {
498 arg4
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
499 arg4
.cookie
.n_len
= sizeof(msg
->lm_xid
);
500 arg4
.alock
.caller_name
= hostname
;
501 arg4
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
502 arg4
.alock
.fh
.n_len
= msg
->lm_fh_len
;
503 arg4
.alock
.oh
.n_bytes
= (char *)&owner
;
504 arg4
.alock
.oh
.n_len
= sizeof(owner
);
505 arg4
.alock
.svid
= msg
->lm_fl
.l_pid
;
506 arg4
.alock
.l_offset
= msg
->lm_fl
.l_start
;
507 arg4
.alock
.l_len
= msg
->lm_fl
.l_len
;
509 if ((cli
= get_client(
510 (struct sockaddr
*)&msg
->lm_addr
,
514 set_auth(cli
, &msg
->lm_cred
);
515 (void)clnt_call(cli
, NLM4_UNLOCK_MSG
,
516 xdr_nlm4_unlockargs
, &arg4
, xdr_void
, &dummy
, timeout
);
518 arg
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
519 arg
.cookie
.n_len
= sizeof(msg
->lm_xid
);
520 arg
.alock
.caller_name
= hostname
;
521 arg
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
522 arg
.alock
.fh
.n_len
= msg
->lm_fh_len
;
523 arg
.alock
.oh
.n_bytes
= (char *)&owner
;
524 arg
.alock
.oh
.n_len
= sizeof(owner
);
525 arg
.alock
.svid
= msg
->lm_fl
.l_pid
;
526 arg
.alock
.l_offset
= msg
->lm_fl
.l_start
;
527 arg
.alock
.l_len
= msg
->lm_fl
.l_len
;
529 if ((cli
= get_client(
530 (struct sockaddr
*)&msg
->lm_addr
,
534 set_auth(cli
, &msg
->lm_cred
);
535 (void)clnt_call(cli
, NLM_UNLOCK_MSG
,
536 xdr_nlm_unlockargs
, &arg
, xdr_void
, &dummy
, timeout
);
543 lock_answer(int version
, netobj
*netcookie
, nlm4_lock
*lock
, int flags
, int result
)
545 struct lockd_ans ans
;
548 if (flags
& LOCK_ANSWER_GRANTED
)
549 ans
.la_flags
|= LOCKD_ANS_GRANTED
;
551 if (netcookie
->n_len
!= sizeof(ans
.la_xid
)) {
552 if (lock
== NULL
) { /* we're screwed */
553 syslog(LOG_ERR
, "inedible nlm cookie");
556 /* no/bad cookie - need to copy lock info to identify request */
559 ans
.la_fh_len
= lock
->fh
.n_len
;
560 if (!lock
->fh
.n_len
|| (lock
->fh
.n_len
> NFS_SMALLFH
)) {
561 syslog(LOG_ERR
, "bogus filehandle size %d in answer", lock
->fh
.n_len
);
564 memcpy(ans
.la_fh
, lock
->fh
.n_bytes
, ans
.la_fh_len
);
565 ans
.la_pid
= lock
->svid
;
566 ans
.la_start
= lock
->l_offset
;
567 ans
.la_len
= lock
->l_len
;
568 ans
.la_flags
|= LOCKD_ANS_LOCK_INFO
;
569 if (flags
& LOCK_ANSWER_LOCK_EXCL
)
570 ans
.la_flags
|= LOCKD_ANS_LOCK_EXCL
;
572 memcpy(&ans
.la_xid
, netcookie
->n_bytes
, sizeof(ans
.la_xid
));
577 syslog(LOG_DEBUG
, "lock answer: pid %lu: %s %d",
578 (unsigned long)ans
.la_pid
,
579 version
== NLM_VERS4
? "nlmv4" : "nlmv3",
582 if (version
== NLM_VERS4
)
586 if ((flags
& LOCK_ANSWER_GRANTED
) && lock
&&
587 !(ans
.la_flags
& LOCKD_ANS_LOCK_INFO
)) {
589 ans
.la_fh_len
= lock
->fh
.n_len
;
590 if (!lock
->fh
.n_len
|| (lock
->fh
.n_len
> NFS_SMALLFH
)) {
591 syslog(LOG_ERR
, "bogus filehandle size %d in answer", lock
->fh
.n_len
);
594 memcpy(ans
.la_fh
, lock
->fh
.n_bytes
, ans
.la_fh_len
);
595 ans
.la_pid
= lock
->svid
;
596 ans
.la_start
= lock
->l_offset
;
597 ans
.la_len
= lock
->l_len
;
598 ans
.la_flags
|= LOCKD_ANS_LOCK_INFO
;
599 if (flags
& LOCK_ANSWER_LOCK_EXCL
)
600 ans
.la_flags
|= LOCKD_ANS_LOCK_EXCL
;
604 ans
.la_errno
= EACCES
;
608 ans
.la_errno
= EACCES
;
610 /* this is an answer to a nlm_test msg */
611 ans
.la_pid
= lock
->svid
;
612 ans
.la_start
= lock
->l_offset
;
613 ans
.la_len
= lock
->l_len
;
614 ans
.la_flags
|= LOCKD_ANS_LOCK_INFO
;
615 if (flags
& LOCK_ANSWER_LOCK_EXCL
)
616 ans
.la_flags
|= LOCKD_ANS_LOCK_EXCL
;
620 case nlm4_denied_nolocks
:
621 ans
.la_errno
= ENOLCK
;
624 ans
.la_errno
= EINPROGRESS
;
626 case nlm4_denied_grace_period
:
627 ans
.la_errno
= EAGAIN
;
630 ans
.la_errno
= EDEADLK
;
633 ans
.la_errno
= EROFS
;
636 ans
.la_errno
= ESTALE
;
639 ans
.la_errno
= EFBIG
;
642 ans
.la_errno
= EACCES
;
649 if ((flags
& LOCK_ANSWER_GRANTED
) && lock
&&
650 !(ans
.la_flags
& LOCKD_ANS_LOCK_INFO
)) {
652 ans
.la_fh_len
= lock
->fh
.n_len
;
653 if (!lock
->fh
.n_len
|| (lock
->fh
.n_len
> NFS_SMALLFH
)) {
654 syslog(LOG_ERR
, "bogus filehandle size %d in answer", lock
->fh
.n_len
);
657 memcpy(ans
.la_fh
, lock
->fh
.n_bytes
, ans
.la_fh_len
);
658 ans
.la_pid
= lock
->svid
;
659 ans
.la_start
= lock
->l_offset
;
660 ans
.la_len
= lock
->l_len
;
661 ans
.la_flags
|= LOCKD_ANS_LOCK_INFO
;
662 if (flags
& LOCK_ANSWER_LOCK_EXCL
)
663 ans
.la_flags
|= LOCKD_ANS_LOCK_EXCL
;
667 ans
.la_errno
= EACCES
;
671 ans
.la_errno
= EACCES
;
673 /* this is an answer to a nlm_test msg */
674 ans
.la_pid
= lock
->svid
;
675 ans
.la_start
= lock
->l_offset
;
676 ans
.la_len
= lock
->l_len
;
677 ans
.la_flags
|= LOCKD_ANS_LOCK_INFO
;
678 if (flags
& LOCK_ANSWER_LOCK_EXCL
)
679 ans
.la_flags
|= LOCKD_ANS_LOCK_EXCL
;
683 case nlm_denied_nolocks
:
684 ans
.la_errno
= ENOLCK
;
687 ans
.la_errno
= EINPROGRESS
;
689 case nlm_denied_grace_period
:
690 ans
.la_errno
= EAGAIN
;
693 ans
.la_errno
= EDEADLK
;
697 if (nfslockdans(LOCKD_ANS_VERSION
, &ans
)) {
698 syslog(LOG_DEBUG
, "lock_answer(%d): process %lu: %m",
699 result
, (u_long
)ans
.la_pid
);
707 * Display the contents of a kernel LOCKD_MSG structure.
712 static char hex
[] = "0123456789abcdef";
716 u_int8_t
*p
, *t
, buf
[NFS_SMALLFH
*3+1];
718 syslog(LOG_DEBUG
, "process ID: %lu\n", (long)mp
->lm_fl
.l_pid
);
720 fsidp
= (fsid_t
*)&mp
->lm_fh
;
721 fidp
= (struct fid
*)((u_int8_t
*)&mp
->lm_fh
+ sizeof(fsid_t
));
723 for (t
= buf
, p
= (u_int8_t
*)mp
->lm_fh
,
725 len
> 0; ++p
, --len
) {
727 *t
++ = hex
[(*p
& 0xf0) >> 4];
728 *t
++ = hex
[*p
& 0x0f];
732 syslog(LOG_DEBUG
, "fh_len %d, fh %s\n", mp
->lm_fh_len
, buf
);
734 /* Show flock structure. */
735 syslog(LOG_DEBUG
, "start %qu; len %qu; pid %lu; type %d; whence %d\n",
736 mp
->lm_fl
.l_start
, mp
->lm_fl
.l_len
, (u_long
)mp
->lm_fl
.l_pid
,
737 mp
->lm_fl
.l_type
, mp
->lm_fl
.l_whence
);
739 /* Show wait flag. */
740 syslog(LOG_DEBUG
, "wait was %s\n", (mp
->lm_flags
& LOCKD_MSG_BLOCK
) ? "set" : "not set");