]> git.saurik.com Git - apple/network_cmds.git/blame - rpc_lockd.tproj/kern.c
network_cmds-176.3.1.tar.gz
[apple/network_cmds.git] / rpc_lockd.tproj / kern.c
CommitLineData
ac2f15b3
A
1/*-
2 * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
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
14 * written permission.
15 *
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
26 * SUCH DAMAGE.
27 *
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 $
30 */
31
32#include <sys/param.h>
33#include <sys/mount.h>
34#include <sys/queue.h>
35#include <sys/socket.h>
36#include <sys/stat.h>
37
38#include <netinet/in.h>
39#include <arpa/inet.h>
40
41#include <err.h>
42#include <errno.h>
43#include <fcntl.h>
44#include <pwd.h>
45#include <stdio.h>
46#include <stdlib.h>
47#include <string.h>
48#include <syslog.h>
49#include <unistd.h>
50#include <netdb.h>
51
52#include "rpcsvc/nlm_prot.h"
53#include <nfs/rpcv2.h>
54#include <nfs/nfsproto.h>
55#include <nfs/nfs_lock.h>
56#include <nfs/nfs.h>
57
58#include "lockd.h"
59#include "lockd_lock.h"
60
ac2f15b3 61#define nfslockdans(_v, _ansp) \
7902cf7e 62 ((_ansp)->la_version = (_v), \
ac2f15b3
A
63 nfsclnt(NFSCLNT_LOCKDANS, (_ansp)))
64
65
66/* Lock request owner. */
67typedef struct __owner {
68 pid_t pid; /* Process ID. */
69 time_t tod; /* Time-of-day. */
70} OWNER;
71static OWNER owner;
72
73static char hostname[MAXHOSTNAMELEN + 1]; /* Hostname. */
74
75static void client_cleanup(void);
76static void set_auth(CLIENT *cl, struct xucred *ucred);
77int lock_request(LOCKD_MSG *);
7902cf7e 78int cancel_request(LOCKD_MSG *);
ac2f15b3
A
79int test_request(LOCKD_MSG *);
80void show(LOCKD_MSG *);
81int unlock_request(LOCKD_MSG *);
82
ac2f15b3
A
83#define d_calls (debug_level > 1)
84#define d_args (debug_level > 2)
85
86static const char *
87from_addr(saddr)
88 struct sockaddr *saddr;
89{
90 static char inet_buf[INET6_ADDRSTRLEN];
91
92 if (getnameinfo(saddr, saddr->sa_len, inet_buf, sizeof(inet_buf),
93 NULL, 0, NI_NUMERICHOST) == 0)
94 return inet_buf;
95 return "???";
96}
97
98/*
99 * client_kern_wait()
100 *
101 * wait for kernel to signal first lock request before starting
102 */
103void
104client_kern_wait(void)
105{
106 if (nfsclnt(NFSCLNT_LOCKDWAIT, NULL))
107 warn("nfsclnt_lockdwait");
108}
109
110void
111client_cleanup(void)
112{
ac2f15b3
A
113 (void) nfsclnt(NFSCLNT_LOCKDFD, (struct lockd_ans *)-1);
114 exit(-1);
115}
116
117/*
118 * client_request --
119 * Loop around messages from the kernel, forwarding them off to
120 * NLM servers.
121 */
122pid_t
123client_request(void)
124{
125 LOCKD_MSG msg;
126/*
127 * select on FIFOs can currently hang, so we'll use
128 * the nfslockdwait syscall instead for now.
129 */
130#define USE_NFSLOCKDWAIT_INSTEAD_OF_SELECT 1
131#ifndef USE_NFSLOCKDWAIT_INSTEAD_OF_SELECT
132 fd_set rdset;
133#endif
134 int fd, nr, ret;
135 pid_t child;
ac2f15b3 136 mode_t old_umask;
ac2f15b3
A
137
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);
143 exit (1);
144 }
145 umask(old_umask);
146
147 /*
148 * Create a separate process, the client code is really a separate
149 * daemon that shares a lot of code.
150 */
151 switch (child = fork()) {
152 case -1:
153 err(1, "fork");
154 case 0:
155 break;
156 default:
157 return (child);
158 }
159
160 signal(SIGHUP, (sig_t)client_cleanup);
161 signal(SIGTERM, (sig_t)client_cleanup);
162
163 /* Setup. */
164 (void)time(&owner.tod);
165 owner.pid = getpid();
166 (void)gethostname(hostname, sizeof(hostname) - 1);
167
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);
7902cf7e 171 _exit (1);
ac2f15b3
A
172 }
173 (void)unlink(_PATH_LCKFIFO);
174 if (nfsclnt(NFSCLNT_LOCKDFD, (struct lockd_ans *)fd)) {
175 syslog(LOG_ERR, "nfsclnt_fd: %d: %m", fd);
7902cf7e 176 _exit (1);
ac2f15b3 177 }
ac2f15b3
A
178
179 for (;;) {
180#ifndef USE_NFSLOCKDWAIT_INSTEAD_OF_SELECT
181 /* Wait for contact... fifo's return EAGAIN when read with
182 * no data
183 */
184 /* Set up the select. */
185 FD_ZERO(&rdset);
186 FD_SET(fd, &rdset);
187 (void)select(fd + 1, &rdset, NULL, NULL, NULL);
188#endif
189
190 /* Read the fixed length message. */
191 if ((nr = read(fd, &msg, sizeof(msg))) == sizeof(msg)) {
192 if (d_args)
193 show(&msg);
194
195 if (msg.lm_version != LOCKD_MSG_VERSION) {
196 syslog(LOG_ERR,
197 "unknown msg type: %d", msg.lm_version);
198 }
199 /*
200 * Send it to the NLM server and don't grant the lock
201 * if we fail for any reason.
202 */
203 switch (msg.lm_fl.l_type) {
204 case F_RDLCK:
205 case F_WRLCK:
7902cf7e 206 if (msg.lm_flags & LOCKD_MSG_TEST)
ac2f15b3 207 ret = test_request(&msg);
7902cf7e
A
208 else if (msg.lm_flags & LOCKD_MSG_CANCEL)
209 ret = cancel_request(&msg);
ac2f15b3
A
210 else
211 ret = lock_request(&msg);
212 break;
213 case F_UNLCK:
214 ret = unlock_request(&msg);
215 break;
216 default:
217 ret = 1;
218 syslog(LOG_ERR,
219 "unknown lock type: %d", msg.lm_fl.l_type);
220 break;
221 }
222 if (ret) {
223 struct lockd_ans ans;
224
7902cf7e 225 ans.la_xid = msg.lm_xid;
ac2f15b3
A
226 ans.la_errno = ENOTSUP;
227
228 if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
229 syslog(LOG_DEBUG, "process %lu: %m",
7902cf7e 230 (u_long)msg.lm_fl.l_pid);
ac2f15b3
A
231 }
232 }
233 } else if (nr == -1) {
234 if (errno != EAGAIN) {
235 syslog(LOG_ERR, "read: %s: %m", _PATH_LCKFIFO);
236 goto err;
237 }
238#ifdef USE_NFSLOCKDWAIT_INSTEAD_OF_SELECT
239 else
240 nfsclnt(NFSCLNT_LOCKDWAIT, NULL);
241#endif
242 } else if (nr != 0) {
243 syslog(LOG_ERR,
244 "%s: discard %d bytes", _PATH_LCKFIFO, nr);
245 }
246#ifdef USE_NFSLOCKDWAIT_INSTEAD_OF_SELECT
247 else
248 nfsclnt(NFSCLNT_LOCKDWAIT, NULL);
249#endif
250 }
251
252 /* Reached only on error. */
253err:
ac2f15b3
A
254 (void) nfsclnt(NFSCLNT_LOCKDFD, (struct lockd_ans *)-1);
255 _exit (1);
256 return 0;
257}
258
259void
260set_auth(cl, xucred)
261 CLIENT *cl;
262 struct xucred *xucred;
263{
264 if (cl->cl_auth != NULL)
265 cl->cl_auth->ah_ops->ah_destroy(cl->cl_auth);
266 cl->cl_auth = authunix_create(hostname,
267 xucred->cr_uid,
268 xucred->cr_groups[0],
269 xucred->cr_ngroups - 1,
270 &xucred->cr_groups[1]);
271}
272
273
274/*
275 * test_request --
276 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
277 */
278int
279test_request(LOCKD_MSG *msg)
280{
281 CLIENT *cli;
282 struct timeval timeout = {0, 0}; /* No timeout, no response. */
283 char dummy;
284
285 if (d_calls)
286 syslog(LOG_DEBUG, "test request: %s: %s to %s",
7902cf7e 287 (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
ac2f15b3
A
288 msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
289 from_addr((struct sockaddr *)&msg->lm_addr));
290
7902cf7e 291 if (msg->lm_flags & LOCKD_MSG_NFSV3) {
ac2f15b3
A
292 struct nlm4_testargs arg4;
293
7902cf7e
A
294 arg4.cookie.n_bytes = (char *)&msg->lm_xid;
295 arg4.cookie.n_len = sizeof(msg->lm_xid);
ac2f15b3
A
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);
7902cf7e 302 arg4.alock.svid = msg->lm_fl.l_pid;
ac2f15b3
A
303 arg4.alock.l_offset = msg->lm_fl.l_start;
304 arg4.alock.l_len = msg->lm_fl.l_len;
305
306 if ((cli = get_client(
307 (struct sockaddr *)&msg->lm_addr,
308 NLM_VERS4)) == NULL)
309 return (1);
310
311 set_auth(cli, &msg->lm_cred);
7902cf7e 312 (void)clnt_call(cli, NLM4_TEST_MSG,
ac2f15b3
A
313 xdr_nlm4_testargs, &arg4, xdr_void, &dummy, timeout);
314 } else {
315 struct nlm_testargs arg;
316
7902cf7e
A
317 arg.cookie.n_bytes = (char *)&msg->lm_xid;
318 arg.cookie.n_len = sizeof(msg->lm_xid);
ac2f15b3
A
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);
7902cf7e 325 arg.alock.svid = msg->lm_fl.l_pid;
ac2f15b3
A
326 arg.alock.l_offset = msg->lm_fl.l_start;
327 arg.alock.l_len = msg->lm_fl.l_len;
328
329 if ((cli = get_client(
330 (struct sockaddr *)&msg->lm_addr,
331 NLM_VERS)) == NULL)
332 return (1);
333
334 set_auth(cli, &msg->lm_cred);
335 (void)clnt_call(cli, NLM_TEST_MSG,
336 xdr_nlm_testargs, &arg, xdr_void, &dummy, timeout);
337 }
338 return (0);
339}
340
341/*
342 * lock_request --
343 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
344 */
345int
346lock_request(LOCKD_MSG *msg)
347{
348 CLIENT *cli;
349 struct nlm4_lockargs arg4;
350 struct nlm_lockargs arg;
351 struct timeval timeout = {0, 0}; /* No timeout, no response. */
352 char dummy;
353
354 if (d_calls)
355 syslog(LOG_DEBUG, "lock request: %s: %s to %s",
7902cf7e 356 (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
ac2f15b3
A
357 msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
358 from_addr((struct sockaddr *)&msg->lm_addr));
359
7902cf7e
A
360 if (msg->lm_flags & LOCKD_MSG_NFSV3) {
361 arg4.cookie.n_bytes = (char *)&msg->lm_xid;
362 arg4.cookie.n_len = sizeof(msg->lm_xid);
363 arg4.block = (msg->lm_flags & LOCKD_MSG_BLOCK) ? 1 : 0;
ac2f15b3
A
364 arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
365 arg4.alock.caller_name = hostname;
366 arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
367 arg4.alock.fh.n_len = msg->lm_fh_len;
368 arg4.alock.oh.n_bytes = (char *)&owner;
369 arg4.alock.oh.n_len = sizeof(owner);
7902cf7e 370 arg4.alock.svid = msg->lm_fl.l_pid;
ac2f15b3
A
371 arg4.alock.l_offset = msg->lm_fl.l_start;
372 arg4.alock.l_len = msg->lm_fl.l_len;
373 arg4.reclaim = 0;
374 arg4.state = nsm_state;
375
376 if ((cli = get_client(
377 (struct sockaddr *)&msg->lm_addr,
378 NLM_VERS4)) == NULL)
379 return (1);
380
381 set_auth(cli, &msg->lm_cred);
7902cf7e 382 (void)clnt_call(cli, NLM4_LOCK_MSG,
ac2f15b3
A
383 xdr_nlm4_lockargs, &arg4, xdr_void, &dummy, timeout);
384 } else {
7902cf7e
A
385 arg.cookie.n_bytes = (char *)&msg->lm_xid;
386 arg.cookie.n_len = sizeof(msg->lm_xid);
387 arg.block = (msg->lm_flags & LOCKD_MSG_BLOCK) ? 1 : 0;
ac2f15b3
A
388 arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
389 arg.alock.caller_name = hostname;
390 arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
391 arg.alock.fh.n_len = msg->lm_fh_len;
392 arg.alock.oh.n_bytes = (char *)&owner;
393 arg.alock.oh.n_len = sizeof(owner);
7902cf7e 394 arg.alock.svid = msg->lm_fl.l_pid;
ac2f15b3
A
395 arg.alock.l_offset = msg->lm_fl.l_start;
396 arg.alock.l_len = msg->lm_fl.l_len;
397 arg.reclaim = 0;
398 arg.state = nsm_state;
399
400 if ((cli = get_client(
401 (struct sockaddr *)&msg->lm_addr,
402 NLM_VERS)) == NULL)
403 return (1);
404
405 set_auth(cli, &msg->lm_cred);
406 (void)clnt_call(cli, NLM_LOCK_MSG,
407 xdr_nlm_lockargs, &arg, xdr_void, &dummy, timeout);
408 }
409 return (0);
410}
411
7902cf7e
A
412/*
413 * cancel_request --
414 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
415 */
416int
417cancel_request(LOCKD_MSG *msg)
418{
419 CLIENT *cli;
420 struct nlm4_cancargs arg4;
421 struct nlm_cancargs arg;
422 struct timeval timeout = {0, 0}; /* No timeout, no response. */
423 char dummy;
424
425 if (d_calls)
426 syslog(LOG_DEBUG, "cancel request: %s: %s to %s",
427 (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
428 msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
429 from_addr((struct sockaddr *)&msg->lm_addr));
430
431 if (msg->lm_flags & LOCKD_MSG_NFSV3) {
432 arg4.cookie.n_bytes = (char *)&msg->lm_xid;
433 arg4.cookie.n_len = sizeof(msg->lm_xid);
434 arg4.block = (msg->lm_flags & LOCKD_MSG_BLOCK) ? 1 : 0;
435 arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
436 arg4.alock.caller_name = hostname;
437 arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
438 arg4.alock.fh.n_len = msg->lm_fh_len;
439 arg4.alock.oh.n_bytes = (char *)&owner;
440 arg4.alock.oh.n_len = sizeof(owner);
441 arg4.alock.svid = msg->lm_fl.l_pid;
442 arg4.alock.l_offset = msg->lm_fl.l_start;
443 arg4.alock.l_len = msg->lm_fl.l_len;
444
445 if ((cli = get_client(
446 (struct sockaddr *)&msg->lm_addr, NLM_VERS4)) == NULL)
447 return (1);
448
449 set_auth(cli, &msg->lm_cred);
450 (void)clnt_call(cli, NLM4_CANCEL_MSG,
451 xdr_nlm4_cancargs, &arg4, xdr_void, &dummy, timeout);
452 } else {
453 arg.cookie.n_bytes = (char *)&msg->lm_xid;
454 arg.cookie.n_len = sizeof(msg->lm_xid);
455 arg.block = (msg->lm_flags & LOCKD_MSG_BLOCK) ? 1 : 0;
456 arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
457 arg.alock.caller_name = hostname;
458 arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
459 arg.alock.fh.n_len = msg->lm_fh_len;
460 arg.alock.oh.n_bytes = (char *)&owner;
461 arg.alock.oh.n_len = sizeof(owner);
462 arg.alock.svid = msg->lm_fl.l_pid;
463 arg.alock.l_offset = msg->lm_fl.l_start;
464 arg.alock.l_len = msg->lm_fl.l_len;
465
466 if ((cli = get_client(
467 (struct sockaddr *)&msg->lm_addr, NLM_VERS)) == NULL)
468 return (1);
469
470 set_auth(cli, &msg->lm_cred);
471 (void)clnt_call(cli, NLM_CANCEL_MSG,
472 xdr_nlm_cancargs, &arg, xdr_void, &dummy, timeout);
473 }
474 return (0);
475}
476
ac2f15b3
A
477/*
478 * unlock_request --
479 * Convert an unlock LOCKD_MSG into an NLM request, and send it off.
480 */
481int
482unlock_request(LOCKD_MSG *msg)
483{
484 CLIENT *cli;
485 struct nlm4_unlockargs arg4;
486 struct nlm_unlockargs arg;
487 struct timeval timeout = {0, 0}; /* No timeout, no response. */
488 char dummy;
489
490 if (d_calls)
491 syslog(LOG_DEBUG, "unlock request: %s: to %s",
7902cf7e 492 (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
ac2f15b3
A
493 from_addr((struct sockaddr *)&msg->lm_addr));
494
7902cf7e
A
495 if (msg->lm_flags & LOCKD_MSG_NFSV3) {
496 arg4.cookie.n_bytes = (char *)&msg->lm_xid;
497 arg4.cookie.n_len = sizeof(msg->lm_xid);
ac2f15b3
A
498 arg4.alock.caller_name = hostname;
499 arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
500 arg4.alock.fh.n_len = msg->lm_fh_len;
501 arg4.alock.oh.n_bytes = (char *)&owner;
502 arg4.alock.oh.n_len = sizeof(owner);
7902cf7e 503 arg4.alock.svid = msg->lm_fl.l_pid;
ac2f15b3
A
504 arg4.alock.l_offset = msg->lm_fl.l_start;
505 arg4.alock.l_len = msg->lm_fl.l_len;
506
507 if ((cli = get_client(
508 (struct sockaddr *)&msg->lm_addr,
509 NLM_VERS4)) == NULL)
510 return (1);
511
512 set_auth(cli, &msg->lm_cred);
7902cf7e 513 (void)clnt_call(cli, NLM4_UNLOCK_MSG,
ac2f15b3
A
514 xdr_nlm4_unlockargs, &arg4, xdr_void, &dummy, timeout);
515 } else {
7902cf7e
A
516 arg.cookie.n_bytes = (char *)&msg->lm_xid;
517 arg.cookie.n_len = sizeof(msg->lm_xid);
ac2f15b3
A
518 arg.alock.caller_name = hostname;
519 arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
520 arg.alock.fh.n_len = msg->lm_fh_len;
521 arg.alock.oh.n_bytes = (char *)&owner;
522 arg.alock.oh.n_len = sizeof(owner);
7902cf7e 523 arg.alock.svid = msg->lm_fl.l_pid;
ac2f15b3
A
524 arg.alock.l_offset = msg->lm_fl.l_start;
525 arg.alock.l_len = msg->lm_fl.l_len;
526
527 if ((cli = get_client(
528 (struct sockaddr *)&msg->lm_addr,
529 NLM_VERS)) == NULL)
530 return (1);
531
532 set_auth(cli, &msg->lm_cred);
533 (void)clnt_call(cli, NLM_UNLOCK_MSG,
534 xdr_nlm_unlockargs, &arg, xdr_void, &dummy, timeout);
535 }
536
537 return (0);
538}
539
540int
7902cf7e 541lock_answer(int version, netobj *netcookie, nlm4_lock *lock, int flags, int result)
ac2f15b3
A
542{
543 struct lockd_ans ans;
544
7902cf7e
A
545 ans.la_flags = 0;
546 if (flags & LOCK_ANSWER_GRANTED)
547 ans.la_flags |= LOCKD_ANS_GRANTED;
548
549 if (netcookie->n_len != sizeof(ans.la_xid)) {
550 if (lock == NULL) { /* we're screwed */
ac2f15b3
A
551 syslog(LOG_ERR, "inedible nlm cookie");
552 return -1;
553 }
7902cf7e
A
554 /* no/bad cookie - need to copy lock info to identify request */
555 ans.la_xid = 0;
556 /* copy lock info */
557 ans.la_fh_len = lock->fh.n_len;
558 if (!lock->fh.n_len || (lock->fh.n_len > NFS_SMALLFH)) {
559 syslog(LOG_ERR, "bogus filehandle size %d in answer", lock->fh.n_len);
560 return -1;
561 }
562 memcpy(ans.la_fh, lock->fh.n_bytes, ans.la_fh_len);
563 ans.la_pid = lock->svid;
564 ans.la_start = lock->l_offset;
565 ans.la_len = lock->l_len;
566 ans.la_flags |= LOCKD_ANS_LOCK_INFO;
567 if (flags & LOCK_ANSWER_LOCK_EXCL)
568 ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
ac2f15b3 569 } else {
7902cf7e
A
570 memcpy(&ans.la_xid, netcookie->n_bytes, sizeof(ans.la_xid));
571 ans.la_fh_len = 0;
ac2f15b3
A
572 }
573
574 if (d_calls)
575 syslog(LOG_DEBUG, "lock answer: pid %lu: %s %d",
7902cf7e 576 (unsigned long)ans.la_pid,
ac2f15b3
A
577 version == NLM_VERS4 ? "nlmv4" : "nlmv3",
578 result);
579
ac2f15b3
A
580 if (version == NLM_VERS4)
581 switch (result) {
582 case nlm4_granted:
583 ans.la_errno = 0;
7902cf7e
A
584 if ((flags & LOCK_ANSWER_GRANTED) && lock &&
585 !(ans.la_flags & LOCKD_ANS_LOCK_INFO)) {
586 /* copy lock info */
587 ans.la_fh_len = lock->fh.n_len;
588 if (!lock->fh.n_len || (lock->fh.n_len > NFS_SMALLFH)) {
589 syslog(LOG_ERR, "bogus filehandle size %d in answer", lock->fh.n_len);
590 return -1;
591 }
592 memcpy(ans.la_fh, lock->fh.n_bytes, ans.la_fh_len);
593 ans.la_pid = lock->svid;
594 ans.la_start = lock->l_offset;
595 ans.la_len = lock->l_len;
596 ans.la_flags |= LOCKD_ANS_LOCK_INFO;
597 if (flags & LOCK_ANSWER_LOCK_EXCL)
598 ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
599 }
ac2f15b3
A
600 break;
601 default:
602 ans.la_errno = EACCES;
603 break;
604 case nlm4_denied:
7902cf7e 605 if (lock == NULL)
ac2f15b3
A
606 ans.la_errno = EACCES;
607 else {
608 /* this is an answer to a nlm_test msg */
7902cf7e
A
609 ans.la_pid = lock->svid;
610 ans.la_start = lock->l_offset;
611 ans.la_len = lock->l_len;
612 ans.la_flags |= LOCKD_ANS_LOCK_INFO;
613 if (flags & LOCK_ANSWER_LOCK_EXCL)
614 ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
ac2f15b3
A
615 ans.la_errno = 0;
616 }
617 break;
618 case nlm4_denied_nolocks:
619 ans.la_errno = ENOLCK;
620 break;
621 case nlm4_blocked:
7902cf7e
A
622 ans.la_errno = EINPROGRESS;
623 break;
ac2f15b3
A
624 case nlm4_denied_grace_period:
625 ans.la_errno = EAGAIN;
626 break;
627 case nlm4_deadlck:
628 ans.la_errno = EDEADLK;
629 break;
630 case nlm4_rofs:
631 ans.la_errno = EROFS;
632 break;
633 case nlm4_stale_fh:
634 ans.la_errno = ESTALE;
635 break;
636 case nlm4_fbig:
637 ans.la_errno = EFBIG;
638 break;
639 case nlm4_failed:
640 ans.la_errno = EACCES;
641 break;
642 }
643 else
644 switch (result) {
645 case nlm_granted:
646 ans.la_errno = 0;
7902cf7e
A
647 if ((flags & LOCK_ANSWER_GRANTED) && lock &&
648 !(ans.la_flags & LOCKD_ANS_LOCK_INFO)) {
649 /* copy lock info */
650 ans.la_fh_len = lock->fh.n_len;
651 if (!lock->fh.n_len || (lock->fh.n_len > NFS_SMALLFH)) {
652 syslog(LOG_ERR, "bogus filehandle size %d in answer", lock->fh.n_len);
653 return -1;
654 }
655 memcpy(ans.la_fh, lock->fh.n_bytes, ans.la_fh_len);
656 ans.la_pid = lock->svid;
657 ans.la_start = lock->l_offset;
658 ans.la_len = lock->l_len;
659 ans.la_flags |= LOCKD_ANS_LOCK_INFO;
660 if (flags & LOCK_ANSWER_LOCK_EXCL)
661 ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
662 }
ac2f15b3
A
663 break;
664 default:
665 ans.la_errno = EACCES;
666 break;
667 case nlm_denied:
7902cf7e 668 if (lock == NULL)
ac2f15b3
A
669 ans.la_errno = EACCES;
670 else {
671 /* this is an answer to a nlm_test msg */
7902cf7e
A
672 ans.la_pid = lock->svid;
673 ans.la_start = lock->l_offset;
674 ans.la_len = lock->l_len;
675 ans.la_flags |= LOCKD_ANS_LOCK_INFO;
676 if (flags & LOCK_ANSWER_LOCK_EXCL)
677 ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
ac2f15b3
A
678 ans.la_errno = 0;
679 }
680 break;
681 case nlm_denied_nolocks:
682 ans.la_errno = ENOLCK;
683 break;
684 case nlm_blocked:
7902cf7e
A
685 ans.la_errno = EINPROGRESS;
686 break;
ac2f15b3
A
687 case nlm_denied_grace_period:
688 ans.la_errno = EAGAIN;
689 break;
690 case nlm_deadlck:
691 ans.la_errno = EDEADLK;
692 break;
693 }
694
695 if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
696 syslog(LOG_DEBUG, "lock_answer(%d): process %lu: %m",
7902cf7e 697 result, (u_long)ans.la_pid);
ac2f15b3
A
698 return -1;
699 }
700 return 0;
701}
702
703/*
704 * show --
705 * Display the contents of a kernel LOCKD_MSG structure.
706 */
707void
708show(LOCKD_MSG *mp)
709{
710 static char hex[] = "0123456789abcdef";
711 struct fid *fidp;
712 fsid_t *fsidp;
713 size_t len;
714 u_int8_t *p, *t, buf[NFS_SMALLFH*3+1];
715
7902cf7e 716 syslog(LOG_DEBUG, "process ID: %lu\n", (long)mp->lm_fl.l_pid);
ac2f15b3
A
717
718 fsidp = (fsid_t *)&mp->lm_fh;
719 fidp = (struct fid *)((u_int8_t *)&mp->lm_fh + sizeof(fsid_t));
720
721 for (t = buf, p = (u_int8_t *)mp->lm_fh,
722 len = mp->lm_fh_len;
723 len > 0; ++p, --len) {
724 *t++ = '\\';
725 *t++ = hex[(*p & 0xf0) >> 4];
726 *t++ = hex[*p & 0x0f];
727 }
728 *t = '\0';
729
730 syslog(LOG_DEBUG, "fh_len %d, fh %s\n", mp->lm_fh_len, buf);
731
732 /* Show flock structure. */
733 syslog(LOG_DEBUG, "start %qu; len %qu; pid %lu; type %d; whence %d\n",
734 mp->lm_fl.l_start, mp->lm_fl.l_len, (u_long)mp->lm_fl.l_pid,
735 mp->lm_fl.l_type, mp->lm_fl.l_whence);
736
737 /* Show wait flag. */
7902cf7e 738 syslog(LOG_DEBUG, "wait was %s\n", (mp->lm_flags & LOCKD_MSG_BLOCK) ? "set" : "not set");
ac2f15b3 739}