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