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