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