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