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