]> git.saurik.com Git - apple/network_cmds.git/blob - rpc_lockd.tproj/kern.c
network_cmds-245.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 fd_set rdset;
127 int fd, nr, ret;
128 pid_t child;
129 mode_t old_umask;
130
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);
136 exit (1);
137 }
138 umask(old_umask);
139
140 /*
141 * Create a separate process, the client code is really a separate
142 * daemon that shares a lot of code.
143 */
144 switch (child = fork()) {
145 case -1:
146 err(1, "fork");
147 case 0:
148 break;
149 default:
150 return (child);
151 }
152
153 signal(SIGHUP, (sig_t)client_cleanup);
154 signal(SIGTERM, (sig_t)client_cleanup);
155
156 /* Setup. */
157 (void)time(&owner.tod);
158 owner.pid = getpid();
159 (void)gethostname(hostname, sizeof(hostname) - 1);
160
161 /* Open the fifo for reading. */
162 if ((fd = open(_PATH_LCKFIFO, O_RDONLY | O_NONBLOCK)) == -1) {
163 syslog(LOG_ERR, "open: %s: %m", _PATH_LCKFIFO);
164 _exit (1);
165 }
166 (void)unlink(_PATH_LCKFIFO);
167 if (nfsclnt(NFSCLNT_LOCKDFD, (struct lockd_ans *)fd)) {
168 syslog(LOG_ERR, "nfsclnt_fd: %d: %m", fd);
169 _exit (1);
170 }
171
172 for (;;) {
173 /* Wait for contact... fifo's return EAGAIN when read with
174 * no data
175 */
176 /* Set up the select. */
177 FD_ZERO(&rdset);
178 FD_SET(fd, &rdset);
179 (void)select(fd + 1, &rdset, NULL, NULL, NULL);
180
181 /* Read the fixed length message. */
182 if ((nr = read(fd, &msg, sizeof(msg))) == sizeof(msg)) {
183 if (d_args)
184 show(&msg);
185
186 if (msg.lm_version != LOCKD_MSG_VERSION) {
187 syslog(LOG_ERR,
188 "unknown msg type: %d", msg.lm_version);
189 }
190 /*
191 * Send it to the NLM server and don't grant the lock
192 * if we fail for any reason.
193 */
194 switch (msg.lm_fl.l_type) {
195 case F_RDLCK:
196 case F_WRLCK:
197 if (msg.lm_flags & LOCKD_MSG_TEST)
198 ret = test_request(&msg);
199 else if (msg.lm_flags & LOCKD_MSG_CANCEL)
200 ret = cancel_request(&msg);
201 else
202 ret = lock_request(&msg);
203 break;
204 case F_UNLCK:
205 ret = unlock_request(&msg);
206 break;
207 default:
208 ret = 1;
209 syslog(LOG_ERR,
210 "unknown lock type: %d", msg.lm_fl.l_type);
211 break;
212 }
213 if (ret) {
214 struct lockd_ans ans;
215
216 ans.la_xid = msg.lm_xid;
217 ans.la_errno = ENOTSUP;
218
219 if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
220 syslog(LOG_DEBUG, "process %lu: %m",
221 (u_long)msg.lm_fl.l_pid);
222 }
223 }
224 } else if (nr == -1) {
225 if (errno != EAGAIN) {
226 syslog(LOG_ERR, "read: %s: %m", _PATH_LCKFIFO);
227 goto err;
228 }
229 } else if (nr != 0) {
230 syslog(LOG_ERR,
231 "%s: discard %d bytes", _PATH_LCKFIFO, nr);
232 }
233 }
234
235 /* Reached only on error. */
236 err:
237 (void) nfsclnt(NFSCLNT_LOCKDFD, (struct lockd_ans *)-1);
238 _exit (1);
239 return 0;
240 }
241
242 void
243 set_auth(cl, xucred)
244 CLIENT *cl;
245 struct xucred *xucred;
246 {
247 if (cl->cl_auth != NULL)
248 cl->cl_auth->ah_ops->ah_destroy(cl->cl_auth);
249 cl->cl_auth = authunix_create(hostname,
250 xucred->cr_uid,
251 xucred->cr_groups[0],
252 xucred->cr_ngroups - 1,
253 &xucred->cr_groups[1]);
254 }
255
256
257 /*
258 * test_request --
259 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
260 */
261 int
262 test_request(LOCKD_MSG *msg)
263 {
264 CLIENT *cli;
265 struct timeval timeout = {0, 0}; /* No timeout, no response. */
266 char dummy;
267
268 if (d_calls)
269 syslog(LOG_DEBUG, "test request: %s: %s to %s",
270 (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
271 msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
272 from_addr((struct sockaddr *)&msg->lm_addr));
273
274 if (msg->lm_flags & LOCKD_MSG_NFSV3) {
275 struct nlm4_testargs arg4;
276
277 arg4.cookie.n_bytes = (char *)&msg->lm_xid;
278 arg4.cookie.n_len = sizeof(msg->lm_xid);
279 arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
280 arg4.alock.caller_name = hostname;
281 arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
282 arg4.alock.fh.n_len = msg->lm_fh_len;
283 arg4.alock.oh.n_bytes = (char *)&owner;
284 arg4.alock.oh.n_len = sizeof(owner);
285 arg4.alock.svid = msg->lm_fl.l_pid;
286 arg4.alock.l_offset = msg->lm_fl.l_start;
287 arg4.alock.l_len = msg->lm_fl.l_len;
288
289 if ((cli = get_client(
290 (struct sockaddr *)&msg->lm_addr,
291 NLM_VERS4)) == NULL)
292 return (1);
293
294 set_auth(cli, &msg->lm_cred);
295 (void)clnt_call(cli, NLM4_TEST_MSG,
296 xdr_nlm4_testargs, &arg4, xdr_void, &dummy, timeout);
297 } else {
298 struct nlm_testargs arg;
299
300 arg.cookie.n_bytes = (char *)&msg->lm_xid;
301 arg.cookie.n_len = sizeof(msg->lm_xid);
302 arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
303 arg.alock.caller_name = hostname;
304 arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
305 arg.alock.fh.n_len = msg->lm_fh_len;
306 arg.alock.oh.n_bytes = (char *)&owner;
307 arg.alock.oh.n_len = sizeof(owner);
308 arg.alock.svid = msg->lm_fl.l_pid;
309 arg.alock.l_offset = msg->lm_fl.l_start;
310 arg.alock.l_len = msg->lm_fl.l_len;
311
312 if ((cli = get_client(
313 (struct sockaddr *)&msg->lm_addr,
314 NLM_VERS)) == NULL)
315 return (1);
316
317 set_auth(cli, &msg->lm_cred);
318 (void)clnt_call(cli, NLM_TEST_MSG,
319 xdr_nlm_testargs, &arg, xdr_void, &dummy, timeout);
320 }
321 return (0);
322 }
323
324 /*
325 * lock_request --
326 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
327 */
328 int
329 lock_request(LOCKD_MSG *msg)
330 {
331 CLIENT *cli;
332 struct nlm4_lockargs arg4;
333 struct nlm_lockargs arg;
334 struct timeval timeout = {0, 0}; /* No timeout, no response. */
335 char dummy;
336
337 if (d_calls)
338 syslog(LOG_DEBUG, "lock request: %s: %s to %s",
339 (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
340 msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
341 from_addr((struct sockaddr *)&msg->lm_addr));
342
343 monitor_lock_host_by_addr((struct sockaddr *)&msg->lm_addr);
344
345 if (msg->lm_flags & LOCKD_MSG_NFSV3) {
346 arg4.cookie.n_bytes = (char *)&msg->lm_xid;
347 arg4.cookie.n_len = sizeof(msg->lm_xid);
348 arg4.block = (msg->lm_flags & LOCKD_MSG_BLOCK) ? 1 : 0;
349 arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
350 arg4.alock.caller_name = hostname;
351 arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
352 arg4.alock.fh.n_len = msg->lm_fh_len;
353 arg4.alock.oh.n_bytes = (char *)&owner;
354 arg4.alock.oh.n_len = sizeof(owner);
355 arg4.alock.svid = msg->lm_fl.l_pid;
356 arg4.alock.l_offset = msg->lm_fl.l_start;
357 arg4.alock.l_len = msg->lm_fl.l_len;
358 arg4.reclaim = 0;
359 arg4.state = nsm_state;
360
361 if ((cli = get_client(
362 (struct sockaddr *)&msg->lm_addr,
363 NLM_VERS4)) == NULL)
364 return (1);
365
366 set_auth(cli, &msg->lm_cred);
367 (void)clnt_call(cli, NLM4_LOCK_MSG,
368 xdr_nlm4_lockargs, &arg4, xdr_void, &dummy, timeout);
369 } else {
370 arg.cookie.n_bytes = (char *)&msg->lm_xid;
371 arg.cookie.n_len = sizeof(msg->lm_xid);
372 arg.block = (msg->lm_flags & LOCKD_MSG_BLOCK) ? 1 : 0;
373 arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
374 arg.alock.caller_name = hostname;
375 arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
376 arg.alock.fh.n_len = msg->lm_fh_len;
377 arg.alock.oh.n_bytes = (char *)&owner;
378 arg.alock.oh.n_len = sizeof(owner);
379 arg.alock.svid = msg->lm_fl.l_pid;
380 arg.alock.l_offset = msg->lm_fl.l_start;
381 arg.alock.l_len = msg->lm_fl.l_len;
382 arg.reclaim = 0;
383 arg.state = nsm_state;
384
385 if ((cli = get_client(
386 (struct sockaddr *)&msg->lm_addr,
387 NLM_VERS)) == NULL)
388 return (1);
389
390 set_auth(cli, &msg->lm_cred);
391 (void)clnt_call(cli, NLM_LOCK_MSG,
392 xdr_nlm_lockargs, &arg, xdr_void, &dummy, timeout);
393 }
394 return (0);
395 }
396
397 /*
398 * cancel_request --
399 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
400 */
401 int
402 cancel_request(LOCKD_MSG *msg)
403 {
404 CLIENT *cli;
405 struct nlm4_cancargs arg4;
406 struct nlm_cancargs arg;
407 struct timeval timeout = {0, 0}; /* No timeout, no response. */
408 char dummy;
409
410 if (d_calls)
411 syslog(LOG_DEBUG, "cancel request: %s: %s to %s",
412 (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
413 msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
414 from_addr((struct sockaddr *)&msg->lm_addr));
415
416 if (msg->lm_flags & LOCKD_MSG_NFSV3) {
417 arg4.cookie.n_bytes = (char *)&msg->lm_xid;
418 arg4.cookie.n_len = sizeof(msg->lm_xid);
419 arg4.block = (msg->lm_flags & LOCKD_MSG_BLOCK) ? 1 : 0;
420 arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
421 arg4.alock.caller_name = hostname;
422 arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
423 arg4.alock.fh.n_len = msg->lm_fh_len;
424 arg4.alock.oh.n_bytes = (char *)&owner;
425 arg4.alock.oh.n_len = sizeof(owner);
426 arg4.alock.svid = msg->lm_fl.l_pid;
427 arg4.alock.l_offset = msg->lm_fl.l_start;
428 arg4.alock.l_len = msg->lm_fl.l_len;
429
430 if ((cli = get_client(
431 (struct sockaddr *)&msg->lm_addr, NLM_VERS4)) == NULL)
432 return (1);
433
434 set_auth(cli, &msg->lm_cred);
435 (void)clnt_call(cli, NLM4_CANCEL_MSG,
436 xdr_nlm4_cancargs, &arg4, xdr_void, &dummy, timeout);
437 } else {
438 arg.cookie.n_bytes = (char *)&msg->lm_xid;
439 arg.cookie.n_len = sizeof(msg->lm_xid);
440 arg.block = (msg->lm_flags & LOCKD_MSG_BLOCK) ? 1 : 0;
441 arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0;
442 arg.alock.caller_name = hostname;
443 arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
444 arg.alock.fh.n_len = msg->lm_fh_len;
445 arg.alock.oh.n_bytes = (char *)&owner;
446 arg.alock.oh.n_len = sizeof(owner);
447 arg.alock.svid = msg->lm_fl.l_pid;
448 arg.alock.l_offset = msg->lm_fl.l_start;
449 arg.alock.l_len = msg->lm_fl.l_len;
450
451 if ((cli = get_client(
452 (struct sockaddr *)&msg->lm_addr, NLM_VERS)) == NULL)
453 return (1);
454
455 set_auth(cli, &msg->lm_cred);
456 (void)clnt_call(cli, NLM_CANCEL_MSG,
457 xdr_nlm_cancargs, &arg, xdr_void, &dummy, timeout);
458 }
459 return (0);
460 }
461
462 /*
463 * unlock_request --
464 * Convert an unlock LOCKD_MSG into an NLM request, and send it off.
465 */
466 int
467 unlock_request(LOCKD_MSG *msg)
468 {
469 CLIENT *cli;
470 struct nlm4_unlockargs arg4;
471 struct nlm_unlockargs arg;
472 struct timeval timeout = {0, 0}; /* No timeout, no response. */
473 char dummy;
474
475 if (d_calls)
476 syslog(LOG_DEBUG, "unlock request: %s: to %s",
477 (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
478 from_addr((struct sockaddr *)&msg->lm_addr));
479
480 if (msg->lm_flags & LOCKD_MSG_NFSV3) {
481 arg4.cookie.n_bytes = (char *)&msg->lm_xid;
482 arg4.cookie.n_len = sizeof(msg->lm_xid);
483 arg4.alock.caller_name = hostname;
484 arg4.alock.fh.n_bytes = (char *)&msg->lm_fh;
485 arg4.alock.fh.n_len = msg->lm_fh_len;
486 arg4.alock.oh.n_bytes = (char *)&owner;
487 arg4.alock.oh.n_len = sizeof(owner);
488 arg4.alock.svid = msg->lm_fl.l_pid;
489 arg4.alock.l_offset = msg->lm_fl.l_start;
490 arg4.alock.l_len = msg->lm_fl.l_len;
491
492 if ((cli = get_client(
493 (struct sockaddr *)&msg->lm_addr,
494 NLM_VERS4)) == NULL)
495 return (1);
496
497 set_auth(cli, &msg->lm_cred);
498 (void)clnt_call(cli, NLM4_UNLOCK_MSG,
499 xdr_nlm4_unlockargs, &arg4, xdr_void, &dummy, timeout);
500 } else {
501 arg.cookie.n_bytes = (char *)&msg->lm_xid;
502 arg.cookie.n_len = sizeof(msg->lm_xid);
503 arg.alock.caller_name = hostname;
504 arg.alock.fh.n_bytes = (char *)&msg->lm_fh;
505 arg.alock.fh.n_len = msg->lm_fh_len;
506 arg.alock.oh.n_bytes = (char *)&owner;
507 arg.alock.oh.n_len = sizeof(owner);
508 arg.alock.svid = msg->lm_fl.l_pid;
509 arg.alock.l_offset = msg->lm_fl.l_start;
510 arg.alock.l_len = msg->lm_fl.l_len;
511
512 if ((cli = get_client(
513 (struct sockaddr *)&msg->lm_addr,
514 NLM_VERS)) == NULL)
515 return (1);
516
517 set_auth(cli, &msg->lm_cred);
518 (void)clnt_call(cli, NLM_UNLOCK_MSG,
519 xdr_nlm_unlockargs, &arg, xdr_void, &dummy, timeout);
520 }
521
522 return (0);
523 }
524
525 int
526 lock_answer(int version, netobj *netcookie, nlm4_lock *lock, int flags, int result)
527 {
528 struct lockd_ans ans;
529
530 ans.la_flags = 0;
531 if (flags & LOCK_ANSWER_GRANTED)
532 ans.la_flags |= LOCKD_ANS_GRANTED;
533
534 if (netcookie->n_len != sizeof(ans.la_xid)) {
535 if (lock == NULL) { /* we're screwed */
536 syslog(LOG_ERR, "inedible nlm cookie");
537 return -1;
538 }
539 /* no/bad cookie - need to copy lock info to identify request */
540 ans.la_xid = 0;
541 /* copy lock info */
542 ans.la_fh_len = lock->fh.n_len;
543 if (!lock->fh.n_len || (lock->fh.n_len > NFS_SMALLFH)) {
544 syslog(LOG_ERR, "bogus filehandle size %d in answer", lock->fh.n_len);
545 return -1;
546 }
547 memcpy(ans.la_fh, lock->fh.n_bytes, ans.la_fh_len);
548 ans.la_pid = lock->svid;
549 ans.la_start = lock->l_offset;
550 ans.la_len = lock->l_len;
551 ans.la_flags |= LOCKD_ANS_LOCK_INFO;
552 if (flags & LOCK_ANSWER_LOCK_EXCL)
553 ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
554 } else {
555 memcpy(&ans.la_xid, netcookie->n_bytes, sizeof(ans.la_xid));
556 ans.la_fh_len = 0;
557 }
558
559 if (d_calls)
560 syslog(LOG_DEBUG, "lock answer: pid %lu: %s %d",
561 (unsigned long)ans.la_pid,
562 version == NLM_VERS4 ? "nlmv4" : "nlmv3",
563 result);
564
565 if (version == NLM_VERS4)
566 switch (result) {
567 case nlm4_granted:
568 ans.la_errno = 0;
569 if ((flags & LOCK_ANSWER_GRANTED) && lock &&
570 !(ans.la_flags & LOCKD_ANS_LOCK_INFO)) {
571 /* copy lock info */
572 ans.la_fh_len = lock->fh.n_len;
573 if (!lock->fh.n_len || (lock->fh.n_len > NFS_SMALLFH)) {
574 syslog(LOG_ERR, "bogus filehandle size %d in answer", lock->fh.n_len);
575 return -1;
576 }
577 memcpy(ans.la_fh, lock->fh.n_bytes, ans.la_fh_len);
578 ans.la_pid = lock->svid;
579 ans.la_start = lock->l_offset;
580 ans.la_len = lock->l_len;
581 ans.la_flags |= LOCKD_ANS_LOCK_INFO;
582 if (flags & LOCK_ANSWER_LOCK_EXCL)
583 ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
584 }
585 break;
586 default:
587 ans.la_errno = EACCES;
588 break;
589 case nlm4_denied:
590 if (lock == NULL)
591 ans.la_errno = EACCES;
592 else {
593 /* this is an answer to a nlm_test msg */
594 ans.la_pid = lock->svid;
595 ans.la_start = lock->l_offset;
596 ans.la_len = lock->l_len;
597 ans.la_flags |= LOCKD_ANS_LOCK_INFO;
598 if (flags & LOCK_ANSWER_LOCK_EXCL)
599 ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
600 ans.la_errno = 0;
601 }
602 break;
603 case nlm4_denied_nolocks:
604 ans.la_errno = ENOLCK;
605 break;
606 case nlm4_blocked:
607 ans.la_errno = EINPROGRESS;
608 break;
609 case nlm4_denied_grace_period:
610 ans.la_errno = EAGAIN;
611 break;
612 case nlm4_deadlck:
613 ans.la_errno = EDEADLK;
614 break;
615 case nlm4_rofs:
616 ans.la_errno = EROFS;
617 break;
618 case nlm4_stale_fh:
619 ans.la_errno = ESTALE;
620 break;
621 case nlm4_fbig:
622 ans.la_errno = EFBIG;
623 break;
624 case nlm4_failed:
625 ans.la_errno = EACCES;
626 break;
627 }
628 else
629 switch (result) {
630 case nlm_granted:
631 ans.la_errno = 0;
632 if ((flags & LOCK_ANSWER_GRANTED) && lock &&
633 !(ans.la_flags & LOCKD_ANS_LOCK_INFO)) {
634 /* copy lock info */
635 ans.la_fh_len = lock->fh.n_len;
636 if (!lock->fh.n_len || (lock->fh.n_len > NFS_SMALLFH)) {
637 syslog(LOG_ERR, "bogus filehandle size %d in answer", lock->fh.n_len);
638 return -1;
639 }
640 memcpy(ans.la_fh, lock->fh.n_bytes, ans.la_fh_len);
641 ans.la_pid = lock->svid;
642 ans.la_start = lock->l_offset;
643 ans.la_len = lock->l_len;
644 ans.la_flags |= LOCKD_ANS_LOCK_INFO;
645 if (flags & LOCK_ANSWER_LOCK_EXCL)
646 ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
647 }
648 break;
649 default:
650 ans.la_errno = EACCES;
651 break;
652 case nlm_denied:
653 if (lock == NULL)
654 ans.la_errno = EACCES;
655 else {
656 /* this is an answer to a nlm_test msg */
657 ans.la_pid = lock->svid;
658 ans.la_start = lock->l_offset;
659 ans.la_len = lock->l_len;
660 ans.la_flags |= LOCKD_ANS_LOCK_INFO;
661 if (flags & LOCK_ANSWER_LOCK_EXCL)
662 ans.la_flags |= LOCKD_ANS_LOCK_EXCL;
663 ans.la_errno = 0;
664 }
665 break;
666 case nlm_denied_nolocks:
667 ans.la_errno = ENOLCK;
668 break;
669 case nlm_blocked:
670 ans.la_errno = EINPROGRESS;
671 break;
672 case nlm_denied_grace_period:
673 ans.la_errno = EAGAIN;
674 break;
675 case nlm_deadlck:
676 ans.la_errno = EDEADLK;
677 break;
678 }
679
680 if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
681 syslog(LOG_DEBUG, "lock_answer(%d): process %lu: %m",
682 result, (u_long)ans.la_pid);
683 return -1;
684 }
685 return 0;
686 }
687
688 /*
689 * show --
690 * Display the contents of a kernel LOCKD_MSG structure.
691 */
692 void
693 show(LOCKD_MSG *mp)
694 {
695 static char hex[] = "0123456789abcdef";
696 size_t len;
697 u_int8_t *p, *t, buf[NFS_SMALLFH*3+1];
698
699 syslog(LOG_DEBUG, "process ID: %lu\n", (long)mp->lm_fl.l_pid);
700
701 for (t = buf, p = (u_int8_t *)mp->lm_fh,
702 len = mp->lm_fh_len;
703 len > 0; ++p, --len) {
704 *t++ = '\\';
705 *t++ = hex[(*p & 0xf0) >> 4];
706 *t++ = hex[*p & 0x0f];
707 }
708 *t = '\0';
709
710 syslog(LOG_DEBUG, "fh_len %d, fh %s\n", mp->lm_fh_len, buf);
711
712 /* Show flock structure. */
713 syslog(LOG_DEBUG, "start %qu; len %qu; pid %lu; type %d; whence %d\n",
714 mp->lm_fl.l_start, mp->lm_fl.l_len, (u_long)mp->lm_fl.l_pid,
715 mp->lm_fl.l_type, mp->lm_fl.l_whence);
716
717 /* Show wait flag. */
718 syslog(LOG_DEBUG, "wait was %s\n", (mp->lm_flags & LOCKD_MSG_BLOCK) ? "set" : "not set");
719 }