1 /* 2 * Copyright (c) 1983, 1991, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * @(#) Copyright (c) 1983, 1991, 1993, 1994 The Regents of the University of California. All rights reserved. 30 * @(#)from: inetd.c 8.4 (Berkeley) 4/13/94 31 * $FreeBSD: src/usr.sbin/inetd/inetd.c,v 1.80.2.11 2003/04/05 13:39:18 dwmalone Exp $ 32 */ 33 34 /* 35 * Inetd - Internet super-server 36 * 37 * This program invokes all internet services as needed. Connection-oriented 38 * services are invoked each time a connection is made, by creating a process. 39 * This process is passed the connection as file descriptor 0 and is expected 40 * to do a getpeername to find out the source host and port. 41 * 42 * Datagram oriented services are invoked when a datagram 43 * arrives; a process is created and passed a pending message 44 * on file descriptor 0. Datagram servers may either connect 45 * to their peer, freeing up the original socket for inetd 46 * to receive further messages on, or ``take over the socket'', 47 * processing all arriving datagrams and, eventually, timing 48 * out. The first type of server is said to be ``multi-threaded''; 49 * the second type of server ``single-threaded''. 50 * 51 * Inetd uses a configuration file which is read at startup 52 * and, possibly, at some later time in response to a hangup signal. 53 * The configuration file is ``free format'' with fields given in the 54 * order shown below. Continuation lines for an entry must begin with 55 * a space or tab. All fields must be present in each entry. 56 * 57 * service name must be in /etc/services 58 * or name a tcpmux service 59 * or specify a unix domain socket 60 * socket type stream/dgram/raw/rdm/seqpacket 61 * protocol tcp[4][6][/ttcp], udp[4][6], unix 62 * wait/nowait single-threaded/multi-threaded 63 * user user to run daemon as 64 * server program full path name 65 * server program arguments maximum of MAXARGS (20) 66 * 67 * TCP services without official port numbers are handled with the 68 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for 69 * requests. When a connection is made from a foreign host, the service 70 * requested is passed to tcpmux, which looks it up in the servtab list 71 * and returns the proper entry for the service. Tcpmux returns a 72 * negative reply if the service doesn't exist, otherwise the invoked 73 * server is expected to return the positive reply if the service type in 74 * inetd.conf file has the prefix "tcpmux/". If the service type has the 75 * prefix "tcpmux/+", tcpmux will return the positive reply for the 76 * process; this is for compatibility with older server code, and also 77 * allows you to invoke programs that use stdin/stdout without putting any 78 * special server code in them. Services that use tcpmux are "nowait" 79 * because they do not have a well-known port and hence cannot listen 80 * for new requests. 81 * 82 * For RPC services 83 * service name/version must be in /etc/rpc 84 * socket type stream/dgram/raw/rdm/seqpacket 85 * protocol rpc/tcp, rpc/udp 86 * wait/nowait single-threaded/multi-threaded 87 * user user to run daemon as 88 * server program full path name 89 * server program arguments maximum of MAXARGS 90 * 91 * Comment lines are indicated by a `#' in column 1. 92 */ 93 #include <sys/param.h> 94 #include <sys/ioctl.h> 95 #include <sys/wait.h> 96 #include <sys/time.h> 97 #include <sys/resource.h> 98 #include <sys/stat.h> 99 #include <sys/un.h> 100 101 #include <netinet/in.h> 102 #include <netinet/tcp.h> 103 #include <arpa/inet.h> 104 #include <rpc/rpc.h> 105 #include <rpc/pmap_clnt.h> 106 107 #include <errno.h> 108 #include <err.h> 109 #include <fcntl.h> 110 #include <grp.h> 111 #include <limits.h> 112 #include <netdb.h> 113 #include <pwd.h> 114 #include <signal.h> 115 #include <stdio.h> 116 #include <stdlib.h> 117 #include <string.h> 118 #include <syslog.h> 119 #include <tcpd.h> 120 #include <unistd.h> 121 #include <libutil.h> 122 #include <sysexits.h> 123 #include <ctype.h> 124 125 #include "inetd.h" 126 #include "pathnames.h" 127 128 /* wrapper for KAME-special getnameinfo() */ 129 #ifndef NI_WITHSCOPEID 130 #define NI_WITHSCOPEID 0 131 #endif 132 133 #ifndef LIBWRAP_ALLOW_FACILITY 134 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH 135 #endif 136 #ifndef LIBWRAP_ALLOW_SEVERITY 137 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO 138 #endif 139 #ifndef LIBWRAP_DENY_FACILITY 140 # define LIBWRAP_DENY_FACILITY LOG_AUTH 141 #endif 142 #ifndef LIBWRAP_DENY_SEVERITY 143 # define LIBWRAP_DENY_SEVERITY LOG_WARNING 144 #endif 145 146 #define ISWRAP(sep) \ 147 ( ((wrap_ex && !(sep)->se_bi) || (wrap_bi && (sep)->se_bi)) \ 148 && (sep->se_family == AF_INET || sep->se_family == AF_INET6) \ 149 && ( ((sep)->se_accept && (sep)->se_socktype == SOCK_STREAM) \ 150 || (sep)->se_socktype == SOCK_DGRAM)) 151 152 #ifdef LOGIN_CAP 153 #include <login_cap.h> 154 155 /* see init.c */ 156 #define RESOURCE_RC "daemon" 157 158 #endif 159 160 #ifndef MAXCHILD 161 #define MAXCHILD -1 /* maximum number of this service 162 < 0 = no limit */ 163 #endif 164 165 #ifndef MAXCPM 166 #define MAXCPM -1 /* rate limit invocations from a 167 single remote address, 168 < 0 = no limit */ 169 #endif 170 171 #ifndef MAXPERIP 172 #define MAXPERIP -1 /* maximum number of this service 173 from a single remote address, 174 < 0 = no limit */ 175 #endif 176 177 #ifndef TOOMANY 178 #define TOOMANY 256 /* don't start more than TOOMANY */ 179 #endif 180 #define CNT_INTVL 60 /* servers in CNT_INTVL sec. */ 181 #define RETRYTIME (60*10) /* retry after bind or server fail */ 182 #define MAX_MAXCHLD 32767 /* max allowable max children */ 183 184 #define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM)) 185 186 void close_sep(struct servtab *); 187 void flag_signal(int); 188 void flag_config(int); 189 void config(void); 190 int cpmip(const struct servtab *, int); 191 void endconfig(void); 192 struct servtab *enter(struct servtab *); 193 void freeconfig(struct servtab *); 194 struct servtab *getconfigent(void); 195 int matchservent(const char *, const char *, const char *); 196 char *nextline(FILE *); 197 void addchild(struct servtab *, int); 198 void flag_reapchild(int); 199 void reapchild(void); 200 void enable(struct servtab *); 201 void disable(struct servtab *); 202 void flag_retry(int); 203 void retry(void); 204 int setconfig(void); 205 void setup(struct servtab *); 206 void unregisterrpc(struct servtab *sep); 207 static struct conninfo *search_conn(struct servtab *sep, int ctrl); 208 static int room_conn(struct servtab *sep, struct conninfo *conn); 209 static void addchild_conn(struct conninfo *conn, pid_t pid); 210 static void reapchild_conn(pid_t pid); 211 static void free_conn(struct conninfo *conn); 212 static void resize_conn(struct servtab *sep, int maxperip); 213 static void free_connlist(struct servtab *sep); 214 static void free_proc(struct procinfo *); 215 static struct procinfo *search_proc(pid_t pid, int add); 216 static int hashval(char *p, int len); 217 218 int allow_severity; 219 int deny_severity; 220 int wrap_ex = 0; 221 int wrap_bi = 0; 222 int debug = 0; 223 int dolog = 0; 224 int maxsock; /* highest-numbered descriptor */ 225 fd_set allsock; 226 int options; 227 int timingout; 228 int toomany = TOOMANY; 229 int maxchild = MAXCHILD; 230 int maxcpm = MAXCPM; 231 int maxperip = MAXPERIP; 232 struct servent *sp; 233 struct rpcent *rpc; 234 char *hostname = NULL; 235 struct sockaddr_in *bind_sa4; 236 int no_v4bind = 1; 237 #ifdef INET6 238 struct sockaddr_in6 *bind_sa6; 239 int no_v6bind = 1; 240 #endif 241 int signalpipe[2]; 242 #ifdef SANITY_CHECK 243 int nsock; 244 #endif 245 uid_t euid; 246 gid_t egid; 247 mode_t mask; 248 249 struct servtab *servtab; 250 251 extern struct biltin biltins[]; 252 253 #define NUMINT (sizeof(intab) / sizeof(struct inent)) 254 const char *CONFIG = _PATH_INETDCONF; 255 const char *pid_file = _PATH_INETDPID; 256 257 static LIST_HEAD(, procinfo) proctable[PERIPSIZE]; 258 259 int 260 getvalue(const char *arg, int *value, const char *whine) 261 { 262 int tmp; 263 char *p; 264 265 tmp = strtol(arg, &p, 0); 266 if (tmp < 0 || *p) { 267 syslog(LOG_ERR, whine, arg); 268 return 1; /* failure */ 269 } 270 *value = tmp; 271 return 0; /* success */ 272 } 273 274 static sa_family_t 275 whichaf(struct request_info *req) 276 { 277 struct sockaddr *sa; 278 279 sa = (struct sockaddr *)req->client->sin; 280 if (sa == NULL) 281 return AF_UNSPEC; 282 if (sa->sa_family == AF_INET6 && 283 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr)) 284 return AF_INET; 285 return sa->sa_family; 286 } 287 288 int 289 main(int argc, char **argv) 290 { 291 struct servtab *sep; 292 struct passwd *pwd; 293 struct group *grp; 294 struct sigaction sa, saalrm, sachld, sahup, sapipe; 295 int ch, dofork; 296 pid_t pid; 297 char buf[50]; 298 #ifdef LOGIN_CAP 299 login_cap_t *lc = NULL; 300 #endif 301 struct request_info req; 302 int denied; 303 char *service = NULL; 304 union { 305 struct sockaddr peer_un; 306 struct sockaddr_in peer_un4; 307 struct sockaddr_in6 peer_un6; 308 struct sockaddr_storage peer_max; 309 } p_un; 310 #define peer p_un.peer_un 311 #define peer4 p_un.peer_un4 312 #define peer6 p_un.peer_un6 313 #define peermax p_un.peer_max 314 int i; 315 struct addrinfo hints, *res; 316 const char *servname; 317 int error; 318 struct conninfo *conn; 319 320 openlog("inetd", LOG_PID | LOG_NOWAIT | LOG_PERROR, LOG_DAEMON); 321 322 while ((ch = getopt(argc, argv, "dlwWR:a:c:C:p:s:")) != -1) 323 switch(ch) { 324 case 'd': 325 debug = 1; 326 options |= SO_DEBUG; 327 break; 328 case 'l': 329 dolog = 1; 330 break; 331 case 'R': 332 getvalue(optarg, &toomany, 333 "-R %s: bad value for service invocation rate"); 334 break; 335 case 'c': 336 getvalue(optarg, &maxchild, 337 "-c %s: bad value for maximum children"); 338 break; 339 case 'C': 340 getvalue(optarg, &maxcpm, 341 "-C %s: bad value for maximum children/minute"); 342 break; 343 case 'a': 344 hostname = optarg; 345 break; 346 case 'p': 347 pid_file = optarg; 348 break; 349 case 's': 350 getvalue(optarg, &maxperip, 351 "-s %s: bad value for maximum children per source address"); 352 break; 353 case 'w': 354 wrap_ex++; 355 break; 356 case 'W': 357 wrap_bi++; 358 break; 359 case '?': 360 default: 361 syslog(LOG_ERR, 362 "usage: inetd [-dlwW] [-a address] [-R rate]" 363 " [-c maximum] [-C rate]" 364 " [-p pidfile] [conf-file]"); 365 exit(EX_USAGE); 366 } 367 /* 368 * Initialize Bind Addrs. 369 * When hostname is NULL, wild card bind addrs are obtained from 370 * getaddrinfo(). But getaddrinfo() requires at least one of 371 * hostname or servname is non NULL. 372 * So when hostname is NULL, set dummy value to servname. 373 */ 374 servname = (hostname == NULL) ? "discard" /* dummy */ : NULL; 375 376 bzero(&hints, sizeof(struct addrinfo)); 377 hints.ai_flags = AI_PASSIVE; 378 hints.ai_family = AF_UNSPEC; 379 error = getaddrinfo(hostname, servname, &hints, &res); 380 if (error != 0) { 381 syslog(LOG_ERR, "-a %s: %s", hostname, gai_strerror(error)); 382 if (error == EAI_SYSTEM) 383 syslog(LOG_ERR, "%s", strerror(errno)); 384 exit(EX_USAGE); 385 } 386 do { 387 if (res->ai_addr == NULL) { 388 syslog(LOG_ERR, "-a %s: getaddrinfo failed", hostname); 389 exit(EX_USAGE); 390 } 391 switch (res->ai_addr->sa_family) { 392 case AF_INET: 393 if (no_v4bind == 0) 394 continue; 395 bind_sa4 = (struct sockaddr_in *)res->ai_addr; 396 /* init port num in case servname is dummy */ 397 bind_sa4->sin_port = 0; 398 no_v4bind = 0; 399 continue; 400 #ifdef INET6 401 case AF_INET6: 402 if (no_v6bind == 0) 403 continue; 404 bind_sa6 = (struct sockaddr_in6 *)res->ai_addr; 405 /* init port num in case servname is dummy */ 406 bind_sa6->sin6_port = 0; 407 no_v6bind = 0; 408 continue; 409 #endif 410 } 411 if (no_v4bind == 0 412 #ifdef INET6 413 && no_v6bind == 0 414 #endif 415 ) 416 break; 417 } while ((res = res->ai_next) != NULL); 418 if (no_v4bind != 0 419 #ifdef INET6 420 && no_v6bind != 0 421 #endif 422 ) { 423 syslog(LOG_ERR, "-a %s: unknown address family", hostname); 424 exit(EX_USAGE); 425 } 426 427 euid = geteuid(); 428 egid = getegid(); 429 umask(mask = umask(0777)); 430 431 argc -= optind; 432 argv += optind; 433 434 if (argc > 0) 435 CONFIG = argv[0]; 436 if (debug == 0) { 437 FILE *fp; 438 if (daemon(0, 0) < 0) { 439 syslog(LOG_WARNING, "daemon(0,0) failed: %m"); 440 } 441 /* From now on we don't want syslog messages going to stderr. */ 442 closelog(); 443 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); 444 /* 445 * In case somebody has started inetd manually, we need to 446 * clear the logname, so that old servers run as root do not 447 * get the user's logname.. 448 */ 449 if (setlogin("") < 0) { 450 syslog(LOG_WARNING, "cannot clear logname: %m"); 451 /* no big deal if it fails.. */ 452 } 453 pid = getpid(); 454 fp = fopen(pid_file, "w"); 455 if (fp) { 456 fprintf(fp, "%ld\n", (long)pid); 457 fclose(fp); 458 } else { 459 syslog(LOG_WARNING, "%s: %m", pid_file); 460 } 461 } 462 for (i = 0; i < PERIPSIZE; ++i) 463 LIST_INIT(&proctable[i]); 464 sa.sa_flags = 0; 465 sigemptyset(&sa.sa_mask); 466 sigaddset(&sa.sa_mask, SIGALRM); 467 sigaddset(&sa.sa_mask, SIGCHLD); 468 sigaddset(&sa.sa_mask, SIGHUP); 469 sa.sa_handler = flag_retry; 470 sigaction(SIGALRM, &sa, &saalrm); 471 config(); 472 sa.sa_handler = flag_config; 473 sigaction(SIGHUP, &sa, &sahup); 474 sa.sa_handler = flag_reapchild; 475 sigaction(SIGCHLD, &sa, &sachld); 476 sa.sa_handler = SIG_IGN; 477 sigaction(SIGPIPE, &sa, &sapipe); 478 479 { 480 /* space for daemons to overwrite environment for ps */ 481 #define DUMMYSIZE 100 482 char dummy[DUMMYSIZE]; 483 484 memset(dummy, 'x', DUMMYSIZE - 1); 485 dummy[DUMMYSIZE - 1] = '\0'; 486 if (setenv("inetd_dummy", dummy, 1) == -1) 487 syslog(LOG_WARNING, "setenv: cannot set inetd_dummy=%s: %m", dummy); 488 489 } 490 491 if (pipe2(signalpipe, O_CLOEXEC) != 0) { 492 syslog(LOG_ERR, "pipe2 (O_CLOEXEC): %m"); 493 exit(EX_OSERR); 494 } 495 FD_SET(signalpipe[0], &allsock); 496 #ifdef SANITY_CHECK 497 nsock++; 498 #endif 499 if (signalpipe[0] > maxsock) 500 maxsock = signalpipe[0]; 501 if (signalpipe[1] > maxsock) 502 maxsock = signalpipe[1]; 503 504 for (;;) { 505 int n, ctrl; 506 fd_set readable; 507 508 #ifdef SANITY_CHECK 509 if (nsock == 0) { 510 syslog(LOG_ERR, "%s: nsock=0", __func__); 511 exit(EX_SOFTWARE); 512 } 513 #endif 514 readable = allsock; 515 if ((n = select(maxsock + 1, &readable, NULL, NULL, NULL)) <= 0) { 516 if (n < 0 && errno != EINTR) { 517 syslog(LOG_WARNING, "select: %m"); 518 sleep(1); 519 } 520 continue; 521 } 522 /* handle any queued signal flags */ 523 if (FD_ISSET(signalpipe[0], &readable)) { 524 int nsig; 525 if (ioctl(signalpipe[0], FIONREAD, &nsig) != 0) { 526 syslog(LOG_ERR, "ioctl: %m"); 527 exit(EX_OSERR); 528 } 529 while (--nsig >= 0) { 530 char c; 531 if (read(signalpipe[0], &c, 1) != 1) { 532 syslog(LOG_ERR, "read: %m"); 533 exit(EX_OSERR); 534 } 535 if (debug) 536 warnx("handling signal flag %c", c); 537 switch(c) { 538 case 'A': /* sigalrm */ 539 retry(); 540 break; 541 case 'C': /* sigchld */ 542 reapchild(); 543 break; 544 case 'H': /* sighup */ 545 config(); 546 break; 547 } 548 } 549 } 550 for (sep = servtab; n && sep; sep = sep->se_next) 551 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) { 552 n--; 553 if (debug) 554 warnx("someone wants %s", sep->se_service); 555 dofork = !sep->se_bi || sep->se_bi->bi_fork || ISWRAP(sep); 556 conn = NULL; 557 if (sep->se_accept && sep->se_socktype == SOCK_STREAM) { 558 i = 1; 559 if (ioctl(sep->se_fd, FIONBIO, &i) < 0) 560 syslog(LOG_ERR, "ioctl (FIONBIO, 1): %m"); 561 ctrl = accept(sep->se_fd, NULL, NULL); 562 if (debug) 563 warnx("accept, ctrl %d", ctrl); 564 if (ctrl < 0) { 565 if (errno != EINTR) 566 syslog(LOG_WARNING, 567 "accept (for %s): %m", 568 sep->se_service); 569 if (sep->se_accept && 570 sep->se_socktype == SOCK_STREAM) 571 close(ctrl); 572 continue; 573 } 574 i = 0; 575 if (ioctl(sep->se_fd, FIONBIO, &i) < 0) 576 syslog(LOG_ERR, "ioctl1(FIONBIO, 0): %m"); 577 if (ioctl(ctrl, FIONBIO, &i) < 0) 578 syslog(LOG_ERR, "ioctl2(FIONBIO, 0): %m"); 579 if (cpmip(sep, ctrl) < 0) { 580 close(ctrl); 581 continue; 582 } 583 if (dofork && 584 (conn = search_conn(sep, ctrl)) != NULL && 585 !room_conn(sep, conn)) { 586 close(ctrl); 587 continue; 588 } 589 } else 590 ctrl = sep->se_fd; 591 if (dolog && !ISWRAP(sep)) { 592 char pname[INET6_ADDRSTRLEN] = "unknown"; 593 socklen_t sl; 594 sl = sizeof peermax; 595 if (getpeername(ctrl, (struct sockaddr *) 596 &peermax, &sl)) { 597 sl = sizeof peermax; 598 if (recvfrom(ctrl, buf, sizeof(buf), 599 MSG_PEEK, 600 (struct sockaddr *)&peermax, 601 &sl) >= 0) { 602 getnameinfo((struct sockaddr *)&peermax, 603 peer.sa_len, 604 pname, sizeof(pname), 605 NULL, 0, 606 NI_NUMERICHOST| 607 NI_WITHSCOPEID); 608 } 609 } else { 610 getnameinfo((struct sockaddr *)&peermax, 611 peer.sa_len, 612 pname, sizeof(pname), 613 NULL, 0, 614 NI_NUMERICHOST| 615 NI_WITHSCOPEID); 616 } 617 syslog(LOG_INFO,"%s from %s", sep->se_service, pname); 618 } 619 sigblock(SIGBLOCK); 620 pid = 0; 621 /* 622 * Fork for all external services, builtins which need to 623 * fork and anything we're wrapping (as wrapping might 624 * block or use hosts_options(5) twist). 625 */ 626 if (dofork) { 627 if (sep->se_count++ == 0) 628 gettimeofday(&sep->se_time, NULL); 629 else if (toomany > 0 && sep->se_count >= toomany) { 630 struct timeval now; 631 632 gettimeofday(&now, NULL); 633 if (now.tv_sec - sep->se_time.tv_sec > 634 CNT_INTVL) { 635 sep->se_time = now; 636 sep->se_count = 1; 637 } else { 638 syslog(LOG_ERR, 639 "%s/%s server failing (looping), service terminated", 640 sep->se_service, sep->se_proto); 641 if (sep->se_accept && 642 sep->se_socktype == SOCK_STREAM) 643 close(ctrl); 644 close_sep(sep); 645 free_conn(conn); 646 sigsetmask(0L); 647 if (!timingout) { 648 timingout = 1; 649 alarm(RETRYTIME); 650 } 651 continue; 652 } 653 } 654 pid = fork(); 655 } 656 if (pid < 0) { 657 syslog(LOG_ERR, "fork: %m"); 658 if (sep->se_accept && 659 sep->se_socktype == SOCK_STREAM) 660 close(ctrl); 661 free_conn(conn); 662 sigsetmask(0L); 663 sleep(1); 664 continue; 665 } 666 if (pid) { 667 addchild_conn(conn, pid); 668 addchild(sep, pid); 669 } 670 sigsetmask(0L); 671 if (pid == 0) { 672 if (dofork) { 673 sigaction(SIGALRM, &saalrm, NULL); 674 sigaction(SIGCHLD, &sachld, NULL); 675 sigaction(SIGHUP, &sahup, NULL); 676 /* SIGPIPE reset before exec */ 677 } 678 /* 679 * Call tcpmux to find the real service to exec. 680 */ 681 if (sep->se_bi && 682 sep->se_bi->bi_fn == (bi_fn_t *) tcpmux) { 683 sep = tcpmux(ctrl); 684 if (sep == NULL) { 685 close(ctrl); 686 _exit(0); 687 } 688 } 689 if (ISWRAP(sep)) { 690 inetd_setproctitle("wrapping", ctrl); 691 service = sep->se_server_name ? 692 sep->se_server_name : sep->se_service; 693 request_init(&req, RQ_DAEMON, service, RQ_FILE, ctrl, NULL); 694 fromhost(&req); 695 deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY; 696 allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY; 697 denied = !hosts_access(&req); 698 if (denied) { 699 syslog(deny_severity, 700 "refused connection from %.500s, service %s (%s%s)", 701 eval_client(&req), service, sep->se_proto, 702 (whichaf(&req) == AF_INET6) ? "6" : ""); 703 if (sep->se_socktype != SOCK_STREAM) 704 recv(ctrl, buf, sizeof (buf), 0); 705 if (dofork) { 706 sleep(1); 707 _exit(0); 708 } 709 } 710 if (dolog) { 711 syslog(allow_severity, 712 "connection from %.500s, service %s (%s%s)", 713 eval_client(&req), service, sep->se_proto, 714 (whichaf(&req) == AF_INET6) ? "6" : ""); 715 } 716 } 717 if (sep->se_bi) { 718 (*sep->se_bi->bi_fn)(ctrl, sep); 719 } else { 720 if (debug) 721 warnx("%d execl %s", 722 getpid(), sep->se_server); 723 /* Clear close-on-exec. */ 724 if (fcntl(ctrl, F_SETFD, 0) < 0) { 725 syslog(LOG_ERR, 726 "%s/%s: fcntl (F_SETFD, 0): %m", 727 sep->se_service, sep->se_proto); 728 _exit(EX_OSERR); 729 } 730 if (ctrl != 0) { 731 dup2(ctrl, 0); 732 close(ctrl); 733 } 734 dup2(0, 1); 735 dup2(0, 2); 736 if ((pwd = getpwnam(sep->se_user)) == NULL) { 737 syslog(LOG_ERR, 738 "%s/%s: %s: no such user", 739 sep->se_service, sep->se_proto, 740 sep->se_user); 741 if (sep->se_socktype != SOCK_STREAM) 742 recv(0, buf, sizeof (buf), 0); 743 _exit(EX_NOUSER); 744 } 745 grp = NULL; 746 if ( sep->se_group != NULL 747 && (grp = getgrnam(sep->se_group)) == NULL 748 ) { 749 syslog(LOG_ERR, 750 "%s/%s: %s: no such group", 751 sep->se_service, sep->se_proto, 752 sep->se_group); 753 if (sep->se_socktype != SOCK_STREAM) 754 recv(0, buf, sizeof (buf), 0); 755 _exit(EX_NOUSER); 756 } 757 if (grp != NULL) 758 pwd->pw_gid = grp->gr_gid; 759 #ifdef LOGIN_CAP 760 if ((lc = login_getclass(sep->se_class)) == NULL) { 761 /* error syslogged by getclass */ 762 syslog(LOG_ERR, 763 "%s/%s: %s: login class error", 764 sep->se_service, sep->se_proto, 765 sep->se_class); 766 if (sep->se_socktype != SOCK_STREAM) 767 recv(0, buf, sizeof (buf), 0); 768 _exit(EX_NOUSER); 769 } 770 #endif 771 if (setsid() < 0) { 772 syslog(LOG_ERR, 773 "%s: can't setsid(): %m", 774 sep->se_service); 775 /* _exit(EX_OSERR); not fatal yet */ 776 } 777 #ifdef LOGIN_CAP 778 if (setusercontext(lc, pwd, pwd->pw_uid, 779 LOGIN_SETALL) != 0) { 780 syslog(LOG_ERR, 781 "%s: can't setusercontext(..%s..): %m", 782 sep->se_service, sep->se_user); 783 _exit(EX_OSERR); 784 } 785 login_close(lc); 786 #else 787 if (pwd->pw_uid) { 788 if (setlogin(sep->se_user) < 0) { 789 syslog(LOG_ERR, 790 "%s: can't setlogin(%s): %m", 791 sep->se_service, sep->se_user); 792 /* _exit(EX_OSERR); not yet */ 793 } 794 if (setgid(pwd->pw_gid) < 0) { 795 syslog(LOG_ERR, 796 "%s: can't set gid %d: %m", 797 sep->se_service, pwd->pw_gid); 798 _exit(EX_OSERR); 799 } 800 initgroups(pwd->pw_name, 801 pwd->pw_gid); 802 if (setuid(pwd->pw_uid) < 0) { 803 syslog(LOG_ERR, 804 "%s: can't set uid %d: %m", 805 sep->se_service, pwd->pw_uid); 806 _exit(EX_OSERR); 807 } 808 } 809 #endif 810 sigaction(SIGPIPE, &sapipe, NULL); 811 execv(sep->se_server, sep->se_argv); 812 syslog(LOG_ERR, 813 "cannot execute %s: %m", sep->se_server); 814 if (sep->se_socktype != SOCK_STREAM) 815 recv(0, buf, sizeof (buf), 0); 816 } 817 if (dofork) 818 _exit(0); 819 } 820 if (sep->se_accept && sep->se_socktype == SOCK_STREAM) 821 close(ctrl); 822 } 823 } 824 } 825 826 /* 827 * Add a signal flag to the signal flag queue for later handling 828 */ 829 830 void 831 flag_signal(int c) 832 { 833 char ch = c; 834 835 if (write(signalpipe[1], &ch, 1) != 1) { 836 syslog(LOG_ERR, "write: %m"); 837 _exit(EX_OSERR); 838 } 839 } 840 841 /* 842 * Record a new child pid for this service. If we've reached the 843 * limit on children, then stop accepting incoming requests. 844 */ 845 846 void 847 addchild(struct servtab *sep, pid_t pid) 848 { 849 if (sep->se_maxchild <= 0) 850 return; 851 #ifdef SANITY_CHECK 852 if (sep->se_numchild >= sep->se_maxchild) { 853 syslog(LOG_ERR, "%s: %d >= %d", 854 __func__, sep->se_numchild, sep->se_maxchild); 855 exit(EX_SOFTWARE); 856 } 857 #endif 858 sep->se_pids[sep->se_numchild++] = pid; 859 if (sep->se_numchild == sep->se_maxchild) 860 disable(sep); 861 } 862 863 /* 864 * Some child process has exited. See if it's on somebody's list. 865 */ 866 867 void 868 flag_reapchild(int signo __unused) 869 { 870 flag_signal('C'); 871 } 872 873 void 874 reapchild(void) 875 { 876 int k, status; 877 pid_t pid; 878 struct servtab *sep; 879 880 for (;;) { 881 pid = wait3(&status, WNOHANG, NULL); 882 if (pid <= 0) 883 break; 884 if (debug) 885 warnx("%d reaped, %s %u", pid, 886 WIFEXITED(status) ? "status" : "signal", 887 WIFEXITED(status) ? WEXITSTATUS(status) 888 : WTERMSIG(status)); 889 for (sep = servtab; sep; sep = sep->se_next) { 890 for (k = 0; k < sep->se_numchild; k++) 891 if (sep->se_pids[k] == pid) 892 break; 893 if (k == sep->se_numchild) 894 continue; 895 if (sep->se_numchild == sep->se_maxchild) 896 enable(sep); 897 sep->se_pids[k] = sep->se_pids[--sep->se_numchild]; 898 if (WIFSIGNALED(status) || WEXITSTATUS(status)) 899 syslog(LOG_WARNING, 900 "%s[%d]: exited, %s %u", 901 sep->se_server, pid, 902 WIFEXITED(status) ? "status" : "signal", 903 WIFEXITED(status) ? WEXITSTATUS(status) 904 : WTERMSIG(status)); 905 break; 906 } 907 reapchild_conn(pid); 908 } 909 } 910 911 void 912 flag_config(int signo __unused) 913 { 914 flag_signal('H'); 915 } 916 917 void 918 config(void) 919 { 920 struct servtab *sep, *new, **sepp; 921 long omask; 922 #ifdef LOGIN_CAP 923 login_cap_t *lc = NULL; 924 #endif 925 926 927 if (!setconfig()) { 928 syslog(LOG_ERR, "%s: %m", CONFIG); 929 return; 930 } 931 for (sep = servtab; sep; sep = sep->se_next) 932 sep->se_checked = 0; 933 while ((new = getconfigent())) { 934 if (getpwnam(new->se_user) == NULL) { 935 syslog(LOG_ERR, 936 "%s/%s: no such user '%s', service ignored", 937 new->se_service, new->se_proto, new->se_user); 938 continue; 939 } 940 if (new->se_group && getgrnam(new->se_group) == NULL) { 941 syslog(LOG_ERR, 942 "%s/%s: no such group '%s', service ignored", 943 new->se_service, new->se_proto, new->se_group); 944 continue; 945 } 946 #ifdef LOGIN_CAP 947 if ((lc = login_getclass(new->se_class)) == NULL) { 948 /* error syslogged by getclass */ 949 syslog(LOG_ERR, 950 "%s/%s: %s: login class error, service ignored", 951 new->se_service, new->se_proto, new->se_class); 952 continue; 953 } 954 login_close(lc); 955 #endif 956 for (sep = servtab; sep; sep = sep->se_next) 957 if (strcmp(sep->se_service, new->se_service) == 0 && 958 strcmp(sep->se_proto, new->se_proto) == 0 && 959 sep->se_socktype == new->se_socktype && 960 sep->se_family == new->se_family) 961 break; 962 if (sep != NULL) { 963 int i; 964 965 #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; } 966 omask = sigblock(SIGBLOCK); 967 if (sep->se_nomapped != new->se_nomapped) { 968 sep->se_nomapped = new->se_nomapped; 969 sep->se_reset = 1; 970 } 971 /* copy over outstanding child pids */ 972 if (sep->se_maxchild > 0 && new->se_maxchild > 0) { 973 new->se_numchild = sep->se_numchild; 974 if (new->se_numchild > new->se_maxchild) 975 new->se_numchild = new->se_maxchild; 976 memcpy(new->se_pids, sep->se_pids, 977 new->se_numchild * sizeof(*new->se_pids)); 978 } 979 SWAP(sep->se_pids, new->se_pids); 980 sep->se_maxchild = new->se_maxchild; 981 sep->se_numchild = new->se_numchild; 982 sep->se_maxcpm = new->se_maxcpm; 983 resize_conn(sep, new->se_maxperip); 984 sep->se_maxperip = new->se_maxperip; 985 sep->se_bi = new->se_bi; 986 /* might need to turn on or off service now */ 987 if (sep->se_fd >= 0) { 988 if (sep->se_maxchild > 0 989 && sep->se_numchild == sep->se_maxchild) { 990 if (FD_ISSET(sep->se_fd, &allsock)) 991 disable(sep); 992 } else { 993 if (!FD_ISSET(sep->se_fd, &allsock)) 994 enable(sep); 995 } 996 } 997 sep->se_accept = new->se_accept; 998 SWAP(sep->se_user, new->se_user); 999 SWAP(sep->se_group, new->se_group); 1000 #ifdef LOGIN_CAP 1001 SWAP(sep->se_class, new->se_class); 1002 #endif 1003 SWAP(sep->se_server, new->se_server); 1004 SWAP(sep->se_server_name, new->se_server_name); 1005 for (i = 0; i < MAXARGV; i++) 1006 SWAP(sep->se_argv[i], new->se_argv[i]); 1007 sigsetmask(omask); 1008 freeconfig(new); 1009 if (debug) 1010 print_service("REDO", sep); 1011 } else { 1012 sep = enter(new); 1013 if (debug) 1014 print_service("ADD ", sep); 1015 } 1016 sep->se_checked = 1; 1017 if (ISMUX(sep)) { 1018 sep->se_fd = -1; 1019 continue; 1020 } 1021 switch (sep->se_family) { 1022 case AF_INET: 1023 if (no_v4bind != 0) { 1024 sep->se_fd = -1; 1025 continue; 1026 } 1027 break; 1028 #ifdef INET6 1029 case AF_INET6: 1030 if (no_v6bind != 0) { 1031 sep->se_fd = -1; 1032 continue; 1033 } 1034 break; 1035 #endif 1036 } 1037 if (!sep->se_rpc) { 1038 if (sep->se_family != AF_UNIX) { 1039 sp = getservbyname(sep->se_service, sep->se_proto); 1040 if (sp == NULL) { 1041 syslog(LOG_ERR, "%s/%s: unknown service", 1042 sep->se_service, sep->se_proto); 1043 sep->se_checked = 0; 1044 continue; 1045 } 1046 } 1047 switch (sep->se_family) { 1048 case AF_INET: 1049 if (sp->s_port != sep->se_ctrladdr4.sin_port) { 1050 sep->se_ctrladdr4.sin_port = 1051 sp->s_port; 1052 sep->se_reset = 1; 1053 } 1054 break; 1055 #ifdef INET6 1056 case AF_INET6: 1057 if (sp->s_port != 1058 sep->se_ctrladdr6.sin6_port) { 1059 sep->se_ctrladdr6.sin6_port = 1060 sp->s_port; 1061 sep->se_reset = 1; 1062 } 1063 break; 1064 #endif 1065 } 1066 if (sep->se_reset != 0 && sep->se_fd >= 0) 1067 close_sep(sep); 1068 } else { 1069 rpc = getrpcbyname(sep->se_service); 1070 if (rpc == NULL) { 1071 syslog(LOG_ERR, "%s/%s unknown RPC service", 1072 sep->se_service, sep->se_proto); 1073 if (sep->se_fd != -1) 1074 close(sep->se_fd); 1075 sep->se_fd = -1; 1076 continue; 1077 } 1078 if (rpc->r_number != sep->se_rpc_prog) { 1079 if (sep->se_rpc_prog) 1080 unregisterrpc(sep); 1081 sep->se_rpc_prog = rpc->r_number; 1082 if (sep->se_fd != -1) 1083 close(sep->se_fd); 1084 sep->se_fd = -1; 1085 } 1086 } 1087 if (sep->se_fd == -1) 1088 setup(sep); 1089 } 1090 endconfig(); 1091 /* 1092 * Purge anything not looked at above. 1093 */ 1094 omask = sigblock(SIGBLOCK); 1095 sepp = &servtab; 1096 while ((sep = *sepp)) { 1097 if (sep->se_checked) { 1098 sepp = &sep->se_next; 1099 continue; 1100 } 1101 *sepp = sep->se_next; 1102 if (sep->se_fd >= 0) 1103 close_sep(sep); 1104 if (debug) 1105 print_service("FREE", sep); 1106 if (sep->se_rpc && sep->se_rpc_prog > 0) 1107 unregisterrpc(sep); 1108 freeconfig(sep); 1109 free(sep); 1110 } 1111 sigsetmask(omask); 1112 } 1113 1114 void 1115 unregisterrpc(struct servtab *sep) 1116 { 1117 u_int i; 1118 struct servtab *sepp; 1119 long omask; 1120 1121 omask = sigblock(SIGBLOCK); 1122 for (sepp = servtab; sepp; sepp = sepp->se_next) { 1123 if (sepp == sep) 1124 continue; 1125 if (sep->se_checked == 0 || 1126 !sepp->se_rpc || 1127 sep->se_rpc_prog != sepp->se_rpc_prog) 1128 continue; 1129 return; 1130 } 1131 if (debug) 1132 print_service("UNREG", sep); 1133 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) 1134 pmap_unset(sep->se_rpc_prog, i); 1135 if (sep->se_fd != -1) 1136 close(sep->se_fd); 1137 sep->se_fd = -1; 1138 sigsetmask(omask); 1139 } 1140 1141 void 1142 flag_retry(int signo __unused) 1143 { 1144 flag_signal('A'); 1145 } 1146 1147 void 1148 retry(void) 1149 { 1150 struct servtab *sep; 1151 1152 timingout = 0; 1153 for (sep = servtab; sep; sep = sep->se_next) 1154 if (sep->se_fd == -1 && !ISMUX(sep)) 1155 setup(sep); 1156 } 1157 1158 void 1159 setup(struct servtab *sep) 1160 { 1161 int on = 1; 1162 1163 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { 1164 if (debug) 1165 warn("socket failed on %s/%s", 1166 sep->se_service, sep->se_proto); 1167 syslog(LOG_ERR, "%s/%s: socket: %m", 1168 sep->se_service, sep->se_proto); 1169 return; 1170 } 1171 /* Set all listening sockets to close-on-exec. */ 1172 if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) { 1173 syslog(LOG_ERR, "%s/%s: fcntl (F_SETFD, FD_CLOEXEC): %m", 1174 sep->se_service, sep->se_proto); 1175 close(sep->se_fd); 1176 return; 1177 } 1178 #define turnon(fd, opt) \ 1179 setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) 1180 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && 1181 turnon(sep->se_fd, SO_DEBUG) < 0) 1182 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 1183 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 1184 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 1185 #ifdef SO_PRIVSTATE 1186 if (turnon(sep->se_fd, SO_PRIVSTATE) < 0) 1187 syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m"); 1188 #endif 1189 /* tftpd opens a new connection then needs more infos */ 1190 if ((sep->se_family == AF_INET6) && 1191 (strcmp(sep->se_proto, "udp") == 0) && 1192 (sep->se_accept == 0) && 1193 (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_PKTINFO, 1194 (char *)&on, sizeof (on)) < 0)) 1195 syslog(LOG_ERR, "setsockopt (IPV6_RECVPKTINFO): %m"); 1196 if (sep->se_family == AF_INET6) { 1197 int flag = sep->se_nomapped ? 1 : 0; 1198 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_V6ONLY, 1199 (char *)&flag, sizeof (flag)) < 0) 1200 syslog(LOG_ERR, "setsockopt (IPV6_V6ONLY): %m"); 1201 } 1202 #undef turnon 1203 if (sep->se_type == TTCP_TYPE) 1204 if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH, 1205 (char *)&on, sizeof (on)) < 0) 1206 syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m"); 1207 if (sep->se_family == AF_UNIX) { 1208 unlink(sep->se_ctrladdr_un.sun_path); 1209 umask(0777); /* Make socket with conservative permissions */ 1210 } 1211 if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr, 1212 sep->se_ctrladdr_size) < 0) { 1213 if (debug) 1214 warn("bind failed on %s/%s", 1215 sep->se_service, sep->se_proto); 1216 syslog(LOG_ERR, "%s/%s: bind: %m", 1217 sep->se_service, sep->se_proto); 1218 close(sep->se_fd); 1219 sep->se_fd = -1; 1220 if (!timingout) { 1221 timingout = 1; 1222 alarm(RETRYTIME); 1223 } 1224 if (sep->se_family == AF_UNIX) 1225 umask(mask); 1226 return; 1227 } 1228 if (sep->se_family == AF_UNIX) { 1229 /* Ick - fch{own,mod} don't work on Unix domain sockets */ 1230 if (chown(sep->se_service, sep->se_sockuid, sep->se_sockgid) < 0) 1231 syslog(LOG_ERR, "chown socket: %m"); 1232 if (chmod(sep->se_service, sep->se_sockmode) < 0) 1233 syslog(LOG_ERR, "chmod socket: %m"); 1234 umask(mask); 1235 } 1236 if (sep->se_rpc) { 1237 u_int i; 1238 socklen_t len = sep->se_ctrladdr_size; 1239 1240 if (sep->se_family != AF_INET) { 1241 syslog(LOG_ERR, 1242 "%s/%s: unsupported address family for rpc", 1243 sep->se_service, sep->se_proto); 1244 close(sep->se_fd); 1245 sep->se_fd = -1; 1246 return; 1247 } 1248 if (getsockname(sep->se_fd, 1249 (struct sockaddr*)&sep->se_ctrladdr, &len) < 0){ 1250 syslog(LOG_ERR, "%s/%s: getsockname: %m", 1251 sep->se_service, sep->se_proto); 1252 close(sep->se_fd); 1253 sep->se_fd = -1; 1254 return; 1255 } 1256 if (debug) 1257 print_service("REG ", sep); 1258 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) { 1259 pmap_unset(sep->se_rpc_prog, i); 1260 pmap_set(sep->se_rpc_prog, i, 1261 (sep->se_socktype == SOCK_DGRAM) 1262 ? IPPROTO_UDP : IPPROTO_TCP, 1263 ntohs(sep->se_ctrladdr4.sin_port)); 1264 } 1265 } 1266 if (sep->se_socktype == SOCK_STREAM) 1267 listen(sep->se_fd, 64); 1268 enable(sep); 1269 if (debug) { 1270 warnx("registered %s on %d", 1271 sep->se_server, sep->se_fd); 1272 } 1273 } 1274 1275 /* 1276 * Finish with a service and its socket. 1277 */ 1278 void 1279 close_sep(struct servtab *sep) 1280 { 1281 if (sep->se_fd >= 0) { 1282 if (FD_ISSET(sep->se_fd, &allsock)) 1283 disable(sep); 1284 close(sep->se_fd); 1285 sep->se_fd = -1; 1286 } 1287 sep->se_count = 0; 1288 sep->se_numchild = 0; /* forget about any existing children */ 1289 } 1290 1291 int 1292 matchservent(const char *name1, const char *name2, const char *proto) 1293 { 1294 char **alias, *p; 1295 struct servent *se; 1296 1297 if (strcmp(proto, "unix") == 0) { 1298 if ((p = strrchr(name1, '/')) != NULL) 1299 name1 = p + 1; 1300 if ((p = strrchr(name2, '/')) != NULL) 1301 name2 = p + 1; 1302 } 1303 if (strcmp(name1, name2) == 0) 1304 return(1); 1305 if ((se = getservbyname(name1, proto)) != NULL) { 1306 if (strcmp(name2, se->s_name) == 0) 1307 return(1); 1308 for (alias = se->s_aliases; *alias; alias++) 1309 if (strcmp(name2, *alias) == 0) 1310 return(1); 1311 } 1312 return(0); 1313 } 1314 1315 struct servtab * 1316 enter(struct servtab *cp) 1317 { 1318 struct servtab *sep; 1319 long omask; 1320 1321 sep = (struct servtab *)malloc(sizeof (*sep)); 1322 if (sep == NULL) { 1323 syslog(LOG_ERR, "malloc: %m"); 1324 exit(EX_OSERR); 1325 } 1326 *sep = *cp; 1327 sep->se_fd = -1; 1328 omask = sigblock(SIGBLOCK); 1329 sep->se_next = servtab; 1330 servtab = sep; 1331 sigsetmask(omask); 1332 return (sep); 1333 } 1334 1335 void 1336 enable(struct servtab *sep) 1337 { 1338 if (debug) 1339 warnx( 1340 "enabling %s, fd %d", sep->se_service, sep->se_fd); 1341 #ifdef SANITY_CHECK 1342 if (sep->se_fd < 0) { 1343 syslog(LOG_ERR, 1344 "%s: %s: bad fd", __func__, sep->se_service); 1345 exit(EX_SOFTWARE); 1346 } 1347 if (ISMUX(sep)) { 1348 syslog(LOG_ERR, 1349 "%s: %s: is mux", __func__, sep->se_service); 1350 exit(EX_SOFTWARE); 1351 } 1352 if (FD_ISSET(sep->se_fd, &allsock)) { 1353 syslog(LOG_ERR, 1354 "%s: %s: not off", __func__, sep->se_service); 1355 exit(EX_SOFTWARE); 1356 } 1357 nsock++; 1358 #endif 1359 FD_SET(sep->se_fd, &allsock); 1360 if (sep->se_fd > maxsock) 1361 maxsock = sep->se_fd; 1362 } 1363 1364 void 1365 disable(struct servtab *sep) 1366 { 1367 if (debug) 1368 warnx( 1369 "disabling %s, fd %d", sep->se_service, sep->se_fd); 1370 #ifdef SANITY_CHECK 1371 if (sep->se_fd < 0) { 1372 syslog(LOG_ERR, 1373 "%s: %s: bad fd", __func__, sep->se_service); 1374 exit(EX_SOFTWARE); 1375 } 1376 if (ISMUX(sep)) { 1377 syslog(LOG_ERR, 1378 "%s: %s: is mux", __func__, sep->se_service); 1379 exit(EX_SOFTWARE); 1380 } 1381 if (!FD_ISSET(sep->se_fd, &allsock)) { 1382 syslog(LOG_ERR, 1383 "%s: %s: not on", __func__, sep->se_service); 1384 exit(EX_SOFTWARE); 1385 } 1386 if (nsock == 0) { 1387 syslog(LOG_ERR, "%s: nsock=0", __func__); 1388 exit(EX_SOFTWARE); 1389 } 1390 nsock--; 1391 #endif 1392 FD_CLR(sep->se_fd, &allsock); 1393 if (sep->se_fd == maxsock) 1394 maxsock--; 1395 } 1396 1397 FILE *fconfig = NULL; 1398 struct servtab serv; 1399 char line[LINE_MAX]; 1400 1401 int 1402 setconfig(void) 1403 { 1404 1405 if (fconfig != NULL) { 1406 fseek(fconfig, 0L, SEEK_SET); 1407 return (1); 1408 } 1409 fconfig = fopen(CONFIG, "r"); 1410 return (fconfig != NULL); 1411 } 1412 1413 void 1414 endconfig(void) 1415 { 1416 if (fconfig) { 1417 fclose(fconfig); 1418 fconfig = NULL; 1419 } 1420 } 1421 1422 struct servtab * 1423 getconfigent(void) 1424 { 1425 struct servtab *sep = &serv; 1426 int argc; 1427 char *cp, *arg, *s; 1428 char *versp; 1429 static char TCPMUX_TOKEN[] = "tcpmux/"; 1430 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1) 1431 int v4bind = 0; 1432 #ifdef INET6 1433 int v6bind = 0; 1434 #endif 1435 int i; 1436 1437 more: 1438 while ((cp = nextline(fconfig)) != NULL) { 1439 if (*cp == '#' || *cp == '\0') 1440 continue; 1441 break; 1442 } 1443 if (cp == NULL) 1444 return (NULL); 1445 /* 1446 * clear the static buffer, since some fields (se_ctrladdr, 1447 * for example) don't get initialized here. 1448 */ 1449 memset(sep, 0, sizeof *sep); 1450 arg = skip(&cp); 1451 if (cp == NULL) { 1452 /* got an empty line containing just blanks/tabs. */ 1453 goto more; 1454 } 1455 if (arg[0] == ':') { /* :user:group:perm: */ 1456 char *user, *group, *perm; 1457 struct passwd *pw; 1458 struct group *gr; 1459 user = arg+1; 1460 if ((group = strchr(user, ':')) == NULL) { 1461 syslog(LOG_ERR, "no group after user '%s'", user); 1462 goto more; 1463 } 1464 *group++ = '\0'; 1465 if ((perm = strchr(group, ':')) == NULL) { 1466 syslog(LOG_ERR, "no mode after group '%s'", group); 1467 goto more; 1468 } 1469 *perm++ = '\0'; 1470 if ((pw = getpwnam(user)) == NULL) { 1471 syslog(LOG_ERR, "no such user '%s'", user); 1472 goto more; 1473 } 1474 sep->se_sockuid = pw->pw_uid; 1475 if ((gr = getgrnam(group)) == NULL) { 1476 syslog(LOG_ERR, "no such user '%s'", group); 1477 goto more; 1478 } 1479 sep->se_sockgid = gr->gr_gid; 1480 sep->se_sockmode = strtol(perm, &arg, 8); 1481 if (*arg != ':') { 1482 syslog(LOG_ERR, "bad mode '%s'", perm); 1483 goto more; 1484 } 1485 *arg++ = '\0'; 1486 } else { 1487 sep->se_sockuid = euid; 1488 sep->se_sockgid = egid; 1489 sep->se_sockmode = 0200; 1490 } 1491 if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) { 1492 char *c = arg + MUX_LEN; 1493 if (*c == '+') { 1494 sep->se_type = MUXPLUS_TYPE; 1495 c++; 1496 } else 1497 sep->se_type = MUX_TYPE; 1498 sep->se_service = newstr(c); 1499 } else { 1500 sep->se_service = newstr(arg); 1501 sep->se_type = NORM_TYPE; 1502 } 1503 arg = sskip(&cp); 1504 if (strcmp(arg, "stream") == 0) 1505 sep->se_socktype = SOCK_STREAM; 1506 else if (strcmp(arg, "dgram") == 0) 1507 sep->se_socktype = SOCK_DGRAM; 1508 else if (strcmp(arg, "rdm") == 0) 1509 sep->se_socktype = SOCK_RDM; 1510 else if (strcmp(arg, "seqpacket") == 0) 1511 sep->se_socktype = SOCK_SEQPACKET; 1512 else if (strcmp(arg, "raw") == 0) 1513 sep->se_socktype = SOCK_RAW; 1514 else 1515 sep->se_socktype = -1; 1516 1517 arg = sskip(&cp); 1518 if (strncmp(arg, "tcp", 3) == 0) { 1519 sep->se_proto = newstr(strsep(&arg, "/")); 1520 if (arg != NULL) { 1521 if (strcmp(arg, "ttcp") == 0) 1522 sep->se_type = TTCP_TYPE; 1523 } 1524 } else { 1525 sep->se_proto = newstr(arg); 1526 } 1527 if (strncmp(sep->se_proto, "rpc/", 4) == 0) { 1528 if (no_v4bind != 0) { 1529 syslog(LOG_NOTICE, "IPv4 bind is ignored for %s", 1530 sep->se_service); 1531 freeconfig(sep); 1532 goto more; 1533 } 1534 memmove(sep->se_proto, sep->se_proto + 4, 1535 strlen(sep->se_proto) + 1 - 4); 1536 sep->se_rpc = 1; 1537 sep->se_rpc_prog = sep->se_rpc_lowvers = 1538 sep->se_rpc_highvers = 0; 1539 memcpy(&sep->se_ctrladdr4, bind_sa4, 1540 sizeof(sep->se_ctrladdr4)); 1541 if ((versp = strrchr(sep->se_service, '/'))) { 1542 *versp++ = '\0'; 1543 switch (sscanf(versp, "%u-%u", 1544 &sep->se_rpc_lowvers, 1545 &sep->se_rpc_highvers)) { 1546 case 2: 1547 break; 1548 case 1: 1549 sep->se_rpc_highvers = 1550 sep->se_rpc_lowvers; 1551 break; 1552 default: 1553 syslog(LOG_ERR, 1554 "bad RPC version specifier; %s", 1555 sep->se_service); 1556 freeconfig(sep); 1557 goto more; 1558 } 1559 } 1560 else { 1561 sep->se_rpc_lowvers = 1562 sep->se_rpc_highvers = 1; 1563 } 1564 } 1565 sep->se_nomapped = 0; 1566 while (isdigit(sep->se_proto[strlen(sep->se_proto) - 1])) { 1567 #ifdef INET6 1568 if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') { 1569 if (no_v6bind != 0) { 1570 syslog(LOG_NOTICE, "IPv6 bind is ignored for %s", 1571 sep->se_service); 1572 freeconfig(sep); 1573 goto more; 1574 } 1575 sep->se_proto[strlen(sep->se_proto) - 1] = '\0'; 1576 v6bind = 1; 1577 continue; 1578 } 1579 #endif 1580 if (sep->se_proto[strlen(sep->se_proto) - 1] == '4') { 1581 sep->se_proto[strlen(sep->se_proto) - 1] = '\0'; 1582 v4bind = 1; 1583 continue; 1584 } 1585 /* illegal version num */ 1586 syslog(LOG_ERR, "bad IP version for %s", sep->se_proto); 1587 freeconfig(sep); 1588 goto more; 1589 } 1590 if (strcmp(sep->se_proto, "unix") == 0) { 1591 sep->se_family = AF_UNIX; 1592 } else 1593 #ifdef INET6 1594 if (v6bind != 0) { 1595 sep->se_family = AF_INET6; 1596 if (v4bind == 0 || no_v4bind != 0) 1597 sep->se_nomapped = 1; 1598 } else 1599 #endif 1600 { /* default to v4 bind if not v6 bind */ 1601 if (no_v4bind != 0) { 1602 syslog(LOG_NOTICE, "IPv4 bind is ignored for %s", 1603 sep->se_service); 1604 freeconfig(sep); 1605 goto more; 1606 } 1607 sep->se_family = AF_INET; 1608 } 1609 /* init ctladdr */ 1610 switch(sep->se_family) { 1611 case AF_INET: 1612 memcpy(&sep->se_ctrladdr4, bind_sa4, 1613 sizeof(sep->se_ctrladdr4)); 1614 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr4); 1615 break; 1616 #ifdef INET6 1617 case AF_INET6: 1618 memcpy(&sep->se_ctrladdr6, bind_sa6, 1619 sizeof(sep->se_ctrladdr6)); 1620 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr6); 1621 break; 1622 #endif 1623 case AF_UNIX: 1624 if (strlen(sep->se_service) >= sizeof(sep->se_ctrladdr_un.sun_path)) { 1625 syslog(LOG_ERR, 1626 "domain socket pathname too long for service %s", 1627 sep->se_service); 1628 goto more; 1629 } 1630 memset(&sep->se_ctrladdr, 0, sizeof(sep->se_ctrladdr)); 1631 sep->se_ctrladdr_un.sun_family = sep->se_family; 1632 sep->se_ctrladdr_un.sun_len = strlen(sep->se_service); 1633 strcpy(sep->se_ctrladdr_un.sun_path, sep->se_service); 1634 sep->se_ctrladdr_size = SUN_LEN(&sep->se_ctrladdr_un); 1635 } 1636 arg = sskip(&cp); 1637 if (!strncmp(arg, "wait", 4)) 1638 sep->se_accept = 0; 1639 else if (!strncmp(arg, "nowait", 6)) 1640 sep->se_accept = 1; 1641 else { 1642 syslog(LOG_ERR, 1643 "%s: bad wait/nowait for service %s", 1644 CONFIG, sep->se_service); 1645 goto more; 1646 } 1647 sep->se_maxchild = -1; 1648 sep->se_maxcpm = -1; 1649 sep->se_maxperip = -1; 1650 if ((s = strchr(arg, '/')) != NULL) { 1651 char *eptr; 1652 u_long val; 1653 1654 val = strtoul(s + 1, &eptr, 10); 1655 if (eptr == s + 1 || val > MAX_MAXCHLD) { 1656 syslog(LOG_ERR, 1657 "%s: bad max-child for service %s", 1658 CONFIG, sep->se_service); 1659 goto more; 1660 } 1661 if (debug) 1662 if (!sep->se_accept && val != 1) 1663 warnx("maxchild=%lu for wait service %s" 1664 " not recommended", val, sep->se_service); 1665 sep->se_maxchild = val; 1666 if (*eptr == '/') 1667 sep->se_maxcpm = strtol(eptr + 1, &eptr, 10); 1668 if (*eptr == '/') 1669 sep->se_maxperip = strtol(eptr + 1, &eptr, 10); 1670 /* 1671 * explicitly do not check for \0 for future expansion / 1672 * backwards compatibility 1673 */ 1674 } 1675 if (ISMUX(sep)) { 1676 /* 1677 * Silently enforce "nowait" mode for TCPMUX services 1678 * since they don't have an assigned port to listen on. 1679 */ 1680 sep->se_accept = 1; 1681 if (strcmp(sep->se_proto, "tcp")) { 1682 syslog(LOG_ERR, 1683 "%s: bad protocol for tcpmux service %s", 1684 CONFIG, sep->se_service); 1685 goto more; 1686 } 1687 if (sep->se_socktype != SOCK_STREAM) { 1688 syslog(LOG_ERR, 1689 "%s: bad socket type for tcpmux service %s", 1690 CONFIG, sep->se_service); 1691 goto more; 1692 } 1693 } 1694 sep->se_user = newstr(sskip(&cp)); 1695 #ifdef LOGIN_CAP 1696 if ((s = strrchr(sep->se_user, '/')) != NULL) { 1697 *s = '\0'; 1698 sep->se_class = newstr(s + 1); 1699 } else 1700 sep->se_class = newstr(RESOURCE_RC); 1701 #endif 1702 if ((s = strrchr(sep->se_user, ':')) != NULL) { 1703 *s = '\0'; 1704 sep->se_group = newstr(s + 1); 1705 } else 1706 sep->se_group = NULL; 1707 sep->se_server = newstr(sskip(&cp)); 1708 if ((sep->se_server_name = strrchr(sep->se_server, '/'))) 1709 sep->se_server_name++; 1710 if (strcmp(sep->se_server, "internal") == 0) { 1711 struct biltin *bi; 1712 1713 for (bi = biltins; bi->bi_service; bi++) 1714 if (bi->bi_socktype == sep->se_socktype && 1715 matchservent(bi->bi_service, sep->se_service, 1716 sep->se_proto)) 1717 break; 1718 if (bi->bi_service == 0) { 1719 syslog(LOG_ERR, "internal service %s unknown", 1720 sep->se_service); 1721 goto more; 1722 } 1723 sep->se_accept = 1; /* force accept mode for built-ins */ 1724 sep->se_bi = bi; 1725 } else 1726 sep->se_bi = NULL; 1727 if (sep->se_maxperip < 0) 1728 sep->se_maxperip = maxperip; 1729 if (sep->se_maxcpm < 0) 1730 sep->se_maxcpm = maxcpm; 1731 if (sep->se_maxchild < 0) { /* apply default max-children */ 1732 if (sep->se_bi && sep->se_bi->bi_maxchild >= 0) 1733 sep->se_maxchild = sep->se_bi->bi_maxchild; 1734 else if (sep->se_accept) 1735 sep->se_maxchild = maxchild > 0 ? maxchild : 0; 1736 else 1737 sep->se_maxchild = 1; 1738 } 1739 if (sep->se_maxchild > 0) { 1740 sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids)); 1741 if (sep->se_pids == NULL) { 1742 syslog(LOG_ERR, "malloc: %m"); 1743 exit(EX_OSERR); 1744 } 1745 } 1746 argc = 0; 1747 for (arg = skip(&cp); cp; arg = skip(&cp)) 1748 if (argc < MAXARGV) { 1749 sep->se_argv[argc++] = newstr(arg); 1750 } else { 1751 syslog(LOG_ERR, 1752 "%s: too many arguments for service %s", 1753 CONFIG, sep->se_service); 1754 goto more; 1755 } 1756 while (argc <= MAXARGV) 1757 sep->se_argv[argc++] = NULL; 1758 for (i = 0; i < PERIPSIZE; ++i) 1759 LIST_INIT(&sep->se_conn[i]); 1760 return (sep); 1761 } 1762 1763 void 1764 freeconfig(struct servtab *cp) 1765 { 1766 int i; 1767 1768 if (cp->se_service) 1769 free(cp->se_service); 1770 if (cp->se_proto) 1771 free(cp->se_proto); 1772 if (cp->se_user) 1773 free(cp->se_user); 1774 if (cp->se_group) 1775 free(cp->se_group); 1776 #ifdef LOGIN_CAP 1777 if (cp->se_class) 1778 free(cp->se_class); 1779 #endif 1780 if (cp->se_server) 1781 free(cp->se_server); 1782 if (cp->se_pids) 1783 free(cp->se_pids); 1784 for (i = 0; i < MAXARGV; i++) 1785 if (cp->se_argv[i]) 1786 free(cp->se_argv[i]); 1787 free_connlist(cp); 1788 } 1789 1790 1791 /* 1792 * Safe skip - if skip returns null, log a syntax error in the 1793 * configuration file and exit. 1794 */ 1795 char * 1796 sskip(char **cpp) 1797 { 1798 char *cp; 1799 1800 cp = skip(cpp); 1801 if (cp == NULL) { 1802 syslog(LOG_ERR, "%s: syntax error", CONFIG); 1803 exit(EX_DATAERR); 1804 } 1805 return (cp); 1806 } 1807 1808 char * 1809 skip(char **cpp) 1810 { 1811 char *cp = *cpp; 1812 char *start; 1813 char quote = '\0'; 1814 1815 again: 1816 while (*cp == ' ' || *cp == '\t') 1817 cp++; 1818 if (*cp == '\0') { 1819 int c; 1820 1821 c = getc(fconfig); 1822 ungetc(c, fconfig); 1823 if (c == ' ' || c == '\t') 1824 if ((cp = nextline(fconfig))) 1825 goto again; 1826 *cpp = NULL; 1827 return (NULL); 1828 } 1829 if (*cp == '"' || *cp == '\'') 1830 quote = *cp++; 1831 start = cp; 1832 if (quote) 1833 while (*cp && *cp != quote) 1834 cp++; 1835 else 1836 while (*cp && *cp != ' ' && *cp != '\t') 1837 cp++; 1838 if (*cp != '\0') 1839 *cp++ = '\0'; 1840 *cpp = cp; 1841 return (start); 1842 } 1843 1844 char * 1845 nextline(FILE *fd) 1846 { 1847 char *cp; 1848 1849 if (fgets(line, sizeof (line), fd) == NULL) 1850 return (NULL); 1851 cp = strchr(line, '\n'); 1852 if (cp) 1853 *cp = '\0'; 1854 return (line); 1855 } 1856 1857 char * 1858 newstr(const char *cp) 1859 { 1860 char *cr; 1861 1862 if ((cr = strdup(cp != NULL ? cp : ""))) 1863 return (cr); 1864 syslog(LOG_ERR, "strdup: %m"); 1865 exit(EX_OSERR); 1866 } 1867 1868 void 1869 inetd_setproctitle(const char *a, int s) 1870 { 1871 socklen_t size; 1872 struct sockaddr_storage ss; 1873 char buf[80], pbuf[INET6_ADDRSTRLEN]; 1874 1875 size = sizeof(ss); 1876 if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) { 1877 getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf), 1878 NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID); 1879 sprintf(buf, "%s [%s]", a, pbuf); 1880 } else 1881 sprintf(buf, "%s", a); 1882 setproctitle("%s", buf); 1883 } 1884 1885 int 1886 check_loop(const struct sockaddr *sa, const struct servtab *sep) 1887 { 1888 struct servtab *se2; 1889 char pname[INET6_ADDRSTRLEN]; 1890 1891 for (se2 = servtab; se2; se2 = se2->se_next) { 1892 if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM) 1893 continue; 1894 1895 switch (se2->se_family) { 1896 case AF_INET: 1897 if (((const struct sockaddr_in *)sa)->sin_port == 1898 se2->se_ctrladdr4.sin_port) 1899 goto isloop; 1900 continue; 1901 #ifdef INET6 1902 case AF_INET6: 1903 if (((const struct sockaddr_in *)sa)->sin_port == 1904 se2->se_ctrladdr4.sin_port) 1905 goto isloop; 1906 continue; 1907 #endif 1908 default: 1909 continue; 1910 } 1911 isloop: 1912 getnameinfo(sa, sa->sa_len, pname, sizeof(pname), NULL, 0, 1913 NI_NUMERICHOST|NI_WITHSCOPEID); 1914 syslog(LOG_WARNING, "%s/%s:%s/%s loop request REFUSED from %s", 1915 sep->se_service, sep->se_proto, 1916 se2->se_service, se2->se_proto, 1917 pname); 1918 return 1; 1919 } 1920 return 0; 1921 } 1922 1923 /* 1924 * print_service: 1925 * Dump relevant information to stderr 1926 */ 1927 void 1928 print_service(const char *action, const struct servtab *sep) 1929 { 1930 fprintf(stderr, 1931 "%s: %s proto=%s accept=%d max=%d user=%s group=%s" 1932 #ifdef LOGIN_CAP 1933 "class=%s" 1934 #endif 1935 " builtin=%p server=%s" 1936 "\n", 1937 action, sep->se_service, sep->se_proto, 1938 sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group, 1939 #ifdef LOGIN_CAP 1940 sep->se_class, 1941 #endif 1942 (void *) sep->se_bi, sep->se_server 1943 ); 1944 } 1945 1946 #define CPMHSIZE 256 1947 #define CPMHMASK (CPMHSIZE-1) 1948 #define CHTGRAN 10 1949 #define CHTSIZE 6 1950 1951 typedef struct CTime { 1952 unsigned long ct_Ticks; 1953 int ct_Count; 1954 } CTime; 1955 1956 typedef struct CHash { 1957 union { 1958 struct in_addr c4_Addr; 1959 struct in6_addr c6_Addr; 1960 } cu_Addr; 1961 #define ch_Addr4 cu_Addr.c4_Addr 1962 #define ch_Addr6 cu_Addr.c6_Addr 1963 int ch_Family; 1964 time_t ch_LTime; 1965 char *ch_Service; 1966 CTime ch_Times[CHTSIZE]; 1967 } CHash; 1968 1969 CHash CHashAry[CPMHSIZE]; 1970 1971 int 1972 cpmip(const struct servtab *sep, int ctrl) 1973 { 1974 struct sockaddr_storage rss; 1975 socklen_t rssLen = sizeof(rss); 1976 int r = 0; 1977 1978 /* 1979 * If getpeername() fails, just let it through (if logging is 1980 * enabled the condition is caught elsewhere) 1981 */ 1982 1983 if (sep->se_maxcpm > 0 && 1984 getpeername(ctrl, (struct sockaddr *)&rss, &rssLen) == 0 ) { 1985 time_t t = time(NULL); 1986 int hv = 0xABC3D20F; 1987 int i; 1988 int cnt = 0; 1989 CHash *chBest = NULL; 1990 unsigned int ticks = t / CHTGRAN; 1991 struct sockaddr_in *sin4; 1992 #ifdef INET6 1993 struct sockaddr_in6 *sin6; 1994 #endif 1995 1996 sin4 = (struct sockaddr_in *)&rss; 1997 #ifdef INET6 1998 sin6 = (struct sockaddr_in6 *)&rss; 1999 #endif 2000 { 2001 char *p; 2002 int addrlen; 2003 2004 switch (rss.ss_family) { 2005 case AF_INET: 2006 p = (char *)&sin4->sin_addr; 2007 addrlen = sizeof(struct in_addr); 2008 break; 2009 #ifdef INET6 2010 case AF_INET6: 2011 p = (char *)&sin6->sin6_addr; 2012 addrlen = sizeof(struct in6_addr); 2013 break; 2014 #endif 2015 default: 2016 /* should not happen */ 2017 return -1; 2018 } 2019 2020 for (i = 0; i < addrlen; ++i, ++p) { 2021 hv = (hv << 5) ^ (hv >> 23) ^ *p; 2022 } 2023 hv = (hv ^ (hv >> 16)); 2024 } 2025 for (i = 0; i < 5; ++i) { 2026 CHash *ch = &CHashAry[(hv + i) & CPMHMASK]; 2027 2028 if (rss.ss_family == AF_INET && 2029 ch->ch_Family == AF_INET && 2030 sin4->sin_addr.s_addr == ch->ch_Addr4.s_addr && 2031 ch->ch_Service && strcmp(sep->se_service, 2032 ch->ch_Service) == 0) { 2033 chBest = ch; 2034 break; 2035 } 2036 #ifdef INET6 2037 if (rss.ss_family == AF_INET6 && 2038 ch->ch_Family == AF_INET6 && 2039 IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, 2040 &ch->ch_Addr6) != 0 && 2041 ch->ch_Service && strcmp(sep->se_service, 2042 ch->ch_Service) == 0) { 2043 chBest = ch; 2044 break; 2045 } 2046 #endif 2047 if (chBest == NULL || ch->ch_LTime == 0 || 2048 ch->ch_LTime < chBest->ch_LTime) { 2049 chBest = ch; 2050 } 2051 } 2052 if ((rss.ss_family == AF_INET && 2053 (chBest->ch_Family != AF_INET || 2054 sin4->sin_addr.s_addr != chBest->ch_Addr4.s_addr)) || 2055 chBest->ch_Service == NULL || 2056 strcmp(sep->se_service, chBest->ch_Service) != 0) { 2057 chBest->ch_Family = sin4->sin_family; 2058 chBest->ch_Addr4 = sin4->sin_addr; 2059 if (chBest->ch_Service) 2060 free(chBest->ch_Service); 2061 chBest->ch_Service = strdup(sep->se_service); 2062 bzero(chBest->ch_Times, sizeof(chBest->ch_Times)); 2063 } 2064 #ifdef INET6 2065 if ((rss.ss_family == AF_INET6 && 2066 (chBest->ch_Family != AF_INET6 || 2067 IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, 2068 &chBest->ch_Addr6) == 0)) || 2069 chBest->ch_Service == NULL || 2070 strcmp(sep->se_service, chBest->ch_Service) != 0) { 2071 chBest->ch_Family = sin6->sin6_family; 2072 chBest->ch_Addr6 = sin6->sin6_addr; 2073 if (chBest->ch_Service) 2074 free(chBest->ch_Service); 2075 chBest->ch_Service = strdup(sep->se_service); 2076 bzero(chBest->ch_Times, sizeof(chBest->ch_Times)); 2077 } 2078 #endif 2079 chBest->ch_LTime = t; 2080 { 2081 CTime *ct = &chBest->ch_Times[ticks % CHTSIZE]; 2082 if (ct->ct_Ticks != ticks) { 2083 ct->ct_Ticks = ticks; 2084 ct->ct_Count = 0; 2085 } 2086 ++ct->ct_Count; 2087 } 2088 for (i = 0; i < CHTSIZE; ++i) { 2089 CTime *ct = &chBest->ch_Times[i]; 2090 if (ct->ct_Ticks <= ticks && 2091 ct->ct_Ticks >= ticks - CHTSIZE) { 2092 cnt += ct->ct_Count; 2093 } 2094 } 2095 if (cnt * (CHTSIZE * CHTGRAN) / 60 > sep->se_maxcpm) { 2096 char pname[INET6_ADDRSTRLEN]; 2097 2098 getnameinfo((struct sockaddr *)&rss, 2099 ((struct sockaddr *)&rss)->sa_len, 2100 pname, sizeof(pname), NULL, 0, 2101 NI_NUMERICHOST|NI_WITHSCOPEID); 2102 r = -1; 2103 syslog(LOG_ERR, 2104 "%s from %s exceeded counts/min (limit %d/min)", 2105 sep->se_service, pname, 2106 sep->se_maxcpm); 2107 } 2108 } 2109 return(r); 2110 } 2111 2112 static struct conninfo * 2113 search_conn(struct servtab *sep, int ctrl) 2114 { 2115 struct sockaddr_storage ss; 2116 socklen_t sslen = sizeof(ss); 2117 struct conninfo *conn; 2118 int hv; 2119 char pname[NI_MAXHOST], pname2[NI_MAXHOST]; 2120 2121 if (sep->se_maxperip <= 0) 2122 return NULL; 2123 2124 /* 2125 * If getpeername() fails, just let it through (if logging is 2126 * enabled the condition is caught elsewhere) 2127 */ 2128 if (getpeername(ctrl, (struct sockaddr *)&ss, &sslen) != 0) 2129 return NULL; 2130 2131 switch (ss.ss_family) { 2132 case AF_INET: 2133 hv = hashval((char *)&((struct sockaddr_in *)&ss)->sin_addr, 2134 sizeof(struct in_addr)); 2135 break; 2136 #ifdef INET6 2137 case AF_INET6: 2138 hv = hashval((char *)&((struct sockaddr_in6 *)&ss)->sin6_addr, 2139 sizeof(struct in6_addr)); 2140 break; 2141 #endif 2142 default: 2143 /* 2144 * Since we only support AF_INET and AF_INET6, just 2145 * let other than AF_INET and AF_INET6 through. 2146 */ 2147 return NULL; 2148 } 2149 2150 if (getnameinfo((struct sockaddr *)&ss, sslen, pname, sizeof(pname), 2151 NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) != 0) 2152 return NULL; 2153 2154 LIST_FOREACH(conn, &sep->se_conn[hv], co_link) { 2155 if (getnameinfo((struct sockaddr *)&conn->co_addr, 2156 conn->co_addr.ss_len, pname2, sizeof(pname2), NULL, 0, 2157 NI_NUMERICHOST | NI_WITHSCOPEID) == 0 && 2158 strcmp(pname, pname2) == 0) 2159 break; 2160 } 2161 2162 if (conn == NULL) { 2163 if ((conn = malloc(sizeof(struct conninfo))) == NULL) { 2164 syslog(LOG_ERR, "malloc: %m"); 2165 exit(EX_OSERR); 2166 } 2167 conn->co_proc = malloc(sep->se_maxperip * sizeof(*conn->co_proc)); 2168 if (conn->co_proc == NULL) { 2169 syslog(LOG_ERR, "malloc: %m"); 2170 exit(EX_OSERR); 2171 } 2172 memcpy(&conn->co_addr, (struct sockaddr *)&ss, sslen); 2173 conn->co_numchild = 0; 2174 LIST_INSERT_HEAD(&sep->se_conn[hv], conn, co_link); 2175 } 2176 2177 /* 2178 * Since a child process is not invoked yet, we cannot 2179 * determine a pid of a child. So, co_proc and co_numchild 2180 * should be filled leter. 2181 */ 2182 2183 return conn; 2184 } 2185 2186 static int 2187 room_conn(struct servtab *sep, struct conninfo *conn) 2188 { 2189 char pname[NI_MAXHOST]; 2190 2191 if (conn->co_numchild >= sep->se_maxperip) { 2192 getnameinfo((struct sockaddr *)&conn->co_addr, 2193 conn->co_addr.ss_len, pname, sizeof(pname), NULL, 0, 2194 NI_NUMERICHOST | NI_WITHSCOPEID); 2195 syslog(LOG_ERR, "%s from %s exceeded counts (limit %d)", 2196 sep->se_service, pname, sep->se_maxperip); 2197 return 0; 2198 } 2199 return 1; 2200 } 2201 2202 static void 2203 addchild_conn(struct conninfo *conn, pid_t pid) 2204 { 2205 struct procinfo *proc; 2206 2207 if (conn == NULL) 2208 return; 2209 2210 if ((proc = search_proc(pid, 1)) != NULL) { 2211 if (proc->pr_conn != NULL) { 2212 syslog(LOG_ERR, 2213 "addchild_conn: child already on process list"); 2214 exit(EX_OSERR); 2215 } 2216 proc->pr_conn = conn; 2217 } 2218 2219 conn->co_proc[conn->co_numchild++] = proc; 2220 } 2221 2222 static void 2223 reapchild_conn(pid_t pid) 2224 { 2225 struct procinfo *proc; 2226 struct conninfo *conn; 2227 int i; 2228 2229 if ((proc = search_proc(pid, 0)) == NULL) 2230 return; 2231 if ((conn = proc->pr_conn) == NULL) 2232 return; 2233 for (i = 0; i < conn->co_numchild; ++i) 2234 if (conn->co_proc[i] == proc) { 2235 conn->co_proc[i] = conn->co_proc[--conn->co_numchild]; 2236 break; 2237 } 2238 free_proc(proc); 2239 free_conn(conn); 2240 } 2241 2242 static void 2243 resize_conn(struct servtab *sep, int maxpip) 2244 { 2245 struct conninfo *conn; 2246 int i, j; 2247 2248 if (sep->se_maxperip <= 0) 2249 return; 2250 if (maxpip <= 0) { 2251 free_connlist(sep); 2252 return; 2253 } 2254 for (i = 0; i < PERIPSIZE; ++i) { 2255 LIST_FOREACH(conn, &sep->se_conn[i], co_link) { 2256 for (j = maxpip; j < conn->co_numchild; ++j) 2257 free_proc(conn->co_proc[j]); 2258 conn->co_proc = realloc(conn->co_proc, 2259 maxpip * sizeof(*conn->co_proc)); 2260 if (conn->co_proc == NULL) { 2261 syslog(LOG_ERR, "realloc: %m"); 2262 exit(EX_OSERR); 2263 } 2264 if (conn->co_numchild > maxpip) 2265 conn->co_numchild = maxpip; 2266 } 2267 } 2268 } 2269 2270 static void 2271 free_connlist(struct servtab *sep) 2272 { 2273 struct conninfo *conn; 2274 int i, j; 2275 2276 for (i = 0; i < PERIPSIZE; ++i) { 2277 while ((conn = LIST_FIRST(&sep->se_conn[i])) != NULL) { 2278 for (j = 0; j < conn->co_numchild; ++j) 2279 free_proc(conn->co_proc[j]); 2280 conn->co_numchild = 0; 2281 free_conn(conn); 2282 } 2283 } 2284 } 2285 2286 static void 2287 free_conn(struct conninfo *conn) 2288 { 2289 if (conn == NULL) 2290 return; 2291 if (conn->co_numchild <= 0) { 2292 LIST_REMOVE(conn, co_link); 2293 free(conn->co_proc); 2294 free(conn); 2295 } 2296 } 2297 2298 static struct procinfo * 2299 search_proc(pid_t pid, int add) 2300 { 2301 struct procinfo *proc; 2302 int hv; 2303 2304 hv = hashval((char *)&pid, sizeof(pid)); 2305 LIST_FOREACH(proc, &proctable[hv], pr_link) { 2306 if (proc->pr_pid == pid) 2307 break; 2308 } 2309 if (proc == NULL && add) { 2310 if ((proc = malloc(sizeof(struct procinfo))) == NULL) { 2311 syslog(LOG_ERR, "malloc: %m"); 2312 exit(EX_OSERR); 2313 } 2314 proc->pr_pid = pid; 2315 proc->pr_conn = NULL; 2316 LIST_INSERT_HEAD(&proctable[hv], proc, pr_link); 2317 } 2318 return proc; 2319 } 2320 2321 static void 2322 free_proc(struct procinfo *proc) 2323 { 2324 if (proc == NULL) 2325 return; 2326 LIST_REMOVE(proc, pr_link); 2327 free(proc); 2328 } 2329 2330 static int 2331 hashval(char *p, int len) 2332 { 2333 int i, hv = 0xABC3D20F; 2334 2335 for (i = 0; i < len; ++i, ++p) 2336 hv = (hv << 5) ^ (hv >> 23) ^ *p; 2337 hv = (hv ^ (hv >> 16)) & (PERIPSIZE - 1); 2338 return hv; 2339 } 2340