11494289fSPeter Wemm /* 21494289fSPeter Wemm * Copyright (c) 1995 31494289fSPeter Wemm * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved. 41494289fSPeter Wemm * 51494289fSPeter Wemm * Redistribution and use in source and binary forms, with or without 61494289fSPeter Wemm * modification, are permitted provided that the following conditions 71494289fSPeter Wemm * are met: 81494289fSPeter Wemm * 1. Redistributions of source code must retain the above copyright 91494289fSPeter Wemm * notice, this list of conditions and the following disclaimer. 101494289fSPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 111494289fSPeter Wemm * notice, this list of conditions and the following disclaimer in the 121494289fSPeter Wemm * documentation and/or other materials provided with the distribution. 131494289fSPeter Wemm * 3. All advertising materials mentioning features or use of this software 141494289fSPeter Wemm * must display the following acknowledgement: 151494289fSPeter Wemm * This product includes software developed for the FreeBSD project 161494289fSPeter Wemm * 4. Neither the name of the author nor the names of any co-contributors 171494289fSPeter Wemm * may be used to endorse or promote products derived from this software 181494289fSPeter Wemm * without specific prior written permission. 191494289fSPeter Wemm * 201494289fSPeter Wemm * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND 211494289fSPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221494289fSPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231494289fSPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 241494289fSPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251494289fSPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261494289fSPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271494289fSPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281494289fSPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291494289fSPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301494289fSPeter Wemm * SUCH DAMAGE. 311494289fSPeter Wemm * 321494289fSPeter Wemm */ 331494289fSPeter Wemm 341494289fSPeter Wemm /* main() function for status monitor daemon. Some of the code in this */ 351494289fSPeter Wemm /* file was generated by running rpcgen /usr/include/rpcsvc/sm_inter.x */ 361494289fSPeter Wemm /* The actual program logic is in the file procs.c */ 371494289fSPeter Wemm 381c38ed81SPhilippe Charnier #include <sys/cdefs.h> 391c38ed81SPhilippe Charnier __FBSDID("$FreeBSD$"); 401c38ed81SPhilippe Charnier 41df82e9baSPhilippe Charnier #include <err.h> 421494289fSPeter Wemm #include <stdio.h> 43df82e9baSPhilippe Charnier #include <stdlib.h> 441494289fSPeter Wemm #include <rpc/rpc.h> 45bcb53b16SMartin Blapp #include <rpc/rpc_com.h> 4696e33c21SAlfred Perlstein #include <string.h> 471494289fSPeter Wemm #include <syslog.h> 481494289fSPeter Wemm #include <sys/types.h> 491494289fSPeter Wemm #include <sys/wait.h> 501494289fSPeter Wemm #include <signal.h> 511c38ed81SPhilippe Charnier #include <unistd.h> 521494289fSPeter Wemm #include "statd.h" 531494289fSPeter Wemm 541494289fSPeter Wemm int debug = 0; /* Controls syslog() calls for debug messages */ 551494289fSPeter Wemm 56bf117edaSAlfred Perlstein static void handle_sigchld(int sig); 57bf117edaSAlfred Perlstein static void usage(void); 581494289fSPeter Wemm 5974e69f9eSMatteo Riondato const char *transports[] = { "udp", "tcp", "udp6", "tcp6" }; 6074e69f9eSMatteo Riondato 61df82e9baSPhilippe Charnier int 621494289fSPeter Wemm main(int argc, char **argv) 631494289fSPeter Wemm { 6474e69f9eSMatteo Riondato SVCXPRT *transp; 651494289fSPeter Wemm struct sigaction sa; 6674e69f9eSMatteo Riondato struct netconfig *nconf; 6774e69f9eSMatteo Riondato struct sockaddr_in sin; 6874e69f9eSMatteo Riondato struct sockaddr_in6 sin6; 6974e69f9eSMatteo Riondato int ch, i, maxindex, r, s, sock; 7074e69f9eSMatteo Riondato char *endptr; 71bcb53b16SMartin Blapp int maxrec = RPC_MAXDATASIZE; 7274e69f9eSMatteo Riondato in_port_t svcport = 0; 731494289fSPeter Wemm 7474e69f9eSMatteo Riondato while ((ch = getopt(argc, argv, "dp:")) != -1) 751c38ed81SPhilippe Charnier switch (ch) { 761c38ed81SPhilippe Charnier case 'd': 771494289fSPeter Wemm debug = 1; 781c38ed81SPhilippe Charnier break; 7974e69f9eSMatteo Riondato case 'p': 8074e69f9eSMatteo Riondato endptr = NULL; 8174e69f9eSMatteo Riondato svcport = (in_port_t)strtoul(optarg, &endptr, 10); 8274e69f9eSMatteo Riondato if (endptr == NULL || *endptr != '\0' || svcport == 0 || 8374e69f9eSMatteo Riondato svcport >= IPPORT_MAX) 8474e69f9eSMatteo Riondato usage(); 8574e69f9eSMatteo Riondato break; 861c38ed81SPhilippe Charnier default: 871c38ed81SPhilippe Charnier usage(); 881494289fSPeter Wemm } 891c38ed81SPhilippe Charnier argc -= optind; 901c38ed81SPhilippe Charnier argv += optind; 911494289fSPeter Wemm 92af37179bSAlfred Perlstein (void)rpcb_unset(SM_PROG, SM_VERS, NULL); 931494289fSPeter Wemm 9474e69f9eSMatteo Riondato /* 9574e69f9eSMatteo Riondato * Check if IPv6 support is present. 9674e69f9eSMatteo Riondato */ 9774e69f9eSMatteo Riondato s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); 9874e69f9eSMatteo Riondato if (s < 0) 9974e69f9eSMatteo Riondato maxindex = 2; 10074e69f9eSMatteo Riondato else { 10174e69f9eSMatteo Riondato close(s); 10274e69f9eSMatteo Riondato maxindex = 4; 10374e69f9eSMatteo Riondato } 10474e69f9eSMatteo Riondato 10574e69f9eSMatteo Riondato if (svcport != 0) { 10674e69f9eSMatteo Riondato bzero(&sin, sizeof(struct sockaddr_in)); 10774e69f9eSMatteo Riondato sin.sin_len = sizeof(struct sockaddr_in); 10874e69f9eSMatteo Riondato sin.sin_family = AF_INET; 10974e69f9eSMatteo Riondato sin.sin_port = htons(svcport); 11074e69f9eSMatteo Riondato 11174e69f9eSMatteo Riondato bzero(&sin6, sizeof(struct sockaddr_in6)); 11274e69f9eSMatteo Riondato sin6.sin6_len = sizeof(struct sockaddr_in6); 11374e69f9eSMatteo Riondato sin6.sin6_family = AF_INET6; 11474e69f9eSMatteo Riondato sin6.sin6_port = htons(svcport); 11574e69f9eSMatteo Riondato } 11674e69f9eSMatteo Riondato 117bcb53b16SMartin Blapp rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec); 118bcb53b16SMartin Blapp 11974e69f9eSMatteo Riondato for (i = 0; i < maxindex; i++) { 12074e69f9eSMatteo Riondato nconf = getnetconfigent(transports[i]); 12174e69f9eSMatteo Riondato if (nconf == NULL) 12274e69f9eSMatteo Riondato errx(1, "cannot get %s netconf: %s.", transports[i], 12374e69f9eSMatteo Riondato nc_sperror()); 12474e69f9eSMatteo Riondato 12574e69f9eSMatteo Riondato if (svcport != 0) { 12674e69f9eSMatteo Riondato if (strcmp(nconf->nc_netid, "udp6") == 0) { 12774e69f9eSMatteo Riondato sock = socket(AF_INET6, SOCK_DGRAM, 12874e69f9eSMatteo Riondato IPPROTO_UDP); 12974e69f9eSMatteo Riondato if (sock != -1) { 13074e69f9eSMatteo Riondato r = bindresvport_sa(sock, 13174e69f9eSMatteo Riondato (struct sockaddr *)&sin6); 13274e69f9eSMatteo Riondato if (r != 0) { 13374e69f9eSMatteo Riondato syslog(LOG_ERR, "bindresvport: %m"); 13474e69f9eSMatteo Riondato exit(1); 13574e69f9eSMatteo Riondato } 13674e69f9eSMatteo Riondato } 13774e69f9eSMatteo Riondato } else if (strcmp(nconf->nc_netid, "udp") == 0) { 13874e69f9eSMatteo Riondato sock = socket(AF_INET, SOCK_DGRAM, 13974e69f9eSMatteo Riondato IPPROTO_UDP); 14074e69f9eSMatteo Riondato if (sock != -1) { 14174e69f9eSMatteo Riondato r = bindresvport(sock, &sin); 14274e69f9eSMatteo Riondato if (r != 0) { 14374e69f9eSMatteo Riondato syslog(LOG_ERR, "bindresvport: %m"); 14474e69f9eSMatteo Riondato exit(1); 14574e69f9eSMatteo Riondato } 14674e69f9eSMatteo Riondato } 14774e69f9eSMatteo Riondato } else if (strcmp(nconf->nc_netid, "tcp6") == 0) { 14874e69f9eSMatteo Riondato sock = socket(AF_INET6, SOCK_STREAM, 14974e69f9eSMatteo Riondato IPPROTO_TCP); 15074e69f9eSMatteo Riondato if (sock != -1) { 15174e69f9eSMatteo Riondato r = bindresvport_sa(sock, 15274e69f9eSMatteo Riondato (struct sockaddr *)&sin6); 15374e69f9eSMatteo Riondato if (r != 0) { 15474e69f9eSMatteo Riondato syslog(LOG_ERR, "bindresvport: %m"); 15574e69f9eSMatteo Riondato exit(1); 15674e69f9eSMatteo Riondato } 15774e69f9eSMatteo Riondato } 15874e69f9eSMatteo Riondato } else if (strcmp(nconf->nc_netid, "tcp") == 0) { 15974e69f9eSMatteo Riondato sock = socket(AF_INET, SOCK_STREAM, 16074e69f9eSMatteo Riondato IPPROTO_TCP); 16174e69f9eSMatteo Riondato if (sock != -1) { 16274e69f9eSMatteo Riondato r = bindresvport(sock, &sin); 16374e69f9eSMatteo Riondato if (r != 0) { 16474e69f9eSMatteo Riondato syslog(LOG_ERR, "bindresvport: %m"); 16574e69f9eSMatteo Riondato exit(1); 16674e69f9eSMatteo Riondato } 16774e69f9eSMatteo Riondato } 16874e69f9eSMatteo Riondato } 16974e69f9eSMatteo Riondato 17074e69f9eSMatteo Riondato transp = svc_tli_create(sock, nconf, NULL, 17174e69f9eSMatteo Riondato RPC_MAXDATASIZE, RPC_MAXDATASIZE); 17274e69f9eSMatteo Riondato } else { 17374e69f9eSMatteo Riondato transp = svc_tli_create(RPC_ANYFD, nconf, NULL, 17474e69f9eSMatteo Riondato RPC_MAXDATASIZE, RPC_MAXDATASIZE); 17574e69f9eSMatteo Riondato } 17674e69f9eSMatteo Riondato 17774e69f9eSMatteo Riondato if (transp == NULL) { 17874e69f9eSMatteo Riondato errx(1, "cannot create %s service.", transports[i]); 17974e69f9eSMatteo Riondato /* NOTREACHED */ 18074e69f9eSMatteo Riondato } 18174e69f9eSMatteo Riondato if (!svc_reg(transp, SM_PROG, SM_VERS, sm_prog_1, nconf)) { 18274e69f9eSMatteo Riondato errx(1, "unable to register (SM_PROG, NLM_SM, %s)", 18374e69f9eSMatteo Riondato transports[i]); 18474e69f9eSMatteo Riondato /* NOTREACHED */ 18574e69f9eSMatteo Riondato } 18674e69f9eSMatteo Riondato freenetconfigent(nconf); 18774e69f9eSMatteo Riondato } 188f61a23adSDon Lewis init_file("/var/db/statd.status"); 1891494289fSPeter Wemm 1901494289fSPeter Wemm /* Note that it is NOT sensible to run this program from inetd - the */ 1911494289fSPeter Wemm /* protocol assumes that it will run immediately at boot time. */ 1921494289fSPeter Wemm daemon(0, 0); 1931494289fSPeter Wemm openlog("rpc.statd", 0, LOG_DAEMON); 1941494289fSPeter Wemm if (debug) syslog(LOG_INFO, "Starting - debug enabled"); 1951494289fSPeter Wemm else syslog(LOG_INFO, "Starting"); 1961494289fSPeter Wemm 1971494289fSPeter Wemm /* Install signal handler to collect exit status of child processes */ 1981494289fSPeter Wemm sa.sa_handler = handle_sigchld; 1991494289fSPeter Wemm sigemptyset(&sa.sa_mask); 2001494289fSPeter Wemm sigaddset(&sa.sa_mask, SIGCHLD); 2011494289fSPeter Wemm sa.sa_flags = SA_RESTART; 2021494289fSPeter Wemm sigaction(SIGCHLD, &sa, NULL); 2031494289fSPeter Wemm 2041494289fSPeter Wemm /* Initialisation now complete - start operating */ 2051494289fSPeter Wemm notify_hosts(); /* Forks a process (if necessary) to do the */ 2061494289fSPeter Wemm /* SM_NOTIFY calls, which may be slow. */ 2071494289fSPeter Wemm 2081494289fSPeter Wemm svc_run(); /* Should never return */ 2091494289fSPeter Wemm exit(1); 2101494289fSPeter Wemm } 2111494289fSPeter Wemm 212df82e9baSPhilippe Charnier static void 213df82e9baSPhilippe Charnier usage() 214df82e9baSPhilippe Charnier { 21574e69f9eSMatteo Riondato fprintf(stderr, "usage: rpc.statd [-d] [-p <port>]\n"); 216df82e9baSPhilippe Charnier exit(1); 217df82e9baSPhilippe Charnier } 2181494289fSPeter Wemm 2191494289fSPeter Wemm /* handle_sigchld ---------------------------------------------------------- */ 2201494289fSPeter Wemm /* 2211494289fSPeter Wemm Purpose: Catch SIGCHLD and collect process status 2221494289fSPeter Wemm Retruns: Nothing. 2231494289fSPeter Wemm Notes: No special action required, other than to collect the 2241494289fSPeter Wemm process status and hence allow the child to die: 2251494289fSPeter Wemm we only use child processes for asynchronous transmission 2261494289fSPeter Wemm of SM_NOTIFY to other systems, so it is normal for the 2271494289fSPeter Wemm children to exit when they have done their work. 2281494289fSPeter Wemm */ 2291494289fSPeter Wemm 230bf117edaSAlfred Perlstein static void handle_sigchld(int sig __unused) 2311494289fSPeter Wemm { 2321494289fSPeter Wemm int pid, status; 2331494289fSPeter Wemm pid = wait4(-1, &status, WNOHANG, (struct rusage*)0); 2341494289fSPeter Wemm if (!pid) syslog(LOG_ERR, "Phantom SIGCHLD??"); 2351494289fSPeter Wemm else if (status == 0) 2361494289fSPeter Wemm { 2371494289fSPeter Wemm if (debug) syslog(LOG_DEBUG, "Child %d exited OK", pid); 2381494289fSPeter Wemm } 2391494289fSPeter Wemm else syslog(LOG_ERR, "Child %d failed with status %d", pid, 2401494289fSPeter Wemm WEXITSTATUS(status)); 2411494289fSPeter Wemm } 2421494289fSPeter Wemm 243