#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
void handle_sig_cleanup(int);
void sigalarm_handler(void);
+void my_svc_run(void);
const char *transports[] = { "udp", "tcp", "udp6", "tcp6" };
int ch;
struct sigaction sigalarm;
int grace_period = 30;
+ struct rlimit rlp;
+ int mib[6];
+ int oldstate;
+ int oldsize;
+ int newstate;
- while ((ch = getopt(argc, argv, "d:g:w")) != (-1)) {
+ while ((ch = getopt(argc, argv, "d:g:wx:")) != (-1)) {
switch (ch) {
case 'd':
debug_level = atoi(optarg);
case 'w':
waitkern = 1;
break;
+ case 'x':
+ host_expire = atoi(optarg);
+ break;
default:
case '?':
usage();
* Note that it is NOT sensible to run this program from inetd - the
* protocol assumes that it will run immediately at boot time.
*/
- if (debug_level != 99 && daemon(0, 0)) {
+ if (debug_level != 99 && daemon(0, debug_level > 0)) {
err(1, "cannot fork");
/* NOTREACHED */
}
signal(SIGHUP, handle_sig_cleanup);
signal(SIGQUIT, handle_sig_cleanup);
- if (claim_pid_file("/var/run/lockd.pid", 0) < 0)
- errx(1, "cannot claim pid file");
+
+
+ openlog("rpc.lockd", debug_level == 99 ? LOG_PERROR : 0, LOG_DAEMON);
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROCDELAYTERM;
+
+ oldstate = 0;
+ oldsize = 4;
+ newstate = 1;
+
+ if (sysctl(mib, 2, &oldstate, &oldsize, &newstate, 4) < 0) {
+ syslog(LOG_INFO, "cannot mark pid for delayed termination");
+ }
+
+ if (claim_pid_file("/var/run/lockd.pid", 0) < 0) {
+ syslog(LOG_ERR, "cannot claim pid file");
+ exit(1);
+ }
if (waitkern) {
struct timespec ts;
nanosleep(&ts, NULL);
}
- openlog("rpc.lockd", 0, LOG_DAEMON);
if (debug_level)
syslog(LOG_INFO, "Starting, debug level %d", debug_level);
else
(void)pmap_unset(NLM_PROG, NLM_VERS4);
transp = svcudp_create(RPC_ANYSOCK);
- if (transp == NULL)
- errx(1, "cannot create udp service");
- if (!svc_register(transp, NLM_PROG, NLM_VERS, nlm_prog_1, IPPROTO_UDP))
- errx(1, "unable to register (NLM_PROG, NLM_VERS, udp)");
- if (!svc_register(transp, NLM_PROG, NLM_VERSX, nlm_prog_3, IPPROTO_UDP))
- errx(1, "unable to register (NLM_PROG, NLM_VERSX, udp)");
- if (!svc_register(transp, NLM_PROG, NLM_VERS4, nlm_prog_4, IPPROTO_UDP))
- errx(1, "unable to register (NLM_PROG, NLM_VERS4, udp)");
+ if (transp == NULL) {
+ syslog(LOG_ERR, "cannot create udp service");
+ exit(1);
+ }
+ if (!svc_register(transp, NLM_PROG, NLM_SM, nlm_prog_0, IPPROTO_UDP)) {
+ syslog(LOG_ERR, "unable to register (NLM_PROG, NLM_SM, udp)");
+ exit(1);
+ }
+ if (!svc_register(transp, NLM_PROG, NLM_VERS, nlm_prog_1, IPPROTO_UDP)) {
+ syslog(LOG_ERR, "unable to register (NLM_PROG, NLM_VERS, udp)");
+ exit(1);
+ }
+ if (!svc_register(transp, NLM_PROG, NLM_VERSX, nlm_prog_3, IPPROTO_UDP)) {
+ syslog(LOG_ERR, "unable to register (NLM_PROG, NLM_VERSX, udp)");
+ exit(1);
+ }
+ if (!svc_register(transp, NLM_PROG, NLM_VERS4, nlm_prog_4, IPPROTO_UDP)) {
+ syslog(LOG_ERR, "unable to register (NLM_PROG, NLM_VERS4, udp)");
+ exit(1);
+ }
transp = svctcp_create(RPC_ANYSOCK, 0, 0);
- if (transp == NULL)
- errx(1, "cannot create tcp service");
- if (!svc_register(transp, NLM_PROG, NLM_VERS, nlm_prog_1, IPPROTO_TCP))
- errx(1, "unable to register (NLM_PROG, NLM_VERS, tcp)");
- if (!svc_register(transp, NLM_PROG, NLM_VERSX, nlm_prog_3, IPPROTO_TCP))
- errx(1, "unable to register (NLM_PROG, NLM_VERSX, tcp)");
- if (!svc_register(transp, NLM_PROG, NLM_VERS4, nlm_prog_4, IPPROTO_TCP))
- errx(1, "unable to register (NLM_PROG, NLM_VERS4, tcp)");
+ if (transp == NULL) {
+ syslog(LOG_ERR, "cannot create tcp service");
+ exit(1);
+ }
+ if (!svc_register(transp, NLM_PROG, NLM_SM, nlm_prog_0, IPPROTO_TCP)) {
+ syslog(LOG_ERR, "unable to register (NLM_PROG, NLM_SM, tcp)");
+ exit(1);
+ }
+ if (!svc_register(transp, NLM_PROG, NLM_VERS, nlm_prog_1, IPPROTO_TCP)) {
+ syslog(LOG_ERR, "unable to register (NLM_PROG, NLM_VERS, tcp)");
+ exit(1);
+ }
+ if (!svc_register(transp, NLM_PROG, NLM_VERSX, nlm_prog_3, IPPROTO_TCP)) {
+ syslog(LOG_ERR, "unable to register (NLM_PROG, NLM_VERSX, tcp)");
+ exit(1);
+ }
+ if (!svc_register(transp, NLM_PROG, NLM_VERS4, nlm_prog_4, IPPROTO_TCP)) {
+ syslog(LOG_ERR, "unable to register (NLM_PROG, NLM_VERS4, tcp)");
+ exit(1);
+ }
sigalarm.sa_handler = (sig_t) sigalarm_handler;
sigemptyset(&sigalarm.sa_mask);
client_pid = client_request();
- svc_run(); /* Should never return */
+ /* raise our resource limits as far as they can go */
+ if (getrlimit(RLIMIT_NOFILE, &rlp)) {
+ syslog(LOG_WARNING, "getrlimit(RLIMIT_NOFILE) failed: %s",
+ strerror(errno));
+ } else {
+ rlp.rlim_cur = rlp.rlim_max;
+ if (setrlimit(RLIMIT_NOFILE, &rlp)) {
+ syslog(LOG_WARNING, "setrlimit(RLIMIT_NOFILE) failed: %s",
+ strerror(errno));
+ }
+ }
+
+ my_svc_run(); /* Should never return */
exit(1);
}
void
usage()
{
- errx(1, "usage: rpc.lockd [-d <debuglevel>] [-g <grace period>] [-w]");
+ errx(1, "usage: rpc.lockd [-d <debuglevel>] [-g <grace period>] "
+ " [-x <statd cache timeout>] [-w]");
}
/*
ret = callrpc("localhost", SM_PROG, SM_VERS, SM_UNMON_ALL,
xdr_my_id, &id, xdr_sm_stat, &stat);
if (ret) {
- warnx("%lu %s", SM_PROG, clnt_sperrno(ret));
+ syslog(LOG_WARNING, "%lu %s", SM_PROG, clnt_sperrno(ret));
if (++attempt < 20) {
sleep(attempt);
continue;
} while (1);
if (ret != 0) {
- errx(1, "%lu %s", SM_PROG, clnt_sperrno(ret));
+ syslog(LOG_ERR, "%lu %s", SM_PROG, clnt_sperrno(ret));
+ exit(1);
}
nsm_state = stat.state;
exit(1);
}
+void
+my_svc_run(void)
+{
+ fd_set readfds;
+ struct timeval timeout;
+ struct timeval now;
+ int error;
+ int hashosts = 0;
+ int tsize = 0;
+ struct timeval *top;
+
+
+ for( ;; ) {
+ timeout.tv_sec = host_expire + 1;
+ timeout.tv_usec = 0;
+
+ tsize = getdtablesize();
+ bcopy(&svc_fdset, &readfds, sizeof(svc_fdset));
+ /*
+ * If there are any expired hosts then sleep with a
+ * timeout to expire them.
+ */
+ if (hashosts && (timeout.tv_sec >= 0))
+ top = &timeout;
+ else
+ top = NULL;
+ error = select(tsize, &readfds, NULL, NULL, top);
+ if (error == -1) {
+ if (errno == EINTR)
+ continue;
+ perror("rpc.lockd: my_svc_run: select failed");
+ return;
+ }
+ gettimeofday(&now, NULL);
+ currsec = now.tv_sec;
+ if (error > 0)
+ svc_getreqset(&readfds);
+ if (debug_level > 3 && error == 0)
+ fprintf(stderr, "my_svc_run: select timeout\n");
+ hashosts = expire_lock_hosts();
+ }
+}