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