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