diff --git a/sbin/rpc.lockd/Makefile b/sbin/rpc.lockd/Makefile deleted file mode 100644 index e734f58437d5..000000000000 --- a/sbin/rpc.lockd/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# $Id: Makefile,v 1.1.1.1 1996/02/17 15:11:28 peter Exp $ - -PROG = rpc.lockd -SRCS = nlm_prot_svc.c lockd.c procs.c -MAN8 = rpc.lockd.8 - -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc - -CFLAGS+= -I. - -CLEANFILES= nlm_prot_svc.c nlm_prot.h - -RPCSRC= ${.DESTDIR}/usr/include/rpcsvc/nlm_prot.x -RPCGEN= rpcgen -L -C - -nlm_prot_svc.c: ${RPCSRC} nlm_prot.h - ${RPCGEN} -m -o ${.TARGET} ${RPCSRC} - -nlm_prot.h: ${RPCSRC} - ${RPCGEN} -h -o ${.TARGET} ${RPCSRC} - -test: test.c - cc -o test test.c -lrpcsvc - -.include diff --git a/sbin/rpc.lockd/handles.c b/sbin/rpc.lockd/handles.c deleted file mode 100644 index 047f6d23ee3f..000000000000 --- a/sbin/rpc.lockd/handles.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 1995 - * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the FreeBSD project - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - - - -#include "nlm_prot.h" - -/* ------------------------------------------------------------------------- */ -/* - - -* need to find all fds in use by a host and free them when host crashes - (need not be efficient) - -* need to find fd corresponding to - -*/ - -typedef struct fdinfo -{ - int fd; /* The file descriptor itself */ - int ref_count; /* Count of hosts using the fd - fd is */ - /* closed when this reaches zero */ - ino_t inode_no; /* The inode number of this file. */ - dev_t device; /* device on which the file lives. */ - struct fdinfo *next; /* Chain of FdInfo structures */ - struct fdinfo *prev; -} FdInfo; diff --git a/sbin/rpc.lockd/lockd.c b/sbin/rpc.lockd/lockd.c deleted file mode 100644 index d68b056fb95c..000000000000 --- a/sbin/rpc.lockd/lockd.c +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 1995 - * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the FreeBSD project - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - - -/* main() function for NFS lock daemon. Most of the code in this */ -/* file was generated by running rpcgen /usr/include/rpcsvc/nlm_prot.x */ -/* The actual program logic is in the file procs.c */ - -#include "lockd.h" - -extern void nlm_prog_1 __P((struct svc_req, register SVCXPRT)); -extern void nlm_prog_3 __P((struct svc_req, register SVCXPRT)); - -int debug_level = 0; /* Zero means no debugging syslog() calls */ - - -main(int argc, char **argv) -{ - SVCXPRT *transp; - - if (argc > 1) - { - if (strncmp(argv[1], "-d", 2)) - { - fprintf(stderr, "Usage: rpc.lockd [-d []]\n"); - exit(1); - } - if (argc > 2) debug_level = atoi(argv[2]); - else debug_level = atoi(argv[1] + 2); - /* Ensure at least some debug if -d with no specified level */ - if (!debug_level) debug_level = 1; - } - - (void)pmap_unset(NLM_PROG, NLM_VERS); - (void)pmap_unset(NLM_PROG, NLM_VERSX); - - transp = svcudp_create(RPC_ANYSOCK); - if (transp == NULL) - { - (void)fprintf(stderr, "cannot create udp service.\n"); - exit(1); - } - if (!svc_register(transp, NLM_PROG, NLM_VERS, nlm_prog_1, IPPROTO_UDP)) - { - (void)fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS, udp).\n"); - exit(1); - } - if (!svc_register(transp, NLM_PROG, NLM_VERSX, nlm_prog_3, IPPROTO_UDP)) - { - (void)fprintf(stderr, "unable to register (NLM_PROG, NLM_VERSX, udp).\n"); - exit(1); - } - - transp = svctcp_create(RPC_ANYSOCK, 0, 0); - if (transp == NULL) - { - (void)fprintf(stderr, "cannot create tcp service.\n"); - exit(1); - } - if (!svc_register(transp, NLM_PROG, NLM_VERS, nlm_prog_1, IPPROTO_TCP)) - { - (void)fprintf(stderr, "unable to register (NLM_PROG, NLM_VERS, tcp).\n"); - exit(1); - } - if (!svc_register(transp, NLM_PROG, NLM_VERSX, nlm_prog_3, IPPROTO_TCP)) - { - (void)fprintf(stderr, "unable to register (NLM_PROG, NLM_VERSX, tcp).\n"); - exit(1); - } - - /* Note that it is NOT sensible to run this program from inetd - the */ - /* protocol assumes that it will run immediately at boot time. */ - if (daemon(0,0)) { - perror("cannot fork"); - exit(1); - } - openlog("rpc.lockd", 0, LOG_DAEMON); - if (debug_level) syslog(LOG_INFO, "Starting, debug level %d", debug_level); - else syslog(LOG_INFO, "Starting"); - - svc_run(); /* Should never return */ - exit(1); -} diff --git a/sbin/rpc.lockd/lockd.h b/sbin/rpc.lockd/lockd.h deleted file mode 100644 index 39586bfd77ae..000000000000 --- a/sbin/rpc.lockd/lockd.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 1995 - * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the FreeBSD project - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - - - -#include -#include -#include -#include /* protocol to talk to rpc.statd */ -#include "nlm_prot.h" /* The protocol we are implementing */ - - -/* global variables ------------------------------------------------------- */ -extern int debug_level; diff --git a/sbin/rpc.lockd/procs.c b/sbin/rpc.lockd/procs.c deleted file mode 100644 index 54e5f814cebb..000000000000 --- a/sbin/rpc.lockd/procs.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Copyright (c) 1995 - * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the FreeBSD project - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - - - -#include "lockd.h" - -#include /* for MAXHOSTNAMELEN */ -#include -#include -#include -#include - - -#define CLIENT_CACHE_SIZE 64 /* No. of client sockets cached */ -#define CLIENT_CACHE_LIFETIME 120 /* In seconds */ - - -/* log_from_addr ----------------------------------------------------------- */ -/* - Purpose: Log name of function called and source address - Returns: Nothing - Notes: Extracts the source address from the transport handle - passed in as part of the called procedure specification -*/ - -static void log_from_addr(char *fun_name, struct svc_req *req) -{ - struct sockaddr_in *addr; - struct hostent *host; - char hostname_buf[40]; - - addr = svc_getcaller(req->rq_xprt); - host = gethostbyaddr((char *)&(addr->sin_addr), addr->sin_len, AF_INET); - if (host) - { - strncpy(hostname_buf, host->h_name, sizeof(hostname_buf)); - hostname_buf[sizeof(hostname_buf) -1] = '\0'; - } - else /* No hostname available - print raw address */ - { - strcpy(hostname_buf, inet_ntoa(addr->sin_addr)); - } - - syslog(LOG_DEBUG, "%s from %s", fun_name, hostname_buf); -} - - -/* get_client -------------------------------------------------------------- */ -/* - Purpose: Get a CLIENT* for making RPC calls to lockd on given host - Returns: CLIENT* pointer, from clnt_udp_create, or NULL if error - Notes: Creating a CLIENT* is quite expensive, involving a - conversation with the remote portmapper to get the - port number. Since a given client is quite likely - to make several locking requests in succession, it is - desirable to cache the created CLIENT*. - - Since we are using UDP rather than TCP, there is no cost - to the remote system in keeping these cached indefinitely. - Unfortunately there is a snag: if the remote system - reboots, the cached portmapper results will be invalid, - and we will never detect this since all of the xxx_msg() - calls return no result - we just fire off a udp packet - and hope for the best. - - We solve this by discarding cached values after two - minutes, regardless of whether they have been used - in the meanwhile (since a bad one might have been used - plenty of times, as the host keeps retrying the request - and we keep sending the reply back to the wrong port). - - Given that the entries will always expire in the order - that they were created, there is no point in a LRU - algorithm for when the cache gets full - entries are - always re-used in sequence. -*/ - -static CLIENT *clnt_cache_ptr[CLIENT_CACHE_SIZE]; -static long clnt_cache_time[CLIENT_CACHE_SIZE]; /* time entry created */ -static struct in_addr clnt_cache_addr[CLIENT_CACHE_SIZE]; -static int clnt_cache_next_to_use = 0; - -static CLIENT *get_client(struct sockaddr_in *host_addr) -{ - CLIENT *client; - int sock_no; - struct timeval retry_time, time_now; - int i; - - gettimeofday(&time_now, NULL); - - /* Search for the given client in the cache, zapping any expired */ - /* entries that we happen to notice in passing. */ - for (i = 0; i < CLIENT_CACHE_SIZE; i++) - { - client = clnt_cache_ptr[i]; - if (client && - ((clnt_cache_time[i] + CLIENT_CACHE_LIFETIME) < time_now.tv_sec)) - { - /* Cache entry has expired. */ - if (debug_level > 3) syslog(LOG_DEBUG, "Expired CLIENT* in cache"); - clnt_cache_time[i] = 0L; - clnt_destroy(client); - clnt_cache_ptr[i] = NULL; - client = NULL; - } - - if (client && !memcmp(&clnt_cache_addr[i], &host_addr->sin_addr, - sizeof(struct in_addr))) - { - /* Found it! */ - if (debug_level > 3) syslog(LOG_DEBUG, "Found CLIENT* in cache"); - return (client); - } - } - - /* Not found in cache. Free the next entry if it is in use */ - if (clnt_cache_ptr[clnt_cache_next_to_use]) - { - clnt_destroy(clnt_cache_ptr[clnt_cache_next_to_use]); - clnt_cache_ptr[clnt_cache_next_to_use] = NULL; - } - - /* Create the new client handle */ - - sock_no = RPC_ANYSOCK; - retry_time.tv_sec = 5; - retry_time.tv_usec = 0; - host_addr->sin_port = 0; /* Force consultation with portmapper */ - client = clntudp_create(host_addr, NLM_PROG, NLM_VERS, retry_time, &sock_no); - if (!client) - { - syslog(LOG_ERR, clnt_spcreateerror("clntudp_create")); - syslog(LOG_ERR, "Unable to return result to %s", - inet_ntoa(host_addr->sin_addr)); - return NULL; - } - - /* Success - update the cache entry */ - clnt_cache_ptr[clnt_cache_next_to_use] = client; - clnt_cache_addr[clnt_cache_next_to_use] = host_addr->sin_addr; - clnt_cache_time[clnt_cache_next_to_use] = time_now.tv_sec; - if (++clnt_cache_next_to_use > CLIENT_CACHE_SIZE) - clnt_cache_next_to_use = 0; - - /* Disable the default timeout, so we can specify our own in calls */ - /* to clnt_call(). [note that the timeout is a different concept */ - /* from the retry period set in clnt_udp_create() above.] */ - retry_time.tv_sec = -1; - retry_time.tv_usec = -1; - clnt_control(client, CLSET_TIMEOUT, &retry_time); - - if (debug_level > 3) syslog(LOG_DEBUG, "Created CLIENT* for %s", - inet_ntoa(host_addr->sin_addr)); - return client; -} - - -/* transmit_result --------------------------------------------------------- */ -/* - Purpose: Transmit result for nlm_xxx_msg pseudo-RPCs - Returns: Nothing - we have no idea if the datagram got there - Notes: clnt_call() will always fail (with timeout) as we are - calling it with timeout 0 as a hack to just issue a datagram - without expecting a result -*/ - -static void transmit_result(int opcode, nlm_res *result, struct svc_req *req) -{ - static char dummy; - struct sockaddr_in *addr; - CLIENT *cli; - int success; - struct timeval timeo; - - addr = svc_getcaller(req->rq_xprt); - if (cli = get_client(addr)) - { - timeo.tv_sec = 0; /* No timeout - not expecting response */ - timeo.tv_usec = 0; - - success = clnt_call(cli, opcode, xdr_nlm_res, result, xdr_void, - &dummy, timeo); - - if (debug_level > 2) syslog(LOG_DEBUG, "clnt_call returns %d\n", success); - } -} - -/* ------------------------------------------------------------------------- */ -/* - Functions for Unix<->Unix locking (ie. monitored locking, with rpc.statd - involved to ensure reclaim of locks after a crash of the "stateless" - server. - - These all come in two flavours - nlm_xxx() and nlm_xxx_msg(). - The first are standard RPCs with argument and result. - The nlm_xxx_msg() calls implement exactly the same functions, but - use two pseudo-RPCs (one in each direction). These calls are NOT - standard use of the RPC protocol in that they do not return a result - at all (NB. this is quite different from returning a void result). - The effect of this is to make the nlm_xxx_msg() calls simple unacknowledged - datagrams, requiring higher-level code to perform retries. - - Despite the disadvantages of the nlm_xxx_msg() approach (some of which - are documented in the comments to get_client() above), this is the - interface used by all current commercial NFS implementations - [Solaris, SCO, AIX etc.]. This is presumed to be because these allow - implementations to continue using the standard RPC libraries, while - avoiding the block-until-result nature of the library interface. - - No client implementations have been identified so far that make use - of the true RPC version (early SunOS releases would be a likely candidate - for testing). -*/ - - -/* nlm_test ---------------------------------------------------------------- */ -/* - Purpose: Test whether a specified lock would be granted if requested - Returns: nlm_granted (or error code) - Notes: -*/ - -nlm_testres *nlm_test_1_svc(nlm_testargs *arg, struct svc_req *rqstp) -{ - static nlm_testres res; - if (debug_level) log_from_addr("nlm_test", rqstp); - - /* Copy the cookie from the argument into the result. Note that this */ - /* is slightly hazardous, as the structure contains a pointer to a */ - /* malloc()ed buffer that will get freed by the caller. However, the */ - /* main function transmits the result before freeing the argument */ - /* so it is in fact safe. */ - res.cookie = arg->cookie; - res.stat.stat = nlm_granted; - return (&res); -} - -void *nlm_test_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp) -{ - nlm_testres res; - static char dummy; - struct sockaddr_in *addr; - CLIENT *cli; - int success; - struct timeval timeo; - - if (debug_level) log_from_addr("nlm_test_msg", rqstp); - - res.cookie = arg->cookie; - res.stat.stat = nlm_granted; - - /* nlm_test has different result type to the other operations, so */ - /* can't use transmit_result() in this case */ - addr = svc_getcaller(rqstp->rq_xprt); - if (cli = get_client(addr)) - { - timeo.tv_sec = 0; /* No timeout - not expecting response */ - timeo.tv_usec = 0; - - success = clnt_call(cli, NLM_TEST_RES, xdr_nlm_testres, &res, xdr_void, - &dummy, timeo); - - if (debug_level > 2) syslog(LOG_DEBUG, "clnt_call returns %d\n", success); - } - return (NULL); -} - -/* nlm_lock ---------------------------------------------------------------- */ -/* - Purposes: Establish a lock - Returns: granted, denied or blocked - Notes: *** grace period support missing -*/ - -nlm_res *nlm_lock_1_svc(nlm_lockargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - if (debug_level) log_from_addr("nlm_lock", rqstp); - - /* copy cookie from arg to result. See comment in nlm_test_1() */ - res.cookie = arg->cookie; - - res.stat.stat = nlm_granted; - return (&res); -} - -void *nlm_lock_msg_1_svc(nlm_lockargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - - if (debug_level) log_from_addr("nlm_lock_msg", rqstp); - - res.cookie = arg->cookie; - res.stat.stat = nlm_granted; - transmit_result(NLM_LOCK_RES, &res, rqstp); - - return (NULL); -} - -/* nlm_cancel -------------------------------------------------------------- */ -/* - Purpose: Cancel a blocked lock request - Returns: granted or denied - Notes: -*/ - -nlm_res *nlm_cancel_1_svc(nlm_cancargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - if (debug_level) log_from_addr("nlm_cancel", rqstp); - - /* copy cookie from arg to result. See comment in nlm_test_1() */ - res.cookie = arg->cookie; - - /* Since at present we never return 'nlm_blocked', there can never be */ - /* a lock to cancel, so this call always fails. */ - res.stat.stat = nlm_denied; - return (&res); -} - -void *nlm_cancel_msg_1_svc(nlm_cancargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - if (debug_level) log_from_addr("nlm_cancel_msg", rqstp); - - res.cookie = arg->cookie; - /* Since at present we never return 'nlm_blocked', there can never be */ - /* a lock to cancel, so this call always fails. */ - res.stat.stat = nlm_denied; - transmit_result(NLM_CANCEL_RES, &res, rqstp); - return (NULL); -} - -/* nlm_unlock -------------------------------------------------------------- */ -/* - Purpose: Release an existing lock - Returns: Always granted, unless during grace period - Notes: "no such lock" error condition is ignored, as the - protocol uses unreliable UDP datagrams, and may well - re-try an unlock that has already succeeded. -*/ - -nlm_res *nlm_unlock_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - if (debug_level) log_from_addr("nlm_unlock", rqstp); - - res.stat.stat= nlm_granted; - res.cookie = arg->cookie; - - return (&res); -} - -void *nlm_unlock_msg_1_svc(nlm_unlockargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - if (debug_level) log_from_addr("nlm_unlock_msg", rqstp); - - res.stat.stat = nlm_granted; - res.cookie = arg->cookie; - - transmit_result(NLM_UNLOCK_RES, &res, rqstp); - return (NULL); -} - -/* ------------------------------------------------------------------------- */ -/* - Client-side pseudo-RPCs for results. Note that for the client there - are only nlm_xxx_msg() versions of each call, since the 'real RPC' - version returns the results in the RPC result, and so the client - does not normally receive incoming RPCs. - - The exception to this is nlm_granted(), which is genuinely an RPC - call from the server to the client - a 'call-back' in normal procedure - call terms. -*/ - -/* nlm_granted ------------------------------------------------------------- */ -/* - Purpose: Receive notification that formerly blocked lock now granted - Returns: always success ('granted') - Notes: -*/ - -nlm_res *nlm_granted_1_svc(nlm_testargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - if (debug_level) log_from_addr("nlm_granted", rqstp); - - /* copy cookie from arg to result. See comment in nlm_test_1() */ - res.cookie = arg->cookie; - - res.stat.stat = nlm_granted; - return (&res); -} - -void *nlm_granted_msg_1_svc(nlm_testargs *arg, struct svc_req *rqstp) -{ - nlm_res res; - if (debug_level) log_from_addr("nlm_granted_msg", rqstp); - - res.cookie = arg->cookie; - res.stat.stat = nlm_granted; - transmit_result(NLM_GRANTED_RES, &res, rqstp); - return (NULL); -} - -/* nlm_test_res ------------------------------------------------------------ */ -/* - Purpose: Accept result from earlier nlm_test_msg() call - Returns: Nothing -*/ - -void *nlm_test_res_1_svc(nlm_testres *arg, struct svc_req *rqstp) -{ - if (debug_level) log_from_addr("nlm_test_res", rqstp); - return (NULL); -} - -/* nlm_lock_res ------------------------------------------------------------ */ -/* - Purpose: Accept result from earlier nlm_lock_msg() call - Returns: Nothing -*/ - -void *nlm_lock_res_1_svc(nlm_res *arg, struct svc_req *rqstp) -{ - if (debug_level) log_from_addr("nlm_lock_res", rqstp); - - return (NULL); -} - -/* nlm_cancel_res ---------------------------------------------------------- */ -/* - Purpose: Accept result from earlier nlm_cancel_msg() call - Returns: Nothing -*/ - -void *nlm_cancel_res_1_svc(nlm_res *arg, struct svc_req *rqstp) -{ - if (debug_level) log_from_addr("nlm_cancel_res", rqstp); - return (NULL); -} - -/* nlm_unlock_res ---------------------------------------------------------- */ -/* - Purpose: Accept result from earlier nlm_unlock_msg() call - Returns: Nothing -*/ - -void *nlm_unlock_res_1_svc(nlm_res *arg, struct svc_req *rqstp) -{ - if (debug_level) log_from_addr("nlm_unlock_res", rqstp); - return (NULL); -} - -/* nlm_granted_res --------------------------------------------------------- */ -/* - Purpose: Accept result from earlier nlm_granted_msg() call - Returns: Nothing -*/ - -void *nlm_granted_res_1_svc(nlm_res *arg, struct svc_req *rqstp) -{ - if (debug_level) log_from_addr("nlm_granted_res", rqstp); - return (NULL); -} - -/* ------------------------------------------------------------------------- */ -/* - Calls for PCNFS locking (aka non-monitored locking, no involvement - of rpc.statd). - - These are all genuine RPCs - no nlm_xxx_msg() nonsense here. -*/ - - -/* nlm_share --------------------------------------------------------------- */ -/* - Purpose: Establish a DOS-style lock - Returns: success or failure - Notes: Blocking locks are not supported - client is expected - to retry if required. -*/ - -nlm_shareres *nlm_share_3_svc(nlm_shareargs *arg, struct svc_req *rqstp) -{ - static nlm_shareres res; - if (debug_level) log_from_addr("nlm_share", rqstp); - - res.cookie = arg->cookie; - res.stat = nlm_granted; - res.sequence = 1234356; /* X/Open says this field is ignored? */ - return (&res); -} - -/* nlm_unshare ------------------------------------------------------------ */ -/* - Purpose: Release a DOS-style lock - Returns: nlm_granted, unless in grace period - Notes: -*/ - -nlm_shareres *nlm_unshare_3_svc(nlm_shareargs *arg, struct svc_req *rqstp) -{ - static nlm_shareres res; - if (debug_level) log_from_addr("nlm_unshare", rqstp); - - res.cookie = arg->cookie; - res.stat = nlm_granted; - res.sequence = 1234356; /* X/Open says this field is ignored? */ - return (&res); -} - -/* nlm_nm_lock ------------------------------------------------------------ */ -/* - Purpose: non-monitored version of nlm_lock() - Returns: as for nlm_lock() - Notes: These locks are in the same style as the standard nlm_lock, - but the rpc.statd should not be called to establish a - monitor for the client machine, since that machine is - declared not to be running a rpc.statd, and so would not - respond to the statd protocol. -*/ - -nlm_res *nlm_nm_lock_3_svc(nlm_lockargs *arg, struct svc_req *rqstp) -{ - static nlm_res res; - if (debug_level) log_from_addr("nlm_nm_lock", rqstp); - - /* copy cookie from arg to result. See comment in nlm_test_1() */ - res.cookie = arg->cookie; - res.stat.stat = nlm_granted; - return (&res); -} - -/* nlm_free_all ------------------------------------------------------------ */ -/* - Purpose: Release all locks held by a named client - Returns: Nothing - Notes: Potential denial of service security problem here - the - locks to be released are specified by a host name, independent - of the address from which the request has arrived. - Should probably be rejected if the named host has been - using monitored locks. -*/ - -void *nlm_free_all_3_svc(nlm_notify *arg, struct svc_req *rqstp) -{ - static char dummy; - - if (debug_level) log_from_addr("nlm_free_all", rqstp); - return (&dummy); -} - - diff --git a/sbin/rpc.lockd/rpc.lockd.8 b/sbin/rpc.lockd/rpc.lockd.8 deleted file mode 100644 index d1fb0a0b6916..000000000000 --- a/sbin/rpc.lockd/rpc.lockd.8 +++ /dev/null @@ -1,94 +0,0 @@ -.\" -*- nroff -*- -.\" -.\" Copyright (c) 1995 A.R.Gordon, andrew.gordon@net-tel.co.uk -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" -.Dd September 24, 1995 -.Dt RPC.LOCK 8 -.Os -.Sh NAME -.Nm rpc.lock -.Nd NFS file locking daemon -.Sh SYNOPSIS -.Nm /sbin/rpc.lockd -.Op Fl d Op Ar debug_level -.Sh DESCRIPTION -.Nm rpc.rstatd -is a daemon which provides file- and record-locking services in an NFS -environment. -.Pp -Options and operands available for -.Nm rpc.lockd : -.Bl -tag -width Ds -.It Fl d -The -.Fl d -option causes debugging information to be written to syslog, recording -all RPC transations to the daemon. These messages are logged with level -LOG_DEBUG and facility LOG_DAEMON. If debug_level is not specified, -level 1 is assumed, giving one log line per protocol operation. Higher -debug levels can be specified, causing display of operation arguments -and internal operations of the daemon. -.El -.Pp -Error conditions are logged to syslog, irrespecive of the debug level, -using log level LOG_ERR and facility LOG_DAEMON. -.Pp -The -.Nm rpc.lockd -daemon must NOT be invoked by -.Xr inetd 8 -because the protocol assumes that the daemon will run from system start time. -Instead, it should be run from -.Xr rc 8 -after the network has been started. -.Sh FILES -.Bl -tag -width /usr/include/rpcsvc/nlm_prot.x -compact -.It Pa /usr/include/rpcsvc/nlm_prot.x -RPC protocol specification for the network lock manager protocol. -.El -.Sh SEE ALSO -.Xr rpc.statd 8 , -.Xr rc 8 , -.Xr syslog 3 -.Sh BUGS -The current implementation provides only the server side of the protocol -(ie. clients running other OS types can establish locks on a FreeBSD fileserver, -but there is currently no means for a FreeBSD client to establish locks). -.Pp -Versions 1, 2 and 3 of the protocol are supported. However, only versions -2 (Unix systems) and 3 (PC-NFS clients) seem to be in common use - the version -1 support has not been tested due to the lack of version 1 clients against -which to test. -.Sh STANDARDS -The implementation is based on the specification in X/Open CAE Specification -C218, "Protocols for X/Open PC Interworking: XNFS, Issue 4", ISBN 1 872630 66 9 diff --git a/sbin/rpc.lockd/test.c b/sbin/rpc.lockd/test.c deleted file mode 100644 index 2f1eb5ad29f6..000000000000 --- a/sbin/rpc.lockd/test.c +++ /dev/null @@ -1,362 +0,0 @@ -#include -#include -#ifndef lint -/*static char sccsid[] = "from: @(#)nlm_prot.x 1.8 87/09/21 Copyr 1987 Sun Micro";*/ -/*static char sccsid[] = "from: * @(#)nlm_prot.x 2.1 88/08/01 4.0 RPCSRC";*/ -static char rcsid[] = "nlm_prot.x,v 1.1 1994/08/04 19:01:48 wollman Exp"; -#endif /* not lint */ - -/* Default timeout can be changed using clnt_control() */ -static struct timeval TIMEOUT = { 0, 0 }; - -nlm_testres * -nlm_test_1(argp, clnt) - struct nlm_testargs *argp; - CLIENT *clnt; -{ - static nlm_testres res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_TEST, xdr_nlm_testargs, argp, xdr_nlm_testres, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return (&res); -} - - -nlm_res * -nlm_lock_1(argp, clnt) - struct nlm_lockargs *argp; - CLIENT *clnt; -{ - enum clnt_stat st; - static nlm_res res; - - bzero((char *)&res, sizeof(res)); - if (st = clnt_call(clnt, NLM_LOCK, xdr_nlm_lockargs, argp, xdr_nlm_res, &res, TIMEOUT) != RPC_SUCCESS) { - printf("clnt_call returns %d\n", st); - clnt_perror(clnt, "humbug"); - return (NULL); - } - return (&res); -} - - -nlm_res * -nlm_cancel_1(argp, clnt) - struct nlm_cancargs *argp; - CLIENT *clnt; -{ - static nlm_res res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_CANCEL, xdr_nlm_cancargs, argp, xdr_nlm_res, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return (&res); -} - - -nlm_res * -nlm_unlock_1(argp, clnt) - struct nlm_unlockargs *argp; - CLIENT *clnt; -{ - static nlm_res res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_UNLOCK, xdr_nlm_unlockargs, argp, xdr_nlm_res, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return (&res); -} - - -nlm_res * -nlm_granted_1(argp, clnt) - struct nlm_testargs *argp; - CLIENT *clnt; -{ - static nlm_res res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_GRANTED, xdr_nlm_testargs, argp, xdr_nlm_res, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return (&res); -} - - -void * -nlm_test_msg_1(argp, clnt) - struct nlm_testargs *argp; - CLIENT *clnt; -{ - static char res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_TEST_MSG, xdr_nlm_testargs, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return ((void *)&res); -} - - -void * -nlm_lock_msg_1(argp, clnt) - struct nlm_lockargs *argp; - CLIENT *clnt; -{ - static char res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_LOCK_MSG, xdr_nlm_lockargs, argp, xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) { - clnt_perror(clnt, "nlm_lock_msg_1"); - return (NULL); - } - return ((void *)&res); -} - - -void * -nlm_cancel_msg_1(argp, clnt) - struct nlm_cancargs *argp; - CLIENT *clnt; -{ - static char res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_CANCEL_MSG, xdr_nlm_cancargs, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return ((void *)&res); -} - - -void * -nlm_unlock_msg_1(argp, clnt) - struct nlm_unlockargs *argp; - CLIENT *clnt; -{ - static char res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_UNLOCK_MSG, xdr_nlm_unlockargs, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return ((void *)&res); -} - - -void * -nlm_granted_msg_1(argp, clnt) - struct nlm_testargs *argp; - CLIENT *clnt; -{ - static char res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_GRANTED_MSG, xdr_nlm_testargs, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return ((void *)&res); -} - - -void * -nlm_test_res_1(argp, clnt) - nlm_testres *argp; - CLIENT *clnt; -{ - static char res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_TEST_RES, xdr_nlm_testres, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return ((void *)&res); -} - - -void * -nlm_lock_res_1(argp, clnt) - nlm_res *argp; - CLIENT *clnt; -{ - static char res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_LOCK_RES, xdr_nlm_res, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return ((void *)&res); -} - - -void * -nlm_cancel_res_1(argp, clnt) - nlm_res *argp; - CLIENT *clnt; -{ - static char res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_CANCEL_RES, xdr_nlm_res, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return ((void *)&res); -} - - -void * -nlm_unlock_res_1(argp, clnt) - nlm_res *argp; - CLIENT *clnt; -{ - static char res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_UNLOCK_RES, xdr_nlm_res, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return ((void *)&res); -} - - -void * -nlm_granted_res_1(argp, clnt) - nlm_res *argp; - CLIENT *clnt; -{ - static char res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_GRANTED_RES, xdr_nlm_res, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return ((void *)&res); -} - - -nlm_shareres * -nlm_share_3(argp, clnt) - nlm_shareargs *argp; - CLIENT *clnt; -{ - static nlm_shareres res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_SHARE, xdr_nlm_shareargs, argp, xdr_nlm_shareres, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return (&res); -} - - -nlm_shareres * -nlm_unshare_3(argp, clnt) - nlm_shareargs *argp; - CLIENT *clnt; -{ - static nlm_shareres res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_UNSHARE, xdr_nlm_shareargs, argp, xdr_nlm_shareres, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return (&res); -} - - -nlm_res * -nlm_nm_lock_3(argp, clnt) - nlm_lockargs *argp; - CLIENT *clnt; -{ - static nlm_res res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_NM_LOCK, xdr_nlm_lockargs, argp, xdr_nlm_res, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return (&res); -} - - -void * -nlm_free_all_3(argp, clnt) - nlm_notify *argp; - CLIENT *clnt; -{ - static char res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, NLM_FREE_ALL, xdr_nlm_notify, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return ((void *)&res); -} - - -int main(int argc, char **argv) -{ - CLIENT *cli; - nlm_res res_block; - nlm_res *out; - nlm_lockargs arg; - struct timeval tim; - - printf("Creating client for host %s\n", argv[1]); - cli = clnt_create(argv[1], NLM_PROG, NLM_VERS, "udp"); - if (!cli) - { - printf("Failed to create client\n"); - exit(1); - } - - - clnt_control(cli, CLGET_TIMEOUT, &tim); - printf("Default timeout was %d.%d\n", tim.tv_sec, tim.tv_usec); - tim.tv_usec = -1; - tim.tv_sec = -1; - clnt_control(cli, CLSET_TIMEOUT, &tim); - clnt_control(cli, CLGET_TIMEOUT, &tim); - printf("timeout now %d.%d\n", tim.tv_sec, tim.tv_usec); - - - arg.cookie.n_len = 4; - arg.cookie.n_bytes = "hello"; - arg.block = 0; - arg.exclusive = 0; - arg.reclaim = 0; - arg.state = 0x1234; - arg.alock.caller_name = "localhost"; - arg.alock.fh.n_len = 32; - arg.alock.fh.n_bytes = "\x04\x04\x02\x00\x01\x00\x00\x00\x0c\x00\x00\x00\xff\xff\xff\xd0\x16\x00\x00\x5b\x7c\xff\xff\xff\xec\x2f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x19\x54\xef\xbf\xd7\x94"; - arg.alock.oh.n_len = 8; - arg.alock.oh.n_bytes = "\x00\x00\x02\xff\xff\xff\xd3"; - arg.alock.svid = 0x5678; - arg.alock.l_offset = 0; - arg.alock.l_len = 100; - - res_block.stat.stat = nlm_granted; - res_block.cookie.n_bytes = "hello"; - res_block.cookie.n_len = 5; - -#if 0 - if (nlm_lock_res_1(&res_block, cli)) printf("Success!\n"); - else printf("Fail\n"); -#else - if (out = nlm_lock_msg_1(&arg, cli)) - { - printf("Success!\n"); - printf("out->stat = %d", out->stat); - } - else - { - printf("Fail\n"); - } -#endif - - return 0; -} diff --git a/sbin/rpc.statd/Makefile b/sbin/rpc.statd/Makefile deleted file mode 100644 index 082963aaf539..000000000000 --- a/sbin/rpc.statd/Makefile +++ /dev/null @@ -1,26 +0,0 @@ -# $Id: Makefile,v 1.1.1.1 1996/02/17 15:11:28 peter Exp $ - -PROG = rpc.statd -SRCS = file.c sm_inter_svc.c statd.c procs.c -MAN8 = rpc.statd.8 - -DPADD= ${LIBRPCSVC} -LDADD= -lrpcsvc - -CFLAGS+= -I. - -CLEANFILES= sm_inter_svc.c sm_inter.h - -RPCSRC= ${.DESTDIR}/usr/include/rpcsvc/sm_inter.x -RPCGEN= rpcgen -L -C - -sm_inter_svc.c: ${RPCSRC} sm_inter.h - ${RPCGEN} -m -o ${.TARGET} ${RPCSRC} - -sm_inter.h: ${RPCSRC} - ${RPCGEN} -h -o ${.TARGET} ${RPCSRC} - -test: test.c - cc -o test test.c -lrpcsvc - -.include diff --git a/sbin/rpc.statd/file.c b/sbin/rpc.statd/file.c deleted file mode 100644 index aeb1fc09651d..000000000000 --- a/sbin/rpc.statd/file.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Copyright (c) 1995 - * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the FreeBSD project - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include -#include -#include -#include -#include -#include -#include /* For mmap() */ -#include -#include - -#include "statd.h" - -FileLayout *status_info; /* Pointer to the mmap()ed status file */ -static int status_fd; /* File descriptor for the open file */ -static off_t status_file_len; /* Current on-disc length of file */ - -/* sync_file --------------------------------------------------------------- */ -/* - Purpose: Packaged call of msync() to flush changes to mmap()ed file - Returns: Nothing. Errors to syslog. -*/ - -void sync_file(void) -{ - if (msync((void *)status_info, 0, 0) < 0) - { - syslog(LOG_ERR, "msync() failed: %s", strerror(errno)); - } -} - -/* find_host -------------------------------------------------------------- */ -/* - Purpose: Find the entry in the status file for a given host - Returns: Pointer to that entry in the mmap() region, or NULL. - Notes: Also creates entries if requested. - Failure to create also returns NULL. -*/ - -HostInfo *find_host(char *hostname, int create) -{ - HostInfo *hp; - HostInfo *spare_slot = NULL; - HostInfo *result = NULL; - int i; - - for (i = 0, hp = status_info->hosts; i < status_info->noOfHosts; i++, hp++) - { - if (!strncasecmp(hostname, hp->hostname, SM_MAXSTRLEN)) - { - result = hp; - break; - } - if (!spare_slot && !hp->monList && !hp->notifyReqd) - spare_slot = hp; - } - - /* Return if entry found, or if not asked to create one. */ - if (result || !create) return (result); - - /* Now create an entry, using the spare slot if one was found or */ - /* adding to the end of the list otherwise, extending file if reqd */ - if (!spare_slot) - { - off_t desired_size; - spare_slot = &status_info->hosts[status_info->noOfHosts]; - desired_size = ((char*)spare_slot - (char*)status_info) + sizeof(HostInfo); - if (desired_size > status_file_len) - { - /* Extend file by writing 1 byte of junk at the desired end pos */ - lseek(status_fd, desired_size - 1, SEEK_SET); - i = write(status_fd, &i, 1); - if (i < 1) - { - syslog(LOG_ERR, "Unable to extend status file"); - return (NULL); - } - status_file_len = desired_size; - } - status_info->noOfHosts++; - } - - /* Initialise the spare slot that has been found/created */ - /* Note that we do not msync(), since the caller is presumed to be */ - /* about to modify the entry further */ - memset(spare_slot, 0, sizeof(HostInfo)); - strncpy(spare_slot->hostname, hostname, SM_MAXSTRLEN); - return (spare_slot); -} - -/* init_file -------------------------------------------------------------- */ -/* - Purpose: Open file, create if necessary, initialise it. - Returns: Nothing - exits on error - Notes: Called before process becomes daemon, hence logs to - stderr rather than syslog. - Opens the file, then mmap()s it for ease of access. - Also performs initial clean-up of the file, zeroing - monitor list pointers, setting the notifyReqd flag in - all hosts that had a monitor list, and incrementing - the state number to the next even value. -*/ - -void init_file(char *filename) -{ - int new_file = FALSE; - char buf[HEADER_LEN]; - int i; - - /* try to open existing file - if not present, create one */ - status_fd = open(filename, O_RDWR); - if ((status_fd < 0) && (errno == ENOENT)) - { - status_fd = open(filename, O_RDWR | O_CREAT, 0644); - new_file = TRUE; - } - if (status_fd < 0) - { - perror("rpc.statd"); - fprintf(stderr, "Unable to open status file %s\n", filename); - exit(1); - } - - /* File now open. mmap() it, with a generous size to allow for */ - /* later growth, where we will extend the file but not re-map it. */ - status_info = (FileLayout *) - mmap(NULL, 0x10000000, PROT_READ | PROT_WRITE, MAP_SHARED, status_fd, 0); - - if (status_info == (FileLayout *) -1) - { - perror("rpc.statd"); - fprintf(stderr, "Unable to mmap() status file\n"); - } - - status_file_len = lseek(status_fd, 0L, SEEK_END); - - /* If the file was not newly created, validate the contents, and if */ - /* defective, re-create from scratch. */ - if (!new_file) - { - if ((status_file_len < HEADER_LEN) || (status_file_len - < (HEADER_LEN + sizeof(HostInfo) * status_info->noOfHosts)) ) - { - fprintf(stderr, "rpc.statd: status file is corrupt\n"); - new_file = TRUE; - } - } - - /* Initialisation of a new, empty file. */ - if (new_file) - { - memset(buf, 0, sizeof(buf)); - lseek(status_fd, 0L, SEEK_SET); - write(status_fd, buf, HEADER_LEN); - status_file_len = HEADER_LEN; - } - else - { - /* Clean-up of existing file - monitored hosts will have a pointer */ - /* to a list of clients, which refers to memory in the previous */ - /* incarnation of the program and so are meaningless now. These */ - /* pointers are zeroed and the fact that the host was previously */ - /* monitored is recorded by setting the notifyReqd flag, which will */ - /* in due course cause a SM_NOTIFY to be sent. */ - /* Note that if we crash twice in quick succession, some hosts may */ - /* already have notifyReqd set, where we didn't manage to notify */ - /* them before the second crash occurred. */ - for (i = 0; i < status_info->noOfHosts; i++) - { - HostInfo *this_host = &status_info->hosts[i]; - - if (this_host->monList) - { - this_host->notifyReqd = TRUE; - this_host->monList = NULL; - } - } - /* Select the next higher even number for the state counter */ - status_info->ourState = (status_info->ourState + 2) & 0xfffffffe; -/*???????******/ status_info->ourState++; - } -} - -/* xdr_stat_chge ----------------------------------------------------------- */ -/* - Purpose: XDR-encode structure of type stat_chge - Returns: TRUE if successful - Notes: This function is missing from librpcsvc, because the - sm_inter.x distributed by Sun omits the SM_NOTIFY - procedure used between co-operating statd's -*/ - -bool_t xdr_stat_chge(XDR *xdrs, stat_chge *objp) -{ - if (!xdr_string(xdrs, &objp->mon_name, SM_MAXSTRLEN)) - { - return (FALSE); - } - if (!xdr_int(xdrs, &objp->state)) - { - return (FALSE); - } - return (TRUE); -} - - -/* notify_one_host --------------------------------------------------------- */ -/* - Purpose: Perform SM_NOTIFY procedure at specified host - Returns: TRUE if success, FALSE if failed. -*/ - -static int notify_one_host(char *hostname) -{ - struct timeval timeout = { 20, 0 }; /* 20 secs timeout */ - CLIENT *cli; - char dummy; - stat_chge arg; - char our_hostname[SM_MAXSTRLEN+1]; - - gethostname(our_hostname, sizeof(our_hostname)); - our_hostname[SM_MAXSTRLEN] = '\0'; - arg.mon_name = our_hostname; - arg.state = status_info->ourState; - - if (debug) syslog (LOG_DEBUG, "Sending SM_NOTIFY to host %s from %s", hostname, our_hostname); - - cli = clnt_create(hostname, SM_PROG, SM_VERS, "udp"); - if (!cli) - { - syslog(LOG_ERR, "Failed to contact host %s%s", hostname, - clnt_spcreateerror("")); - return (FALSE); - } - - if (clnt_call(cli, SM_NOTIFY, xdr_stat_chge, &arg, xdr_void, &dummy, timeout) - != RPC_SUCCESS) - { - syslog(LOG_ERR, "Failed to contact rpc.statd at host %s", hostname); - clnt_destroy(cli); - return (FALSE); - } - - clnt_destroy(cli); - return (TRUE); -} - -/* notify_hosts ------------------------------------------------------------ */ -/* - Purpose: Send SM_NOTIFY to all hosts marked as requiring it - Returns: Nothing, immediately - forks a process to do the work. - Notes: Does nothing if there are no monitored hosts. - Called after all the initialisation has been done - - logs to syslog. -*/ - -void notify_hosts(void) -{ - int i; - int attempts; - int work_to_do = FALSE; - HostInfo *hp; - pid_t pid; - - /* First check if there is in fact any work to do. */ - for (i = status_info->noOfHosts, hp = status_info->hosts; i ; i--, hp++) - { - if (hp->notifyReqd) - { - work_to_do = TRUE; - break; - } - } - - if (!work_to_do) return; /* No work found */ - - pid = fork(); - if (pid == -1) - { - syslog(LOG_ERR, "Unable to fork notify process - %s", strerror(errno)); - return; - } - if (pid) return; - - /* Here in the child process. We continue until all the hosts marked */ - /* as requiring notification have been duly notified. */ - /* If one of the initial attempts fails, we sleep for a while and */ - /* have another go. This is necessary because when we have crashed, */ - /* (eg. a power outage) it is quite possible that we won't be able to */ - /* contact all monitored hosts immediately on restart, either because */ - /* they crashed too and take longer to come up (in which case the */ - /* notification isn't really required), or more importantly if some */ - /* router etc. needed to reach the monitored host has not come back */ - /* up yet. In this case, we will be a bit late in re-establishing */ - /* locks (after the grace period) but that is the best we can do. */ - /* We try 10 times at 5 sec intervals, 10 more times at 1 minute */ - /* intervals, then 24 more times at hourly intervals, finally */ - /* giving up altogether if the host hasn't come back to life after */ - /* 24 hours. */ - - for (attempts = 0; attempts < 44; attempts++) - { - work_to_do = FALSE; /* Unless anything fails */ - for (i = status_info->noOfHosts, hp = status_info->hosts; i ; i--, hp++) - { - if (hp->notifyReqd) - { - if (notify_one_host(hp->hostname)) - { - hp->notifyReqd = FALSE; - sync_file(); - } - else work_to_do = TRUE; - } - } - if (!work_to_do) break; - if (attempts < 10) sleep(5); - else if (attempts < 20) sleep(60); - else sleep(60*60); - } - exit(0); -} - - diff --git a/sbin/rpc.statd/procs.c b/sbin/rpc.statd/procs.c deleted file mode 100644 index c43f86b9ad5f..000000000000 --- a/sbin/rpc.statd/procs.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (c) 1995 - * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the FreeBSD project - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - - -#include -#include -#include -#include -#include -#include -#include /* for gethostbyname() */ - -#include "statd.h" - -/* sm_stat_1 --------------------------------------------------------------- */ -/* - Purpose: RPC call to enquire if a host can be monitored - Returns: TRUE for any hostname that can be looked up to give - an address. -*/ - -struct sm_stat_res *sm_stat_1_svc(sm_name *arg, struct svc_req *req) -{ - static sm_stat_res res; - - if (debug) syslog(LOG_DEBUG, "stat called for host %s", arg->mon_name); - - if (gethostbyname(arg->mon_name)) res.res_stat = stat_succ; - else - { - syslog(LOG_ERR, "invalid hostname to sm_stat: %s", arg->mon_name); - res.res_stat = stat_fail; - } - - res.state = status_info->ourState; - return (&res); -} - -/* sm_mon_1 ---------------------------------------------------------------- */ -/* - Purpose: RPC procedure to establish a monitor request - Returns: Success, unless lack of resources prevents - the necessary structures from being set up - to record the request, or if the hostname is not - valid (as judged by gethostbyname()) -*/ - -struct sm_stat_res *sm_mon_1_svc(mon *arg, struct svc_req *req) -{ - static sm_stat_res res; - HostInfo *hp; - MonList *lp; - - if (debug) - { - syslog(LOG_DEBUG, "monitor request for host %s", arg->mon_id.mon_name); - syslog(LOG_DEBUG, "recall host: %s prog: %d ver: %d proc: %d", - arg->mon_id.mon_name, arg->mon_id.my_id.my_name, - arg->mon_id.my_id.my_prog, arg->mon_id.my_id.my_vers, - arg->mon_id.my_id.my_proc); - } - - res.res_stat = stat_fail; /* Assume fail until set otherwise */ - res.state = status_info->ourState; - - /* Find existing host entry, or create one if not found */ - /* If find_host() fails, it will have logged the error already. */ - if (!gethostbyname(arg->mon_id.mon_name)) - { - syslog(LOG_ERR, "Invalid hostname to sm_mon: %s", arg->mon_id.mon_name); - } - else if (hp = find_host(arg->mon_id.mon_name, TRUE)) - { - lp = (MonList *)malloc(sizeof(MonList)); - if (!lp) - { - syslog(LOG_ERR, "Out of memory"); - } - else - { - strncpy(lp->notifyHost, arg->mon_id.my_id.my_name, SM_MAXSTRLEN); - lp->notifyProg = arg->mon_id.my_id.my_prog; - lp->notifyVers = arg->mon_id.my_id.my_vers; - lp->notifyProc = arg->mon_id.my_id.my_proc; - memcpy(lp->notifyData, arg->priv, sizeof(lp->notifyData)); - - lp->next = hp->monList; - hp->monList = lp; - sync_file(); - - res.res_stat = stat_succ; /* Report success */ - } - } - - return (&res); -} - -/* do_unmon ---------------------------------------------------------------- */ -/* - Purpose: Remove a monitor request from a host - Returns: TRUE if found, FALSE if not found. - Notes: Common code from sm_unmon_1_svc and sm_unmon_all_1_svc - In the unlikely event of more than one identical monitor - request, all are removed. -*/ - -static int do_unmon(HostInfo *hp, my_id *idp) -{ - MonList *lp, *next; - MonList *last = NULL; - int result = FALSE; - - lp = hp->monList; - while (lp) - { - if (!strncasecmp(idp->my_name, lp->notifyHost, SM_MAXSTRLEN) - && (idp->my_prog == lp->notifyProg) && (idp->my_proc == lp->notifyProc) - && (idp->my_vers == lp->notifyVers)) - { - /* found one. Unhook from chain and free. */ - next = lp->next; - if (last) last->next = next; - else hp->monList = next; - free(lp); - lp = next; - result = TRUE; - } - else - { - last = lp; - lp = lp->next; - } - } - return (result); -} - -/* sm_unmon_1 -------------------------------------------------------------- */ -/* - Purpose: RPC procedure to release a monitor request. - Returns: Local machine's status number - Notes: The supplied mon_id should match the value passed in an - earlier call to sm_mon_1 -*/ - -struct sm_stat *sm_unmon_1_svc(mon_id *arg, struct svc_req *req) -{ - static sm_stat res; - HostInfo *hp; - - if (debug) - { - syslog(LOG_DEBUG, "un-monitor request for host %s", arg->mon_name); - syslog(LOG_DEBUG, "recall host: %s prog: %d ver: %d proc: %d", - arg->mon_name, arg->my_id.my_name, arg->my_id.my_prog, - arg->my_id.my_vers, arg->my_id.my_proc); - } - - if (hp = find_host(arg->mon_name, FALSE)) - { - if (do_unmon(hp, &arg->my_id)) sync_file(); - else - { - syslog(LOG_ERR, "unmon request from %s, no matching monitor", - arg->my_id.my_name); - } - } - else syslog(LOG_ERR, "unmon request from %s for unknown host %s", - arg->my_id.my_name, arg->mon_name); - - res.state = status_info->ourState; - - return (&res); -} - -/* sm_unmon_all_1 ---------------------------------------------------------- */ -/* - Purpose: RPC procedure to release monitor requests. - Returns: Local machine's status number - Notes: Releases all monitor requests (if any) from the specified - host and program number. -*/ - -struct sm_stat *sm_unmon_all_1_svc(my_id *arg, struct svc_req *req) -{ - static sm_stat res; - HostInfo *hp; - MonList *lp; - int i; - - if (debug) - { - syslog(LOG_DEBUG, "unmon_all for host: %s prog: %d ver: %d proc: %d", - arg->my_name, arg->my_prog, arg->my_vers, arg->my_proc); - } - - for (i = status_info->noOfHosts, hp = status_info->hosts; i; i--, hp++) - { - do_unmon(hp, arg); - } - sync_file(); - - res.state = status_info->ourState; - - return (&res); -} - -/* sm_simu_crash_1 --------------------------------------------------------- */ -/* - Purpose: RPC procedure to simulate a crash - Returns: Nothing - Notes: Standardised mechanism for debug purposes - The specification says that we should drop all of our - status information (apart from the list of monitored hosts - on disc). However, this would confuse the rpc.lockd - which would be unaware that all of its monitor requests - had been silently junked. Hence we in fact retain all - current requests and simply increment the status counter - and inform all hosts on the monitor list. -*/ - -void *sm_simu_crash_1_svc(void *v, struct svc_req *req) -{ - static char dummy; - int work_to_do; - HostInfo *hp; - int i; - - if (debug) syslog(LOG_DEBUG, "simu_crash called!!"); - - /* Simulate crash by setting notify-required flag on all monitored */ - /* hosts, and incrementing our status number. notify_hosts() is */ - /* then called to fork a process to do the notifications. */ - - for (i = status_info->noOfHosts, hp = status_info->hosts; i ; i--, hp++) - { - if (hp->monList) - { - work_to_do = TRUE; - hp->notifyReqd = TRUE; - } - } - status_info->ourState += 2; /* always even numbers if not crashed */ - - if (work_to_do) notify_hosts(); - - return (&dummy); -} - -/* sm_notify_1 ------------------------------------------------------------- */ -/* - Purpose: RPC procedure notifying local statd of the crash of another - Returns: Nothing - Notes: There is danger of deadlock, since it is quite likely that - the client procedure that we call will in turn call us - to remove or adjust the monitor request. - We therefore fork() a process to do the notifications. - Note that the main HostInfo structure is in a mmap() - region and so will be shared with the child, but the - monList pointed to by the HostInfo is in normal memory. - Hence if we read the monList before forking, we are - protected from the parent servicing other requests - that modify the list. -*/ - -void *sm_notify_1_svc(stat_chge *arg, struct svc_req *req) -{ - struct timeval timeout = { 20, 0 }; /* 20 secs timeout */ - CLIENT *cli; - static char dummy; - status tx_arg; /* arg sent to callback procedure */ - MonList *lp; - HostInfo *hp; - pid_t pid; - - if (debug) syslog(LOG_DEBUG, "notify from host %s, new state %d", - arg->mon_name, arg->state); - - hp = find_host(arg->mon_name, FALSE); - if (!hp) - { - /* Never heard of this host - why is it notifying us? */ - syslog(LOG_ERR, "Unsolicited notification from host %s", arg->mon_name); - return; - } - lp = hp->monList; - if (!lp) return (FALSE); /* We know this host, but have no */ - /* outstanding requests. */ - pid = fork(); - if (pid == -1) - { - syslog(LOG_ERR, "Unable to fork notify process - %s", strerror(errno)); - return; - } - if (pid) return (&dummy); /* Parent returns */ - - while (lp) - { - tx_arg.mon_name = arg->mon_name; - tx_arg.state = arg->state; - memcpy(tx_arg.priv, lp->notifyData, sizeof(tx_arg.priv)); - cli = clnt_create(lp->notifyHost, lp->notifyProg, lp->notifyVers, "udp"); - if (!cli) - { - syslog(LOG_ERR, "Failed to contact host %s%s", lp->notifyHost, - clnt_spcreateerror("")); - } - else - { - if (clnt_call(cli, lp->notifyProc, xdr_status, &tx_arg, xdr_void, &dummy, - timeout) != RPC_SUCCESS) - { - syslog(LOG_ERR, "Failed to call rpc.statd client at host %s", - lp->notifyHost); - } - clnt_destroy(cli); - } - lp = lp->next; - } - - exit (0); /* Child quits */ -} - diff --git a/sbin/rpc.statd/rpc.statd.8 b/sbin/rpc.statd/rpc.statd.8 deleted file mode 100644 index 34b095fedb23..000000000000 --- a/sbin/rpc.statd/rpc.statd.8 +++ /dev/null @@ -1,107 +0,0 @@ -.\" -*- nroff -*- -.\" -.\" Copyright (c) 1995 A.R.Gordon, andrew.gordon@net-tel.co.uk -.\" All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" -.Dd September 19, 1995 -.Dt RPC.STATD 8 -.Os -.Sh NAME -.Nm rpc.statd -.Nd host status monitoring daemon -.Sh SYNOPSIS -.Nm /sbin/rpc.statd -.Op Fl d -.Sh DESCRIPTION -.Nm rpc.rstatd -is a daemon which co-operates with rpc.statd daemons on other hosts to provide -a status monitoring service. The daemon accepts requests from -programs running on the local host (typically, -.Xr rpc.lockd 8 , -the NFS file locking daemon) to monitor the status of specified -hosts. If a monitored host crashes and restarts, the remote daemon will -notify the local daemon, which in turn will notify the local program(s) -which requested the monitoring service. Conversely, if this host crashes -and re-starts, when the -.Nm rpc.statd -re-starts, it will notify all of the hosts which were being monitored -at the time of the crash. -.Pp -Options and operands available for -.Nm rpc.statd : -.Bl -tag -width Ds -.It Fl d -The -.Fl d -option causes debugging information to be written to syslog, recording -all RPC transations to the daemon. These messages are logged with level -LOG_DEBUG and facility LOG_DAEMON. Error conditions are logged irrespective -of this option, using level LOG_ERR. -.El -.Pp -The -.Nm rpc.rstatd -daemon must NOT be invoked by -.Xr inetd 8 -because the protocol assumes that the daemon will run from system start time. -Instead, it should be run from -.Xr rc 8 -after the network has been started. -.Sh FILES -.Bl -tag -width /usr/include/rpcsvc/sm_inter.x -compact -.It Pa /var/db/statd.status -non-volatile record of currently monitored hosts. -.It Pa /usr/include/rpcsvc/sm_inter.x -RPC protocol specification used by local applications to register monitoring requests. -.El -.Sh SEE ALSO -.Xr rpc.lockd 8 , -.Xr rc 8 , -.Xr syslog 3 -.Sh BUGS -There is no means for the daemon to tell when a monitored host has -disappeared permanently (eg. catastrophic harware failure), as opposed -to transient failure of the host or an intermediate router. At present, -it will re-try notification attempts at frequent intervals for 10 minutes, -then hourly, and finally gives up after 24 hours. - -The protocol requires that symmetric monitor requests are made to both -the local and remote daemon in order to establish a monitored relationship. -This is convenient for the NFS locking protocol, but probably reduces the -usefulness of the monitoring system for other applications. - -The current implementation uses more than 1Kbyte per monitored host in -the status file (and also in VM). This may be inefficient for NFS servers -with large numbers of clients. -.Sh STANDARDS -The implementation is based on the specification in X/Open CAE Specification -C218, "Protocols for X/Open PC Interworking: XNFS, Issue 4", ISBN 1 872630 66 9 diff --git a/sbin/rpc.statd/statd.c b/sbin/rpc.statd/statd.c deleted file mode 100644 index 915cab55c97f..000000000000 --- a/sbin/rpc.statd/statd.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 1995 - * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the FreeBSD project - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - - -/* main() function for status monitor daemon. Some of the code in this */ -/* file was generated by running rpcgen /usr/include/rpcsvc/sm_inter.x */ -/* The actual program logic is in the file procs.c */ - -#include -#include -#include -#include -#include -#include -#include "statd.h" - -#ifndef lint -static char rcsid[] = "$id: $"; -#endif /* not lint */ - -int debug = 0; /* Controls syslog() calls for debug messages */ - -extern void sm_prog_1(struct svc_req *rqstp, SVCXPRT *transp); -static void handle_sigchld(); - -main(int argc, char **argv) -{ - SVCXPRT *transp; - struct sigaction sa; - - if (argc > 1) - { - if (strcmp(argv[1], "-d")) - { - fprintf(stderr, "Usage: rpc.statd [-d]\n"); - exit(1); - } - debug = 1; - } - - (void)pmap_unset(SM_PROG, SM_VERS); - - transp = svcudp_create(RPC_ANYSOCK); - if (transp == NULL) - { - fprintf(stderr, "cannot create udp service.\n"); - exit(1); - } - if (!svc_register(transp, SM_PROG, SM_VERS, sm_prog_1, IPPROTO_UDP)) - { - fprintf(stderr, "unable to register (SM_PROG, SM_VERS, udp).\n"); - exit(1); - } - - transp = svctcp_create(RPC_ANYSOCK, 0, 0); - if (transp == NULL) - { - fprintf(stderr, "cannot create tcp service.\n"); - exit(1); - } - if (!svc_register(transp, SM_PROG, SM_VERS, sm_prog_1, IPPROTO_TCP)) { - fprintf(stderr, "unable to register (SM_PROG, SM_VERS, tcp).\n"); - exit(1); - } - init_file("/var/db/statd.status"); - - /* Note that it is NOT sensible to run this program from inetd - the */ - /* protocol assumes that it will run immediately at boot time. */ - daemon(0, 0); - openlog("rpc.statd", 0, LOG_DAEMON); - if (debug) syslog(LOG_INFO, "Starting - debug enabled"); - else syslog(LOG_INFO, "Starting"); - - /* Install signal handler to collect exit status of child processes */ - sa.sa_handler = handle_sigchld; - sigemptyset(&sa.sa_mask); - sigaddset(&sa.sa_mask, SIGCHLD); - sa.sa_flags = SA_RESTART; - sigaction(SIGCHLD, &sa, NULL); - - /* Initialisation now complete - start operating */ - notify_hosts(); /* Forks a process (if necessary) to do the */ - /* SM_NOTIFY calls, which may be slow. */ - - svc_run(); /* Should never return */ - exit(1); -} - - -/* handle_sigchld ---------------------------------------------------------- */ -/* - Purpose: Catch SIGCHLD and collect process status - Retruns: Nothing. - Notes: No special action required, other than to collect the - process status and hence allow the child to die: - we only use child processes for asynchronous transmission - of SM_NOTIFY to other systems, so it is normal for the - children to exit when they have done their work. -*/ - -static void handle_sigchld(int sig, int code, struct sigcontext *scp) -{ - int pid, status; - pid = wait4(-1, &status, WNOHANG, (struct rusage*)0); - if (!pid) syslog(LOG_ERR, "Phantom SIGCHLD??"); - else if (status == 0) - { - if (debug) syslog(LOG_DEBUG, "Child %d exited OK", pid); - } - else syslog(LOG_ERR, "Child %d failed with status %d", pid, - WEXITSTATUS(status)); -} - diff --git a/sbin/rpc.statd/statd.h b/sbin/rpc.statd/statd.h deleted file mode 100644 index 7b4e6598adae..000000000000 --- a/sbin/rpc.statd/statd.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 1995 - * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed for the FreeBSD project - * 4. Neither the name of the author nor the names of any co-contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - - - -#include "sm_inter.h" - -/* These pieces are missing from the distributed sm_inter.x, which */ -/* omits the SM_NOTIFY procedure used between cooperating rpc.statd's */ - -#define SM_NOTIFY ((u_long)6) -extern void *sm_notify_1(); - -struct stat_chge -{ - char *mon_name; - int state; -}; -typedef struct stat_chge stat_chge; -bool_t xdr_stat_chge(); - -/* ------------------------------------------------------------------------- */ -/* - Data structures for recording monitored hosts - - The information held by the status monitor comprises a list of hosts - that we have been asked to monitor, and, associated with each monitored - host, one or more clients to be called back if the monitored host crashes. - - The list of monitored hosts must be retained over a crash, so that upon - re-boot we can call the SM_NOTIFY procedure in all those hosts so as to - cause them to start recovery processing. On the other hand, the client - call-backs are not required to be preserved: they are assumed (in the - protocol design) to be local processes which will have crashed when - we did, and so are discarded on restart. - - We handle this by keeping the list of monitored hosts in a file - (/var/statd.state) which is mmap()ed and whose format is described - by the typedef FileLayout. The lists of client callbacks are chained - off this structure, but are held in normal memory and so will be - lost after a re-boot. Hence the actual values of MonList * pointers - in the copy on disc have no significance, but their NULL/non-NULL - status indicates whether this host is actually being monitored or if it - is an empty slot in the file. -*/ - -typedef struct MonList_s -{ - struct MonList_s *next; /* Next in list or NULL */ - char notifyHost[SM_MAXSTRLEN + 1]; /* Host to notify */ - int notifyProg; /* RPC program number to call */ - int notifyVers; /* version number */ - int notifyProc; /* procedure number */ - unsigned char notifyData[16]; /* Opaque data from caller */ -} MonList; - -typedef struct -{ - char hostname[SM_MAXSTRLEN + 1]; /* Name of monitored host */ - int notifyReqd; /* TRUE if we've crashed and not yet */ - /* informed the monitored host */ - MonList *monList; /* List of clients to inform if we */ - /* hear that the monitored host has */ - /* crashed, NULL if no longer monitored */ -} HostInfo; - - -/* Overall file layout. */ - -typedef struct -{ - int ourState; /* State number as defined in statd protocol */ - int noOfHosts; /* Number of elements in hosts[] */ - char reserved[248]; /* Reserved for future use */ - HostInfo hosts[1]; /* vector of monitored hosts */ -} FileLayout; - -#define HEADER_LEN (sizeof(FileLayout) - sizeof(HostInfo)) - -/* ------------------------------------------------------------------------- */ - -/* Global variables */ - -extern FileLayout *status_info; /* The mmap()ed status file */ - -extern int debug; /* =1 to enable diagnostics to syslog */ - -/* Function prototypes */ - -extern HostInfo *find_host(char * /*hostname*/, int /*create*/); -extern void init_file(char * /*filename*/); -extern void notify_hosts(void); -extern void sync_file(void); diff --git a/sbin/rpc.statd/test.c b/sbin/rpc.statd/test.c deleted file mode 100644 index e864485f6f48..000000000000 --- a/sbin/rpc.statd/test.c +++ /dev/null @@ -1,138 +0,0 @@ -#include -#include -#include - - -/* Default timeout can be changed using clnt_control() */ -static struct timeval TIMEOUT = { 25, 0 }; - -struct sm_stat_res * -sm_stat_1(argp, clnt) - struct sm_name *argp; - CLIENT *clnt; -{ - static struct sm_stat_res res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, SM_STAT, xdr_sm_name, argp, xdr_sm_stat_res, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return (&res); -} - - -struct sm_stat_res * -sm_mon_1(argp, clnt) - struct mon *argp; - CLIENT *clnt; -{ - static struct sm_stat_res res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, SM_MON, xdr_mon, argp, xdr_sm_stat_res, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return (&res); -} - - -struct sm_stat * -sm_unmon_1(argp, clnt) - struct mon_id *argp; - CLIENT *clnt; -{ - static struct sm_stat res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, SM_UNMON, xdr_mon_id, argp, xdr_sm_stat, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return (&res); -} - - -struct sm_stat * -sm_unmon_all_1(argp, clnt) - struct my_id *argp; - CLIENT *clnt; -{ - static struct sm_stat res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, SM_UNMON_ALL, xdr_my_id, argp, xdr_sm_stat, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return (&res); -} - - -void * -sm_simu_crash_1(argp, clnt) - void *argp; - CLIENT *clnt; -{ - static char res; - - bzero((char *)&res, sizeof(res)); - if (clnt_call(clnt, SM_SIMU_CRASH, xdr_void, argp, xdr_void, &res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); - } - return ((void *)&res); -} - - -int main(int argc, char **argv) -{ - CLIENT *cli; - char dummy; - void *out; - struct mon mon; - - if (argc < 2) - { - fprintf(stderr, "usage: test | crash\n"); - fprintf(stderr, "Always talks to statd at localhost\n"); - exit(1); - } - - printf("Creating client for localhost\n" ); - cli = clnt_create("localhost", SM_PROG, SM_VERS, "udp"); - if (!cli) - { - printf("Failed to create client\n"); - exit(1); - } - - mon.mon_id.mon_name = argv[1]; - mon.mon_id.my_id.my_name = argv[1]; - mon.mon_id.my_id.my_prog = SM_PROG; - mon.mon_id.my_id.my_vers = SM_VERS; - mon.mon_id.my_id.my_proc = 1; /* have it call sm_stat() !!! */ - - if (strcmp(argv[1], "crash")) - { - /* Hostname given */ - struct sm_stat_res *res; - if (res = sm_mon_1(&mon, cli)) - { - printf("Success!\n"); - } - else - { - printf("Fail\n"); - } - } - else - { - if (out = sm_simu_crash_1(&dummy, cli)) - { - printf("Success!\n"); - } - else - { - printf("Fail\n"); - } - } - - return 0; -}