1 /* $OpenBSD: inetd.c,v 1.86 2001/11/05 09:43:50 deraadt Exp $ */ 2 /* $NetBSD: inetd.c,v 1.11 1996/02/22 11:14:41 mycroft Exp $ */ 3 /* 4 * Copyright (c) 1983,1991 The Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #ifndef lint 37 char copyright[] = 38 "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 39 All rights reserved.\n"; 40 #endif /* not lint */ 41 42 #ifndef lint 43 /*static char sccsid[] = "from: @(#)inetd.c 5.30 (Berkeley) 6/3/91";*/ 44 static char rcsid[] = "$OpenBSD: inetd.c,v 1.86 2001/11/05 09:43:50 deraadt Exp $"; 45 #endif /* not lint */ 46 47 /* 48 * Inetd - Internet super-server 49 * 50 * This program invokes all internet services as needed. 51 * connection-oriented services are invoked each time a 52 * connection is made, by creating a process. This process 53 * is passed the connection as file descriptor 0 and is 54 * expected to do a getpeername to find out the source host 55 * and port. 56 * 57 * Datagram oriented services are invoked when a datagram 58 * arrives; a process is created and passed a pending message 59 * on file descriptor 0. Datagram servers may either connect 60 * to their peer, freeing up the original socket for inetd 61 * to receive further messages on, or ``take over the socket'', 62 * processing all arriving datagrams and, eventually, timing 63 * out. The first type of server is said to be ``multi-threaded''; 64 * the second type of server ``single-threaded''. 65 * 66 * Inetd uses a configuration file which is read at startup 67 * and, possibly, at some later time in response to a hangup signal. 68 * The configuration file is ``free format'' with fields given in the 69 * order shown below. Continuation lines for an entry must begin with 70 * a space or tab. All fields must be present in each entry. 71 * 72 * service name must be in /etc/services 73 * socket type stream/dgram/raw/rdm/seqpacket 74 * protocol must be in /etc/protocols 75 * wait/nowait[.max] single-threaded/multi-threaded, max # 76 * user[.group] or user[:group] user/group to run daemon as 77 * server program full path name 78 * server program arguments maximum of MAXARGS (20) 79 * 80 * For RPC services 81 * service name/version must be in /etc/rpc 82 * socket type stream/dgram/raw/rdm/seqpacket 83 * protocol must be in /etc/protocols 84 * wait/nowait[.max] single-threaded/multi-threaded 85 * user[.group] or user[:group] user to run daemon as 86 * server program full path name 87 * server program arguments maximum of MAXARGS (20) 88 * 89 * For non-RPC services, the "service name" can be of the form 90 * hostaddress:servicename, in which case the hostaddress is used 91 * as the host portion of the address to listen on. If hostaddress 92 * consists of a single `*' character, INADDR_ANY is used. 93 * 94 * A line can also consist of just 95 * hostaddress: 96 * where hostaddress is as in the preceding paragraph. Such a line must 97 * have no further fields; the specified hostaddress is remembered and 98 * used for all further lines that have no hostaddress specified, 99 * until the next such line (or EOF). (This is why * is provided to 100 * allow explicit specification of INADDR_ANY.) A line 101 * *: 102 * is implicitly in effect at the beginning of the file. 103 * 104 * The hostaddress specifier may (and often will) contain dots; 105 * the service name must not. 106 * 107 * For RPC services, host-address specifiers are accepted and will 108 * work to some extent; however, because of limitations in the 109 * portmapper interface, it will not work to try to give more than 110 * one line for any given RPC service, even if the host-address 111 * specifiers are different. 112 * 113 * Comment lines are indicated by a `#' in column 1. 114 */ 115 116 /* 117 * Here's the scoop concerning the user[.:]group feature: 118 * 119 * 1) set-group-option off. 120 * 121 * a) user = root: NO setuid() or setgid() is done 122 * 123 * b) other: setgid(primary group as found in passwd) 124 * initgroups(name, primary group) 125 * setuid() 126 * 127 * 2) set-group-option on. 128 * 129 * a) user = root: setgid(specified group) 130 * NO initgroups() 131 * NO setuid() 132 * 133 * b) other: setgid(specified group) 134 * initgroups(name, specified group) 135 * setuid() 136 * 137 */ 138 139 #include <sys/param.h> 140 #include <sys/stat.h> 141 #include <sys/ioctl.h> 142 #include <sys/socket.h> 143 #include <sys/un.h> 144 #include <sys/file.h> 145 #include <sys/wait.h> 146 #include <sys/time.h> 147 #include <sys/resource.h> 148 149 #ifndef RLIMIT_NOFILE 150 #define RLIMIT_NOFILE RLIMIT_OFILE 151 #endif 152 153 #include <netinet/in.h> 154 #include <arpa/inet.h> 155 156 #include <errno.h> 157 #include <ctype.h> 158 #include <signal.h> 159 #include <netdb.h> 160 #include <syslog.h> 161 #include <pwd.h> 162 #include <grp.h> 163 #include <stdio.h> 164 #include <stdlib.h> 165 #include <unistd.h> 166 #include <string.h> 167 #include <login_cap.h> 168 #include <rpc/rpc.h> 169 #include <rpc/pmap_clnt.h> 170 #include <rpcsvc/nfs_prot.h> 171 #include "pathnames.h" 172 173 #define TOOMANY 256 /* don't start more than TOOMANY */ 174 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ 175 #define RETRYTIME (60*10) /* retry after bind or server fail */ 176 177 void config __P((int)); 178 void doconfig __P((void)); 179 void reap __P((int)); 180 void doreap __P((void)); 181 void retry __P((int)); 182 void doretry __P((void)); 183 void die __P((int)); 184 void dodie __P((void)); 185 186 int debug = 0; 187 int nsock, maxsock; 188 fd_set *allsockp; 189 int allsockn; 190 int toomany = TOOMANY; 191 int options; 192 int timingout; 193 struct servent *sp; 194 char *curdom; 195 uid_t uid; 196 sigset_t blockmask; 197 sigset_t emptymask; 198 199 #ifndef OPEN_MAX 200 #define OPEN_MAX 64 201 #endif 202 203 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ 204 #define FD_MARGIN (8) 205 typeof(((struct rlimit *)0)->rlim_cur) rlim_ofile_cur = OPEN_MAX; 206 207 #ifdef RLIMIT_NOFILE 208 struct rlimit rlim_ofile; 209 #endif 210 211 struct servtab { 212 char *se_hostaddr; /* host address to listen on */ 213 char *se_service; /* name of service */ 214 int se_socktype; /* type of socket to use */ 215 int se_family; /* address family */ 216 char *se_proto; /* protocol used */ 217 int se_rpcprog; /* rpc program number */ 218 int se_rpcversl; /* rpc program lowest version */ 219 int se_rpcversh; /* rpc program highest version */ 220 #define isrpcservice(sep) ((sep)->se_rpcversl != 0) 221 pid_t se_wait; /* single threaded server */ 222 short se_checked; /* looked at during merge */ 223 char *se_user; /* user name to run as */ 224 char *se_group; /* group name to run as */ 225 struct biltin *se_bi; /* if built-in, description */ 226 char *se_server; /* server program */ 227 #define MAXARGV 20 228 char *se_argv[MAXARGV+1]; /* program arguments */ 229 int se_fd; /* open descriptor */ 230 union { 231 struct sockaddr se_un_ctrladdr; 232 struct sockaddr_in se_un_ctrladdr_in; 233 struct sockaddr_in6 se_un_ctrladdr_in6; 234 struct sockaddr_un se_un_ctrladdr_un; 235 struct sockaddr_storage se_un_ctrladdr_storage; 236 } se_un; /* bound address */ 237 #define se_ctrladdr se_un.se_un_ctrladdr 238 #define se_ctrladdr_in se_un.se_un_ctrladdr_in 239 #define se_ctrladdr_in6 se_un.se_un_ctrladdr_in6 240 #define se_ctrladdr_un se_un.se_un_ctrladdr_un 241 #define se_ctrladdr_storage se_un.se_un_ctrladdr_storage 242 int se_ctrladdr_size; 243 int se_max; /* max # of instances of this service */ 244 int se_count; /* number started since se_time */ 245 struct timeval se_time; /* start of se_count */ 246 struct servtab *se_next; 247 } *servtab; 248 249 void echo_stream __P((int, struct servtab *)); 250 void discard_stream __P((int, struct servtab *)); 251 void machtime_stream __P((int, struct servtab *)); 252 void daytime_stream __P((int, struct servtab *)); 253 void chargen_stream __P((int, struct servtab *)); 254 void echo_dg __P((int, struct servtab *)); 255 void discard_dg __P((int, struct servtab *)); 256 void machtime_dg __P((int, struct servtab *)); 257 void daytime_dg __P((int, struct servtab *)); 258 void chargen_dg __P((int, struct servtab *)); 259 260 struct biltin { 261 char *bi_service; /* internally provided service name */ 262 int bi_socktype; /* type of socket supported */ 263 short bi_fork; /* 1 if should fork before call */ 264 short bi_wait; /* 1 if should wait for child */ 265 void (*bi_fn) __P((int, struct servtab *)); 266 } biltins[] = { 267 /* Echo received data */ 268 { "echo", SOCK_STREAM, 1, 0, echo_stream }, 269 { "echo", SOCK_DGRAM, 0, 0, echo_dg }, 270 271 /* Internet /dev/null */ 272 { "discard", SOCK_STREAM, 1, 0, discard_stream }, 273 { "discard", SOCK_DGRAM, 0, 0, discard_dg }, 274 275 /* Return 32 bit time since 1900 */ 276 { "time", SOCK_STREAM, 0, 0, machtime_stream }, 277 { "time", SOCK_DGRAM, 0, 0, machtime_dg }, 278 279 /* Return human-readable time */ 280 { "daytime", SOCK_STREAM, 0, 0, daytime_stream }, 281 { "daytime", SOCK_DGRAM, 0, 0, daytime_dg }, 282 283 /* Familiar character generator */ 284 { "chargen", SOCK_STREAM, 1, 0, chargen_stream }, 285 { "chargen", SOCK_DGRAM, 0, 0, chargen_dg }, 286 287 { 0 } 288 }; 289 290 volatile sig_atomic_t wantretry; 291 volatile sig_atomic_t wantconfig; 292 volatile sig_atomic_t wantreap; 293 volatile sig_atomic_t wantdie; 294 295 #define NUMINT (sizeof(intab) / sizeof(struct inent)) 296 char *CONFIG = _PATH_INETDCONF; 297 char **Argv; 298 char *LastArg; 299 char *progname; 300 301 void logpid __P((void)); 302 303 void 304 fd_grow(fd_set **fdsp, int *bytes, int fd) 305 { 306 caddr_t new; 307 int newbytes; 308 309 newbytes = howmany(fd+1, NFDBITS) * sizeof(fd_mask); 310 if (newbytes > *bytes) { 311 newbytes *= 2; /* optimism */ 312 new = realloc(*fdsp, newbytes); 313 if (new == NULL) { 314 syslog(LOG_ERR, "Out of memory."); 315 exit(1); 316 } 317 memset(new + *bytes, 0, newbytes - *bytes); 318 *fdsp = (fd_set *)new; 319 *bytes = newbytes; 320 } 321 } 322 323 int 324 main(argc, argv, envp) 325 int argc; 326 char *argv[], *envp[]; 327 { 328 extern char *optarg; 329 extern int optind; 330 register struct servtab *sep; 331 register struct passwd *pwd; 332 register struct group *grp = NULL; 333 register int tmpint; 334 struct sigaction sa, sapipe; 335 int ch, dofork; 336 pid_t pid; 337 char buf[50]; 338 fd_set *readablep = NULL; 339 int readablen = 0; 340 341 Argv = argv; 342 if (envp == 0 || *envp == 0) 343 envp = argv; 344 while (*envp) 345 envp++; 346 LastArg = envp[-1] + strlen(envp[-1]); 347 348 progname = strrchr(argv[0], '/'); 349 progname = progname ? progname + 1 : argv[0]; 350 351 while ((ch = getopt(argc, argv, "dR:")) != -1) 352 switch(ch) { 353 case 'd': 354 debug = 1; 355 options |= SO_DEBUG; 356 break; 357 case 'R': { /* invocation rate */ 358 char *p; 359 int val; 360 361 val = strtoul(optarg, &p, 0); 362 if (val >= 1 && *p == NULL) { 363 toomany = val; 364 break; 365 } 366 syslog(LOG_ERR, 367 "-R %s: bad value for service invocation rate", 368 optarg); 369 break; 370 } 371 case '?': 372 default: 373 fprintf(stderr, "usage: %s [-R rate] [-d] [conf]\n", 374 progname); 375 exit(1); 376 } 377 argc -= optind; 378 argv += optind; 379 380 uid = getuid(); 381 if (uid != 0) 382 CONFIG = NULL; 383 if (argc > 0) 384 CONFIG = argv[0]; 385 if (CONFIG == NULL) { 386 fprintf(stderr, "%s: non-root must specify a config file\n", 387 progname); 388 exit(1); 389 } 390 391 if (debug == 0) { 392 daemon(0, 0); 393 if (uid == 0) 394 (void) setlogin(""); 395 } 396 397 if (uid == 0) { 398 gid_t gid = getgid(); 399 400 /* If run by hand, ensure groups vector gets trashed */ 401 setgroups(1, &gid); 402 } 403 404 openlog(progname, LOG_PID | LOG_NOWAIT, LOG_DAEMON); 405 logpid(); 406 407 #ifdef RLIMIT_NOFILE 408 if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) { 409 syslog(LOG_ERR, "getrlimit: %m"); 410 } else { 411 rlim_ofile_cur = rlim_ofile.rlim_cur; 412 if (rlim_ofile_cur == RLIM_INFINITY) /* ! */ 413 rlim_ofile_cur = OPEN_MAX; 414 } 415 #endif 416 417 sigemptyset(&emptymask); 418 sigemptyset(&blockmask); 419 sigaddset(&blockmask, SIGCHLD); 420 sigaddset(&blockmask, SIGHUP); 421 sigaddset(&blockmask, SIGALRM); 422 423 memset((char *)&sa, 0, sizeof(sa)); 424 sigemptyset(&sa.sa_mask); 425 sigaddset(&sa.sa_mask, SIGALRM); 426 sigaddset(&sa.sa_mask, SIGCHLD); 427 sigaddset(&sa.sa_mask, SIGHUP); 428 sa.sa_handler = retry; 429 sigaction(SIGALRM, &sa, NULL); 430 doconfig(); 431 sa.sa_handler = config; 432 sigaction(SIGHUP, &sa, NULL); 433 sa.sa_handler = reap; 434 sigaction(SIGCHLD, &sa, NULL); 435 sa.sa_handler = die; 436 sigaction(SIGTERM, &sa, NULL); 437 sa.sa_handler = die; 438 sigaction(SIGINT, &sa, NULL); 439 sa.sa_handler = SIG_IGN; 440 sigaction(SIGPIPE, &sa, &sapipe); 441 442 { 443 /* space for daemons to overwrite environment for ps */ 444 #define DUMMYSIZE 100 445 char dummy[DUMMYSIZE]; 446 447 (void)memset(dummy, 'x', DUMMYSIZE - 1); 448 dummy[DUMMYSIZE - 1] = '\0'; 449 450 (void)setenv("inetd_dummy", dummy, 1); 451 } 452 453 for (;;) { 454 int n, ctrl = -1; 455 456 if (nsock == 0) { 457 (void) sigprocmask(SIG_BLOCK, &blockmask, NULL); 458 while (nsock == 0) { 459 if (wantretry || wantconfig || wantreap) 460 break; 461 sigsuspend(&emptymask); 462 } 463 (void) sigprocmask(SIG_SETMASK, &emptymask, NULL); 464 } 465 466 if (wantretry || wantconfig || wantreap) { 467 if (wantretry) { 468 doretry(); 469 wantretry = 0; 470 } 471 if (wantconfig) { 472 doconfig(); 473 wantconfig = 0; 474 } 475 if (wantreap) { 476 doreap(); 477 wantreap = 0; 478 } 479 if (wantdie) { 480 dodie(); 481 } 482 continue; 483 } 484 485 if (readablen != allsockn) { 486 if (readablep) 487 free(readablep); 488 readablep = (fd_set *)calloc(allsockn, 1); 489 if (readablep == NULL) { 490 syslog(LOG_ERR, "Out of memory."); 491 exit(1); 492 } 493 readablen = allsockn; 494 } 495 bcopy(allsockp, readablep, allsockn); 496 497 if ((n = select(maxsock + 1, readablep, NULL, NULL, NULL)) <= 0) { 498 if (n < 0 && errno != EINTR) { 499 syslog(LOG_WARNING, "select: %m"); 500 sleep(1); 501 } 502 continue; 503 } 504 for (sep = servtab; n && sep; sep = sep->se_next) 505 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, readablep)) { 506 n--; 507 if (debug) 508 fprintf(stderr, "someone wants %s\n", sep->se_service); 509 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { 510 ctrl = accept(sep->se_fd, NULL, NULL); 511 if (debug) 512 fprintf(stderr, "accept, ctrl %d\n", ctrl); 513 if (ctrl < 0) { 514 if (errno == EINTR) 515 continue; 516 syslog(LOG_WARNING, "accept (for %s): %m", 517 sep->se_service); 518 continue; 519 } 520 if (sep->se_family == AF_INET && 521 sep->se_socktype == SOCK_STREAM) { 522 struct sockaddr_in peer; 523 int plen = sizeof(peer); 524 525 if (getpeername(ctrl, (struct sockaddr *)&peer, 526 &plen) < 0) { 527 syslog(LOG_WARNING, "could not getpeername"); 528 close(ctrl); 529 continue; 530 } 531 if (ntohs(peer.sin_port) == 20) { 532 /* ignore things that look like ftp bounce */ 533 close(ctrl); 534 continue; 535 } 536 } 537 } else 538 ctrl = sep->se_fd; 539 (void) sigprocmask(SIG_BLOCK, &blockmask, NULL); 540 pid = 0; 541 dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork); 542 if (dofork) { 543 if (sep->se_count++ == 0) 544 (void)gettimeofday(&sep->se_time, NULL); 545 else if (sep->se_count >= sep->se_max) { 546 struct timeval now; 547 548 (void)gettimeofday(&now, NULL); 549 if (now.tv_sec - sep->se_time.tv_sec > 550 CNT_INTVL) { 551 sep->se_time = now; 552 sep->se_count = 1; 553 } else { 554 if (!sep->se_wait && 555 sep->se_socktype == SOCK_STREAM) 556 close(ctrl); 557 if (sep->se_family == AF_INET && 558 ntohs(sep->se_ctrladdr_in.sin_port) >= 559 IPPORT_RESERVED) { 560 /* 561 * Cannot close it -- there are 562 * thieves on the system. 563 * Simply ignore the connection. 564 */ 565 --sep->se_count; 566 continue; 567 } 568 syslog(LOG_ERR, 569 "%s/%s server failing (looping), service terminated", 570 sep->se_service, sep->se_proto); 571 if (!sep->se_wait && 572 sep->se_socktype == SOCK_STREAM) 573 close(ctrl); 574 FD_CLR(sep->se_fd, allsockp); 575 (void) close(sep->se_fd); 576 sep->se_fd = -1; 577 sep->se_count = 0; 578 nsock--; 579 sigprocmask(SIG_SETMASK, &emptymask, 580 NULL); 581 if (!timingout) { 582 timingout = 1; 583 alarm(RETRYTIME); 584 } 585 continue; 586 } 587 } 588 pid = fork(); 589 } 590 if (pid < 0) { 591 syslog(LOG_ERR, "fork: %m"); 592 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 593 close(ctrl); 594 sigprocmask(SIG_SETMASK, &emptymask, NULL); 595 sleep(1); 596 continue; 597 } 598 if (pid && sep->se_wait) { 599 sep->se_wait = pid; 600 FD_CLR(sep->se_fd, allsockp); 601 nsock--; 602 } 603 sigprocmask(SIG_SETMASK, &emptymask, NULL); 604 if (pid == 0) { 605 if (sep->se_bi) 606 (*sep->se_bi->bi_fn)(ctrl, sep); 607 else { 608 if ((pwd = getpwnam(sep->se_user)) == NULL) { 609 syslog(LOG_ERR, 610 "getpwnam: %s: No such user", 611 sep->se_user); 612 if (sep->se_socktype != SOCK_STREAM) 613 recv(0, buf, sizeof (buf), 0); 614 exit(1); 615 } 616 if (setsid() <0) 617 syslog(LOG_ERR, "%s: setsid: %m", 618 sep->se_service); 619 if (sep->se_group && 620 (grp = getgrnam(sep->se_group)) == NULL) { 621 syslog(LOG_ERR, 622 "getgrnam: %s: No such group", 623 sep->se_group); 624 if (sep->se_socktype != SOCK_STREAM) 625 recv(0, buf, sizeof (buf), 0); 626 exit(1); 627 } 628 if (uid != 0) { 629 /* a user running private inetd */ 630 if (uid != pwd->pw_uid) 631 exit(1); 632 } else { 633 tmpint = LOGIN_SETALL & 634 ~(LOGIN_SETGROUP|LOGIN_SETLOGIN); 635 if (pwd->pw_uid) 636 tmpint |= LOGIN_SETGROUP|LOGIN_SETLOGIN; 637 if (sep->se_group) { 638 pwd->pw_gid = grp->gr_gid; 639 tmpint |= LOGIN_SETGROUP; 640 } 641 if (setusercontext(0, pwd, pwd->pw_uid, 642 tmpint) < 0) 643 syslog(LOG_ERR, 644 "%s/%s: setusercontext: %m", 645 sep->se_service, 646 sep->se_proto); 647 } 648 if (debug) 649 fprintf(stderr, "%d execl %s\n", 650 getpid(), sep->se_server); 651 dup2(ctrl, 0); 652 close(ctrl); 653 dup2(0, 1); 654 dup2(0, 2); 655 closelog(); 656 for (tmpint = rlim_ofile_cur-1; --tmpint > 2; ) 657 (void)close(tmpint); 658 sigaction(SIGPIPE, &sapipe, NULL); 659 execv(sep->se_server, sep->se_argv); 660 if (sep->se_socktype != SOCK_STREAM) 661 recv(0, buf, sizeof (buf), 0); 662 syslog(LOG_ERR, "execv %s: %m", sep->se_server); 663 exit(1); 664 } 665 } 666 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) 667 close(ctrl); 668 } 669 } 670 } 671 672 int 673 dg_badinput(sa) 674 struct sockaddr *sa; 675 { 676 struct in_addr in; 677 struct in6_addr *in6; 678 u_int16_t port; 679 680 switch (sa->sa_family) { 681 case AF_INET: 682 in.s_addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr); 683 port = ntohs(((struct sockaddr_in *)sa)->sin_port); 684 v4chk: 685 if (IN_MULTICAST(in.s_addr)) 686 goto bad; 687 switch ((in.s_addr & 0xff000000) >> 24) { 688 case 0: case 127: case 255: 689 goto bad; 690 } 691 /* XXX should check for subnet broadcast using getifaddrs(3) */ 692 break; 693 case AF_INET6: 694 in6 = &((struct sockaddr_in6 *)sa)->sin6_addr; 695 port = ntohs(((struct sockaddr_in6 *)sa)->sin6_port); 696 if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6)) 697 goto bad; 698 /* 699 * OpenBSD does not support IPv4 mapped adderss (RFC2553 700 * inbound behavior) at all. We should drop it. 701 */ 702 if (IN6_IS_ADDR_V4MAPPED(in6)) 703 goto bad; 704 if (IN6_IS_ADDR_V4COMPAT(in6)) { 705 memcpy(&in, &in6->s6_addr[12], sizeof(in)); 706 in.s_addr = ntohl(in.s_addr); 707 goto v4chk; 708 } 709 break; 710 default: 711 /* XXX unsupported af, is it safe to assume it to be safe? */ 712 return 0; 713 } 714 715 if (port < IPPORT_RESERVED || port == NFS_PORT) 716 goto bad; 717 718 return (0); 719 720 bad: 721 return (1); 722 } 723 724 void 725 reap(int sig) 726 { 727 wantreap = 1; 728 } 729 730 void 731 doreap(void) 732 { 733 pid_t pid; 734 int status; 735 register struct servtab *sep; 736 737 if (debug) 738 fprintf(stderr, "reaping asked for\n"); 739 740 for (;;) { 741 pid = wait3(&status, WNOHANG, NULL); 742 if (pid <= 0) 743 break; 744 if (debug) 745 fprintf(stderr, "%d reaped, status %x\n", pid, status); 746 for (sep = servtab; sep; sep = sep->se_next) 747 if (sep->se_wait == pid) { 748 if (WIFEXITED(status) && WEXITSTATUS(status)) 749 syslog(LOG_WARNING, 750 "%s: exit status 0x%x", 751 sep->se_server, WEXITSTATUS(status)); 752 else if (WIFSIGNALED(status)) 753 syslog(LOG_WARNING, 754 "%s: exit signal 0x%x", 755 sep->se_server, WTERMSIG(status)); 756 sep->se_wait = 1; 757 fd_grow(&allsockp, &allsockn, sep->se_fd); 758 FD_SET(sep->se_fd, allsockp); 759 nsock++; 760 if (debug) 761 fprintf(stderr, "restored %s, fd %d\n", 762 sep->se_service, sep->se_fd); 763 } 764 } 765 } 766 767 int setconfig __P((void)); 768 void endconfig __P((void)); 769 770 void register_rpc __P((struct servtab *)); 771 void unregister_rpc __P((struct servtab *)); 772 void freeconfig __P((struct servtab *)); 773 void print_service __P((char *, struct servtab *)); 774 void setup __P((struct servtab *)); 775 struct servtab *getconfigent __P((void)); 776 struct servtab *enter __P((struct servtab *)); 777 int matchconf __P((struct servtab *, struct servtab *)); 778 779 void 780 config(int sig) 781 { 782 wantconfig = 1; 783 } 784 785 void 786 doconfig(void) 787 { 788 register struct servtab *sep, *cp, **sepp; 789 int n, add; 790 char protoname[10]; 791 sigset_t omask; 792 793 if (!setconfig()) { 794 syslog(LOG_ERR, "%s: %m", CONFIG); 795 return; 796 } 797 for (sep = servtab; sep; sep = sep->se_next) 798 sep->se_checked = 0; 799 cp = getconfigent(); 800 while (cp != NULL) { 801 for (sep = servtab; sep; sep = sep->se_next) 802 if (matchconf(sep, cp)) 803 break; 804 add = 0; 805 if (sep != 0) { 806 int i; 807 808 #define SWAP(type, a, b) {type c=(type)a; (type)a=(type)b; (type)b=(type)c;} 809 810 sigprocmask(SIG_BLOCK, &blockmask, &omask); 811 /* 812 * sep->se_wait may be holding the pid of a daemon 813 * that we're waiting for. If so, don't overwrite 814 * it unless the config file explicitly says don't 815 * wait. 816 */ 817 if (cp->se_bi == 0 && 818 (sep->se_wait == 1 || cp->se_wait == 0)) 819 sep->se_wait = cp->se_wait; 820 SWAP(int, cp->se_max, sep->se_max); 821 SWAP(char *, sep->se_user, cp->se_user); 822 SWAP(char *, sep->se_group, cp->se_group); 823 SWAP(char *, sep->se_server, cp->se_server); 824 for (i = 0; i < MAXARGV; i++) 825 SWAP(char *, sep->se_argv[i], cp->se_argv[i]); 826 #undef SWAP 827 if (isrpcservice(sep)) 828 unregister_rpc(sep); 829 sep->se_rpcversl = cp->se_rpcversl; 830 sep->se_rpcversh = cp->se_rpcversh; 831 sigprocmask(SIG_SETMASK, &omask, NULL); 832 freeconfig(cp); 833 add = 1; 834 } else { 835 sep = enter(cp); 836 } 837 sep->se_checked = 1; 838 839 switch (sep->se_family) { 840 case AF_UNIX: 841 if (sep->se_fd != -1) 842 break; 843 (void)unlink(sep->se_service); 844 n = strlen(sep->se_service); 845 if (n > sizeof sep->se_ctrladdr_un.sun_path - 1) 846 n = sizeof sep->se_ctrladdr_un.sun_path - 1; 847 strncpy(sep->se_ctrladdr_un.sun_path, 848 sep->se_service, n); 849 sep->se_ctrladdr_un.sun_path[n] = '\0'; 850 sep->se_ctrladdr_un.sun_family = AF_UNIX; 851 sep->se_ctrladdr_size = n + 852 sizeof sep->se_ctrladdr_un.sun_family; 853 setup(sep); 854 break; 855 case AF_INET: 856 sep->se_ctrladdr_in.sin_family = AF_INET; 857 /* se_ctrladdr_in was set in getconfigent */ 858 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in; 859 860 if (isrpcservice(sep)) { 861 struct rpcent *rp; 862 863 sep->se_rpcprog = atoi(sep->se_service); 864 if (sep->se_rpcprog == 0) { 865 rp = getrpcbyname(sep->se_service); 866 if (rp == 0) { 867 syslog(LOG_ERR, 868 "%s: unknown rpc service", 869 sep->se_service); 870 goto serv_unknown; 871 } 872 sep->se_rpcprog = rp->r_number; 873 } 874 if (sep->se_fd == -1) 875 setup(sep); 876 if (sep->se_fd != -1) 877 register_rpc(sep); 878 } else { 879 u_short port = htons(atoi(sep->se_service)); 880 881 if (!port) { 882 /* XXX */ 883 strncpy(protoname, sep->se_proto, 884 sizeof(protoname)); 885 if (isdigit(protoname[strlen(protoname) - 1])) 886 protoname[strlen(protoname) - 1] = '\0'; 887 sp = getservbyname(sep->se_service, 888 protoname); 889 if (sp == 0) { 890 syslog(LOG_ERR, 891 "%s/%s: unknown service", 892 sep->se_service, sep->se_proto); 893 goto serv_unknown; 894 } 895 port = sp->s_port; 896 } 897 if (port != sep->se_ctrladdr_in.sin_port) { 898 sep->se_ctrladdr_in.sin_port = port; 899 if (sep->se_fd != -1) { 900 FD_CLR(sep->se_fd, allsockp); 901 nsock--; 902 (void) close(sep->se_fd); 903 } 904 sep->se_fd = -1; 905 } 906 if (sep->se_fd == -1) 907 setup(sep); 908 } 909 break; 910 case AF_INET6: 911 sep->se_ctrladdr_in6.sin6_family = AF_INET6; 912 /* se_ctrladdr_in was set in getconfigent */ 913 sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in6; 914 915 if (isrpcservice(sep)) { 916 struct rpcent *rp; 917 918 sep->se_rpcprog = atoi(sep->se_service); 919 if (sep->se_rpcprog == 0) { 920 rp = getrpcbyname(sep->se_service); 921 if (rp == 0) { 922 syslog(LOG_ERR, 923 "%s: unknown rpc service", 924 sep->se_service); 925 goto serv_unknown; 926 } 927 sep->se_rpcprog = rp->r_number; 928 } 929 if (sep->se_fd == -1) 930 setup(sep); 931 if (sep->se_fd != -1) 932 register_rpc(sep); 933 } else { 934 u_short port = htons(atoi(sep->se_service)); 935 936 if (!port) { 937 /* XXX */ 938 strncpy(protoname, sep->se_proto, 939 sizeof(protoname)); 940 if (isdigit(protoname[strlen(protoname) - 1])) 941 protoname[strlen(protoname) - 1] = '\0'; 942 sp = getservbyname(sep->se_service, 943 protoname); 944 if (sp == 0) { 945 syslog(LOG_ERR, 946 "%s/%s: unknown service", 947 sep->se_service, sep->se_proto); 948 goto serv_unknown; 949 } 950 port = sp->s_port; 951 } 952 if (port != sep->se_ctrladdr_in6.sin6_port) { 953 sep->se_ctrladdr_in6.sin6_port = port; 954 if (sep->se_fd != -1) { 955 FD_CLR(sep->se_fd, allsockp); 956 nsock--; 957 (void) close(sep->se_fd); 958 } 959 sep->se_fd = -1; 960 } 961 if (sep->se_fd == -1) 962 setup(sep); 963 } 964 break; 965 } 966 serv_unknown: 967 if (cp->se_next != NULL) { 968 struct servtab *tmp = cp; 969 970 cp = cp->se_next; 971 free(tmp); 972 } else { 973 free(cp); 974 cp = getconfigent(); 975 } 976 if (debug) 977 print_service(add ? "REDO" : "ADD", sep); 978 } 979 endconfig(); 980 /* 981 * Purge anything not looked at above. 982 */ 983 sigprocmask(SIG_BLOCK, &blockmask, &omask); 984 sepp = &servtab; 985 while ((sep = *sepp)) { 986 if (sep->se_checked) { 987 sepp = &sep->se_next; 988 continue; 989 } 990 *sepp = sep->se_next; 991 if (sep->se_fd != -1) { 992 FD_CLR(sep->se_fd, allsockp); 993 nsock--; 994 (void) close(sep->se_fd); 995 } 996 if (isrpcservice(sep)) 997 unregister_rpc(sep); 998 if (sep->se_family == AF_UNIX) 999 (void)unlink(sep->se_service); 1000 if (debug) 1001 print_service("FREE", sep); 1002 freeconfig(sep); 1003 free((char *)sep); 1004 } 1005 sigprocmask(SIG_SETMASK, &omask, NULL); 1006 } 1007 1008 void 1009 retry(int sig) 1010 { 1011 wantretry = 1; 1012 } 1013 1014 void 1015 doretry(void) 1016 { 1017 register struct servtab *sep; 1018 1019 timingout = 0; 1020 for (sep = servtab; sep; sep = sep->se_next) { 1021 if (sep->se_fd == -1) { 1022 switch (sep->se_family) { 1023 case AF_UNIX: 1024 case AF_INET: 1025 case AF_INET6: 1026 setup(sep); 1027 if (sep->se_fd != -1 && isrpcservice(sep)) 1028 register_rpc(sep); 1029 break; 1030 } 1031 } 1032 } 1033 } 1034 1035 void 1036 die(int sig) 1037 { 1038 wantdie = 1; 1039 } 1040 1041 void 1042 dodie(void) 1043 { 1044 register struct servtab *sep; 1045 1046 for (sep = servtab; sep; sep = sep->se_next) { 1047 if (sep->se_fd == -1) 1048 continue; 1049 1050 switch (sep->se_family) { 1051 case AF_UNIX: 1052 (void)unlink(sep->se_service); 1053 break; 1054 case AF_INET: 1055 case AF_INET6: 1056 if (sep->se_wait == 1 && isrpcservice(sep)) 1057 unregister_rpc(sep); 1058 break; 1059 } 1060 (void)close(sep->se_fd); 1061 } 1062 (void)unlink(_PATH_INETDPID); 1063 exit(0); 1064 } 1065 1066 int bump_nofile __P((void)); 1067 1068 void 1069 setup(sep) 1070 register struct servtab *sep; 1071 { 1072 int on = 1; 1073 int r; 1074 1075 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { 1076 syslog(LOG_ERR, "%s/%s: socket: %m", 1077 sep->se_service, sep->se_proto); 1078 return; 1079 } 1080 #define turnon(fd, opt) \ 1081 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) 1082 if (strncmp(sep->se_proto, "tcp", 3) == 0 && (options & SO_DEBUG) && 1083 turnon(sep->se_fd, SO_DEBUG) < 0) 1084 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 1085 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 1086 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 1087 #undef turnon 1088 if (isrpcservice(sep)) { 1089 struct passwd *pwd; 1090 1091 /* 1092 * for RPC services, attempt to use a reserved port 1093 * if they are going to be running as root. 1094 * 1095 * Also, zero out the port for all RPC services; let bind() 1096 * find one. 1097 */ 1098 sep->se_ctrladdr_in.sin_port = 0; 1099 if (sep->se_user && (pwd = getpwnam(sep->se_user)) && 1100 pwd->pw_uid == 0 && uid == 0) 1101 r = bindresvport(sep->se_fd, &sep->se_ctrladdr_in); 1102 else { 1103 r = bind(sep->se_fd, &sep->se_ctrladdr, 1104 sep->se_ctrladdr_size); 1105 if (r == 0) { 1106 int len = sep->se_ctrladdr_size; 1107 int saveerrno = errno; 1108 1109 /* update se_ctrladdr_in.sin_port */ 1110 r = getsockname(sep->se_fd, &sep->se_ctrladdr, 1111 &len); 1112 if (r <= 0) 1113 errno = saveerrno; 1114 } 1115 } 1116 } else 1117 r = bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size); 1118 if (r < 0) { 1119 syslog(LOG_ERR, "%s/%s: bind: %m", 1120 sep->se_service, sep->se_proto); 1121 (void) close(sep->se_fd); 1122 sep->se_fd = -1; 1123 if (!timingout) { 1124 timingout = 1; 1125 alarm(RETRYTIME); 1126 } 1127 return; 1128 } 1129 if (sep->se_socktype == SOCK_STREAM) 1130 listen(sep->se_fd, 10); 1131 1132 fd_grow(&allsockp, &allsockn, sep->se_fd); 1133 FD_SET(sep->se_fd, allsockp); 1134 nsock++; 1135 if (sep->se_fd > maxsock) { 1136 maxsock = sep->se_fd; 1137 if (maxsock > rlim_ofile_cur - FD_MARGIN) 1138 bump_nofile(); 1139 } 1140 } 1141 1142 void 1143 register_rpc(sep) 1144 register struct servtab *sep; 1145 { 1146 int n; 1147 struct sockaddr_in sin; 1148 struct protoent *pp; 1149 1150 if ((pp = getprotobyname(sep->se_proto+4)) == NULL) { 1151 syslog(LOG_ERR, "%s: getproto: %m", 1152 sep->se_proto); 1153 return; 1154 } 1155 n = sizeof sin; 1156 if (getsockname(sep->se_fd, (struct sockaddr *)&sin, &n) < 0) { 1157 syslog(LOG_ERR, "%s/%s: getsockname: %m", 1158 sep->se_service, sep->se_proto); 1159 return; 1160 } 1161 1162 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1163 if (debug) 1164 fprintf(stderr, "pmap_set: %u %u %u %u\n", 1165 sep->se_rpcprog, n, pp->p_proto, 1166 ntohs(sin.sin_port)); 1167 (void)pmap_unset(sep->se_rpcprog, n); 1168 if (!pmap_set(sep->se_rpcprog, n, pp->p_proto, ntohs(sin.sin_port))) 1169 syslog(LOG_ERR, "%s %s: pmap_set: %u %u %u %u: %m", 1170 sep->se_service, sep->se_proto, 1171 sep->se_rpcprog, n, pp->p_proto, 1172 ntohs(sin.sin_port)); 1173 } 1174 } 1175 1176 void 1177 unregister_rpc(sep) 1178 register struct servtab *sep; 1179 { 1180 int n; 1181 1182 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1183 if (debug) 1184 fprintf(stderr, "pmap_unset(%u, %u)\n", 1185 sep->se_rpcprog, n); 1186 if (!pmap_unset(sep->se_rpcprog, n)) 1187 syslog(LOG_ERR, "pmap_unset(%u, %u)", 1188 sep->se_rpcprog, n); 1189 } 1190 } 1191 1192 1193 struct servtab * 1194 enter(cp) 1195 struct servtab *cp; 1196 { 1197 register struct servtab *sep; 1198 sigset_t omask; 1199 1200 sep = (struct servtab *)malloc(sizeof (*sep)); 1201 if (sep == NULL) { 1202 syslog(LOG_ERR, "Out of memory."); 1203 exit(1); 1204 } 1205 *sep = *cp; 1206 sep->se_fd = -1; 1207 sep->se_rpcprog = -1; 1208 sigprocmask(SIG_BLOCK, &blockmask, &omask); 1209 sep->se_next = servtab; 1210 servtab = sep; 1211 sigprocmask(SIG_SETMASK, &omask, NULL); 1212 return (sep); 1213 } 1214 1215 int 1216 matchconf (old, new) 1217 struct servtab *old; 1218 struct servtab *new; 1219 { 1220 if (strcmp(old->se_service, new->se_service) != 0) 1221 return (0); 1222 1223 if (strcmp(old->se_hostaddr, new->se_hostaddr) != 0) 1224 return (0); 1225 1226 if (strcmp(old->se_proto, new->se_proto) != 0) 1227 return (0); 1228 1229 /* 1230 * If the new servtab is bound to a specific address, check that the 1231 * old servtab is bound to the same entry. If the new service is not 1232 * bound to a specific address then the check of se_hostaddr above 1233 * is sufficient. 1234 */ 1235 1236 if (old->se_family == AF_INET && new->se_family == AF_INET && 1237 bcmp(&old->se_ctrladdr_in.sin_addr, 1238 &new->se_ctrladdr_in.sin_addr, 1239 sizeof(new->se_ctrladdr_in.sin_addr)) != 0) 1240 return (0); 1241 1242 if (old->se_family == AF_INET6 && new->se_family == AF_INET6 && 1243 bcmp(&old->se_ctrladdr_in6.sin6_addr, 1244 &new->se_ctrladdr_in6.sin6_addr, 1245 sizeof(new->se_ctrladdr_in6.sin6_addr)) != 0) 1246 return (0); 1247 if (old->se_family == AF_INET6 && new->se_family == AF_INET6 && 1248 old->se_ctrladdr_in6.sin6_scope_id != 1249 new->se_ctrladdr_in6.sin6_scope_id) 1250 return (0); 1251 1252 return (1); 1253 } 1254 1255 FILE *fconfig = NULL; 1256 char line[1024]; 1257 char *defhost; 1258 char *skip __P((char **, int)); 1259 char *nextline __P((FILE *)); 1260 char *newstr __P((char *)); 1261 struct servtab *dupconfig __P((struct servtab *)); 1262 1263 int 1264 setconfig() 1265 { 1266 if (defhost) free(defhost); 1267 defhost = newstr("*"); 1268 if (fconfig != NULL) { 1269 fseek(fconfig, 0L, SEEK_SET); 1270 return (1); 1271 } 1272 fconfig = fopen(CONFIG, "r"); 1273 return (fconfig != NULL); 1274 } 1275 1276 void 1277 endconfig() 1278 { 1279 if (fconfig) { 1280 (void) fclose(fconfig); 1281 fconfig = NULL; 1282 } 1283 if (defhost) { 1284 free(defhost); 1285 defhost = 0; 1286 } 1287 } 1288 1289 struct servtab * 1290 getconfigent() 1291 { 1292 register struct servtab *sep; 1293 int argc; 1294 char *cp, *arg, *s; 1295 char *hostdelim; 1296 struct servtab *nsep; 1297 struct servtab *psep; 1298 1299 sep = (struct servtab *) malloc(sizeof(struct servtab)); 1300 if (sep == NULL) { 1301 syslog(LOG_ERR, "malloc: %m"); 1302 exit(1); 1303 } 1304 1305 memset(sep, 0, sizeof *sep); 1306 more: 1307 freeconfig(sep); 1308 1309 while ((cp = nextline(fconfig)) && *cp == '#') 1310 ; 1311 if (cp == NULL) { 1312 free(sep); 1313 return (NULL); 1314 } 1315 1316 memset((char *)sep, 0, sizeof *sep); 1317 arg = skip(&cp, 0); 1318 if (arg == NULL) { 1319 /* A blank line. */ 1320 goto more; 1321 } 1322 1323 /* Check for a host name. */ 1324 hostdelim = strrchr(arg, ':'); 1325 if (hostdelim) { 1326 *hostdelim = '\0'; 1327 if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') { 1328 hostdelim[-1] = '\0'; 1329 sep->se_hostaddr = newstr(arg + 1); 1330 } else 1331 sep->se_hostaddr = newstr(arg); 1332 arg = hostdelim + 1; 1333 /* 1334 * If the line is of the form `host:', then just change the 1335 * default host for the following lines. 1336 */ 1337 if (*arg == '\0') { 1338 arg = skip(&cp, 0); 1339 if (cp == NULL) { 1340 free(defhost); 1341 defhost = newstr(sep->se_hostaddr); 1342 goto more; 1343 } 1344 } 1345 } else 1346 sep->se_hostaddr = newstr(defhost); 1347 1348 sep->se_service = newstr(arg); 1349 if ((arg = skip(&cp, 1)) == NULL) 1350 goto more; 1351 1352 if (strcmp(arg, "stream") == 0) 1353 sep->se_socktype = SOCK_STREAM; 1354 else if (strcmp(arg, "dgram") == 0) 1355 sep->se_socktype = SOCK_DGRAM; 1356 else if (strcmp(arg, "rdm") == 0) 1357 sep->se_socktype = SOCK_RDM; 1358 else if (strcmp(arg, "seqpacket") == 0) 1359 sep->se_socktype = SOCK_SEQPACKET; 1360 else if (strcmp(arg, "raw") == 0) 1361 sep->se_socktype = SOCK_RAW; 1362 else 1363 sep->se_socktype = -1; 1364 1365 if ((arg = skip(&cp, 1)) == NULL) 1366 goto more; 1367 1368 sep->se_proto = newstr(arg); 1369 1370 if (strcmp(sep->se_proto, "unix") == 0) { 1371 sep->se_family = AF_UNIX; 1372 } else { 1373 sep->se_family = AF_INET; 1374 if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') 1375 sep->se_family = AF_INET6; 1376 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 1377 char *cp, *ccp; 1378 long l; 1379 1380 cp = strchr(sep->se_service, '/'); 1381 if (cp == 0) { 1382 syslog(LOG_ERR, "%s: no rpc version", 1383 sep->se_service); 1384 goto more; 1385 } 1386 *cp++ = '\0'; 1387 l = strtol(cp, &ccp, 0); 1388 if (ccp == cp || l < 0 || l > INT_MAX) { 1389 badafterall: 1390 syslog(LOG_ERR, "%s/%s: bad rpc version", 1391 sep->se_service, cp); 1392 goto more; 1393 } 1394 sep->se_rpcversl = sep->se_rpcversh = l; 1395 if (*ccp == '-') { 1396 cp = ccp + 1; 1397 l = strtol(cp, &ccp, 0); 1398 if (ccp == cp || l < 0 || l > INT_MAX || 1399 l < sep->se_rpcversl || *ccp) 1400 goto badafterall; 1401 sep->se_rpcversh = l; 1402 } else if (*ccp != '\0') 1403 goto badafterall; 1404 } 1405 } 1406 arg = skip(&cp, 1); 1407 if (arg == NULL) 1408 goto more; 1409 1410 s = strchr(arg, '.'); 1411 if (s) { 1412 char *p; 1413 1414 *s++ = '\0'; 1415 sep->se_max = strtoul(s, &p, 0); 1416 if (sep->se_max < 1 || *p) { 1417 syslog(LOG_ERR, "%s: illegal max field \"%s\", setting to %d", 1418 sep->se_service, s, toomany); 1419 sep->se_max = toomany; 1420 } 1421 } else 1422 sep->se_max = toomany; 1423 1424 sep->se_wait = strcmp(arg, "wait") == 0; 1425 if ((arg = skip(&cp, 1)) == NULL) 1426 goto more; 1427 sep->se_user = newstr(arg); 1428 arg = strchr(sep->se_user, '.'); 1429 if (arg == NULL) 1430 arg = strchr(sep->se_user, ':'); 1431 if (arg) { 1432 *arg++ = '\0'; 1433 sep->se_group = newstr(arg); 1434 } 1435 if ((arg = skip(&cp, 1)) == NULL) 1436 goto more; 1437 1438 sep->se_server = newstr(arg); 1439 if (strcmp(sep->se_server, "internal") == 0) { 1440 struct biltin *bi; 1441 1442 for (bi = biltins; bi->bi_service; bi++) 1443 if (bi->bi_socktype == sep->se_socktype && 1444 strcmp(bi->bi_service, sep->se_service) == 0) 1445 break; 1446 if (bi->bi_service == 0) { 1447 syslog(LOG_ERR, "internal service %s unknown", 1448 sep->se_service); 1449 goto more; 1450 } 1451 sep->se_bi = bi; 1452 sep->se_wait = bi->bi_wait; 1453 } else 1454 sep->se_bi = NULL; 1455 argc = 0; 1456 for (arg = skip(&cp, 0); cp; arg = skip(&cp, 0)) { 1457 if (argc < MAXARGV) 1458 sep->se_argv[argc++] = newstr(arg); 1459 } 1460 while (argc <= MAXARGV) 1461 sep->se_argv[argc++] = NULL; 1462 1463 /* 1464 * Now that we've processed the entire line, check if the hostname 1465 * specifier was a comma separated list of hostnames. If so 1466 * we'll make new entries for each address. 1467 */ 1468 while ((hostdelim = strrchr(sep->se_hostaddr, ',')) != NULL) { 1469 nsep = dupconfig(sep); 1470 1471 /* 1472 * NULL terminate the hostname field of the existing entry, 1473 * and make a dup for the new entry. 1474 */ 1475 *hostdelim++ = '\0'; 1476 nsep->se_hostaddr = newstr(hostdelim); 1477 1478 nsep->se_next = sep->se_next; 1479 sep->se_next = nsep; 1480 } 1481 1482 nsep = sep; 1483 while (nsep != NULL) { 1484 nsep->se_checked = 1; 1485 switch (nsep->se_family) { 1486 case AF_INET: 1487 case AF_INET6: 1488 { 1489 struct addrinfo hints, *res0, *res; 1490 char *host, *port; 1491 int error; 1492 int s; 1493 1494 /* check if the family is supported */ 1495 s = socket(nsep->se_family, SOCK_DGRAM, 0); 1496 if (s < 0) { 1497 syslog(LOG_WARNING, 1498 "%s/%s: %s: the address family is not supported by the kernel", 1499 nsep->se_service, nsep->se_proto, 1500 nsep->se_hostaddr); 1501 nsep->se_checked = 0; 1502 goto skip; 1503 } 1504 close(s); 1505 1506 memset(&hints, 0, sizeof(hints)); 1507 hints.ai_family = nsep->se_family; 1508 hints.ai_socktype = nsep->se_socktype; 1509 hints.ai_flags = AI_PASSIVE; 1510 if (!strcmp(nsep->se_hostaddr, "*")) 1511 host = NULL; 1512 else 1513 host = nsep->se_hostaddr; 1514 port = "0"; 1515 /* XXX shortened IPv4 syntax is now forbidden */ 1516 error = getaddrinfo(host, port, &hints, &res0); 1517 if (error) { 1518 syslog(LOG_ERR, "%s/%s: %s: %s", 1519 nsep->se_service, nsep->se_proto, 1520 nsep->se_hostaddr, 1521 gai_strerror(error)); 1522 nsep->se_checked = 0; 1523 goto skip; 1524 } 1525 for (res = res0; res; res = res->ai_next) { 1526 if (res->ai_addrlen > 1527 sizeof(nsep->se_ctrladdr_storage)) 1528 continue; 1529 if (res == res0) { 1530 memcpy(&nsep->se_ctrladdr_storage, 1531 res->ai_addr, res->ai_addrlen); 1532 continue; 1533 } 1534 1535 psep = dupconfig(nsep); 1536 psep->se_hostaddr = newstr(nsep->se_hostaddr); 1537 psep->se_checked = 1; 1538 memcpy(&psep->se_ctrladdr_storage, res->ai_addr, 1539 res->ai_addrlen); 1540 psep->se_ctrladdr_size = res->ai_addrlen; 1541 1542 /* 1543 * Prepend to list, don't want to look up its 1544 * hostname again. 1545 */ 1546 psep->se_next = sep; 1547 sep = psep; 1548 } 1549 freeaddrinfo(res0); 1550 break; 1551 } 1552 } 1553 skip: 1554 nsep = nsep->se_next; 1555 } 1556 1557 /* 1558 * Finally, free any entries which failed the gethostbyname 1559 * check. 1560 */ 1561 psep = NULL; 1562 nsep = sep; 1563 while (nsep != NULL) { 1564 struct servtab *tsep; 1565 1566 if (nsep->se_checked == 0) { 1567 tsep = nsep; 1568 if (psep == NULL) { 1569 sep = nsep->se_next; 1570 nsep = sep; 1571 } else { 1572 nsep = nsep->se_next; 1573 psep->se_next = nsep; 1574 } 1575 freeconfig(tsep); 1576 } else { 1577 nsep->se_checked = 0; 1578 psep = nsep; 1579 nsep = nsep->se_next; 1580 } 1581 } 1582 1583 return (sep); 1584 } 1585 1586 void 1587 freeconfig(cp) 1588 register struct servtab *cp; 1589 { 1590 int i; 1591 1592 if (cp->se_hostaddr) 1593 free(cp->se_hostaddr); 1594 if (cp->se_service) 1595 free(cp->se_service); 1596 if (cp->se_proto) 1597 free(cp->se_proto); 1598 if (cp->se_user) 1599 free(cp->se_user); 1600 if (cp->se_group) 1601 free(cp->se_group); 1602 if (cp->se_server) 1603 free(cp->se_server); 1604 for (i = 0; i < MAXARGV; i++) 1605 if (cp->se_argv[i]) 1606 free(cp->se_argv[i]); 1607 } 1608 1609 char * 1610 skip(cpp, report) 1611 char **cpp; 1612 int report; 1613 { 1614 char *cp = *cpp; 1615 char *start; 1616 1617 erp: 1618 if (*cpp == NULL) { 1619 if (report) 1620 syslog(LOG_ERR, "syntax error in inetd config file"); 1621 return (NULL); 1622 } 1623 1624 again: 1625 while (*cp == ' ' || *cp == '\t') 1626 cp++; 1627 if (*cp == '\0') { 1628 int c; 1629 1630 c = getc(fconfig); 1631 (void) ungetc(c, fconfig); 1632 if (c == ' ' || c == '\t') 1633 if ((cp = nextline(fconfig))) 1634 goto again; 1635 *cpp = NULL; 1636 goto erp; 1637 } 1638 start = cp; 1639 while (*cp && *cp != ' ' && *cp != '\t') 1640 cp++; 1641 if (*cp != '\0') 1642 *cp++ = '\0'; 1643 if ((*cpp = cp) == NULL) 1644 goto erp; 1645 1646 return (start); 1647 } 1648 1649 char * 1650 nextline(fd) 1651 FILE *fd; 1652 { 1653 char *cp; 1654 1655 if (fgets(line, sizeof (line), fd) == NULL) 1656 return (NULL); 1657 cp = strchr(line, '\n'); 1658 if (cp) 1659 *cp = '\0'; 1660 return (line); 1661 } 1662 1663 char * 1664 newstr(cp) 1665 char *cp; 1666 { 1667 if ((cp = strdup(cp ? cp : ""))) 1668 return(cp); 1669 syslog(LOG_ERR, "strdup: %m"); 1670 exit(1); 1671 } 1672 1673 struct servtab * 1674 dupconfig(sep) 1675 struct servtab *sep; 1676 { 1677 struct servtab *newtab; 1678 int argc; 1679 1680 newtab = (struct servtab *) malloc(sizeof(struct servtab)); 1681 1682 if (newtab == NULL) { 1683 syslog(LOG_ERR, "malloc: %m"); 1684 exit(1); 1685 } 1686 1687 memset((char *)newtab, 0, sizeof(struct servtab)); 1688 1689 newtab->se_service = sep->se_service ? newstr(sep->se_service) : NULL; 1690 newtab->se_socktype = sep->se_socktype; 1691 newtab->se_family = sep->se_family; 1692 newtab->se_proto = sep->se_proto ? newstr(sep->se_proto) : NULL; 1693 newtab->se_rpcprog = sep->se_rpcprog; 1694 newtab->se_rpcversl = sep->se_rpcversl; 1695 newtab->se_rpcversh = sep->se_rpcversh; 1696 newtab->se_wait = sep->se_wait; 1697 newtab->se_user = sep->se_user ? newstr(sep->se_user) : NULL; 1698 newtab->se_group = sep->se_group ? newstr(sep->se_group) : NULL; 1699 newtab->se_bi = sep->se_bi; 1700 newtab->se_server = sep->se_server ? newstr(sep->se_server) : 0; 1701 1702 for (argc = 0; argc <= MAXARGV; argc++) 1703 newtab->se_argv[argc] = sep->se_argv[argc] ? 1704 newstr(sep->se_argv[argc]) : NULL; 1705 newtab->se_max = sep->se_max; 1706 1707 return (newtab); 1708 } 1709 1710 void 1711 inetd_setproctitle(a, s) 1712 char *a; 1713 int s; 1714 { 1715 int size; 1716 register char *cp; 1717 struct sockaddr_in sin; 1718 char buf[80]; 1719 1720 cp = Argv[0]; 1721 size = sizeof(sin); 1722 (void) snprintf(buf, sizeof buf, "-%s", a); 1723 if (getpeername(s, (struct sockaddr *)&sin, &size) == 0) { 1724 char *s = inet_ntoa(sin.sin_addr); 1725 1726 buf[sizeof(buf) - 1 - strlen(s) - 3] = '\0'; 1727 strcat(buf, " ["); 1728 strcat(buf, s); 1729 strcat(buf, "]"); 1730 } 1731 strncpy(cp, buf, LastArg - cp); 1732 cp += strlen(cp); 1733 while (cp < LastArg) 1734 *cp++ = ' '; 1735 } 1736 1737 void 1738 logpid() 1739 { 1740 FILE *fp; 1741 1742 if ((fp = fopen(_PATH_INETDPID, "w")) != NULL) { 1743 fprintf(fp, "%u\n", getpid()); 1744 (void)fclose(fp); 1745 } 1746 } 1747 1748 int 1749 bump_nofile() 1750 { 1751 #ifdef RLIMIT_NOFILE 1752 1753 #define FD_CHUNK 32 1754 1755 struct rlimit rl; 1756 1757 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1758 syslog(LOG_ERR, "getrlimit: %m"); 1759 return -1; 1760 } 1761 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK); 1762 rl.rlim_cur = MIN(FD_SETSIZE, rl.rlim_cur + FD_CHUNK); 1763 if (rl.rlim_cur <= rlim_ofile_cur) { 1764 syslog(LOG_ERR, 1765 "bump_nofile: cannot extend file limit, max = %d", 1766 (int)rl.rlim_cur); 1767 return -1; 1768 } 1769 1770 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { 1771 syslog(LOG_ERR, "setrlimit: %m"); 1772 return -1; 1773 } 1774 1775 rlim_ofile_cur = rl.rlim_cur; 1776 return 0; 1777 1778 #else 1779 syslog(LOG_ERR, "bump_nofile: cannot extend file limit"); 1780 return -1; 1781 #endif 1782 } 1783 1784 /* 1785 * Internet services provided internally by inetd: 1786 */ 1787 #define BUFSIZE 4096 1788 1789 /* ARGSUSED */ 1790 void 1791 echo_stream(s, sep) /* Echo service -- echo data back */ 1792 int s; 1793 struct servtab *sep; 1794 { 1795 char buffer[BUFSIZE]; 1796 int i; 1797 1798 inetd_setproctitle(sep->se_service, s); 1799 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1800 write(s, buffer, i) > 0) 1801 ; 1802 exit(0); 1803 } 1804 1805 /* ARGSUSED */ 1806 void 1807 echo_dg(s, sep) /* Echo service -- echo data back */ 1808 int s; 1809 struct servtab *sep; 1810 { 1811 char buffer[BUFSIZE]; 1812 int i, size; 1813 struct sockaddr_storage ss; 1814 1815 size = sizeof(ss); 1816 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, (struct sockaddr *)&ss, 1817 &size)) < 0) 1818 return; 1819 if (dg_badinput((struct sockaddr *)&ss)) 1820 return; 1821 (void) sendto(s, buffer, i, 0, (struct sockaddr *)&ss, size); 1822 } 1823 1824 /* ARGSUSED */ 1825 void 1826 discard_stream(s, sep) /* Discard service -- ignore data */ 1827 int s; 1828 struct servtab *sep; 1829 { 1830 char buffer[BUFSIZE]; 1831 1832 inetd_setproctitle(sep->se_service, s); 1833 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || 1834 errno == EINTR) 1835 ; 1836 exit(0); 1837 } 1838 1839 /* ARGSUSED */ 1840 void 1841 discard_dg(s, sep) /* Discard service -- ignore data */ 1842 int s; 1843 struct servtab *sep; 1844 { 1845 char buffer[BUFSIZE]; 1846 1847 (void) read(s, buffer, sizeof(buffer)); 1848 } 1849 1850 #include <ctype.h> 1851 #define LINESIZ 72 1852 char ring[128]; 1853 char *endring; 1854 1855 void 1856 initring() 1857 { 1858 register int i; 1859 1860 endring = ring; 1861 1862 for (i = 0; i <= 128; ++i) 1863 if (isprint(i)) 1864 *endring++ = i; 1865 } 1866 1867 /* ARGSUSED */ 1868 void 1869 chargen_stream(s, sep) /* Character generator */ 1870 int s; 1871 struct servtab *sep; 1872 { 1873 register char *rs; 1874 int len; 1875 char text[LINESIZ+2]; 1876 1877 inetd_setproctitle(sep->se_service, s); 1878 1879 if (!endring) { 1880 initring(); 1881 rs = ring; 1882 } 1883 1884 text[LINESIZ] = '\r'; 1885 text[LINESIZ + 1] = '\n'; 1886 for (rs = ring;;) { 1887 if ((len = endring - rs) >= LINESIZ) 1888 memmove(text, rs, LINESIZ); 1889 else { 1890 memmove(text, rs, len); 1891 memmove(text + len, ring, LINESIZ - len); 1892 } 1893 if (++rs == endring) 1894 rs = ring; 1895 if (write(s, text, sizeof(text)) != sizeof(text)) 1896 break; 1897 } 1898 exit(0); 1899 } 1900 1901 /* ARGSUSED */ 1902 void 1903 chargen_dg(s, sep) /* Character generator */ 1904 int s; 1905 struct servtab *sep; 1906 { 1907 struct sockaddr_storage ss; 1908 static char *rs; 1909 int len, size; 1910 char text[LINESIZ+2]; 1911 1912 if (endring == 0) { 1913 initring(); 1914 rs = ring; 1915 } 1916 1917 size = sizeof(ss); 1918 if (recvfrom(s, text, sizeof(text), 0, (struct sockaddr *)&ss, 1919 &size) < 0) 1920 return; 1921 if (dg_badinput((struct sockaddr *)&ss)) 1922 return; 1923 1924 if ((len = endring - rs) >= LINESIZ) 1925 memmove(text, rs, LINESIZ); 1926 else { 1927 memmove(text, rs, len); 1928 memmove(text + len, ring, LINESIZ - len); 1929 } 1930 if (++rs == endring) 1931 rs = ring; 1932 text[LINESIZ] = '\r'; 1933 text[LINESIZ + 1] = '\n'; 1934 (void) sendto(s, text, sizeof(text), 0, (struct sockaddr *)&ss, size); 1935 } 1936 1937 /* 1938 * Return a machine readable date and time, in the form of the 1939 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1940 * returns the number of seconds since midnight, Jan 1, 1970, 1941 * we must add 2208988800 seconds to this figure to make up for 1942 * some seventy years Bell Labs was asleep. 1943 */ 1944 1945 u_int 1946 machtime() 1947 { 1948 struct timeval tv; 1949 1950 if (gettimeofday(&tv, NULL) < 0) { 1951 fprintf(stderr, "Unable to get time of day\n"); 1952 return (0L); 1953 } 1954 return (htonl((u_int)tv.tv_sec + 2208988800UL)); 1955 } 1956 1957 /* ARGSUSED */ 1958 void 1959 machtime_stream(s, sep) 1960 int s; 1961 struct servtab *sep; 1962 { 1963 u_int result; 1964 1965 result = machtime(); 1966 (void) write(s, (char *) &result, sizeof(result)); 1967 } 1968 1969 /* ARGSUSED */ 1970 void 1971 machtime_dg(s, sep) 1972 int s; 1973 struct servtab *sep; 1974 { 1975 u_int result; 1976 struct sockaddr_storage ss; 1977 int size; 1978 1979 size = sizeof(ss); 1980 if (recvfrom(s, (char *)&result, sizeof(result), 0, 1981 (struct sockaddr *)&ss, &size) < 0) 1982 return; 1983 if (dg_badinput((struct sockaddr *)&ss)) 1984 return; 1985 result = machtime(); 1986 (void) sendto(s, (char *) &result, sizeof(result), 0, 1987 (struct sockaddr *)&ss, size); 1988 } 1989 1990 /* ARGSUSED */ 1991 void 1992 daytime_stream(s, sep) /* Return human-readable time of day */ 1993 int s; 1994 struct servtab *sep; 1995 { 1996 char buffer[256]; 1997 time_t time(), clock; 1998 1999 clock = time(NULL); 2000 2001 (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); 2002 (void) write(s, buffer, strlen(buffer)); 2003 } 2004 2005 /* ARGSUSED */ 2006 void 2007 daytime_dg(s, sep) /* Return human-readable time of day */ 2008 int s; 2009 struct servtab *sep; 2010 { 2011 char buffer[256]; 2012 time_t time(), clock; 2013 struct sockaddr_storage ss; 2014 int size; 2015 2016 clock = time((time_t *) 0); 2017 2018 size = sizeof(ss); 2019 if (recvfrom(s, buffer, sizeof(buffer), 0, (struct sockaddr *)&ss, 2020 &size) < 0) 2021 return; 2022 if (dg_badinput((struct sockaddr *)&ss)) 2023 return; 2024 (void) sprintf(buffer, "%.24s\r\n", ctime(&clock)); 2025 (void) sendto(s, buffer, strlen(buffer), 0, (struct sockaddr *)&ss, 2026 size); 2027 } 2028 2029 /* 2030 * print_service: 2031 * Dump relevant information to stderr 2032 */ 2033 void 2034 print_service(action, sep) 2035 char *action; 2036 struct servtab *sep; 2037 { 2038 if (strcmp(sep->se_hostaddr, "*") == 0) 2039 fprintf(stderr, "%s: %s ", action, sep->se_service); 2040 else 2041 fprintf(stderr, "%s: %s:%s ", action, sep->se_hostaddr, 2042 sep->se_service); 2043 2044 if (isrpcservice(sep)) 2045 fprintf(stderr, "rpcprog=%d, rpcvers=%d/%d, proto=%s,", 2046 sep->se_rpcprog, sep->se_rpcversh, 2047 sep->se_rpcversl, sep->se_proto); 2048 else 2049 fprintf(stderr, "proto=%s,", sep->se_proto); 2050 2051 fprintf(stderr, 2052 " wait.max=%hd.%d user:group=%s.%s builtin=%lx server=%s\n", 2053 sep->se_wait, sep->se_max, sep->se_user, 2054 sep->se_group ? sep->se_group : "wheel", 2055 (long)sep->se_bi, sep->se_server); 2056 } 2057