xref: /openbsd-src/libexec/rpc.rstatd/rstatd.c (revision 5b133f3f277e80f096764111e64f3a1284acb179)
1*5b133f3fSguenther /*	$OpenBSD: rstatd.c,v 1.31 2023/03/08 04:43:05 guenther Exp $	*/
25d36dfa4Sniklas 
3df930be7Sderaadt /*-
4df930be7Sderaadt  * Copyright (c) 1993, John Brezak
5df930be7Sderaadt  * All rights reserved.
6df930be7Sderaadt  *
7df930be7Sderaadt  * Redistribution and use in source and binary forms, with or without
8df930be7Sderaadt  * modification, are permitted provided that the following conditions
9df930be7Sderaadt  * are met:
10df930be7Sderaadt  * 1. Redistributions of source code must retain the above copyright
11df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer.
12df930be7Sderaadt  * 2. Redistributions in binary form must reproduce the above copyright
13df930be7Sderaadt  *    notice, this list of conditions and the following disclaimer in the
14df930be7Sderaadt  *    documentation and/or other materials provided with the distribution.
1576d2b7a4Sderaadt  * 3. The name of the author may not be used to endorse or promote products
1676d2b7a4Sderaadt  *    derived from this software without specific prior written permission.
17df930be7Sderaadt  *
18df930be7Sderaadt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19df930be7Sderaadt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20df930be7Sderaadt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21df930be7Sderaadt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22df930be7Sderaadt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23df930be7Sderaadt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24df930be7Sderaadt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25df930be7Sderaadt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26df930be7Sderaadt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27df930be7Sderaadt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28df930be7Sderaadt  * SUCH DAMAGE.
29df930be7Sderaadt  */
30df930be7Sderaadt 
31a5553e71Sderaadt #include <sys/types.h>
32a5553e71Sderaadt #include <sys/socket.h>
33df930be7Sderaadt #include <stdio.h>
34bad7586eSderaadt #include <stdlib.h>
35718e4ab6Sderaadt #include <string.h>
36bad7586eSderaadt #include <unistd.h>
37a47b6461Sderaadt #include <limits.h>
38df930be7Sderaadt #include <signal.h>
397f04c10bSderaadt #include <pwd.h>
40df930be7Sderaadt #include <syslog.h>
41bad7586eSderaadt #include <errno.h>
42bad7586eSderaadt #include <rpc/rpc.h>
43df930be7Sderaadt #include <rpcsvc/rstat.h>
44df930be7Sderaadt 
45bad7586eSderaadt extern void rstat_service(struct svc_req *, SVCXPRT *);
46bad7586eSderaadt 
47bad7586eSderaadt void my_svc_run(void);
48df930be7Sderaadt 
49df930be7Sderaadt int from_inetd = 1;	/* started from inetd ? */
50df930be7Sderaadt int closedown = 20;	/* how long to wait before going dormant */
51df930be7Sderaadt 
527f04c10bSderaadt volatile sig_atomic_t gotsig;
537f04c10bSderaadt 
54aa31cba2Sderaadt static void
getsig(int signo)557f04c10bSderaadt getsig(int signo)
567f04c10bSderaadt {
577f04c10bSderaadt 	gotsig = 1;
587f04c10bSderaadt }
597f04c10bSderaadt 
607f04c10bSderaadt 
61a5553e71Sderaadt int
main(int argc,char * argv[])627f04c10bSderaadt main(int argc, char *argv[])
63df930be7Sderaadt {
6471fc4cb2Sderaadt 	int sock = 0, proto = 0;
6571fc4cb2Sderaadt 	socklen_t fromlen;
667f04c10bSderaadt 	struct passwd *pw;
6755342a86Sbrad 	struct sockaddr_storage from;
68bad7586eSderaadt 	SVCXPRT *transp;
69df930be7Sderaadt 
70b1afbf54Sderaadt 	openlog("rpc.rstatd", LOG_NDELAY|LOG_CONS|LOG_PID, LOG_DAEMON);
71b1afbf54Sderaadt 
72ac4529faSthib 	if ((pw = getpwnam("_rstatd")) == NULL) {
73ac4529faSthib 		syslog(LOG_ERR, "no such user _rstatd");
74ac4529faSthib 		exit(1);
75ac4529faSthib 	}
767f04c10bSderaadt 	if (chroot("/var/empty") == -1) {
777f04c10bSderaadt 		syslog(LOG_ERR, "cannot chdir to /var/empty.");
787f04c10bSderaadt 		exit(1);
797f04c10bSderaadt 	}
807f04c10bSderaadt 	chdir("/");
817f04c10bSderaadt 
827f04c10bSderaadt 	setgroups(1, &pw->pw_gid);
837f04c10bSderaadt 	setegid(pw->pw_gid);
847f04c10bSderaadt 	setgid(pw->pw_gid);
857f04c10bSderaadt 	seteuid(pw->pw_uid);
86af7bf410Sderaadt 	setuid(pw->pw_uid);
877f04c10bSderaadt 
88df930be7Sderaadt 	if (argc == 2)
89a47b6461Sderaadt 		closedown = strtonum(argv[1], 1, INT_MAX, NULL);
90a47b6461Sderaadt 	if (closedown == 0)
91df930be7Sderaadt 		closedown = 20;
92df930be7Sderaadt 
93df930be7Sderaadt 	/*
94df930be7Sderaadt 	 * See if inetd started us
95df930be7Sderaadt 	 */
96df930be7Sderaadt 	fromlen = sizeof(from);
97df69c215Sderaadt 	if (getsockname(0, (struct sockaddr *)&from, &fromlen) == -1) {
98df930be7Sderaadt 		from_inetd = 0;
99df930be7Sderaadt 		sock = RPC_ANYSOCK;
100df930be7Sderaadt 		proto = IPPROTO_UDP;
101df930be7Sderaadt 	}
102df930be7Sderaadt 
103df930be7Sderaadt 	if (!from_inetd) {
104df930be7Sderaadt 		daemon(0, 0);
105df930be7Sderaadt 
106df930be7Sderaadt 		(void)pmap_unset(RSTATPROG, RSTATVERS_TIME);
107df930be7Sderaadt 		(void)pmap_unset(RSTATPROG, RSTATVERS_SWTCH);
108df930be7Sderaadt 		(void)pmap_unset(RSTATPROG, RSTATVERS_ORIG);
109df930be7Sderaadt 
1107f04c10bSderaadt 		(void) signal(SIGINT, getsig);
1117f04c10bSderaadt 		(void) signal(SIGTERM, getsig);
1127f04c10bSderaadt 		(void) signal(SIGHUP, getsig);
113df930be7Sderaadt 	}
114df930be7Sderaadt 
115df930be7Sderaadt 	transp = svcudp_create(sock);
116df930be7Sderaadt 	if (transp == NULL) {
117df930be7Sderaadt 		syslog(LOG_ERR, "cannot create udp service.");
118df930be7Sderaadt 		exit(1);
119df930be7Sderaadt 	}
120df930be7Sderaadt 	if (!svc_register(transp, RSTATPROG, RSTATVERS_TIME, rstat_service, proto)) {
121df930be7Sderaadt 		syslog(LOG_ERR, "unable to register (RSTATPROG, RSTATVERS_TIME, udp).");
122df930be7Sderaadt 		exit(1);
123df930be7Sderaadt 	}
124df930be7Sderaadt 	if (!svc_register(transp, RSTATPROG, RSTATVERS_SWTCH, rstat_service, proto)) {
125df930be7Sderaadt 		syslog(LOG_ERR, "unable to register (RSTATPROG, RSTATVERS_SWTCH, udp).");
126df930be7Sderaadt 		exit(1);
127df930be7Sderaadt 	}
128df930be7Sderaadt 	if (!svc_register(transp, RSTATPROG, RSTATVERS_ORIG, rstat_service, proto)) {
129df930be7Sderaadt 		syslog(LOG_ERR, "unable to register (RSTATPROG, RSTATVERS_ORIG, udp).");
130df930be7Sderaadt 		exit(1);
131df930be7Sderaadt 	}
132df930be7Sderaadt 
133bad7586eSderaadt 	my_svc_run();
134df930be7Sderaadt 	syslog(LOG_ERR, "svc_run returned");
135df930be7Sderaadt 	exit(1);
136df930be7Sderaadt }
137bad7586eSderaadt 
138bad7586eSderaadt void
my_svc_run(void)1397f04c10bSderaadt my_svc_run(void)
140bad7586eSderaadt {
141bad7586eSderaadt 	extern volatile sig_atomic_t wantupdatestat;
142bad7586eSderaadt 	extern void updatestat(void);
143fcc5cfe8Sderaadt 	struct pollfd *pfd = NULL, *newp;
144fcc5cfe8Sderaadt 	int nready, saved_max_pollfd = 0;
145bad7586eSderaadt 
146bad7586eSderaadt 	for (;;) {
147bad7586eSderaadt 		if (wantupdatestat) {
148bad7586eSderaadt 			wantupdatestat = 0;
149458e279fSotto 			updatestat();
150bad7586eSderaadt 		}
151924fb87eSmillert 		if (gotsig) {
152924fb87eSmillert 			(void) pmap_unset(RSTATPROG, RSTATVERS_TIME);
153924fb87eSmillert 			(void) pmap_unset(RSTATPROG, RSTATVERS_SWTCH);
154924fb87eSmillert 			(void) pmap_unset(RSTATPROG, RSTATVERS_ORIG);
155924fb87eSmillert 			exit(0);
156924fb87eSmillert 		}
157fcc5cfe8Sderaadt 		if (svc_max_pollfd > saved_max_pollfd) {
1586e690932Sderaadt 			newp = reallocarray(pfd, svc_max_pollfd, sizeof(*pfd));
159fcc5cfe8Sderaadt 			if (newp == NULL) {
160fcc5cfe8Sderaadt 				free(pfd);
161fcc5cfe8Sderaadt 				perror("svc_run: - realloc failed");
162fcc5cfe8Sderaadt 				return;
163bad7586eSderaadt 			}
164fcc5cfe8Sderaadt 			pfd = newp;
165fcc5cfe8Sderaadt 			saved_max_pollfd = svc_max_pollfd;
166fcc5cfe8Sderaadt 		}
1676e690932Sderaadt 		memcpy(pfd, svc_pollfd, svc_max_pollfd * sizeof(*pfd));
168fcc5cfe8Sderaadt 
169fcc5cfe8Sderaadt 		nready = poll(pfd, svc_max_pollfd, INFTIM);
170fcc5cfe8Sderaadt 		switch (nready) {
171fcc5cfe8Sderaadt 		case -1:
172fcc5cfe8Sderaadt 			if (errno == EINTR)
173fcc5cfe8Sderaadt 				continue;
174fcc5cfe8Sderaadt 			perror("svc_run: - poll failed");
175fcc5cfe8Sderaadt 			free(pfd);
176bad7586eSderaadt 			return;
177bad7586eSderaadt 		case 0:
178bad7586eSderaadt 			continue;
179bad7586eSderaadt 		default:
180fcc5cfe8Sderaadt 			svc_getreq_poll(pfd, nready);
181bad7586eSderaadt 		}
182bad7586eSderaadt 	}
183bad7586eSderaadt }
184