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