1 /* $NetBSD: inetd.c,v 1.143 2026/06/04 10:41:15 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center and by Matthias Scheler. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 * POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 /* 34 * Copyright (c) 1983, 1991, 1993, 1994 35 * The Regents of the University of California. All rights reserved. 36 * 37 * Redistribution and use in source and binary forms, with or without 38 * modification, are permitted provided that the following conditions 39 * are met: 40 * 1. Redistributions of source code must retain the above copyright 41 * notice, this list of conditions and the following disclaimer. 42 * 2. Redistributions in binary form must reproduce the above copyright 43 * notice, this list of conditions and the following disclaimer in the 44 * documentation and/or other materials provided with the distribution. 45 * 3. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 */ 61 62 #include <sys/cdefs.h> 63 #ifndef lint 64 __COPYRIGHT("@(#) Copyright (c) 1983, 1991, 1993, 1994\ 65 The Regents of the University of California. All rights reserved."); 66 #if 0 67 static char sccsid[] = "@(#)inetd.c 8.4 (Berkeley) 4/13/94"; 68 #else 69 __RCSID("$NetBSD: inetd.c,v 1.143 2026/06/04 10:41:15 riastradh Exp $"); 70 #endif 71 #endif /* not lint */ 72 73 /* 74 * Inetd - Internet super-server 75 * 76 * This program invokes all internet services as needed. Connection-oriented 77 * services are invoked each time a connection is made, by creating a process. 78 * This process is passed the connection as file descriptor 0 and is expected 79 * to do a getpeername to find out the source host and port. 80 * 81 * Datagram oriented services are invoked when a datagram 82 * arrives; a process is created and passed a pending message 83 * on file descriptor 0. Datagram servers may either connect 84 * to their peer, freeing up the original socket for inetd 85 * to receive further messages on, or ``take over the socket'', 86 * processing all arriving datagrams and, eventually, timing 87 * out. The first type of server is said to be ``multi-threaded''; 88 * the second type of server ``single-threaded''. 89 * 90 * Inetd uses a configuration file which is read at startup 91 * and, possibly, at some later time in response to a hangup signal. 92 * The configuration file is ``free format'' with fields given in the 93 * order shown below. Continuation lines for an entry must being with 94 * a space or tab. All fields must be present in each entry. 95 * 96 * service name must be in /etc/services or must 97 * name a tcpmux service 98 * socket type[:accf[,arg]] stream/dgram/raw/rdm/seqpacket, 99 only stream can name an accept filter 100 * protocol must be in /etc/protocols 101 * wait/nowait[:max] single-threaded/multi-threaded, max # 102 * user[:group] user/group to run daemon as 103 * server program full path name 104 * server program arguments maximum of MAXARGV (64) 105 * 106 * For RPC services 107 * service name/version must be in /etc/rpc 108 * socket type stream/dgram/raw/rdm/seqpacket 109 * protocol must be in /etc/protocols 110 * wait/nowait[:max] single-threaded/multi-threaded 111 * user[:group] user to run daemon as 112 * server program full path name 113 * server program arguments maximum of MAXARGV (64) 114 * 115 * For non-RPC services, the "service name" can be of the form 116 * hostaddress:servicename, in which case the hostaddress is used 117 * as the host portion of the address to listen on. If hostaddress 118 * consists of a single `*' character, INADDR_ANY is used. 119 * 120 * A line can also consist of just 121 * hostaddress: 122 * where hostaddress is as in the preceding paragraph. Such a line must 123 * have no further fields; the specified hostaddress is remembered and 124 * used for all further lines that have no hostaddress specified, 125 * until the next such line (or EOF). (This is why * is provided to 126 * allow explicit specification of INADDR_ANY.) A line 127 * *: 128 * is implicitly in effect at the beginning of the file. 129 * 130 * The hostaddress specifier may (and often will) contain dots; 131 * the service name must not. 132 * 133 * For RPC services, host-address specifiers are accepted and will 134 * work to some extent; however, because of limitations in the 135 * portmapper interface, it will not work to try to give more than 136 * one line for any given RPC service, even if the host-address 137 * specifiers are different. 138 * 139 * TCP services without official port numbers are handled with the 140 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for 141 * requests. When a connection is made from a foreign host, the service 142 * requested is passed to tcpmux, which looks it up in the servtab list 143 * and returns the proper entry for the service. Tcpmux returns a 144 * negative reply if the service doesn't exist, otherwise the invoked 145 * server is expected to return the positive reply if the service type in 146 * inetd.conf file has the prefix "tcpmux/". If the service type has the 147 * prefix "tcpmux/+", tcpmux will return the positive reply for the 148 * process; this is for compatibility with older server code, and also 149 * allows you to invoke programs that use stdin/stdout without putting any 150 * special server code in them. Services that use tcpmux are "nowait" 151 * because they do not have a well-known port and hence cannot listen 152 * for new requests. 153 * 154 * Comment lines are indicated by a `#' in column 1. 155 * 156 * #ifdef IPSEC 157 * Comment lines that start with "#@" denote IPsec policy string, as described 158 * in ipsec_set_policy(3). This will affect all the following items in 159 * inetd.conf(8). To reset the policy, just use "#@" line. By default, 160 * there's no IPsec policy. 161 * #endif 162 */ 163 164 /* 165 * Here's the scoop concerning the user:group feature: 166 * 167 * 1) set-group-option off. 168 * 169 * a) user = root: NO setuid() or setgid() is done 170 * 171 * b) other: setuid() 172 * setgid(primary group as found in passwd) 173 * initgroups(name, primary group) 174 * 175 * 2) set-group-option on. 176 * 177 * a) user = root: NO setuid() 178 * setgid(specified group) 179 * NO initgroups() 180 * 181 * b) other: setuid() 182 * setgid(specified group) 183 * initgroups(name, specified group) 184 * 185 */ 186 187 #include <sys/param.h> 188 #include <sys/stat.h> 189 #include <sys/ioctl.h> 190 #include <sys/wait.h> 191 #include <sys/resource.h> 192 #include <sys/event.h> 193 #include <sys/socket.h> 194 #include <sys/queue.h> 195 196 #include <ctype.h> 197 #include <err.h> 198 #include <errno.h> 199 #include <fcntl.h> 200 #include <glob.h> 201 #include <grp.h> 202 #include <libgen.h> 203 #include <pwd.h> 204 #include <signal.h> 205 #include <stdio.h> 206 #include <stdlib.h> 207 #include <string.h> 208 #include <syslog.h> 209 #include <unistd.h> 210 #include <util.h> 211 #include <ifaddrs.h> 212 213 #include "inetd.h" 214 215 #ifdef LIBWRAP 216 # include <tcpd.h> 217 #ifndef LIBWRAP_ALLOW_FACILITY 218 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH 219 #endif 220 #ifndef LIBWRAP_ALLOW_SEVERITY 221 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO 222 #endif 223 #ifndef LIBWRAP_DENY_FACILITY 224 # define LIBWRAP_DENY_FACILITY LOG_AUTH 225 #endif 226 #ifndef LIBWRAP_DENY_SEVERITY 227 # define LIBWRAP_DENY_SEVERITY LOG_WARNING 228 #endif 229 int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY; 230 int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY; 231 #endif 232 233 static bool foreground; 234 int debug; 235 #ifdef LIBWRAP 236 int lflag; 237 #endif 238 int maxsock; 239 int kq; 240 int options; 241 int timingout; 242 const int niflags = NI_NUMERICHOST | NI_NUMERICSERV; 243 244 #ifndef OPEN_MAX 245 #define OPEN_MAX 64 246 #endif 247 248 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */ 249 #define FD_MARGIN (8) 250 rlim_t rlim_ofile_cur = OPEN_MAX; 251 252 struct rlimit rlim_ofile; 253 254 struct kevent changebuf[64]; 255 size_t changes; 256 257 struct servtab *servtab; 258 259 static ssize_t recvfromto(int, void * restrict, size_t, int, 260 struct sockaddr * restrict, socklen_t * restrict, 261 struct sockaddr * restrict, socklen_t * restrict); 262 static ssize_t sendfromto(int, const void *, size_t, int, 263 const struct sockaddr *, socklen_t, const struct sockaddr *, socklen_t); 264 static void chargen_dg(int, struct servtab *); 265 static void chargen_stream(int, struct servtab *); 266 static void daytime_dg(int, struct servtab *); 267 static void daytime_stream(int, struct servtab *); 268 static void discard_dg(int, struct servtab *); 269 static void discard_stream(int, struct servtab *); 270 static void echo_dg(int, struct servtab *); 271 static void echo_stream(int, struct servtab *); 272 __dead static void goaway(void); 273 static void machtime_dg(int, struct servtab *); 274 static void machtime_stream(int, struct servtab *); 275 static void reapchild(void); 276 static void retry(void); 277 static void run_service(int, struct servtab *, int); 278 static void tcpmux(int, struct servtab *); 279 __dead static void usage(void); 280 static void bump_nofile(void); 281 static void inetd_setproctitle(char *, int); 282 static void initring(void); 283 static uint32_t machtime(void); 284 static int port_good_dg(struct sockaddr *); 285 static int dg_broadcast(struct in_addr *); 286 static int my_kevent(const struct kevent *, size_t, struct kevent *, size_t); 287 static struct kevent *allocchange(void); 288 static int get_line(int, char *, int); 289 static void spawn(struct servtab *, int); 290 291 static void suspend_sep(struct servtab *); 292 static void resume_sep(struct servtab *); 293 294 static void add_child(struct servtab *, pid_t); 295 static void remove_child(struct servtab *, pid_t); 296 297 struct biltin { 298 const char *bi_service; /* internally provided service name */ 299 int bi_socktype; /* type of socket supported */ 300 short bi_fork; /* 1 if should fork before call */ 301 short bi_wait; /* 1 if should wait for child */ 302 void (*bi_fn)(int, struct servtab *); 303 /* function which performs it */ 304 } biltins[] = { 305 /* Echo received data */ 306 { "echo", SOCK_STREAM, true, false, echo_stream }, 307 { "echo", SOCK_DGRAM, false, false, echo_dg }, 308 309 /* Internet /dev/null */ 310 { "discard", SOCK_STREAM, true, false, discard_stream }, 311 { "discard", SOCK_DGRAM, false, false, discard_dg }, 312 313 /* Return 32 bit time since 1970 */ 314 { "time", SOCK_STREAM, false, false, machtime_stream }, 315 { "time", SOCK_DGRAM, false, false, machtime_dg }, 316 317 /* Return human-readable time */ 318 { "daytime", SOCK_STREAM, false, false, daytime_stream }, 319 { "daytime", SOCK_DGRAM, false, false, daytime_dg }, 320 321 /* Familiar character generator */ 322 { "chargen", SOCK_STREAM, true, false, chargen_stream }, 323 { "chargen", SOCK_DGRAM, false, false, chargen_dg }, 324 325 { "tcpmux", SOCK_STREAM, true, false, tcpmux } 326 }; 327 328 /* list of "bad" ports. I.e. ports that are most obviously used for 329 * "cycling packets" denial of service attacks. See /etc/services. 330 * List must end with port number "0". 331 */ 332 333 u_int16_t bad_ports[] = { 7, 9, 13, 19, 37, 0 }; 334 335 336 #define NUMINT (sizeof(intab) / sizeof(struct inent)) 337 const char *CONFIG = _PATH_INETDCONF; 338 339 static int my_signals[] = 340 { SIGALRM, SIGHUP, SIGCHLD, SIGTERM, SIGINT, SIGPIPE }; 341 342 int 343 main(int argc, char *argv[]) 344 { 345 int ch, n, reload = 1; 346 347 while ((ch = getopt(argc, argv, 348 #ifdef LIBWRAP 349 "dfl" 350 #else 351 "df" 352 #endif 353 )) != -1) 354 switch(ch) { 355 case 'd': 356 foreground = true; 357 debug = true; 358 options |= SO_DEBUG; 359 break; 360 case 'f': 361 foreground = true; 362 break; 363 #ifdef LIBWRAP 364 case 'l': 365 lflag = true; 366 break; 367 #endif 368 case '?': 369 default: 370 usage(); 371 } 372 argc -= optind; 373 argv += optind; 374 375 if (argc > 0) 376 CONFIG = argv[0]; 377 378 if (!foreground) 379 daemon(0, 0); 380 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON); 381 pidfile(NULL); 382 383 kq = kqueue(); 384 if (kq < 0) { 385 syslog(LOG_ERR, "kqueue: %m"); 386 return (EXIT_FAILURE); 387 } 388 389 if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) { 390 syslog(LOG_ERR, "getrlimit: %m"); 391 } else { 392 rlim_ofile_cur = rlim_ofile.rlim_cur; 393 if (rlim_ofile_cur == RLIM_INFINITY) /* ! */ 394 rlim_ofile_cur = OPEN_MAX; 395 } 396 397 for (n = 0; n < (int)__arraycount(my_signals); n++) { 398 int signum; 399 400 signum = my_signals[n]; 401 if (signum != SIGCHLD) 402 (void) signal(signum, SIG_IGN); 403 404 if (signum != SIGPIPE) { 405 struct kevent *ev; 406 407 ev = allocchange(); 408 EV_SET(ev, signum, EVFILT_SIGNAL, EV_ADD | EV_ENABLE, 409 0, 0, 0); 410 } 411 } 412 413 for (;;) { 414 int ctrl; 415 struct kevent eventbuf[64], *ev; 416 struct servtab *sep; 417 418 if (reload) { 419 reload = false; 420 config_root(); 421 } 422 423 n = my_kevent(changebuf, changes, eventbuf, __arraycount(eventbuf)); 424 changes = 0; 425 426 for (ev = eventbuf; n > 0; ev++, n--) { 427 if (ev->filter == EVFILT_SIGNAL) { 428 switch (ev->ident) { 429 case SIGALRM: 430 retry(); 431 break; 432 case SIGCHLD: 433 reapchild(); 434 break; 435 case SIGTERM: 436 case SIGINT: 437 goaway(); 438 break; 439 case SIGHUP: 440 reload = true; 441 break; 442 } 443 continue; 444 } 445 if (ev->filter != EVFILT_READ) 446 continue; 447 sep = (struct servtab *)ev->udata; 448 /* Paranoia */ 449 if ((int)ev->ident != sep->se_fd) 450 continue; 451 DPRINTF(SERV_FMT ": service requested" , SERV_PARAMS(sep)); 452 if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) { 453 /* XXX here do the libwrap check-before-accept*/ 454 ctrl = accept(sep->se_fd, NULL, NULL); 455 DPRINTF(SERV_FMT ": accept, ctrl fd %d", 456 SERV_PARAMS(sep), ctrl); 457 if (ctrl < 0) { 458 if (errno != EINTR && errno != EBADF) 459 syslog(LOG_WARNING, 460 SERV_FMT ": accept: %m", 461 SERV_PARAMS(sep)); 462 continue; 463 } 464 sep->se_accept_count++; 465 if (sep->se_accept_max != SERVTAB_UNSPEC_SIZE_T && 466 sep->se_accept_count >= sep->se_accept_max) 467 suspend_sep(sep); 468 } else 469 ctrl = sep->se_fd; 470 spawn(sep, ctrl); 471 } 472 } 473 } 474 475 static void 476 spawn(struct servtab *sep, int ctrl) 477 { 478 int dofork; 479 pid_t pid; 480 481 pid = 0; 482 #ifdef LIBWRAP_INTERNAL 483 dofork = true; 484 #else 485 dofork = (sep->se_bi == NULL || sep->se_bi->bi_fork); 486 #endif 487 if (dofork) { 488 if (rl_process(sep, ctrl)) { 489 return; 490 } 491 pid = fork(); 492 if (pid < 0) { 493 syslog(LOG_ERR, "fork: %m"); 494 if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) { 495 sep->se_accept_count--; 496 if (sep->se_accept_max != SERVTAB_UNSPEC_SIZE_T && 497 sep->se_accept_count < sep->se_accept_max) 498 resume_sep(sep); 499 close(ctrl); 500 } 501 sleep(1); 502 return; 503 } 504 if (pid != 0 && sep->se_accept_children != NULL) 505 add_child(sep, pid); 506 if (pid != 0 && sep->se_wait != 0) { 507 struct kevent *ev; 508 509 sep->se_wait = pid; 510 ev = allocchange(); 511 EV_SET(ev, sep->se_fd, EVFILT_READ, 512 EV_DELETE, 0, 0, 0); 513 } 514 if (pid == 0) { 515 size_t n; 516 517 for (n = 0; n < __arraycount(my_signals); n++) 518 (void) signal(my_signals[n], SIG_DFL); 519 /* Don't put services in terminal session */ 520 if (foreground) 521 setsid(); 522 } 523 } 524 if (pid == 0) { 525 run_service(ctrl, sep, dofork); 526 if (dofork) 527 exit(EXIT_SUCCESS); 528 } 529 if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) 530 close(ctrl); 531 } 532 533 static void 534 run_service(int ctrl, struct servtab *sep, int didfork) 535 { 536 struct passwd *pwd; 537 struct group *grp = NULL; /* XXX gcc */ 538 char buf[NI_MAXSERV]; 539 struct servtab *s; 540 #ifdef LIBWRAP 541 char abuf[BUFSIZ]; 542 struct request_info req; 543 int denied; 544 char *service = NULL; /* XXX gcc */ 545 #endif 546 547 #ifdef LIBWRAP 548 #ifndef LIBWRAP_INTERNAL 549 if (sep->se_bi == 0) 550 #endif 551 if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) { 552 request_init(&req, RQ_DAEMON, sep->se_argv[0] != NULL ? 553 sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL); 554 fromhost(&req); 555 denied = hosts_access(&req) == 0; 556 if (denied || lflag) { 557 if (getnameinfo(&sep->se_ctrladdr, 558 (socklen_t)sep->se_ctrladdr.sa_len, NULL, 0, 559 buf, sizeof(buf), 0) != 0) { 560 /* shouldn't happen */ 561 (void)snprintf(buf, sizeof buf, "%d", 562 ntohs(sep->se_ctrladdr_in.sin_port)); 563 } 564 service = buf; 565 if (req.client->sin != NULL) { 566 sockaddr_snprintf(abuf, sizeof(abuf), "%a", 567 req.client->sin); 568 } else { 569 strcpy(abuf, "(null)"); 570 } 571 } 572 if (denied) { 573 syslog(deny_severity, 574 "refused connection from %.500s(%s), service %s (%s)", 575 eval_client(&req), abuf, service, sep->se_proto); 576 goto reject; 577 } 578 if (lflag) { 579 syslog(allow_severity, 580 "connection from %.500s(%s), service %s (%s)", 581 eval_client(&req), abuf, service, sep->se_proto); 582 } 583 } 584 #endif /* LIBWRAP */ 585 586 if (sep->se_bi != NULL) { 587 if (didfork) { 588 for (s = servtab; s != NULL; s = s->se_next) 589 if (s->se_fd != -1 && s->se_fd != ctrl) { 590 close(s->se_fd); 591 s->se_fd = -1; 592 } 593 } 594 (*sep->se_bi->bi_fn)(ctrl, sep); 595 } else { 596 if ((pwd = getpwnam(sep->se_user)) == NULL) { 597 syslog(LOG_ERR, "%s/%s: %s: No such user", 598 sep->se_service, sep->se_proto, sep->se_user); 599 goto reject; 600 } 601 if (sep->se_group != NULL && 602 (grp = getgrnam(sep->se_group)) == NULL) { 603 syslog(LOG_ERR, "%s/%s: %s: No such group", 604 sep->se_service, sep->se_proto, sep->se_group); 605 goto reject; 606 } 607 if (pwd->pw_uid != 0) { 608 if (sep->se_group != NULL) 609 pwd->pw_gid = grp->gr_gid; 610 if (setgid(pwd->pw_gid) < 0) { 611 syslog(LOG_ERR, 612 "%s/%s: can't set gid %d: %m", sep->se_service, 613 sep->se_proto, pwd->pw_gid); 614 goto reject; 615 } 616 (void) initgroups(pwd->pw_name, 617 pwd->pw_gid); 618 if (setuid(pwd->pw_uid) < 0) { 619 syslog(LOG_ERR, 620 "%s/%s: can't set uid %d: %m", sep->se_service, 621 sep->se_proto, pwd->pw_uid); 622 goto reject; 623 } 624 } else if (sep->se_group != NULL) { 625 (void) setgid((gid_t)grp->gr_gid); 626 } 627 DPRINTF("%d execl %s", 628 getpid(), sep->se_server); 629 /* Set our control descriptor to not close-on-exec... */ 630 if (fcntl(ctrl, F_SETFD, 0) < 0) 631 syslog(LOG_ERR, "fcntl (%d, F_SETFD, 0): %m", ctrl); 632 /* ...and dup it to stdin, stdout, and stderr. */ 633 if (ctrl != 0) { 634 dup2(ctrl, 0); 635 close(ctrl); 636 ctrl = 0; 637 } 638 dup2(0, 1); 639 dup2(0, 2); 640 if (rlim_ofile.rlim_cur != rlim_ofile_cur && 641 setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) 642 syslog(LOG_ERR, "setrlimit: %m"); 643 execv(sep->se_server, sep->se_argv); 644 syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server); 645 reject: 646 if (sep->se_socktype != SOCK_STREAM) 647 recv(ctrl, buf, sizeof (buf), 0); 648 _exit(EXIT_FAILURE); 649 } 650 } 651 652 static void 653 add_child(struct servtab *sep, pid_t pid) 654 { 655 if (sep->se_accept_max != SERVTAB_UNSPEC_SIZE_T && 656 sep->se_accept_count <= sep->se_accept_max && 657 sep->se_accept_count > 0) 658 sep->se_accept_children[sep->se_accept_count-1] = pid; 659 } 660 661 static void 662 remove_child(struct servtab *sep, pid_t pid) 663 { 664 size_t i, tail; 665 666 for (i=0; i<sep->se_accept_count; ++i) { 667 if (sep->se_accept_children[i] != pid) 668 continue; 669 670 if (sep->se_accept_max != SERVTAB_UNSPEC_SIZE_T && 671 sep->se_accept_count <= sep->se_accept_max) 672 resume_sep(sep); 673 674 sep->se_accept_count--; 675 tail = sep->se_accept_count - i; 676 677 memmove(&sep->se_accept_children[i], 678 &sep->se_accept_children[i+1], 679 tail * sizeof(pid_t)); 680 681 break; 682 } 683 } 684 685 static void 686 reapchild(void) 687 { 688 int status; 689 pid_t pid; 690 struct servtab *sep; 691 692 for (;;) { 693 pid = wait3(&status, WNOHANG, NULL); 694 if (pid <= 0) 695 break; 696 DPRINTF("%d reaped, status %#x", pid, status); 697 for (sep = servtab; sep != NULL; sep = sep->se_next) { 698 if (sep->se_wait == pid) { 699 struct kevent *ev; 700 701 if (WIFEXITED(status) && WEXITSTATUS(status)) 702 syslog(LOG_WARNING, 703 "%s: exit status %u", 704 sep->se_server, WEXITSTATUS(status)); 705 else if (WIFSIGNALED(status)) 706 syslog(LOG_WARNING, 707 "%s: exit signal %u", 708 sep->se_server, WTERMSIG(status)); 709 sep->se_wait = 1; 710 ev = allocchange(); 711 EV_SET(ev, sep->se_fd, EVFILT_READ, 712 EV_ADD | EV_ENABLE, 0, 0, (intptr_t)sep); 713 DPRINTF("restored %s, fd %d", 714 sep->se_service, sep->se_fd); 715 } 716 717 if (sep->se_accept_children != NULL) 718 remove_child(sep, pid); 719 } 720 } 721 } 722 723 static void 724 retry(void) 725 { 726 struct servtab *sep; 727 728 timingout = false; 729 for (sep = servtab; sep != NULL; sep = sep->se_next) { 730 if (sep->se_fd == -1 && !ISMUX(sep)) { 731 switch (sep->se_family) { 732 case AF_LOCAL: 733 case AF_INET: 734 #ifdef INET6 735 case AF_INET6: 736 #endif 737 setup(sep); 738 if (sep->se_fd >= 0 && isrpcservice(sep)) 739 register_rpc(sep); 740 break; 741 } 742 } 743 } 744 } 745 746 static void 747 goaway(void) 748 { 749 struct servtab *sep; 750 751 for (sep = servtab; sep != NULL; sep = sep->se_next) { 752 if (sep->se_fd == -1) 753 continue; 754 755 switch (sep->se_family) { 756 case AF_LOCAL: 757 (void)unlink(sep->se_service); 758 break; 759 case AF_INET: 760 #ifdef INET6 761 case AF_INET6: 762 #endif 763 if (sep->se_wait == 1 && isrpcservice(sep)) 764 unregister_rpc(sep); 765 break; 766 } 767 (void)close(sep->se_fd); 768 sep->se_fd = -1; 769 } 770 771 DPRINTF("Going away."); 772 773 exit(EXIT_SUCCESS); 774 } 775 776 void 777 setup(struct servtab *sep) 778 { 779 int on = 1; 780 #ifdef INET6 781 int off = 0; 782 #endif 783 struct kevent *ev; 784 785 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { 786 DPRINTF("socket failed on " SERV_FMT ": %s", 787 SERV_PARAMS(sep), strerror(errno)); 788 syslog(LOG_ERR, "%s/%s: socket: %m", 789 sep->se_service, sep->se_proto); 790 return; 791 } 792 /* Set all listening sockets to close-on-exec. */ 793 if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) { 794 syslog(LOG_ERR, SERV_FMT ": fcntl(F_SETFD, FD_CLOEXEC): %m", 795 SERV_PARAMS(sep)); 796 close(sep->se_fd); 797 sep->se_fd = -1; 798 return; 799 } 800 801 #define turnon(fd, opt) \ 802 setsockopt(fd, SOL_SOCKET, opt, &on, (socklen_t)sizeof(on)) 803 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) && 804 turnon(sep->se_fd, SO_DEBUG) < 0) 805 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m"); 806 if (turnon(sep->se_fd, SO_REUSEADDR) < 0) 807 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m"); 808 #undef turnon 809 810 /* Set the socket buffer sizes, if specified. */ 811 if (sep->se_sndbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET, 812 SO_SNDBUF, &sep->se_sndbuf, (socklen_t)sizeof(sep->se_sndbuf)) < 0) 813 syslog(LOG_ERR, "setsockopt (SO_SNDBUF %d): %m", 814 sep->se_sndbuf); 815 if (sep->se_rcvbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET, 816 SO_RCVBUF, &sep->se_rcvbuf, (socklen_t)sizeof(sep->se_rcvbuf)) < 0) 817 syslog(LOG_ERR, "setsockopt (SO_RCVBUF %d): %m", 818 sep->se_rcvbuf); 819 #ifdef INET6 820 if (sep->se_family == AF_INET6) { 821 int *v; 822 v = (sep->se_type == FAITH_TYPE) ? &on : &off; 823 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, 824 v, (socklen_t)sizeof(*v)) < 0) 825 syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m"); 826 } 827 #endif 828 #ifdef IPSEC 829 /* Avoid setting a policy if a policy specifier doesn't exist. */ 830 if (sep->se_policy != NULL) { 831 int e = ipsecsetup(sep->se_family, sep->se_fd, sep->se_policy); 832 if (e < 0) { 833 syslog(LOG_ERR, SERV_FMT ": ipsec setup failed", 834 SERV_PARAMS(sep)); 835 (void)close(sep->se_fd); 836 sep->se_fd = -1; 837 return; 838 } 839 } 840 #endif 841 842 if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) { 843 DPRINTF(SERV_FMT ": bind failed: %s", 844 SERV_PARAMS(sep), strerror(errno)); 845 syslog(LOG_ERR, SERV_FMT ": bind: %m", 846 SERV_PARAMS(sep)); 847 (void) close(sep->se_fd); 848 sep->se_fd = -1; 849 if (!timingout) { 850 timingout = true; 851 alarm(RETRYTIME); 852 } 853 return; 854 } 855 if (sep->se_socktype == SOCK_STREAM) 856 listen(sep->se_fd, 128); 857 858 /* for internal dgram, setsockopt() is required for recvfromto() */ 859 if (sep->se_socktype == SOCK_DGRAM && sep->se_bi != NULL) { 860 switch (sep->se_family) { 861 case AF_INET: 862 if (setsockopt(sep->se_fd, IPPROTO_IP, 863 IP_RECVDSTADDR, &on, sizeof(on)) < 0) 864 syslog(LOG_ERR, 865 "setsockopt (IP_RECVDSTADDR): %m"); 866 break; 867 #ifdef INET6 868 case AF_INET6: 869 if (setsockopt(sep->se_fd, IPPROTO_IPV6, 870 IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) 871 syslog(LOG_ERR, 872 "setsockopt (IPV6_RECVPKTINFO): %m"); 873 break; 874 #endif 875 } 876 } 877 878 /* Allocate list of children */ 879 if (sep->se_accept_max != SERVTAB_UNSPEC_SIZE_T && 880 sep->se_accept_max > 0) { 881 sep->se_accept_children = calloc(sep->se_accept_max, 882 sizeof(pid_t)); 883 if (sep->se_accept_children == NULL) { 884 syslog(LOG_ERR, SERV_FMT ": accept_max too large: %m", 885 SERV_PARAMS(sep)); 886 sep->se_accept_max = SERVTAB_UNSPEC_SIZE_T; 887 } 888 } 889 890 /* Set the accept filter, if specified. To be done after listen.*/ 891 if (sep->se_accf.af_name[0] != 0 && setsockopt(sep->se_fd, SOL_SOCKET, 892 SO_ACCEPTFILTER, &sep->se_accf, 893 (socklen_t)sizeof(sep->se_accf)) < 0) 894 syslog(LOG_ERR, "setsockopt(SO_ACCEPTFILTER %s): %m", 895 sep->se_accf.af_name); 896 897 ev = allocchange(); 898 EV_SET(ev, sep->se_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 899 (intptr_t)sep); 900 if (sep->se_fd > maxsock) { 901 maxsock = sep->se_fd; 902 if (maxsock > (int)(rlim_ofile_cur - FD_MARGIN)) 903 bump_nofile(); 904 } 905 DPRINTF(SERV_FMT ": registered on fd %d", SERV_PARAMS(sep), sep->se_fd); 906 } 907 908 /* 909 * Finish with a service and its socket. 910 */ 911 void 912 close_sep(struct servtab *sep) 913 { 914 915 if (sep->se_fd >= 0) { 916 (void) close(sep->se_fd); 917 sep->se_fd = -1; 918 } 919 sep->se_count = 0; 920 if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) { 921 rl_clear_ip_list(sep); 922 } 923 } 924 925 /* 926 * Suspend service by ignoring connect events 927 */ 928 static void 929 suspend_sep(struct servtab *sep) 930 { 931 struct kevent *ev; 932 933 if (sep->se_accept_count == sep->se_accept_max) { 934 ev = allocchange(); 935 EV_SET(ev, sep->se_fd, EVFILT_READ, EV_DISABLE, 0, 0, 936 (intptr_t)sep); 937 } 938 939 if (sep->se_accept_mark == 0) 940 syslog(LOG_ERR, SERV_FMT 941 ": accept_max reached (%zu); service suspended", 942 SERV_PARAMS(sep), 943 sep->se_accept_max); 944 945 if (sep->se_accept_max > 0) 946 sep->se_accept_mark = sep->se_accept_max - 1; 947 else 948 sep->se_accept_mark = 0; 949 } 950 951 /* 952 * Resume service by listening to connect events 953 */ 954 static void 955 resume_sep(struct servtab *sep) 956 { 957 struct kevent *ev; 958 959 if (sep->se_accept_count == sep->se_accept_max) { 960 ev = allocchange(); 961 EV_SET(ev, sep->se_fd, EVFILT_READ, EV_ENABLE, 0, 0, 962 (intptr_t)sep); 963 } 964 965 if (sep->se_accept_mark == 0 || 966 sep->se_accept_count < sep->se_accept_mark) { 967 syslog(LOG_ERR, SERV_FMT 968 ": fell below accept_max (%zu); service resumed", 969 SERV_PARAMS(sep), 970 sep->se_accept_max); 971 sep->se_accept_mark = 0; 972 } 973 } 974 975 void 976 register_rpc(struct servtab *sep) 977 { 978 #ifdef RPC 979 struct netbuf nbuf; 980 struct sockaddr_storage ss; 981 struct netconfig *nconf; 982 socklen_t socklen; 983 int n; 984 985 if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) { 986 syslog(LOG_ERR, "%s: getnetconfigent failed", 987 sep->se_proto); 988 return; 989 } 990 socklen = sizeof ss; 991 if (getsockname(sep->se_fd, (struct sockaddr *)(void *)&ss, &socklen) < 0) { 992 syslog(LOG_ERR, SERV_FMT ": getsockname: %m", 993 SERV_PARAMS(sep)); 994 return; 995 } 996 997 nbuf.buf = &ss; 998 nbuf.len = ss.ss_len; 999 nbuf.maxlen = sizeof (struct sockaddr_storage); 1000 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1001 DPRINTF("rpcb_set: %u %d %s %s", 1002 sep->se_rpcprog, n, nconf->nc_netid, 1003 taddr2uaddr(nconf, &nbuf)); 1004 (void)rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf); 1005 if (rpcb_set((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf, &nbuf) == 0) 1006 syslog(LOG_ERR, "rpcb_set: %u %d %s %s%s", 1007 sep->se_rpcprog, n, nconf->nc_netid, 1008 taddr2uaddr(nconf, &nbuf), clnt_spcreateerror("")); 1009 } 1010 #endif /* RPC */ 1011 } 1012 1013 void 1014 unregister_rpc(struct servtab *sep) 1015 { 1016 #ifdef RPC 1017 int n; 1018 struct netconfig *nconf; 1019 1020 if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) { 1021 syslog(LOG_ERR, "%s: getnetconfigent failed", 1022 sep->se_proto); 1023 return; 1024 } 1025 1026 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { 1027 DPRINTF("rpcb_unset(%u, %d, %s)", 1028 sep->se_rpcprog, n, nconf->nc_netid); 1029 if (rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf) == 0) 1030 syslog(LOG_ERR, "rpcb_unset(%u, %d, %s) failed\n", 1031 sep->se_rpcprog, n, nconf->nc_netid); 1032 } 1033 #endif /* RPC */ 1034 } 1035 1036 static void 1037 inetd_setproctitle(char *a, int s) 1038 { 1039 socklen_t size; 1040 struct sockaddr_storage ss; 1041 char hbuf[NI_MAXHOST]; 1042 const char *hp; 1043 struct sockaddr *sa; 1044 1045 size = sizeof(ss); 1046 sa = (struct sockaddr *)(void *)&ss; 1047 if (getpeername(s, sa, &size) == 0) { 1048 if (getnameinfo(sa, size, hbuf, (socklen_t)sizeof(hbuf), NULL, 1049 0, niflags) != 0) 1050 hp = "?"; 1051 else 1052 hp = hbuf; 1053 setproctitle("-%s [%s]", a, hp); 1054 } else 1055 setproctitle("-%s", a); 1056 } 1057 1058 static void 1059 bump_nofile(void) 1060 { 1061 #define FD_CHUNK 32 1062 struct rlimit rl; 1063 1064 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { 1065 syslog(LOG_ERR, "getrlimit: %m"); 1066 return; 1067 } 1068 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK); 1069 if (rl.rlim_cur <= rlim_ofile_cur) { 1070 syslog(LOG_ERR, 1071 "bump_nofile: cannot extend file limit, max = %d", 1072 (int)rl.rlim_cur); 1073 return; 1074 } 1075 1076 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { 1077 syslog(LOG_ERR, "setrlimit: %m"); 1078 return; 1079 } 1080 1081 rlim_ofile_cur = rl.rlim_cur; 1082 return; 1083 } 1084 1085 /* 1086 * In order to get the destination address (`to') with recvfromto(), 1087 * IP_RECVDSTADDR or IP_RECVPKTINFO for AF_INET, or IPV6_RECVPKTINFO 1088 * for AF_INET6, must be enabled with setsockopt(2). 1089 * 1090 * .sin_port and .sin6_port in 'to' are always stored as zero. 1091 * If necessary, extract them using getsockname(2). 1092 */ 1093 static ssize_t 1094 recvfromto(int s, void * restrict buf, size_t len, int flags, 1095 struct sockaddr * restrict from, socklen_t * restrict fromlen, 1096 struct sockaddr * restrict to, socklen_t * restrict tolen) 1097 { 1098 struct msghdr msg; 1099 struct iovec vec; 1100 struct cmsghdr *cmsg; 1101 struct sockaddr_storage ss; 1102 char cmsgbuf[1024]; 1103 ssize_t rc; 1104 1105 if (to == NULL) 1106 return recvfrom(s, buf, len, flags, from, fromlen); 1107 1108 if (tolen == NULL || fromlen == NULL) { 1109 errno = EFAULT; 1110 return -1; 1111 } 1112 1113 vec.iov_base = buf; 1114 vec.iov_len = len; 1115 msg.msg_name = from; 1116 msg.msg_namelen = *fromlen; 1117 msg.msg_iov = &vec; 1118 msg.msg_iovlen = 1; 1119 msg.msg_control = cmsgbuf; 1120 msg.msg_controllen = sizeof(cmsgbuf); 1121 1122 rc = recvmsg(s, &msg, flags); 1123 if (rc < 0) 1124 return rc; 1125 *fromlen = msg.msg_namelen; 1126 1127 memset(&ss, 0, sizeof(ss)); 1128 for (cmsg = (struct cmsghdr *)CMSG_FIRSTHDR(&msg); cmsg != NULL; 1129 cmsg = (struct cmsghdr *)CMSG_NXTHDR(&msg, cmsg)) { 1130 if (cmsg->cmsg_level == IPPROTO_IP && 1131 cmsg->cmsg_type == IP_RECVDSTADDR) { 1132 struct in_addr *dst = (struct in_addr *)CMSG_DATA(cmsg); 1133 struct sockaddr_in *sin = (struct sockaddr_in *)&ss; 1134 1135 sin->sin_len = sizeof(*sin); 1136 sin->sin_family = AF_INET; 1137 sin->sin_addr = *dst; 1138 break; 1139 } 1140 if (cmsg->cmsg_level == IPPROTO_IP && 1141 cmsg->cmsg_type == IP_PKTINFO) { 1142 struct in_pktinfo *pi = 1143 (struct in_pktinfo *)CMSG_DATA(cmsg); 1144 struct sockaddr_in *sin = (struct sockaddr_in *)&ss; 1145 1146 sin->sin_len = sizeof(*sin); 1147 sin->sin_family = AF_INET; 1148 sin->sin_addr = pi->ipi_addr; 1149 break; 1150 } 1151 #ifdef INET6 1152 if (cmsg->cmsg_level == IPPROTO_IPV6 && 1153 cmsg->cmsg_type == IPV6_PKTINFO) { 1154 struct in6_pktinfo *pi6 = 1155 (struct in6_pktinfo *)CMSG_DATA(cmsg); 1156 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&ss; 1157 1158 sin6->sin6_len = sizeof(*sin6); 1159 sin6->sin6_family = AF_INET6; 1160 sin6->sin6_addr = pi6->ipi6_addr; 1161 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) || 1162 IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) 1163 sin6->sin6_scope_id = pi6->ipi6_ifindex; 1164 else 1165 sin6->sin6_scope_id = 0; 1166 break; 1167 } 1168 #endif /* INET6 */ 1169 } 1170 1171 socklen_t sslen = (*tolen < ss.ss_len) ? *tolen : ss.ss_len; 1172 if (sslen > 0) 1173 memcpy(to, &ss, sslen); 1174 *tolen = sslen; 1175 1176 return rc; 1177 } 1178 1179 /* 1180 * When sending, the source port is selected as the one bind(2)'ed 1181 * to the socket. 1182 * .sin_port and .sin6_port in `from' are always ignored. 1183 */ 1184 static ssize_t 1185 sendfromto(int s, const void *buf, size_t len, int flags, 1186 const struct sockaddr *from, socklen_t fromlen, 1187 const struct sockaddr *to, socklen_t tolen) 1188 { 1189 struct msghdr msg; 1190 struct iovec vec; 1191 struct cmsghdr *cmsg; 1192 char cmsgbuf[256]; 1193 __CTASSERT(sizeof(cmsgbuf) > CMSG_SPACE(sizeof(struct in_pktinfo))); 1194 #ifdef INET6 1195 __CTASSERT(sizeof(cmsgbuf) > CMSG_SPACE(sizeof(struct in6_pktinfo))); 1196 #endif 1197 1198 if (from == NULL || fromlen == 0) 1199 return sendto(s, buf, len, flags, to, tolen); 1200 1201 vec.iov_base = __UNCONST(buf); 1202 vec.iov_len = len; 1203 msg.msg_name = __UNCONST(to); 1204 msg.msg_namelen = tolen; 1205 msg.msg_iov = &vec; 1206 msg.msg_iovlen = 1; 1207 msg.msg_control = cmsgbuf; 1208 msg.msg_controllen = 0; 1209 1210 if (fromlen < 2) { /* sa_len + sa_family */ 1211 errno = EINVAL; 1212 return -1; 1213 } 1214 1215 cmsg = (struct cmsghdr *)cmsgbuf; 1216 if (from->sa_family == AF_INET) { 1217 const struct sockaddr_in *from4 = 1218 (const struct sockaddr_in *)from; 1219 struct in_pktinfo *pi; 1220 1221 if (fromlen != sizeof(struct sockaddr_in) || 1222 from4->sin_family != AF_INET) { 1223 errno = EINVAL; 1224 return -1; 1225 } 1226 1227 msg.msg_controllen += CMSG_SPACE(sizeof(struct in_pktinfo)); 1228 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 1229 cmsg->cmsg_level = IPPROTO_IP; 1230 cmsg->cmsg_type = IP_PKTINFO; 1231 1232 pi = (struct in_pktinfo *)CMSG_DATA(cmsg); 1233 pi->ipi_addr = from4->sin_addr; 1234 pi->ipi_ifindex = 0; 1235 #ifdef INET6 1236 } else if (from->sa_family == AF_INET6) { 1237 const struct sockaddr_in6 *from6 = 1238 (const struct sockaddr_in6 *)from; 1239 struct in6_pktinfo *pi6; 1240 1241 if (fromlen != sizeof(struct sockaddr_in6) || 1242 from6->sin6_family != AF_INET6) { 1243 errno = EINVAL; 1244 return -1; 1245 } 1246 1247 msg.msg_controllen += CMSG_SPACE(sizeof(struct in6_pktinfo)); 1248 cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); 1249 cmsg->cmsg_level = IPPROTO_IPV6; 1250 cmsg->cmsg_type = IPV6_PKTINFO; 1251 1252 pi6 = (struct in6_pktinfo *)CMSG_DATA(cmsg); 1253 pi6->ipi6_addr = from6->sin6_addr; 1254 if (IN6_IS_ADDR_LINKLOCAL(&from6->sin6_addr) || 1255 IN6_IS_ADDR_MC_LINKLOCAL(&from6->sin6_addr)) { 1256 pi6->ipi6_ifindex = from6->sin6_scope_id; 1257 } else { 1258 pi6->ipi6_ifindex = 0; 1259 } 1260 #endif /* INET6 */ 1261 } else { 1262 return sendto(s, buf, len, flags, to, tolen); 1263 } 1264 1265 return sendmsg(s, &msg, flags); 1266 } 1267 1268 /* 1269 * Internet services provided internally by inetd: 1270 */ 1271 #define BUFSIZE 4096 1272 1273 /* ARGSUSED */ 1274 static void 1275 echo_stream(int s, struct servtab *sep) /* Echo service -- echo data back */ 1276 { 1277 char buffer[BUFSIZE]; 1278 ssize_t i; 1279 1280 inetd_setproctitle(sep->se_service, s); 1281 while ((i = read(s, buffer, sizeof(buffer))) > 0 && 1282 write(s, buffer, (size_t)i) > 0) 1283 continue; 1284 } 1285 1286 /* ARGSUSED */ 1287 static void 1288 echo_dg(int s, struct servtab *sep) /* Echo service -- echo data back */ 1289 { 1290 char buffer[BUFSIZE]; 1291 ssize_t i; 1292 socklen_t rsize, lsize; 1293 struct sockaddr_storage remote, local; 1294 struct sockaddr *lsa, *rsa; 1295 1296 rsa = (struct sockaddr *)(void *)&remote; 1297 lsa = (struct sockaddr *)(void *)&local; 1298 rsize = sizeof(remote); 1299 lsize = sizeof(local); 1300 if ((i = recvfromto(s, buffer, sizeof(buffer), 0, 1301 rsa, &rsize, lsa, &lsize)) < 0) 1302 return; 1303 if (port_good_dg(rsa)) 1304 (void) sendfromto(s, buffer, (size_t)i, 0, 1305 lsa, lsize, rsa, rsize); 1306 } 1307 1308 /* ARGSUSED */ 1309 static void 1310 discard_stream(int s, struct servtab *sep) /* Discard service -- ignore data */ 1311 { 1312 char buffer[BUFSIZE]; 1313 1314 inetd_setproctitle(sep->se_service, s); 1315 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || 1316 errno == EINTR) 1317 ; 1318 } 1319 1320 /* ARGSUSED */ 1321 static void 1322 discard_dg(int s, struct servtab *sep) /* Discard service -- ignore data */ 1323 1324 { 1325 char buffer[BUFSIZE]; 1326 1327 (void) read(s, buffer, sizeof(buffer)); 1328 } 1329 1330 #define LINESIZ 72 1331 char ring[128]; 1332 char *endring; 1333 1334 static void 1335 initring(void) 1336 { 1337 int i; 1338 1339 endring = ring; 1340 1341 for (i = 0; i <= 128; ++i) 1342 if (isprint(i)) 1343 *endring++ = (char)i; 1344 } 1345 1346 /* ARGSUSED */ 1347 static void 1348 chargen_stream(int s, struct servtab *sep) /* Character generator */ 1349 { 1350 size_t len; 1351 char *rs, text[LINESIZ+2]; 1352 1353 inetd_setproctitle(sep->se_service, s); 1354 1355 if (endring == NULL) { 1356 initring(); 1357 rs = ring; 1358 } 1359 1360 text[LINESIZ] = '\r'; 1361 text[LINESIZ + 1] = '\n'; 1362 for (rs = ring;;) { 1363 if ((len = (size_t)(endring - rs)) >= LINESIZ) 1364 memmove(text, rs, LINESIZ); 1365 else { 1366 memmove(text, rs, len); 1367 memmove(text + len, ring, LINESIZ - len); 1368 } 1369 if (++rs == endring) 1370 rs = ring; 1371 if (write(s, text, sizeof(text)) != sizeof(text)) 1372 break; 1373 } 1374 } 1375 1376 /* ARGSUSED */ 1377 static void 1378 chargen_dg(int s, struct servtab *sep) /* Character generator */ 1379 { 1380 struct sockaddr_storage remote, local; 1381 struct sockaddr *rsa, *lsa; 1382 static char *rs; 1383 size_t len; 1384 socklen_t rsize, lsize; 1385 char text[LINESIZ+2]; 1386 1387 if (endring == 0) { 1388 initring(); 1389 rs = ring; 1390 } 1391 1392 rsa = (struct sockaddr *)(void *)&remote; 1393 lsa = (struct sockaddr *)(void *)&local; 1394 rsize = sizeof(remote); 1395 lsize = sizeof(local); 1396 if (recvfromto(s, text, sizeof(text), 0, 1397 rsa, &rsize, lsa, &lsize) < 0) 1398 return; 1399 1400 if (!port_good_dg(rsa)) 1401 return; 1402 1403 if ((len = (size_t)(endring - rs)) >= LINESIZ) 1404 memmove(text, rs, LINESIZ); 1405 else { 1406 memmove(text, rs, len); 1407 memmove(text + len, ring, LINESIZ - len); 1408 } 1409 if (++rs == endring) 1410 rs = ring; 1411 text[LINESIZ] = '\r'; 1412 text[LINESIZ + 1] = '\n'; 1413 (void) sendfromto(s, text, sizeof(text), 0, lsa, lsize, rsa, rsize); 1414 } 1415 1416 /* 1417 * Return a machine readable date and time, in the form of the 1418 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday 1419 * returns the number of seconds since midnight, Jan 1, 1970, 1420 * we must add 2208988800 seconds to this figure to make up for 1421 * some seventy years Bell Labs was asleep. 1422 */ 1423 1424 static uint32_t 1425 machtime(void) 1426 { 1427 struct timeval tv; 1428 1429 if (gettimeofday(&tv, NULL) < 0) { 1430 DPRINTF("Unable to get time of day"); 1431 return (0); 1432 } 1433 #define OFFSET ((uint32_t)25567 * 24*60*60) 1434 return (htonl((uint32_t)(tv.tv_sec + OFFSET))); 1435 #undef OFFSET 1436 } 1437 1438 /* ARGSUSED */ 1439 static void 1440 machtime_stream(int s, struct servtab *sep) 1441 { 1442 uint32_t result; 1443 1444 result = machtime(); 1445 (void) write(s, &result, sizeof(result)); 1446 } 1447 1448 /* ARGSUSED */ 1449 void 1450 machtime_dg(int s, struct servtab *sep) 1451 { 1452 uint32_t result; 1453 struct sockaddr_storage remote, local; 1454 struct sockaddr *rsa, *lsa; 1455 socklen_t rsize, lsize; 1456 1457 rsa = (struct sockaddr *)(void *)&remote; 1458 lsa = (struct sockaddr *)(void *)&local; 1459 rsize = sizeof(remote); 1460 lsize = sizeof(local); 1461 if (recvfromto(s, &result, sizeof(result), 0, 1462 rsa, &rsize, lsa, &lsize) < 0) 1463 return; 1464 if (!port_good_dg(rsa)) 1465 return; 1466 result = machtime(); 1467 (void)sendfromto(s, &result, sizeof(result), 0, lsa, lsize, rsa, rsize); 1468 } 1469 1470 /* ARGSUSED */ 1471 static void 1472 daytime_stream(int s,struct servtab *sep) 1473 /* Return human-readable time of day */ 1474 { 1475 char buffer[256]; 1476 time_t clk; 1477 int len; 1478 1479 clk = time((time_t *) 0); 1480 1481 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk)); 1482 (void) write(s, buffer, (size_t)len); 1483 } 1484 1485 /* ARGSUSED */ 1486 void 1487 daytime_dg(int s, struct servtab *sep) 1488 /* Return human-readable time of day */ 1489 { 1490 char buffer[256]; 1491 time_t clk; 1492 struct sockaddr_storage remote, local; 1493 struct sockaddr *rsa, *lsa; 1494 socklen_t rsize, lsize; 1495 int len; 1496 1497 clk = time((time_t *) 0); 1498 1499 rsa = (struct sockaddr *)(void *)&remote; 1500 lsa = (struct sockaddr *)(void *)&local; 1501 rsize = sizeof(remote); 1502 lsize = sizeof(local); 1503 if (recvfromto(s, buffer, sizeof(buffer), 0, 1504 rsa, &rsize, lsa, &lsize) < 0) 1505 return; 1506 if (!port_good_dg(rsa)) 1507 return; 1508 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk)); 1509 (void) sendfromto(s, buffer, (size_t)len, 0, lsa, lsize, rsa, rsize); 1510 } 1511 1512 static void 1513 usage(void) 1514 { 1515 #ifdef LIBWRAP 1516 (void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname()); 1517 #else 1518 (void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname()); 1519 #endif 1520 exit(EXIT_FAILURE); 1521 } 1522 1523 1524 /* 1525 * Based on TCPMUX.C by Mark K. Lottor November 1988 1526 * sri-nic::ps:<mkl>tcpmux.c 1527 */ 1528 1529 static int /* # of characters upto \r,\n or \0 */ 1530 get_line(int fd, char *buf, int len) 1531 { 1532 int count = 0; 1533 ssize_t n; 1534 1535 do { 1536 n = read(fd, buf, (size_t)(len - count)); 1537 if (n == 0) 1538 return (count); 1539 if (n < 0) 1540 return (-1); 1541 while (--n >= 0) { 1542 if (*buf == '\r' || *buf == '\n' || *buf == '\0') 1543 return (count); 1544 count++; 1545 buf++; 1546 } 1547 } while (count < len); 1548 return (count); 1549 } 1550 1551 #define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */ 1552 1553 #define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1) 1554 1555 static void 1556 tcpmux(int ctrl, struct servtab *sep) 1557 { 1558 char service[MAX_SERV_LEN+1]; 1559 int len; 1560 1561 /* Get requested service name */ 1562 if ((len = get_line(ctrl, service, MAX_SERV_LEN)) < 0) { 1563 strwrite(ctrl, "-Error reading service name\r\n"); 1564 goto reject; 1565 } 1566 service[len] = '\0'; 1567 1568 DPRINTF("tcpmux: %s: service requested", service); 1569 1570 /* 1571 * Help is a required command, and lists available services, 1572 * one per line. 1573 */ 1574 if (strcasecmp(service, "help") == 0) { 1575 strwrite(ctrl, "+Available services:\r\n"); 1576 strwrite(ctrl, "help\r\n"); 1577 for (sep = servtab; sep != NULL; sep = sep->se_next) { 1578 if (!ISMUX(sep)) 1579 continue; 1580 (void)write(ctrl, sep->se_service, 1581 strlen(sep->se_service)); 1582 strwrite(ctrl, "\r\n"); 1583 } 1584 goto reject; 1585 } 1586 1587 /* Try matching a service in inetd.conf with the request */ 1588 for (sep = servtab; sep != NULL; sep = sep->se_next) { 1589 if (!ISMUX(sep)) 1590 continue; 1591 if (strcasecmp(service, sep->se_service) == 0) { 1592 if (ISMUXPLUS(sep)) 1593 strwrite(ctrl, "+Go\r\n"); 1594 run_service(ctrl, sep, true /* forked */); 1595 return; 1596 } 1597 } 1598 strwrite(ctrl, "-Service not available\r\n"); 1599 reject: 1600 _exit(EXIT_FAILURE); 1601 } 1602 1603 /* 1604 * check if the address/port where send data to is one of the obvious ports 1605 * that are used for denial of service attacks like two echo ports 1606 * just echoing data between them 1607 */ 1608 static int 1609 port_good_dg(struct sockaddr *sa) 1610 { 1611 struct in_addr in; 1612 struct sockaddr_in *sin; 1613 #ifdef INET6 1614 struct in6_addr *in6; 1615 struct sockaddr_in6 *sin6; 1616 #endif 1617 u_int16_t port; 1618 int i; 1619 char hbuf[NI_MAXHOST]; 1620 1621 switch (sa->sa_family) { 1622 case AF_INET: 1623 sin = (struct sockaddr_in *)(void *)sa; 1624 in.s_addr = ntohl(sin->sin_addr.s_addr); 1625 port = ntohs(sin->sin_port); 1626 #ifdef INET6 1627 v4chk: 1628 #endif 1629 if (IN_MULTICAST(in.s_addr)) 1630 goto bad; 1631 switch ((in.s_addr & 0xff000000) >> 24) { 1632 case 0: case 127: case 255: 1633 goto bad; 1634 } 1635 if (dg_broadcast(&in)) 1636 goto bad; 1637 break; 1638 #ifdef INET6 1639 case AF_INET6: 1640 sin6 = (struct sockaddr_in6 *)(void *)sa; 1641 in6 = &sin6->sin6_addr; 1642 port = ntohs(sin6->sin6_port); 1643 if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6)) 1644 goto bad; 1645 if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) { 1646 memcpy(&in, &in6->s6_addr[12], sizeof(in)); 1647 in.s_addr = ntohl(in.s_addr); 1648 goto v4chk; 1649 } 1650 break; 1651 #endif 1652 default: 1653 /* XXX unsupported af, is it safe to assume it to be safe? */ 1654 return true; 1655 } 1656 1657 for (i = 0; bad_ports[i] != 0; i++) { 1658 if (port == bad_ports[i]) 1659 goto bad; 1660 } 1661 1662 return true; 1663 1664 bad: 1665 if (getnameinfo(sa, sa->sa_len, hbuf, (socklen_t)sizeof(hbuf), NULL, 0, 1666 niflags) != 0) 1667 strlcpy(hbuf, "?", sizeof(hbuf)); 1668 syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d", 1669 hbuf, port); 1670 return false; 1671 } 1672 1673 /* XXX need optimization */ 1674 static int 1675 dg_broadcast(struct in_addr *in) 1676 { 1677 struct ifaddrs *ifa, *ifap; 1678 struct sockaddr_in *sin; 1679 1680 if (getifaddrs(&ifap) < 0) 1681 return false; 1682 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 1683 if (ifa->ifa_addr->sa_family != AF_INET || 1684 (ifa->ifa_flags & IFF_BROADCAST) == 0) 1685 continue; 1686 sin = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr; 1687 if (sin->sin_addr.s_addr == in->s_addr) { 1688 freeifaddrs(ifap); 1689 return true; 1690 } 1691 } 1692 freeifaddrs(ifap); 1693 return false; 1694 } 1695 1696 static int 1697 my_kevent(const struct kevent *changelist, size_t nchanges, 1698 struct kevent *eventlist, size_t nevents) 1699 { 1700 int result; 1701 1702 while ((result = kevent(kq, changelist, nchanges, eventlist, nevents, 1703 NULL)) < 0) 1704 if (errno != EINTR) { 1705 syslog(LOG_ERR, "kevent: %m"); 1706 exit(EXIT_FAILURE); 1707 } 1708 1709 return (result); 1710 } 1711 1712 static struct kevent * 1713 allocchange(void) 1714 { 1715 if (changes == __arraycount(changebuf)) { 1716 (void) my_kevent(changebuf, __arraycount(changebuf), NULL, 0); 1717 changes = 0; 1718 } 1719 1720 return (&changebuf[changes++]); 1721 } 1722 1723 bool 1724 try_biltin(struct servtab *sep) 1725 { 1726 for (size_t i = 0; i < __arraycount(biltins); i++) { 1727 if (biltins[i].bi_socktype == sep->se_socktype && 1728 strcmp(biltins[i].bi_service, sep->se_service) == 0) { 1729 sep->se_bi = &biltins[i]; 1730 sep->se_wait = biltins[i].bi_wait; 1731 return true; 1732 } 1733 } 1734 return false; 1735 } 1736