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