1 /* 2 * Copyright (c) 1983,1991 The Regents of the University of California. 3 * 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 char copyright[] = 36 "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 37 All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 static char sccsid[] = "@(#)inetd.c 5.30 (Berkeley) 6/3/91"; 42 #endif /* not lint */ 43 44 /* 45 * Inetd - Internet super-server 46 * 47 * This program invokes all internet services as needed. 48 * connection-oriented services are invoked each time a 49 * connection is made, by creating a process. This process 50 * is passed the connection as file descriptor 0 and is 51 * expected to do a getpeername to find out the source host 52 * 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 70 * socket type stream/dgram/raw/rdm/seqpacket 71 * protocol must be in /etc/protocols 72 * wait/nowait single-threaded/multi-threaded 73 * user user to run daemon as 74 * server program full path name 75 * server program arguments maximum of MAXARGS (20) 76 * 77 * For RPC services 78 * service name/version must be in /etc/rpc 79 * socket type stream/dgram/raw/rdm/seqpacket 80 * protocol must be in /etc/protocols 81 * wait/nowait single-threaded/multi-threaded 82 * user user to run daemon as 83 * server program full path name 84 * server program arguments maximum of MAXARGS (20) 85 * 86 * Comment lines are indicated by a `#' in column 1. 87 */ 88 #include <sys/param.h> 89 #include <sys/stat.h> 90 #include <sys/ioctl.h> 91 #include <sys/socket.h> 92 #include <sys/file.h> 93 #include <sys/wait.h> 94 #include <sys/time.h> 95 #include <sys/resource.h> 96 97 #include <netinet/in.h> 98 #include <arpa/inet.h> 99 100 #include <errno.h> 101 #include <signal.h> 102 #include <netdb.h> 103 #include <syslog.h> 104 #include <pwd.h> 105 #include <stdio.h> 106 #include <string.h> 107 #include <rpc/rpc.h> 108 #include "pathnames.h" 109 110 #define TOOMANY 40 /* don't start more than TOOMANY */ 111 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ 112 #define RETRYTIME (60*10) /* retry after bind or server fail */ 113 114 #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM)) 115 116 void config(), reapchild(), retry(), unregisterrpc(); 117 118 int debug = 0; 119 int nsock, maxsock; 120 fd_set allsock; 121 int options; 122 int timingout; 123 struct servent *sp; 124 struct rpcent *rpc; 125 126 struct servtab { 127 char *se_service; /* name of service */ 128 int se_socktype; /* type of socket to use */ 129 char *se_proto; /* protocol used */ 130 short se_wait; /* single threaded server */ 131 short se_checked; /* looked at during merge */ 132 char *se_user; /* user name to run as */ 133 struct biltin *se_bi; /* if built-in, description */ 134 char *se_server; /* server program */ 135 #define MAXARGV 20 136 char *se_argv[MAXARGV+1]; /* program arguments */ 137 int se_fd; /* open descriptor */ 138 struct sockaddr_in se_ctrladdr;/* bound address */ 139 int se_rpc; /* ==1 if this is an RPC service */ 140 int se_rpc_prog; /* RPC program number */ 141 u_int se_rpc_lowvers; /* RPC low version */ 142 u_int se_rpc_highvers; /* RPC high version */ 143 int se_count; /* number started since se_time */ 144 struct timeval se_time; /* start of se_count */ 145 struct servtab *se_next; 146 } *servtab; 147 148 int echo_stream(), discard_stream(), machtime_stream(); 149 int daytime_stream(), chargen_stream(); 150 int echo_dg(), discard_dg(), machtime_dg(), daytime_dg(), chargen_dg(); 151 152 struct biltin { 153 char *bi_service; /* internally provided service name */ 154 int bi_socktype; /* type of socket supported */ 155 short bi_fork; /* 1 if should fork before call */ 156 short bi_wait; /* 1 if should wait for child */ 157 int (*bi_fn)(); /* function which performs it */ 158 } biltins[] = { 159 /* Echo received data */ 160 "echo", SOCK_STREAM, 1, 0, echo_stream, 161 "echo", SOCK_DGRAM, 0, 0, echo_dg, 162 163 /* Internet /dev/null */ 164 "discard", SOCK_STREAM, 1, 0, discard_stream, 165 "discard", SOCK_DGRAM, 0, 0, discard_dg, 166 167 /* Return 32 bit time since 1970 */ 168 "time", SOCK_STREAM, 0, 0, machtime_stream, 169 "time", SOCK_DGRAM, 0, 0, machtime_dg, 170 171 /* Return human-readable time */ 172 "daytime", SOCK_STREAM, 0, 0, daytime_stream, 173 "daytime", SOCK_DGRAM, 0, 0, daytime_dg, 174 175 /* Familiar character generator */ 176 "chargen", SOCK_STREAM, 1, 0, chargen_stream, 177 "chargen", SOCK_DGRAM, 0, 0, chargen_dg, 178 0 179 }; 180 181 #define NUMINT (sizeof(intab) / sizeof(struct inent)) 182 char *CONFIG = _PATH_INETDCONF; 183 char **Argv; 184 char *LastArg; 185 186 main(argc, argv, envp) 187 int argc; 188 char *argv[], *envp[]; 189 { 190 extern char *optarg; 191 extern int optind; 192 register struct servtab *sep; 193 register struct passwd *pwd; 194 register int tmpint; 195 struct sigvec sv; 196 int ch, pid, dofork; 197 char buf[50]; 198 199 Argv = argv; 200 if (envp == 0 || *envp == 0) 201 envp = argv; 202 while (*envp) 203 envp++; 204 LastArg = envp[-1] + strlen(envp[-1]); 205 206 while ((ch = getopt(argc, argv, "d")) != EOF) 207 switch(ch) { 208 case 'd': 209 debug = 1; 210 options |= SO_DEBUG; 211 break; 212 case '?': 213 default: 214 fprintf(stderr, "usage: inetd [-d]"); 215 exit(1); 216 } 217 argc -= optind; 218 argv += optind; 219 220 if (argc > 0) 221 CONFIG = argv[0]; 222 if (debug == 0) 223 daemon(0, 0); 224 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); 225 bzero((char *)&sv, sizeof(sv)); 226 sv.sv_mask = SIGBLOCK; 227 sv.sv_handler = retry; 228 sigvec(SIGALRM, &sv, (struct sigvec *)0); 229 config(); 230 sv.sv_handler = config; 231 sigvec(SIGHUP, &sv, (struct sigvec *)0); 232 sv.sv_handler = reapchild; 233 sigvec(SIGCHLD, &sv, (struct sigvec *)0); 234 235 { 236 /* space for daemons to overwrite environment for ps */ 237 #define DUMMYSIZE 100 238 char dummy[DUMMYSIZE]; 239 240 (void)memset(dummy, 'x', sizeof(DUMMYSIZE) - 1); 241 dummy[DUMMYSIZE - 1] = '\0'; 242 (void)setenv("inetd_dummy", dummy, 1); 243 } 244 245 for (;;) { 246 int n, ctrl; 247 fd_set readable; 248 249 if (nsock == 0) { 250 (void) sigblock(SIGBLOCK); 251 while (nsock == 0) 252 sigpause(0L); 253 (void) sigsetmask(0L); 254 } 255 readable = allsock; 256 if ((n = select(maxsock + 1, &readable, (fd_set *)0, 257 (fd_set *)0, (struct timeval *)0)) <= 0) { 258 if (n < 0 && errno != EINTR) 259 syslog(LOG_WARNING, "select: %m\n"); 260 sleep(1); 261 continue; 262 } 263 for (sep = servtab; n && sep; sep = sep->se_next) 264 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) { 265 n--; 266 if (debug) 267 fprintf(stderr, "someone wants %s\n", 268 sep->se_service); 269 if (sep->se_socktype == SOCK_STREAM) { 270 ctrl = accept(sep->se_fd, (struct sockaddr *)0, 271 (int *)0); 272 if (debug) 273 fprintf(stderr, "accept, ctrl %d\n", ctrl); 274 if (ctrl < 0) { 275 if (errno == EINTR) 276 continue; 277 syslog(LOG_WARNING, "accept (for %s): %m", 278 sep->se_service); 279 continue; 280 } 281 } else 282 ctrl = sep->se_fd; 283 (void) sigblock(SIGBLOCK); 284 pid = 0; 285 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); 286 if (dofork) { 287 if (sep->se_count++ == 0) 288 (void)gettimeofday(&sep->se_time, 289 (struct timezone *)0); 290 else if (sep->se_count >= TOOMANY) { 291 struct timeval now; 292 293 (void)gettimeofday(&now, (struct timezone *)0); 294 if (now.tv_sec - sep->se_time.tv_sec > 295 CNT_INTVL) { 296 sep->se_time = now; 297 sep->se_count = 1; 298 } else { 299 syslog(LOG_ERR, 300 "%s/%s server failing (looping), service terminated\n", 301 sep->se_service, sep->se_proto); 302 FD_CLR(sep->se_fd, &allsock); 303 (void) close(sep->se_fd); 304 sep->se_fd = -1; 305 sep->se_count = 0; 306 nsock--; 307 if (!timingout) { 308 timingout = 1; 309 alarm(RETRYTIME); 310 } 311 } 312 } 313 pid = fork(); 314 } 315 if (pid < 0) { 316 syslog(LOG_ERR, "fork: %m"); 317 if (sep->se_socktype == SOCK_STREAM) 318 close(ctrl); 319 sigsetmask(0L); 320 sleep(1); 321 continue; 322 } 323 if (pid && sep->se_wait) { 324 sep->se_wait = pid; 325 if (sep->se_fd >= 0) { 326 FD_CLR(sep->se_fd, &allsock); 327 nsock--; 328 } 329 } 330 sigsetmask(0L); 331 if (pid == 0) { 332 if (debug && dofork) 333 setsid(); 334 if (dofork) 335 for (tmpint = maxsock; --tmpint > 2; ) 336 if (tmpint != ctrl) 337 close(tmpint); 338 if (sep->se_bi) 339 (*sep->se_bi->bi_fn)(ctrl, sep); 340 else { 341 if (debug) 342 fprintf(stderr, "%d execl %s\n", 343 getpid(), sep->se_server); 344 dup2(ctrl, 0); 345 close(ctrl); 346 dup2(0, 1); 347 dup2(0, 2); 348 if ((pwd = getpwnam(sep->se_user)) == NULL) { 349 syslog(LOG_ERR, 350 "getpwnam: %s: No such user", 351 sep->se_user); 352 if (sep->se_socktype != SOCK_STREAM) 353 recv(0, buf, sizeof (buf), 0); 354 _exit(1); 355 } 356 if (pwd->pw_uid) { 357 (void) setgid((gid_t)pwd->pw_gid); 358 initgroups(pwd->pw_name, pwd->pw_gid); 359 (void) setuid((uid_t)pwd->pw_uid); 360 } 361 execv(sep->se_server, sep->se_argv); 362 if (sep->se_socktype != SOCK_STREAM) 363 recv(0, buf, sizeof (buf), 0); 364 syslog(LOG_ERR, "execv %s: %m", sep->se_server); 365 _exit(1); 366 } 367 } 368 if (sep->se_socktype == SOCK_STREAM) 369 close(ctrl); 370 } 371 } 372 } 373 374 void 375 reapchild() 376 { 377 int status; 378 int pid; 379 register struct servtab *sep; 380 381 for (;;) { 382 pid = wait3(&status, WNOHANG, (struct rusage *)0); 383 if (pid <= 0) 384 break; 385 if (debug) 386 fprintf(stderr, "%d reaped\n", pid); 387 for (sep = servtab; sep; sep = sep->se_next) 388 if (sep->se_wait == pid) { 389 if (status) 390 syslog(LOG_WARNING, 391 "%s: exit status 0x%x", 392 sep->se_server, status); 393 if (debug) 394 fprintf(stderr, "restored %s, fd %d\n", 395 sep->se_service, sep->se_fd); 396 FD_SET(sep->se_fd, &allsock); 397 nsock++; 398 sep->se_wait = 1; 399 } 400 } 401 } 402 403 void 404 config() 405 { 406 register struct servtab *sep, *cp, **sepp; 407 struct servtab *getconfigent(), *enter(); 408 long omask; 409 410 if (!setconfig()) { 411 syslog(LOG_ERR, "%s: %m", CONFIG); 412 return; 413 } 414 for (sep = servtab; sep; sep = sep->se_next) 415 sep->se_checked = 0; 416 while (cp = getconfigent()) { 417 for (sep = servtab; sep; sep = sep->se_next) 418 if (strcmp(sep->se_service, cp->se_service) == 0 && 419 strcmp(sep->se_proto, cp->se_proto) == 0) 420 break; 421 if (sep != 0) { 422 int i; 423 424 omask = sigblock(SIGBLOCK); 425 /* 426 * sep->se_wait may be holding the pid of a daemon 427 * that we're waiting for. If so, don't overwrite 428 * it unless the config file explicitly says don't 429 * wait. 430 */ 431 if (cp->se_bi == 0 && 432 (sep->se_wait == 1 || cp->se_wait == 0)) 433 sep->se_wait = cp->se_wait; 434 #define SWAP(a, b) { char *c = a; a = b; b = c; } 435 if (cp->se_user) 436 SWAP(sep->se_user, cp->se_user); 437 if (cp->se_server) 438 SWAP(sep->se_server, cp->se_server); 439 for (i = 0; i < MAXARGV; i++) 440 SWAP(sep->se_argv[i], cp->se_argv[i]); 441 sigsetmask(omask); 442 freeconfig(cp); 443 if (debug) 444 print_service("REDO", sep); 445 } else { 446 sep = enter(cp); 447 if (debug) 448 print_service("ADD ", sep); 449 } 450 sep->se_checked = 1; 451 if (!sep->se_rpc) { 452 sp = getservbyname(sep->se_service, sep->se_proto); 453 if (sp == 0) { 454 syslog(LOG_ERR, "%s/%s: unknown service", 455 sep->se_service, sep->se_proto); 456 if (sep->se_fd != -1) 457 (void) close(sep->se_fd); 458 sep->se_fd = -1; 459 continue; 460 } 461 if (sp->s_port != sep->se_ctrladdr.sin_port) { 462 sep->se_ctrladdr.sin_port = sp->s_port; 463 if (sep->se_fd != -1) 464 (void) close(sep->se_fd); 465 sep->se_fd = -1; 466 } 467 } 468 else { 469 rpc = getrpcbyname(sep->se_service); 470 if (rpc == 0) { 471 syslog(LOG_ERR, "%s/%s unknown RPC service.", 472 sep->se_service, sep->se_proto); 473 if (sep->se_fd != -1) 474 (void) close(sep->se_fd); 475 sep->se_fd = -1; 476 continue; 477 } 478 if (rpc->r_number != sep->se_rpc_prog) { 479 if (sep->se_rpc_prog) 480 unregisterrpc(sep); 481 sep->se_rpc_prog = rpc->r_number; 482 if (sep->se_fd != -1) 483 (void) close(sep->se_fd); 484 sep->se_fd = -1; 485 } 486 } 487 488 if (sep->se_fd == -1) 489 setup(sep); 490 } 491 endconfig(); 492 /* 493 * Purge anything not looked at above. 494 */ 495 omask = sigblock(SIGBLOCK); 496 sepp = &servtab; 497 while (sep = *sepp) { 498 if (sep->se_checked) { 499 sepp = &sep->se_next; 500 continue; 501 } 502 *sepp = sep->se_next; 503 if (sep->se_fd != -1) { 504 FD_CLR(sep->se_fd, &allsock); 505 nsock--; 506 (void) close(sep->se_fd); 507 } 508 if (debug) 509 print_service("FREE", sep); 510 if (sep->se_rpc && sep->se_rpc_prog > 0) 511 unregisterrpc(sep); 512 freeconfig(sep); 513 free((char *)sep); 514 } 515 (void) sigsetmask(omask); 516 } 517 518 void 519 unregisterrpc(sep) 520 register struct servtab *sep; 521 { 522 int i; 523 struct servtab *sepp; 524 long omask; 525 526 omask = sigblock(SIGBLOCK); 527 for (sepp = servtab; sepp; sepp = sepp->se_next) { 528 if (sepp == sep) 529 continue; 530 if (sep->se_checked == 0 || 531 !sepp->se_rpc || 532 sep->se_rpc_prog != sepp->se_rpc_prog) 533 continue; 534 return; 535 } 536 if (debug) 537 print_service("UNREG", sep); 538 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) 539 pmap_unset(sep->se_rpc_prog, i); 540 if (sep->se_fd != -1) 541 (void) close(sep->se_fd); 542 sep->se_fd = -1; 543 (void) sigsetmask(omask); 544 } 545 546 void 547 retry() 548 { 549 register struct servtab *sep; 550 551 timingout = 0; 552 for (sep = servtab; sep; sep = sep->se_next) 553 if (sep->se_fd == -1) 554 setup(sep); 555 } 556 557 setup(sep) 558 register struct servtab *sep; 559 { 560 int on = 1; 561 562 if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) { 563 syslog(LOG_ERR, "%s/%s: socket: %m", 564 sep->se_service, sep->se_proto); 565 return; 566 } 567 #define turnon(fd, opt) \ 568 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) 569 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && 570 turnon(sep->se_fd, SO_DEBUG) < 0) 571 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 572 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 573 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 574 #undef turnon 575 if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr, 576 sizeof (sep->se_ctrladdr)) < 0) { 577 syslog(LOG_ERR, "%s/%s: bind: %m", 578 sep->se_service, sep->se_proto); 579 (void) close(sep->se_fd); 580 sep->se_fd = -1; 581 if (!timingout) { 582 timingout = 1; 583 alarm(RETRYTIME); 584 } 585 return; 586 } 587 if (sep->se_rpc) { 588 int i, len; 589 if (getsockname(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr, 590 &len) < 0) { 591 syslog(LOG_ERR, "%s/%s: getsockname: %m", 592 sep->se_service, sep->se_proto); 593 (void) close(sep->se_fd); 594 sep->se_fd = -1; 595 return; 596 } 597 if (debug) 598 print_service("REG ", sep); 599 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) { 600 pmap_unset(sep->se_rpc_prog, i); 601 pmap_set(sep->se_rpc_prog, i, 602 (sep->se_socktype == SOCK_DGRAM) 603 ? IPPROTO_UDP : IPPROTO_TCP, 604 ntohs(sep->se_ctrladdr.sin_port)); 605 } 606 607 } 608 if (sep->se_socktype == SOCK_STREAM) 609 listen(sep->se_fd, 10); 610 FD_SET(sep->se_fd, &allsock); 611 nsock++; 612 if (sep->se_fd > maxsock) 613 maxsock = sep->se_fd; 614 } 615 616 struct servtab * 617 enter(cp) 618 struct servtab *cp; 619 { 620 register struct servtab *sep; 621 long omask; 622 623 sep = (struct servtab *)malloc(sizeof (*sep)); 624 if (sep == (struct servtab *)0) { 625 syslog(LOG_ERR, "Out of memory."); 626 exit(-1); 627 } 628 *sep = *cp; 629 sep->se_fd = -1; 630 omask = sigblock(SIGBLOCK); 631 sep->se_next = servtab; 632 servtab = sep; 633 sigsetmask(omask); 634 return (sep); 635 } 636 637 FILE *fconfig = NULL; 638 struct servtab serv; 639 char line[256]; 640 char *skip(), *nextline(); 641 642 setconfig() 643 { 644 645 if (fconfig != NULL) { 646 fseek(fconfig, 0L, L_SET); 647 return (1); 648 } 649 fconfig = fopen(CONFIG, "r"); 650 return (fconfig != NULL); 651 } 652 653 endconfig() 654 { 655 if (fconfig) { 656 (void) fclose(fconfig); 657 fconfig = NULL; 658 } 659 } 660 661 struct servtab * 662 getconfigent() 663 { 664 register struct servtab *sep = &serv; 665 int argc; 666 char *cp, *arg, *newstr(); 667 char *versp; 668 669 more: 670 while ((cp = nextline(fconfig)) && *cp == '#') 671 ; 672 if (cp == NULL) 673 return ((struct servtab *)0); 674 sep->se_service = newstr(skip(&cp)); 675 arg = skip(&cp); 676 if (strcmp(arg, "stream") == 0) 677 sep->se_socktype = SOCK_STREAM; 678 else if (strcmp(arg, "dgram") == 0) 679 sep->se_socktype = SOCK_DGRAM; 680 else if (strcmp(arg, "rdm") == 0) 681 sep->se_socktype = SOCK_RDM; 682 else if (strcmp(arg, "seqpacket") == 0) 683 sep->se_socktype = SOCK_SEQPACKET; 684 else if (strcmp(arg, "raw") == 0) 685 sep->se_socktype = SOCK_RAW; 686 else 687 sep->se_socktype = -1; 688 sep->se_proto = newstr(skip(&cp)); 689 sep->se_rpc = 0; 690 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 691 sep->se_proto += 4; 692 sep->se_rpc = 1; 693 sep->se_rpc_prog = sep->se_rpc_lowvers = sep->se_rpc_lowvers = 0; 694 sep->se_ctrladdr.sin_family = AF_INET; 695 sep->se_ctrladdr.sin_port = 0; 696 sep->se_ctrladdr.sin_addr.s_addr = htonl(INADDR_ANY); 697 if (versp = rindex(sep->se_service, '/')) { 698 *versp++ = '\0'; 699 switch (sscanf(versp, "%d-%d", 700 &sep->se_rpc_lowvers, 701 &sep->se_rpc_highvers)) { 702 case 2: 703 break; 704 case 1: 705 sep->se_rpc_highvers = 706 sep->se_rpc_lowvers; 707 break; 708 default: 709 syslog(LOG_ERR, "bad RPC version specifier; %s\n", sep->se_service); 710 freeconfig(sep); 711 goto more; 712 } 713 } 714 else { 715 sep->se_rpc_lowvers = 716 sep->se_rpc_highvers = 1; 717 } 718 } 719 arg = skip(&cp); 720 sep->se_wait = strcmp(arg, "wait") == 0; 721 sep->se_user = newstr(skip(&cp)); 722 sep->se_server = newstr(skip(&cp)); 723 if (strcmp(sep->se_server, "internal") == 0) { 724 register struct biltin *bi; 725 726 for (bi = biltins; bi->bi_service; bi++) 727 if (bi->bi_socktype == sep->se_socktype && 728 strcmp(bi->bi_service, sep->se_service) == 0) 729 break; 730 if (bi->bi_service == 0) { 731 syslog(LOG_ERR, "internal service %s unknown\n", 732 sep->se_service); 733 goto more; 734 } 735 sep->se_bi = bi; 736 sep->se_wait = bi->bi_wait; 737 } else 738 sep->se_bi = NULL; 739 argc = 0; 740 for (arg = skip(&cp); cp; arg = skip(&cp)) 741 if (argc < MAXARGV) 742 sep->se_argv[argc++] = newstr(arg); 743 while (argc <= MAXARGV) 744 sep->se_argv[argc++] = NULL; 745 return (sep); 746 } 747 748 freeconfig(cp) 749 register struct servtab *cp; 750 { 751 int i; 752 753 if (cp->se_service) 754 free(cp->se_service); 755 if (cp->se_proto) 756 free(cp->se_proto); 757 if (cp->se_user) 758 free(cp->se_user); 759 if (cp->se_server) 760 free(cp->se_server); 761 for (i = 0; i < MAXARGV; i++) 762 if (cp->se_argv[i]) 763 free(cp->se_argv[i]); 764 } 765 766 char * 767 skip(cpp) 768 char **cpp; 769 { 770 register char *cp = *cpp; 771 char *start; 772 773 again: 774 while (*cp == ' ' || *cp == '\t') 775 cp++; 776 if (*cp == '\0') { 777 int c; 778 779 c = getc(fconfig); 780 (void) ungetc(c, fconfig); 781 if (c == ' ' || c == '\t') 782 if (cp = nextline(fconfig)) 783 goto again; 784 *cpp = (char *)0; 785 return ((char *)0); 786 } 787 start = cp; 788 while (*cp && *cp != ' ' && *cp != '\t') 789 cp++; 790 if (*cp != '\0') 791 *cp++ = '\0'; 792 *cpp = cp; 793 return (start); 794 } 795 796 char * 797 nextline(fd) 798 FILE *fd; 799 { 800 char *cp; 801 802 if (fgets(line, sizeof (line), fd) == NULL) 803 return ((char *)0); 804 cp = index(line, '\n'); 805 if (cp) 806 *cp = '\0'; 807 return (line); 808 } 809 810 char * 811 newstr(cp) 812 char *cp; 813 { 814 if (cp = strdup(cp ? cp : "")) 815 return(cp); 816 syslog(LOG_ERR, "strdup: %m"); 817 exit(-1); 818 } 819 820 setproctitle(a, s) 821 char *a; 822 int s; 823 { 824 int size; 825 register char *cp; 826 struct sockaddr_in sin; 827 char buf[80]; 828 829 cp = Argv[0]; 830 size = sizeof(sin); 831 if (getpeername(s, (struct sockaddr *)&sin, &size) == 0) 832 (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); 833 else 834 (void) sprintf(buf, "-%s", a); 835 strncpy(cp, buf, LastArg - cp); 836 cp += strlen(cp); 837 while (cp < LastArg) 838 *cp++ = ' '; 839 } 840 841 /* 842 * Internet services provided internally by inetd: 843 */ 844 #define BUFSIZE 8192 845 846 /* ARGSUSED */ 847 echo_stream(s, sep) /* Echo service -- echo data back */ 848 int s; 849 struct servtab *sep; 850 { 851 char buffer[BUFSIZE]; 852 int i; 853 854 setproctitle(sep->se_service, s); 855 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 856 write(s, buffer, i) > 0) 857 ; 858 exit(0); 859 } 860 861 /* ARGSUSED */ 862 echo_dg(s, sep) /* Echo service -- echo data back */ 863 int s; 864 struct servtab *sep; 865 { 866 char buffer[BUFSIZE]; 867 int i, size; 868 struct sockaddr sa; 869 870 size = sizeof(sa); 871 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0) 872 return; 873 (void) sendto(s, buffer, i, 0, &sa, sizeof(sa)); 874 } 875 876 /* ARGSUSED */ 877 discard_stream(s, sep) /* Discard service -- ignore data */ 878 int s; 879 struct servtab *sep; 880 { 881 int ret; 882 char buffer[BUFSIZE]; 883 884 setproctitle(sep->se_service, s); 885 while (1) { 886 while ((ret = read(s, buffer, sizeof(buffer))) > 0) 887 ; 888 if (ret == 0 || errno != EINTR) 889 break; 890 } 891 exit(0); 892 } 893 894 /* ARGSUSED */ 895 discard_dg(s, sep) /* Discard service -- ignore data */ 896 int s; 897 struct servtab *sep; 898 { 899 char buffer[BUFSIZE]; 900 901 (void) read(s, buffer, sizeof(buffer)); 902 } 903 904 #include <ctype.h> 905 #define LINESIZ 72 906 char ring[128]; 907 char *endring; 908 909 initring() 910 { 911 register int i; 912 913 endring = ring; 914 915 for (i = 0; i <= 128; ++i) 916 if (isprint(i)) 917 *endring++ = i; 918 } 919 920 /* ARGSUSED */ 921 chargen_stream(s, sep) /* Character generator */ 922 int s; 923 struct servtab *sep; 924 { 925 register char *rs; 926 int len; 927 char text[LINESIZ+2]; 928 929 setproctitle(sep->se_service, s); 930 931 if (!endring) { 932 initring(); 933 rs = ring; 934 } 935 936 text[LINESIZ] = '\r'; 937 text[LINESIZ + 1] = '\n'; 938 for (rs = ring;;) { 939 if ((len = endring - rs) >= LINESIZ) 940 bcopy(rs, text, LINESIZ); 941 else { 942 bcopy(rs, text, len); 943 bcopy(ring, text + len, LINESIZ - len); 944 } 945 if (++rs == endring) 946 rs = ring; 947 if (write(s, text, sizeof(text)) != sizeof(text)) 948 break; 949 } 950 exit(0); 951 } 952 953 /* ARGSUSED */ 954 chargen_dg(s, sep) /* Character generator */ 955 int s; 956 struct servtab *sep; 957 { 958 struct sockaddr sa; 959 static char *rs; 960 int len, size; 961 char text[LINESIZ+2]; 962 963 if (endring == 0) { 964 initring(); 965 rs = ring; 966 } 967 968 size = sizeof(sa); 969 if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0) 970 return; 971 972 if ((len = endring - rs) >= LINESIZ) 973 bcopy(rs, text, LINESIZ); 974 else { 975 bcopy(rs, text, len); 976 bcopy(ring, text + len, LINESIZ - len); 977 } 978 if (++rs == endring) 979 rs = ring; 980 text[LINESIZ] = '\r'; 981 text[LINESIZ + 1] = '\n'; 982 (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa)); 983 } 984 985 /* 986 * Return a machine readable date and time, in the form of the 987 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 988 * returns the number of seconds since midnight, Jan 1, 1970, 989 * we must add 2208988800 seconds to this figure to make up for 990 * some seventy years Bell Labs was asleep. 991 */ 992 993 long 994 machtime() 995 { 996 struct timeval tv; 997 998 if (gettimeofday(&tv, (struct timezone *)0) < 0) { 999 fprintf(stderr, "Unable to get time of day\n"); 1000 return (0L); 1001 } 1002 return (htonl((long)tv.tv_sec + 2208988800)); 1003 } 1004 1005 /* ARGSUSED */ 1006 machtime_stream(s, sep) 1007 int s; 1008 struct servtab *sep; 1009 { 1010 long result; 1011 1012 result = machtime(); 1013 (void) write(s, (char *) &result, sizeof(result)); 1014 } 1015 1016 /* ARGSUSED */ 1017 machtime_dg(s, sep) 1018 int s; 1019 struct servtab *sep; 1020 { 1021 long result; 1022 struct sockaddr sa; 1023 int size; 1024 1025 size = sizeof(sa); 1026 if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0) 1027 return; 1028 result = machtime(); 1029 (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa)); 1030 } 1031 1032 /* ARGSUSED */ 1033 daytime_stream(s, sep) /* Return human-readable time of day */ 1034 int s; 1035 struct servtab *sep; 1036 { 1037 char buffer[256]; 1038 time_t time(), clock; 1039 char *ctime(); 1040 1041 clock = time((time_t *) 0); 1042 1043 (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); 1044 (void) write(s, buffer, strlen(buffer)); 1045 } 1046 1047 /* ARGSUSED */ 1048 daytime_dg(s, sep) /* Return human-readable time of day */ 1049 int s; 1050 struct servtab *sep; 1051 { 1052 char buffer[256]; 1053 time_t time(), clock; 1054 struct sockaddr sa; 1055 int size; 1056 char *ctime(); 1057 1058 clock = time((time_t *) 0); 1059 1060 size = sizeof(sa); 1061 if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0) 1062 return; 1063 (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); 1064 (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa)); 1065 } 1066 1067 /* 1068 * print_service: 1069 * Dump relevant information to stderr 1070 */ 1071 print_service(action, sep) 1072 char *action; 1073 struct servtab *sep; 1074 { 1075 if (sep->se_rpc) 1076 fprintf(stderr, 1077 "%s: %s rpcnum=%d, rpcvers=%d/%d, wait=%d, user=%s builtin=%x server=%s\n", 1078 action, sep->se_service, 1079 sep->se_rpc_prog, sep->se_rpc_lowvers, sep->se_rpc_highvers, 1080 sep->se_wait, sep->se_user, (int)sep->se_bi, sep->se_server); 1081 else 1082 fprintf(stderr, 1083 "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n", 1084 action, sep->se_service, sep->se_proto, 1085 sep->se_wait, sep->se_user, (int)sep->se_bi, sep->se_server); 1086 } 1087