1df57947fSPedro F. Giffuni /*-
2df57947fSPedro F. Giffuni * SPDX-License-Identifier: BSD-4-Clause
3df57947fSPedro F. Giffuni *
416118c2bSBill Paul * Copyright (c) 1995, 1996
516118c2bSBill Paul * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
616118c2bSBill Paul *
716118c2bSBill Paul * Redistribution and use in source and binary forms, with or without
816118c2bSBill Paul * modification, are permitted provided that the following conditions
916118c2bSBill Paul * are met:
1016118c2bSBill Paul * 1. Redistributions of source code must retain the above copyright
1116118c2bSBill Paul * notice, this list of conditions and the following disclaimer.
1216118c2bSBill Paul * 2. Redistributions in binary form must reproduce the above copyright
1316118c2bSBill Paul * notice, this list of conditions and the following disclaimer in the
1416118c2bSBill Paul * documentation and/or other materials provided with the distribution.
1516118c2bSBill Paul * 3. All advertising materials mentioning features or use of this software
1616118c2bSBill Paul * must display the following acknowledgement:
1716118c2bSBill Paul * This product includes software developed by Bill Paul.
1816118c2bSBill Paul * 4. Neither the name of the author nor the names of any co-contributors
1916118c2bSBill Paul * may be used to endorse or promote products derived from this software
2016118c2bSBill Paul * without specific prior written permission.
2116118c2bSBill Paul *
2216118c2bSBill Paul * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
2316118c2bSBill Paul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2416118c2bSBill Paul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2516118c2bSBill Paul * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
2616118c2bSBill Paul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2716118c2bSBill Paul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2816118c2bSBill Paul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2916118c2bSBill Paul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3016118c2bSBill Paul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3116118c2bSBill Paul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3216118c2bSBill Paul * SUCH DAMAGE.
3316118c2bSBill Paul */
3416118c2bSBill Paul
35b728350eSDavid E. O'Brien #include <sys/cdefs.h>
3616118c2bSBill Paul #include "ypxfrd.h"
371e96bb57SPhilippe Charnier #include <err.h>
381e96bb57SPhilippe Charnier #include <fcntl.h>
391a37aa56SDavid E. O'Brien #include <paths.h>
4016118c2bSBill Paul #include <stdio.h>
4116118c2bSBill Paul #include <stdlib.h> /* getenv, exit */
429136d119SPeter Wemm #include <unistd.h>
4316118c2bSBill Paul #include <rpc/pmap_clnt.h> /* for pmap_unset */
443ff0fa2aSStefan Farfeleder #include <rpc/rpc_com.h>
4516118c2bSBill Paul #include <string.h> /* strcmp */
4616118c2bSBill Paul #include <signal.h>
4716118c2bSBill Paul #include <sys/ttycom.h> /* TIOCNOTTY */
4816118c2bSBill Paul #ifdef __cplusplus
4916118c2bSBill Paul #include <sysent.h> /* getdtablesize, open */
5016118c2bSBill Paul #endif /* __cplusplus */
5116118c2bSBill Paul #include <memory.h>
5216118c2bSBill Paul #include <sys/socket.h>
5316118c2bSBill Paul #include <netinet/in.h>
5416118c2bSBill Paul #include <syslog.h>
5516118c2bSBill Paul #include "ypxfrd_extern.h"
5616118c2bSBill Paul #include <sys/wait.h>
5716118c2bSBill Paul #include <errno.h>
5816118c2bSBill Paul
5916118c2bSBill Paul #ifndef SIG_PF
6016118c2bSBill Paul #define SIG_PF void(*)(int)
6116118c2bSBill Paul #endif
6216118c2bSBill Paul
6316118c2bSBill Paul #ifdef DEBUG
6416118c2bSBill Paul #define RPC_SVC_FG
6516118c2bSBill Paul #endif
6616118c2bSBill Paul
6716118c2bSBill Paul #define _RPCSVC_CLOSEDOWN 120
6816118c2bSBill Paul int _rpcpmstart; /* Started by a port monitor ? */
6916118c2bSBill Paul static int _rpcfdtype;
7016118c2bSBill Paul /* Whether Stream or Datagram ? */
7116118c2bSBill Paul /* States a server can be in wrt request */
7216118c2bSBill Paul
7316118c2bSBill Paul #define _IDLE 0
7416118c2bSBill Paul #define _SERVED 1
7516118c2bSBill Paul #define _SERVING 2
7616118c2bSBill Paul
7716118c2bSBill Paul extern int _rpcsvcstate; /* Set when a request is serviced */
7816118c2bSBill Paul
79*3a166b33SKyle Evans int debug;
80*3a166b33SKyle Evans
8116118c2bSBill Paul char *progname = "rpc.ypxfrd";
8216118c2bSBill Paul char *yp_dir = "/var/yp/";
8316118c2bSBill Paul
84dc584ddbSDag-Erling Smørgrav static void
_msgout(char * msg)85dc584ddbSDag-Erling Smørgrav _msgout(char *msg)
8616118c2bSBill Paul {
8716118c2bSBill Paul #ifdef RPC_SVC_FG
8816118c2bSBill Paul if (_rpcpmstart)
89ed9ee320SKris Kennaway syslog(LOG_ERR, "%s", msg);
9016118c2bSBill Paul else
911e96bb57SPhilippe Charnier warnx("%s", msg);
9216118c2bSBill Paul #else
93ed9ee320SKris Kennaway syslog(LOG_ERR, "%s", msg);
9416118c2bSBill Paul #endif
9516118c2bSBill Paul }
9616118c2bSBill Paul
9716118c2bSBill Paul static void
closedown(int sig)9816118c2bSBill Paul closedown(int sig)
9916118c2bSBill Paul {
10016118c2bSBill Paul if (_rpcsvcstate == _IDLE) {
10116118c2bSBill Paul extern fd_set svc_fdset;
10216118c2bSBill Paul static int size;
10316118c2bSBill Paul int i, openfd;
10416118c2bSBill Paul
10516118c2bSBill Paul if (_rpcfdtype == SOCK_DGRAM)
10616118c2bSBill Paul exit(0);
10716118c2bSBill Paul if (size == 0) {
10816118c2bSBill Paul size = getdtablesize();
10916118c2bSBill Paul }
11016118c2bSBill Paul for (i = 0, openfd = 0; i < size && openfd < 2; i++)
11116118c2bSBill Paul if (FD_ISSET(i, &svc_fdset))
11216118c2bSBill Paul openfd++;
11316118c2bSBill Paul if (openfd <= 1)
11416118c2bSBill Paul exit(0);
11516118c2bSBill Paul }
11616118c2bSBill Paul if (_rpcsvcstate == _SERVED)
11716118c2bSBill Paul _rpcsvcstate = _IDLE;
11816118c2bSBill Paul
11916118c2bSBill Paul (void) signal(SIGALRM, (SIG_PF) closedown);
12016118c2bSBill Paul (void) alarm(_RPCSVC_CLOSEDOWN/2);
12116118c2bSBill Paul }
12216118c2bSBill Paul
12316118c2bSBill Paul
12416118c2bSBill Paul static void
ypxfrd_svc_run(void)125dc584ddbSDag-Erling Smørgrav ypxfrd_svc_run(void)
12616118c2bSBill Paul {
12716118c2bSBill Paul #ifdef FD_SETSIZE
12816118c2bSBill Paul fd_set readfds;
12916118c2bSBill Paul #else
13016118c2bSBill Paul int readfds;
13116118c2bSBill Paul #endif /* def FD_SETSIZE */
13216118c2bSBill Paul extern int forked;
13316118c2bSBill Paul int pid;
13416118c2bSBill Paul int fd_setsize = _rpc_dtablesize();
13516118c2bSBill Paul
13616118c2bSBill Paul /* Establish the identity of the parent ypserv process. */
13716118c2bSBill Paul pid = getpid();
13816118c2bSBill Paul
13916118c2bSBill Paul for (;;) {
14016118c2bSBill Paul #ifdef FD_SETSIZE
14116118c2bSBill Paul readfds = svc_fdset;
14216118c2bSBill Paul #else
14316118c2bSBill Paul readfds = svc_fds;
14416118c2bSBill Paul #endif /* def FD_SETSIZE */
14516118c2bSBill Paul switch (select(fd_setsize, &readfds, NULL, NULL,
14616118c2bSBill Paul (struct timeval *)0)) {
14716118c2bSBill Paul case -1:
14816118c2bSBill Paul if (errno == EINTR) {
14916118c2bSBill Paul continue;
15016118c2bSBill Paul }
1511e96bb57SPhilippe Charnier warn("svc_run: - select failed");
15216118c2bSBill Paul return;
15316118c2bSBill Paul case 0:
15416118c2bSBill Paul continue;
15516118c2bSBill Paul default:
15616118c2bSBill Paul svc_getreqset(&readfds);
15716118c2bSBill Paul if (forked && pid != getpid())
15816118c2bSBill Paul exit(0);
15916118c2bSBill Paul }
16016118c2bSBill Paul }
16116118c2bSBill Paul }
16216118c2bSBill Paul
reaper(int sig)163dc584ddbSDag-Erling Smørgrav static void reaper(int sig)
16416118c2bSBill Paul {
16516118c2bSBill Paul int status;
16602cd25bfSBill Paul int saved_errno;
16702cd25bfSBill Paul
16802cd25bfSBill Paul saved_errno = errno;
16916118c2bSBill Paul
17016118c2bSBill Paul if (sig == SIGHUP) {
17116118c2bSBill Paul load_securenets();
17202cd25bfSBill Paul errno = saved_errno;
17316118c2bSBill Paul return;
17416118c2bSBill Paul }
17516118c2bSBill Paul
17616118c2bSBill Paul if (sig == SIGCHLD) {
17716118c2bSBill Paul while (wait3(&status, WNOHANG, NULL) > 0)
17816118c2bSBill Paul children--;
17916118c2bSBill Paul } else {
18016118c2bSBill Paul (void) pmap_unset(YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS);
18116118c2bSBill Paul exit(0);
18216118c2bSBill Paul }
18302cd25bfSBill Paul
18402cd25bfSBill Paul errno = saved_errno;
18516118c2bSBill Paul }
18616118c2bSBill Paul
187dc584ddbSDag-Erling Smørgrav void
usage(void)188dc584ddbSDag-Erling Smørgrav usage(void)
18916118c2bSBill Paul {
1901e96bb57SPhilippe Charnier fprintf(stderr, "usage: rpc.ypxfrd [-p path]\n");
19116118c2bSBill Paul exit(0);
19216118c2bSBill Paul }
19316118c2bSBill Paul
1941e96bb57SPhilippe Charnier int
main(int argc,char * argv[])195dc584ddbSDag-Erling Smørgrav main(int argc, char *argv[])
19616118c2bSBill Paul {
1971e96bb57SPhilippe Charnier register SVCXPRT *transp = NULL;
19816118c2bSBill Paul int sock;
1991e96bb57SPhilippe Charnier int proto = 0;
20016118c2bSBill Paul struct sockaddr_in saddr;
20116118c2bSBill Paul int asize = sizeof (saddr);
20216118c2bSBill Paul int ch;
20316118c2bSBill Paul
2046c3f552aSWarner Losh while ((ch = getopt(argc, argv, "p:h")) != -1) {
20516118c2bSBill Paul switch (ch) {
20616118c2bSBill Paul case 'p':
20716118c2bSBill Paul yp_dir = optarg;
20816118c2bSBill Paul break;
20916118c2bSBill Paul default:
21016118c2bSBill Paul usage();
21116118c2bSBill Paul break;
21216118c2bSBill Paul }
21316118c2bSBill Paul }
21416118c2bSBill Paul
21516118c2bSBill Paul load_securenets();
21616118c2bSBill Paul
21716118c2bSBill Paul if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) {
21816118c2bSBill Paul int ssize = sizeof (int);
21916118c2bSBill Paul
22016118c2bSBill Paul if (saddr.sin_family != AF_INET)
22116118c2bSBill Paul exit(1);
22216118c2bSBill Paul if (getsockopt(0, SOL_SOCKET, SO_TYPE,
22316118c2bSBill Paul (char *)&_rpcfdtype, &ssize) == -1)
22416118c2bSBill Paul exit(1);
22516118c2bSBill Paul sock = 0;
22616118c2bSBill Paul _rpcpmstart = 1;
22716118c2bSBill Paul proto = 0;
22816118c2bSBill Paul openlog("rpc.ypxfrd", LOG_PID, LOG_DAEMON);
22916118c2bSBill Paul } else {
23016118c2bSBill Paul #ifndef RPC_SVC_FG
23116118c2bSBill Paul int size;
23216118c2bSBill Paul int pid, i;
23316118c2bSBill Paul
23416118c2bSBill Paul pid = fork();
2351e96bb57SPhilippe Charnier if (pid < 0)
2361e96bb57SPhilippe Charnier err(1, "fork");
23716118c2bSBill Paul if (pid)
23816118c2bSBill Paul exit(0);
23916118c2bSBill Paul size = getdtablesize();
24016118c2bSBill Paul for (i = 0; i < size; i++)
24116118c2bSBill Paul (void) close(i);
2421a37aa56SDavid E. O'Brien i = open(_PATH_CONSOLE, 2);
24316118c2bSBill Paul (void) dup2(i, 1);
24416118c2bSBill Paul (void) dup2(i, 2);
2451a37aa56SDavid E. O'Brien i = open(_PATH_TTY, 2);
24616118c2bSBill Paul if (i >= 0) {
24716118c2bSBill Paul (void) ioctl(i, TIOCNOTTY, (char *)NULL);
24816118c2bSBill Paul (void) close(i);
24916118c2bSBill Paul }
25016118c2bSBill Paul openlog("rpc.ypxfrd", LOG_PID, LOG_DAEMON);
25116118c2bSBill Paul #endif
25216118c2bSBill Paul sock = RPC_ANYSOCK;
25316118c2bSBill Paul (void) pmap_unset(YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS);
25416118c2bSBill Paul }
25516118c2bSBill Paul
25616118c2bSBill Paul if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) {
25716118c2bSBill Paul transp = svcudp_create(sock);
25816118c2bSBill Paul if (transp == NULL) {
25916118c2bSBill Paul _msgout("cannot create udp service.");
26016118c2bSBill Paul exit(1);
26116118c2bSBill Paul }
26216118c2bSBill Paul if (!_rpcpmstart)
26316118c2bSBill Paul proto = IPPROTO_UDP;
26416118c2bSBill Paul if (!svc_register(transp, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, ypxfrd_freebsd_prog_1, proto)) {
26516118c2bSBill Paul _msgout("unable to register (YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, udp).");
26616118c2bSBill Paul exit(1);
26716118c2bSBill Paul }
26816118c2bSBill Paul }
26916118c2bSBill Paul
27016118c2bSBill Paul if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) {
27116118c2bSBill Paul transp = svctcp_create(sock, 0, 0);
27216118c2bSBill Paul if (transp == NULL) {
27316118c2bSBill Paul _msgout("cannot create tcp service.");
27416118c2bSBill Paul exit(1);
27516118c2bSBill Paul }
27616118c2bSBill Paul if (!_rpcpmstart)
27716118c2bSBill Paul proto = IPPROTO_TCP;
27816118c2bSBill Paul if (!svc_register(transp, YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, ypxfrd_freebsd_prog_1, proto)) {
27916118c2bSBill Paul _msgout("unable to register (YPXFRD_FREEBSD_PROG, YPXFRD_FREEBSD_VERS, tcp).");
28016118c2bSBill Paul exit(1);
28116118c2bSBill Paul }
28216118c2bSBill Paul }
28316118c2bSBill Paul
28416118c2bSBill Paul if (transp == (SVCXPRT *)NULL) {
28516118c2bSBill Paul _msgout("could not create a handle");
28616118c2bSBill Paul exit(1);
28716118c2bSBill Paul }
28816118c2bSBill Paul if (_rpcpmstart) {
28916118c2bSBill Paul (void) signal(SIGALRM, (SIG_PF) closedown);
29016118c2bSBill Paul (void) alarm(_RPCSVC_CLOSEDOWN/2);
29116118c2bSBill Paul }
29216118c2bSBill Paul
29316118c2bSBill Paul (void) signal(SIGPIPE, SIG_IGN);
29416118c2bSBill Paul (void) signal(SIGCHLD, (SIG_PF) reaper);
29516118c2bSBill Paul (void) signal(SIGTERM, (SIG_PF) reaper);
29616118c2bSBill Paul (void) signal(SIGINT, (SIG_PF) reaper);
29716118c2bSBill Paul (void) signal(SIGHUP, (SIG_PF) reaper);
29816118c2bSBill Paul
29916118c2bSBill Paul ypxfrd_svc_run();
30016118c2bSBill Paul _msgout("svc_run returned");
30116118c2bSBill Paul exit(1);
30216118c2bSBill Paul /* NOTREACHED */
30316118c2bSBill Paul }
304