]> git.saurik.com Git - apple/network_cmds.git/blob - rpc_lockd.tproj/kern.c
network_cmds-176.3.3.tar.gz
[apple/network_cmds.git] / rpc_lockd.tproj / kern.c
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
61 #define nfslockdans(_v, _ansp) \
62 ((_ansp)->la_version = (_v), \
63 nfsclnt(NFSCLNT_LOCKDANS, (_ansp)))
64
65
66 /* Lock request owner. */
67 typedef struct __owner {
68 pid_t pid; /* Process ID. */
69 time_t tod; /* Time-of-day. */
70 } OWNER;
71 static OWNER owner;
72
73 static char hostname[MAXHOSTNAMELEN + 1]; /* Hostname. */
74
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 *);
82
83 #define d_calls (debug_level > 1)
84 #define d_args (debug_level > 2)
85
86 static const char *
87 from_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 */
103 void
104 client_kern_wait(void)
105 {
106 if (nfsclnt(NFSCLNT_LOCKDWAIT, NULL))
107 warn("nfsclnt_lockdwait");
108 }
109
110 void
111 client_cleanup(void)
112 {
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 */
122 pid_t
123 client_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;
136 mode_t old_umask;
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);
171 _exit (1);
172 }
173 (void)unlink(_PATH_LCKFIFO);
174 if (nfsclnt(NFSCLNT_LOCKDFD, (struct lockd_ans *)fd)) {
175 syslog(LOG_ERR, "nfsclnt_fd: %d: %m", fd);
176 _exit (1);
177 }
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:
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);
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
225 ans.la_xid = msg.lm_xid;
226 ans.la_errno = ENOTSUP;
227
228 if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
229 syslog(LOG_DEBUG, "process %lu: %m",
230 (u_long)msg.lm_fl.l_pid);
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. */
253 err:
254 (void) nfsclnt(NFSCLNT_LOCKDFD, (struct lockd_ans *)-1);
255 _exit (1);
256 return 0;
257 }
258
259 void
260 set_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 */
278 int
279 test_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",
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));
290
291 if (msg->lm_flags & LOCKD_MSG_NFSV3) {
292 struct nlm4_testargs arg4;
293
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;
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);
312 (void)clnt_call(cli, NLM4_TEST_MSG,
313 xdr_nlm4_testargs, &arg4, xdr_void, &dummy, timeout);
314 } else {
315 struct nlm_testargs arg;
316
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;
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 */
345 int
346 lock_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",
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));
359
360 monitor_lock_host_by_addr((struct sockaddr *)&msg->lm_addr);
361
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;
375 arg4.reclaim = 0;
376 arg4.state = nsm_state;
377
378 if ((cli = get_client(
379 (struct sockaddr *)&msg->lm_addr,
380 NLM_VERS4)) == NULL)
381 return (1);
382
383 set_auth(cli, &msg->lm_cred);
384 (void)clnt_call(cli, NLM4_LOCK_MSG,
385 xdr_nlm4_lockargs, &arg4, xdr_void, &dummy, timeout);
386 } else {
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;
399 arg.reclaim = 0;
400 arg.state = nsm_state;
401
402 if ((cli = get_client(
403 (struct sockaddr *)&msg->lm_addr,
404 NLM_VERS)) == NULL)
405 return (1);
406
407 set_auth(cli, &msg->lm_cred);
408 (void)clnt_call(cli, NLM_LOCK_MSG,
409 xdr_nlm_lockargs, &arg, xdr_void, &dummy, timeout);
410 }
411 return (0);
412 }
413
414 /*
415 * cancel_request --
416 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
417 */
418 int
419 cancel_request(LOCKD_MSG *msg)
420 {
421 CLIENT *cli;
422 struct nlm4_cancargs arg4;
423 struct nlm_cancargs arg;
424 struct timeval timeout = {0, 0}; /* No timeout, no response. */
425 char dummy;
426
427 if (d_calls)
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));
432
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;
446
447 if ((cli = get_client(
448 (struct sockaddr *)&msg->lm_addr, NLM_VERS4)) == NULL)
449 return (1);
450
451 set_auth(cli, &msg->lm_cred);
452 (void)clnt_call(cli, NLM4_CANCEL_MSG,
453 xdr_nlm4_cancargs, &arg4, xdr_void, &dummy, timeout);
454 } else {
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;
467
468 if ((cli = get_client(
469 (struct sockaddr *)&msg->lm_addr, NLM_VERS)) == NULL)
470 return (1);
471
472 set_auth(cli, &msg->lm_cred);
473 (void)clnt_call(cli, NLM_CANCEL_MSG,
474 xdr_nlm_cancargs, &arg, xdr_void, &dummy, timeout);
475 }
476 return (0);
477 }
478
479 /*
480 * unlock_request --
481 * Convert an unlock LOCKD_MSG into an NLM request, and send it off.
482 */
483 int
484 unlock_request(LOCKD_MSG *msg)
485 {
486 CLIENT *cli;
487 struct nlm4_unlockargs arg4;
488 struct nlm_unlockargs arg;
489 struct timeval timeout = {0, 0}; /* No timeout, no response. */
490 char dummy;
491
492 if (d_calls)
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));
496
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;
508
509 if ((cli = get_client(
510 (struct sockaddr *)&msg->lm_addr,
511 NLM_VERS4)) == NULL)
512 return (1);
513
514 set_auth(cli, &msg->lm_cred);
515 (void)clnt_call(cli, NLM4_UNLOCK_MSG,
516 xdr_nlm4_unlockargs, &arg4, xdr_void, &dummy, timeout);
517 } else {
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;
528
529 if ((cli = get_client(
530 (struct sockaddr *)&msg->lm_addr,
531 NLM_VERS)) == NULL)
532 return (1);
533
534 set_auth(cli, &msg->lm_cred);
535 (void)clnt_call(cli, NLM_UNLOCK_MSG,
536 xdr_nlm_unlockargs, &arg, xdr_void, &dummy, timeout);
537 }
538
539 return (0);
540 }
541
542 int
543 lock_answer(int version, netobj *netcookie, nlm4_lock *lock, int flags, int result)
544 {
545 struct lockd_ans ans;
546
547 ans.la_flags = 0;
548 if (flags & LOCK_ANSWER_GRANTED)
549 ans.la_flags |= LOCKD_ANS_GRANTED;
550
551 if (netcookie->n_len != sizeof(ans.la_xid)) {
552 if (lock == NULL) { /* we're screwed */
553 syslog(LOG_ERR, "inedible nlm cookie");
554 return -1;
555 }
556 /* no/bad cookie - need to copy lock info to identify request */
557 ans.la_xid = 0;
558 /* copy lock info */
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);
562 return -1;
563 }
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;
571 } else {
572 memcpy(&ans.la_xid, netcookie->n_bytes, sizeof(ans.la_xid));
573 ans.la_fh_len = 0;
574 }
575
576 if (d_calls)
577 syslog(LOG_DEBUG, "lock answer: pid %lu: %s %d",
578 (unsigned long)ans.la_pid,
579 version == NLM_VERS4 ? "nlmv4" : "nlmv3",
580 result);
581
582 if (version == NLM_VERS4)
583 switch (result) {
584 case nlm4_granted:
585 ans.la_errno = 0;
586 if ((flags & LOCK_ANSWER_GRANTED) && lock &&
587 !(ans.la_flags & LOCKD_ANS_LOCK_INFO)) {
588 /* copy 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);
592 return -1;
593 }
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;
601 }
602 break;
603 default:
604 ans.la_errno = EACCES;
605 break;
606 case nlm4_denied:
607 if (lock == NULL)
608 ans.la_errno = EACCES;
609 else {
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;
617 ans.la_errno = 0;
618 }
619 break;
620 case nlm4_denied_nolocks:
621 ans.la_errno = ENOLCK;
622 break;
623 case nlm4_blocked:
624 ans.la_errno = EINPROGRESS;
625 break;
626 case nlm4_denied_grace_period:
627 ans.la_errno = EAGAIN;
628 break;
629 case nlm4_deadlck:
630 ans.la_errno = EDEADLK;
631 break;
632 case nlm4_rofs:
633 ans.la_errno = EROFS;
634 break;
635 case nlm4_stale_fh:
636 ans.la_errno = ESTALE;
637 break;
638 case nlm4_fbig:
639 ans.la_errno = EFBIG;
640 break;
641 case nlm4_failed:
642 ans.la_errno = EACCES;
643 break;
644 }
645 else
646 switch (result) {
647 case nlm_granted:
648 ans.la_errno = 0;
649 if ((flags & LOCK_ANSWER_GRANTED) && lock &&
650 !(ans.la_flags & LOCKD_ANS_LOCK_INFO)) {
651 /* copy 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);
655 return -1;
656 }
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;
664 }
665 break;
666 default:
667 ans.la_errno = EACCES;
668 break;
669 case nlm_denied:
670 if (lock == NULL)
671 ans.la_errno = EACCES;
672 else {
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;
680 ans.la_errno = 0;
681 }
682 break;
683 case nlm_denied_nolocks:
684 ans.la_errno = ENOLCK;
685 break;
686 case nlm_blocked:
687 ans.la_errno = EINPROGRESS;
688 break;
689 case nlm_denied_grace_period:
690 ans.la_errno = EAGAIN;
691 break;
692 case nlm_deadlck:
693 ans.la_errno = EDEADLK;
694 break;
695 }
696
697 if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
698 syslog(LOG_DEBUG, "lock_answer(%d): process %lu: %m",
699 result, (u_long)ans.la_pid);
700 return -1;
701 }
702 return 0;
703 }
704
705 /*
706 * show --
707 * Display the contents of a kernel LOCKD_MSG structure.
708 */
709 void
710 show(LOCKD_MSG *mp)
711 {
712 static char hex[] = "0123456789abcdef";
713 struct fid *fidp;
714 fsid_t *fsidp;
715 size_t len;
716 u_int8_t *p, *t, buf[NFS_SMALLFH*3+1];
717
718 syslog(LOG_DEBUG, "process ID: %lu\n", (long)mp->lm_fl.l_pid);
719
720 fsidp = (fsid_t *)&mp->lm_fh;
721 fidp = (struct fid *)((u_int8_t *)&mp->lm_fh + sizeof(fsid_t));
722
723 for (t = buf, p = (u_int8_t *)mp->lm_fh,
724 len = mp->lm_fh_len;
725 len > 0; ++p, --len) {
726 *t++ = '\\';
727 *t++ = hex[(*p & 0xf0) >> 4];
728 *t++ = hex[*p & 0x0f];
729 }
730 *t = '\0';
731
732 syslog(LOG_DEBUG, "fh_len %d, fh %s\n", mp->lm_fh_len, buf);
733
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);
738
739 /* Show wait flag. */
740 syslog(LOG_DEBUG, "wait was %s\n", (mp->lm_flags & LOCKD_MSG_BLOCK) ? "set" : "not set");
741 }