1 /* $NetBSD: inetd.c,v 1.36 1997/10/05 16:40:25 mrg 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.36 1997/10/05 16:40:25 mrg 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 )) != EOF) 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 < 0 && errno != EINTR) 471 syslog(LOG_WARNING, "select: %m"); 472 sleep(1); 473 continue; 474 } 475 for (sep = servtab; n && sep; sep = nsep) { 476 nsep = sep->se_next; 477 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) { 478 n--; 479 if (debug) 480 fprintf(stderr, "someone wants %s\n", sep->se_service); 481 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 482 /* XXX here do the libwrap check-before-accept */ 483 ctrl = accept(sep->se_fd, (struct sockaddr *)0, 484 (int *)0); 485 if (debug) 486 fprintf(stderr, "accept, ctrl %d\n", ctrl); 487 if (ctrl < 0) { 488 if (errno != EINTR) 489 syslog(LOG_WARNING, 490 "accept (for %s): %m", 491 sep->se_service); 492 continue; 493 } 494 } else 495 ctrl = sep->se_fd; 496 (void) sigblock(SIGBLOCK); 497 pid = 0; 498 #ifdef LIBWRAP_INTERNAL 499 dofork = 1; 500 #else 501 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); 502 #endif 503 if (dofork) { 504 if (sep->se_count++ == 0) 505 (void)gettimeofday(&sep->se_time, 506 (struct timezone *)0); 507 else if (sep->se_count >= sep->se_max) { 508 struct timeval now; 509 510 (void)gettimeofday(&now, (struct timezone *)0); 511 if (now.tv_sec - sep->se_time.tv_sec > 512 CNT_INTVL) { 513 sep->se_time = now; 514 sep->se_count = 1; 515 } else { 516 syslog(LOG_ERR, 517 "%s/%s server failing (looping), service terminated\n", 518 sep->se_service, sep->se_proto); 519 close_sep(sep); 520 sigsetmask(0L); 521 if (!timingout) { 522 timingout = 1; 523 alarm(RETRYTIME); 524 } 525 continue; 526 } 527 } 528 pid = fork(); 529 if (pid < 0) { 530 syslog(LOG_ERR, "fork: %m"); 531 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 532 close(ctrl); 533 sigsetmask(0L); 534 sleep(1); 535 continue; 536 } 537 if (pid != 0 && sep->se_wait) { 538 sep->se_wait = pid; 539 FD_CLR(sep->se_fd, &allsock); 540 nsock--; 541 } 542 if (pid == 0 && debug) 543 setsid(); 544 } 545 sigsetmask(0L); 546 if (pid == 0) { 547 run_service(ctrl, sep); 548 if (dofork) 549 exit(0); 550 } 551 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 552 close(ctrl); 553 } 554 } 555 } 556 } 557 558 void 559 run_service(ctrl, sep) 560 int ctrl; 561 struct servtab *sep; 562 { 563 struct passwd *pwd; 564 struct group *grp = NULL; /* XXX gcc */ 565 #ifdef LIBWRAP 566 struct request_info req; 567 int denied; 568 char buf[7], *service = NULL; /* XXX gcc */ 569 #endif 570 571 #ifdef LIBWRAP 572 #ifndef LIBWRAP_INTERNAL 573 if (sep->se_bi == 0) 574 #endif 575 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 576 request_init(&req, RQ_DAEMON, sep->se_argv[0] ? 577 sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL); 578 fromhost(&req); 579 denied = !hosts_access(&req); 580 if (denied || lflag) { 581 sp = getservbyport(sep->se_ctrladdr_in.sin_port, 582 sep->se_proto); 583 if (sp == NULL) { 584 (void)snprintf(buf, sizeof buf, "%d", 585 ntohs(sep->se_ctrladdr_in.sin_port)); 586 service = buf; 587 } else 588 service = sp->s_name; 589 } 590 if (denied) { 591 syslog(deny_severity, 592 "refused connection from %.500s, service %s (%s)", 593 eval_client(&req), service, sep->se_proto); 594 goto reject; 595 } 596 if (lflag) { 597 syslog(allow_severity, 598 "connection from %.500s, service %s (%s)", 599 eval_client(&req), service, sep->se_proto); 600 } 601 } 602 #endif /* LIBWRAP */ 603 604 if (sep->se_bi) { 605 (*sep->se_bi->bi_fn)(ctrl, sep); 606 } else { 607 if ((pwd = getpwnam(sep->se_user)) == NULL) { 608 syslog(LOG_ERR, "%s/%s: %s: No such user", 609 sep->se_service, sep->se_proto, sep->se_user); 610 goto reject; 611 } 612 if (sep->se_group && 613 (grp = getgrnam(sep->se_group)) == NULL) { 614 syslog(LOG_ERR, "%s/%s: %s: No such group", 615 sep->se_service, sep->se_proto, sep->se_group); 616 goto reject; 617 } 618 if (pwd->pw_uid) { 619 if (sep->se_group) 620 pwd->pw_gid = grp->gr_gid; 621 if (setgid(pwd->pw_gid) < 0) { 622 syslog(LOG_ERR, 623 "%s/%s: can't set gid %d: %m", sep->se_service, 624 sep->se_proto, pwd->pw_gid); 625 goto reject; 626 } 627 (void) initgroups(pwd->pw_name, 628 pwd->pw_gid); 629 if (setuid(pwd->pw_uid) < 0) { 630 syslog(LOG_ERR, 631 "%s/%s: can't set uid %d: %m", sep->se_service, 632 sep->se_proto, pwd->pw_uid); 633 goto reject; 634 } 635 } else if (sep->se_group) { 636 (void) setgid((gid_t)grp->gr_gid); 637 } 638 if (debug) 639 fprintf(stderr, "%d execl %s\n", 640 getpid(), sep->se_server); 641 #ifdef MULOG 642 if (sep->se_log) 643 dolog(sep, ctrl); 644 #endif 645 /* Set our control descriptor to not close-on-exec... */ 646 if (fcntl(ctrl, F_SETFD, 0) < 0) 647 syslog(LOG_ERR, "fcntl (F_SETFD, 0): %m"); 648 /* ...and dup it to stdin, stdout, and stderr. */ 649 if (ctrl != 0) { 650 dup2(ctrl, 0); 651 close(ctrl); 652 ctrl = 0; 653 } 654 dup2(0, 1); 655 dup2(0, 2); 656 #ifdef RLIMIT_NOFILE 657 if (rlim_ofile.rlim_cur != rlim_ofile_cur && 658 setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) 659 syslog(LOG_ERR, "setrlimit: %m"); 660 #endif 661 execv(sep->se_server, sep->se_argv); 662 syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server); 663 reject: 664 if (sep->se_socktype != SOCK_STREAM) 665 recv(ctrl, buf, sizeof (buf), 0); 666 _exit(1); 667 } 668 } 669 670 void 671 reapchild(signo) 672 int signo; 673 { 674 int status; 675 pid_t pid; 676 struct servtab *sep; 677 678 for (;;) { 679 pid = wait3(&status, WNOHANG, (struct rusage *)0); 680 if (pid <= 0) 681 break; 682 if (debug) 683 fprintf(stderr, "%d reaped, status %#x\n", 684 pid, status); 685 for (sep = servtab; sep; sep = sep->se_next) 686 if (sep->se_wait == pid) { 687 if (WIFEXITED(status) && WEXITSTATUS(status)) 688 syslog(LOG_WARNING, 689 "%s: exit status 0x%x", 690 sep->se_server, WEXITSTATUS(status)); 691 else if (WIFSIGNALED(status)) 692 syslog(LOG_WARNING, 693 "%s: exit signal 0x%x", 694 sep->se_server, WTERMSIG(status)); 695 sep->se_wait = 1; 696 FD_SET(sep->se_fd, &allsock); 697 nsock++; 698 if (debug) 699 fprintf(stderr, "restored %s, fd %d\n", 700 sep->se_service, sep->se_fd); 701 } 702 } 703 } 704 705 void 706 config(signo) 707 int signo; 708 { 709 struct servtab *sep, *cp, **sepp; 710 long omask; 711 int n; 712 713 if (!setconfig()) { 714 syslog(LOG_ERR, "%s: %m", CONFIG); 715 return; 716 } 717 for (sep = servtab; sep; sep = sep->se_next) 718 sep->se_checked = 0; 719 while ((cp = getconfigent())) { 720 for (sep = servtab; sep; sep = sep->se_next) 721 if (strcmp(sep->se_service, cp->se_service) == 0 && 722 strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 && 723 strcmp(sep->se_proto, cp->se_proto) == 0 && 724 ISMUX(sep) == ISMUX(cp)) 725 break; 726 if (sep != 0) { 727 int i; 728 729 #define SWAP(type, a, b) {type c=(type)a; (type)a=(type)b; (type)b=(type)c;} 730 731 omask = sigblock(SIGBLOCK); 732 /* 733 * sep->se_wait may be holding the pid of a daemon 734 * that we're waiting for. If so, don't overwrite 735 * it unless the config file explicitly says don't 736 * wait. 737 */ 738 if (cp->se_bi == 0 && 739 (sep->se_wait == 1 || cp->se_wait == 0)) 740 sep->se_wait = cp->se_wait; 741 SWAP(char *, sep->se_user, cp->se_user); 742 SWAP(char *, sep->se_group, cp->se_group); 743 SWAP(char *, sep->se_server, cp->se_server); 744 for (i = 0; i < MAXARGV; i++) 745 SWAP(char *, sep->se_argv[i], cp->se_argv[i]); 746 SWAP(int, cp->se_type, sep->se_type); 747 SWAP(int, cp->se_max, sep->se_max); 748 #undef SWAP 749 if (isrpcservice(sep)) 750 unregister_rpc(sep); 751 sep->se_rpcversl = cp->se_rpcversl; 752 sep->se_rpcversh = cp->se_rpcversh; 753 sigsetmask(omask); 754 freeconfig(cp); 755 if (debug) 756 print_service("REDO", sep); 757 } else { 758 sep = enter(cp); 759 if (debug) 760 print_service("ADD ", sep); 761 } 762 sep->se_checked = 1; 763 764 switch (sep->se_family) { 765 case AF_UNIX: 766 if (sep->se_fd != -1) 767 break; 768 (void)unlink(sep->se_service); 769 n = strlen(sep->se_service); 770 if (n > sizeof(sep->se_ctrladdr_un.sun_path) - 1) 771 n = sizeof(sep->se_ctrladdr_un.sun_path) - 1; 772 strncpy(sep->se_ctrladdr_un.sun_path, 773 sep->se_service, n); 774 sep->se_ctrladdr_un.sun_family = AF_UNIX; 775 sep->se_ctrladdr_size = n + 776 sizeof(sep->se_ctrladdr_un) - 777 sizeof(sep->se_ctrladdr_un.sun_path); 778 if (!ISMUX(sep)) 779 setup(sep); 780 break; 781 case AF_INET: 782 sep->se_ctrladdr_in.sin_family = AF_INET; 783 if (!strcmp(sep->se_hostaddr,"*")) 784 sep->se_ctrladdr_in.sin_addr.s_addr = 785 INADDR_ANY; 786 else if (!inet_aton(sep->se_hostaddr, 787 &sep->se_ctrladdr_in.sin_addr)) { 788 /* Do we really want to support hostname lookups here? */ 789 struct hostent *hp; 790 hp = gethostbyname(sep->se_hostaddr); 791 if (hp == 0) { 792 syslog(LOG_ERR, "%s: unknown host", 793 sep->se_hostaddr); 794 sep->se_checked = 0; 795 continue; 796 } else if (hp->h_addrtype != AF_INET) { 797 syslog(LOG_ERR, 798 "%s: address isn't an Internet address", 799 sep->se_hostaddr); 800 sep->se_checked = 0; 801 continue; 802 } else if (hp->h_length != sizeof(struct in_addr)) { 803 syslog(LOG_ERR, 804 "%s: address size wrong (under DNS corruption attack?)", 805 sep->se_hostaddr); 806 sep->se_checked = 0; 807 continue; 808 } else { 809 memcpy(&sep->se_ctrladdr_in.sin_addr, 810 hp->h_addr_list[0], 811 sizeof(struct in_addr)); 812 } 813 } 814 if (ISMUX(sep)) { 815 sep->se_fd = -1; 816 continue; 817 } 818 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr_in); 819 if (isrpcservice(sep)) { 820 struct rpcent *rp; 821 822 sep->se_rpcprog = atoi(sep->se_service); 823 if (sep->se_rpcprog == 0) { 824 rp = getrpcbyname(sep->se_service); 825 if (rp == 0) { 826 syslog(LOG_ERR, 827 "%s/%s: unknown service", 828 sep->se_service, 829 sep->se_proto); 830 sep->se_checked = 0; 831 continue; 832 } 833 sep->se_rpcprog = rp->r_number; 834 } 835 if (sep->se_fd == -1 && !ISMUX(sep)) 836 setup(sep); 837 if (sep->se_fd != -1) 838 register_rpc(sep); 839 } else { 840 u_short port = htons(atoi(sep->se_service)); 841 842 if (!port) { 843 sp = getservbyname(sep->se_service, 844 sep->se_proto); 845 if (sp == 0) { 846 syslog(LOG_ERR, 847 "%s/%s: unknown service", 848 sep->se_service, 849 sep->se_proto); 850 sep->se_checked = 0; 851 continue; 852 } 853 port = sp->s_port; 854 } 855 if (port != sep->se_ctrladdr_in.sin_port) { 856 sep->se_ctrladdr_in.sin_port = port; 857 if (sep->se_fd >= 0) 858 close_sep(sep); 859 } 860 if (sep->se_fd == -1 && !ISMUX(sep)) 861 setup(sep); 862 } 863 } 864 } 865 endconfig(); 866 /* 867 * Purge anything not looked at above. 868 */ 869 omask = sigblock(SIGBLOCK); 870 sepp = &servtab; 871 while ((sep = *sepp)) { 872 if (sep->se_checked) { 873 sepp = &sep->se_next; 874 continue; 875 } 876 *sepp = sep->se_next; 877 if (sep->se_fd >= 0) 878 close_sep(sep); 879 if (isrpcservice(sep)) 880 unregister_rpc(sep); 881 if (sep->se_family == AF_UNIX) 882 (void)unlink(sep->se_service); 883 if (debug) 884 print_service("FREE", sep); 885 freeconfig(sep); 886 free((char *)sep); 887 } 888 (void) sigsetmask(omask); 889 } 890 891 void 892 retry(signo) 893 int signo; 894 { 895 struct servtab *sep; 896 897 timingout = 0; 898 for (sep = servtab; sep; sep = sep->se_next) { 899 if (sep->se_fd == -1 && !ISMUX(sep)) { 900 switch (sep->se_family) { 901 case AF_UNIX: 902 case AF_INET: 903 setup(sep); 904 if (sep->se_fd != -1 && isrpcservice(sep)) 905 register_rpc(sep); 906 break; 907 } 908 } 909 } 910 } 911 912 void 913 goaway(signo) 914 int signo; 915 { 916 struct servtab *sep; 917 918 for (sep = servtab; sep; sep = sep->se_next) { 919 if (sep->se_fd == -1) 920 continue; 921 922 switch (sep->se_family) { 923 case AF_UNIX: 924 (void)unlink(sep->se_service); 925 break; 926 case AF_INET: 927 if (sep->se_wait == 1 && isrpcservice(sep)) 928 unregister_rpc(sep); 929 break; 930 } 931 (void)close(sep->se_fd); 932 } 933 (void)unlink(_PATH_INETDPID); 934 exit(0); 935 } 936 937 void 938 setup(sep) 939 struct servtab *sep; 940 { 941 int on = 1; 942 943 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { 944 if (debug) 945 fprintf(stderr, "socket failed on %s/%s: %s\n", 946 sep->se_service, sep->se_proto, strerror(errno)); 947 syslog(LOG_ERR, "%s/%s: socket: %m", 948 sep->se_service, sep->se_proto); 949 return; 950 } 951 /* Set all listening sockets to close-on-exec. */ 952 if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) 953 syslog(LOG_ERR, "fcntl (F_SETFD, FD_CLOEXEC): %m"); 954 #define turnon(fd, opt) \ 955 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) 956 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && 957 turnon(sep->se_fd, SO_DEBUG) < 0) 958 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 959 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 960 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 961 #undef turnon 962 if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) { 963 if (debug) 964 fprintf(stderr, "bind failed on %s/%s: %s\n", 965 sep->se_service, sep->se_proto, strerror(errno)); 966 syslog(LOG_ERR, "%s/%s: bind: %m", 967 sep->se_service, sep->se_proto); 968 (void) close(sep->se_fd); 969 sep->se_fd = -1; 970 if (!timingout) { 971 timingout = 1; 972 alarm(RETRYTIME); 973 } 974 return; 975 } 976 if (sep->se_socktype == SOCK_STREAM) 977 listen(sep->se_fd, 10); 978 979 FD_SET(sep->se_fd, &allsock); 980 nsock++; 981 if (sep->se_fd > maxsock) { 982 maxsock = sep->se_fd; 983 if (maxsock > rlim_ofile_cur - FD_MARGIN) 984 bump_nofile(); 985 } 986 if (debug) 987 fprintf(stderr, "registered %s on %d\n", 988 sep->se_server, sep->se_fd); 989 } 990 991 /* 992 * Finish with a service and its socket. 993 */ 994 void 995 close_sep(sep) 996 struct servtab *sep; 997 { 998 if (sep->se_fd >= 0) { 999 nsock--; 1000 FD_CLR(sep->se_fd, &allsock); 1001 (void) close(sep->se_fd); 1002 sep->se_fd = -1; 1003 } 1004 sep->se_count = 0; 1005 /* 1006 * Don't keep the pid of this running deamon: when reapchild() 1007 * reaps this pid, it would erroneously increment nsock. 1008 */ 1009 if (sep->se_wait > 1) 1010 sep->se_wait = 1; 1011 } 1012 1013 void 1014 register_rpc(sep) 1015 struct servtab *sep; 1016 { 1017 #ifdef RPC 1018 int n; 1019 struct sockaddr_in sin; 1020 struct protoent *pp; 1021 1022 if ((pp = getprotobyname(sep->se_proto+4)) == NULL) { 1023 syslog(LOG_ERR, "%s: getproto: %m", 1024 sep->se_proto); 1025 return; 1026 } 1027 n = sizeof sin; 1028 if (getsockname(sep->se_fd, (struct sockaddr *)&sin, &n) < 0) { 1029 syslog(LOG_ERR, "%s/%s: getsockname: %m", 1030 sep->se_service, sep->se_proto); 1031 return; 1032 } 1033 1034 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1035 if (debug) 1036 fprintf(stderr, "pmap_set: %u %u %u %u\n", 1037 sep->se_rpcprog, n, pp->p_proto, 1038 ntohs(sin.sin_port)); 1039 (void)pmap_unset(sep->se_rpcprog, n); 1040 if (!pmap_set(sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port))) 1041 syslog(LOG_ERR, "pmap_set: %u %u %u %u: %m", 1042 sep->se_rpcprog, n, pp->p_proto, 1043 ntohs(sin.sin_port)); 1044 } 1045 #endif /* RPC */ 1046 } 1047 1048 void 1049 unregister_rpc(sep) 1050 struct servtab *sep; 1051 { 1052 #ifdef RPC 1053 int n; 1054 1055 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1056 if (debug) 1057 fprintf(stderr, "pmap_unset(%u, %u)\n", 1058 sep->se_rpcprog, n); 1059 if (!pmap_unset(sep->se_rpcprog, n)) 1060 syslog(LOG_ERR, "pmap_unset(%u, %u)\n", 1061 sep->se_rpcprog, n); 1062 } 1063 #endif /* RPC */ 1064 } 1065 1066 1067 struct servtab * 1068 enter(cp) 1069 struct servtab *cp; 1070 { 1071 struct servtab *sep; 1072 long omask; 1073 1074 sep = (struct servtab *)malloc(sizeof (*sep)); 1075 if (sep == (struct servtab *)0) { 1076 syslog(LOG_ERR, "Out of memory."); 1077 exit(-1); 1078 } 1079 *sep = *cp; 1080 sep->se_fd = -1; 1081 sep->se_rpcprog = -1; 1082 omask = sigblock(SIGBLOCK); 1083 sep->se_next = servtab; 1084 servtab = sep; 1085 sigsetmask(omask); 1086 return (sep); 1087 } 1088 1089 FILE *fconfig = NULL; 1090 struct servtab serv; 1091 char line[LINE_MAX]; 1092 char *defhost; 1093 1094 int 1095 setconfig() 1096 { 1097 if (defhost) free(defhost); 1098 defhost = newstr("*"); 1099 if (fconfig != NULL) { 1100 fseek(fconfig, 0L, SEEK_SET); 1101 return (1); 1102 } 1103 fconfig = fopen(CONFIG, "r"); 1104 return (fconfig != NULL); 1105 } 1106 1107 void 1108 endconfig() 1109 { 1110 if (fconfig) { 1111 (void) fclose(fconfig); 1112 fconfig = NULL; 1113 } 1114 if (defhost) { 1115 free(defhost); 1116 defhost = 0; 1117 } 1118 } 1119 1120 struct servtab * 1121 getconfigent() 1122 { 1123 struct servtab *sep = &serv; 1124 int argc; 1125 char *cp, *arg; 1126 static char TCPMUX_TOKEN[] = "tcpmux/"; 1127 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) 1128 char *hostdelim; 1129 1130 more: 1131 #ifdef MULOG 1132 while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0')) { 1133 /* Avoid use of `skip' if there is a danger of it looking 1134 * at continuation lines. 1135 */ 1136 do { 1137 cp++; 1138 } while (*cp == ' ' || *cp == '\t'); 1139 if (*cp == '\0') 1140 continue; 1141 if ((arg = skip(&cp)) == NULL) 1142 continue; 1143 if (strcmp(arg, "DOMAIN")) 1144 continue; 1145 if (curdom) 1146 free(curdom); 1147 curdom = NULL; 1148 while (*cp == ' ' || *cp == '\t') 1149 cp++; 1150 if (*cp == '\0') 1151 continue; 1152 arg = cp; 1153 while (*cp && *cp != ' ' && *cp != '\t') 1154 cp++; 1155 if (*cp != '\0') 1156 *cp++ = '\0'; 1157 curdom = newstr(arg); 1158 } 1159 #else 1160 while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0')) 1161 ; 1162 #endif 1163 if (cp == NULL) 1164 return ((struct servtab *)0); 1165 /* 1166 * clear the static buffer, since some fields (se_ctrladdr, 1167 * for example) don't get initialized here. 1168 */ 1169 memset((caddr_t)sep, 0, sizeof *sep); 1170 arg = skip(&cp); 1171 if (cp == NULL) { 1172 /* got an empty line containing just blanks/tabs. */ 1173 goto more; 1174 } 1175 /* Check for a host name. */ 1176 hostdelim = strrchr(arg, ':'); 1177 if (hostdelim) { 1178 *hostdelim = '\0'; 1179 sep->se_hostaddr = newstr(arg); 1180 arg = hostdelim + 1; 1181 /* 1182 * If the line is of the form `host:', then just change the 1183 * default host for the following lines. 1184 */ 1185 if (*arg == '\0') { 1186 arg = skip(&cp); 1187 if (cp == NULL) { 1188 free(defhost); 1189 defhost = sep->se_hostaddr; 1190 goto more; 1191 } 1192 } 1193 } else 1194 sep->se_hostaddr = newstr(defhost); 1195 if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) { 1196 char *c = arg + MUX_LEN; 1197 if (*c == '+') { 1198 sep->se_type = MUXPLUS_TYPE; 1199 c++; 1200 } else 1201 sep->se_type = MUX_TYPE; 1202 sep->se_service = newstr(c); 1203 } else { 1204 sep->se_service = newstr(arg); 1205 sep->se_type = NORM_TYPE; 1206 } 1207 1208 arg = sskip(&cp); 1209 if (strcmp(arg, "stream") == 0) 1210 sep->se_socktype = SOCK_STREAM; 1211 else if (strcmp(arg, "dgram") == 0) 1212 sep->se_socktype = SOCK_DGRAM; 1213 else if (strcmp(arg, "rdm") == 0) 1214 sep->se_socktype = SOCK_RDM; 1215 else if (strcmp(arg, "seqpacket") == 0) 1216 sep->se_socktype = SOCK_SEQPACKET; 1217 else if (strcmp(arg, "raw") == 0) 1218 sep->se_socktype = SOCK_RAW; 1219 else 1220 sep->se_socktype = -1; 1221 1222 sep->se_proto = newstr(sskip(&cp)); 1223 if (strcmp(sep->se_proto, "unix") == 0) { 1224 sep->se_family = AF_UNIX; 1225 } else { 1226 sep->se_family = AF_INET; 1227 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 1228 #ifdef RPC 1229 char *cp, *ccp; 1230 cp = strchr(sep->se_service, '/'); 1231 if (cp == 0) { 1232 syslog(LOG_ERR, "%s: no rpc version", 1233 sep->se_service); 1234 goto more; 1235 } 1236 *cp++ = '\0'; 1237 sep->se_rpcversl = sep->se_rpcversh = 1238 strtol(cp, &ccp, 0); 1239 if (ccp == cp) { 1240 badafterall: 1241 syslog(LOG_ERR, "%s/%s: bad rpc version", 1242 sep->se_service, cp); 1243 goto more; 1244 } 1245 if (*ccp == '-') { 1246 cp = ccp + 1; 1247 sep->se_rpcversh = strtol(cp, &ccp, 0); 1248 if (ccp == cp) 1249 goto badafterall; 1250 } 1251 #else 1252 syslog(LOG_ERR, "%s: rpc services not suported", 1253 sep->se_service); 1254 goto more; 1255 #endif /* RPC */ 1256 } 1257 } 1258 arg = sskip(&cp); 1259 { 1260 char *cp; 1261 cp = strchr(arg, '.'); 1262 if (cp) { 1263 *cp++ = '\0'; 1264 sep->se_max = atoi(cp); 1265 } else 1266 sep->se_max = TOOMANY; 1267 } 1268 sep->se_wait = strcmp(arg, "wait") == 0; 1269 if (ISMUX(sep)) { 1270 /* 1271 * Silently enforce "nowait" for TCPMUX services since 1272 * they don't have an assigned port to listen on. 1273 */ 1274 sep->se_wait = 0; 1275 1276 if (strcmp(sep->se_proto, "tcp")) { 1277 syslog(LOG_ERR, 1278 "%s: bad protocol for tcpmux service %s", 1279 CONFIG, sep->se_service); 1280 goto more; 1281 } 1282 if (sep->se_socktype != SOCK_STREAM) { 1283 syslog(LOG_ERR, 1284 "%s: bad socket type for tcpmux service %s", 1285 CONFIG, sep->se_service); 1286 goto more; 1287 } 1288 } 1289 sep->se_user = newstr(sskip(&cp)); 1290 if ((sep->se_group = strchr(sep->se_user, '.'))) 1291 *sep->se_group++ = '\0'; 1292 sep->se_server = newstr(sskip(&cp)); 1293 if (strcmp(sep->se_server, "internal") == 0) { 1294 struct biltin *bi; 1295 1296 for (bi = biltins; bi->bi_service; bi++) 1297 if (bi->bi_socktype == sep->se_socktype && 1298 strcmp(bi->bi_service, sep->se_service) == 0) 1299 break; 1300 if (bi->bi_service == 0) { 1301 syslog(LOG_ERR, "internal service %s unknown", 1302 sep->se_service); 1303 goto more; 1304 } 1305 sep->se_bi = bi; 1306 sep->se_wait = bi->bi_wait; 1307 } else 1308 sep->se_bi = NULL; 1309 argc = 0; 1310 for (arg = skip(&cp); cp; arg = skip(&cp)) { 1311 #if MULOG 1312 char *colon; 1313 1314 if (argc == 0 && (colon = strrchr(arg, ':'))) { 1315 while (arg < colon) { 1316 int x; 1317 char *ccp; 1318 1319 switch (*arg++) { 1320 case 'l': 1321 x = 1; 1322 if (isdigit(*arg)) { 1323 x = strtol(arg, &ccp, 0); 1324 if (ccp == arg) 1325 break; 1326 arg = ccp; 1327 } 1328 sep->se_log &= ~MULOG_RFC931; 1329 sep->se_log |= x; 1330 break; 1331 case 'a': 1332 sep->se_log |= MULOG_RFC931; 1333 break; 1334 default: 1335 break; 1336 } 1337 } 1338 arg = colon + 1; 1339 } 1340 #endif 1341 if (argc < MAXARGV) 1342 sep->se_argv[argc++] = newstr(arg); 1343 } 1344 while (argc <= MAXARGV) 1345 sep->se_argv[argc++] = NULL; 1346 return (sep); 1347 } 1348 1349 void 1350 freeconfig(cp) 1351 struct servtab *cp; 1352 { 1353 int i; 1354 1355 if (cp->se_hostaddr) 1356 free(cp->se_hostaddr); 1357 if (cp->se_service) 1358 free(cp->se_service); 1359 if (cp->se_proto) 1360 free(cp->se_proto); 1361 if (cp->se_user) 1362 free(cp->se_user); 1363 /* Note: se_group is part of the newstr'ed se_user */ 1364 if (cp->se_server) 1365 free(cp->se_server); 1366 for (i = 0; i < MAXARGV; i++) 1367 if (cp->se_argv[i]) 1368 free(cp->se_argv[i]); 1369 } 1370 1371 1372 /* 1373 * Safe skip - if skip returns null, log a syntax error in the 1374 * configuration file and exit. 1375 */ 1376 char * 1377 sskip(cpp) 1378 char **cpp; 1379 { 1380 char *cp; 1381 1382 cp = skip(cpp); 1383 if (cp == NULL) { 1384 syslog(LOG_ERR, "%s: syntax error", CONFIG); 1385 exit(-1); 1386 } 1387 return (cp); 1388 } 1389 1390 char * 1391 skip(cpp) 1392 char **cpp; 1393 { 1394 char *cp = *cpp; 1395 char *start; 1396 1397 if (*cpp == NULL) 1398 return ((char *)0); 1399 1400 again: 1401 while (*cp == ' ' || *cp == '\t') 1402 cp++; 1403 if (*cp == '\0') { 1404 int c; 1405 1406 c = getc(fconfig); 1407 (void) ungetc(c, fconfig); 1408 if (c == ' ' || c == '\t') 1409 if ((cp = nextline(fconfig))) 1410 goto again; 1411 *cpp = (char *)0; 1412 return ((char *)0); 1413 } 1414 start = cp; 1415 while (*cp && *cp != ' ' && *cp != '\t') 1416 cp++; 1417 if (*cp != '\0') 1418 *cp++ = '\0'; 1419 *cpp = cp; 1420 return (start); 1421 } 1422 1423 char * 1424 nextline(fd) 1425 FILE *fd; 1426 { 1427 char *cp; 1428 1429 if (fgets(line, sizeof (line), fd) == NULL) 1430 return ((char *)0); 1431 cp = strchr(line, '\n'); 1432 if (cp) 1433 *cp = '\0'; 1434 return (line); 1435 } 1436 1437 char * 1438 newstr(cp) 1439 char *cp; 1440 { 1441 if ((cp = strdup(cp ? cp : ""))) 1442 return (cp); 1443 syslog(LOG_ERR, "strdup: %m"); 1444 exit(-1); 1445 } 1446 1447 void 1448 inetd_setproctitle(a, s) 1449 char *a; 1450 int s; 1451 { 1452 int size; 1453 char *cp; 1454 struct sockaddr_in sin; 1455 char buf[80]; 1456 1457 cp = Argv[0]; 1458 size = sizeof(sin); 1459 if (getpeername(s, (struct sockaddr *)&sin, &size) == 0) 1460 (void)snprintf(buf, sizeof buf, "-%s [%s]", a, 1461 inet_ntoa(sin.sin_addr)); 1462 else 1463 (void)snprintf(buf, sizeof buf, "-%s", a); 1464 strncpy(cp, buf, LastArg - cp); 1465 cp += strlen(cp); 1466 while (cp < LastArg) 1467 *cp++ = ' '; 1468 } 1469 1470 void 1471 logpid() 1472 { 1473 FILE *fp; 1474 1475 if ((fp = fopen(_PATH_INETDPID, "w")) != NULL) { 1476 fprintf(fp, "%u\n", getpid()); 1477 (void)fclose(fp); 1478 } 1479 } 1480 1481 void 1482 bump_nofile() 1483 { 1484 #ifdef RLIMIT_NOFILE 1485 1486 #define FD_CHUNK 32 1487 1488 struct rlimit rl; 1489 1490 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1491 syslog(LOG_ERR, "getrlimit: %m"); 1492 return; 1493 } 1494 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK); 1495 if (rl.rlim_cur <= rlim_ofile_cur) { 1496 syslog(LOG_ERR, 1497 "bump_nofile: cannot extend file limit, max = %d", 1498 (int)rl.rlim_cur); 1499 return; 1500 } 1501 1502 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { 1503 syslog(LOG_ERR, "setrlimit: %m"); 1504 return; 1505 } 1506 1507 rlim_ofile_cur = rl.rlim_cur; 1508 return; 1509 1510 #else 1511 syslog(LOG_ERR, "bump_nofile: cannot extend file limit"); 1512 return; 1513 #endif 1514 } 1515 1516 /* 1517 * Internet services provided internally by inetd: 1518 */ 1519 #define BUFSIZE 4096 1520 1521 /* ARGSUSED */ 1522 void 1523 echo_stream(s, sep) /* Echo service -- echo data back */ 1524 int s; 1525 struct servtab *sep; 1526 { 1527 char buffer[BUFSIZE]; 1528 int i; 1529 1530 inetd_setproctitle(sep->se_service, s); 1531 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1532 write(s, buffer, i) > 0) 1533 ; 1534 } 1535 1536 /* ARGSUSED */ 1537 void 1538 echo_dg(s, sep) /* Echo service -- echo data back */ 1539 int s; 1540 struct servtab *sep; 1541 { 1542 char buffer[BUFSIZE]; 1543 int i, size; 1544 struct sockaddr sa; 1545 1546 size = sizeof(sa); 1547 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0) 1548 return; 1549 (void) sendto(s, buffer, i, 0, &sa, sizeof(sa)); 1550 } 1551 1552 /* ARGSUSED */ 1553 void 1554 discard_stream(s, sep) /* Discard service -- ignore data */ 1555 int s; 1556 struct servtab *sep; 1557 { 1558 char buffer[BUFSIZE]; 1559 1560 inetd_setproctitle(sep->se_service, s); 1561 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || 1562 errno == EINTR) 1563 ; 1564 } 1565 1566 /* ARGSUSED */ 1567 void 1568 discard_dg(s, sep) /* Discard service -- ignore data */ 1569 int s; 1570 struct servtab *sep; 1571 { 1572 char buffer[BUFSIZE]; 1573 1574 (void) read(s, buffer, sizeof(buffer)); 1575 } 1576 1577 #include <ctype.h> 1578 #define LINESIZ 72 1579 char ring[128]; 1580 char *endring; 1581 1582 void 1583 initring() 1584 { 1585 int i; 1586 1587 endring = ring; 1588 1589 for (i = 0; i <= 128; ++i) 1590 if (isprint(i)) 1591 *endring++ = i; 1592 } 1593 1594 /* ARGSUSED */ 1595 void 1596 chargen_stream(s, sep) /* Character generator */ 1597 int s; 1598 struct servtab *sep; 1599 { 1600 int len; 1601 char *rs, text[LINESIZ+2]; 1602 1603 inetd_setproctitle(sep->se_service, s); 1604 1605 if (!endring) { 1606 initring(); 1607 rs = ring; 1608 } 1609 1610 text[LINESIZ] = '\r'; 1611 text[LINESIZ + 1] = '\n'; 1612 for (rs = ring;;) { 1613 if ((len = endring - rs) >= LINESIZ) 1614 memmove(text, rs, LINESIZ); 1615 else { 1616 memmove(text, rs, len); 1617 memmove(text + len, ring, LINESIZ - len); 1618 } 1619 if (++rs == endring) 1620 rs = ring; 1621 if (write(s, text, sizeof(text)) != sizeof(text)) 1622 break; 1623 } 1624 } 1625 1626 /* ARGSUSED */ 1627 void 1628 chargen_dg(s, sep) /* Character generator */ 1629 int s; 1630 struct servtab *sep; 1631 { 1632 struct sockaddr sa; 1633 static char *rs; 1634 int len, size; 1635 char text[LINESIZ+2]; 1636 1637 if (endring == 0) { 1638 initring(); 1639 rs = ring; 1640 } 1641 1642 size = sizeof(sa); 1643 if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0) 1644 return; 1645 1646 if ((len = endring - rs) >= LINESIZ) 1647 memmove(text, rs, LINESIZ); 1648 else { 1649 memmove(text, rs, len); 1650 memmove(text + len, ring, LINESIZ - len); 1651 } 1652 if (++rs == endring) 1653 rs = ring; 1654 text[LINESIZ] = '\r'; 1655 text[LINESIZ + 1] = '\n'; 1656 (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa)); 1657 } 1658 1659 /* 1660 * Return a machine readable date and time, in the form of the 1661 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1662 * returns the number of seconds since midnight, Jan 1, 1970, 1663 * we must add 2208988800 seconds to this figure to make up for 1664 * some seventy years Bell Labs was asleep. 1665 */ 1666 1667 long 1668 machtime() 1669 { 1670 struct timeval tv; 1671 1672 if (gettimeofday(&tv, (struct timezone *)0) < 0) { 1673 if (debug) 1674 fprintf(stderr, "Unable to get time of day\n"); 1675 return (0L); 1676 } 1677 #define OFFSET ((u_long)25567 * 24*60*60) 1678 return (htonl((long)(tv.tv_sec + OFFSET))); 1679 #undef OFFSET 1680 } 1681 1682 /* ARGSUSED */ 1683 void 1684 machtime_stream(s, sep) 1685 int s; 1686 struct servtab *sep; 1687 { 1688 long result; 1689 1690 result = machtime(); 1691 (void) write(s, (char *) &result, sizeof(result)); 1692 } 1693 1694 /* ARGSUSED */ 1695 void 1696 machtime_dg(s, sep) 1697 int s; 1698 struct servtab *sep; 1699 { 1700 long result; 1701 struct sockaddr sa; 1702 int size; 1703 1704 size = sizeof(sa); 1705 if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0) 1706 return; 1707 result = machtime(); 1708 (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa)); 1709 } 1710 1711 /* ARGSUSED */ 1712 void 1713 daytime_stream(s, sep) /* Return human-readable time of day */ 1714 int s; 1715 struct servtab *sep; 1716 { 1717 char buffer[256]; 1718 time_t clock; 1719 int len; 1720 1721 clock = time((time_t *) 0); 1722 1723 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 1724 (void) write(s, buffer, len); 1725 } 1726 1727 /* ARGSUSED */ 1728 void 1729 daytime_dg(s, sep) /* Return human-readable time of day */ 1730 int s; 1731 struct servtab *sep; 1732 { 1733 char buffer[256]; 1734 time_t clock; 1735 struct sockaddr sa; 1736 int size, len; 1737 1738 clock = time((time_t *) 0); 1739 1740 size = sizeof(sa); 1741 if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0) 1742 return; 1743 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clock)); 1744 (void) sendto(s, buffer, len, 0, &sa, sizeof(sa)); 1745 } 1746 1747 /* 1748 * print_service: 1749 * Dump relevant information to stderr 1750 */ 1751 void 1752 print_service(action, sep) 1753 char *action; 1754 struct servtab *sep; 1755 { 1756 if (isrpcservice(sep)) 1757 fprintf(stderr, 1758 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%d, user.group=%s.%s builtin=%lx server=%s\n", 1759 action, sep->se_service, 1760 sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto, 1761 sep->se_wait, sep->se_max, sep->se_user, sep->se_group, 1762 (long)sep->se_bi, sep->se_server); 1763 else 1764 fprintf(stderr, 1765 "%s: %s proto=%s, wait.max=%d.%d, user.group=%s.%s builtin=%lx server=%s\n", 1766 action, sep->se_service, sep->se_proto, 1767 sep->se_wait, sep->se_max, sep->se_user, sep->se_group, 1768 (long)sep->se_bi, sep->se_server); 1769 } 1770 1771 void 1772 usage() 1773 { 1774 1775 #ifdef LIBWRAP 1776 (void)fprintf(stderr, "usage: %s [-dl] [conf]\n", __progname); 1777 #else 1778 (void)fprintf(stderr, "usage: %s [-d] [conf]\n", __progname); 1779 #endif 1780 exit(1); 1781 } 1782 1783 1784 /* 1785 * Based on TCPMUX.C by Mark K. Lottor November 1988 1786 * sri-nic::ps:<mkl>tcpmux.c 1787 */ 1788 1789 static int /* # of characters upto \r,\n or \0 */ 1790 getline(fd, buf, len) 1791 int fd; 1792 char *buf; 1793 int len; 1794 { 1795 int count = 0, n; 1796 1797 do { 1798 n = read(fd, buf, len-count); 1799 if (n == 0) 1800 return (count); 1801 if (n < 0) 1802 return (-1); 1803 while (--n >= 0) { 1804 if (*buf == '\r' || *buf == '\n' || *buf == '\0') 1805 return (count); 1806 count++; 1807 buf++; 1808 } 1809 } while (count < len); 1810 return (count); 1811 } 1812 1813 #define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */ 1814 1815 #define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1) 1816 1817 void 1818 tcpmux(ctrl, sep) 1819 int ctrl; 1820 struct servtab *sep; 1821 { 1822 char service[MAX_SERV_LEN+1]; 1823 int len; 1824 1825 /* Get requested service name */ 1826 if ((len = getline(ctrl, service, MAX_SERV_LEN)) < 0) { 1827 strwrite(ctrl, "-Error reading service name\r\n"); 1828 goto reject; 1829 } 1830 service[len] = '\0'; 1831 1832 if (debug) 1833 fprintf(stderr, "tcpmux: someone wants %s\n", service); 1834 1835 /* 1836 * Help is a required command, and lists available services, 1837 * one per line. 1838 */ 1839 if (!strcasecmp(service, "help")) { 1840 strwrite(ctrl, "+Available services:\r\n"); 1841 strwrite(ctrl, "help\r\n"); 1842 for (sep = servtab; sep; sep = sep->se_next) { 1843 if (!ISMUX(sep)) 1844 continue; 1845 (void)write(ctrl, sep->se_service, 1846 strlen(sep->se_service)); 1847 strwrite(ctrl, "\r\n"); 1848 } 1849 goto reject; 1850 } 1851 1852 /* Try matching a service in inetd.conf with the request */ 1853 for (sep = servtab; sep; sep = sep->se_next) { 1854 if (!ISMUX(sep)) 1855 continue; 1856 if (!strcasecmp(service, sep->se_service)) { 1857 if (ISMUXPLUS(sep)) 1858 strwrite(ctrl, "+Go\r\n"); 1859 run_service(ctrl, sep); 1860 return; 1861 } 1862 } 1863 strwrite(ctrl, "-Service not available\r\n"); 1864 reject: 1865 _exit(1); 1866 } 1867 1868 1869 #ifdef MULOG 1870 dolog(sep, ctrl) 1871 struct servtab *sep; 1872 int ctrl; 1873 { 1874 struct sockaddr sa; 1875 struct sockaddr_in *sin = (struct sockaddr_in *)&sa; 1876 int len = sizeof(sa); 1877 struct hostent *hp; 1878 char *host, *dp, buf[BUFSIZ], *rfc931_name(); 1879 int connected = 1; 1880 1881 if (sep->se_family != AF_INET) 1882 return; 1883 1884 if (getpeername(ctrl, &sa, &len) < 0) { 1885 if (errno != ENOTCONN) { 1886 syslog(LOG_ERR, "getpeername: %m"); 1887 return; 1888 } 1889 if (recvfrom(ctrl, buf, sizeof(buf), MSG_PEEK, &sa, &len) < 0) { 1890 syslog(LOG_ERR, "recvfrom: %m"); 1891 return; 1892 } 1893 connected = 0; 1894 } 1895 if (sa.sa_family != AF_INET) { 1896 syslog(LOG_ERR, "unexpected address family %u", sa.sa_family); 1897 return; 1898 } 1899 1900 hp = gethostbyaddr((char *) &sin->sin_addr.s_addr, 1901 sizeof (sin->sin_addr.s_addr), AF_INET); 1902 1903 host = hp?hp->h_name:inet_ntoa(sin->sin_addr); 1904 1905 switch (sep->se_log & ~MULOG_RFC931) { 1906 case 0: 1907 return; 1908 case 1: 1909 if (curdom == NULL || *curdom == '\0') 1910 break; 1911 dp = host + strlen(host) - strlen(curdom); 1912 if (dp < host) 1913 break; 1914 if (debug) 1915 fprintf(stderr, "check \"%s\" against curdom \"%s\"\n", 1916 host, curdom); 1917 if (strcasecmp(dp, curdom) == 0) 1918 return; 1919 break; 1920 case 2: 1921 default: 1922 break; 1923 } 1924 1925 openlog("", LOG_NOWAIT, MULOG); 1926 1927 if (connected && (sep->se_log & MULOG_RFC931)) 1928 syslog(LOG_INFO, "%s@%s wants %s", 1929 rfc931_name(sin, ctrl), host, sep->se_service); 1930 else 1931 syslog(LOG_INFO, "%s wants %s", 1932 host, sep->se_service); 1933 } 1934 1935 /* 1936 * From tcp_log by 1937 * Wietse Venema, Eindhoven University of Technology, The Netherlands. 1938 */ 1939 #if 0 1940 static char sccsid[] = "@(#) rfc931.c 1.3 92/08/31 22:54:46"; 1941 #endif 1942 1943 #include <setjmp.h> 1944 1945 #define RFC931_PORT 113 /* Semi-well-known port */ 1946 #define TIMEOUT 4 1947 #define TIMEOUT2 10 1948 1949 static jmp_buf timebuf; 1950 1951 /* timeout - handle timeouts */ 1952 1953 static void timeout(sig) 1954 int sig; 1955 { 1956 longjmp(timebuf, sig); 1957 } 1958 1959 /* rfc931_name - return remote user name */ 1960 1961 char * 1962 rfc931_name(there, ctrl) 1963 struct sockaddr_in *there; /* remote link information */ 1964 int ctrl; 1965 { 1966 struct sockaddr_in here; /* local link information */ 1967 struct sockaddr_in sin; /* for talking to RFC931 daemon */ 1968 int length; 1969 int s; 1970 unsigned remote; 1971 unsigned local; 1972 static char user[256]; /* XXX */ 1973 char buf[256]; 1974 char *cp; 1975 char *result = "USER_UNKNOWN"; 1976 int len; 1977 1978 /* Find out local port number of our stdin. */ 1979 1980 length = sizeof(here); 1981 if (getsockname(ctrl, (struct sockaddr *) &here, &length) == -1) { 1982 syslog(LOG_ERR, "getsockname: %m"); 1983 return (result); 1984 } 1985 /* Set up timer so we won't get stuck. */ 1986 1987 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 1988 syslog(LOG_ERR, "socket: %m"); 1989 return (result); 1990 } 1991 1992 sin = here; 1993 sin.sin_port = htons(0); 1994 if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { 1995 syslog(LOG_ERR, "bind: %m"); 1996 return (result); 1997 } 1998 1999 signal(SIGALRM, timeout); 2000 if (setjmp(timebuf)) { 2001 close(s); /* not: fclose(fp) */ 2002 return (result); 2003 } 2004 alarm(TIMEOUT); 2005 2006 /* Connect to the RFC931 daemon. */ 2007 2008 sin = *there; 2009 sin.sin_port = htons(RFC931_PORT); 2010 if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { 2011 close(s); 2012 alarm(0); 2013 return (result); 2014 } 2015 2016 /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */ 2017 (void)snprintf(buf, sizeof buf, "%u,%u\r\n", ntohs(there->sin_port), 2018 ntohs(here.sin_port)); 2019 2020 2021 for (len = 0, cp = buf; len < strlen(buf); ) { 2022 int n; 2023 2024 if ((n = write(s, cp, strlen(buf) - len)) == -1) { 2025 close(s); 2026 alarm(0); 2027 return (result); 2028 } 2029 cp += n; 2030 len += n; 2031 } 2032 2033 /* Read response */ 2034 for (cp = buf; cp < buf + sizeof(buf) - 1; ) { 2035 char c; 2036 if (read(s, &c, 1) != 1) { 2037 close(s); 2038 alarm(0); 2039 return (result); 2040 } 2041 if (c == '\n') 2042 break; 2043 *cp++ = c; 2044 } 2045 *cp = '\0'; 2046 2047 if (sscanf(buf, "%u , %u : USERID :%*[^:]:%255s", &remote, &local, user) == 3 2048 && ntohs(there->sin_port) == remote 2049 && ntohs(here.sin_port) == local) { 2050 2051 /* Strip trailing carriage return. */ 2052 if (cp = strchr(user, '\r')) 2053 *cp = 0; 2054 result = user; 2055 } 2056 2057 alarm(0); 2058 close(s); 2059 return (result); 2060 } 2061 #endif 2062