1 /* $NetBSD: inetd.c,v 1.38 1997/10/17 13:53:30 lukem Exp $ */ 2 3 /* 4 * Copyright (c) 1983, 1991, 1993, 1994 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/cdefs.h> 37 #ifndef lint 38 __COPYRIGHT("@(#) Copyright (c) 1983, 1991, 1993, 1994\n\ 39 The Regents of the University of California. All rights reserved.\n"); 40 #if 0 41 static char sccsid[] = "@(#)inetd.c 8.4 (Berkeley) 4/13/94"; 42 #else 43 __RCSID("$NetBSD: inetd.c,v 1.38 1997/10/17 13:53:30 lukem Exp $"); 44 #endif 45 #endif /* not lint */ 46 47 /* 48 * Inetd - Internet super-server 49 * 50 * This program invokes all internet services as needed. Connection-oriented 51 * services are invoked each time a connection is made, by creating a process. 52 * This process is passed the connection as file descriptor 0 and is expected 53 * to do a getpeername to find out the source host and port. 54 * 55 * Datagram oriented services are invoked when a datagram 56 * arrives; a process is created and passed a pending message 57 * on file descriptor 0. Datagram servers may either connect 58 * to their peer, freeing up the original socket for inetd 59 * to receive further messages on, or ``take over the socket'', 60 * processing all arriving datagrams and, eventually, timing 61 * out. The first type of server is said to be ``multi-threaded''; 62 * the second type of server ``single-threaded''. 63 * 64 * Inetd uses a configuration file which is read at startup 65 * and, possibly, at some later time in response to a hangup signal. 66 * The configuration file is ``free format'' with fields given in the 67 * order shown below. Continuation lines for an entry must being with 68 * a space or tab. All fields must be present in each entry. 69 * 70 * service name must be in /etc/services or must 71 * name a tcpmux service 72 * socket type stream/dgram/raw/rdm/seqpacket 73 * protocol must be in /etc/protocols 74 * wait/nowait[.max] single-threaded/multi-threaded, max # 75 * user[.group] user/group to run daemon as 76 * server program full path name 77 * server program arguments maximum of MAXARGS (20) 78 * 79 * For RPC services 80 * service name/version must be in /etc/rpc 81 * socket type stream/dgram/raw/rdm/seqpacket 82 * protocol must be in /etc/protocols 83 * wait/nowait[.max] single-threaded/multi-threaded 84 * user[.group] user to run daemon as 85 * server program full path name 86 * server program arguments maximum of MAXARGS (20) 87 * 88 * For non-RPC services, the "service name" can be of the form 89 * hostaddress:servicename, in which case the hostaddress is used 90 * as the host portion of the address to listen on. If hostaddress 91 * consists of a single `*' character, INADDR_ANY is used. 92 * 93 * A line can also consist of just 94 * hostaddress: 95 * where hostaddress is as in the preceding paragraph. Such a line must 96 * have no further fields; the specified hostaddress is remembered and 97 * used for all further lines that have no hostaddress specified, 98 * until the next such line (or EOF). (This is why * is provided to 99 * allow explicit specification of INADDR_ANY.) A line 100 * *: 101 * is implicitly in effect at the beginning of the file. 102 * 103 * The hostaddress specifier may (and often will) contain dots; 104 * the service name must not. 105 * 106 * For RPC services, host-address specifiers are accepted and will 107 * work to some extent; however, because of limitations in the 108 * portmapper interface, it will not work to try to give more than 109 * one line for any given RPC service, even if the host-address 110 * specifiers are different. 111 * 112 * TCP services without official port numbers are handled with the 113 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for 114 * requests. When a connection is made from a foreign host, the service 115 * requested is passed to tcpmux, which looks it up in the servtab list 116 * and returns the proper entry for the service. Tcpmux returns a 117 * negative reply if the service doesn't exist, otherwise the invoked 118 * server is expected to return the positive reply if the service type in 119 * inetd.conf file has the prefix "tcpmux/". If the service type has the 120 * prefix "tcpmux/+", tcpmux will return the positive reply for the 121 * process; this is for compatibility with older server code, and also 122 * allows you to invoke programs that use stdin/stdout without putting any 123 * special server code in them. Services that use tcpmux are "nowait" 124 * because they do not have a well-known port and hence cannot listen 125 * for new requests. 126 * 127 * Comment lines are indicated by a `#' in column 1. 128 */ 129 130 /* 131 * Here's the scoop concerning the user.group feature: 132 * 133 * 1) set-group-option off. 134 * 135 * a) user = root: NO setuid() or setgid() is done 136 * 137 * b) other: setuid() 138 * setgid(primary group as found in passwd) 139 * initgroups(name, primary group) 140 * 141 * 2) set-group-option on. 142 * 143 * a) user = root: NO setuid() 144 * setgid(specified group) 145 * NO initgroups() 146 * 147 * b) other: setuid() 148 * setgid(specified group) 149 * initgroups(name, specified group) 150 * 151 */ 152 153 #include <sys/param.h> 154 #include <sys/stat.h> 155 #include <sys/ioctl.h> 156 #include <sys/socket.h> 157 #include <sys/un.h> 158 #include <sys/wait.h> 159 #include <sys/time.h> 160 #include <sys/resource.h> 161 162 #ifndef RLIMIT_NOFILE 163 #define RLIMIT_NOFILE RLIMIT_OFILE 164 #endif 165 166 #define RPC 167 168 #include <netinet/in.h> 169 #include <arpa/inet.h> 170 #ifdef RPC 171 #include <rpc/rpc.h> 172 #include <rpc/pmap_clnt.h> 173 #endif 174 175 #include <errno.h> 176 #include <fcntl.h> 177 #include <grp.h> 178 #include <netdb.h> 179 #include <pwd.h> 180 #include <signal.h> 181 #include <stdio.h> 182 #include <stdlib.h> 183 #include <string.h> 184 #include <syslog.h> 185 #include <unistd.h> 186 187 #include "pathnames.h" 188 189 #ifdef LIBWRAP 190 # include <tcpd.h> 191 #ifndef LIBWRAP_ALLOW_FACILITY 192 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH 193 #endif 194 #ifndef LIBWRAP_ALLOW_SEVERITY 195 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO 196 #endif 197 #ifndef LIBWRAP_DENY_FACILITY 198 # define LIBWRAP_DENY_FACILITY LOG_AUTH 199 #endif 200 #ifndef LIBWRAP_DENY_SEVERITY 201 # define LIBWRAP_DENY_SEVERITY LOG_WARNING 202 #endif 203 int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY; 204 int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY; 205 #endif 206 207 #define TOOMANY 40 /* don't start more than TOOMANY */ 208 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ 209 #define RETRYTIME (60*10) /* retry after bind or server fail */ 210 211 #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM)) 212 213 int debug; 214 #ifdef LIBWRAP 215 int lflag; 216 #endif 217 int nsock, maxsock; 218 fd_set allsock; 219 int options; 220 int timingout; 221 struct servent *sp; 222 char *curdom; 223 224 #ifndef OPEN_MAX 225 #define OPEN_MAX 64 226 #endif 227 228 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ 229 #define FD_MARGIN (8) 230 typeof(((struct rlimit *)0)->rlim_cur) rlim_ofile_cur = OPEN_MAX; 231 232 #ifdef RLIMIT_NOFILE 233 struct rlimit rlim_ofile; 234 #endif 235 236 struct servtab { 237 char *se_hostaddr; /* host address to listen on */ 238 char *se_service; /* name of service */ 239 int se_socktype; /* type of socket to use */ 240 int se_family; /* address family */ 241 char *se_proto; /* protocol used */ 242 int se_rpcprog; /* rpc program number */ 243 int se_rpcversl; /* rpc program lowest version */ 244 int se_rpcversh; /* rpc program highest version */ 245 #define isrpcservice(sep) ((sep)->se_rpcversl != 0) 246 short se_wait; /* single threaded server */ 247 short se_checked; /* looked at during merge */ 248 char *se_user; /* user name to run as */ 249 char *se_group; /* group name to run as */ 250 struct biltin *se_bi; /* if built-in, description */ 251 char *se_server; /* server program */ 252 #define MAXARGV 20 253 char *se_argv[MAXARGV+1]; /* program arguments */ 254 int se_fd; /* open descriptor */ 255 int se_type; /* type */ 256 union { 257 struct sockaddr se_un_ctrladdr; 258 struct sockaddr_in se_un_ctrladdr_in; 259 struct sockaddr_un se_un_ctrladdr_un; 260 } se_un; /* bound address */ 261 #define se_ctrladdr se_un.se_un_ctrladdr 262 #define se_ctrladdr_in se_un.se_un_ctrladdr_in 263 #define se_ctrladdr_un se_un.se_un_ctrladdr_un 264 int se_ctrladdr_size; 265 int se_max; /* max # of instances of this service */ 266 int se_count; /* number started since se_time */ 267 struct timeval se_time; /* start of se_count */ 268 #ifdef MULOG 269 int se_log; 270 #define MULOG_RFC931 0x40000000 271 #endif 272 struct servtab *se_next; 273 } *servtab; 274 275 #define NORM_TYPE 0 276 #define MUX_TYPE 1 277 #define MUXPLUS_TYPE 2 278 #define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \ 279 ((sep)->se_type == MUXPLUS_TYPE)) 280 #define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE) 281 282 283 void chargen_dg __P((int, struct servtab *)); 284 void chargen_stream __P((int, struct servtab *)); 285 void close_sep __P((struct servtab *)); 286 void config __P((int)); 287 void daytime_dg __P((int, struct servtab *)); 288 void daytime_stream __P((int, struct servtab *)); 289 void discard_dg __P((int, struct servtab *)); 290 void discard_stream __P((int, struct servtab *)); 291 void echo_dg __P((int, struct servtab *)); 292 void echo_stream __P((int, struct servtab *)); 293 void endconfig __P((void)); 294 struct servtab *enter __P((struct servtab *)); 295 void freeconfig __P((struct servtab *)); 296 struct servtab *getconfigent __P((void)); 297 void goaway __P((int)); 298 void machtime_dg __P((int, struct servtab *)); 299 void machtime_stream __P((int, struct servtab *)); 300 char *newstr __P((char *)); 301 char *nextline __P((FILE *)); 302 void print_service __P((char *, struct servtab *)); 303 void reapchild __P((int)); 304 void retry __P((int)); 305 void run_service __P((int, struct servtab *)); 306 int setconfig __P((void)); 307 void setup __P((struct servtab *)); 308 char *sskip __P((char **)); 309 char *skip __P((char **)); 310 void tcpmux __P((int, struct servtab *)); 311 void usage __P((void)); 312 void logpid __P((void)); 313 void register_rpc __P((struct servtab *sep)); 314 void unregister_rpc __P((struct servtab *sep)); 315 void bump_nofile __P((void)); 316 void inetd_setproctitle __P((char *, int)); 317 void initring __P((void)); 318 long machtime __P((void)); 319 static int getline __P((int, char *, int)); 320 int main __P((int, char *[], char *[])); 321 322 struct biltin { 323 char *bi_service; /* internally provided service name */ 324 int bi_socktype; /* type of socket supported */ 325 short bi_fork; /* 1 if should fork before call */ 326 short bi_wait; /* 1 if should wait for child */ 327 void (*bi_fn) __P((int, struct servtab *)); 328 /* function which performs it */ 329 } biltins[] = { 330 /* Echo received data */ 331 { "echo", SOCK_STREAM, 1, 0, echo_stream }, 332 { "echo", SOCK_DGRAM, 0, 0, echo_dg }, 333 334 /* Internet /dev/null */ 335 { "discard", SOCK_STREAM, 1, 0, discard_stream }, 336 { "discard", SOCK_DGRAM, 0, 0, discard_dg }, 337 338 /* Return 32 bit time since 1970 */ 339 { "time", SOCK_STREAM, 0, 0, machtime_stream }, 340 { "time", SOCK_DGRAM, 0, 0, machtime_dg }, 341 342 /* Return human-readable time */ 343 { "daytime", SOCK_STREAM, 0, 0, daytime_stream }, 344 { "daytime", SOCK_DGRAM, 0, 0, daytime_dg }, 345 346 /* Familiar character generator */ 347 { "chargen", SOCK_STREAM, 1, 0, chargen_stream }, 348 { "chargen", SOCK_DGRAM, 0, 0, chargen_dg }, 349 350 { "tcpmux", SOCK_STREAM, 1, 0, tcpmux }, 351 352 { NULL } 353 }; 354 355 #define NUMINT (sizeof(intab) / sizeof(struct inent)) 356 char *CONFIG = _PATH_INETDCONF; 357 char **Argv; 358 char *LastArg; 359 extern char *__progname; 360 361 #ifdef sun 362 /* 363 * Sun's RPC library caches the result of `dtablesize()' 364 * This is incompatible with our "bumping" of file descriptors "on demand" 365 */ 366 int 367 _rpc_dtablesize() 368 { 369 return rlim_ofile_cur; 370 } 371 #endif 372 373 int 374 main(argc, argv, envp) 375 int argc; 376 char *argv[], *envp[]; 377 { 378 struct servtab *sep, *nsep; 379 struct sigvec sv; 380 int ch, dofork; 381 pid_t pid; 382 383 Argv = argv; 384 if (envp == 0 || *envp == 0) 385 envp = argv; 386 while (*envp) 387 envp++; 388 LastArg = envp[-1] + strlen(envp[-1]); 389 390 while ((ch = getopt(argc, argv, 391 #ifdef LIBWRAP 392 "dl" 393 #else 394 "d" 395 #endif 396 )) != -1) 397 switch(ch) { 398 case 'd': 399 debug = 1; 400 options |= SO_DEBUG; 401 break; 402 #ifdef LIBWRAP 403 case 'l': 404 lflag = 1; 405 break; 406 #endif 407 case '?': 408 default: 409 usage(); 410 } 411 argc -= optind; 412 argv += optind; 413 414 if (argc > 0) 415 CONFIG = argv[0]; 416 417 if (debug == 0) 418 daemon(0, 0); 419 openlog(__progname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 420 logpid(); 421 422 #ifdef RLIMIT_NOFILE 423 if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) { 424 syslog(LOG_ERR, "getrlimit: %m"); 425 } else { 426 rlim_ofile_cur = rlim_ofile.rlim_cur; 427 if (rlim_ofile_cur == RLIM_INFINITY) /* ! */ 428 rlim_ofile_cur = OPEN_MAX; 429 } 430 #endif 431 432 memset(&sv, 0, sizeof(sv)); 433 sv.sv_mask = SIGBLOCK; 434 sv.sv_handler = retry; 435 sigvec(SIGALRM, &sv, (struct sigvec *)0); 436 config(SIGHUP); 437 sv.sv_handler = config; 438 sigvec(SIGHUP, &sv, (struct sigvec *)0); 439 sv.sv_handler = reapchild; 440 sigvec(SIGCHLD, &sv, (struct sigvec *)0); 441 sv.sv_handler = goaway; 442 sigvec(SIGTERM, &sv, (struct sigvec *)0); 443 sv.sv_handler = goaway; 444 sigvec(SIGINT, &sv, (struct sigvec *)0); 445 446 { 447 /* space for daemons to overwrite environment for ps */ 448 #define DUMMYSIZE 100 449 char dummy[DUMMYSIZE]; 450 451 (void)memset(dummy, 'x', DUMMYSIZE - 1); 452 dummy[DUMMYSIZE - 1] = '\0'; 453 454 (void)setenv("inetd_dummy", dummy, 1); 455 } 456 457 for (;;) { 458 int n, ctrl; 459 fd_set readable; 460 461 if (nsock == 0) { 462 (void) sigblock(SIGBLOCK); 463 while (nsock == 0) 464 sigpause(0L); 465 (void) sigsetmask(0L); 466 } 467 readable = allsock; 468 if ((n = select(maxsock + 1, &readable, (fd_set *)0, 469 (fd_set *)0, (struct timeval *)0)) <= 0) { 470 if (n == -1 && errno != EINTR) { 471 syslog(LOG_WARNING, "select: %m"); 472 sleep(1); 473 } 474 continue; 475 } 476 for (sep = servtab; n && sep; sep = nsep) { 477 nsep = sep->se_next; 478 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) { 479 n--; 480 if (debug) 481 fprintf(stderr, "someone wants %s\n", sep->se_service); 482 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 483 /* XXX here do the libwrap check-before-accept */ 484 ctrl = accept(sep->se_fd, (struct sockaddr *)0, 485 (int *)0); 486 if (debug) 487 fprintf(stderr, "accept, ctrl %d\n", ctrl); 488 if (ctrl < 0) { 489 if (errno != EINTR) 490 syslog(LOG_WARNING, 491 "accept (for %s): %m", 492 sep->se_service); 493 continue; 494 } 495 } else 496 ctrl = sep->se_fd; 497 (void) sigblock(SIGBLOCK); 498 pid = 0; 499 #ifdef LIBWRAP_INTERNAL 500 dofork = 1; 501 #else 502 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); 503 #endif 504 if (dofork) { 505 if (sep->se_count++ == 0) 506 (void)gettimeofday(&sep->se_time, 507 (struct timezone *)0); 508 else if (sep->se_count >= sep->se_max) { 509 struct timeval now; 510 511 (void)gettimeofday(&now, (struct timezone *)0); 512 if (now.tv_sec - sep->se_time.tv_sec > 513 CNT_INTVL) { 514 sep->se_time = now; 515 sep->se_count = 1; 516 } else { 517 syslog(LOG_ERR, 518 "%s/%s server failing (looping), service terminated\n", 519 sep->se_service, sep->se_proto); 520 close_sep(sep); 521 sigsetmask(0L); 522 if (!timingout) { 523 timingout = 1; 524 alarm(RETRYTIME); 525 } 526 continue; 527 } 528 } 529 pid = fork(); 530 if (pid < 0) { 531 syslog(LOG_ERR, "fork: %m"); 532 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 533 close(ctrl); 534 sigsetmask(0L); 535 sleep(1); 536 continue; 537 } 538 if (pid != 0 && sep->se_wait) { 539 sep->se_wait = pid; 540 FD_CLR(sep->se_fd, &allsock); 541 nsock--; 542 } 543 if (pid == 0 && debug) 544 setsid(); 545 } 546 sigsetmask(0L); 547 if (pid == 0) { 548 run_service(ctrl, sep); 549 if (dofork) 550 exit(0); 551 } 552 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 553 close(ctrl); 554 } 555 } 556 } 557 } 558 559 void 560 run_service(ctrl, sep) 561 int ctrl; 562 struct servtab *sep; 563 { 564 struct passwd *pwd; 565 struct group *grp = NULL; /* XXX gcc */ 566 #ifdef LIBWRAP 567 struct request_info req; 568 int denied; 569 char buf[7], *service = NULL; /* XXX gcc */ 570 #endif 571 572 #ifdef LIBWRAP 573 #ifndef LIBWRAP_INTERNAL 574 if (sep->se_bi == 0) 575 #endif 576 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 577 request_init(&req, RQ_DAEMON, sep->se_argv[0] ? 578 sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL); 579 fromhost(&req); 580 denied = !hosts_access(&req); 581 if (denied || lflag) { 582 sp = getservbyport(sep->se_ctrladdr_in.sin_port, 583 sep->se_proto); 584 if (sp == NULL) { 585 (void)snprintf(buf, sizeof buf, "%d", 586 ntohs(sep->se_ctrladdr_in.sin_port)); 587 service = buf; 588 } else 589 service = sp->s_name; 590 } 591 if (denied) { 592 syslog(deny_severity, 593 "refused connection from %.500s, service %s (%s)", 594 eval_client(&req), service, sep->se_proto); 595 goto reject; 596 } 597 if (lflag) { 598 syslog(allow_severity, 599 "connection from %.500s, service %s (%s)", 600 eval_client(&req), service, sep->se_proto); 601 } 602 } 603 #endif /* LIBWRAP */ 604 605 if (sep->se_bi) { 606 (*sep->se_bi->bi_fn)(ctrl, sep); 607 } else { 608 if ((pwd = getpwnam(sep->se_user)) == NULL) { 609 syslog(LOG_ERR, "%s/%s: %s: No such user", 610 sep->se_service, sep->se_proto, sep->se_user); 611 goto reject; 612 } 613 if (sep->se_group && 614 (grp = getgrnam(sep->se_group)) == NULL) { 615 syslog(LOG_ERR, "%s/%s: %s: No such group", 616 sep->se_service, sep->se_proto, sep->se_group); 617 goto reject; 618 } 619 if (pwd->pw_uid) { 620 if (sep->se_group) 621 pwd->pw_gid = grp->gr_gid; 622 if (setgid(pwd->pw_gid) < 0) { 623 syslog(LOG_ERR, 624 "%s/%s: can't set gid %d: %m", sep->se_service, 625 sep->se_proto, pwd->pw_gid); 626 goto reject; 627 } 628 (void) initgroups(pwd->pw_name, 629 pwd->pw_gid); 630 if (setuid(pwd->pw_uid) < 0) { 631 syslog(LOG_ERR, 632 "%s/%s: can't set uid %d: %m", sep->se_service, 633 sep->se_proto, pwd->pw_uid); 634 goto reject; 635 } 636 } else if (sep->se_group) { 637 (void) setgid((gid_t)grp->gr_gid); 638 } 639 if (debug) 640 fprintf(stderr, "%d execl %s\n", 641 getpid(), sep->se_server); 642 #ifdef MULOG 643 if (sep->se_log) 644 dolog(sep, ctrl); 645 #endif 646 /* Set our control descriptor to not close-on-exec... */ 647 if (fcntl(ctrl, F_SETFD, 0) < 0) 648 syslog(LOG_ERR, "fcntl (F_SETFD, 0): %m"); 649 /* ...and dup it to stdin, stdout, and stderr. */ 650 if (ctrl != 0) { 651 dup2(ctrl, 0); 652 close(ctrl); 653 ctrl = 0; 654 } 655 dup2(0, 1); 656 dup2(0, 2); 657 #ifdef RLIMIT_NOFILE 658 if (rlim_ofile.rlim_cur != rlim_ofile_cur && 659 setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) 660 syslog(LOG_ERR, "setrlimit: %m"); 661 #endif 662 execv(sep->se_server, sep->se_argv); 663 syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server); 664 reject: 665 if (sep->se_socktype != SOCK_STREAM) 666 recv(ctrl, buf, sizeof (buf), 0); 667 _exit(1); 668 } 669 } 670 671 void 672 reapchild(signo) 673 int signo; 674 { 675 int status; 676 pid_t pid; 677 struct servtab *sep; 678 679 for (;;) { 680 pid = wait3(&status, WNOHANG, (struct rusage *)0); 681 if (pid <= 0) 682 break; 683 if (debug) 684 fprintf(stderr, "%d reaped, status %#x\n", 685 pid, status); 686 for (sep = servtab; sep; sep = sep->se_next) 687 if (sep->se_wait == pid) { 688 if (WIFEXITED(status) && WEXITSTATUS(status)) 689 syslog(LOG_WARNING, 690 "%s: exit status 0x%x", 691 sep->se_server, WEXITSTATUS(status)); 692 else if (WIFSIGNALED(status)) 693 syslog(LOG_WARNING, 694 "%s: exit signal 0x%x", 695 sep->se_server, WTERMSIG(status)); 696 sep->se_wait = 1; 697 FD_SET(sep->se_fd, &allsock); 698 nsock++; 699 if (debug) 700 fprintf(stderr, "restored %s, fd %d\n", 701 sep->se_service, sep->se_fd); 702 } 703 } 704 } 705 706 void 707 config(signo) 708 int signo; 709 { 710 struct servtab *sep, *cp, **sepp; 711 long omask; 712 int n; 713 714 if (!setconfig()) { 715 syslog(LOG_ERR, "%s: %m", CONFIG); 716 return; 717 } 718 for (sep = servtab; sep; sep = sep->se_next) 719 sep->se_checked = 0; 720 while ((cp = getconfigent())) { 721 for (sep = servtab; sep; sep = sep->se_next) 722 if (strcmp(sep->se_service, cp->se_service) == 0 && 723 strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 && 724 strcmp(sep->se_proto, cp->se_proto) == 0 && 725 ISMUX(sep) == ISMUX(cp)) 726 break; 727 if (sep != 0) { 728 int i; 729 730 #define SWAP(type, a, b) {type c=(type)a; (type)a=(type)b; (type)b=(type)c;} 731 732 omask = sigblock(SIGBLOCK); 733 /* 734 * sep->se_wait may be holding the pid of a daemon 735 * that we're waiting for. If so, don't overwrite 736 * it unless the config file explicitly says don't 737 * wait. 738 */ 739 if (cp->se_bi == 0 && 740 (sep->se_wait == 1 || cp->se_wait == 0)) 741 sep->se_wait = cp->se_wait; 742 SWAP(char *, sep->se_user, cp->se_user); 743 SWAP(char *, sep->se_group, cp->se_group); 744 SWAP(char *, sep->se_server, cp->se_server); 745 for (i = 0; i < MAXARGV; i++) 746 SWAP(char *, sep->se_argv[i], cp->se_argv[i]); 747 SWAP(int, cp->se_type, sep->se_type); 748 SWAP(int, cp->se_max, sep->se_max); 749 #undef SWAP 750 if (isrpcservice(sep)) 751 unregister_rpc(sep); 752 sep->se_rpcversl = cp->se_rpcversl; 753 sep->se_rpcversh = cp->se_rpcversh; 754 sigsetmask(omask); 755 freeconfig(cp); 756 if (debug) 757 print_service("REDO", sep); 758 } else { 759 sep = enter(cp); 760 if (debug) 761 print_service("ADD ", sep); 762 } 763 sep->se_checked = 1; 764 765 switch (sep->se_family) { 766 case AF_UNIX: 767 if (sep->se_fd != -1) 768 break; 769 n = strlen(sep->se_service); 770 if (n > sizeof(sep->se_ctrladdr_un.sun_path)) { 771 syslog(LOG_ERR, "%s: address too long", 772 sep->se_service); 773 sep->se_checked = 0; 774 continue; 775 } 776 (void)unlink(sep->se_service); 777 strncpy(sep->se_ctrladdr_un.sun_path, 778 sep->se_service, n); 779 sep->se_ctrladdr_un.sun_family = AF_UNIX; 780 sep->se_ctrladdr_size = n + 781 sizeof(sep->se_ctrladdr_un) - 782 sizeof(sep->se_ctrladdr_un.sun_path); 783 if (!ISMUX(sep)) 784 setup(sep); 785 break; 786 case AF_INET: 787 sep->se_ctrladdr_in.sin_family = AF_INET; 788 if (!strcmp(sep->se_hostaddr,"*")) 789 sep->se_ctrladdr_in.sin_addr.s_addr = 790 INADDR_ANY; 791 else if (!inet_aton(sep->se_hostaddr, 792 &sep->se_ctrladdr_in.sin_addr)) { 793 /* Do we really want to support hostname lookups here? */ 794 struct hostent *hp; 795 hp = gethostbyname(sep->se_hostaddr); 796 if (hp == 0) { 797 syslog(LOG_ERR, "%s: unknown host", 798 sep->se_hostaddr); 799 sep->se_checked = 0; 800 continue; 801 } else if (hp->h_addrtype != AF_INET) { 802 syslog(LOG_ERR, 803 "%s: address isn't an Internet address", 804 sep->se_hostaddr); 805 sep->se_checked = 0; 806 continue; 807 } else if (hp->h_length != sizeof(struct in_addr)) { 808 syslog(LOG_ERR, 809 "%s: address size wrong (under DNS corruption attack?)", 810 sep->se_hostaddr); 811 sep->se_checked = 0; 812 continue; 813 } else { 814 memcpy(&sep->se_ctrladdr_in.sin_addr, 815 hp->h_addr_list[0], 816 sizeof(struct in_addr)); 817 } 818 } 819 if (ISMUX(sep)) { 820 sep->se_fd = -1; 821 continue; 822 } 823 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr_in); 824 if (isrpcservice(sep)) { 825 struct rpcent *rp; 826 827 sep->se_rpcprog = atoi(sep->se_service); 828 if (sep->se_rpcprog == 0) { 829 rp = getrpcbyname(sep->se_service); 830 if (rp == 0) { 831 syslog(LOG_ERR, 832 "%s/%s: unknown service", 833 sep->se_service, 834 sep->se_proto); 835 sep->se_checked = 0; 836 continue; 837 } 838 sep->se_rpcprog = rp->r_number; 839 } 840 if (sep->se_fd == -1 && !ISMUX(sep)) 841 setup(sep); 842 if (sep->se_fd != -1) 843 register_rpc(sep); 844 } else { 845 u_short port = htons(atoi(sep->se_service)); 846 847 if (!port) { 848 sp = getservbyname(sep->se_service, 849 sep->se_proto); 850 if (sp == 0) { 851 syslog(LOG_ERR, 852 "%s/%s: unknown service", 853 sep->se_service, 854 sep->se_proto); 855 sep->se_checked = 0; 856 continue; 857 } 858 port = sp->s_port; 859 } 860 if (port != sep->se_ctrladdr_in.sin_port) { 861 sep->se_ctrladdr_in.sin_port = port; 862 if (sep->se_fd >= 0) 863 close_sep(sep); 864 } 865 if (sep->se_fd == -1 && !ISMUX(sep)) 866 setup(sep); 867 } 868 } 869 } 870 endconfig(); 871 /* 872 * Purge anything not looked at above. 873 */ 874 omask = sigblock(SIGBLOCK); 875 sepp = &servtab; 876 while ((sep = *sepp)) { 877 if (sep->se_checked) { 878 sepp = &sep->se_next; 879 continue; 880 } 881 *sepp = sep->se_next; 882 if (sep->se_fd >= 0) 883 close_sep(sep); 884 if (isrpcservice(sep)) 885 unregister_rpc(sep); 886 if (sep->se_family == AF_UNIX) 887 (void)unlink(sep->se_service); 888 if (debug) 889 print_service("FREE", sep); 890 freeconfig(sep); 891 free((char *)sep); 892 } 893 (void) sigsetmask(omask); 894 } 895 896 void 897 retry(signo) 898 int signo; 899 { 900 struct servtab *sep; 901 902 timingout = 0; 903 for (sep = servtab; sep; sep = sep->se_next) { 904 if (sep->se_fd == -1 && !ISMUX(sep)) { 905 switch (sep->se_family) { 906 case AF_UNIX: 907 case AF_INET: 908 setup(sep); 909 if (sep->se_fd != -1 && isrpcservice(sep)) 910 register_rpc(sep); 911 break; 912 } 913 } 914 } 915 } 916 917 void 918 goaway(signo) 919 int signo; 920 { 921 struct servtab *sep; 922 923 for (sep = servtab; sep; sep = sep->se_next) { 924 if (sep->se_fd == -1) 925 continue; 926 927 switch (sep->se_family) { 928 case AF_UNIX: 929 (void)unlink(sep->se_service); 930 break; 931 case AF_INET: 932 if (sep->se_wait == 1 && isrpcservice(sep)) 933 unregister_rpc(sep); 934 break; 935 } 936 (void)close(sep->se_fd); 937 } 938 (void)unlink(_PATH_INETDPID); 939 exit(0); 940 } 941 942 void 943 setup(sep) 944 struct servtab *sep; 945 { 946 int on = 1; 947 948 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { 949 if (debug) 950 fprintf(stderr, "socket failed on %s/%s: %s\n", 951 sep->se_service, sep->se_proto, strerror(errno)); 952 syslog(LOG_ERR, "%s/%s: socket: %m", 953 sep->se_service, sep->se_proto); 954 return; 955 } 956 /* Set all listening sockets to close-on-exec. */ 957 if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) 958 syslog(LOG_ERR, "fcntl (F_SETFD, FD_CLOEXEC): %m"); 959 #define turnon(fd, opt) \ 960 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) 961 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && 962 turnon(sep->se_fd, SO_DEBUG) < 0) 963 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 964 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 965 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 966 #undef turnon 967 if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) { 968 if (debug) 969 fprintf(stderr, "bind failed on %s/%s: %s\n", 970 sep->se_service, sep->se_proto, strerror(errno)); 971 syslog(LOG_ERR, "%s/%s: bind: %m", 972 sep->se_service, sep->se_proto); 973 (void) close(sep->se_fd); 974 sep->se_fd = -1; 975 if (!timingout) { 976 timingout = 1; 977 alarm(RETRYTIME); 978 } 979 return; 980 } 981 if (sep->se_socktype == SOCK_STREAM) 982 listen(sep->se_fd, 10); 983 984 FD_SET(sep->se_fd, &allsock); 985 nsock++; 986 if (sep->se_fd > maxsock) { 987 maxsock = sep->se_fd; 988 if (maxsock > rlim_ofile_cur - FD_MARGIN) 989 bump_nofile(); 990 } 991 if (debug) 992 fprintf(stderr, "registered %s on %d\n", 993 sep->se_server, sep->se_fd); 994 } 995 996 /* 997 * Finish with a service and its socket. 998 */ 999 void 1000 close_sep(sep) 1001 struct servtab *sep; 1002 { 1003 if (sep->se_fd >= 0) { 1004 nsock--; 1005 FD_CLR(sep->se_fd, &allsock); 1006 (void) close(sep->se_fd); 1007 sep->se_fd = -1; 1008 } 1009 sep->se_count = 0; 1010 /* 1011 * Don't keep the pid of this running deamon: when reapchild() 1012 * reaps this pid, it would erroneously increment nsock. 1013 */ 1014 if (sep->se_wait > 1) 1015 sep->se_wait = 1; 1016 } 1017 1018 void 1019 register_rpc(sep) 1020 struct servtab *sep; 1021 { 1022 #ifdef RPC 1023 int n; 1024 struct sockaddr_in sin; 1025 struct protoent *pp; 1026 1027 if ((pp = getprotobyname(sep->se_proto+4)) == NULL) { 1028 syslog(LOG_ERR, "%s: getproto: %m", 1029 sep->se_proto); 1030 return; 1031 } 1032 n = sizeof sin; 1033 if (getsockname(sep->se_fd, (struct sockaddr *)&sin, &n) < 0) { 1034 syslog(LOG_ERR, "%s/%s: getsockname: %m", 1035 sep->se_service, sep->se_proto); 1036 return; 1037 } 1038 1039 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1040 if (debug) 1041 fprintf(stderr, "pmap_set: %u %u %u %u\n", 1042 sep->se_rpcprog, n, pp->p_proto, 1043 ntohs(sin.sin_port)); 1044 (void)pmap_unset(sep->se_rpcprog, n); 1045 if (!pmap_set(sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port))) 1046 syslog(LOG_ERR, "pmap_set: %u %u %u %u: %m", 1047 sep->se_rpcprog, n, pp->p_proto, 1048 ntohs(sin.sin_port)); 1049 } 1050 #endif /* RPC */ 1051 } 1052 1053 void 1054 unregister_rpc(sep) 1055 struct servtab *sep; 1056 { 1057 #ifdef RPC 1058 int n; 1059 1060 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1061 if (debug) 1062 fprintf(stderr, "pmap_unset(%u, %u)\n", 1063 sep->se_rpcprog, n); 1064 if (!pmap_unset(sep->se_rpcprog, n)) 1065 syslog(LOG_ERR, "pmap_unset(%u, %u)\n", 1066 sep->se_rpcprog, n); 1067 } 1068 #endif /* RPC */ 1069 } 1070 1071 1072 struct servtab * 1073 enter(cp) 1074 struct servtab *cp; 1075 { 1076 struct servtab *sep; 1077 long omask; 1078 1079 sep = (struct servtab *)malloc(sizeof (*sep)); 1080 if (sep == (struct servtab *)0) { 1081 syslog(LOG_ERR, "Out of memory."); 1082 exit(-1); 1083 } 1084 *sep = *cp; 1085 sep->se_fd = -1; 1086 sep->se_rpcprog = -1; 1087 omask = sigblock(SIGBLOCK); 1088 sep->se_next = servtab; 1089 servtab = sep; 1090 sigsetmask(omask); 1091 return (sep); 1092 } 1093 1094 FILE *fconfig = NULL; 1095 struct servtab serv; 1096 char line[LINE_MAX]; 1097 char *defhost; 1098 1099 int 1100 setconfig() 1101 { 1102 if (defhost) free(defhost); 1103 defhost = newstr("*"); 1104 if (fconfig != NULL) { 1105 fseek(fconfig, 0L, SEEK_SET); 1106 return (1); 1107 } 1108 fconfig = fopen(CONFIG, "r"); 1109 return (fconfig != NULL); 1110 } 1111 1112 void 1113 endconfig() 1114 { 1115 if (fconfig) { 1116 (void) fclose(fconfig); 1117 fconfig = NULL; 1118 } 1119 if (defhost) { 1120 free(defhost); 1121 defhost = 0; 1122 } 1123 } 1124 1125 struct servtab * 1126 getconfigent() 1127 { 1128 struct servtab *sep = &serv; 1129 int argc; 1130 char *cp, *arg; 1131 static char TCPMUX_TOKEN[] = "tcpmux/"; 1132 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) 1133 char *hostdelim; 1134 1135 more: 1136 #ifdef MULOG 1137 while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0')) { 1138 /* Avoid use of `skip' if there is a danger of it looking 1139 * at continuation lines. 1140 */ 1141 do { 1142 cp++; 1143 } while (*cp == ' ' || *cp == '\t'); 1144 if (*cp == '\0') 1145 continue; 1146 if ((arg = skip(&cp)) == NULL) 1147 continue; 1148 if (strcmp(arg, "DOMAIN")) 1149 continue; 1150 if (curdom) 1151 free(curdom); 1152 curdom = NULL; 1153 while (*cp == ' ' || *cp == '\t') 1154 cp++; 1155 if (*cp == '\0') 1156 continue; 1157 arg = cp; 1158 while (*cp && *cp != ' ' && *cp != '\t') 1159 cp++; 1160 if (*cp != '\0') 1161 *cp++ = '\0'; 1162 curdom = newstr(arg); 1163 } 1164 #else 1165 while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0')) 1166 ; 1167 #endif 1168 if (cp == NULL) 1169 return ((struct servtab *)0); 1170 /* 1171 * clear the static buffer, since some fields (se_ctrladdr, 1172 * for example) don't get initialized here. 1173 */ 1174 memset((caddr_t)sep, 0, sizeof *sep); 1175 arg = skip(&cp); 1176 if (cp == NULL) { 1177 /* got an empty line containing just blanks/tabs. */ 1178 goto more; 1179 } 1180 /* Check for a host name. */ 1181 hostdelim = strrchr(arg, ':'); 1182 if (hostdelim) { 1183 *hostdelim = '\0'; 1184 sep->se_hostaddr = newstr(arg); 1185 arg = hostdelim + 1; 1186 /* 1187 * If the line is of the form `host:', then just change the 1188 * default host for the following lines. 1189 */ 1190 if (*arg == '\0') { 1191 arg = skip(&cp); 1192 if (cp == NULL) { 1193 free(defhost); 1194 defhost = sep->se_hostaddr; 1195 goto more; 1196 } 1197 } 1198 } else 1199 sep->se_hostaddr = newstr(defhost); 1200 if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) { 1201 char *c = arg + MUX_LEN; 1202 if (*c == '+') { 1203 sep->se_type = MUXPLUS_TYPE; 1204 c++; 1205 } else 1206 sep->se_type = MUX_TYPE; 1207 sep->se_service = newstr(c); 1208 } else { 1209 sep->se_service = newstr(arg); 1210 sep->se_type = NORM_TYPE; 1211 } 1212 1213 arg = sskip(&cp); 1214 if (strcmp(arg, "stream") == 0) 1215 sep->se_socktype = SOCK_STREAM; 1216 else if (strcmp(arg, "dgram") == 0) 1217 sep->se_socktype = SOCK_DGRAM; 1218 else if (strcmp(arg, "rdm") == 0) 1219 sep->se_socktype = SOCK_RDM; 1220 else if (strcmp(arg, "seqpacket") == 0) 1221 sep->se_socktype = SOCK_SEQPACKET; 1222 else if (strcmp(arg, "raw") == 0) 1223 sep->se_socktype = SOCK_RAW; 1224 else 1225 sep->se_socktype = -1; 1226 1227 sep->se_proto = newstr(sskip(&cp)); 1228 if (strcmp(sep->se_proto, "unix") == 0) { 1229 sep->se_family = AF_UNIX; 1230 } else { 1231 sep->se_family = AF_INET; 1232 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 1233 #ifdef RPC 1234 char *cp, *ccp; 1235 cp = strchr(sep->se_service, '/'); 1236 if (cp == 0) { 1237 syslog(LOG_ERR, "%s: no rpc version", 1238 sep->se_service); 1239 goto more; 1240 } 1241 *cp++ = '\0'; 1242 sep->se_rpcversl = sep->se_rpcversh = 1243 strtol(cp, &ccp, 0); 1244 if (ccp == cp) { 1245 badafterall: 1246 syslog(LOG_ERR, "%s/%s: bad rpc version", 1247 sep->se_service, cp); 1248 goto more; 1249 } 1250 if (*ccp == '-') { 1251 cp = ccp + 1; 1252 sep->se_rpcversh = strtol(cp, &ccp, 0); 1253 if (ccp == cp) 1254 goto badafterall; 1255 } 1256 #else 1257 syslog(LOG_ERR, "%s: rpc services not suported", 1258 sep->se_service); 1259 goto more; 1260 #endif /* RPC */ 1261 } 1262 } 1263 arg = sskip(&cp); 1264 { 1265 char *cp; 1266 cp = strchr(arg, '.'); 1267 if (cp) { 1268 *cp++ = '\0'; 1269 sep->se_max = atoi(cp); 1270 } else 1271 sep->se_max = TOOMANY; 1272 } 1273 sep->se_wait = strcmp(arg, "wait") == 0; 1274 if (ISMUX(sep)) { 1275 /* 1276 * Silently enforce "nowait" for TCPMUX services since 1277 * they don't have an assigned port to listen on. 1278 */ 1279 sep->se_wait = 0; 1280 1281 if (strcmp(sep->se_proto, "tcp")) { 1282 syslog(LOG_ERR, 1283 "%s: bad protocol for tcpmux service %s", 1284 CONFIG, sep->se_service); 1285 goto more; 1286 } 1287 if (sep->se_socktype != SOCK_STREAM) { 1288 syslog(LOG_ERR, 1289 "%s: bad socket type for tcpmux service %s", 1290 CONFIG, sep->se_service); 1291 goto more; 1292 } 1293 } 1294 sep->se_user = newstr(sskip(&cp)); 1295 if ((sep->se_group = strchr(sep->se_user, '.'))) 1296 *sep->se_group++ = '\0'; 1297 sep->se_server = newstr(sskip(&cp)); 1298 if (strcmp(sep->se_server, "internal") == 0) { 1299 struct biltin *bi; 1300 1301 for (bi = biltins; bi->bi_service; bi++) 1302 if (bi->bi_socktype == sep->se_socktype && 1303 strcmp(bi->bi_service, sep->se_service) == 0) 1304 break; 1305 if (bi->bi_service == 0) { 1306 syslog(LOG_ERR, "internal service %s unknown", 1307 sep->se_service); 1308 goto more; 1309 } 1310 sep->se_bi = bi; 1311 sep->se_wait = bi->bi_wait; 1312 } else 1313 sep->se_bi = NULL; 1314 argc = 0; 1315 for (arg = skip(&cp); cp; arg = skip(&cp)) { 1316 #if MULOG 1317 char *colon; 1318 1319 if (argc == 0 && (colon = strrchr(arg, ':'))) { 1320 while (arg < colon) { 1321 int x; 1322 char *ccp; 1323 1324 switch (*arg++) { 1325 case 'l': 1326 x = 1; 1327 if (isdigit(*arg)) { 1328 x = strtol(arg, &ccp, 0); 1329 if (ccp == arg) 1330 break; 1331 arg = ccp; 1332 } 1333 sep->se_log &= ~MULOG_RFC931; 1334 sep->se_log |= x; 1335 break; 1336 case 'a': 1337 sep->se_log |= MULOG_RFC931; 1338 break; 1339 default: 1340 break; 1341 } 1342 } 1343 arg = colon + 1; 1344 } 1345 #endif 1346 if (argc < MAXARGV) 1347 sep->se_argv[argc++] = newstr(arg); 1348 } 1349 while (argc <= MAXARGV) 1350 sep->se_argv[argc++] = NULL; 1351 return (sep); 1352 } 1353 1354 void 1355 freeconfig(cp) 1356 struct servtab *cp; 1357 { 1358 int i; 1359 1360 if (cp->se_hostaddr) 1361 free(cp->se_hostaddr); 1362 if (cp->se_service) 1363 free(cp->se_service); 1364 if (cp->se_proto) 1365 free(cp->se_proto); 1366 if (cp->se_user) 1367 free(cp->se_user); 1368 /* Note: se_group is part of the newstr'ed se_user */ 1369 if (cp->se_server) 1370 free(cp->se_server); 1371 for (i = 0; i < MAXARGV; i++) 1372 if (cp->se_argv[i]) 1373 free(cp->se_argv[i]); 1374 } 1375 1376 1377 /* 1378 * Safe skip - if skip returns null, log a syntax error in the 1379 * configuration file and exit. 1380 */ 1381 char * 1382 sskip(cpp) 1383 char **cpp; 1384 { 1385 char *cp; 1386 1387 cp = skip(cpp); 1388 if (cp == NULL) { 1389 syslog(LOG_ERR, "%s: syntax error", CONFIG); 1390 exit(-1); 1391 } 1392 return (cp); 1393 } 1394 1395 char * 1396 skip(cpp) 1397 char **cpp; 1398 { 1399 char *cp = *cpp; 1400 char *start; 1401 1402 if (*cpp == NULL) 1403 return ((char *)0); 1404 1405 again: 1406 while (*cp == ' ' || *cp == '\t') 1407 cp++; 1408 if (*cp == '\0') { 1409 int c; 1410 1411 c = getc(fconfig); 1412 (void) ungetc(c, fconfig); 1413 if (c == ' ' || c == '\t') 1414 if ((cp = nextline(fconfig))) 1415 goto again; 1416 *cpp = (char *)0; 1417 return ((char *)0); 1418 } 1419 start = cp; 1420 while (*cp && *cp != ' ' && *cp != '\t') 1421 cp++; 1422 if (*cp != '\0') 1423 *cp++ = '\0'; 1424 *cpp = cp; 1425 return (start); 1426 } 1427 1428 char * 1429 nextline(fd) 1430 FILE *fd; 1431 { 1432 char *cp; 1433 1434 if (fgets(line, sizeof (line), fd) == NULL) 1435 return ((char *)0); 1436 cp = strchr(line, '\n'); 1437 if (cp) 1438 *cp = '\0'; 1439 return (line); 1440 } 1441 1442 char * 1443 newstr(cp) 1444 char *cp; 1445 { 1446 if ((cp = strdup(cp ? cp : ""))) 1447 return (cp); 1448 syslog(LOG_ERR, "strdup: %m"); 1449 exit(-1); 1450 } 1451 1452 void 1453 inetd_setproctitle(a, s) 1454 char *a; 1455 int s; 1456 { 1457 int size; 1458 char *cp; 1459 struct sockaddr_in sin; 1460 char buf[80]; 1461 1462 cp = Argv[0]; 1463 size = sizeof(sin); 1464 if (getpeername(s, (struct sockaddr *)&sin, &size) == 0) 1465 (void)snprintf(buf, sizeof buf, "-%s [%s]", a, 1466 inet_ntoa(sin.sin_addr)); 1467 else 1468 (void)snprintf(buf, sizeof buf, "-%s", a); 1469 strncpy(cp, buf, LastArg - cp); 1470 cp += strlen(cp); 1471 while (cp < LastArg) 1472 *cp++ = ' '; 1473 } 1474 1475 void 1476 logpid() 1477 { 1478 FILE *fp; 1479 1480 if ((fp = fopen(_PATH_INETDPID, "w")) != NULL) { 1481 fprintf(fp, "%u\n", getpid()); 1482 (void)fclose(fp); 1483 } 1484 } 1485 1486 void 1487 bump_nofile() 1488 { 1489 #ifdef RLIMIT_NOFILE 1490 1491 #define FD_CHUNK 32 1492 1493 struct rlimit rl; 1494 1495 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1496 syslog(LOG_ERR, "getrlimit: %m"); 1497 return; 1498 } 1499 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK); 1500 if (rl.rlim_cur <= rlim_ofile_cur) { 1501 syslog(LOG_ERR, 1502 "bump_nofile: cannot extend file limit, max = %d", 1503 (int)rl.rlim_cur); 1504 return; 1505 } 1506 1507 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { 1508 syslog(LOG_ERR, "setrlimit: %m"); 1509 return; 1510 } 1511 1512 rlim_ofile_cur = rl.rlim_cur; 1513 return; 1514 1515 #else 1516 syslog(LOG_ERR, "bump_nofile: cannot extend file limit"); 1517 return; 1518 #endif 1519 } 1520 1521 /* 1522 * Internet services provided internally by inetd: 1523 */ 1524 #define BUFSIZE 4096 1525 1526 /* ARGSUSED */ 1527 void 1528 echo_stream(s, sep) /* Echo service -- echo data back */ 1529 int s; 1530 struct servtab *sep; 1531 { 1532 char buffer[BUFSIZE]; 1533 int i; 1534 1535 inetd_setproctitle(sep->se_service, s); 1536 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1537 write(s, buffer, i) > 0) 1538 ; 1539 } 1540 1541 /* ARGSUSED */ 1542 void 1543 echo_dg(s, sep) /* Echo service -- echo data back */ 1544 int s; 1545 struct servtab *sep; 1546 { 1547 char buffer[BUFSIZE]; 1548 int i, size; 1549 struct sockaddr sa; 1550 1551 size = sizeof(sa); 1552 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0) 1553 return; 1554 (void) sendto(s, buffer, i, 0, &sa, sizeof(sa)); 1555 } 1556 1557 /* ARGSUSED */ 1558 void 1559 discard_stream(s, sep) /* Discard service -- ignore data */ 1560 int s; 1561 struct servtab *sep; 1562 { 1563 char buffer[BUFSIZE]; 1564 1565 inetd_setproctitle(sep->se_service, s); 1566 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || 1567 errno == EINTR) 1568 ; 1569 } 1570 1571 /* ARGSUSED */ 1572 void 1573 discard_dg(s, sep) /* Discard service -- ignore data */ 1574 int s; 1575 struct servtab *sep; 1576 { 1577 char buffer[BUFSIZE]; 1578 1579 (void) read(s, buffer, sizeof(buffer)); 1580 } 1581 1582 #include <ctype.h> 1583 #define LINESIZ 72 1584 char ring[128]; 1585 char *endring; 1586 1587 void 1588 initring() 1589 { 1590 int i; 1591 1592 endring = ring; 1593 1594 for (i = 0; i <= 128; ++i) 1595 if (isprint(i)) 1596 *endring++ = i; 1597 } 1598 1599 /* ARGSUSED */ 1600 void 1601 chargen_stream(s, sep) /* Character generator */ 1602 int s; 1603 struct servtab *sep; 1604 { 1605 int len; 1606 char *rs, text[LINESIZ+2]; 1607 1608 inetd_setproctitle(sep->se_service, s); 1609 1610 if (!endring) { 1611 initring(); 1612 rs = ring; 1613 } 1614 1615 text[LINESIZ] = '\r'; 1616 text[LINESIZ + 1] = '\n'; 1617 for (rs = ring;;) { 1618 if ((len = endring - rs) >= LINESIZ) 1619 memmove(text, rs, LINESIZ); 1620 else { 1621 memmove(text, rs, len); 1622 memmove(text + len, ring, LINESIZ - len); 1623 } 1624 if (++rs == endring) 1625 rs = ring; 1626 if (write(s, text, sizeof(text)) != sizeof(text)) 1627 break; 1628 } 1629 } 1630 1631 /* ARGSUSED */ 1632 void 1633 chargen_dg(s, sep) /* Character generator */ 1634 int s; 1635 struct servtab *sep; 1636 { 1637 struct sockaddr sa; 1638 static char *rs; 1639 int len, size; 1640 char text[LINESIZ+2]; 1641 1642 if (endring == 0) { 1643 initring(); 1644 rs = ring; 1645 } 1646 1647 size = sizeof(sa); 1648 if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0) 1649 return; 1650 1651 if ((len = endring - rs) >= LINESIZ) 1652 memmove(text, rs, LINESIZ); 1653 else { 1654 memmove(text, rs, len); 1655 memmove(text + len, ring, LINESIZ - len); 1656 } 1657 if (++rs == endring) 1658 rs = ring; 1659 text[LINESIZ] = '\r'; 1660 text[LINESIZ + 1] = '\n'; 1661 (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa)); 1662 } 1663 1664 /* 1665 * Return a machine readable date and time, in the form of the 1666 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1667 * returns the number of seconds since midnight, Jan 1, 1970, 1668 * we must add 2208988800 seconds to this figure to make up for 1669 * some seventy years Bell Labs was asleep. 1670 */ 1671 1672 long 1673 machtime() 1674 { 1675 struct timeval tv; 1676 1677 if (gettimeofday(&tv, (struct timezone *)0) < 0) { 1678 if (debug) 1679 fprintf(stderr, "Unable to get time of day\n"); 1680 return (0L); 1681 } 1682 #define OFFSET ((u_long)25567 * 24*60*60) 1683 return (htonl((long)(tv.tv_sec + OFFSET))); 1684 #undef OFFSET 1685 } 1686 1687 /* ARGSUSED */ 1688 void 1689 machtime_stream(s, sep) 1690 int s; 1691 struct servtab *sep; 1692 { 1693 long result; 1694 1695 result = machtime(); 1696 (void) write(s, (char *) &result, sizeof(result)); 1697 } 1698 1699 /* ARGSUSED */ 1700 void 1701 machtime_dg(s, sep) 1702 int s; 1703 struct servtab *sep; 1704 { 1705 long result; 1706 struct sockaddr sa; 1707 int size; 1708 1709 size = sizeof(sa); 1710 if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0) 1711 return; 1712 result = machtime(); 1713 (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa)); 1714 } 1715 1716 /* ARGSUSED */ 1717 void 1718 daytime_stream(s, sep) /* Return human-readable time of day */ 1719 int s; 1720 struct servtab *sep; 1721 { 1722 char buffer[256]; 1723 time_t clock; 1724 int len; 1725 1726 clock = time((time_t *) 0); 1727 1728 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 1729 (void) write(s, buffer, len); 1730 } 1731 1732 /* ARGSUSED */ 1733 void 1734 daytime_dg(s, sep) /* Return human-readable time of day */ 1735 int s; 1736 struct servtab *sep; 1737 { 1738 char buffer[256]; 1739 time_t clock; 1740 struct sockaddr sa; 1741 int size, len; 1742 1743 clock = time((time_t *) 0); 1744 1745 size = sizeof(sa); 1746 if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0) 1747 return; 1748 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 1749 (void) sendto(s, buffer, len, 0, &sa, sizeof(sa)); 1750 } 1751 1752 /* 1753 * print_service: 1754 * Dump relevant information to stderr 1755 */ 1756 void 1757 print_service(action, sep) 1758 char *action; 1759 struct servtab *sep; 1760 { 1761 if (isrpcservice(sep)) 1762 fprintf(stderr, 1763 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%d, user.group=%s.%s builtin=%lx server=%s\n", 1764 action, sep->se_service, 1765 sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto, 1766 sep->se_wait, sep->se_max, sep->se_user, sep->se_group, 1767 (long)sep->se_bi, sep->se_server); 1768 else 1769 fprintf(stderr, 1770 "%s: %s proto=%s, wait.max=%d.%d, user.group=%s.%s builtin=%lx server=%s\n", 1771 action, sep->se_service, sep->se_proto, 1772 sep->se_wait, sep->se_max, sep->se_user, sep->se_group, 1773 (long)sep->se_bi, sep->se_server); 1774 } 1775 1776 void 1777 usage() 1778 { 1779 1780 #ifdef LIBWRAP 1781 (void)fprintf(stderr, "usage: %s [-dl] [conf]\n", __progname); 1782 #else 1783 (void)fprintf(stderr, "usage: %s [-d] [conf]\n", __progname); 1784 #endif 1785 exit(1); 1786 } 1787 1788 1789 /* 1790 * Based on TCPMUX.C by Mark K. Lottor November 1988 1791 * sri-nic::ps:<mkl>tcpmux.c 1792 */ 1793 1794 static int /* # of characters upto \r,\n or \0 */ 1795 getline(fd, buf, len) 1796 int fd; 1797 char *buf; 1798 int len; 1799 { 1800 int count = 0, n; 1801 1802 do { 1803 n = read(fd, buf, len-count); 1804 if (n == 0) 1805 return (count); 1806 if (n < 0) 1807 return (-1); 1808 while (--n >= 0) { 1809 if (*buf == '\r' || *buf == '\n' || *buf == '\0') 1810 return (count); 1811 count++; 1812 buf++; 1813 } 1814 } while (count < len); 1815 return (count); 1816 } 1817 1818 #define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */ 1819 1820 #define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1) 1821 1822 void 1823 tcpmux(ctrl, sep) 1824 int ctrl; 1825 struct servtab *sep; 1826 { 1827 char service[MAX_SERV_LEN+1]; 1828 int len; 1829 1830 /* Get requested service name */ 1831 if ((len = getline(ctrl, service, MAX_SERV_LEN)) < 0) { 1832 strwrite(ctrl, "-Error reading service name\r\n"); 1833 goto reject; 1834 } 1835 service[len] = '\0'; 1836 1837 if (debug) 1838 fprintf(stderr, "tcpmux: someone wants %s\n", service); 1839 1840 /* 1841 * Help is a required command, and lists available services, 1842 * one per line. 1843 */ 1844 if (!strcasecmp(service, "help")) { 1845 strwrite(ctrl, "+Available services:\r\n"); 1846 strwrite(ctrl, "help\r\n"); 1847 for (sep = servtab; sep; sep = sep->se_next) { 1848 if (!ISMUX(sep)) 1849 continue; 1850 (void)write(ctrl, sep->se_service, 1851 strlen(sep->se_service)); 1852 strwrite(ctrl, "\r\n"); 1853 } 1854 goto reject; 1855 } 1856 1857 /* Try matching a service in inetd.conf with the request */ 1858 for (sep = servtab; sep; sep = sep->se_next) { 1859 if (!ISMUX(sep)) 1860 continue; 1861 if (!strcasecmp(service, sep->se_service)) { 1862 if (ISMUXPLUS(sep)) 1863 strwrite(ctrl, "+Go\r\n"); 1864 run_service(ctrl, sep); 1865 return; 1866 } 1867 } 1868 strwrite(ctrl, "-Service not available\r\n"); 1869 reject: 1870 _exit(1); 1871 } 1872 1873 1874 #ifdef MULOG 1875 dolog(sep, ctrl) 1876 struct servtab *sep; 1877 int ctrl; 1878 { 1879 struct sockaddr sa; 1880 struct sockaddr_in *sin = (struct sockaddr_in *)&sa; 1881 int len = sizeof(sa); 1882 struct hostent *hp; 1883 char *host, *dp, buf[BUFSIZ], *rfc931_name(); 1884 int connected = 1; 1885 1886 if (sep->se_family != AF_INET) 1887 return; 1888 1889 if (getpeername(ctrl, &sa, &len) < 0) { 1890 if (errno != ENOTCONN) { 1891 syslog(LOG_ERR, "getpeername: %m"); 1892 return; 1893 } 1894 if (recvfrom(ctrl, buf, sizeof(buf), MSG_PEEK, &sa, &len) < 0) { 1895 syslog(LOG_ERR, "recvfrom: %m"); 1896 return; 1897 } 1898 connected = 0; 1899 } 1900 if (sa.sa_family != AF_INET) { 1901 syslog(LOG_ERR, "unexpected address family %u", sa.sa_family); 1902 return; 1903 } 1904 1905 hp = gethostbyaddr((char *) &sin->sin_addr.s_addr, 1906 sizeof (sin->sin_addr.s_addr), AF_INET); 1907 1908 host = hp?hp->h_name:inet_ntoa(sin->sin_addr); 1909 1910 switch (sep->se_log & ~MULOG_RFC931) { 1911 case 0: 1912 return; 1913 case 1: 1914 if (curdom == NULL || *curdom == '\0') 1915 break; 1916 dp = host + strlen(host) - strlen(curdom); 1917 if (dp < host) 1918 break; 1919 if (debug) 1920 fprintf(stderr, "check \"%s\" against curdom \"%s\"\n", 1921 host, curdom); 1922 if (strcasecmp(dp, curdom) == 0) 1923 return; 1924 break; 1925 case 2: 1926 default: 1927 break; 1928 } 1929 1930 openlog("", LOG_NOWAIT, MULOG); 1931 1932 if (connected && (sep->se_log & MULOG_RFC931)) 1933 syslog(LOG_INFO, "%s@%s wants %s", 1934 rfc931_name(sin, ctrl), host, sep->se_service); 1935 else 1936 syslog(LOG_INFO, "%s wants %s", 1937 host, sep->se_service); 1938 } 1939 1940 /* 1941 * From tcp_log by 1942 * Wietse Venema, Eindhoven University of Technology, The Netherlands. 1943 */ 1944 #if 0 1945 static char sccsid[] = "@(#) rfc931.c 1.3 92/08/31 22:54:46"; 1946 #endif 1947 1948 #include <setjmp.h> 1949 1950 #define RFC931_PORT 113 /* Semi-well-known port */ 1951 #define TIMEOUT 4 1952 #define TIMEOUT2 10 1953 1954 static jmp_buf timebuf; 1955 1956 /* timeout - handle timeouts */ 1957 1958 static void timeout(sig) 1959 int sig; 1960 { 1961 longjmp(timebuf, sig); 1962 } 1963 1964 /* rfc931_name - return remote user name */ 1965 1966 char * 1967 rfc931_name(there, ctrl) 1968 struct sockaddr_in *there; /* remote link information */ 1969 int ctrl; 1970 { 1971 struct sockaddr_in here; /* local link information */ 1972 struct sockaddr_in sin; /* for talking to RFC931 daemon */ 1973 int length; 1974 int s; 1975 unsigned remote; 1976 unsigned local; 1977 static char user[256]; /* XXX */ 1978 char buf[256]; 1979 char *cp; 1980 char *result = "USER_UNKNOWN"; 1981 int len; 1982 1983 /* Find out local port number of our stdin. */ 1984 1985 length = sizeof(here); 1986 if (getsockname(ctrl, (struct sockaddr *) &here, &length) == -1) { 1987 syslog(LOG_ERR, "getsockname: %m"); 1988 return (result); 1989 } 1990 /* Set up timer so we won't get stuck. */ 1991 1992 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 1993 syslog(LOG_ERR, "socket: %m"); 1994 return (result); 1995 } 1996 1997 sin = here; 1998 sin.sin_port = htons(0); 1999 if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { 2000 syslog(LOG_ERR, "bind: %m"); 2001 return (result); 2002 } 2003 2004 signal(SIGALRM, timeout); 2005 if (setjmp(timebuf)) { 2006 close(s); /* not: fclose(fp) */ 2007 return (result); 2008 } 2009 alarm(TIMEOUT); 2010 2011 /* Connect to the RFC931 daemon. */ 2012 2013 sin = *there; 2014 sin.sin_port = htons(RFC931_PORT); 2015 if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { 2016 close(s); 2017 alarm(0); 2018 return (result); 2019 } 2020 2021 /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */ 2022 (void)snprintf(buf, sizeof buf, "%u,%u\r\n", ntohs(there->sin_port), 2023 ntohs(here.sin_port)); 2024 2025 2026 for (len = 0, cp = buf; len < strlen(buf); ) { 2027 int n; 2028 2029 if ((n = write(s, cp, strlen(buf) - len)) == -1) { 2030 close(s); 2031 alarm(0); 2032 return (result); 2033 } 2034 cp += n; 2035 len += n; 2036 } 2037 2038 /* Read response */ 2039 for (cp = buf; cp < buf + sizeof(buf) - 1; ) { 2040 char c; 2041 if (read(s, &c, 1) != 1) { 2042 close(s); 2043 alarm(0); 2044 return (result); 2045 } 2046 if (c == '\n') 2047 break; 2048 *cp++ = c; 2049 } 2050 *cp = '\0'; 2051 2052 if (sscanf(buf, "%u , %u : USERID :%*[^:]:%255s", &remote, &local, user) == 3 2053 && ntohs(there->sin_port) == remote 2054 && ntohs(here.sin_port) == local) { 2055 2056 /* Strip trailing carriage return. */ 2057 if (cp = strchr(user, '\r')) 2058 *cp = 0; 2059 result = user; 2060 } 2061 2062 alarm(0); 2063 close(s); 2064 return (result); 2065 } 2066 #endif 2067