kern.c revision 161394
175631Salfred/*- 275631Salfred * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved. 375631Salfred * 475631Salfred * Redistribution and use in source and binary forms, with or without 575631Salfred * modification, are permitted provided that the following conditions 675631Salfred * are met: 775631Salfred * 1. Redistributions of source code must retain the above copyright 875631Salfred * notice, this list of conditions and the following disclaimer. 975631Salfred * 2. Redistributions in binary form must reproduce the above copyright 1075631Salfred * notice, this list of conditions and the following disclaimer in the 1175631Salfred * documentation and/or other materials provided with the distribution. 1275631Salfred * 3. Berkeley Software Design Inc's name may not be used to endorse or 1375631Salfred * promote products derived from this software without specific prior 1475631Salfred * written permission. 1575631Salfred * 1675631Salfred * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN INC ``AS IS'' AND 1775631Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1875631Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1975631Salfred * ARE DISCLAIMED. IN NO EVENT SHALL BERKELEY SOFTWARE DESIGN INC BE LIABLE 2075631Salfred * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2175631Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2275631Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2375631Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2475631Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2575631Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2675631Salfred * SUCH DAMAGE. 2775631Salfred * 2875631Salfred * from BSDI kern.c,v 1.2 1998/11/25 22:38:27 don Exp 2975631Salfred */ 3075631Salfred 31146445Scharnier#include <sys/cdefs.h> 32146445Scharnier__FBSDID("$FreeBSD: head/usr.sbin/rpc.lockd/kern.c 161394 2006-08-17 05:55:20Z maxim $"); 33146445Scharnier 3475631Salfred#include <sys/param.h> 3575631Salfred#include <sys/mount.h> 3675631Salfred#include <sys/queue.h> 3775631Salfred#include <sys/socket.h> 3875631Salfred#include <sys/stat.h> 3975631Salfred 4086299Salfred#include <netinet/in.h> 4186299Salfred#include <arpa/inet.h> 4286299Salfred 4375631Salfred#include <err.h> 4475631Salfred#include <errno.h> 4575631Salfred#include <fcntl.h> 46138431Sphk#include <paths.h> 4786279Salfred#include <pwd.h> 4875631Salfred#include <stdio.h> 4975631Salfred#include <stdlib.h> 5075631Salfred#include <string.h> 5175631Salfred#include <syslog.h> 5275631Salfred#include <unistd.h> 53100134Salfred#include <netdb.h> 5475631Salfred 5575631Salfred#include "nlm_prot.h" 5683653Speter#include <nfs/rpcv2.h> 5783653Speter#include <nfs/nfsproto.h> 5883653Speter#include <nfsclient/nfs_lock.h> 5975631Salfred 6075631Salfred#include "lockd.h" 6175631Salfred#include "lockd_lock.h" 6283653Speter#include <nfsclient/nfs.h> 6375631Salfred 6486279Salfred#define DAEMON_USERNAME "daemon" 6586279Salfred 6675631Salfred/* Lock request owner. */ 6775631Salfredtypedef struct __owner { 6875631Salfred pid_t pid; /* Process ID. */ 6975631Salfred time_t tod; /* Time-of-day. */ 7075631Salfred} OWNER; 7175631Salfredstatic OWNER owner; 7275631Salfred 7375631Salfredstatic char hostname[MAXHOSTNAMELEN + 1]; /* Hostname. */ 74146445Scharnierstatic int devfd; 7575631Salfred 7686299Salfredstatic void client_cleanup(void); 77146445Scharnierstatic const char *from_addr(struct sockaddr *); 78146445Scharnierint lock_request(LOCKD_MSG *); 79101947Salfredstatic void set_auth(CLIENT *cl, struct xucred *ucred); 80146445Scharniervoid show(LOCKD_MSG *); 8175631Salfredint test_request(LOCKD_MSG *); 8275631Salfredint unlock_request(LOCKD_MSG *); 8375631Salfred 84138431Sphkstatic int 85138431Sphknfslockdans(int vers, struct lockd_ans *ansp) 86138431Sphk{ 87138431Sphk 88138431Sphk ansp->la_vers = vers; 89143723Scognet return (write(devfd, ansp, sizeof *ansp) <= 0); 90138431Sphk} 91138431Sphk 9275631Salfred/* 9375631Salfred * will break because fifo needs to be repopened when EOF'd 9475631Salfred */ 9575631Salfred#define lockd_seteuid(uid) seteuid(uid) 9675631Salfred 9775979Salfred#define d_calls (debug_level > 1) 9875979Salfred#define d_args (debug_level > 2) 9975631Salfred 100100134Salfredstatic const char * 101100134Salfredfrom_addr(saddr) 102100134Salfred struct sockaddr *saddr; 103100134Salfred{ 104100134Salfred static char inet_buf[INET6_ADDRSTRLEN]; 10575979Salfred 106100134Salfred if (getnameinfo(saddr, saddr->sa_len, inet_buf, sizeof(inet_buf), 107100134Salfred NULL, 0, NI_NUMERICHOST) == 0) 108100134Salfred return inet_buf; 109100134Salfred return "???"; 110100134Salfred} 111100134Salfred 11275631Salfredvoid 11386299Salfredclient_cleanup(void) 11475631Salfred{ 11575631Salfred (void)lockd_seteuid(0); 11675631Salfred exit(-1); 11775631Salfred} 11875631Salfred 11975631Salfred/* 12075631Salfred * client_request -- 12175631Salfred * Loop around messages from the kernel, forwarding them off to 12275631Salfred * NLM servers. 12375631Salfred */ 12475631Salfredpid_t 12575631Salfredclient_request(void) 12675631Salfred{ 12775631Salfred LOCKD_MSG msg; 128138431Sphk int nr, ret; 12975631Salfred pid_t child; 13086279Salfred uid_t daemon_uid; 13186279Salfred struct passwd *pw; 13275631Salfred 133138431Sphk /* Open the dev . */ 134138431Sphk devfd = open(_PATH_DEV _PATH_NFSLCKDEV, O_RDWR | O_NONBLOCK); 135138431Sphk if (devfd < 0) { 136138431Sphk syslog(LOG_ERR, "open: %s: %m", _PATH_NFSLCKDEV); 137138431Sphk goto err; 13875631Salfred } 139158968Srodrigc 140158968Srodrigc signal(SIGPIPE, SIG_IGN); 141158968Srodrigc 14275631Salfred /* 14375631Salfred * Create a separate process, the client code is really a separate 14475631Salfred * daemon that shares a lot of code. 14575631Salfred */ 14675631Salfred switch (child = fork()) { 14775631Salfred case -1: 14875631Salfred err(1, "fork"); 14975631Salfred case 0: 150161394Smaxim setproctitle("client"); 15175631Salfred break; 15275631Salfred default: 153161394Smaxim setproctitle("server"); 15475631Salfred return (child); 15575631Salfred } 15675631Salfred 15786299Salfred signal(SIGHUP, (sig_t)client_cleanup); 15886299Salfred signal(SIGTERM, (sig_t)client_cleanup); 15975631Salfred 16075631Salfred /* Setup. */ 16175631Salfred (void)time(&owner.tod); 16275631Salfred owner.pid = getpid(); 16375631Salfred (void)gethostname(hostname, sizeof(hostname) - 1); 16475631Salfred 16586279Salfred pw = getpwnam(DAEMON_USERNAME); 16686279Salfred if (pw == NULL) { 16786279Salfred syslog(LOG_ERR, "getpwnam: %s: %m", DAEMON_USERNAME); 16886279Salfred goto err; 16986279Salfred } 17086279Salfred daemon_uid = pw->pw_uid; 17175631Salfred /* drop our root priviledges */ 17275631Salfred (void)lockd_seteuid(daemon_uid); 17375631Salfred 17475631Salfred for (;;) { 17575631Salfred /* Read the fixed length message. */ 176138431Sphk if ((nr = read(devfd, &msg, sizeof(msg))) == sizeof(msg)) { 17775631Salfred if (d_args) 17875631Salfred show(&msg); 17975631Salfred 18075631Salfred if (msg.lm_version != LOCKD_MSG_VERSION) { 18175631Salfred syslog(LOG_ERR, 18275631Salfred "unknown msg type: %d", msg.lm_version); 18375631Salfred } 18475631Salfred /* 18575631Salfred * Send it to the NLM server and don't grant the lock 18675631Salfred * if we fail for any reason. 18775631Salfred */ 18875631Salfred switch (msg.lm_fl.l_type) { 18975631Salfred case F_RDLCK: 19075631Salfred case F_WRLCK: 19175631Salfred if (msg.lm_getlk) 19275631Salfred ret = test_request(&msg); 19375631Salfred else 19475631Salfred ret = lock_request(&msg); 19575631Salfred break; 19675631Salfred case F_UNLCK: 19775631Salfred ret = unlock_request(&msg); 19875631Salfred break; 19975631Salfred default: 20075631Salfred ret = 1; 20175631Salfred syslog(LOG_ERR, 20275631Salfred "unknown lock type: %d", msg.lm_fl.l_type); 20375631Salfred break; 20475631Salfred } 20575631Salfred if (ret) { 20675631Salfred struct lockd_ans ans; 20775631Salfred 20875631Salfred ans.la_msg_ident = msg.lm_msg_ident; 20975631Salfred ans.la_errno = EHOSTUNREACH; 21075631Salfred 21175631Salfred if (nfslockdans(LOCKD_ANS_VERSION, &ans)) { 21275631Salfred syslog((errno == EPIPE ? LOG_INFO : 21375631Salfred LOG_ERR), "process %lu: %m", 21475631Salfred (u_long)msg.lm_msg_ident.pid); 21575631Salfred } 21675631Salfred } 21775631Salfred } else if (nr == -1) { 21875631Salfred if (errno != EAGAIN) { 219138431Sphk syslog(LOG_ERR, "read: %s: %m", _PATH_NFSLCKDEV); 22075631Salfred goto err; 22175631Salfred } 22275631Salfred } else if (nr != 0) { 22375631Salfred syslog(LOG_ERR, 224138431Sphk "%s: discard %d bytes", _PATH_NFSLCKDEV, nr); 22575631Salfred } 22675631Salfred } 22775631Salfred 22875631Salfred /* Reached only on error. */ 22975631Salfrederr: 23075631Salfred (void)lockd_seteuid(0); 23175631Salfred _exit (1); 23275631Salfred} 23375631Salfred 23475631Salfredvoid 235101947Salfredset_auth(cl, xucred) 23686186Salfred CLIENT *cl; 237101947Salfred struct xucred *xucred; 23875631Salfred{ 239152549Sharti int ngroups; 240152549Sharti 241152549Sharti ngroups = xucred->cr_ngroups - 1; 242152549Sharti if (ngroups > NGRPS) 243152549Sharti ngroups = NGRPS; 24475631Salfred if (cl->cl_auth != NULL) 24575631Salfred cl->cl_auth->ah_ops->ah_destroy(cl->cl_auth); 24675631Salfred cl->cl_auth = authunix_create(hostname, 247101947Salfred xucred->cr_uid, 248101947Salfred xucred->cr_groups[0], 249152549Sharti ngroups, 250101947Salfred &xucred->cr_groups[1]); 25175631Salfred} 25275631Salfred 25375631Salfred 25475631Salfred/* 25575631Salfred * test_request -- 25675631Salfred * Convert a lock LOCKD_MSG into an NLM request, and send it off. 25775631Salfred */ 25875631Salfredint 25975631Salfredtest_request(LOCKD_MSG *msg) 26075631Salfred{ 26175631Salfred CLIENT *cli; 26275631Salfred struct timeval timeout = {0, 0}; /* No timeout, no response. */ 26375631Salfred char dummy; 26475631Salfred 26575631Salfred if (d_calls) 26675631Salfred syslog(LOG_DEBUG, "test request: %s: %s to %s", 26775631Salfred msg->lm_nfsv3 ? "V4" : "V1/3", 26875631Salfred msg->lm_fl.l_type == F_WRLCK ? "write" : "read", 269100134Salfred from_addr((struct sockaddr *)&msg->lm_addr)); 27075631Salfred 27175631Salfred if (msg->lm_nfsv3) { 27275631Salfred struct nlm4_testargs arg4; 27375631Salfred 27475631Salfred arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident; 27575631Salfred arg4.cookie.n_len = sizeof(msg->lm_msg_ident); 27675631Salfred arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0; 27775631Salfred arg4.alock.caller_name = hostname; 27875631Salfred arg4.alock.fh.n_bytes = (char *)&msg->lm_fh; 27975631Salfred arg4.alock.fh.n_len = msg->lm_fh_len; 28075631Salfred arg4.alock.oh.n_bytes = (char *)&owner; 28175631Salfred arg4.alock.oh.n_len = sizeof(owner); 28275631Salfred arg4.alock.svid = msg->lm_msg_ident.pid; 28375631Salfred arg4.alock.l_offset = msg->lm_fl.l_start; 28475631Salfred arg4.alock.l_len = msg->lm_fl.l_len; 28575631Salfred 28675631Salfred if ((cli = get_client( 28775631Salfred (struct sockaddr *)&msg->lm_addr, 28875631Salfred NLM_VERS4)) == NULL) 28975631Salfred return (1); 29075631Salfred 29175631Salfred set_auth(cli, &msg->lm_cred); 29275631Salfred (void)clnt_call(cli, NLM_TEST_MSG, 293121558Speter (xdrproc_t)xdr_nlm4_testargs, &arg4, 294121558Speter (xdrproc_t)xdr_void, &dummy, timeout); 29575631Salfred } else { 29675631Salfred struct nlm_testargs arg; 29775631Salfred 29875631Salfred arg.cookie.n_bytes = (char *)&msg->lm_msg_ident; 29975631Salfred arg.cookie.n_len = sizeof(msg->lm_msg_ident); 30075631Salfred arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0; 30175631Salfred arg.alock.caller_name = hostname; 30275631Salfred arg.alock.fh.n_bytes = (char *)&msg->lm_fh; 30375631Salfred arg.alock.fh.n_len = msg->lm_fh_len; 30475631Salfred arg.alock.oh.n_bytes = (char *)&owner; 30575631Salfred arg.alock.oh.n_len = sizeof(owner); 30675631Salfred arg.alock.svid = msg->lm_msg_ident.pid; 30775631Salfred arg.alock.l_offset = msg->lm_fl.l_start; 30875631Salfred arg.alock.l_len = msg->lm_fl.l_len; 30975631Salfred 31075631Salfred if ((cli = get_client( 31175631Salfred (struct sockaddr *)&msg->lm_addr, 31275631Salfred NLM_VERS)) == NULL) 31375631Salfred return (1); 31475631Salfred 31575631Salfred set_auth(cli, &msg->lm_cred); 31675631Salfred (void)clnt_call(cli, NLM_TEST_MSG, 317121558Speter (xdrproc_t)xdr_nlm_testargs, &arg, 318121558Speter (xdrproc_t)xdr_void, &dummy, timeout); 31975631Salfred } 32075631Salfred return (0); 32175631Salfred} 32275631Salfred 32375631Salfred/* 32475631Salfred * lock_request -- 32575631Salfred * Convert a lock LOCKD_MSG into an NLM request, and send it off. 32675631Salfred */ 32775631Salfredint 32875631Salfredlock_request(LOCKD_MSG *msg) 32975631Salfred{ 33075631Salfred CLIENT *cli; 33175631Salfred struct nlm4_lockargs arg4; 33275631Salfred struct nlm_lockargs arg; 33375631Salfred struct timeval timeout = {0, 0}; /* No timeout, no response. */ 33475631Salfred char dummy; 33575631Salfred 33675631Salfred if (d_calls) 33775631Salfred syslog(LOG_DEBUG, "lock request: %s: %s to %s", 33875631Salfred msg->lm_nfsv3 ? "V4" : "V1/3", 33975631Salfred msg->lm_fl.l_type == F_WRLCK ? "write" : "read", 340100134Salfred from_addr((struct sockaddr *)&msg->lm_addr)); 34175631Salfred 34275631Salfred if (msg->lm_nfsv3) { 34375631Salfred arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident; 34475631Salfred arg4.cookie.n_len = sizeof(msg->lm_msg_ident); 34575631Salfred arg4.block = msg->lm_wait ? 1 : 0; 34675631Salfred arg4.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0; 34775631Salfred arg4.alock.caller_name = hostname; 34875631Salfred arg4.alock.fh.n_bytes = (char *)&msg->lm_fh; 34975631Salfred arg4.alock.fh.n_len = msg->lm_fh_len; 35075631Salfred arg4.alock.oh.n_bytes = (char *)&owner; 35175631Salfred arg4.alock.oh.n_len = sizeof(owner); 35275631Salfred arg4.alock.svid = msg->lm_msg_ident.pid; 35375631Salfred arg4.alock.l_offset = msg->lm_fl.l_start; 35475631Salfred arg4.alock.l_len = msg->lm_fl.l_len; 35575631Salfred arg4.reclaim = 0; 35675631Salfred arg4.state = nsm_state; 35775631Salfred 35875631Salfred if ((cli = get_client( 35975631Salfred (struct sockaddr *)&msg->lm_addr, 36075631Salfred NLM_VERS4)) == NULL) 36175631Salfred return (1); 36275631Salfred 36375631Salfred set_auth(cli, &msg->lm_cred); 36475631Salfred (void)clnt_call(cli, NLM_LOCK_MSG, 365121558Speter (xdrproc_t)xdr_nlm4_lockargs, &arg4, 366121558Speter (xdrproc_t)xdr_void, &dummy, timeout); 36775631Salfred } else { 36875631Salfred arg.cookie.n_bytes = (char *)&msg->lm_msg_ident; 36975631Salfred arg.cookie.n_len = sizeof(msg->lm_msg_ident); 37075631Salfred arg.block = msg->lm_wait ? 1 : 0; 37175631Salfred arg.exclusive = msg->lm_fl.l_type == F_WRLCK ? 1 : 0; 37275631Salfred arg.alock.caller_name = hostname; 37375631Salfred arg.alock.fh.n_bytes = (char *)&msg->lm_fh; 37475631Salfred arg.alock.fh.n_len = msg->lm_fh_len; 37575631Salfred arg.alock.oh.n_bytes = (char *)&owner; 37675631Salfred arg.alock.oh.n_len = sizeof(owner); 37775631Salfred arg.alock.svid = msg->lm_msg_ident.pid; 37875631Salfred arg.alock.l_offset = msg->lm_fl.l_start; 37975631Salfred arg.alock.l_len = msg->lm_fl.l_len; 38075631Salfred arg.reclaim = 0; 38175631Salfred arg.state = nsm_state; 38275631Salfred 38375631Salfred if ((cli = get_client( 38475631Salfred (struct sockaddr *)&msg->lm_addr, 38575631Salfred NLM_VERS)) == NULL) 38675631Salfred return (1); 38775631Salfred 38875631Salfred set_auth(cli, &msg->lm_cred); 38975631Salfred (void)clnt_call(cli, NLM_LOCK_MSG, 390121558Speter (xdrproc_t)xdr_nlm_lockargs, &arg, 391121558Speter (xdrproc_t)xdr_void, &dummy, timeout); 39275631Salfred } 39375631Salfred return (0); 39475631Salfred} 39575631Salfred 39675631Salfred/* 39775631Salfred * unlock_request -- 39875631Salfred * Convert an unlock LOCKD_MSG into an NLM request, and send it off. 39975631Salfred */ 40075631Salfredint 40175631Salfredunlock_request(LOCKD_MSG *msg) 40275631Salfred{ 40375631Salfred CLIENT *cli; 40475631Salfred struct nlm4_unlockargs arg4; 40575631Salfred struct nlm_unlockargs arg; 40675631Salfred struct timeval timeout = {0, 0}; /* No timeout, no response. */ 40775631Salfred char dummy; 40875631Salfred 40975631Salfred if (d_calls) 41075631Salfred syslog(LOG_DEBUG, "unlock request: %s: to %s", 41175631Salfred msg->lm_nfsv3 ? "V4" : "V1/3", 412100134Salfred from_addr((struct sockaddr *)&msg->lm_addr)); 41375631Salfred 41475631Salfred if (msg->lm_nfsv3) { 41575631Salfred arg4.cookie.n_bytes = (char *)&msg->lm_msg_ident; 41675631Salfred arg4.cookie.n_len = sizeof(msg->lm_msg_ident); 41775631Salfred arg4.alock.caller_name = hostname; 41875631Salfred arg4.alock.fh.n_bytes = (char *)&msg->lm_fh; 41975631Salfred arg4.alock.fh.n_len = msg->lm_fh_len; 42075631Salfred arg4.alock.oh.n_bytes = (char *)&owner; 42175631Salfred arg4.alock.oh.n_len = sizeof(owner); 42275631Salfred arg4.alock.svid = msg->lm_msg_ident.pid; 42375631Salfred arg4.alock.l_offset = msg->lm_fl.l_start; 42475631Salfred arg4.alock.l_len = msg->lm_fl.l_len; 42575631Salfred 42675631Salfred if ((cli = get_client( 42775631Salfred (struct sockaddr *)&msg->lm_addr, 42875631Salfred NLM_VERS4)) == NULL) 42975631Salfred return (1); 43075631Salfred 43175631Salfred set_auth(cli, &msg->lm_cred); 43275631Salfred (void)clnt_call(cli, NLM_UNLOCK_MSG, 433121558Speter (xdrproc_t)xdr_nlm4_unlockargs, &arg4, 434121558Speter (xdrproc_t)xdr_void, &dummy, timeout); 43575631Salfred } else { 43675631Salfred arg.cookie.n_bytes = (char *)&msg->lm_msg_ident; 43775631Salfred arg.cookie.n_len = sizeof(msg->lm_msg_ident); 43875631Salfred arg.alock.caller_name = hostname; 43975631Salfred arg.alock.fh.n_bytes = (char *)&msg->lm_fh; 44075631Salfred arg.alock.fh.n_len = msg->lm_fh_len; 44175631Salfred arg.alock.oh.n_bytes = (char *)&owner; 44275631Salfred arg.alock.oh.n_len = sizeof(owner); 44375631Salfred arg.alock.svid = msg->lm_msg_ident.pid; 44475631Salfred arg.alock.l_offset = msg->lm_fl.l_start; 44575631Salfred arg.alock.l_len = msg->lm_fl.l_len; 44675631Salfred 44775631Salfred if ((cli = get_client( 44875631Salfred (struct sockaddr *)&msg->lm_addr, 44975631Salfred NLM_VERS)) == NULL) 45075631Salfred return (1); 45175631Salfred 45275631Salfred set_auth(cli, &msg->lm_cred); 45375631Salfred (void)clnt_call(cli, NLM_UNLOCK_MSG, 454121558Speter (xdrproc_t)xdr_nlm_unlockargs, &arg, 455121558Speter (xdrproc_t)xdr_void, &dummy, timeout); 45675631Salfred } 45775631Salfred 45875631Salfred return (0); 45975631Salfred} 46075631Salfred 46175631Salfredint 46275631Salfredlock_answer(int pid, netobj *netcookie, int result, int *pid_p, int version) 46375631Salfred{ 46475631Salfred struct lockd_ans ans; 46575631Salfred 46675631Salfred if (netcookie->n_len != sizeof(ans.la_msg_ident)) { 46775631Salfred if (pid == -1) { /* we're screwed */ 46875631Salfred syslog(LOG_ERR, "inedible nlm cookie"); 46975631Salfred return -1; 47075631Salfred } 47175631Salfred ans.la_msg_ident.pid = pid; 47275631Salfred ans.la_msg_ident.msg_seq = -1; 47375631Salfred } else { 47486186Salfred memcpy(&ans.la_msg_ident, netcookie->n_bytes, 47586186Salfred sizeof(ans.la_msg_ident)); 47675631Salfred } 47775631Salfred 47875631Salfred if (d_calls) 47975979Salfred syslog(LOG_DEBUG, "lock answer: pid %lu: %s %d", 48086299Salfred (unsigned long)ans.la_msg_ident.pid, 48175979Salfred version == NLM_VERS4 ? "nlmv4" : "nlmv3", 48275979Salfred result); 48375631Salfred 48475631Salfred ans.la_set_getlk_pid = 0; 48575631Salfred if (version == NLM_VERS4) 48675631Salfred switch (result) { 48775631Salfred case nlm4_granted: 48875631Salfred ans.la_errno = 0; 48975631Salfred break; 49075631Salfred default: 49175631Salfred ans.la_errno = EACCES; 49275631Salfred break; 49375631Salfred case nlm4_denied: 49475631Salfred if (pid_p == NULL) 495115012Srwatson ans.la_errno = EAGAIN; 49675631Salfred else { 49775631Salfred /* this is an answer to a nlm_test msg */ 49875631Salfred ans.la_set_getlk_pid = 1; 49975631Salfred ans.la_getlk_pid = *pid_p; 50075631Salfred ans.la_errno = 0; 50175631Salfred } 50275631Salfred break; 50375631Salfred case nlm4_denied_nolocks: 50475631Salfred ans.la_errno = EAGAIN; 50575631Salfred break; 50675631Salfred case nlm4_blocked: 50775631Salfred return -1; 50875631Salfred /* NOTREACHED */ 50975631Salfred case nlm4_denied_grace_period: 51075631Salfred ans.la_errno = EAGAIN; 51175631Salfred break; 51275631Salfred case nlm4_deadlck: 51375631Salfred ans.la_errno = EDEADLK; 51475631Salfred break; 51575631Salfred case nlm4_rofs: 51675631Salfred ans.la_errno = EROFS; 51775631Salfred break; 51875631Salfred case nlm4_stale_fh: 51975631Salfred ans.la_errno = ESTALE; 52075631Salfred break; 52175631Salfred case nlm4_fbig: 52275631Salfred ans.la_errno = EFBIG; 52375631Salfred break; 52475631Salfred case nlm4_failed: 52575631Salfred ans.la_errno = EACCES; 52675631Salfred break; 52775631Salfred } 52875631Salfred else 52975631Salfred switch (result) { 53075631Salfred case nlm_granted: 53175631Salfred ans.la_errno = 0; 53275631Salfred break; 53375631Salfred default: 53475631Salfred ans.la_errno = EACCES; 53575631Salfred break; 53675631Salfred case nlm_denied: 53775631Salfred if (pid_p == NULL) 538115012Srwatson ans.la_errno = EAGAIN; 53975631Salfred else { 54075631Salfred /* this is an answer to a nlm_test msg */ 54175631Salfred ans.la_set_getlk_pid = 1; 54275631Salfred ans.la_getlk_pid = *pid_p; 54375631Salfred ans.la_errno = 0; 54475631Salfred } 54575631Salfred break; 54675631Salfred case nlm_denied_nolocks: 54775631Salfred ans.la_errno = EAGAIN; 54875631Salfred break; 54975631Salfred case nlm_blocked: 55075631Salfred return -1; 55175631Salfred /* NOTREACHED */ 55275631Salfred case nlm_denied_grace_period: 55375631Salfred ans.la_errno = EAGAIN; 55475631Salfred break; 55575631Salfred case nlm_deadlck: 55675631Salfred ans.la_errno = EDEADLK; 55775631Salfred break; 55875631Salfred } 55975631Salfred 56075631Salfred if (nfslockdans(LOCKD_ANS_VERSION, &ans)) { 56175631Salfred syslog(((errno == EPIPE || errno == ESRCH) ? 56275631Salfred LOG_INFO : LOG_ERR), 56375631Salfred "process %lu: %m", (u_long)ans.la_msg_ident.pid); 56475631Salfred return -1; 56575631Salfred } 56675631Salfred return 0; 56775631Salfred} 56875631Salfred 56975631Salfred/* 57075631Salfred * show -- 57175631Salfred * Display the contents of a kernel LOCKD_MSG structure. 57275631Salfred */ 57375631Salfredvoid 57475631Salfredshow(LOCKD_MSG *mp) 57575631Salfred{ 57675631Salfred static char hex[] = "0123456789abcdef"; 57775631Salfred struct fid *fidp; 57875631Salfred fsid_t *fsidp; 57975631Salfred size_t len; 58075631Salfred u_int8_t *p, *t, buf[NFS_SMALLFH*3+1]; 58175631Salfred 58286187Salfred syslog(LOG_DEBUG, "process ID: %lu\n", (long)mp->lm_msg_ident.pid); 58375631Salfred 58475631Salfred fsidp = (fsid_t *)&mp->lm_fh; 58575631Salfred fidp = (struct fid *)((u_int8_t *)&mp->lm_fh + sizeof(fsid_t)); 58675631Salfred 58775631Salfred for (t = buf, p = (u_int8_t *)mp->lm_fh, 58875631Salfred len = mp->lm_fh_len; 58975631Salfred len > 0; ++p, --len) { 59075631Salfred *t++ = '\\'; 59175631Salfred *t++ = hex[(*p & 0xf0) >> 4]; 59275631Salfred *t++ = hex[*p & 0x0f]; 59375631Salfred } 59475631Salfred *t = '\0'; 59575631Salfred 596121558Speter syslog(LOG_DEBUG, "fh_len %d, fh %s\n", (int)mp->lm_fh_len, buf); 59775631Salfred 59875631Salfred /* Show flock structure. */ 59986187Salfred syslog(LOG_DEBUG, "start %qu; len %qu; pid %lu; type %d; whence %d\n", 600121558Speter (unsigned long long)mp->lm_fl.l_start, 601121558Speter (unsigned long long)mp->lm_fl.l_len, (u_long)mp->lm_fl.l_pid, 60275631Salfred mp->lm_fl.l_type, mp->lm_fl.l_whence); 60375631Salfred 60475631Salfred /* Show wait flag. */ 60586187Salfred syslog(LOG_DEBUG, "wait was %s\n", mp->lm_wait ? "set" : "not set"); 60675631Salfred} 607