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