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