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