]>
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
131 /* Recreate the NLM fifo. */
132 (void)unlink(_PATH_LCKFIFO
);
133 old_umask
= umask(S_IXGRP
|S_IXOTH
);
134 if (mkfifo(_PATH_LCKFIFO
, S_IWUSR
| S_IRUSR
)) {
135 syslog(LOG_ERR
, "mkfifo: %s: %m", _PATH_LCKFIFO
);
141 * Create a separate process, the client code is really a separate
142 * daemon that shares a lot of code.
144 switch (child
= fork()) {
153 signal(SIGHUP
, (sig_t
)client_cleanup
);
154 signal(SIGTERM
, (sig_t
)client_cleanup
);
157 (void)time(&owner
.tod
);
158 owner
.pid
= getpid();
160 /* Open the fifo for reading. */
161 if ((fd
= open(_PATH_LCKFIFO
, O_RDONLY
| O_NONBLOCK
)) == -1) {
162 syslog(LOG_ERR
, "open: %s: %m", _PATH_LCKFIFO
);
165 (void)unlink(_PATH_LCKFIFO
);
166 if (nfsclnt(NFSCLNT_LOCKDFD
, (struct lockd_ans
*)fd
)) {
167 syslog(LOG_ERR
, "nfsclnt_fd: %d: %m", fd
);
172 /* Wait for contact... fifo's return EAGAIN when read with
175 /* Set up the select. */
178 (void)select(fd
+ 1, &rdset
, NULL
, NULL
, NULL
);
181 * Hold off getting hostname until first
182 * lock request. Otherwise we risk getting
183 * an initial ".local" name.
185 if (hostname
[0] == '\0')
186 (void)gethostname(hostname
, sizeof(hostname
) - 1);
188 /* Read the fixed length message. */
189 if ((nr
= read(fd
, &msg
, sizeof(msg
))) == sizeof(msg
)) {
193 if (msg
.lm_version
!= LOCKD_MSG_VERSION
) {
195 "unknown msg type: %d", msg
.lm_version
);
198 * Send it to the NLM server and don't grant the lock
199 * if we fail for any reason.
201 switch (msg
.lm_fl
.l_type
) {
204 if (msg
.lm_flags
& LOCKD_MSG_TEST
)
205 ret
= test_request(&msg
);
206 else if (msg
.lm_flags
& LOCKD_MSG_CANCEL
)
207 ret
= cancel_request(&msg
);
209 ret
= lock_request(&msg
);
212 ret
= unlock_request(&msg
);
217 "unknown lock type: %d", msg
.lm_fl
.l_type
);
221 struct lockd_ans ans
;
223 ans
.la_xid
= msg
.lm_xid
;
224 ans
.la_errno
= ENOTSUP
;
226 if (nfslockdans(LOCKD_ANS_VERSION
, &ans
)) {
227 syslog(LOG_DEBUG
, "process %lu: %m",
228 (u_long
)msg
.lm_fl
.l_pid
);
231 } else if (nr
== -1) {
232 if (errno
!= EAGAIN
) {
233 syslog(LOG_ERR
, "read: %s: %m", _PATH_LCKFIFO
);
236 } else if (nr
!= 0) {
238 "%s: discard %d bytes", _PATH_LCKFIFO
, nr
);
242 /* Reached only on error. */
244 (void) nfsclnt(NFSCLNT_LOCKDFD
, (struct lockd_ans
*)-1);
252 struct xucred
*xucred
;
254 if (cl
->cl_auth
!= NULL
)
255 cl
->cl_auth
->ah_ops
->ah_destroy(cl
->cl_auth
);
256 cl
->cl_auth
= authunix_create(hostname
,
258 xucred
->cr_groups
[0],
259 xucred
->cr_ngroups
- 1,
260 &xucred
->cr_groups
[1]);
266 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
269 test_request(LOCKD_MSG
*msg
)
272 struct timeval timeout
= {0, 0}; /* No timeout, no response. */
276 syslog(LOG_DEBUG
, "test request: %s: %s to %s",
277 (msg
->lm_flags
& LOCKD_MSG_NFSV3
) ? "V4" : "V1/3",
278 msg
->lm_fl
.l_type
== F_WRLCK
? "write" : "read",
279 from_addr((struct sockaddr
*)&msg
->lm_addr
));
281 if (msg
->lm_flags
& LOCKD_MSG_NFSV3
) {
282 struct nlm4_testargs arg4
;
284 arg4
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
285 arg4
.cookie
.n_len
= sizeof(msg
->lm_xid
);
286 arg4
.exclusive
= msg
->lm_fl
.l_type
== F_WRLCK
? 1 : 0;
287 arg4
.alock
.caller_name
= hostname
;
288 arg4
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
289 arg4
.alock
.fh
.n_len
= msg
->lm_fh_len
;
290 arg4
.alock
.oh
.n_bytes
= (char *)&owner
;
291 arg4
.alock
.oh
.n_len
= sizeof(owner
);
292 arg4
.alock
.svid
= msg
->lm_fl
.l_pid
;
293 arg4
.alock
.l_offset
= msg
->lm_fl
.l_start
;
294 arg4
.alock
.l_len
= msg
->lm_fl
.l_len
;
296 if ((cli
= get_client(
297 (struct sockaddr
*)&msg
->lm_addr
,
301 set_auth(cli
, &msg
->lm_cred
);
302 (void)clnt_call(cli
, NLM4_TEST_MSG
,
303 xdr_nlm4_testargs
, &arg4
, xdr_void
, &dummy
, timeout
);
305 struct nlm_testargs arg
;
307 arg
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
308 arg
.cookie
.n_len
= sizeof(msg
->lm_xid
);
309 arg
.exclusive
= msg
->lm_fl
.l_type
== F_WRLCK
? 1 : 0;
310 arg
.alock
.caller_name
= hostname
;
311 arg
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
312 arg
.alock
.fh
.n_len
= msg
->lm_fh_len
;
313 arg
.alock
.oh
.n_bytes
= (char *)&owner
;
314 arg
.alock
.oh
.n_len
= sizeof(owner
);
315 arg
.alock
.svid
= msg
->lm_fl
.l_pid
;
316 arg
.alock
.l_offset
= msg
->lm_fl
.l_start
;
317 arg
.alock
.l_len
= msg
->lm_fl
.l_len
;
319 if ((cli
= get_client(
320 (struct sockaddr
*)&msg
->lm_addr
,
324 set_auth(cli
, &msg
->lm_cred
);
325 (void)clnt_call(cli
, NLM_TEST_MSG
,
326 xdr_nlm_testargs
, &arg
, xdr_void
, &dummy
, timeout
);
333 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
336 lock_request(LOCKD_MSG
*msg
)
339 struct nlm4_lockargs arg4
;
340 struct nlm_lockargs arg
;
341 struct timeval timeout
= {0, 0}; /* No timeout, no response. */
345 syslog(LOG_DEBUG
, "lock request: %s: %s to %s",
346 (msg
->lm_flags
& LOCKD_MSG_NFSV3
) ? "V4" : "V1/3",
347 msg
->lm_fl
.l_type
== F_WRLCK
? "write" : "read",
348 from_addr((struct sockaddr
*)&msg
->lm_addr
));
350 monitor_lock_host_by_addr((struct sockaddr
*)&msg
->lm_addr
);
352 if (msg
->lm_flags
& LOCKD_MSG_NFSV3
) {
353 arg4
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
354 arg4
.cookie
.n_len
= sizeof(msg
->lm_xid
);
355 arg4
.block
= (msg
->lm_flags
& LOCKD_MSG_BLOCK
) ? 1 : 0;
356 arg4
.exclusive
= msg
->lm_fl
.l_type
== F_WRLCK
? 1 : 0;
357 arg4
.alock
.caller_name
= hostname
;
358 arg4
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
359 arg4
.alock
.fh
.n_len
= msg
->lm_fh_len
;
360 arg4
.alock
.oh
.n_bytes
= (char *)&owner
;
361 arg4
.alock
.oh
.n_len
= sizeof(owner
);
362 arg4
.alock
.svid
= msg
->lm_fl
.l_pid
;
363 arg4
.alock
.l_offset
= msg
->lm_fl
.l_start
;
364 arg4
.alock
.l_len
= msg
->lm_fl
.l_len
;
366 arg4
.state
= nsm_state
;
368 if ((cli
= get_client(
369 (struct sockaddr
*)&msg
->lm_addr
,
373 set_auth(cli
, &msg
->lm_cred
);
374 (void)clnt_call(cli
, NLM4_LOCK_MSG
,
375 xdr_nlm4_lockargs
, &arg4
, xdr_void
, &dummy
, timeout
);
377 arg
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
378 arg
.cookie
.n_len
= sizeof(msg
->lm_xid
);
379 arg
.block
= (msg
->lm_flags
& LOCKD_MSG_BLOCK
) ? 1 : 0;
380 arg
.exclusive
= msg
->lm_fl
.l_type
== F_WRLCK
? 1 : 0;
381 arg
.alock
.caller_name
= hostname
;
382 arg
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
383 arg
.alock
.fh
.n_len
= msg
->lm_fh_len
;
384 arg
.alock
.oh
.n_bytes
= (char *)&owner
;
385 arg
.alock
.oh
.n_len
= sizeof(owner
);
386 arg
.alock
.svid
= msg
->lm_fl
.l_pid
;
387 arg
.alock
.l_offset
= msg
->lm_fl
.l_start
;
388 arg
.alock
.l_len
= msg
->lm_fl
.l_len
;
390 arg
.state
= nsm_state
;
392 if ((cli
= get_client(
393 (struct sockaddr
*)&msg
->lm_addr
,
397 set_auth(cli
, &msg
->lm_cred
);
398 (void)clnt_call(cli
, NLM_LOCK_MSG
,
399 xdr_nlm_lockargs
, &arg
, xdr_void
, &dummy
, timeout
);
406 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
409 cancel_request(LOCKD_MSG
*msg
)
412 struct nlm4_cancargs arg4
;
413 struct nlm_cancargs arg
;
414 struct timeval timeout
= {0, 0}; /* No timeout, no response. */
418 syslog(LOG_DEBUG
, "cancel request: %s: %s to %s",
419 (msg
->lm_flags
& LOCKD_MSG_NFSV3
) ? "V4" : "V1/3",
420 msg
->lm_fl
.l_type
== F_WRLCK
? "write" : "read",
421 from_addr((struct sockaddr
*)&msg
->lm_addr
));
423 if (msg
->lm_flags
& LOCKD_MSG_NFSV3
) {
424 arg4
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
425 arg4
.cookie
.n_len
= sizeof(msg
->lm_xid
);
426 arg4
.block
= (msg
->lm_flags
& LOCKD_MSG_BLOCK
) ? 1 : 0;
427 arg4
.exclusive
= msg
->lm_fl
.l_type
== F_WRLCK
? 1 : 0;
428 arg4
.alock
.caller_name
= hostname
;
429 arg4
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
430 arg4
.alock
.fh
.n_len
= msg
->lm_fh_len
;
431 arg4
.alock
.oh
.n_bytes
= (char *)&owner
;
432 arg4
.alock
.oh
.n_len
= sizeof(owner
);
433 arg4
.alock
.svid
= msg
->lm_fl
.l_pid
;
434 arg4
.alock
.l_offset
= msg
->lm_fl
.l_start
;
435 arg4
.alock
.l_len
= msg
->lm_fl
.l_len
;
437 if ((cli
= get_client(
438 (struct sockaddr
*)&msg
->lm_addr
, NLM_VERS4
)) == NULL
)
441 set_auth(cli
, &msg
->lm_cred
);
442 (void)clnt_call(cli
, NLM4_CANCEL_MSG
,
443 xdr_nlm4_cancargs
, &arg4
, xdr_void
, &dummy
, timeout
);
445 arg
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
446 arg
.cookie
.n_len
= sizeof(msg
->lm_xid
);
447 arg
.block
= (msg
->lm_flags
& LOCKD_MSG_BLOCK
) ? 1 : 0;
448 arg
.exclusive
= msg
->lm_fl
.l_type
== F_WRLCK
? 1 : 0;
449 arg
.alock
.caller_name
= hostname
;
450 arg
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
451 arg
.alock
.fh
.n_len
= msg
->lm_fh_len
;
452 arg
.alock
.oh
.n_bytes
= (char *)&owner
;
453 arg
.alock
.oh
.n_len
= sizeof(owner
);
454 arg
.alock
.svid
= msg
->lm_fl
.l_pid
;
455 arg
.alock
.l_offset
= msg
->lm_fl
.l_start
;
456 arg
.alock
.l_len
= msg
->lm_fl
.l_len
;
458 if ((cli
= get_client(
459 (struct sockaddr
*)&msg
->lm_addr
, NLM_VERS
)) == NULL
)
462 set_auth(cli
, &msg
->lm_cred
);
463 (void)clnt_call(cli
, NLM_CANCEL_MSG
,
464 xdr_nlm_cancargs
, &arg
, xdr_void
, &dummy
, timeout
);
471 * Convert an unlock LOCKD_MSG into an NLM request, and send it off.
474 unlock_request(LOCKD_MSG
*msg
)
477 struct nlm4_unlockargs arg4
;
478 struct nlm_unlockargs arg
;
479 struct timeval timeout
= {0, 0}; /* No timeout, no response. */
483 syslog(LOG_DEBUG
, "unlock request: %s: to %s",
484 (msg
->lm_flags
& LOCKD_MSG_NFSV3
) ? "V4" : "V1/3",
485 from_addr((struct sockaddr
*)&msg
->lm_addr
));
487 if (msg
->lm_flags
& LOCKD_MSG_NFSV3
) {
488 arg4
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
489 arg4
.cookie
.n_len
= sizeof(msg
->lm_xid
);
490 arg4
.alock
.caller_name
= hostname
;
491 arg4
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
492 arg4
.alock
.fh
.n_len
= msg
->lm_fh_len
;
493 arg4
.alock
.oh
.n_bytes
= (char *)&owner
;
494 arg4
.alock
.oh
.n_len
= sizeof(owner
);
495 arg4
.alock
.svid
= msg
->lm_fl
.l_pid
;
496 arg4
.alock
.l_offset
= msg
->lm_fl
.l_start
;
497 arg4
.alock
.l_len
= msg
->lm_fl
.l_len
;
499 if ((cli
= get_client(
500 (struct sockaddr
*)&msg
->lm_addr
,
504 set_auth(cli
, &msg
->lm_cred
);
505 (void)clnt_call(cli
, NLM4_UNLOCK_MSG
,
506 xdr_nlm4_unlockargs
, &arg4
, xdr_void
, &dummy
, timeout
);
508 arg
.cookie
.n_bytes
= (char *)&msg
->lm_xid
;
509 arg
.cookie
.n_len
= sizeof(msg
->lm_xid
);
510 arg
.alock
.caller_name
= hostname
;
511 arg
.alock
.fh
.n_bytes
= (char *)&msg
->lm_fh
;
512 arg
.alock
.fh
.n_len
= msg
->lm_fh_len
;
513 arg
.alock
.oh
.n_bytes
= (char *)&owner
;
514 arg
.alock
.oh
.n_len
= sizeof(owner
);
515 arg
.alock
.svid
= msg
->lm_fl
.l_pid
;
516 arg
.alock
.l_offset
= msg
->lm_fl
.l_start
;
517 arg
.alock
.l_len
= msg
->lm_fl
.l_len
;
519 if ((cli
= get_client(
520 (struct sockaddr
*)&msg
->lm_addr
,
524 set_auth(cli
, &msg
->lm_cred
);
525 (void)clnt_call(cli
, NLM_UNLOCK_MSG
,
526 xdr_nlm_unlockargs
, &arg
, xdr_void
, &dummy
, timeout
);
533 lock_answer(int version
, netobj
*netcookie
, nlm4_lock
*lock
, int flags
, int result
)
535 struct lockd_ans ans
;
538 if (flags
& LOCK_ANSWER_GRANTED
)
539 ans
.la_flags
|= LOCKD_ANS_GRANTED
;
541 if (netcookie
->n_len
!= sizeof(ans
.la_xid
)) {
542 if (lock
== NULL
) { /* we're screwed */
543 syslog(LOG_ERR
, "inedible nlm cookie");
546 /* no/bad cookie - need to copy lock info to identify request */
549 ans
.la_fh_len
= lock
->fh
.n_len
;
550 if (!lock
->fh
.n_len
|| (lock
->fh
.n_len
> NFS_SMALLFH
)) {
551 syslog(LOG_ERR
, "bogus filehandle size %d in answer", lock
->fh
.n_len
);
554 memcpy(ans
.la_fh
, lock
->fh
.n_bytes
, ans
.la_fh_len
);
555 ans
.la_pid
= lock
->svid
;
556 ans
.la_start
= lock
->l_offset
;
557 ans
.la_len
= lock
->l_len
;
558 ans
.la_flags
|= LOCKD_ANS_LOCK_INFO
;
559 if (flags
& LOCK_ANSWER_LOCK_EXCL
)
560 ans
.la_flags
|= LOCKD_ANS_LOCK_EXCL
;
562 memcpy(&ans
.la_xid
, netcookie
->n_bytes
, sizeof(ans
.la_xid
));
567 syslog(LOG_DEBUG
, "lock answer: pid %lu: %s %d",
568 (unsigned long)ans
.la_pid
,
569 version
== NLM_VERS4
? "nlmv4" : "nlmv3",
572 if (version
== NLM_VERS4
)
576 if ((flags
& LOCK_ANSWER_GRANTED
) && lock
&&
577 !(ans
.la_flags
& LOCKD_ANS_LOCK_INFO
)) {
579 ans
.la_fh_len
= lock
->fh
.n_len
;
580 if (!lock
->fh
.n_len
|| (lock
->fh
.n_len
> NFS_SMALLFH
)) {
581 syslog(LOG_ERR
, "bogus filehandle size %d in answer", lock
->fh
.n_len
);
584 memcpy(ans
.la_fh
, lock
->fh
.n_bytes
, ans
.la_fh_len
);
585 ans
.la_pid
= lock
->svid
;
586 ans
.la_start
= lock
->l_offset
;
587 ans
.la_len
= lock
->l_len
;
588 ans
.la_flags
|= LOCKD_ANS_LOCK_INFO
;
589 if (flags
& LOCK_ANSWER_LOCK_EXCL
)
590 ans
.la_flags
|= LOCKD_ANS_LOCK_EXCL
;
594 ans
.la_errno
= EACCES
;
598 ans
.la_errno
= EACCES
;
600 /* this is an answer to a nlm_test msg */
601 ans
.la_pid
= lock
->svid
;
602 ans
.la_start
= lock
->l_offset
;
603 ans
.la_len
= lock
->l_len
;
604 ans
.la_flags
|= LOCKD_ANS_LOCK_INFO
;
605 if (flags
& LOCK_ANSWER_LOCK_EXCL
)
606 ans
.la_flags
|= LOCKD_ANS_LOCK_EXCL
;
610 case nlm4_denied_nolocks
:
611 ans
.la_errno
= ENOLCK
;
614 ans
.la_errno
= EINPROGRESS
;
616 case nlm4_denied_grace_period
:
617 ans
.la_errno
= EAGAIN
;
620 ans
.la_errno
= EDEADLK
;
623 ans
.la_errno
= EROFS
;
626 ans
.la_errno
= ESTALE
;
629 ans
.la_errno
= EFBIG
;
632 ans
.la_errno
= EACCES
;
639 if ((flags
& LOCK_ANSWER_GRANTED
) && lock
&&
640 !(ans
.la_flags
& LOCKD_ANS_LOCK_INFO
)) {
642 ans
.la_fh_len
= lock
->fh
.n_len
;
643 if (!lock
->fh
.n_len
|| (lock
->fh
.n_len
> NFS_SMALLFH
)) {
644 syslog(LOG_ERR
, "bogus filehandle size %d in answer", lock
->fh
.n_len
);
647 memcpy(ans
.la_fh
, lock
->fh
.n_bytes
, ans
.la_fh_len
);
648 ans
.la_pid
= lock
->svid
;
649 ans
.la_start
= lock
->l_offset
;
650 ans
.la_len
= lock
->l_len
;
651 ans
.la_flags
|= LOCKD_ANS_LOCK_INFO
;
652 if (flags
& LOCK_ANSWER_LOCK_EXCL
)
653 ans
.la_flags
|= LOCKD_ANS_LOCK_EXCL
;
657 ans
.la_errno
= EACCES
;
661 ans
.la_errno
= EACCES
;
663 /* this is an answer to a nlm_test msg */
664 ans
.la_pid
= lock
->svid
;
665 ans
.la_start
= lock
->l_offset
;
666 ans
.la_len
= lock
->l_len
;
667 ans
.la_flags
|= LOCKD_ANS_LOCK_INFO
;
668 if (flags
& LOCK_ANSWER_LOCK_EXCL
)
669 ans
.la_flags
|= LOCKD_ANS_LOCK_EXCL
;
673 case nlm_denied_nolocks
:
674 ans
.la_errno
= ENOLCK
;
677 ans
.la_errno
= EINPROGRESS
;
679 case nlm_denied_grace_period
:
680 ans
.la_errno
= EAGAIN
;
683 ans
.la_errno
= EDEADLK
;
687 if (nfslockdans(LOCKD_ANS_VERSION
, &ans
)) {
688 syslog(LOG_DEBUG
, "lock_answer(%d): process %lu: %m",
689 result
, (u_long
)ans
.la_pid
);
697 * Display the contents of a kernel LOCKD_MSG structure.
702 static char hex
[] = "0123456789abcdef";
704 u_int8_t
*p
, *t
, buf
[NFS_SMALLFH
*3+1];
706 syslog(LOG_DEBUG
, "process ID: %lu\n", (long)mp
->lm_fl
.l_pid
);
708 for (t
= buf
, p
= (u_int8_t
*)mp
->lm_fh
,
710 len
> 0; ++p
, --len
) {
712 *t
++ = hex
[(*p
& 0xf0) >> 4];
713 *t
++ = hex
[*p
& 0x0f];
717 syslog(LOG_DEBUG
, "fh_len %d, fh %s\n", mp
->lm_fh_len
, buf
);
719 /* Show flock structure. */
720 syslog(LOG_DEBUG
, "start %qu; len %qu; pid %lu; type %d; whence %d\n",
721 mp
->lm_fl
.l_start
, mp
->lm_fl
.l_len
, (u_long
)mp
->lm_fl
.l_pid
,
722 mp
->lm_fl
.l_type
, mp
->lm_fl
.l_whence
);
724 /* Show wait flag. */
725 syslog(LOG_DEBUG
, "wait was %s\n", (mp
->lm_flags
& LOCKD_MSG_BLOCK
) ? "set" : "not set");