yp_main.c revision 143415
1116742Ssam/* 2116904Ssam * Copyright (c) 1995 3139530Ssam * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved. 4116742Ssam * 5116742Ssam * Redistribution and use in source and binary forms, with or without 6116742Ssam * modification, are permitted provided that the following conditions 7116742Ssam * are met: 8116742Ssam * 1. Redistributions of source code must retain the above copyright 9116742Ssam * notice, this list of conditions and the following disclaimer. 10116904Ssam * 2. Redistributions in binary form must reproduce the above copyright 11116904Ssam * notice, this list of conditions and the following disclaimer in the 12116904Ssam * documentation and/or other materials provided with the distribution. 13116904Ssam * 3. All advertising materials mentioning features or use of this software 14116904Ssam * must display the following acknowledgement: 15116904Ssam * This product includes software developed by Bill Paul. 16116742Ssam * 4. Neither the name of the author nor the names of any co-contributors 17116742Ssam * may be used to endorse or promote products derived from this software 18116742Ssam * without specific prior written permission. 19116742Ssam * 20116742Ssam * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 21116904Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22116904Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23116904Ssam * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE 24116904Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25116904Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26116904Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27116904Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28116904Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29116904Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30116904Ssam * SUCH DAMAGE. 31116742Ssam */ 32116742Ssam 33116742Ssam#include <sys/cdefs.h> 34116742Ssam__FBSDID("$FreeBSD: head/usr.sbin/ypserv/yp_main.c 143415 2005-03-11 14:17:12Z stefanf $"); 35116742Ssam 36116742Ssam/* 37116742Ssam * ypserv startup function. 38116742Ssam * We need out own main() since we have to do some additional work 39116742Ssam * that rpcgen won't do for us. Most of this file was generated using 40116742Ssam * rpcgen.new, and later modified. 41138568Ssam */ 42116742Ssam 43116742Ssam#include "yp.h" 44116742Ssam#include <err.h> 45116742Ssam#include <errno.h> 46116742Ssam#include <memory.h> 47116742Ssam#include <stdio.h> 48116742Ssam#include <signal.h> 49116742Ssam#include <stdlib.h> /* getenv, exit */ 50116742Ssam#include <string.h> /* strcmp */ 51116742Ssam#include <syslog.h> 52147221Ssam#include <unistd.h> 53147221Ssam#include <rpc/pmap_clnt.h> /* for pmap_unset */ 54147221Ssam#ifdef __cplusplus 55147221Ssam#include <sysent.h> /* getdtablesize, open */ 56147221Ssam#endif /* __cplusplus */ 57147221Ssam#include <sys/socket.h> 58147221Ssam#include <netinet/in.h> 59147221Ssam#include <sys/wait.h> 60147221Ssam#include "yp_extern.h" 61147221Ssam#include <rpc/rpc.h> 62138568Ssam 63138568Ssam#ifndef SIG_PF 64138568Ssam#define SIG_PF void(*)(int) 65138568Ssam#endif 66116742Ssam 67138568Ssam#define _RPCSVC_CLOSEDOWN 120 68138568Ssamint _rpcpmstart; /* Started by a port monitor ? */ 69138568Ssamstatic int _rpcfdtype; 70138568Ssam /* Whether Stream or Datagram ? */ 71120104Ssam /* States a server can be in wrt request */ 72138568Ssam 73138568Ssam#define _IDLE 0 74116742Ssam#define _SERVED 1 75148304Ssam#define _SERVING 2 76138568Ssam 77138568Ssamextern void ypprog_1(struct svc_req *, register SVCXPRT *); 78148863Ssamextern void ypprog_2(struct svc_req *, register SVCXPRT *); 79148863Ssamextern int _rpc_dtablesize(void); 80138568Ssamextern int _rpcsvcstate; /* Set when a request is serviced */ 81138568Ssamchar *progname = "ypserv"; 82138568Ssamchar *yp_dir = _PATH_YP; 83127876Ssam/*int debug = 0;*/ 84120481Ssamint do_dns = 0; 85116742Ssamint resfd; 86138568Ssam 87116742Ssamstatic 88116742Ssamvoid _msgout(char* msg) 89138568Ssam{ 90138568Ssam if (debug) { 91138568Ssam if (_rpcpmstart) 92138568Ssam syslog(LOG_ERR, "%s", msg); 93138568Ssam else 94138568Ssam warnx("%s", msg); 95138568Ssam } else 96138568Ssam syslog(LOG_ERR, "%s", msg); 97138568Ssam} 98138568Ssam 99138568Ssampid_t yp_pid; 100148863Ssam 101148863Ssamstatic void 102148863Ssamyp_svc_run(void) 103148863Ssam{ 104148863Ssam#ifdef FD_SETSIZE 105148863Ssam fd_set readfds; 106148863Ssam#else 107148863Ssam int readfds; 108148863Ssam#endif /* def FD_SETSIZE */ 109148863Ssam extern int forked; 110148863Ssam int fd_setsize = _rpc_dtablesize(); 111138568Ssam struct timeval timeout; 112138568Ssam 113138568Ssam /* Establish the identity of the parent ypserv process. */ 114138568Ssam yp_pid = getpid(); 115138568Ssam 116138568Ssam for (;;) { 117138568Ssam#ifdef FD_SETSIZE 118138568Ssam readfds = svc_fdset; 119138568Ssam#else 120138568Ssam readfds = svc_fds; 121138568Ssam#endif /* def FD_SETSIZE */ 122138568Ssam 123138568Ssam FD_SET(resfd, &readfds); 124138568Ssam 125138568Ssam timeout.tv_sec = RESOLVER_TIMEOUT; 126138568Ssam timeout.tv_usec = 0; 127138568Ssam switch (select(fd_setsize, &readfds, NULL, NULL, 128138568Ssam &timeout)) { 129118887Ssam case -1: 130148863Ssam if (errno == EINTR) { 131148863Ssam continue; 132148863Ssam } 133148863Ssam warn("svc_run: - select failed"); 134148863Ssam return; 135148863Ssam case 0: 136118887Ssam if (getpid() == yp_pid) 137148863Ssam yp_prune_dnsq(); 138138568Ssam break; 139138568Ssam default: 140138568Ssam if (getpid() == yp_pid) { 141138568Ssam if (FD_ISSET(resfd, &readfds)) { 142148863Ssam yp_run_dnsq(); 143138568Ssam FD_CLR(resfd, &readfds); 144138568Ssam } 145138568Ssam svc_getreqset(&readfds); 146138568Ssam } 147138568Ssam } 148138568Ssam if (yp_pid != getpid()) 149138568Ssam _exit(0); 150138568Ssam } 151138568Ssam} 152138568Ssam 153138568Ssamstatic void 154138568Ssamunregister(void) 155138568Ssam{ 156138568Ssam (void) pmap_unset(YPPROG, YPVERS); 157138568Ssam (void) pmap_unset(YPPROG, YPOLDVERS); 158138568Ssam} 159138568Ssam 160138568Ssamstatic void 161138568Ssamreaper(int sig) 162138568Ssam{ 163138568Ssam int status; 164138568Ssam int saved_errno; 165138568Ssam 166138568Ssam saved_errno = errno; 167138568Ssam 168138568Ssam if (sig == SIGHUP) { 169138568Ssam load_securenets(); 170138568Ssam#ifdef DB_CACHE 171138568Ssam yp_flush_all(); 172138568Ssam#endif 173138568Ssam errno = saved_errno; 174148863Ssam return; 175116742Ssam } 176116742Ssam 177116742Ssam if (sig == SIGCHLD) { 178138568Ssam while (wait3(&status, WNOHANG, NULL) > 0) 179116742Ssam children--; 180116742Ssam } else { 181138568Ssam unregister(); 182138568Ssam exit(0); 183138568Ssam } 184138568Ssam errno = saved_errno; 185138568Ssam return; 186140753Ssam} 187138568Ssam 188138568Ssamstatic void 189138568Ssamusage(void) 190138568Ssam{ 191138568Ssam fprintf(stderr, "usage: ypserv [-h] [-d] [-n] [-p path]\n"); 192138568Ssam exit(1); 193138568Ssam} 194138568Ssam 195116742Ssamstatic void 196116742Ssamclosedown(int sig) 197138568Ssam{ 198138568Ssam if (_rpcsvcstate == _IDLE) { 199138568Ssam extern fd_set svc_fdset; 200138568Ssam static int size; 201138568Ssam int i, openfd; 202148302Ssam 203138568Ssam if (_rpcfdtype == SOCK_DGRAM) { 204148302Ssam unregister(); 205148302Ssam exit(0); 206138568Ssam } 207139528Ssam if (size == 0) { 208138568Ssam size = getdtablesize(); 209138568Ssam } 210138568Ssam for (i = 0, openfd = 0; i < size && openfd < 2; i++) 211148302Ssam if (FD_ISSET(i, &svc_fdset)) 212138568Ssam openfd++; 213138568Ssam if (openfd <= 1) { 214138568Ssam unregister(); 215138568Ssam exit(0); 216116742Ssam } 217138568Ssam } 218138568Ssam if (_rpcsvcstate == _SERVED) 219138568Ssam _rpcsvcstate = _IDLE; 220138568Ssam 221138568Ssam (void) signal(SIGALRM, (SIG_PF) closedown); 222138568Ssam (void) alarm(_RPCSVC_CLOSEDOWN/2); 223138568Ssam} 224138568Ssam 225138568Ssamint 226138568Ssammain(int argc, char *argv[]) 227138568Ssam{ 228138568Ssam register SVCXPRT *transp = NULL; 229116742Ssam int sock; 230116742Ssam int proto = 0; 231116742Ssam struct sockaddr_in saddr; 232138568Ssam socklen_t asize = sizeof (saddr); 233138568Ssam int ch; 234138568Ssam 235138568Ssam while ((ch = getopt(argc, argv, "hdnp:")) != -1) { 236138568Ssam switch (ch) { 237138568Ssam case 'd': 238138568Ssam debug = ypdb_debug = 1; 239138568Ssam break; 240138568Ssam case 'n': 241138568Ssam do_dns = 1; 242138568Ssam break; 243138568Ssam case 'p': 244138568Ssam yp_dir = optarg; 245138568Ssam break; 246138568Ssam case 'h': 247138568Ssam default: 248116742Ssam usage(); 249138568Ssam } 250116742Ssam } 251116742Ssam 252117811Ssam load_securenets(); 253138568Ssam yp_init_resolver(); 254116742Ssam#ifdef DB_CACHE 255116742Ssam yp_init_dbs(); 256138568Ssam#endif 257138568Ssam if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { 258138568Ssam int ssize = sizeof (int); 259138568Ssam 260138568Ssam if (saddr.sin_family != AF_INET) 261138568Ssam exit(1); 262138568Ssam if (getsockopt(0, SOL_SOCKET, SO_TYPE, 263138568Ssam (char *)&_rpcfdtype, &ssize) == -1) 264138568Ssam exit(1); 265138568Ssam sock = 0; 266138568Ssam _rpcpmstart = 1; 267138568Ssam proto = 0; 268138568Ssam openlog("ypserv", LOG_PID, LOG_DAEMON); 269148936Ssam } else { 270138568Ssam if (!debug) { 271138568Ssam if (daemon(0,0)) { 272116742Ssam err(1,"cannot fork"); 273116742Ssam } 274116742Ssam openlog("ypserv", LOG_PID, LOG_DAEMON); 275116742Ssam } 276116742Ssam sock = RPC_ANYSOCK; 277116742Ssam (void) pmap_unset(YPPROG, YPVERS); 278138568Ssam (void) pmap_unset(YPPROG, 1); 279116742Ssam } 280116742Ssam 281138568Ssam if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_DGRAM)) { 282117811Ssam transp = svcudp_create(sock); 283117811Ssam if (transp == NULL) { 284117811Ssam _msgout("cannot create udp service"); 285117811Ssam exit(1); 286121180Ssam } 287117811Ssam if (!_rpcpmstart) 288121180Ssam proto = IPPROTO_UDP; 289121180Ssam if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) { 290121180Ssam _msgout("unable to register (YPPROG, YPOLDVERS, udp)"); 291139520Ssam exit(1); 292139520Ssam } 293138568Ssam if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { 294139520Ssam _msgout("unable to register (YPPROG, YPVERS, udp)"); 295116742Ssam exit(1); 296138568Ssam } 297116742Ssam } 298138568Ssam 299138568Ssam if ((_rpcfdtype == 0) || (_rpcfdtype == SOCK_STREAM)) { 300138568Ssam transp = svctcp_create(sock, 0, 0); 301116742Ssam if (transp == NULL) { 302138568Ssam _msgout("cannot create tcp service"); 303138568Ssam exit(1); 304117811Ssam } 305138568Ssam if (!_rpcpmstart) 306116742Ssam proto = IPPROTO_TCP; 307116742Ssam if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) { 308116742Ssam _msgout("unable to register (YPPROG, YPOLDVERS, tcp)"); 309116742Ssam exit(1); 310116742Ssam } 311138568Ssam if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { 312138568Ssam _msgout("unable to register (YPPROG, YPVERS, tcp)"); 313116742Ssam exit(1); 314116742Ssam } 315116742Ssam } 316138568Ssam 317138568Ssam if (transp == (SVCXPRT *)NULL) { 318138568Ssam _msgout("could not create a handle"); 319138568Ssam exit(1); 320138568Ssam } 321138568Ssam if (_rpcpmstart) { 322138568Ssam (void) signal(SIGALRM, (SIG_PF) closedown); 323148936Ssam (void) alarm(_RPCSVC_CLOSEDOWN/2); 324138568Ssam } 325116742Ssam/* 326116742Ssam * Make sure SIGPIPE doesn't blow us away while servicing TCP 327116742Ssam * connections. 328138568Ssam */ 329138568Ssam (void) signal(SIGPIPE, SIG_IGN); 330138568Ssam (void) signal(SIGCHLD, (SIG_PF) reaper); 331148936Ssam (void) signal(SIGTERM, (SIG_PF) reaper); 332138568Ssam (void) signal(SIGINT, (SIG_PF) reaper); 333148936Ssam (void) signal(SIGHUP, (SIG_PF) reaper); 334148936Ssam yp_svc_run(); 335148936Ssam _msgout("svc_run returned"); 336148936Ssam exit(1); 337148936Ssam /* NOTREACHED */ 338148936Ssam} 339148936Ssam