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.8 1994/05/25 02:49:38 cgd 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[.max] single-threaded/multi-threaded, max # 74 * user[.group] user/group 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[.max] single-threaded/multi-threaded 83 * user[.group] 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 90 /* 91 * Here's the scoop concerning the user.group feature: 92 * 93 * 1) set-group-option off. 94 * 95 * a) user = root: NO setuid() or setgid() is done 96 * 97 * b) other: setuid() 98 * setgid(primary group as found in passwd) 99 * initgroups(name, primary group) 100 * 101 * 2) set-group-option on. 102 * 103 * a) user = root: NO setuid() 104 * setgid(specified group) 105 * NO initgroups() 106 * 107 * b) other: setuid() 108 * setgid(specified group) 109 * initgroups(name, specified group) 110 * 111 */ 112 113 #include <sys/param.h> 114 #include <sys/stat.h> 115 #include <sys/ioctl.h> 116 #include <sys/socket.h> 117 #include <sys/un.h> 118 #include <sys/file.h> 119 #include <sys/wait.h> 120 #include <sys/time.h> 121 #include <sys/resource.h> 122 123 #ifndef RLIMIT_NOFILE 124 #define RLIMIT_NOFILE RLIMIT_OFILE 125 #endif 126 127 #define RPC 128 129 #include <netinet/in.h> 130 #include <arpa/inet.h> 131 132 #include <errno.h> 133 #include <signal.h> 134 #include <netdb.h> 135 #include <syslog.h> 136 #include <pwd.h> 137 #include <grp.h> 138 #include <stdio.h> 139 #include <string.h> 140 #ifdef RPC 141 #include <rpc/rpc.h> 142 #endif 143 #include "pathnames.h" 144 145 #define TOOMANY 40 /* don't start more than TOOMANY */ 146 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ 147 #define RETRYTIME (60*10) /* retry after bind or server fail */ 148 149 #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM)) 150 151 extern int errno; 152 153 void config(), reapchild(), retry(), goaway(); 154 char *index(); 155 156 int debug = 0; 157 int nsock, maxsock; 158 fd_set allsock; 159 int options; 160 int timingout; 161 struct servent *sp; 162 char *curdom; 163 164 #ifndef OPEN_MAX 165 #define OPEN_MAX 64 166 #endif 167 168 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ 169 #define FD_MARGIN (8) 170 typeof(((struct rlimit *)0)->rlim_cur) rlim_ofile_cur = OPEN_MAX; 171 172 #ifdef RLIMIT_NOFILE 173 struct rlimit rlim_ofile; 174 #endif 175 176 struct servtab { 177 char *se_service; /* name of service */ 178 int se_socktype; /* type of socket to use */ 179 int se_family; /* address family */ 180 char *se_proto; /* protocol used */ 181 int se_rpcprog; /* rpc program number */ 182 int se_rpcversl; /* rpc program lowest version */ 183 int se_rpcversh; /* rpc program highest version */ 184 #define isrpcservice(sep) ((sep)->se_rpcversl != 0) 185 short se_wait; /* single threaded server */ 186 short se_checked; /* looked at during merge */ 187 char *se_user; /* user name to run as */ 188 char *se_group; /* group name to run as */ 189 struct biltin *se_bi; /* if built-in, description */ 190 char *se_server; /* server program */ 191 #define MAXARGV 20 192 char *se_argv[MAXARGV+1]; /* program arguments */ 193 int se_fd; /* open descriptor */ 194 union { 195 struct sockaddr se_un_ctrladdr; 196 struct sockaddr_in se_un_ctrladdr_in; 197 struct sockaddr_un se_un_ctrladdr_un; 198 } se_un; /* bound address */ 199 #define se_ctrladdr se_un.se_un_ctrladdr 200 #define se_ctrladdr_in se_un.se_un_ctrladdr_in 201 #define se_ctrladdr_un se_un.se_un_ctrladdr_un 202 int se_ctrladdr_size; 203 int se_max; /* max # of instances of this service */ 204 int se_count; /* number started since se_time */ 205 struct timeval se_time; /* start of se_count */ 206 #ifdef MULOG 207 int se_log; 208 #define MULOG_RFC931 0x40000000 209 #endif 210 struct servtab *se_next; 211 } *servtab; 212 213 int echo_stream(), discard_stream(), machtime_stream(); 214 int daytime_stream(), chargen_stream(); 215 int echo_dg(), discard_dg(), machtime_dg(), daytime_dg(), chargen_dg(); 216 217 struct biltin { 218 char *bi_service; /* internally provided service name */ 219 int bi_socktype; /* type of socket supported */ 220 short bi_fork; /* 1 if should fork before call */ 221 short bi_wait; /* 1 if should wait for child */ 222 int (*bi_fn)(); /* function which performs it */ 223 } biltins[] = { 224 /* Echo received data */ 225 "echo", SOCK_STREAM, 1, 0, echo_stream, 226 "echo", SOCK_DGRAM, 0, 0, echo_dg, 227 228 /* Internet /dev/null */ 229 "discard", SOCK_STREAM, 1, 0, discard_stream, 230 "discard", SOCK_DGRAM, 0, 0, discard_dg, 231 232 /* Return 32 bit time since 1900 */ 233 "time", SOCK_STREAM, 0, 0, machtime_stream, 234 "time", SOCK_DGRAM, 0, 0, machtime_dg, 235 236 /* Return human-readable time */ 237 "daytime", SOCK_STREAM, 0, 0, daytime_stream, 238 "daytime", SOCK_DGRAM, 0, 0, daytime_dg, 239 240 /* Familiar character generator */ 241 "chargen", SOCK_STREAM, 1, 0, chargen_stream, 242 "chargen", SOCK_DGRAM, 0, 0, chargen_dg, 243 0 244 }; 245 246 #define NUMINT (sizeof(intab) / sizeof(struct inent)) 247 char *CONFIG = _PATH_INETDCONF; 248 char **Argv; 249 char *LastArg; 250 char *progname; 251 252 #ifdef sun 253 /* 254 * Sun's RPC library caches the result of `dtablesize()' 255 * This is incompatible with our "bumping" of file descriptors "on demand" 256 */ 257 int 258 _rpc_dtablesize() 259 { 260 return rlim_ofile_cur; 261 } 262 #endif 263 264 main(argc, argv, envp) 265 int argc; 266 char *argv[], *envp[]; 267 { 268 extern char *optarg; 269 extern int optind; 270 register struct servtab *sep; 271 register struct passwd *pwd; 272 register struct group *grp; 273 register int tmpint; 274 struct sigvec sv; 275 int ch, pid, dofork; 276 char buf[50]; 277 278 Argv = argv; 279 if (envp == 0 || *envp == 0) 280 envp = argv; 281 while (*envp) 282 envp++; 283 LastArg = envp[-1] + strlen(envp[-1]); 284 285 progname = strrchr(argv[0], '/'); 286 progname = progname ? progname + 1 : argv[0]; 287 288 while ((ch = getopt(argc, argv, "d")) != EOF) 289 switch(ch) { 290 case 'd': 291 debug = 1; 292 options |= SO_DEBUG; 293 break; 294 case '?': 295 default: 296 fprintf(stderr, "usage: %s [-d] [conf]", progname); 297 exit(1); 298 } 299 argc -= optind; 300 argv += optind; 301 302 if (argc > 0) 303 CONFIG = argv[0]; 304 305 if (debug == 0) 306 daemon(0, 0); 307 openlog(progname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 308 logpid(); 309 310 #ifdef RLIMIT_NOFILE 311 if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) { 312 syslog(LOG_ERR, "getrlimit: %m"); 313 } else { 314 rlim_ofile_cur = rlim_ofile.rlim_cur; 315 if (rlim_ofile_cur == RLIM_INFINITY) /* ! */ 316 rlim_ofile_cur = OPEN_MAX; 317 } 318 #endif 319 320 bzero((char *)&sv, sizeof(sv)); 321 sv.sv_mask = SIGBLOCK; 322 sv.sv_handler = retry; 323 sigvec(SIGALRM, &sv, (struct sigvec *)0); 324 config(); 325 sv.sv_handler = config; 326 sigvec(SIGHUP, &sv, (struct sigvec *)0); 327 sv.sv_handler = reapchild; 328 sigvec(SIGCHLD, &sv, (struct sigvec *)0); 329 sv.sv_handler = goaway; 330 sigvec(SIGTERM, &sv, (struct sigvec *)0); 331 sv.sv_handler = goaway; 332 sigvec(SIGINT, &sv, (struct sigvec *)0); 333 334 { 335 /* space for daemons to overwrite environment for ps */ 336 #define DUMMYSIZE 100 337 char dummy[DUMMYSIZE]; 338 339 (void)memset(dummy, 'x', DUMMYSIZE - 1); 340 dummy[DUMMYSIZE - 1] = '\0'; 341 342 (void)setenv("inetd_dummy", dummy, 1); 343 } 344 345 for (;;) { 346 int n, ctrl; 347 fd_set readable; 348 349 if (nsock == 0) { 350 (void) sigblock(SIGBLOCK); 351 while (nsock == 0) 352 sigpause(0L); 353 (void) sigsetmask(0L); 354 } 355 readable = allsock; 356 if ((n = select(maxsock + 1, &readable, (fd_set *)0, 357 (fd_set *)0, (struct timeval *)0)) <= 0) { 358 if (n < 0 && errno != EINTR) 359 syslog(LOG_WARNING, "select: %m\n"); 360 sleep(1); 361 continue; 362 } 363 for (sep = servtab; n && sep; sep = sep->se_next) 364 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) { 365 n--; 366 if (debug) 367 fprintf(stderr, "someone wants %s\n", sep->se_service); 368 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 369 ctrl = accept(sep->se_fd, (struct sockaddr *)0, 370 (int *)0); 371 if (debug) 372 fprintf(stderr, "accept, ctrl %d\n", ctrl); 373 if (ctrl < 0) { 374 if (errno == EINTR) 375 continue; 376 syslog(LOG_WARNING, "accept (for %s): %m", 377 sep->se_service); 378 continue; 379 } 380 } else 381 ctrl = sep->se_fd; 382 (void) sigblock(SIGBLOCK); 383 pid = 0; 384 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); 385 if (dofork) { 386 if (sep->se_count++ == 0) 387 (void)gettimeofday(&sep->se_time, 388 (struct timezone *)0); 389 else if (sep->se_count >= sep->se_max) { 390 struct timeval now; 391 392 (void)gettimeofday(&now, (struct timezone *)0); 393 if (now.tv_sec - sep->se_time.tv_sec > 394 CNT_INTVL) { 395 sep->se_time = now; 396 sep->se_count = 1; 397 } else { 398 syslog(LOG_ERR, 399 "%s/%s server failing (looping), service terminated\n", 400 sep->se_service, sep->se_proto); 401 FD_CLR(sep->se_fd, &allsock); 402 (void) close(sep->se_fd); 403 sep->se_fd = -1; 404 sep->se_count = 0; 405 nsock--; 406 sigsetmask(0L); 407 if (!timingout) { 408 timingout = 1; 409 alarm(RETRYTIME); 410 } 411 continue; 412 } 413 } 414 pid = fork(); 415 } 416 if (pid < 0) { 417 syslog(LOG_ERR, "fork: %m"); 418 if (sep->se_socktype == SOCK_STREAM) 419 close(ctrl); 420 sigsetmask(0L); 421 sleep(1); 422 continue; 423 } 424 if (pid && sep->se_wait) { 425 sep->se_wait = pid; 426 FD_CLR(sep->se_fd, &allsock); 427 nsock--; 428 } 429 sigsetmask(0L); 430 if (pid == 0) { 431 if (debug && dofork) 432 setsid(); 433 if (sep->se_bi) 434 (*sep->se_bi->bi_fn)(ctrl, sep); 435 else { 436 if ((pwd = getpwnam(sep->se_user)) == NULL) { 437 syslog(LOG_ERR, 438 "getpwnam: %s: No such user", 439 sep->se_user); 440 if (sep->se_socktype != SOCK_STREAM) 441 recv(0, buf, sizeof (buf), 0); 442 _exit(1); 443 } 444 if (sep->se_group && 445 (grp = getgrnam(sep->se_group)) == NULL) { 446 syslog(LOG_ERR, 447 "getgrnam: %s: No such group", 448 sep->se_group); 449 if (sep->se_socktype != SOCK_STREAM) 450 recv(0, buf, sizeof (buf), 0); 451 _exit(1); 452 } 453 if (pwd->pw_uid) { 454 if (sep->se_group) 455 pwd->pw_gid = grp->gr_gid; 456 (void) setgid((gid_t)pwd->pw_gid); 457 initgroups(pwd->pw_name, pwd->pw_gid); 458 (void) setuid((uid_t)pwd->pw_uid); 459 } else if (sep->se_group) { 460 (void) setgid((gid_t)grp->gr_gid); 461 } 462 if (debug) 463 fprintf(stderr, "%d execl %s\n", 464 getpid(), sep->se_server); 465 #ifdef MULOG 466 if (sep->se_log) 467 dolog(sep, ctrl); 468 #endif 469 dup2(ctrl, 0); 470 close(ctrl); 471 dup2(0, 1); 472 dup2(0, 2); 473 #ifdef RLIMIT_NOFILE 474 if (rlim_ofile.rlim_cur != rlim_ofile_cur) { 475 if (setrlimit(RLIMIT_NOFILE, 476 &rlim_ofile) < 0) 477 syslog(LOG_ERR,"setrlimit: %m"); 478 } 479 #endif 480 for (tmpint = rlim_ofile_cur-1; --tmpint > 2; ) 481 (void)close(tmpint); 482 execv(sep->se_server, sep->se_argv); 483 if (sep->se_socktype != SOCK_STREAM) 484 recv(0, buf, sizeof (buf), 0); 485 syslog(LOG_ERR, "execv %s: %m", sep->se_server); 486 _exit(1); 487 } 488 } 489 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 490 close(ctrl); 491 } 492 } 493 } 494 495 void 496 reapchild() 497 { 498 int status; 499 int pid; 500 register struct servtab *sep; 501 502 for (;;) { 503 pid = wait3(&status, WNOHANG, (struct rusage *)0); 504 if (pid <= 0) 505 break; 506 if (debug) 507 fprintf(stderr, "%d reaped\n", pid); 508 for (sep = servtab; sep; sep = sep->se_next) 509 if (sep->se_wait == pid) { 510 if (WIFEXITED(status) && WEXITSTATUS(status)) 511 syslog(LOG_WARNING, 512 "%s: exit status 0x%x", 513 sep->se_server, WEXITSTATUS(status)); 514 else if (WIFSIGNALED(status)) 515 syslog(LOG_WARNING, 516 "%s: exit signal 0x%x", 517 sep->se_server, WTERMSIG(status)); 518 sep->se_wait = 1; 519 FD_SET(sep->se_fd, &allsock); 520 nsock++; 521 if (debug) 522 fprintf(stderr, "restored %s, fd %d\n", 523 sep->se_service, sep->se_fd); 524 } 525 } 526 } 527 528 void 529 config() 530 { 531 register struct servtab *sep, *cp, **sepp; 532 struct servtab *getconfigent(), *enter(); 533 long omask; 534 int n; 535 536 if (!setconfig()) { 537 syslog(LOG_ERR, "%s: %m", CONFIG); 538 return; 539 } 540 for (sep = servtab; sep; sep = sep->se_next) 541 sep->se_checked = 0; 542 while (cp = getconfigent()) { 543 for (sep = servtab; sep; sep = sep->se_next) 544 if (strcmp(sep->se_service, cp->se_service) == 0 && 545 strcmp(sep->se_proto, cp->se_proto) == 0) 546 break; 547 if (sep != 0) { 548 int i; 549 550 #define SWAP(type, a, b) {type c=(type)a; (type)a=(type)b; (type)b=(type)c;} 551 552 omask = sigblock(SIGBLOCK); 553 /* 554 * sep->se_wait may be holding the pid of a daemon 555 * that we're waiting for. If so, don't overwrite 556 * it unless the config file explicitly says don't 557 * wait. 558 */ 559 if (cp->se_bi == 0 && 560 (sep->se_wait == 1 || cp->se_wait == 0)) 561 sep->se_wait = cp->se_wait; 562 if (cp->se_max != sep->se_max) 563 SWAP(int, cp->se_max, sep->se_max); 564 if (cp->se_user) 565 SWAP(char *, sep->se_user, cp->se_user); 566 if (cp->se_group) 567 SWAP(char *, sep->se_group, cp->se_group); 568 if (cp->se_server) 569 SWAP(char *, sep->se_server, cp->se_server); 570 for (i = 0; i < MAXARGV; i++) 571 SWAP(char *, sep->se_argv[i], cp->se_argv[i]); 572 #undef SWAP 573 if (isrpcservice(sep)) 574 unregister_rpc(sep); 575 sep->se_rpcversl = cp->se_rpcversl; 576 sep->se_rpcversh = cp->se_rpcversh; 577 sigsetmask(omask); 578 freeconfig(cp); 579 if (debug) 580 print_service("REDO", sep); 581 } else { 582 sep = enter(cp); 583 if (debug) 584 print_service("ADD ", sep); 585 } 586 sep->se_checked = 1; 587 588 switch (sep->se_family) { 589 case AF_UNIX: 590 if (sep->se_fd != -1) 591 break; 592 (void)unlink(sep->se_service); 593 n = strlen(sep->se_service); 594 if (n > sizeof sep->se_ctrladdr_un.sun_path - 1) 595 n = sizeof sep->se_ctrladdr_un.sun_path - 1; 596 strncpy(sep->se_ctrladdr_un.sun_path, sep->se_service, n); 597 sep->se_ctrladdr_un.sun_family = AF_UNIX; 598 sep->se_ctrladdr_size = n + 599 sizeof sep->se_ctrladdr_un.sun_family; 600 setup(sep); 601 break; 602 case AF_INET: 603 sep->se_ctrladdr_in.sin_family = AF_INET; 604 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in; 605 if (isrpcservice(sep)) { 606 struct rpcent *rp; 607 608 sep->se_rpcprog = atoi(sep->se_service); 609 if (sep->se_rpcprog == 0) { 610 rp = getrpcbyname(sep->se_service); 611 if (rp == 0) { 612 syslog(LOG_ERR, 613 "%s: unknown service", 614 sep->se_service); 615 continue; 616 } 617 sep->se_rpcprog = rp->r_number; 618 } 619 if (sep->se_fd == -1) 620 setup(sep); 621 if (sep->se_fd != -1) 622 register_rpc(sep); 623 } else { 624 u_short port = htons(atoi(sep->se_service)); 625 626 if (!port) { 627 sp = getservbyname(sep->se_service, 628 sep->se_proto); 629 if (sp == 0) { 630 syslog(LOG_ERR, 631 "%s/%s: unknown service", 632 sep->se_service, sep->se_proto); 633 continue; 634 } 635 port = sp->s_port; 636 } 637 if (port != sep->se_ctrladdr_in.sin_port) { 638 sep->se_ctrladdr_in.sin_port = port; 639 if (sep->se_fd != -1) { 640 FD_CLR(sep->se_fd, &allsock); 641 nsock--; 642 (void) close(sep->se_fd); 643 } 644 sep->se_fd = -1; 645 } 646 if (sep->se_fd == -1) 647 setup(sep); 648 } 649 } 650 } 651 endconfig(); 652 /* 653 * Purge anything not looked at above. 654 */ 655 omask = sigblock(SIGBLOCK); 656 sepp = &servtab; 657 while (sep = *sepp) { 658 if (sep->se_checked) { 659 sepp = &sep->se_next; 660 continue; 661 } 662 *sepp = sep->se_next; 663 if (sep->se_fd != -1) { 664 FD_CLR(sep->se_fd, &allsock); 665 nsock--; 666 (void) close(sep->se_fd); 667 } 668 if (isrpcservice(sep)) 669 unregister_rpc(sep); 670 if (sep->se_family == AF_UNIX) 671 (void)unlink(sep->se_service); 672 if (debug) 673 print_service("FREE", sep); 674 freeconfig(sep); 675 free((char *)sep); 676 } 677 (void) sigsetmask(omask); 678 } 679 680 void 681 retry() 682 { 683 register struct servtab *sep; 684 685 timingout = 0; 686 for (sep = servtab; sep; sep = sep->se_next) { 687 if (sep->se_fd == -1) { 688 switch (sep->se_family) { 689 case AF_UNIX: 690 case AF_INET: 691 setup(sep); 692 if (sep->se_fd != -1 && isrpcservice(sep)) 693 register_rpc(sep); 694 break; 695 } 696 } 697 } 698 } 699 700 void 701 goaway() 702 { 703 register struct servtab *sep; 704 705 for (sep = servtab; sep; sep = sep->se_next) { 706 if (sep->se_fd == -1) 707 continue; 708 709 switch (sep->se_family) { 710 case AF_UNIX: 711 (void)unlink(sep->se_service); 712 break; 713 case AF_INET: 714 if (sep->se_wait == 1 && isrpcservice(sep)) 715 unregister_rpc(sep); 716 break; 717 } 718 (void)close(sep->se_fd); 719 } 720 (void)unlink(_PATH_INETDPID); 721 exit(0); 722 } 723 724 725 setup(sep) 726 register struct servtab *sep; 727 { 728 int on = 1; 729 730 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { 731 syslog(LOG_ERR, "%s/%s: socket: %m", 732 sep->se_service, sep->se_proto); 733 return; 734 } 735 #define turnon(fd, opt) \ 736 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) 737 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && 738 turnon(sep->se_fd, SO_DEBUG) < 0) 739 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 740 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 741 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 742 #undef turnon 743 if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) { 744 syslog(LOG_ERR, "%s/%s: bind: %m", 745 sep->se_service, sep->se_proto); 746 (void) close(sep->se_fd); 747 sep->se_fd = -1; 748 if (!timingout) { 749 timingout = 1; 750 alarm(RETRYTIME); 751 } 752 return; 753 } 754 if (sep->se_socktype == SOCK_STREAM) 755 listen(sep->se_fd, 10); 756 757 FD_SET(sep->se_fd, &allsock); 758 nsock++; 759 if (sep->se_fd > maxsock) { 760 maxsock = sep->se_fd; 761 if (maxsock > rlim_ofile_cur - FD_MARGIN) 762 bump_nofile(); 763 } 764 } 765 766 register_rpc(sep) 767 register struct servtab *sep; 768 { 769 #ifdef RPC 770 int n; 771 struct sockaddr_in sin; 772 struct protoent *pp; 773 774 if ((pp = getprotobyname(sep->se_proto+4)) == NULL) { 775 syslog(LOG_ERR, "%s: getproto: %m", 776 sep->se_proto); 777 return; 778 } 779 n = sizeof sin; 780 if (getsockname(sep->se_fd, (struct sockaddr *)&sin, &n) < 0) { 781 syslog(LOG_ERR, "%s/%s: getsockname: %m", 782 sep->se_service, sep->se_proto); 783 return; 784 } 785 786 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 787 if (debug) 788 fprintf(stderr, "pmap_set: %u %u %u %u\n", 789 sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port)); 790 (void)pmap_unset(sep->se_rpcprog, n); 791 if (!pmap_set(sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port))) 792 syslog(LOG_ERR, "pmap_set: %u %u %u %u: %m", 793 sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port)); 794 } 795 #endif /* RPC */ 796 } 797 798 unregister_rpc(sep) 799 register struct servtab *sep; 800 { 801 #ifdef RPC 802 int n; 803 804 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 805 if (debug) 806 fprintf(stderr, "pmap_unset(%u, %u)\n", 807 sep->se_rpcprog, n); 808 if (!pmap_unset(sep->se_rpcprog, n)) 809 syslog(LOG_ERR, "pmap_unset(%u, %u)\n", 810 sep->se_rpcprog, n); 811 } 812 #endif /* RPC */ 813 } 814 815 816 struct servtab * 817 enter(cp) 818 struct servtab *cp; 819 { 820 register struct servtab *sep; 821 long omask; 822 823 sep = (struct servtab *)malloc(sizeof (*sep)); 824 if (sep == (struct servtab *)0) { 825 syslog(LOG_ERR, "Out of memory."); 826 exit(-1); 827 } 828 *sep = *cp; 829 sep->se_fd = -1; 830 sep->se_rpcprog = -1; 831 omask = sigblock(SIGBLOCK); 832 sep->se_next = servtab; 833 servtab = sep; 834 sigsetmask(omask); 835 return (sep); 836 } 837 838 FILE *fconfig = NULL; 839 struct servtab serv; 840 char line[256]; 841 char *skip(), *nextline(); 842 843 setconfig() 844 { 845 846 if (fconfig != NULL) { 847 fseek(fconfig, 0L, L_SET); 848 return (1); 849 } 850 fconfig = fopen(CONFIG, "r"); 851 return (fconfig != NULL); 852 } 853 854 endconfig() 855 { 856 if (fconfig) { 857 (void) fclose(fconfig); 858 fconfig = NULL; 859 } 860 } 861 862 struct servtab * 863 getconfigent() 864 { 865 register struct servtab *sep = &serv; 866 int argc; 867 char *cp, *arg, *newstr(); 868 869 more: 870 #ifdef MULOG 871 while ((cp = nextline(fconfig)) && *cp == '#') { 872 /* Avoid use of `skip' if there is a danger of it looking 873 * at continuation lines. 874 */ 875 do { 876 cp++; 877 } while (*cp == ' ' || *cp == '\t'); 878 if (*cp == '\0') 879 continue; 880 if ((arg = skip(&cp)) == NULL) 881 continue; 882 if (strcmp(arg, "DOMAIN")) 883 continue; 884 if (curdom) 885 free(curdom); 886 curdom = NULL; 887 while (*cp == ' ' || *cp == '\t') 888 cp++; 889 if (*cp == '\0') 890 continue; 891 arg = cp; 892 while (*cp && *cp != ' ' && *cp != '\t') 893 cp++; 894 if (*cp != '\0') 895 *cp++ = '\0'; 896 curdom = newstr(arg); 897 } 898 #else 899 while ((cp = nextline(fconfig)) && *cp == '#') 900 ; 901 #endif 902 if (cp == NULL) 903 return ((struct servtab *)0); 904 bzero((char *)sep, sizeof *sep); 905 sep->se_service = newstr(skip(&cp)); 906 arg = skip(&cp); 907 if (arg == NULL) 908 goto more; 909 910 if (strcmp(arg, "stream") == 0) 911 sep->se_socktype = SOCK_STREAM; 912 else if (strcmp(arg, "dgram") == 0) 913 sep->se_socktype = SOCK_DGRAM; 914 else if (strcmp(arg, "rdm") == 0) 915 sep->se_socktype = SOCK_RDM; 916 else if (strcmp(arg, "seqpacket") == 0) 917 sep->se_socktype = SOCK_SEQPACKET; 918 else if (strcmp(arg, "raw") == 0) 919 sep->se_socktype = SOCK_RAW; 920 else 921 sep->se_socktype = -1; 922 923 sep->se_proto = newstr(skip(&cp)); 924 if (strcmp(sep->se_proto, "unix") == 0) { 925 sep->se_family = AF_UNIX; 926 } else { 927 sep->se_family = AF_INET; 928 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 929 #ifdef RPC 930 char *cp, *ccp; 931 cp = index(sep->se_service, '/'); 932 if (cp == 0) { 933 syslog(LOG_ERR, "%s: no rpc version", 934 sep->se_service); 935 goto more; 936 } 937 *cp++ = '\0'; 938 sep->se_rpcversl = 939 sep->se_rpcversh = strtol(cp, &ccp, 0); 940 if (ccp == cp) { 941 badafterall: 942 syslog(LOG_ERR, "%s/%s: bad rpc version", 943 sep->se_service, cp); 944 goto more; 945 } 946 if (*ccp == '-') { 947 cp = ccp + 1; 948 sep->se_rpcversh = strtol(cp, &ccp, 0); 949 if (ccp == cp) 950 goto badafterall; 951 } 952 #else 953 syslog(LOG_ERR, "%s: rpc services not suported", 954 sep->se_service); 955 goto more; 956 #endif /* RPC */ 957 } 958 } 959 arg = skip(&cp); 960 if (arg == NULL) 961 goto more; 962 { 963 char *s = index(arg, '.'); 964 if (s) { 965 *s++ = '\0'; 966 sep->se_max = atoi(s); 967 } else 968 sep->se_max = TOOMANY; 969 } 970 sep->se_wait = strcmp(arg, "wait") == 0; 971 sep->se_user = newstr(skip(&cp)); 972 if (sep->se_group = index(sep->se_user, '.')) { 973 *sep->se_group++ = '\0'; 974 } 975 sep->se_server = newstr(skip(&cp)); 976 if (strcmp(sep->se_server, "internal") == 0) { 977 register struct biltin *bi; 978 979 for (bi = biltins; bi->bi_service; bi++) 980 if (bi->bi_socktype == sep->se_socktype && 981 strcmp(bi->bi_service, sep->se_service) == 0) 982 break; 983 if (bi->bi_service == 0) { 984 syslog(LOG_ERR, "internal service %s unknown\n", 985 sep->se_service); 986 goto more; 987 } 988 sep->se_bi = bi; 989 sep->se_wait = bi->bi_wait; 990 } else 991 sep->se_bi = NULL; 992 argc = 0; 993 for (arg = skip(&cp); cp; arg = skip(&cp)) { 994 #if MULOG 995 char *colon, *rindex(); 996 997 if (argc == 0 && (colon = rindex(arg, ':'))) { 998 while (arg < colon) { 999 int x; 1000 char *ccp; 1001 1002 switch (*arg++) { 1003 case 'l': 1004 x = 1; 1005 if (isdigit(*arg)) { 1006 x = strtol(arg, &ccp, 0); 1007 if (ccp == arg) 1008 break; 1009 arg = ccp; 1010 } 1011 sep->se_log &= ~MULOG_RFC931; 1012 sep->se_log |= x; 1013 break; 1014 case 'a': 1015 sep->se_log |= MULOG_RFC931; 1016 break; 1017 default: 1018 break; 1019 } 1020 } 1021 arg = colon + 1; 1022 } 1023 #endif 1024 if (argc < MAXARGV) 1025 sep->se_argv[argc++] = newstr(arg); 1026 } 1027 while (argc <= MAXARGV) 1028 sep->se_argv[argc++] = NULL; 1029 return (sep); 1030 } 1031 1032 freeconfig(cp) 1033 register struct servtab *cp; 1034 { 1035 int i; 1036 1037 if (cp->se_service) 1038 free(cp->se_service); 1039 if (cp->se_proto) 1040 free(cp->se_proto); 1041 if (cp->se_user) 1042 free(cp->se_user); 1043 /* Note: se_group is part of the newstr'ed se_user */ 1044 if (cp->se_server) 1045 free(cp->se_server); 1046 for (i = 0; i < MAXARGV; i++) 1047 if (cp->se_argv[i]) 1048 free(cp->se_argv[i]); 1049 } 1050 1051 char * 1052 skip(cpp) 1053 char **cpp; 1054 { 1055 register char *cp = *cpp; 1056 char *start; 1057 1058 if (*cpp == NULL) 1059 return ((char *)0); 1060 1061 again: 1062 while (*cp == ' ' || *cp == '\t') 1063 cp++; 1064 if (*cp == '\0') { 1065 int c; 1066 1067 c = getc(fconfig); 1068 (void) ungetc(c, fconfig); 1069 if (c == ' ' || c == '\t') 1070 if (cp = nextline(fconfig)) 1071 goto again; 1072 *cpp = (char *)0; 1073 return ((char *)0); 1074 } 1075 start = cp; 1076 while (*cp && *cp != ' ' && *cp != '\t') 1077 cp++; 1078 if (*cp != '\0') 1079 *cp++ = '\0'; 1080 *cpp = cp; 1081 return (start); 1082 } 1083 1084 char * 1085 nextline(fd) 1086 FILE *fd; 1087 { 1088 char *cp; 1089 1090 if (fgets(line, sizeof (line), fd) == NULL) 1091 return ((char *)0); 1092 cp = index(line, '\n'); 1093 if (cp) 1094 *cp = '\0'; 1095 return (line); 1096 } 1097 1098 char * 1099 newstr(cp) 1100 char *cp; 1101 { 1102 if (cp = strdup(cp ? cp : "")) 1103 return(cp); 1104 syslog(LOG_ERR, "strdup: %m"); 1105 exit(-1); 1106 } 1107 1108 setproctitle(a, s) 1109 char *a; 1110 int s; 1111 { 1112 int size; 1113 register char *cp; 1114 struct sockaddr_in sin; 1115 char buf[80]; 1116 1117 cp = Argv[0]; 1118 size = sizeof(sin); 1119 if (getpeername(s, (struct sockaddr *)&sin, &size) == 0) 1120 (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); 1121 else 1122 (void) sprintf(buf, "-%s", a); 1123 strncpy(cp, buf, LastArg - cp); 1124 cp += strlen(cp); 1125 while (cp < LastArg) 1126 *cp++ = ' '; 1127 } 1128 1129 logpid() 1130 { 1131 FILE *fp; 1132 1133 if ((fp = fopen(_PATH_INETDPID, "w")) != NULL) { 1134 fprintf(fp, "%u\n", getpid()); 1135 (void)fclose(fp); 1136 } 1137 } 1138 1139 bump_nofile() 1140 { 1141 #ifdef RLIMIT_NOFILE 1142 1143 #define FD_CHUNK 32 1144 1145 struct rlimit rl; 1146 1147 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1148 syslog(LOG_ERR, "getrlimit: %m"); 1149 return -1; 1150 } 1151 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK); 1152 if (rl.rlim_cur <= rlim_ofile_cur) { 1153 syslog(LOG_ERR, 1154 "bump_nofile: cannot extend file limit, max = %d", 1155 rl.rlim_cur); 1156 return -1; 1157 } 1158 1159 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { 1160 syslog(LOG_ERR, "setrlimit: %m"); 1161 return -1; 1162 } 1163 1164 rlim_ofile_cur = rl.rlim_cur; 1165 return 0; 1166 1167 #else 1168 syslog(LOG_ERR, "bump_nofile: cannot extend file limit"); 1169 return -1; 1170 #endif 1171 } 1172 1173 /* 1174 * Internet services provided internally by inetd: 1175 */ 1176 #define BUFSIZE 4096 1177 1178 /* ARGSUSED */ 1179 echo_stream(s, sep) /* Echo service -- echo data back */ 1180 int s; 1181 struct servtab *sep; 1182 { 1183 char buffer[BUFSIZE]; 1184 int i; 1185 1186 setproctitle(sep->se_service, s); 1187 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1188 write(s, buffer, i) > 0) 1189 ; 1190 exit(0); 1191 } 1192 1193 /* ARGSUSED */ 1194 echo_dg(s, sep) /* Echo service -- echo data back */ 1195 int s; 1196 struct servtab *sep; 1197 { 1198 char buffer[BUFSIZE]; 1199 int i, size; 1200 struct sockaddr sa; 1201 1202 size = sizeof(sa); 1203 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size)) < 0) 1204 return; 1205 (void) sendto(s, buffer, i, 0, &sa, sizeof(sa)); 1206 } 1207 1208 /* ARGSUSED */ 1209 discard_stream(s, sep) /* Discard service -- ignore data */ 1210 int s; 1211 struct servtab *sep; 1212 { 1213 char buffer[BUFSIZE]; 1214 1215 setproctitle(sep->se_service, s); 1216 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || 1217 errno == EINTR) 1218 ; 1219 exit(0); 1220 } 1221 1222 /* ARGSUSED */ 1223 discard_dg(s, sep) /* Discard service -- ignore data */ 1224 int s; 1225 struct servtab *sep; 1226 { 1227 char buffer[BUFSIZE]; 1228 1229 (void) read(s, buffer, sizeof(buffer)); 1230 } 1231 1232 #include <ctype.h> 1233 #define LINESIZ 72 1234 char ring[128]; 1235 char *endring; 1236 1237 initring() 1238 { 1239 register int i; 1240 1241 endring = ring; 1242 1243 for (i = 0; i <= 128; ++i) 1244 if (isprint(i)) 1245 *endring++ = i; 1246 } 1247 1248 /* ARGSUSED */ 1249 chargen_stream(s, sep) /* Character generator */ 1250 int s; 1251 struct servtab *sep; 1252 { 1253 register char *rs; 1254 int len; 1255 char text[LINESIZ+2]; 1256 1257 setproctitle(sep->se_service, s); 1258 1259 if (!endring) { 1260 initring(); 1261 rs = ring; 1262 } 1263 1264 text[LINESIZ] = '\r'; 1265 text[LINESIZ + 1] = '\n'; 1266 for (rs = ring;;) { 1267 if ((len = endring - rs) >= LINESIZ) 1268 bcopy(rs, text, LINESIZ); 1269 else { 1270 bcopy(rs, text, len); 1271 bcopy(ring, text + len, LINESIZ - len); 1272 } 1273 if (++rs == endring) 1274 rs = ring; 1275 if (write(s, text, sizeof(text)) != sizeof(text)) 1276 break; 1277 } 1278 exit(0); 1279 } 1280 1281 /* ARGSUSED */ 1282 chargen_dg(s, sep) /* Character generator */ 1283 int s; 1284 struct servtab *sep; 1285 { 1286 struct sockaddr sa; 1287 static char *rs; 1288 int len, size; 1289 char text[LINESIZ+2]; 1290 1291 if (endring == 0) { 1292 initring(); 1293 rs = ring; 1294 } 1295 1296 size = sizeof(sa); 1297 if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0) 1298 return; 1299 1300 if ((len = endring - rs) >= LINESIZ) 1301 bcopy(rs, text, LINESIZ); 1302 else { 1303 bcopy(rs, text, len); 1304 bcopy(ring, text + len, LINESIZ - len); 1305 } 1306 if (++rs == endring) 1307 rs = ring; 1308 text[LINESIZ] = '\r'; 1309 text[LINESIZ + 1] = '\n'; 1310 (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa)); 1311 } 1312 1313 /* 1314 * Return a machine readable date and time, in the form of the 1315 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1316 * returns the number of seconds since midnight, Jan 1, 1970, 1317 * we must add 2208988800 seconds to this figure to make up for 1318 * some seventy years Bell Labs was asleep. 1319 */ 1320 1321 long 1322 machtime() 1323 { 1324 struct timeval tv; 1325 1326 if (gettimeofday(&tv, (struct timezone *)0) < 0) { 1327 fprintf(stderr, "Unable to get time of day\n"); 1328 return (0L); 1329 } 1330 return (htonl((long)tv.tv_sec + 2208988800UL)); 1331 } 1332 1333 /* ARGSUSED */ 1334 machtime_stream(s, sep) 1335 int s; 1336 struct servtab *sep; 1337 { 1338 long result; 1339 1340 result = machtime(); 1341 (void) write(s, (char *) &result, sizeof(result)); 1342 } 1343 1344 /* ARGSUSED */ 1345 machtime_dg(s, sep) 1346 int s; 1347 struct servtab *sep; 1348 { 1349 long result; 1350 struct sockaddr sa; 1351 int size; 1352 1353 size = sizeof(sa); 1354 if (recvfrom(s, (char *)&result, sizeof(result), 0, &sa, &size) < 0) 1355 return; 1356 result = machtime(); 1357 (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa)); 1358 } 1359 1360 /* ARGSUSED */ 1361 daytime_stream(s, sep) /* Return human-readable time of day */ 1362 int s; 1363 struct servtab *sep; 1364 { 1365 char buffer[256]; 1366 time_t time(), clock; 1367 char *ctime(); 1368 1369 clock = time((time_t *) 0); 1370 1371 (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); 1372 (void) write(s, buffer, strlen(buffer)); 1373 } 1374 1375 /* ARGSUSED */ 1376 daytime_dg(s, sep) /* Return human-readable time of day */ 1377 int s; 1378 struct servtab *sep; 1379 { 1380 char buffer[256]; 1381 time_t time(), clock; 1382 struct sockaddr sa; 1383 int size; 1384 char *ctime(); 1385 1386 clock = time((time_t *) 0); 1387 1388 size = sizeof(sa); 1389 if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0) 1390 return; 1391 (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); 1392 (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa)); 1393 } 1394 1395 /* 1396 * print_service: 1397 * Dump relevant information to stderr 1398 */ 1399 print_service(action, sep) 1400 char *action; 1401 struct servtab *sep; 1402 { 1403 if (isrpcservice(sep)) 1404 fprintf(stderr, 1405 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%d, user.group=%s.%s builtin=%x server=%s\n", 1406 action, sep->se_service, 1407 sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto, 1408 sep->se_wait, sep->se_max, sep->se_user, sep->se_group, 1409 (int)sep->se_bi, sep->se_server); 1410 else 1411 fprintf(stderr, 1412 "%s: %s proto=%s, wait.max=%d.%d, user.group=%s.%s builtin=%x server=%s\n", 1413 action, sep->se_service, sep->se_proto, 1414 sep->se_wait, sep->se_max, sep->se_user, sep->se_group, 1415 (int)sep->se_bi, sep->se_server); 1416 } 1417 1418 #ifdef MULOG 1419 dolog(sep, ctrl) 1420 struct servtab *sep; 1421 int ctrl; 1422 { 1423 struct sockaddr sa; 1424 struct sockaddr_in *sin = (struct sockaddr_in *)&sa; 1425 int len = sizeof(sa); 1426 struct hostent *hp; 1427 char *host, *dp, buf[BUFSIZ], *rfc931_name(); 1428 int connected = 1; 1429 1430 if (sep->se_family != AF_INET) 1431 return; 1432 1433 if (getpeername(ctrl, &sa, &len) < 0) { 1434 if (errno != ENOTCONN) { 1435 syslog(LOG_ERR, "getpeername: %m"); 1436 return; 1437 } 1438 if (recvfrom(ctrl, buf, sizeof(buf), MSG_PEEK, &sa, &len) < 0) { 1439 syslog(LOG_ERR, "recvfrom: %m"); 1440 return; 1441 } 1442 connected = 0; 1443 } 1444 if (sa.sa_family != AF_INET) { 1445 syslog(LOG_ERR, "unexpected address family %u", sa.sa_family); 1446 return; 1447 } 1448 1449 hp = gethostbyaddr((char *) &sin->sin_addr.s_addr, 1450 sizeof (sin->sin_addr.s_addr), AF_INET); 1451 1452 host = hp?hp->h_name:inet_ntoa(sin->sin_addr); 1453 1454 switch (sep->se_log & ~MULOG_RFC931) { 1455 case 0: 1456 return; 1457 case 1: 1458 if (curdom == NULL || *curdom == '\0') 1459 break; 1460 dp = host + strlen(host) - strlen(curdom); 1461 if (dp < host) 1462 break; 1463 if (debug) 1464 fprintf(stderr, "check \"%s\" against curdom \"%s\"\n", 1465 host, curdom); 1466 if (strcasecmp(dp, curdom) == 0) 1467 return; 1468 break; 1469 case 2: 1470 default: 1471 break; 1472 } 1473 1474 openlog("", LOG_NOWAIT, MULOG); 1475 1476 if (connected && (sep->se_log & MULOG_RFC931)) 1477 syslog(LOG_INFO, "%s@%s wants %s", 1478 rfc931_name(sin, ctrl), host, sep->se_service); 1479 else 1480 syslog(LOG_INFO, "%s wants %s", 1481 host, sep->se_service); 1482 } 1483 /* 1484 * From tcp_log by 1485 * Wietse Venema, Eindhoven University of Technology, The Netherlands. 1486 */ 1487 #if 0 1488 static char sccsid[] = "@(#) rfc931.c 1.3 92/08/31 22:54:46"; 1489 #endif 1490 1491 #include <setjmp.h> 1492 1493 #define RFC931_PORT 113 /* Semi-well-known port */ 1494 #define TIMEOUT 4 1495 #define TIMEOUT2 10 1496 1497 static jmp_buf timebuf; 1498 1499 /* timeout - handle timeouts */ 1500 1501 static void timeout(sig) 1502 int sig; 1503 { 1504 longjmp(timebuf, sig); 1505 } 1506 1507 /* rfc931_name - return remote user name */ 1508 1509 char * 1510 rfc931_name(there, ctrl) 1511 struct sockaddr_in *there; /* remote link information */ 1512 int ctrl; 1513 { 1514 struct sockaddr_in here; /* local link information */ 1515 struct sockaddr_in sin; /* for talking to RFC931 daemon */ 1516 int length; 1517 int s; 1518 unsigned remote; 1519 unsigned local; 1520 static char user[256]; /* XXX */ 1521 char buf[256]; 1522 char *cp; 1523 char *result = "USER_UNKNOWN"; 1524 int len; 1525 1526 /* Find out local port number of our stdin. */ 1527 1528 length = sizeof(here); 1529 if (getsockname(ctrl, (struct sockaddr *) &here, &length) == -1) { 1530 syslog(LOG_ERR, "getsockname: %m"); 1531 return (result); 1532 } 1533 /* Set up timer so we won't get stuck. */ 1534 1535 if ((s = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 1536 syslog(LOG_ERR, "socket: %m"); 1537 return (result); 1538 } 1539 1540 sin = here; 1541 sin.sin_port = htons(0); 1542 if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { 1543 syslog(LOG_ERR, "bind: %m"); 1544 return (result); 1545 } 1546 1547 signal(SIGALRM, timeout); 1548 if (setjmp(timebuf)) { 1549 close(s); /* not: fclose(fp) */ 1550 return (result); 1551 } 1552 alarm(TIMEOUT); 1553 1554 /* Connect to the RFC931 daemon. */ 1555 1556 sin = *there; 1557 sin.sin_port = htons(RFC931_PORT); 1558 if (connect(s, (struct sockaddr *) &sin, sizeof(sin)) == -1) { 1559 close(s); 1560 alarm(0); 1561 return (result); 1562 } 1563 1564 /* Query the RFC 931 server. Would 13-byte writes ever be broken up? */ 1565 sprintf(buf, "%u,%u\r\n", ntohs(there->sin_port), ntohs(here.sin_port)); 1566 1567 1568 for (len = 0, cp = buf; len < strlen(buf); ) { 1569 int n; 1570 if ((n = write(s, cp, strlen(buf) - len)) == -1) { 1571 close(s); 1572 alarm(0); 1573 return (result); 1574 } 1575 cp += n; 1576 len += n; 1577 } 1578 1579 /* Read response */ 1580 for (cp = buf; cp < buf + sizeof(buf) - 1; ) { 1581 char c; 1582 if (read(s, &c, 1) != 1) { 1583 close(s); 1584 alarm(0); 1585 return (result); 1586 } 1587 if (c == '\n') 1588 break; 1589 *cp++ = c; 1590 } 1591 *cp = '\0'; 1592 1593 if (sscanf(buf, "%u , %u : USERID :%*[^:]:%255s", &remote, &local, user) == 3 1594 && ntohs(there->sin_port) == remote 1595 && ntohs(here.sin_port) == local) { 1596 1597 /* Strip trailing carriage return. */ 1598 if (cp = strchr(user, '\r')) 1599 *cp = 0; 1600 result = user; 1601 } 1602 1603 alarm(0); 1604 close(s); 1605 return (result); 1606 } 1607 #endif 1608