]> git.saurik.com Git - apple/network_cmds.git/blame - rpc_lockd.tproj/kern.c
network_cmds-245.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;
ac2f15b3 126 fd_set rdset;
ac2f15b3
A
127 int fd, nr, ret;
128 pid_t child;
ac2f15b3 129 mode_t old_umask;
ac2f15b3
A
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();
ac2f15b3
A
159
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);
7902cf7e 163 _exit (1);
ac2f15b3
A
164 }
165 (void)unlink(_PATH_LCKFIFO);
166 if (nfsclnt(NFSCLNT_LOCKDFD, (struct lockd_ans *)fd)) {
167 syslog(LOG_ERR, "nfsclnt_fd: %d: %m", fd);
7902cf7e 168 _exit (1);
ac2f15b3 169 }
ac2f15b3
A
170
171 for (;;) {
ac2f15b3
A
172 /* Wait for contact... fifo's return EAGAIN when read with
173 * no data
174 */
175 /* Set up the select. */
176 FD_ZERO(&rdset);
177 FD_SET(fd, &rdset);
178 (void)select(fd + 1, &rdset, NULL, NULL, NULL);
ac2f15b3 179
6720d03d
A
180 /*
181 * Hold off getting hostname until first
182 * lock request. Otherwise we risk getting
183 * an initial ".local" name.
184 */
185 if (hostname[0] == '\0')
186 (void)gethostname(hostname, sizeof(hostname) - 1);
187
ac2f15b3
A
188 /* Read the fixed length message. */
189 if ((nr = read(fd, &msg, sizeof(msg))) == sizeof(msg)) {
190 if (d_args)
191 show(&msg);
192
193 if (msg.lm_version != LOCKD_MSG_VERSION) {
194 syslog(LOG_ERR,
195 "unknown msg type: %d", msg.lm_version);
196 }
197 /*
198 * Send it to the NLM server and don't grant the lock
199 * if we fail for any reason.
200 */
201 switch (msg.lm_fl.l_type) {
202 case F_RDLCK:
203 case F_WRLCK:
7902cf7e 204 if (msg.lm_flags & LOCKD_MSG_TEST)
ac2f15b3 205 ret = test_request(&msg);
7902cf7e
A
206 else if (msg.lm_flags & LOCKD_MSG_CANCEL)
207 ret = cancel_request(&msg);
ac2f15b3
A
208 else
209 ret = lock_request(&msg);
210 break;
211 case F_UNLCK:
212 ret = unlock_request(&msg);
213 break;
214 default:
215 ret = 1;
216 syslog(LOG_ERR,
217 "unknown lock type: %d", msg.lm_fl.l_type);
218 break;
219 }
220 if (ret) {
221 struct lockd_ans ans;
222
7902cf7e 223 ans.la_xid = msg.lm_xid;
ac2f15b3
A
224 ans.la_errno = ENOTSUP;
225
226 if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
227 syslog(LOG_DEBUG, "process %lu: %m",
7902cf7e 228 (u_long)msg.lm_fl.l_pid);
ac2f15b3
A
229 }
230 }
231 } else if (nr == -1) {
232 if (errno != EAGAIN) {
233 syslog(LOG_ERR, "read: %s: %m", _PATH_LCKFIFO);
234 goto err;
235 }
ac2f15b3
A
236 } else if (nr != 0) {
237 syslog(LOG_ERR,
238 "%s: discard %d bytes", _PATH_LCKFIFO, nr);
239 }
ac2f15b3
A
240 }
241
242 /* Reached only on error. */
243err:
ac2f15b3
A
244 (void) nfsclnt(NFSCLNT_LOCKDFD, (struct lockd_ans *)-1);
245 _exit (1);
246 return 0;
247}
248
249void
250set_auth(cl, xucred)
251 CLIENT *cl;
252 struct xucred *xucred;
253{
254 if (cl->cl_auth != NULL)
255 cl->cl_auth->ah_ops->ah_destroy(cl->cl_auth);
256 cl->cl_auth = authunix_create(hostname,
257 xucred->cr_uid,
258 xucred->cr_groups[0],
259 xucred->cr_ngroups - 1,
260 &xucred->cr_groups[1]);
261}
262
263
264/*
265 * test_request --
266 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
267 */
268int
269test_request(LOCKD_MSG *msg)
270{
271 CLIENT *cli;
272 struct timeval timeout = {0, 0}; /* No timeout, no response. */
273 char dummy;
274
275 if (d_calls)
276 syslog(LOG_DEBUG, "test request: %s: %s to %s",
7902cf7e 277 (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
ac2f15b3
A
278 msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
279 from_addr((struct sockaddr *)&msg->lm_addr));
280
7902cf7e 281 if (msg->lm_flags & LOCKD_MSG_NFSV3) {
ac2f15b3
A
282 struct nlm4_testargs arg4;
283
7902cf7e
A
284 arg4.cookie.n_bytes = (char *)&msg->lm_xid;
285 arg4.cookie.n_len = sizeof(msg->lm_xid);
ac2f15b3
A
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);
7902cf7e 292 arg4.alock.svid = msg->lm_fl.l_pid;
ac2f15b3
A
293 arg4.alock.l_offset = msg->lm_fl.l_start;
294 arg4.alock.l_len = msg->lm_fl.l_len;
295
296 if ((cli = get_client(
297 (struct sockaddr *)&msg->lm_addr,
298 NLM_VERS4)) == NULL)
299 return (1);
300
301 set_auth(cli, &msg->lm_cred);
7902cf7e 302 (void)clnt_call(cli, NLM4_TEST_MSG,
ac2f15b3
A
303 xdr_nlm4_testargs, &arg4, xdr_void, &dummy, timeout);
304 } else {
305 struct nlm_testargs arg;
306
7902cf7e
A
307 arg.cookie.n_bytes = (char *)&msg->lm_xid;
308 arg.cookie.n_len = sizeof(msg->lm_xid);
ac2f15b3
A
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);
7902cf7e 315 arg.alock.svid = msg->lm_fl.l_pid;
ac2f15b3
A
316 arg.alock.l_offset = msg->lm_fl.l_start;
317 arg.alock.l_len = msg->lm_fl.l_len;
318
319 if ((cli = get_client(
320 (struct sockaddr *)&msg->lm_addr,
321 NLM_VERS)) == NULL)
322 return (1);
323
324 set_auth(cli, &msg->lm_cred);
325 (void)clnt_call(cli, NLM_TEST_MSG,
326 xdr_nlm_testargs, &arg, xdr_void, &dummy, timeout);
327 }
328 return (0);
329}
330
331/*
332 * lock_request --
333 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
334 */
335int
336lock_request(LOCKD_MSG *msg)
337{
338 CLIENT *cli;
339 struct nlm4_lockargs arg4;
340 struct nlm_lockargs arg;
341 struct timeval timeout = {0, 0}; /* No timeout, no response. */
342 char dummy;
343
344 if (d_calls)
345 syslog(LOG_DEBUG, "lock request: %s: %s to %s",
7902cf7e 346 (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
ac2f15b3
A
347 msg->lm_fl.l_type == F_WRLCK ? "write" : "read",
348 from_addr((struct sockaddr *)&msg->lm_addr));
349
ccaf7288
A
350 monitor_lock_host_by_addr((struct sockaddr *)&msg->lm_addr);
351
7902cf7e
A
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;
ac2f15b3
A
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);
7902cf7e 362 arg4.alock.svid = msg->lm_fl.l_pid;
ac2f15b3
A
363 arg4.alock.l_offset = msg->lm_fl.l_start;
364 arg4.alock.l_len = msg->lm_fl.l_len;
365 arg4.reclaim = 0;
366 arg4.state = nsm_state;
367
368 if ((cli = get_client(
369 (struct sockaddr *)&msg->lm_addr,
370 NLM_VERS4)) == NULL)
371 return (1);
372
373 set_auth(cli, &msg->lm_cred);
7902cf7e 374 (void)clnt_call(cli, NLM4_LOCK_MSG,
ac2f15b3
A
375 xdr_nlm4_lockargs, &arg4, xdr_void, &dummy, timeout);
376 } else {
7902cf7e
A
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;
ac2f15b3
A
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);
7902cf7e 386 arg.alock.svid = msg->lm_fl.l_pid;
ac2f15b3
A
387 arg.alock.l_offset = msg->lm_fl.l_start;
388 arg.alock.l_len = msg->lm_fl.l_len;
389 arg.reclaim = 0;
390 arg.state = nsm_state;
391
392 if ((cli = get_client(
393 (struct sockaddr *)&msg->lm_addr,
394 NLM_VERS)) == NULL)
395 return (1);
396
397 set_auth(cli, &msg->lm_cred);
398 (void)clnt_call(cli, NLM_LOCK_MSG,
399 xdr_nlm_lockargs, &arg, xdr_void, &dummy, timeout);
400 }
401 return (0);
402}
403
7902cf7e
A
404/*
405 * cancel_request --
406 * Convert a lock LOCKD_MSG into an NLM request, and send it off.
407 */
408int
409cancel_request(LOCKD_MSG *msg)
410{
411 CLIENT *cli;
412 struct nlm4_cancargs arg4;
413 struct nlm_cancargs arg;
414 struct timeval timeout = {0, 0}; /* No timeout, no response. */
415 char dummy;
416
417 if (d_calls)
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));
422
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;
436
437 if ((cli = get_client(
438 (struct sockaddr *)&msg->lm_addr, NLM_VERS4)) == NULL)
439 return (1);
440
441 set_auth(cli, &msg->lm_cred);
442 (void)clnt_call(cli, NLM4_CANCEL_MSG,
443 xdr_nlm4_cancargs, &arg4, xdr_void, &dummy, timeout);
444 } else {
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;
457
458 if ((cli = get_client(
459 (struct sockaddr *)&msg->lm_addr, NLM_VERS)) == NULL)
460 return (1);
461
462 set_auth(cli, &msg->lm_cred);
463 (void)clnt_call(cli, NLM_CANCEL_MSG,
464 xdr_nlm_cancargs, &arg, xdr_void, &dummy, timeout);
465 }
466 return (0);
467}
468
ac2f15b3
A
469/*
470 * unlock_request --
471 * Convert an unlock LOCKD_MSG into an NLM request, and send it off.
472 */
473int
474unlock_request(LOCKD_MSG *msg)
475{
476 CLIENT *cli;
477 struct nlm4_unlockargs arg4;
478 struct nlm_unlockargs arg;
479 struct timeval timeout = {0, 0}; /* No timeout, no response. */
480 char dummy;
481
482 if (d_calls)
483 syslog(LOG_DEBUG, "unlock request: %s: to %s",
7902cf7e 484 (msg->lm_flags & LOCKD_MSG_NFSV3) ? "V4" : "V1/3",
ac2f15b3
A
485 from_addr((struct sockaddr *)&msg->lm_addr));
486
7902cf7e
A
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);
ac2f15b3
A
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);
7902cf7e 495 arg4.alock.svid = msg->lm_fl.l_pid;
ac2f15b3
A
496 arg4.alock.l_offset = msg->lm_fl.l_start;
497 arg4.alock.l_len = msg->lm_fl.l_len;
498
499 if ((cli = get_client(
500 (struct sockaddr *)&msg->lm_addr,
501 NLM_VERS4)) == NULL)
502 return (1);
503
504 set_auth(cli, &msg->lm_cred);
7902cf7e 505 (void)clnt_call(cli, NLM4_UNLOCK_MSG,
ac2f15b3
A
506 xdr_nlm4_unlockargs, &arg4, xdr_void, &dummy, timeout);
507 } else {
7902cf7e
A
508 arg.cookie.n_bytes = (char *)&msg->lm_xid;
509 arg.cookie.n_len = sizeof(msg->lm_xid);
ac2f15b3
A
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);
7902cf7e 515 arg.alock.svid = msg->lm_fl.l_pid;
ac2f15b3
A
516 arg.alock.l_offset = msg->lm_fl.l_start;
517 arg.alock.l_len = msg->lm_fl.l_len;
518
519 if ((cli = get_client(
520 (struct sockaddr *)&msg->lm_addr,
521 NLM_VERS)) == NULL)
522 return (1);
523
524 set_auth(cli, &msg->lm_cred);
525 (void)clnt_call(cli, NLM_UNLOCK_MSG,
526 xdr_nlm_unlockargs, &arg, xdr_void, &dummy, timeout);
527 }
528
529 return (0);
530}
531
532int
7902cf7e 533lock_answer(int version, netobj *netcookie, nlm4_lock *lock, int flags, int result)
ac2f15b3
A
534{
535 struct lockd_ans ans;
536
7902cf7e
A
537 ans.la_flags = 0;
538 if (flags & LOCK_ANSWER_GRANTED)
539 ans.la_flags |= LOCKD_ANS_GRANTED;
540
541 if (netcookie->n_len != sizeof(ans.la_xid)) {
542 if (lock == NULL) { /* we're screwed */
ac2f15b3
A
543 syslog(LOG_ERR, "inedible nlm cookie");
544 return -1;
545 }
7902cf7e
A
546 /* no/bad cookie - need to copy lock info to identify request */
547 ans.la_xid = 0;
548 /* copy lock info */
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);
552 return -1;
553 }
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;
ac2f15b3 561 } else {
7902cf7e
A
562 memcpy(&ans.la_xid, netcookie->n_bytes, sizeof(ans.la_xid));
563 ans.la_fh_len = 0;
ac2f15b3
A
564 }
565
566 if (d_calls)
567 syslog(LOG_DEBUG, "lock answer: pid %lu: %s %d",
7902cf7e 568 (unsigned long)ans.la_pid,
ac2f15b3
A
569 version == NLM_VERS4 ? "nlmv4" : "nlmv3",
570 result);
571
ac2f15b3
A
572 if (version == NLM_VERS4)
573 switch (result) {
574 case nlm4_granted:
575 ans.la_errno = 0;
7902cf7e
A
576 if ((flags & LOCK_ANSWER_GRANTED) && lock &&
577 !(ans.la_flags & LOCKD_ANS_LOCK_INFO)) {
578 /* copy 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);
582 return -1;
583 }
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;
591 }
ac2f15b3
A
592 break;
593 default:
594 ans.la_errno = EACCES;
595 break;
596 case nlm4_denied:
7902cf7e 597 if (lock == NULL)
ac2f15b3
A
598 ans.la_errno = EACCES;
599 else {
600 /* this is an answer to a nlm_test msg */
7902cf7e
A
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;
ac2f15b3
A
607 ans.la_errno = 0;
608 }
609 break;
610 case nlm4_denied_nolocks:
611 ans.la_errno = ENOLCK;
612 break;
613 case nlm4_blocked:
7902cf7e
A
614 ans.la_errno = EINPROGRESS;
615 break;
ac2f15b3
A
616 case nlm4_denied_grace_period:
617 ans.la_errno = EAGAIN;
618 break;
619 case nlm4_deadlck:
620 ans.la_errno = EDEADLK;
621 break;
622 case nlm4_rofs:
623 ans.la_errno = EROFS;
624 break;
625 case nlm4_stale_fh:
626 ans.la_errno = ESTALE;
627 break;
628 case nlm4_fbig:
629 ans.la_errno = EFBIG;
630 break;
631 case nlm4_failed:
632 ans.la_errno = EACCES;
633 break;
634 }
635 else
636 switch (result) {
637 case nlm_granted:
638 ans.la_errno = 0;
7902cf7e
A
639 if ((flags & LOCK_ANSWER_GRANTED) && lock &&
640 !(ans.la_flags & LOCKD_ANS_LOCK_INFO)) {
641 /* copy 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);
645 return -1;
646 }
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;
654 }
ac2f15b3
A
655 break;
656 default:
657 ans.la_errno = EACCES;
658 break;
659 case nlm_denied:
7902cf7e 660 if (lock == NULL)
ac2f15b3
A
661 ans.la_errno = EACCES;
662 else {
663 /* this is an answer to a nlm_test msg */
7902cf7e
A
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;
ac2f15b3
A
670 ans.la_errno = 0;
671 }
672 break;
673 case nlm_denied_nolocks:
674 ans.la_errno = ENOLCK;
675 break;
676 case nlm_blocked:
7902cf7e
A
677 ans.la_errno = EINPROGRESS;
678 break;
ac2f15b3
A
679 case nlm_denied_grace_period:
680 ans.la_errno = EAGAIN;
681 break;
682 case nlm_deadlck:
683 ans.la_errno = EDEADLK;
684 break;
685 }
686
687 if (nfslockdans(LOCKD_ANS_VERSION, &ans)) {
688 syslog(LOG_DEBUG, "lock_answer(%d): process %lu: %m",
7902cf7e 689 result, (u_long)ans.la_pid);
ac2f15b3
A
690 return -1;
691 }
692 return 0;
693}
694
695/*
696 * show --
697 * Display the contents of a kernel LOCKD_MSG structure.
698 */
699void
700show(LOCKD_MSG *mp)
701{
702 static char hex[] = "0123456789abcdef";
ac2f15b3
A
703 size_t len;
704 u_int8_t *p, *t, buf[NFS_SMALLFH*3+1];
705
7902cf7e 706 syslog(LOG_DEBUG, "process ID: %lu\n", (long)mp->lm_fl.l_pid);
ac2f15b3 707
ac2f15b3
A
708 for (t = buf, p = (u_int8_t *)mp->lm_fh,
709 len = mp->lm_fh_len;
710 len > 0; ++p, --len) {
711 *t++ = '\\';
712 *t++ = hex[(*p & 0xf0) >> 4];
713 *t++ = hex[*p & 0x0f];
714 }
715 *t = '\0';
716
717 syslog(LOG_DEBUG, "fh_len %d, fh %s\n", mp->lm_fh_len, buf);
718
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);
723
724 /* Show wait flag. */
7902cf7e 725 syslog(LOG_DEBUG, "wait was %s\n", (mp->lm_flags & LOCKD_MSG_BLOCK) ? "set" : "not set");
ac2f15b3 726}