inetd.c revision 1.141 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