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 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 /* from: @(#)inetd.c 8.4 (Berkeley) 4/13/94"; */ 42 static char inetd_c_rcsid[] = 43 "$Id$"; 44 #endif /* not lint */ 45 46 /* 47 * Inetd - Internet super-server 48 * 49 * This program invokes all internet services as needed. Connection-oriented 50 * services are invoked each time a connection is made, by creating a process. 51 * This process is passed the connection as file descriptor 0 and is expected 52 * to do a getpeername to find out the source host and port. 53 * 54 * Datagram oriented services are invoked when a datagram 55 * arrives; a process is created and passed a pending message 56 * on file descriptor 0. Datagram servers may either connect 57 * to their peer, freeing up the original socket for inetd 58 * to receive further messages on, or ``take over the socket'', 59 * processing all arriving datagrams and, eventually, timing 60 * out. The first type of server is said to be ``multi-threaded''; 61 * the second type of server ``single-threaded''. 62 * 63 * Inetd uses a configuration file which is read at startup 64 * and, possibly, at some later time in response to a hangup signal. 65 * The configuration file is ``free format'' with fields given in the 66 * order shown below. Continuation lines for an entry must being with 67 * a space or tab. All fields must be present in each entry. 68 * 69 * service name must be in /etc/services or must 70 * name a tcpmux service 71 * socket type stream/dgram/raw/rdm/seqpacket 72 * protocol must be in /etc/protocols 73 * wait/nowait single-threaded/multi-threaded 74 * user user to run daemon as 75 * server program full path name 76 * server program arguments maximum of MAXARGS (20) 77 * 78 * TCP services without official port numbers are handled with the 79 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for 80 * requests. When a connection is made from a foreign host, the service 81 * requested is passed to tcpmux, which looks it up in the servtab list 82 * and returns the proper entry for the service. Tcpmux returns a 83 * negative reply if the service doesn't exist, otherwise the invoked 84 * server is expected to return the positive reply if the service type in 85 * inetd.conf file has the prefix "tcpmux/". If the service type has the 86 * prefix "tcpmux/+", tcpmux will return the positive reply for the 87 * process; this is for compatibility with older server code, and also 88 * allows you to invoke programs that use stdin/stdout without putting any 89 * special server code in them. Services that use tcpmux are "nowait" 90 * because they do not have a well-known port and hence cannot listen 91 * for new requests. 92 * 93 * For RPC services 94 * service name/version must be in /etc/rpc 95 * socket type stream/dgram/raw/rdm/seqpacket 96 * protocol must be in /etc/protocols 97 * wait/nowait single-threaded/multi-threaded 98 * user user to run daemon as 99 * server program full path name 100 * server program arguments maximum of MAXARGS 101 * 102 * Comment lines are indicated by a `#' in column 1. 103 */ 104 #include <sys/param.h> 105 #include <sys/stat.h> 106 #include <sys/ioctl.h> 107 #include <sys/socket.h> 108 #include <sys/wait.h> 109 #include <sys/time.h> 110 #include <sys/resource.h> 111 112 #include <netinet/in.h> 113 #include <arpa/inet.h> 114 #include <rpc/rpc.h> 115 116 #include <errno.h> 117 #include <fcntl.h> 118 #include <netdb.h> 119 #include <pwd.h> 120 #include <signal.h> 121 #include <stdio.h> 122 #include <stdlib.h> 123 #include <string.h> 124 #include <syslog.h> 125 #include <unistd.h> 126 127 #include "pathnames.h" 128 129 #define TOOMANY 256 /* don't start more than TOOMANY */ 130 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ 131 #define RETRYTIME (60*10) /* retry after bind or server fail */ 132 133 #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM)) 134 135 136 int debug = 0; 137 int log = 0; 138 int nsock, maxsock; 139 fd_set allsock; 140 int options; 141 int timingout; 142 int toomany = TOOMANY; 143 struct servent *sp; 144 struct rpcent *rpc; 145 146 struct servtab { 147 char *se_service; /* name of service */ 148 int se_socktype; /* type of socket to use */ 149 char *se_proto; /* protocol used */ 150 short se_wait; /* single threaded server */ 151 short se_checked; /* looked at during merge */ 152 char *se_user; /* user name to run as */ 153 struct biltin *se_bi; /* if built-in, description */ 154 char *se_server; /* server program */ 155 #define MAXARGV 20 156 char *se_argv[MAXARGV+1]; /* program arguments */ 157 int se_fd; /* open descriptor */ 158 int se_type; /* type */ 159 struct sockaddr_in se_ctrladdr;/* bound address */ 160 int se_rpc; /* ==1 if RPC service */ 161 int se_rpc_prog; /* RPC program number */ 162 u_int se_rpc_lowvers; /* RPC low version */ 163 u_int se_rpc_highvers; /* RPC high version */ 164 int se_count; /* number started since se_time */ 165 struct timeval se_time; /* start of se_count */ 166 struct servtab *se_next; 167 } *servtab; 168 169 #define NORM_TYPE 0 170 #define MUX_TYPE 1 171 #define MUXPLUS_TYPE 2 172 #define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \ 173 ((sep)->se_type == MUXPLUS_TYPE)) 174 #define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE) 175 176 177 void chargen_dg __P((int, struct servtab *)); 178 void chargen_stream __P((int, struct servtab *)); 179 void close_sep __P((struct servtab *)); 180 void config __P((int)); 181 void daytime_dg __P((int, struct servtab *)); 182 void daytime_stream __P((int, struct servtab *)); 183 void discard_dg __P((int, struct servtab *)); 184 void discard_stream __P((int, struct servtab *)); 185 void echo_dg __P((int, struct servtab *)); 186 void echo_stream __P((int, struct servtab *)); 187 void endconfig __P((void)); 188 struct servtab *enter __P((struct servtab *)); 189 void freeconfig __P((struct servtab *)); 190 struct servtab *getconfigent __P((void)); 191 void machtime_dg __P((int, struct servtab *)); 192 void machtime_stream __P((int, struct servtab *)); 193 char *newstr __P((char *)); 194 char *nextline __P((FILE *)); 195 void print_service __P((char *, struct servtab *)); 196 void reapchild __P((int)); 197 void retry __P((int)); 198 int setconfig __P((void)); 199 void setup __P((struct servtab *)); 200 char *sskip __P((char **)); 201 char *skip __P((char **)); 202 struct servtab *tcpmux __P((int)); 203 204 void unregisterrpc __P((register struct servtab *sep)); 205 206 struct biltin { 207 char *bi_service; /* internally provided service name */ 208 int bi_socktype; /* type of socket supported */ 209 short bi_fork; /* 1 if should fork before call */ 210 short bi_wait; /* 1 if should wait for child */ 211 void (*bi_fn)(); /* function which performs it */ 212 } biltins[] = { 213 /* Echo received data */ 214 { "echo", SOCK_STREAM, 1, 0, echo_stream }, 215 { "echo", SOCK_DGRAM, 0, 0, echo_dg }, 216 217 /* Internet /dev/null */ 218 { "discard", SOCK_STREAM, 1, 0, discard_stream }, 219 { "discard", SOCK_DGRAM, 0, 0, discard_dg }, 220 221 /* Return 32 bit time since 1970 */ 222 { "time", SOCK_STREAM, 0, 0, machtime_stream }, 223 { "time", SOCK_DGRAM, 0, 0, machtime_dg }, 224 225 /* Return human-readable time */ 226 { "daytime", SOCK_STREAM, 0, 0, daytime_stream }, 227 { "daytime", SOCK_DGRAM, 0, 0, daytime_dg }, 228 229 /* Familiar character generator */ 230 { "chargen", SOCK_STREAM, 1, 0, chargen_stream }, 231 { "chargen", SOCK_DGRAM, 0, 0, chargen_dg }, 232 233 { "tcpmux", SOCK_STREAM, 1, 0, (void (*)())tcpmux }, 234 235 { NULL } 236 }; 237 238 #define NUMINT (sizeof(intab) / sizeof(struct inent)) 239 char *CONFIG = _PATH_INETDCONF; 240 char **Argv; 241 char *LastArg; 242 243 int 244 main(argc, argv, envp) 245 int argc; 246 char *argv[], *envp[]; 247 { 248 struct servtab *sep; 249 struct passwd *pwd; 250 struct sigvec sv; 251 int tmpint, ch, dofork; 252 pid_t pid; 253 char buf[50]; 254 struct sockaddr_in peer; 255 int i; 256 257 Argv = argv; 258 if (envp == 0 || *envp == 0) 259 envp = argv; 260 while (*envp) 261 envp++; 262 LastArg = envp[-1] + strlen(envp[-1]); 263 264 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); 265 266 while ((ch = getopt(argc, argv, "dlR:")) != EOF) 267 switch(ch) { 268 case 'd': 269 debug = 1; 270 options |= SO_DEBUG; 271 break; 272 case 'l': 273 log = 1; 274 break; 275 case 'R': { /* invocation rate */ 276 char *p; 277 278 tmpint = strtol(optarg, &p, 0); 279 if (tmpint < 1 || *p) 280 syslog(LOG_ERR, 281 "-R %s: bad value for service invocation rate", 282 optarg); 283 else 284 toomany = tmpint; 285 break; 286 } 287 case '?': 288 default: 289 syslog(LOG_ERR, 290 "usage: inetd [-dl] [-R rate] [conf-file]"); 291 exit(1); 292 } 293 argc -= optind; 294 argv += optind; 295 296 if (argc > 0) 297 CONFIG = argv[0]; 298 if (debug == 0) { 299 daemon(0, 0); 300 } 301 memset(&sv, 0, sizeof(sv)); 302 sv.sv_mask = SIGBLOCK; 303 sv.sv_handler = retry; 304 sigvec(SIGALRM, &sv, (struct sigvec *)0); 305 config(SIGHUP); 306 sv.sv_handler = config; 307 sigvec(SIGHUP, &sv, (struct sigvec *)0); 308 sv.sv_handler = reapchild; 309 sigvec(SIGCHLD, &sv, (struct sigvec *)0); 310 311 { 312 /* space for daemons to overwrite environment for ps */ 313 #define DUMMYSIZE 100 314 char dummy[DUMMYSIZE]; 315 316 (void)memset(dummy, 'x', sizeof(DUMMYSIZE) - 1); 317 dummy[DUMMYSIZE - 1] = '\0'; 318 (void)setenv("inetd_dummy", dummy, 1); 319 } 320 321 for (;;) { 322 int n, ctrl; 323 fd_set readable; 324 325 if (nsock == 0) { 326 (void) sigblock(SIGBLOCK); 327 while (nsock == 0) 328 sigpause(0L); 329 (void) sigsetmask(0L); 330 } 331 readable = allsock; 332 if ((n = select(maxsock + 1, &readable, (fd_set *)0, 333 (fd_set *)0, (struct timeval *)0)) <= 0) { 334 if (n < 0 && errno != EINTR) 335 syslog(LOG_WARNING, "select: %m"); 336 sleep(1); 337 continue; 338 } 339 for (sep = servtab; n && sep; sep = sep->se_next) 340 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) { 341 n--; 342 if (debug) 343 fprintf(stderr, "someone wants %s\n", 344 sep->se_service); 345 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 346 ctrl = accept(sep->se_fd, (struct sockaddr *)0, 347 (int *)0); 348 if (debug) 349 fprintf(stderr, "accept, ctrl %d\n", ctrl); 350 if (ctrl < 0) { 351 if (errno != EINTR) 352 syslog(LOG_WARNING, 353 "accept (for %s): %m", 354 sep->se_service); 355 continue; 356 } 357 if(log) { 358 i = sizeof peer; 359 if(getpeername(ctrl, (struct sockaddr *) 360 &peer, &i)) { 361 syslog(LOG_WARNING, 362 "getpeername(for %s): %m", 363 sep->se_service); 364 continue; 365 } 366 syslog(LOG_INFO,"%s from %s", 367 sep->se_service, 368 inet_ntoa(peer.sin_addr)); 369 } 370 /* 371 * Call tcpmux to find the real service to exec. 372 */ 373 if (sep->se_bi && 374 sep->se_bi->bi_fn == (void (*)()) tcpmux) { 375 sep = tcpmux(ctrl); 376 if (sep == NULL) { 377 close(ctrl); 378 continue; 379 } 380 } 381 } else 382 ctrl = sep->se_fd; 383 (void) sigblock(SIGBLOCK); 384 pid = 0; 385 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); 386 if (dofork) { 387 if (sep->se_count++ == 0) 388 (void)gettimeofday(&sep->se_time, 389 (struct timezone *)0); 390 else if (sep->se_count >= toomany) { 391 struct timeval now; 392 393 (void)gettimeofday(&now, (struct timezone *)0); 394 if (now.tv_sec - sep->se_time.tv_sec > 395 CNT_INTVL) { 396 sep->se_time = now; 397 sep->se_count = 1; 398 } else { 399 syslog(LOG_ERR, 400 "%s/%s server failing (looping), service terminated", 401 sep->se_service, sep->se_proto); 402 close_sep(sep); 403 sigsetmask(0L); 404 if (!timingout) { 405 timingout = 1; 406 alarm(RETRYTIME); 407 } 408 continue; 409 } 410 } 411 pid = fork(); 412 } 413 if (pid < 0) { 414 syslog(LOG_ERR, "fork: %m"); 415 if (!sep->se_wait && 416 sep->se_socktype == SOCK_STREAM) 417 close(ctrl); 418 sigsetmask(0L); 419 sleep(1); 420 continue; 421 } 422 if (pid && sep->se_wait) { 423 sep->se_wait = pid; 424 if (sep->se_fd >= 0) { 425 FD_CLR(sep->se_fd, &allsock); 426 nsock--; 427 } 428 } 429 sigsetmask(0L); 430 if (pid == 0) { 431 if (debug && dofork) 432 setsid(); 433 if (dofork) { 434 if (debug) 435 fprintf(stderr, "+ Closing from %d\n", 436 maxsock); 437 for (tmpint = maxsock; tmpint > 2; tmpint--) 438 if (tmpint != ctrl) 439 close(tmpint); 440 } 441 if (sep->se_bi) 442 (*sep->se_bi->bi_fn)(ctrl, sep); 443 else { 444 if (debug) 445 fprintf(stderr, "%d execl %s\n", 446 getpid(), sep->se_server); 447 dup2(ctrl, 0); 448 close(ctrl); 449 dup2(0, 1); 450 dup2(0, 2); 451 if ((pwd = getpwnam(sep->se_user)) == NULL) { 452 syslog(LOG_ERR, 453 "%s/%s: %s: No such user", 454 sep->se_service, sep->se_proto, 455 sep->se_user); 456 if (sep->se_socktype != SOCK_STREAM) 457 recv(0, buf, sizeof (buf), 0); 458 _exit(1); 459 } 460 if (pwd->pw_uid) { 461 if (setgid(pwd->pw_gid) < 0) { 462 syslog(LOG_ERR, 463 "%s: can't set gid %d: %m", 464 sep->se_service, pwd->pw_gid); 465 _exit(1); 466 } 467 (void) initgroups(pwd->pw_name, 468 pwd->pw_gid); 469 if (setuid(pwd->pw_uid) < 0) { 470 syslog(LOG_ERR, 471 "%s: can't set uid %d: %m", 472 sep->se_service, pwd->pw_uid); 473 _exit(1); 474 } 475 } 476 execv(sep->se_server, sep->se_argv); 477 if (sep->se_socktype != SOCK_STREAM) 478 recv(0, buf, sizeof (buf), 0); 479 syslog(LOG_ERR, 480 "cannot execute %s: %m", sep->se_server); 481 _exit(1); 482 } 483 } 484 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 485 close(ctrl); 486 } 487 } 488 } 489 490 void 491 reapchild(signo) 492 int signo; 493 { 494 int status; 495 pid_t pid; 496 struct servtab *sep; 497 498 for (;;) { 499 pid = wait3(&status, WNOHANG, (struct rusage *)0); 500 if (pid <= 0) 501 break; 502 if (debug) 503 fprintf(stderr, "%d reaped, status %#x\n", 504 pid, status); 505 for (sep = servtab; sep; sep = sep->se_next) 506 if (sep->se_wait == pid) { 507 if (status) 508 syslog(LOG_WARNING, 509 "%s: exit status 0x%x", 510 sep->se_server, status); 511 if (debug) 512 fprintf(stderr, "restored %s, fd %d\n", 513 sep->se_service, sep->se_fd); 514 FD_SET(sep->se_fd, &allsock); 515 nsock++; 516 sep->se_wait = 1; 517 } 518 } 519 } 520 521 void 522 config(signo) 523 int signo; 524 { 525 struct servtab *sep, *cp, **sepp; 526 struct passwd *pwd; 527 long omask; 528 529 if (!setconfig()) { 530 syslog(LOG_ERR, "%s: %m", CONFIG); 531 return; 532 } 533 for (sep = servtab; sep; sep = sep->se_next) 534 sep->se_checked = 0; 535 while (cp = getconfigent()) { 536 if ((pwd = getpwnam(cp->se_user)) == NULL) { 537 syslog(LOG_ERR, 538 "%s/%s: No such user '%s', service ignored", 539 cp->se_service, cp->se_proto, cp->se_user); 540 continue; 541 } 542 for (sep = servtab; sep; sep = sep->se_next) 543 if (strcmp(sep->se_service, cp->se_service) == 0 && 544 strcmp(sep->se_proto, cp->se_proto) == 0) 545 break; 546 if (sep != 0) { 547 int i; 548 549 omask = sigblock(SIGBLOCK); 550 /* 551 * sep->se_wait may be holding the pid of a daemon 552 * that we're waiting for. If so, don't overwrite 553 * it unless the config file explicitly says don't 554 * wait. 555 */ 556 if (cp->se_bi == 0 && 557 (sep->se_wait == 1 || cp->se_wait == 0)) 558 sep->se_wait = cp->se_wait; 559 #define SWAP(a, b) { char *c = a; a = b; b = c; } 560 if (cp->se_user) 561 SWAP(sep->se_user, cp->se_user); 562 if (cp->se_server) 563 SWAP(sep->se_server, cp->se_server); 564 for (i = 0; i < MAXARGV; i++) 565 SWAP(sep->se_argv[i], cp->se_argv[i]); 566 sigsetmask(omask); 567 freeconfig(cp); 568 if (debug) 569 print_service("REDO", sep); 570 } else { 571 sep = enter(cp); 572 if (debug) 573 print_service("ADD ", sep); 574 } 575 sep->se_checked = 1; 576 if (ISMUX(sep)) { 577 sep->se_fd = -1; 578 continue; 579 } 580 if (!sep->se_rpc) { 581 sp = getservbyname(sep->se_service, sep->se_proto); 582 if (sp == 0) { 583 syslog(LOG_ERR, "%s/%s: unknown service", 584 sep->se_service, sep->se_proto); 585 sep->se_checked = 0; 586 continue; 587 } 588 if (sp->s_port != sep->se_ctrladdr.sin_port) { 589 sep->se_ctrladdr.sin_family = AF_INET; 590 sep->se_ctrladdr.sin_port = sp->s_port; 591 if (sep->se_fd >= 0) 592 close_sep(sep); 593 } 594 } else { 595 rpc = getrpcbyname(sep->se_service); 596 if (rpc == 0) { 597 syslog(LOG_ERR, "%s/%s unknown RPC service.", 598 sep->se_service, sep->se_proto); 599 if (sep->se_fd != -1) 600 (void) close(sep->se_fd); 601 sep->se_fd = -1; 602 continue; 603 } 604 if (rpc->r_number != sep->se_rpc_prog) { 605 if (sep->se_rpc_prog) 606 unregisterrpc(sep); 607 sep->se_rpc_prog = rpc->r_number; 608 if (sep->se_fd != -1) 609 (void) close(sep->se_fd); 610 sep->se_fd = -1; 611 } 612 } 613 if (sep->se_fd == -1) 614 setup(sep); 615 } 616 endconfig(); 617 /* 618 * Purge anything not looked at above. 619 */ 620 omask = sigblock(SIGBLOCK); 621 sepp = &servtab; 622 while (sep = *sepp) { 623 if (sep->se_checked) { 624 sepp = &sep->se_next; 625 continue; 626 } 627 *sepp = sep->se_next; 628 if (sep->se_fd >= 0) 629 close_sep(sep); 630 if (debug) 631 print_service("FREE", sep); 632 if (sep->se_rpc && sep->se_rpc_prog > 0) 633 unregisterrpc(sep); 634 freeconfig(sep); 635 free((char *)sep); 636 } 637 (void) sigsetmask(omask); 638 } 639 640 void 641 unregisterrpc(sep) 642 struct servtab *sep; 643 { 644 int i; 645 struct servtab *sepp; 646 long omask; 647 648 omask = sigblock(SIGBLOCK); 649 for (sepp = servtab; sepp; sepp = sepp->se_next) { 650 if (sepp == sep) 651 continue; 652 if (sep->se_checked == 0 || 653 !sepp->se_rpc || 654 sep->se_rpc_prog != sepp->se_rpc_prog) 655 continue; 656 return; 657 } 658 if (debug) 659 print_service("UNREG", sep); 660 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) 661 pmap_unset(sep->se_rpc_prog, i); 662 if (sep->se_fd != -1) 663 (void) close(sep->se_fd); 664 sep->se_fd = -1; 665 (void) sigsetmask(omask); 666 } 667 668 void 669 retry(signo) 670 int signo; 671 { 672 struct servtab *sep; 673 674 timingout = 0; 675 for (sep = servtab; sep; sep = sep->se_next) 676 if (sep->se_fd == -1) 677 setup(sep); 678 } 679 680 void 681 setup(sep) 682 struct servtab *sep; 683 { 684 int on = 1; 685 686 if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) { 687 if (debug) 688 fprintf(stderr, "socket failed on %s/%s: %s\n", 689 sep->se_service, sep->se_proto, 690 strerror(errno)); 691 syslog(LOG_ERR, "%s/%s: socket: %m", 692 sep->se_service, sep->se_proto); 693 return; 694 } 695 #define turnon(fd, opt) \ 696 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) 697 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && 698 turnon(sep->se_fd, SO_DEBUG) < 0) 699 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 700 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 701 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 702 #undef turnon 703 if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr, 704 sizeof (sep->se_ctrladdr)) < 0) { 705 if (debug) 706 fprintf(stderr, "bind failed on %s/%s: %s\n", 707 sep->se_service, sep->se_proto, 708 strerror(errno)); 709 syslog(LOG_ERR, "%s/%s: bind: %m", 710 sep->se_service, sep->se_proto); 711 (void) close(sep->se_fd); 712 sep->se_fd = -1; 713 if (!timingout) { 714 timingout = 1; 715 alarm(RETRYTIME); 716 } 717 return; 718 } 719 if (sep->se_rpc) { 720 int i, len = sizeof(struct sockaddr); 721 722 if (getsockname(sep->se_fd, 723 (struct sockaddr*)&sep->se_ctrladdr, &len) < 0){ 724 syslog(LOG_ERR, "%s/%s: getsockname: %m", 725 sep->se_service, sep->se_proto); 726 (void) close(sep->se_fd); 727 sep->se_fd = -1; 728 return; 729 } 730 if (debug) 731 print_service("REG ", sep); 732 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) { 733 pmap_unset(sep->se_rpc_prog, i); 734 pmap_set(sep->se_rpc_prog, i, 735 (sep->se_socktype == SOCK_DGRAM) 736 ? IPPROTO_UDP : IPPROTO_TCP, 737 ntohs(sep->se_ctrladdr.sin_port)); 738 } 739 740 } 741 if (sep->se_socktype == SOCK_STREAM) 742 listen(sep->se_fd, 10); 743 FD_SET(sep->se_fd, &allsock); 744 nsock++; 745 if (sep->se_fd > maxsock) 746 maxsock = sep->se_fd; 747 if (debug) { 748 fprintf(stderr, "registered %s on %d\n", 749 sep->se_server, sep->se_fd); 750 } 751 } 752 753 /* 754 * Finish with a service and its socket. 755 */ 756 void 757 close_sep(sep) 758 struct servtab *sep; 759 { 760 if (sep->se_fd >= 0) { 761 nsock--; 762 FD_CLR(sep->se_fd, &allsock); 763 (void) close(sep->se_fd); 764 sep->se_fd = -1; 765 } 766 sep->se_count = 0; 767 /* 768 * Don't keep the pid of this running deamon: when reapchild() 769 * reaps this pid, it would erroneously increment nsock. 770 */ 771 if (sep->se_wait > 1) 772 sep->se_wait = 1; 773 } 774 775 struct servtab * 776 enter(cp) 777 struct servtab *cp; 778 { 779 struct servtab *sep; 780 long omask; 781 782 sep = (struct servtab *)malloc(sizeof (*sep)); 783 if (sep == (struct servtab *)0) { 784 syslog(LOG_ERR, "Out of memory."); 785 exit(-1); 786 } 787 *sep = *cp; 788 sep->se_fd = -1; 789 omask = sigblock(SIGBLOCK); 790 sep->se_next = servtab; 791 servtab = sep; 792 sigsetmask(omask); 793 return (sep); 794 } 795 796 FILE *fconfig = NULL; 797 struct servtab serv; 798 char line[LINE_MAX]; 799 800 int 801 setconfig() 802 { 803 804 if (fconfig != NULL) { 805 fseek(fconfig, 0L, SEEK_SET); 806 return (1); 807 } 808 fconfig = fopen(CONFIG, "r"); 809 return (fconfig != NULL); 810 } 811 812 void 813 endconfig() 814 { 815 if (fconfig) { 816 (void) fclose(fconfig); 817 fconfig = NULL; 818 } 819 } 820 821 struct servtab * 822 getconfigent() 823 { 824 struct servtab *sep = &serv; 825 int argc; 826 char *cp, *arg; 827 char *versp; 828 static char TCPMUX_TOKEN[] = "tcpmux/"; 829 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) 830 831 more: 832 while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0')) 833 ; 834 if (cp == NULL) 835 return ((struct servtab *)0); 836 /* 837 * clear the static buffer, since some fields (se_ctrladdr, 838 * for example) don't get initialized here. 839 */ 840 memset((caddr_t)sep, 0, sizeof *sep); 841 arg = skip(&cp); 842 if (cp == NULL) { 843 /* got an empty line containing just blanks/tabs. */ 844 goto more; 845 } 846 if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) { 847 char *c = arg + MUX_LEN; 848 if (*c == '+') { 849 sep->se_type = MUXPLUS_TYPE; 850 c++; 851 } else 852 sep->se_type = MUX_TYPE; 853 sep->se_service = newstr(c); 854 } else { 855 sep->se_service = newstr(arg); 856 sep->se_type = NORM_TYPE; 857 } 858 arg = sskip(&cp); 859 if (strcmp(arg, "stream") == 0) 860 sep->se_socktype = SOCK_STREAM; 861 else if (strcmp(arg, "dgram") == 0) 862 sep->se_socktype = SOCK_DGRAM; 863 else if (strcmp(arg, "rdm") == 0) 864 sep->se_socktype = SOCK_RDM; 865 else if (strcmp(arg, "seqpacket") == 0) 866 sep->se_socktype = SOCK_SEQPACKET; 867 else if (strcmp(arg, "raw") == 0) 868 sep->se_socktype = SOCK_RAW; 869 else 870 sep->se_socktype = -1; 871 sep->se_proto = newstr(sskip(&cp)); 872 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 873 sep->se_proto += 4; 874 sep->se_rpc = 1; 875 sep->se_rpc_prog = sep->se_rpc_lowvers = 876 sep->se_rpc_lowvers = 0; 877 sep->se_ctrladdr.sin_family = AF_INET; 878 sep->se_ctrladdr.sin_port = 0; 879 sep->se_ctrladdr.sin_addr.s_addr = htonl(INADDR_ANY); 880 if ((versp = rindex(sep->se_service, '/'))) { 881 *versp++ = '\0'; 882 switch (sscanf(versp, "%d-%d", 883 &sep->se_rpc_lowvers, 884 &sep->se_rpc_highvers)) { 885 case 2: 886 break; 887 case 1: 888 sep->se_rpc_highvers = 889 sep->se_rpc_lowvers; 890 break; 891 default: 892 syslog(LOG_ERR, 893 "bad RPC version specifier; %s\n", 894 sep->se_service); 895 freeconfig(sep); 896 goto more; 897 } 898 } 899 else { 900 sep->se_rpc_lowvers = 901 sep->se_rpc_highvers = 1; 902 } 903 } 904 arg = sskip(&cp); 905 sep->se_wait = strcmp(arg, "wait") == 0; 906 if (ISMUX(sep)) { 907 /* 908 * Silently enforce "nowait" for TCPMUX services since 909 * they don't have an assigned port to listen on. 910 */ 911 sep->se_wait = 0; 912 913 if (strcmp(sep->se_proto, "tcp")) { 914 syslog(LOG_ERR, 915 "%s: bad protocol for tcpmux service %s", 916 CONFIG, sep->se_service); 917 goto more; 918 } 919 if (sep->se_socktype != SOCK_STREAM) { 920 syslog(LOG_ERR, 921 "%s: bad socket type for tcpmux service %s", 922 CONFIG, sep->se_service); 923 goto more; 924 } 925 } 926 sep->se_user = newstr(sskip(&cp)); 927 sep->se_server = newstr(sskip(&cp)); 928 if (strcmp(sep->se_server, "internal") == 0) { 929 struct biltin *bi; 930 931 for (bi = biltins; bi->bi_service; bi++) 932 if (bi->bi_socktype == sep->se_socktype && 933 strcmp(bi->bi_service, sep->se_service) == 0) 934 break; 935 if (bi->bi_service == 0) { 936 syslog(LOG_ERR, "internal service %s unknown", 937 sep->se_service); 938 goto more; 939 } 940 sep->se_bi = bi; 941 sep->se_wait = bi->bi_wait; 942 } else 943 sep->se_bi = NULL; 944 argc = 0; 945 for (arg = skip(&cp); cp; arg = skip(&cp)) 946 if (argc < MAXARGV) 947 sep->se_argv[argc++] = newstr(arg); 948 while (argc <= MAXARGV) 949 sep->se_argv[argc++] = NULL; 950 return (sep); 951 } 952 953 void 954 freeconfig(cp) 955 struct servtab *cp; 956 { 957 int i; 958 959 if (cp->se_service) 960 free(cp->se_service); 961 if (cp->se_proto) 962 free(cp->se_proto); 963 if (cp->se_user) 964 free(cp->se_user); 965 if (cp->se_server) 966 free(cp->se_server); 967 for (i = 0; i < MAXARGV; i++) 968 if (cp->se_argv[i]) 969 free(cp->se_argv[i]); 970 } 971 972 973 /* 974 * Safe skip - if skip returns null, log a syntax error in the 975 * configuration file and exit. 976 */ 977 char * 978 sskip(cpp) 979 char **cpp; 980 { 981 char *cp; 982 983 cp = skip(cpp); 984 if (cp == NULL) { 985 syslog(LOG_ERR, "%s: syntax error", CONFIG); 986 exit(-1); 987 } 988 return (cp); 989 } 990 991 char * 992 skip(cpp) 993 char **cpp; 994 { 995 char *cp = *cpp; 996 char *start; 997 998 again: 999 while (*cp == ' ' || *cp == '\t') 1000 cp++; 1001 if (*cp == '\0') { 1002 int c; 1003 1004 c = getc(fconfig); 1005 (void) ungetc(c, fconfig); 1006 if (c == ' ' || c == '\t') 1007 if (cp = nextline(fconfig)) 1008 goto again; 1009 *cpp = (char *)0; 1010 return ((char *)0); 1011 } 1012 start = cp; 1013 while (*cp && *cp != ' ' && *cp != '\t') 1014 cp++; 1015 if (*cp != '\0') 1016 *cp++ = '\0'; 1017 *cpp = cp; 1018 return (start); 1019 } 1020 1021 char * 1022 nextline(fd) 1023 FILE *fd; 1024 { 1025 char *cp; 1026 1027 if (fgets(line, sizeof (line), fd) == NULL) 1028 return ((char *)0); 1029 cp = strchr(line, '\n'); 1030 if (cp) 1031 *cp = '\0'; 1032 return (line); 1033 } 1034 1035 char * 1036 newstr(cp) 1037 char *cp; 1038 { 1039 if (cp = strdup(cp ? cp : "")) 1040 return (cp); 1041 syslog(LOG_ERR, "strdup: %m"); 1042 exit(-1); 1043 } 1044 1045 void 1046 setproctitle(a, s) 1047 char *a; 1048 int s; 1049 { 1050 int size; 1051 char *cp; 1052 struct sockaddr_in sin; 1053 char buf[80]; 1054 1055 cp = Argv[0]; 1056 size = sizeof(sin); 1057 if (getpeername(s, (struct sockaddr *)&sin, &size) == 0) 1058 (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); 1059 else 1060 (void) sprintf(buf, "-%s", a); 1061 strncpy(cp, buf, LastArg - cp); 1062 cp += strlen(cp); 1063 while (cp < LastArg) 1064 *cp++ = ' '; 1065 } 1066 1067 /* 1068 * Internet services provided internally by inetd: 1069 */ 1070 #define BUFSIZE 8192 1071 1072 /* ARGSUSED */ 1073 void 1074 echo_stream(s, sep) /* Echo service -- echo data back */ 1075 int s; 1076 struct servtab *sep; 1077 { 1078 char buffer[BUFSIZE]; 1079 int i; 1080 1081 setproctitle(sep->se_service, s); 1082 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1083 write(s, buffer, i) > 0) 1084 ; 1085 exit(0); 1086 } 1087 1088 int check_loop(sin, sep) 1089 struct sockaddr_in *sin; 1090 struct servtab *sep; 1091 { 1092 struct servtab *se2; 1093 1094 for (se2 = servtab; se2; se2 = se2->se_next) { 1095 if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM) 1096 continue; 1097 1098 if (sin->sin_port == se2->se_ctrladdr.sin_port) { 1099 syslog(LOG_WARNING, 1100 "%s/%s:%s/%s loop request REFUSED from %s", 1101 sep->se_service, sep->se_proto, 1102 se2->se_service, se2->se_proto, 1103 inet_ntoa(sin->sin_addr)); 1104 return 1; 1105 } 1106 } 1107 return 0; 1108 } 1109 1110 /* ARGSUSED */ 1111 void 1112 echo_dg(s, sep) /* Echo service -- echo data back */ 1113 int s; 1114 struct servtab *sep; 1115 { 1116 char buffer[BUFSIZE]; 1117 int i, size; 1118 struct sockaddr_in sin; 1119 1120 size = sizeof(sin); 1121 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, 1122 (struct sockaddr *)&sin, &size)) < 0) 1123 return; 1124 1125 if (check_loop(&sin, sep)) 1126 return; 1127 1128 (void) sendto(s, buffer, i, 0, (struct sockaddr *)&sin, 1129 sizeof(sin)); 1130 } 1131 1132 /* ARGSUSED */ 1133 void 1134 discard_stream(s, sep) /* Discard service -- ignore data */ 1135 int s; 1136 struct servtab *sep; 1137 { 1138 int ret; 1139 char buffer[BUFSIZE]; 1140 1141 setproctitle(sep->se_service, s); 1142 while (1) { 1143 while ((ret = read(s, buffer, sizeof(buffer))) > 0) 1144 ; 1145 if (ret == 0 || errno != EINTR) 1146 break; 1147 } 1148 exit(0); 1149 } 1150 1151 /* ARGSUSED */ 1152 void 1153 discard_dg(s, sep) /* Discard service -- ignore data */ 1154 int s; 1155 struct servtab *sep; 1156 { 1157 char buffer[BUFSIZE]; 1158 1159 (void) read(s, buffer, sizeof(buffer)); 1160 } 1161 1162 #include <ctype.h> 1163 #define LINESIZ 72 1164 char ring[128]; 1165 char *endring; 1166 1167 void 1168 initring() 1169 { 1170 int i; 1171 1172 endring = ring; 1173 1174 for (i = 0; i <= 128; ++i) 1175 if (isprint(i)) 1176 *endring++ = i; 1177 } 1178 1179 /* ARGSUSED */ 1180 void 1181 chargen_stream(s, sep) /* Character generator */ 1182 int s; 1183 struct servtab *sep; 1184 { 1185 int len; 1186 char *rs, text[LINESIZ+2]; 1187 1188 setproctitle(sep->se_service, s); 1189 1190 if (!endring) { 1191 initring(); 1192 rs = ring; 1193 } 1194 1195 text[LINESIZ] = '\r'; 1196 text[LINESIZ + 1] = '\n'; 1197 for (rs = ring;;) { 1198 if ((len = endring - rs) >= LINESIZ) 1199 memmove(text, rs, LINESIZ); 1200 else { 1201 memmove(text, rs, len); 1202 memmove(text + len, ring, LINESIZ - len); 1203 } 1204 if (++rs == endring) 1205 rs = ring; 1206 if (write(s, text, sizeof(text)) != sizeof(text)) 1207 break; 1208 } 1209 exit(0); 1210 } 1211 1212 /* ARGSUSED */ 1213 void 1214 chargen_dg(s, sep) /* Character generator */ 1215 int s; 1216 struct servtab *sep; 1217 { 1218 struct sockaddr_in sin; 1219 static char *rs; 1220 int len, size; 1221 char text[LINESIZ+2]; 1222 1223 if (endring == 0) { 1224 initring(); 1225 rs = ring; 1226 } 1227 1228 size = sizeof(sin); 1229 if (recvfrom(s, text, sizeof(text), 0, 1230 (struct sockaddr *)&sin, &size) < 0) 1231 return; 1232 1233 if (check_loop(&sin, sep)) 1234 return; 1235 1236 if ((len = endring - rs) >= LINESIZ) 1237 memmove(text, rs, LINESIZ); 1238 else { 1239 memmove(text, rs, len); 1240 memmove(text + len, ring, LINESIZ - len); 1241 } 1242 if (++rs == endring) 1243 rs = ring; 1244 text[LINESIZ] = '\r'; 1245 text[LINESIZ + 1] = '\n'; 1246 (void) sendto(s, text, sizeof(text), 0, 1247 (struct sockaddr *)&sin, sizeof(sin)); 1248 } 1249 1250 /* 1251 * Return a machine readable date and time, in the form of the 1252 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1253 * returns the number of seconds since midnight, Jan 1, 1970, 1254 * we must add 2208988800 seconds to this figure to make up for 1255 * some seventy years Bell Labs was asleep. 1256 */ 1257 1258 long 1259 machtime() 1260 { 1261 struct timeval tv; 1262 1263 if (gettimeofday(&tv, (struct timezone *)0) < 0) { 1264 if (debug) 1265 fprintf(stderr, "Unable to get time of day\n"); 1266 return (0L); 1267 } 1268 #define OFFSET ((u_long)25567 * 24*60*60) 1269 return (htonl((long)(tv.tv_sec + OFFSET))); 1270 #undef OFFSET 1271 } 1272 1273 /* ARGSUSED */ 1274 void 1275 machtime_stream(s, sep) 1276 int s; 1277 struct servtab *sep; 1278 { 1279 long result; 1280 1281 result = machtime(); 1282 (void) write(s, (char *) &result, sizeof(result)); 1283 } 1284 1285 /* ARGSUSED */ 1286 void 1287 machtime_dg(s, sep) 1288 int s; 1289 struct servtab *sep; 1290 { 1291 long result; 1292 struct sockaddr_in sin; 1293 int size; 1294 1295 size = sizeof(sin); 1296 if (recvfrom(s, (char *)&result, sizeof(result), 0, 1297 (struct sockaddr *)&sin, &size) < 0) 1298 return; 1299 1300 if (check_loop(&sin, sep)) 1301 return; 1302 1303 result = machtime(); 1304 (void) sendto(s, (char *) &result, sizeof(result), 0, 1305 (struct sockaddr *)&sin, sizeof(sin)); 1306 } 1307 1308 /* ARGSUSED */ 1309 void 1310 daytime_stream(s, sep) /* Return human-readable time of day */ 1311 int s; 1312 struct servtab *sep; 1313 { 1314 char buffer[256]; 1315 time_t clock; 1316 1317 clock = time((time_t *) 0); 1318 1319 (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); 1320 (void) write(s, buffer, strlen(buffer)); 1321 } 1322 1323 /* ARGSUSED */ 1324 void 1325 daytime_dg(s, sep) /* Return human-readable time of day */ 1326 int s; 1327 struct servtab *sep; 1328 { 1329 char buffer[256]; 1330 time_t clock; 1331 struct sockaddr_in sin; 1332 int size; 1333 1334 clock = time((time_t *) 0); 1335 1336 size = sizeof(sin); 1337 if (recvfrom(s, buffer, sizeof(buffer), 0, 1338 (struct sockaddr *)&sin, &size) < 0) 1339 return; 1340 1341 if (check_loop(&sin, sep)) 1342 return; 1343 1344 (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); 1345 (void) sendto(s, buffer, strlen(buffer), 0, 1346 (struct sockaddr *)&sin, sizeof(sin)); 1347 } 1348 1349 /* 1350 * print_service: 1351 * Dump relevant information to stderr 1352 */ 1353 void 1354 print_service(action, sep) 1355 char *action; 1356 struct servtab *sep; 1357 { 1358 if(sep->se_rpc) 1359 fprintf(stderr, 1360 "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n", 1361 action, sep->se_service, sep->se_proto, 1362 sep->se_wait, sep->se_user, (int)sep->se_bi, 1363 sep->se_server); 1364 else 1365 fprintf(stderr, 1366 "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n", 1367 action, sep->se_service, sep->se_proto, 1368 sep->se_wait, sep->se_user, (int)sep->se_bi, 1369 sep->se_server); 1370 } 1371 1372 /* 1373 * Based on TCPMUX.C by Mark K. Lottor November 1988 1374 * sri-nic::ps:<mkl>tcpmux.c 1375 */ 1376 1377 1378 static int /* # of characters upto \r,\n or \0 */ 1379 getline(fd, buf, len) 1380 int fd; 1381 char *buf; 1382 int len; 1383 { 1384 int count = 0, n; 1385 1386 do { 1387 n = read(fd, buf, len-count); 1388 if (n == 0) 1389 return (count); 1390 if (n < 0) 1391 return (-1); 1392 while (--n >= 0) { 1393 if (*buf == '\r' || *buf == '\n' || *buf == '\0') 1394 return (count); 1395 count++; 1396 buf++; 1397 } 1398 } while (count < len); 1399 return (count); 1400 } 1401 1402 #define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */ 1403 1404 #define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1) 1405 1406 struct servtab * 1407 tcpmux(s) 1408 int s; 1409 { 1410 struct servtab *sep; 1411 char service[MAX_SERV_LEN+1]; 1412 int len; 1413 1414 /* Get requested service name */ 1415 if ((len = getline(s, service, MAX_SERV_LEN)) < 0) { 1416 strwrite(s, "-Error reading service name\r\n"); 1417 return (NULL); 1418 } 1419 service[len] = '\0'; 1420 1421 if (debug) 1422 fprintf(stderr, "tcpmux: someone wants %s\n", service); 1423 1424 /* 1425 * Help is a required command, and lists available services, 1426 * one per line. 1427 */ 1428 if (!strcasecmp(service, "help")) { 1429 for (sep = servtab; sep; sep = sep->se_next) { 1430 if (!ISMUX(sep)) 1431 continue; 1432 (void)write(s,sep->se_service,strlen(sep->se_service)); 1433 strwrite(s, "\r\n"); 1434 } 1435 return (NULL); 1436 } 1437 1438 /* Try matching a service in inetd.conf with the request */ 1439 for (sep = servtab; sep; sep = sep->se_next) { 1440 if (!ISMUX(sep)) 1441 continue; 1442 if (!strcasecmp(service, sep->se_service)) { 1443 if (ISMUXPLUS(sep)) { 1444 strwrite(s, "+Go\r\n"); 1445 } 1446 return (sep); 1447 } 1448 } 1449 strwrite(s, "-Service not available\r\n"); 1450 return (NULL); 1451 } 1452