inetd.c revision 1.134 1 /* $NetBSD: inetd.c,v 1.134 2021/09/03 20:24:28 rillig Exp $ */
2
3 /*-
4 * Copyright (c) 1998, 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center and by Matthias Scheler.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 /*
34 * Copyright (c) 1983, 1991, 1993, 1994
35 * The Regents of the University of California. All rights reserved.
36 *
37 * Redistribution and use in source and binary forms, with or without
38 * modification, are permitted provided that the following conditions
39 * are met:
40 * 1. Redistributions of source code must retain the above copyright
41 * notice, this list of conditions and the following disclaimer.
42 * 2. Redistributions in binary form must reproduce the above copyright
43 * notice, this list of conditions and the following disclaimer in the
44 * documentation and/or other materials provided with the distribution.
45 * 3. Neither the name of the University nor the names of its contributors
46 * may be used to endorse or promote products derived from this software
47 * without specific prior written permission.
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59 * SUCH DAMAGE.
60 */
61
62 #include <sys/cdefs.h>
63 #ifndef lint
64 __COPYRIGHT("@(#) Copyright (c) 1983, 1991, 1993, 1994\
65 The Regents of the University of California. All rights reserved.");
66 #if 0
67 static char sccsid[] = "@(#)inetd.c 8.4 (Berkeley) 4/13/94";
68 #else
69 __RCSID("$NetBSD: inetd.c,v 1.134 2021/09/03 20:24:28 rillig Exp $");
70 #endif
71 #endif /* not lint */
72
73 /*
74 * Inetd - Internet super-server
75 *
76 * This program invokes all internet services as needed. Connection-oriented
77 * services are invoked each time a connection is made, by creating a process.
78 * This process is passed the connection as file descriptor 0 and is expected
79 * to do a getpeername to find out the source host and port.
80 *
81 * Datagram oriented services are invoked when a datagram
82 * arrives; a process is created and passed a pending message
83 * on file descriptor 0. Datagram servers may either connect
84 * to their peer, freeing up the original socket for inetd
85 * to receive further messages on, or ``take over the socket'',
86 * processing all arriving datagrams and, eventually, timing
87 * out. The first type of server is said to be ``multi-threaded'';
88 * the second type of server ``single-threaded''.
89 *
90 * Inetd uses a configuration file which is read at startup
91 * and, possibly, at some later time in response to a hangup signal.
92 * The configuration file is ``free format'' with fields given in the
93 * order shown below. Continuation lines for an entry must being with
94 * a space or tab. All fields must be present in each entry.
95 *
96 * service name must be in /etc/services or must
97 * name a tcpmux service
98 * socket type[:accf[,arg]] stream/dgram/raw/rdm/seqpacket,
99 only stream can name an accept filter
100 * protocol must be in /etc/protocols
101 * wait/nowait[:max] single-threaded/multi-threaded, max #
102 * user[:group] user/group to run daemon as
103 * server program full path name
104 * server program arguments maximum of MAXARGV (64)
105 *
106 * For RPC services
107 * service name/version must be in /etc/rpc
108 * socket type stream/dgram/raw/rdm/seqpacket
109 * protocol must be in /etc/protocols
110 * wait/nowait[:max] single-threaded/multi-threaded
111 * user[:group] user to run daemon as
112 * server program full path name
113 * server program arguments maximum of MAXARGV (64)
114 *
115 * For non-RPC services, the "service name" can be of the form
116 * hostaddress:servicename, in which case the hostaddress is used
117 * as the host portion of the address to listen on. If hostaddress
118 * consists of a single `*' character, INADDR_ANY is used.
119 *
120 * A line can also consist of just
121 * hostaddress:
122 * where hostaddress is as in the preceding paragraph. Such a line must
123 * have no further fields; the specified hostaddress is remembered and
124 * used for all further lines that have no hostaddress specified,
125 * until the next such line (or EOF). (This is why * is provided to
126 * allow explicit specification of INADDR_ANY.) A line
127 * *:
128 * is implicitly in effect at the beginning of the file.
129 *
130 * The hostaddress specifier may (and often will) contain dots;
131 * the service name must not.
132 *
133 * For RPC services, host-address specifiers are accepted and will
134 * work to some extent; however, because of limitations in the
135 * portmapper interface, it will not work to try to give more than
136 * one line for any given RPC service, even if the host-address
137 * specifiers are different.
138 *
139 * TCP services without official port numbers are handled with the
140 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
141 * requests. When a connection is made from a foreign host, the service
142 * requested is passed to tcpmux, which looks it up in the servtab list
143 * and returns the proper entry for the service. Tcpmux returns a
144 * negative reply if the service doesn't exist, otherwise the invoked
145 * server is expected to return the positive reply if the service type in
146 * inetd.conf file has the prefix "tcpmux/". If the service type has the
147 * prefix "tcpmux/+", tcpmux will return the positive reply for the
148 * process; this is for compatibility with older server code, and also
149 * allows you to invoke programs that use stdin/stdout without putting any
150 * special server code in them. Services that use tcpmux are "nowait"
151 * because they do not have a well-known port and hence cannot listen
152 * for new requests.
153 *
154 * Comment lines are indicated by a `#' in column 1.
155 *
156 * #ifdef IPSEC
157 * Comment lines that start with "#@" denote IPsec policy string, as described
158 * in ipsec_set_policy(3). This will affect all the following items in
159 * inetd.conf(8). To reset the policy, just use "#@" line. By default,
160 * there's no IPsec policy.
161 * #endif
162 */
163
164 /*
165 * Here's the scoop concerning the user:group feature:
166 *
167 * 1) set-group-option off.
168 *
169 * a) user = root: NO setuid() or setgid() is done
170 *
171 * b) other: setuid()
172 * setgid(primary group as found in passwd)
173 * initgroups(name, primary group)
174 *
175 * 2) set-group-option on.
176 *
177 * a) user = root: NO setuid()
178 * setgid(specified group)
179 * NO initgroups()
180 *
181 * b) other: setuid()
182 * setgid(specified group)
183 * initgroups(name, specified group)
184 *
185 */
186
187 #include <sys/param.h>
188 #include <sys/stat.h>
189 #include <sys/ioctl.h>
190 #include <sys/wait.h>
191 #include <sys/resource.h>
192 #include <sys/event.h>
193 #include <sys/socket.h>
194
195
196 #ifndef NO_RPC
197 #define RPC
198 #endif
199
200 #include <net/if.h>
201
202 #ifdef RPC
203 #include <rpc/rpc.h>
204 #include <rpc/rpcb_clnt.h>
205 #include <netconfig.h>
206 #endif
207
208 #include <ctype.h>
209 #include <err.h>
210 #include <errno.h>
211 #include <fcntl.h>
212 #include <glob.h>
213 #include <grp.h>
214 #include <libgen.h>
215 #include <pwd.h>
216 #include <signal.h>
217 #include <stdio.h>
218 #include <stdlib.h>
219 #include <string.h>
220 #include <syslog.h>
221 #include <unistd.h>
222 #include <util.h>
223 #include <ifaddrs.h>
224
225 #include "inetd.h"
226
227 #ifdef LIBWRAP
228 # include <tcpd.h>
229 #ifndef LIBWRAP_ALLOW_FACILITY
230 # define LIBWRAP_ALLOW_FACILITY LOG_AUTH
231 #endif
232 #ifndef LIBWRAP_ALLOW_SEVERITY
233 # define LIBWRAP_ALLOW_SEVERITY LOG_INFO
234 #endif
235 #ifndef LIBWRAP_DENY_FACILITY
236 # define LIBWRAP_DENY_FACILITY LOG_AUTH
237 #endif
238 #ifndef LIBWRAP_DENY_SEVERITY
239 # define LIBWRAP_DENY_SEVERITY LOG_WARNING
240 #endif
241 int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
242 int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
243 #endif
244
245 #define CNT_INTVL ((time_t)60) /* servers in CNT_INTVL sec. */
246 #define RETRYTIME (60*10) /* retry after bind or server fail */
247
248 int debug;
249 #ifdef LIBWRAP
250 int lflag;
251 #endif
252 int maxsock;
253 int kq;
254 int options;
255 int timingout;
256 const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
257
258 #ifndef OPEN_MAX
259 #define OPEN_MAX 64
260 #endif
261
262 /* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
263 #define FD_MARGIN (8)
264 rlim_t rlim_ofile_cur = OPEN_MAX;
265
266 struct rlimit rlim_ofile;
267
268 struct kevent changebuf[64];
269 size_t changes;
270
271 struct servtab *servtab;
272
273 static void chargen_dg(int, struct servtab *);
274 static void chargen_stream(int, struct servtab *);
275 static void close_sep(struct servtab *);
276 static void config(void);
277 static void daytime_dg(int, struct servtab *);
278 static void daytime_stream(int, struct servtab *);
279 static void discard_dg(int, struct servtab *);
280 static void discard_stream(int, struct servtab *);
281 static void echo_dg(int, struct servtab *);
282 static void echo_stream(int, struct servtab *);
283 static void endconfig(void);
284 static struct servtab *enter(struct servtab *);
285 static struct servtab *getconfigent(char **);
286 __dead static void goaway(void);
287 static void machtime_dg(int, struct servtab *);
288 static void machtime_stream(int, struct servtab *);
289 #ifdef DEBUG_ENABLE
290 static void print_service(const char *, struct servtab *);
291 #endif
292 static void reapchild(void);
293 static void retry(void);
294 static void run_service(int, struct servtab *, int);
295 static void setup(struct servtab *);
296 static char *skip(char **);
297 static void tcpmux(int, struct servtab *);
298 __dead static void usage(void);
299 static void register_rpc(struct servtab *);
300 static void unregister_rpc(struct servtab *);
301 static void bump_nofile(void);
302 static void inetd_setproctitle(char *, int);
303 static void initring(void);
304 static uint32_t machtime(void);
305 static int port_good_dg(struct sockaddr *);
306 static int dg_broadcast(struct in_addr *);
307 static int my_kevent(const struct kevent *, size_t, struct kevent *, size_t);
308 static struct kevent *allocchange(void);
309 static int get_line(int, char *, int);
310 static void spawn(struct servtab *, int);
311 static struct servtab init_servtab(void);
312 static int rl_process(struct servtab *, int);
313 static struct se_ip_list_node *rl_add(struct servtab *, char *);
314 static void rl_reset(struct servtab *, time_t);
315 static struct se_ip_list_node *rl_try_get_ip(struct servtab *, char *);
316 static void include_configs(char *);
317 static int glob_error(const char *, int);
318 static void read_glob_configs(char *);
319 static void prepare_next_config(const char*);
320 static bool is_same_service(const struct servtab *, const struct servtab *);
321 static char *gen_file_pattern(const char *, const char *);
322 static bool check_no_reinclude(const char *);
323 static void include_matched_path(char *);
324 static void purge_unchecked(void);
325 static void config_root(void);
326 static void clear_ip_list(struct servtab *);
327 static time_t rl_time(void);
328 static void rl_get_name(struct servtab *, int, char *);
329 static void rl_drop_connection(struct servtab *, int);
330
331 struct biltin {
332 const char *bi_service; /* internally provided service name */
333 int bi_socktype; /* type of socket supported */
334 short bi_fork; /* 1 if should fork before call */
335 short bi_wait; /* 1 if should wait for child */
336 void (*bi_fn)(int, struct servtab *);
337 /* function which performs it */
338 } biltins[] = {
339 /* Echo received data */
340 { "echo", SOCK_STREAM, true, false, echo_stream },
341 { "echo", SOCK_DGRAM, false, false, echo_dg },
342
343 /* Internet /dev/null */
344 { "discard", SOCK_STREAM, true, false, discard_stream },
345 { "discard", SOCK_DGRAM, false, false, discard_dg },
346
347 /* Return 32 bit time since 1970 */
348 { "time", SOCK_STREAM, false, false, machtime_stream },
349 { "time", SOCK_DGRAM, false, false, machtime_dg },
350
351 /* Return human-readable time */
352 { "daytime", SOCK_STREAM, false, false, daytime_stream },
353 { "daytime", SOCK_DGRAM, false, false, daytime_dg },
354
355 /* Familiar character generator */
356 { "chargen", SOCK_STREAM, true, false, chargen_stream },
357 { "chargen", SOCK_DGRAM, false, false, chargen_dg },
358
359 { "tcpmux", SOCK_STREAM, true, false, tcpmux },
360
361 { NULL, 0, false, false, NULL }
362 };
363
364 /* list of "bad" ports. I.e. ports that are most obviously used for
365 * "cycling packets" denial of service attacks. See /etc/services.
366 * List must end with port number "0".
367 */
368
369 u_int16_t bad_ports[] = { 7, 9, 13, 19, 37, 0 };
370
371
372 #define NUMINT (sizeof(intab) / sizeof(struct inent))
373 const char *CONFIG = _PATH_INETDCONF;
374
375 static int my_signals[] =
376 { SIGALRM, SIGHUP, SIGCHLD, SIGTERM, SIGINT, SIGPIPE };
377
378 int
379 main(int argc, char *argv[])
380 {
381 int ch, n, reload = 1;
382
383 while ((ch = getopt(argc, argv,
384 #ifdef LIBWRAP
385 "dl"
386 #else
387 "d"
388 #endif
389 )) != -1)
390 switch(ch) {
391 case 'd':
392 debug = true;
393 options |= SO_DEBUG;
394 break;
395 #ifdef LIBWRAP
396 case 'l':
397 lflag = true;
398 break;
399 #endif
400 case '?':
401 default:
402 usage();
403 }
404 argc -= optind;
405 argv += optind;
406
407 if (argc > 0)
408 CONFIG = argv[0];
409
410 if (!debug)
411 daemon(0, 0);
412 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
413 pidfile(NULL);
414
415 kq = kqueue();
416 if (kq < 0) {
417 syslog(LOG_ERR, "kqueue: %m");
418 return (EXIT_FAILURE);
419 }
420
421 if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
422 syslog(LOG_ERR, "getrlimit: %m");
423 } else {
424 rlim_ofile_cur = rlim_ofile.rlim_cur;
425 if (rlim_ofile_cur == RLIM_INFINITY) /* ! */
426 rlim_ofile_cur = OPEN_MAX;
427 }
428
429 for (n = 0; n < (int)__arraycount(my_signals); n++) {
430 int signum;
431
432 signum = my_signals[n];
433 if (signum != SIGCHLD)
434 (void) signal(signum, SIG_IGN);
435
436 if (signum != SIGPIPE) {
437 struct kevent *ev;
438
439 ev = allocchange();
440 EV_SET(ev, signum, EVFILT_SIGNAL, EV_ADD | EV_ENABLE,
441 0, 0, 0);
442 }
443 }
444
445 for (;;) {
446 int ctrl;
447 struct kevent eventbuf[64], *ev;
448 struct servtab *sep;
449
450 if (reload) {
451 reload = false;
452 config_root();
453 }
454
455 n = my_kevent(changebuf, changes, eventbuf, __arraycount(eventbuf));
456 changes = 0;
457
458 for (ev = eventbuf; n > 0; ev++, n--) {
459 if (ev->filter == EVFILT_SIGNAL) {
460 switch (ev->ident) {
461 case SIGALRM:
462 retry();
463 break;
464 case SIGCHLD:
465 reapchild();
466 break;
467 case SIGTERM:
468 case SIGINT:
469 goaway();
470 break;
471 case SIGHUP:
472 reload = true;
473 break;
474 }
475 continue;
476 }
477 if (ev->filter != EVFILT_READ)
478 continue;
479 sep = (struct servtab *)ev->udata;
480 /* Paranoia */
481 if ((int)ev->ident != sep->se_fd)
482 continue;
483 DPRINTF(SERV_FMT ": service requested" , SERV_PARAMS(sep));
484 if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) {
485 /* XXX here do the libwrap check-before-accept*/
486 ctrl = accept(sep->se_fd, NULL, NULL);
487 DPRINTF(SERV_FMT ": accept, ctrl fd %d",
488 SERV_PARAMS(sep), ctrl);
489 if (ctrl < 0) {
490 if (errno != EINTR)
491 syslog(LOG_WARNING,
492 SERV_FMT ": accept: %m",
493 SERV_PARAMS(sep));
494 continue;
495 }
496 } else
497 ctrl = sep->se_fd;
498 spawn(sep, ctrl);
499 }
500 }
501 }
502
503 static void
504 spawn(struct servtab *sep, int ctrl)
505 {
506 int dofork;
507 pid_t pid;
508
509 pid = 0;
510 #ifdef LIBWRAP_INTERNAL
511 dofork = true;
512 #else
513 dofork = (sep->se_bi == NULL || sep->se_bi->bi_fork);
514 #endif
515 if (dofork) {
516 if (rl_process(sep, ctrl)) {
517 return;
518 }
519 pid = fork();
520 if (pid < 0) {
521 syslog(LOG_ERR, "fork: %m");
522 if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM)
523 close(ctrl);
524 sleep(1);
525 return;
526 }
527 if (pid != 0 && sep->se_wait != 0) {
528 struct kevent *ev;
529
530 sep->se_wait = pid;
531 ev = allocchange();
532 EV_SET(ev, sep->se_fd, EVFILT_READ,
533 EV_DELETE, 0, 0, 0);
534 }
535 if (pid == 0) {
536 size_t n;
537
538 for (n = 0; n < __arraycount(my_signals); n++)
539 (void) signal(my_signals[n], SIG_DFL);
540 if (debug)
541 setsid();
542 }
543 }
544 if (pid == 0) {
545 run_service(ctrl, sep, dofork);
546 if (dofork)
547 exit(0);
548 }
549 if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM)
550 close(ctrl);
551 }
552
553 static void
554 run_service(int ctrl, struct servtab *sep, int didfork)
555 {
556 struct passwd *pwd;
557 struct group *grp = NULL; /* XXX gcc */
558 char buf[NI_MAXSERV];
559 struct servtab *s;
560 #ifdef LIBWRAP
561 char abuf[BUFSIZ];
562 struct request_info req;
563 int denied;
564 char *service = NULL; /* XXX gcc */
565 #endif
566
567 #ifdef LIBWRAP
568 #ifndef LIBWRAP_INTERNAL
569 if (sep->se_bi == 0)
570 #endif
571 if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) {
572 request_init(&req, RQ_DAEMON, sep->se_argv[0] != NULL ?
573 sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL);
574 fromhost(&req);
575 denied = hosts_access(&req) == 0;
576 if (denied || lflag) {
577 if (getnameinfo(&sep->se_ctrladdr,
578 (socklen_t)sep->se_ctrladdr.sa_len, NULL, 0,
579 buf, sizeof(buf), 0) != 0) {
580 /* shouldn't happen */
581 (void)snprintf(buf, sizeof buf, "%d",
582 ntohs(sep->se_ctrladdr_in.sin_port));
583 }
584 service = buf;
585 if (req.client->sin != NULL) {
586 sockaddr_snprintf(abuf, sizeof(abuf), "%a",
587 req.client->sin);
588 } else {
589 strcpy(abuf, "(null)");
590 }
591 }
592 if (denied) {
593 syslog(deny_severity,
594 "refused connection from %.500s(%s), service %s (%s)",
595 eval_client(&req), abuf, service, sep->se_proto);
596 goto reject;
597 }
598 if (lflag) {
599 syslog(allow_severity,
600 "connection from %.500s(%s), service %s (%s)",
601 eval_client(&req), abuf, service, sep->se_proto);
602 }
603 }
604 #endif /* LIBWRAP */
605
606 if (sep->se_bi != NULL) {
607 if (didfork) {
608 for (s = servtab; s != NULL; s = s->se_next)
609 if (s->se_fd != -1 && s->se_fd != ctrl) {
610 close(s->se_fd);
611 s->se_fd = -1;
612 }
613 }
614 (*sep->se_bi->bi_fn)(ctrl, sep);
615 } else {
616 if ((pwd = getpwnam(sep->se_user)) == NULL) {
617 syslog(LOG_ERR, "%s/%s: %s: No such user",
618 sep->se_service, sep->se_proto, sep->se_user);
619 goto reject;
620 }
621 if (sep->se_group != NULL &&
622 (grp = getgrnam(sep->se_group)) == NULL) {
623 syslog(LOG_ERR, "%s/%s: %s: No such group",
624 sep->se_service, sep->se_proto, sep->se_group);
625 goto reject;
626 }
627 if (pwd->pw_uid != 0) {
628 if (sep->se_group != NULL)
629 pwd->pw_gid = grp->gr_gid;
630 if (setgid(pwd->pw_gid) < 0) {
631 syslog(LOG_ERR,
632 "%s/%s: can't set gid %d: %m", sep->se_service,
633 sep->se_proto, pwd->pw_gid);
634 goto reject;
635 }
636 (void) initgroups(pwd->pw_name,
637 pwd->pw_gid);
638 if (setuid(pwd->pw_uid) < 0) {
639 syslog(LOG_ERR,
640 "%s/%s: can't set uid %d: %m", sep->se_service,
641 sep->se_proto, pwd->pw_uid);
642 goto reject;
643 }
644 } else if (sep->se_group != NULL) {
645 (void) setgid((gid_t)grp->gr_gid);
646 }
647 DPRINTF("%d execl %s",
648 getpid(), sep->se_server);
649 /* Set our control descriptor to not close-on-exec... */
650 if (fcntl(ctrl, F_SETFD, 0) < 0)
651 syslog(LOG_ERR, "fcntl (%d, F_SETFD, 0): %m", ctrl);
652 /* ...and dup it to stdin, stdout, and stderr. */
653 if (ctrl != 0) {
654 dup2(ctrl, 0);
655 close(ctrl);
656 ctrl = 0;
657 }
658 dup2(0, 1);
659 dup2(0, 2);
660 if (rlim_ofile.rlim_cur != rlim_ofile_cur &&
661 setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0)
662 syslog(LOG_ERR, "setrlimit: %m");
663 execv(sep->se_server, sep->se_argv);
664 syslog(LOG_ERR, "cannot execute %s: %m", sep->se_server);
665 reject:
666 if (sep->se_socktype != SOCK_STREAM)
667 recv(ctrl, buf, sizeof (buf), 0);
668 _exit(EXIT_FAILURE);
669 }
670 }
671
672 static void
673 reapchild(void)
674 {
675 int status;
676 pid_t pid;
677 struct servtab *sep;
678
679 for (;;) {
680 pid = wait3(&status, WNOHANG, NULL);
681 if (pid <= 0)
682 break;
683 DPRINTF("%d reaped, status %#x", pid, status);
684 for (sep = servtab; sep != NULL; sep = sep->se_next)
685 if (sep->se_wait == pid) {
686 struct kevent *ev;
687
688 if (WIFEXITED(status) && WEXITSTATUS(status))
689 syslog(LOG_WARNING,
690 "%s: exit status %u",
691 sep->se_server, WEXITSTATUS(status));
692 else if (WIFSIGNALED(status))
693 syslog(LOG_WARNING,
694 "%s: exit signal %u",
695 sep->se_server, WTERMSIG(status));
696 sep->se_wait = 1;
697 ev = allocchange();
698 EV_SET(ev, sep->se_fd, EVFILT_READ,
699 EV_ADD | EV_ENABLE, 0, 0, (intptr_t)sep);
700 DPRINTF("restored %s, fd %d",
701 sep->se_service, sep->se_fd);
702 }
703 }
704 }
705
706 size_t line_number;
707
708 /*
709 * Recursively merge loaded service definitions with any defined
710 * in the current or included config files.
711 */
712 static void
713 config(void)
714 {
715 struct servtab *sep, *cp;
716 /*
717 * Current position in line, used with key-values notation,
718 * saves cp across getconfigent calls.
719 */
720 char *current_pos;
721 size_t n;
722
723 /* open config file from beginning */
724 fconfig = fopen(CONFIG, "r");
725 if(fconfig == NULL) {
726 syslog(LOG_ERR, "%s: %m", CONFIG);
727 return;
728 }
729
730 /* First call to nextline will advance line_number to 1 */
731 line_number = 0;
732
733 /* Start parsing at the beginning of the first line */
734 current_pos = nextline(fconfig);
735
736 while ((cp = getconfigent(¤t_pos)) != NULL) {
737 /* Find an already existing service definition */
738 for (sep = servtab; sep != NULL; sep = sep->se_next)
739 if (is_same_service(sep, cp))
740 break;
741 if (sep != NULL) {
742 int i;
743
744 #define SWAP(type, a, b) {type c = a; a = b; b = c;}
745
746 /*
747 * sep->se_wait may be holding the pid of a daemon
748 * that we're waiting for. If so, don't overwrite
749 * it unless the config file explicitly says don't
750 * wait.
751 */
752 if (cp->se_bi == 0 &&
753 (sep->se_wait == 1 || cp->se_wait == 0))
754 sep->se_wait = cp->se_wait;
755 SWAP(char *, sep->se_user, cp->se_user);
756 SWAP(char *, sep->se_group, cp->se_group);
757 SWAP(char *, sep->se_server, cp->se_server);
758 for (i = 0; i < MAXARGV; i++)
759 SWAP(char *, sep->se_argv[i], cp->se_argv[i]);
760 #ifdef IPSEC
761 SWAP(char *, sep->se_policy, cp->se_policy);
762 #endif
763 SWAP(service_type, cp->se_type, sep->se_type);
764 SWAP(size_t, cp->se_service_max, sep->se_service_max);
765 SWAP(size_t, cp->se_ip_max, sep->se_ip_max);
766 #undef SWAP
767 if (isrpcservice(sep))
768 unregister_rpc(sep);
769 sep->se_rpcversl = cp->se_rpcversl;
770 sep->se_rpcversh = cp->se_rpcversh;
771 freeconfig(cp);
772 #ifdef DEBUG_ENABLE
773 if (debug)
774 print_service("REDO", sep);
775 #endif
776 } else {
777 sep = enter(cp);
778 #ifdef DEBUG_ENABLE
779 if (debug)
780 print_service("ADD ", sep);
781 #endif
782 }
783 sep->se_checked = 1;
784
785 /*
786 * Remainder of config(void) checks validity of servtab options
787 * and sets up the service by setting up sockets (in setup(servtab)).
788 */
789 switch (sep->se_family) {
790 case AF_LOCAL:
791 if (sep->se_fd != -1)
792 break;
793 n = strlen(sep->se_service);
794 if (n >= sizeof(sep->se_ctrladdr_un.sun_path)) {
795 syslog(LOG_ERR, "%s/%s: address too long",
796 sep->se_service, sep->se_proto);
797 sep->se_checked = 0;
798 continue;
799 }
800 (void)unlink(sep->se_service);
801 strlcpy(sep->se_ctrladdr_un.sun_path,
802 sep->se_service, n + 1);
803 sep->se_ctrladdr_un.sun_family = AF_LOCAL;
804 sep->se_ctrladdr_size = (socklen_t)(n +
805 sizeof(sep->se_ctrladdr_un) -
806 sizeof(sep->se_ctrladdr_un.sun_path));
807 if (!ISMUX(sep))
808 setup(sep);
809 break;
810 case AF_INET:
811 #ifdef INET6
812 case AF_INET6:
813 #endif
814 {
815 struct addrinfo hints, *res;
816 char *host;
817 const char *port;
818 int error;
819 int s;
820
821 /* check if the family is supported */
822 s = socket(sep->se_family, SOCK_DGRAM, 0);
823 if (s < 0) {
824 syslog(LOG_WARNING,
825 "%s/%s: %s: the address family is not "
826 "supported by the kernel",
827 sep->se_service, sep->se_proto,
828 sep->se_hostaddr);
829 sep->se_checked = false;
830 continue;
831 }
832 close(s);
833
834 memset(&hints, 0, sizeof(hints));
835 hints.ai_family = sep->se_family;
836 hints.ai_socktype = sep->se_socktype;
837 hints.ai_flags = AI_PASSIVE;
838 if (strcmp(sep->se_hostaddr, "*") == 0)
839 host = NULL;
840 else
841 host = sep->se_hostaddr;
842 if (isrpcservice(sep) || ISMUX(sep))
843 port = "0";
844 else
845 port = sep->se_service;
846 error = getaddrinfo(host, port, &hints, &res);
847 if (error != 0) {
848 if (error == EAI_SERVICE) {
849 /* gai_strerror not friendly enough */
850 syslog(LOG_WARNING, SERV_FMT ": "
851 "unknown service",
852 SERV_PARAMS(sep));
853 } else {
854 syslog(LOG_ERR, SERV_FMT ": %s: %s",
855 SERV_PARAMS(sep),
856 sep->se_hostaddr,
857 gai_strerror(error));
858 }
859 sep->se_checked = false;
860 continue;
861 }
862 if (res->ai_next != NULL) {
863 syslog(LOG_ERR,
864 SERV_FMT ": %s: resolved to multiple addr",
865 SERV_PARAMS(sep),
866 sep->se_hostaddr);
867 sep->se_checked = false;
868 freeaddrinfo(res);
869 continue;
870 }
871 memcpy(&sep->se_ctrladdr, res->ai_addr,
872 res->ai_addrlen);
873 if (ISMUX(sep)) {
874 sep->se_fd = -1;
875 freeaddrinfo(res);
876 continue;
877 }
878 sep->se_ctrladdr_size = res->ai_addrlen;
879 freeaddrinfo(res);
880 #ifdef RPC
881 if (isrpcservice(sep)) {
882 struct rpcent *rp;
883
884 sep->se_rpcprog = atoi(sep->se_service);
885 if (sep->se_rpcprog == 0) {
886 rp = getrpcbyname(sep->se_service);
887 if (rp == 0) {
888 syslog(LOG_ERR,
889 SERV_FMT
890 ": unknown service",
891 SERV_PARAMS(sep));
892 sep->se_checked = false;
893 continue;
894 }
895 sep->se_rpcprog = rp->r_number;
896 }
897 if (sep->se_fd == -1 && !ISMUX(sep))
898 setup(sep);
899 if (sep->se_fd != -1)
900 register_rpc(sep);
901 } else
902 #endif
903 {
904 if (sep->se_fd >= 0)
905 close_sep(sep);
906 if (sep->se_fd == -1 && !ISMUX(sep))
907 setup(sep);
908 }
909 }
910 }
911 }
912 endconfig();
913 }
914
915 static void
916 retry(void)
917 {
918 struct servtab *sep;
919
920 timingout = false;
921 for (sep = servtab; sep != NULL; sep = sep->se_next) {
922 if (sep->se_fd == -1 && !ISMUX(sep)) {
923 switch (sep->se_family) {
924 case AF_LOCAL:
925 case AF_INET:
926 #ifdef INET6
927 case AF_INET6:
928 #endif
929 setup(sep);
930 if (sep->se_fd >= 0 && isrpcservice(sep))
931 register_rpc(sep);
932 break;
933 }
934 }
935 }
936 }
937
938 static void
939 goaway(void)
940 {
941 struct servtab *sep;
942
943 for (sep = servtab; sep != NULL; sep = sep->se_next) {
944 if (sep->se_fd == -1)
945 continue;
946
947 switch (sep->se_family) {
948 case AF_LOCAL:
949 (void)unlink(sep->se_service);
950 break;
951 case AF_INET:
952 #ifdef INET6
953 case AF_INET6:
954 #endif
955 if (sep->se_wait == 1 && isrpcservice(sep))
956 unregister_rpc(sep);
957 break;
958 }
959 (void)close(sep->se_fd);
960 sep->se_fd = -1;
961 }
962 exit(0);
963 }
964
965 static void
966 setup(struct servtab *sep)
967 {
968 int on = 1;
969 #ifdef INET6
970 int off = 0;
971 #endif
972 struct kevent *ev;
973
974 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
975 DPRINTF("socket failed on " SERV_FMT ": %s",
976 SERV_PARAMS(sep), strerror(errno));
977 syslog(LOG_ERR, "%s/%s: socket: %m",
978 sep->se_service, sep->se_proto);
979 return;
980 }
981 /* Set all listening sockets to close-on-exec. */
982 if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) {
983 syslog(LOG_ERR, SERV_FMT ": fcntl(F_SETFD, FD_CLOEXEC): %m",
984 SERV_PARAMS(sep));
985 close(sep->se_fd);
986 sep->se_fd = -1;
987 return;
988 }
989
990 #define turnon(fd, opt) \
991 setsockopt(fd, SOL_SOCKET, opt, &on, (socklen_t)sizeof(on))
992 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
993 turnon(sep->se_fd, SO_DEBUG) < 0)
994 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
995 if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
996 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
997 #undef turnon
998
999 /* Set the socket buffer sizes, if specified. */
1000 if (sep->se_sndbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
1001 SO_SNDBUF, &sep->se_sndbuf, (socklen_t)sizeof(sep->se_sndbuf)) < 0)
1002 syslog(LOG_ERR, "setsockopt (SO_SNDBUF %d): %m",
1003 sep->se_sndbuf);
1004 if (sep->se_rcvbuf != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
1005 SO_RCVBUF, &sep->se_rcvbuf, (socklen_t)sizeof(sep->se_rcvbuf)) < 0)
1006 syslog(LOG_ERR, "setsockopt (SO_RCVBUF %d): %m",
1007 sep->se_rcvbuf);
1008 #ifdef INET6
1009 if (sep->se_family == AF_INET6) {
1010 int *v;
1011 v = (sep->se_type == FAITH_TYPE) ? &on : &off;
1012 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH,
1013 v, (socklen_t)sizeof(*v)) < 0)
1014 syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
1015 }
1016 #endif
1017 #ifdef IPSEC
1018 /* Avoid setting a policy if a policy specifier doesn't exist. */
1019 if (sep->se_policy != NULL) {
1020 int e = ipsecsetup(sep->se_family, sep->se_fd, sep->se_policy);
1021 if (e < 0) {
1022 syslog(LOG_ERR, SERV_FMT ": ipsec setup failed",
1023 SERV_PARAMS(sep));
1024 (void)close(sep->se_fd);
1025 sep->se_fd = -1;
1026 return;
1027 }
1028 }
1029 #endif
1030
1031 if (bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size) < 0) {
1032 DPRINTF(SERV_FMT ": bind failed: %s",
1033 SERV_PARAMS(sep), strerror(errno));
1034 syslog(LOG_ERR, SERV_FMT ": bind: %m",
1035 SERV_PARAMS(sep));
1036 (void) close(sep->se_fd);
1037 sep->se_fd = -1;
1038 if (!timingout) {
1039 timingout = true;
1040 alarm(RETRYTIME);
1041 }
1042 return;
1043 }
1044 if (sep->se_socktype == SOCK_STREAM)
1045 listen(sep->se_fd, 10);
1046
1047 /* Set the accept filter, if specified. To be done after listen.*/
1048 if (sep->se_accf.af_name[0] != 0 && setsockopt(sep->se_fd, SOL_SOCKET,
1049 SO_ACCEPTFILTER, &sep->se_accf,
1050 (socklen_t)sizeof(sep->se_accf)) < 0)
1051 syslog(LOG_ERR, "setsockopt(SO_ACCEPTFILTER %s): %m",
1052 sep->se_accf.af_name);
1053
1054 ev = allocchange();
1055 EV_SET(ev, sep->se_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0,
1056 (intptr_t)sep);
1057 if (sep->se_fd > maxsock) {
1058 maxsock = sep->se_fd;
1059 if (maxsock > (int)(rlim_ofile_cur - FD_MARGIN))
1060 bump_nofile();
1061 }
1062 DPRINTF(SERV_FMT ": registered on fd %d", SERV_PARAMS(sep), sep->se_fd);
1063 }
1064
1065 /*
1066 * Finish with a service and its socket.
1067 */
1068 static void
1069 close_sep(struct servtab *sep)
1070 {
1071
1072 if (sep->se_fd >= 0) {
1073 (void) close(sep->se_fd);
1074 sep->se_fd = -1;
1075 }
1076 sep->se_count = 0;
1077 if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) {
1078 clear_ip_list(sep);
1079 }
1080 }
1081
1082 static void
1083 register_rpc(struct servtab *sep)
1084 {
1085 #ifdef RPC
1086 struct netbuf nbuf;
1087 struct sockaddr_storage ss;
1088 struct netconfig *nconf;
1089 socklen_t socklen;
1090 int n;
1091
1092 if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) {
1093 syslog(LOG_ERR, "%s: getnetconfigent failed",
1094 sep->se_proto);
1095 return;
1096 }
1097 socklen = sizeof ss;
1098 if (getsockname(sep->se_fd, (struct sockaddr *)(void *)&ss, &socklen) < 0) {
1099 syslog(LOG_ERR, SERV_FMT ": getsockname: %m",
1100 SERV_PARAMS(sep));
1101 return;
1102 }
1103
1104 nbuf.buf = &ss;
1105 nbuf.len = ss.ss_len;
1106 nbuf.maxlen = sizeof (struct sockaddr_storage);
1107 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
1108 DPRINTF("rpcb_set: %u %d %s %s",
1109 sep->se_rpcprog, n, nconf->nc_netid,
1110 taddr2uaddr(nconf, &nbuf));
1111 (void)rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf);
1112 if (rpcb_set((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf, &nbuf) == 0)
1113 syslog(LOG_ERR, "rpcb_set: %u %d %s %s%s",
1114 sep->se_rpcprog, n, nconf->nc_netid,
1115 taddr2uaddr(nconf, &nbuf), clnt_spcreateerror(""));
1116 }
1117 #endif /* RPC */
1118 }
1119
1120 static void
1121 unregister_rpc(struct servtab *sep)
1122 {
1123 #ifdef RPC
1124 int n;
1125 struct netconfig *nconf;
1126
1127 if ((nconf = getnetconfigent(sep->se_proto+4)) == NULL) {
1128 syslog(LOG_ERR, "%s: getnetconfigent failed",
1129 sep->se_proto);
1130 return;
1131 }
1132
1133 for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) {
1134 DPRINTF("rpcb_unset(%u, %d, %s)",
1135 sep->se_rpcprog, n, nconf->nc_netid);
1136 if (rpcb_unset((unsigned int)sep->se_rpcprog, (unsigned int)n, nconf) == 0)
1137 syslog(LOG_ERR, "rpcb_unset(%u, %d, %s) failed\n",
1138 sep->se_rpcprog, n, nconf->nc_netid);
1139 }
1140 #endif /* RPC */
1141 }
1142
1143
1144 static struct servtab *
1145 enter(struct servtab *cp)
1146 {
1147 struct servtab *sep;
1148
1149 sep = malloc(sizeof (*sep));
1150 if (sep == NULL) {
1151 syslog(LOG_ERR, "Out of memory.");
1152 exit(EXIT_FAILURE);
1153 }
1154 *sep = *cp;
1155 sep->se_fd = -1;
1156 sep->se_rpcprog = -1;
1157 sep->se_next = servtab;
1158 servtab = sep;
1159 return (sep);
1160 }
1161
1162 FILE *fconfig;
1163 /* Temporary storage for new servtab */
1164 static struct servtab serv;
1165 /* Current line from current config file */
1166 static char line[LINE_MAX];
1167 char *defhost;
1168 #ifdef IPSEC
1169 char *policy;
1170 #endif
1171
1172 static void
1173 endconfig(void)
1174 {
1175 if (fconfig != NULL) {
1176 (void) fclose(fconfig);
1177 fconfig = NULL;
1178 }
1179 if (defhost != NULL) {
1180 free(defhost);
1181 defhost = NULL;
1182 }
1183
1184 #ifdef IPSEC
1185 if (policy != NULL) {
1186 free(policy);
1187 policy = NULL;
1188 }
1189 #endif
1190
1191 }
1192
1193 #define LOG_EARLY_ENDCONF() \
1194 ERR("Exiting %s early. Some services will be unavailable", CONFIG)
1195
1196 #define LOG_TOO_FEW_ARGS() \
1197 ERR("Expected more arguments")
1198
1199 /* Parse the next service and apply any directives, and returns it as servtab */
1200 static struct servtab *
1201 getconfigent(char **current_pos)
1202 {
1203 struct servtab *sep = &serv;
1204 int argc, val;
1205 char *cp, *cp0, *arg, *buf0, *buf1, *sz0, *sz1;
1206 static char TCPMUX_TOKEN[] = "tcpmux/";
1207 #define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
1208 char *hostdelim;
1209
1210 /*
1211 * Pre-condition: current_pos points into line,
1212 * line contains config line. Continue where the last getconfigent left off.
1213 * Allows for multiple service definitions per line.
1214 */
1215 cp = *current_pos;
1216
1217 if (false) {
1218 /*
1219 * Go to the next line, but only after attemting to read the current
1220 * one! Keep reading until we find a valid definition or EOF.
1221 */
1222 more:
1223 cp = nextline(fconfig);
1224 }
1225
1226 if (cp == NULL) {
1227 /* EOF or I/O error, let config() know to exit the file */
1228 return NULL;
1229 }
1230
1231 /* Comments and IPsec policies */
1232 if (cp[0] == '#') {
1233 #ifdef IPSEC
1234 /* lines starting with #@ is not a comment, but the policy */
1235 if (cp[1] == '@') {
1236 char *p;
1237 for (p = cp + 2; p && *p && isspace((unsigned char)*p); p++)
1238 ;
1239 if (*p == '\0') {
1240 if (policy)
1241 free(policy);
1242 policy = NULL;
1243 } else {
1244 if (ipsecsetup_test(p) < 0) {
1245 ERR("Invalid IPsec policy \"%s\"", p);
1246 LOG_EARLY_ENDCONF();
1247 /*
1248 * Stop reading the current config to prevent services
1249 * from being run without IPsec.
1250 */
1251 return NULL;
1252 } else {
1253 if (policy)
1254 free(policy);
1255 policy = newstr(p);
1256 }
1257 }
1258 }
1259 #endif
1260
1261 goto more;
1262 }
1263
1264 /* Parse next token: listen-addr/hostname, service-spec, .include */
1265 arg = skip(&cp);
1266
1267 if (cp == NULL) {
1268 goto more;
1269 }
1270
1271 if(arg[0] == '.') {
1272 if (strcmp(&arg[1], "include") == 0) {
1273 /* include directive */
1274 arg = skip(&cp);
1275 if(arg == NULL) {
1276 LOG_TOO_FEW_ARGS();
1277 return NULL;
1278 }
1279 include_configs(arg);
1280 goto more;
1281 } else {
1282 ERR("Unknown directive '%s'", &arg[1]);
1283 goto more;
1284 }
1285 }
1286
1287 /* After this point, we might need to store data in a servtab */
1288 *sep = init_servtab();
1289
1290 /* Check for a host name. */
1291 hostdelim = strrchr(arg, ':');
1292 if (hostdelim != NULL) {
1293 *hostdelim = '\0';
1294 if (arg[0] == '[' && hostdelim > arg && hostdelim[-1] == ']') {
1295 hostdelim[-1] = '\0';
1296 sep->se_hostaddr = newstr(arg + 1);
1297 } else
1298 sep->se_hostaddr = newstr(arg);
1299 arg = hostdelim + 1;
1300 /*
1301 * If the line is of the form `host:', then just change the
1302 * default host for the following lines.
1303 */
1304 if (*arg == '\0') {
1305 arg = skip(&cp);
1306 if (cp == NULL) {
1307 free(defhost);
1308 defhost = sep->se_hostaddr;
1309 goto more;
1310 }
1311 }
1312 } else {
1313 /* No host address found, set it to NULL to indicate absence */
1314 sep->se_hostaddr = NULL;
1315 }
1316 if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1317 char *c = arg + MUX_LEN;
1318 if (*c == '+') {
1319 sep->se_type = MUXPLUS_TYPE;
1320 c++;
1321 } else
1322 sep->se_type = MUX_TYPE;
1323 sep->se_service = newstr(c);
1324 } else {
1325 sep->se_service = newstr(arg);
1326 sep->se_type = NORM_TYPE;
1327 }
1328
1329 DPRINTCONF("Found service definition '%s'", sep->se_service);
1330
1331 /* on/off/socktype */
1332 arg = skip(&cp);
1333 if (arg == NULL) {
1334 LOG_TOO_FEW_ARGS();
1335 freeconfig(sep);
1336 goto more;
1337 }
1338
1339 /* Check for new v2 syntax */
1340 if (strcmp(arg, "on") == 0 || strncmp(arg, "on#", 3) == 0) {
1341
1342 if (arg[2] == '#') {
1343 cp = nextline(fconfig);
1344 }
1345
1346 switch(parse_syntax_v2(sep, &cp)) {
1347 case V2_SUCCESS:
1348 *current_pos = cp;
1349 return sep;
1350 case V2_SKIP:
1351 /* Skip invalid definitions, freeconfig is called in parse_v2.c */
1352 *current_pos = cp;
1353 freeconfig(sep);
1354 goto more;
1355 case V2_ERROR:
1356 /*
1357 * Unrecoverable error, stop reading. freeconfig is called
1358 * in parse_v2.c
1359 */
1360 LOG_EARLY_ENDCONF();
1361 freeconfig(sep);
1362 return NULL;
1363 }
1364 } else if (strcmp(arg, "off") == 0 || strncmp(arg, "off#", 4) == 0) {
1365
1366 if (arg[3] == '#') {
1367 cp = nextline(fconfig);
1368 }
1369
1370 /* Parse syntax the same as with 'on', but ignore the result */
1371 switch(parse_syntax_v2(sep, &cp)) {
1372 case V2_SUCCESS:
1373 case V2_SKIP:
1374 *current_pos = cp;
1375 freeconfig(sep);
1376 goto more;
1377 case V2_ERROR:
1378 /* Unrecoverable error, stop reading */
1379 LOG_EARLY_ENDCONF();
1380 freeconfig(sep);
1381 return NULL;
1382 }
1383 } else {
1384 /* continue parsing v1 */
1385 parse_socktype(arg, sep);
1386 if (sep->se_socktype == SOCK_STREAM) {
1387 parse_accept_filter(arg, sep);
1388 }
1389 if (sep->se_hostaddr == NULL) {
1390 /* Set host to current default */
1391 sep->se_hostaddr = newstr(defhost);
1392 }
1393 }
1394
1395 /* protocol */
1396 arg = skip(&cp);
1397 if (arg == NULL) {
1398 LOG_TOO_FEW_ARGS();
1399 freeconfig(sep);
1400 goto more;
1401 }
1402 if (sep->se_type == NORM_TYPE &&
1403 strncmp(arg, "faith/", strlen("faith/")) == 0) {
1404 arg += strlen("faith/");
1405 sep->se_type = FAITH_TYPE;
1406 }
1407 sep->se_proto = newstr(arg);
1408
1409 #define MALFORMED(arg) \
1410 do { \
1411 ERR("%s: malformed buffer size option `%s'", \
1412 sep->se_service, (arg)); \
1413 freeconfig(sep); \
1414 goto more; \
1415 } while (false)
1416
1417 #define GETVAL(arg) \
1418 do { \
1419 if (!isdigit((unsigned char)*(arg))) \
1420 MALFORMED(arg); \
1421 val = (int)strtol((arg), &cp0, 10); \
1422 if (cp0 != NULL) { \
1423 if (cp0[1] != '\0') \
1424 MALFORMED((arg)); \
1425 if (cp0[0] == 'k') \
1426 val *= 1024; \
1427 if (cp0[0] == 'm') \
1428 val *= 1024 * 1024; \
1429 } \
1430 if (val < 1) { \
1431 ERR("%s: invalid buffer size `%s'", \
1432 sep->se_service, (arg)); \
1433 freeconfig(sep); \
1434 goto more; \
1435 } \
1436 } while (false)
1437
1438 #define ASSIGN(arg) \
1439 do { \
1440 if (strcmp((arg), "sndbuf") == 0) \
1441 sep->se_sndbuf = val; \
1442 else if (strcmp((arg), "rcvbuf") == 0) \
1443 sep->se_rcvbuf = val; \
1444 else \
1445 MALFORMED((arg)); \
1446 } while (false)
1447
1448 /*
1449 * Extract the send and receive buffer sizes before parsing
1450 * the protocol.
1451 */
1452 sep->se_sndbuf = sep->se_rcvbuf = 0;
1453 buf0 = buf1 = sz0 = sz1 = NULL;
1454 if ((buf0 = strchr(sep->se_proto, ',')) != NULL) {
1455 /* Not meaningful for Tcpmux services. */
1456 if (ISMUX(sep)) {
1457 ERR("%s: can't specify buffer sizes for "
1458 "tcpmux services", sep->se_service);
1459 goto more;
1460 }
1461
1462 /* Skip the , */
1463 *buf0++ = '\0';
1464
1465 /* Check to see if another socket buffer size was specified. */
1466 if ((buf1 = strchr(buf0, ',')) != NULL) {
1467 /* Skip the , */
1468 *buf1++ = '\0';
1469
1470 /* Make sure a 3rd one wasn't specified. */
1471 if (strchr(buf1, ',') != NULL) {
1472 ERR("%s: too many buffer sizes", sep->se_service);
1473 goto more;
1474 }
1475
1476 /* Locate the size. */
1477 if ((sz1 = strchr(buf1, '=')) == NULL)
1478 MALFORMED(buf1);
1479
1480 /* Skip the = */
1481 *sz1++ = '\0';
1482 }
1483
1484 /* Locate the size. */
1485 if ((sz0 = strchr(buf0, '=')) == NULL)
1486 MALFORMED(buf0);
1487
1488 /* Skip the = */
1489 *sz0++ = '\0';
1490
1491 GETVAL(sz0);
1492 ASSIGN(buf0);
1493
1494 if (buf1 != NULL) {
1495 GETVAL(sz1);
1496 ASSIGN(buf1);
1497 }
1498 }
1499
1500 #undef ASSIGN
1501 #undef GETVAL
1502 #undef MALFORMED
1503
1504 if (parse_protocol(sep)) {
1505 freeconfig(sep);
1506 goto more;
1507 }
1508
1509 /* wait/nowait:max */
1510 arg = skip(&cp);
1511 if (arg == NULL) {
1512 LOG_TOO_FEW_ARGS();
1513 freeconfig(sep);
1514 goto more;
1515 }
1516
1517 /* Rate limiting parsing */ {
1518 char *cp1;
1519 if ((cp1 = strchr(arg, ':')) == NULL)
1520 cp1 = strchr(arg, '.');
1521 if (cp1 != NULL) {
1522 int rstatus;
1523 *cp1++ = '\0';
1524 sep->se_service_max = (size_t)strtou(cp1, NULL, 10, 0,
1525 SERVTAB_COUNT_MAX, &rstatus);
1526
1527 if (rstatus != 0) {
1528 if (rstatus != ERANGE) {
1529 /* For compatibility with atoi parsing */
1530 sep->se_service_max = 0;
1531 }
1532
1533 WRN("Improper \"max\" value '%s', "
1534 "using '%zu' instead: %s",
1535 cp1,
1536 sep->se_service_max,
1537 strerror(rstatus));
1538 }
1539
1540 } else
1541 sep->se_service_max = TOOMANY;
1542 }
1543 if (parse_wait(sep, strcmp(arg, "wait") == 0)) {
1544 freeconfig(sep);
1545 goto more;
1546 }
1547
1548 /* Parse user:group token */
1549 arg = skip(&cp);
1550 if(arg == NULL) {
1551 LOG_TOO_FEW_ARGS();
1552 freeconfig(sep);
1553 goto more;
1554 }
1555 char* separator = strchr(arg, ':');
1556 if (separator == NULL) {
1557 /* Backwards compatibility, allow dot instead of colon */
1558 separator = strchr(arg, '.');
1559 }
1560
1561 if (separator == NULL) {
1562 /* Only user was specified */
1563 sep->se_group = NULL;
1564 } else {
1565 *separator = '\0';
1566 sep->se_group = newstr(separator + 1);
1567 }
1568
1569 sep->se_user = newstr(arg);
1570
1571 /* Parser server-program (path to binary or "internal") */
1572 arg = skip(&cp);
1573 if (arg == NULL) {
1574 LOG_TOO_FEW_ARGS();
1575 freeconfig(sep);
1576 goto more;
1577 }
1578 if (parse_server(sep, arg)) {
1579 freeconfig(sep);
1580 goto more;
1581 }
1582
1583 argc = 0;
1584 for (arg = skip(&cp); cp != NULL; arg = skip(&cp)) {
1585 if (argc < MAXARGV)
1586 sep->se_argv[argc++] = newstr(arg);
1587 }
1588 while (argc <= MAXARGV)
1589 sep->se_argv[argc++] = NULL;
1590 #ifdef IPSEC
1591 sep->se_policy = policy != NULL ? newstr(policy) : NULL;
1592 #endif
1593 /* getconfigent read a positional service def, move to next line */
1594 *current_pos = nextline(fconfig);
1595 return (sep);
1596 }
1597
1598 void
1599 freeconfig(struct servtab *cp)
1600 {
1601 int i;
1602
1603 if (cp->se_hostaddr)
1604 free(cp->se_hostaddr);
1605 if (cp->se_service)
1606 free(cp->se_service);
1607 if (cp->se_proto)
1608 free(cp->se_proto);
1609 if (cp->se_user)
1610 free(cp->se_user);
1611 if(cp->se_group)
1612 free(cp->se_group);
1613 if (cp->se_server)
1614 free(cp->se_server);
1615 for (i = 0; i < MAXARGV; i++)
1616 if (cp->se_argv[i])
1617 free(cp->se_argv[i]);
1618 #ifdef IPSEC
1619 if (cp->se_policy)
1620 free(cp->se_policy);
1621 #endif
1622 }
1623
1624 /*
1625 * Get next token *in the current service definition* from config file.
1626 * Allows multi-line parse if single space or single tab-indented.
1627 * Things in quotes are considered single token.
1628 * Advances cp to next token.
1629 */
1630 static char *
1631 skip(char **cpp)
1632 {
1633 char *cp = *cpp;
1634 char *start;
1635 char quote;
1636
1637 if (*cpp == NULL)
1638 return (NULL);
1639
1640 again:
1641 while (*cp == ' ' || *cp == '\t')
1642 cp++;
1643 if (*cp == '\0') {
1644 int c;
1645
1646 c = getc(fconfig);
1647 (void) ungetc(c, fconfig);
1648 if (c == ' ' || c == '\t')
1649 if ((cp = nextline(fconfig)) != NULL)
1650 goto again;
1651 *cpp = NULL;
1652 return (NULL);
1653 }
1654 start = cp;
1655 /* Parse shell-style quotes */
1656 quote = '\0';
1657 while (*cp != '\0' && (quote != '\0' || (*cp != ' ' && *cp != '\t'))) {
1658 if (*cp == '\'' || *cp == '"') {
1659 if (quote != '\0' && *cp != quote)
1660 cp++;
1661 else {
1662 if (quote != '\0')
1663 quote = '\0';
1664 else
1665 quote = *cp;
1666 memmove(cp, cp+1, strlen(cp));
1667 }
1668 } else
1669 cp++;
1670 }
1671 if (*cp != '\0')
1672 *cp++ = '\0';
1673 *cpp = cp;
1674 return (start);
1675 }
1676
1677 char *
1678 nextline(FILE *fd)
1679 {
1680 char *cp;
1681
1682 if (fgets(line, (int)sizeof(line), fd) == NULL) {
1683 if (ferror(fd) != 0) {
1684 ERR("Error when reading next line: %s", strerror(errno));
1685 }
1686 return NULL;
1687 }
1688 cp = strchr(line, '\n');
1689 if (cp != NULL)
1690 *cp = '\0';
1691 line_number++;
1692 return line;
1693 }
1694
1695 char *
1696 newstr(const char *cp)
1697 {
1698 char *dp;
1699 if ((dp = strdup((cp != NULL) ? cp : "")) != NULL)
1700 return (dp);
1701 syslog(LOG_ERR, "strdup: %m");
1702 exit(EXIT_FAILURE);
1703 /*NOTREACHED*/
1704 }
1705
1706 static void
1707 inetd_setproctitle(char *a, int s)
1708 {
1709 socklen_t size;
1710 struct sockaddr_storage ss;
1711 char hbuf[NI_MAXHOST];
1712 const char *hp;
1713 struct sockaddr *sa;
1714
1715 size = sizeof(ss);
1716 sa = (struct sockaddr *)(void *)&ss;
1717 if (getpeername(s, sa, &size) == 0) {
1718 if (getnameinfo(sa, size, hbuf, (socklen_t)sizeof(hbuf), NULL,
1719 0, niflags) != 0)
1720 hp = "?";
1721 else
1722 hp = hbuf;
1723 setproctitle("-%s [%s]", a, hp);
1724 } else
1725 setproctitle("-%s", a);
1726 }
1727
1728 static void
1729 bump_nofile(void)
1730 {
1731 #define FD_CHUNK 32
1732 struct rlimit rl;
1733
1734 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1735 syslog(LOG_ERR, "getrlimit: %m");
1736 return;
1737 }
1738 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
1739 if (rl.rlim_cur <= rlim_ofile_cur) {
1740 syslog(LOG_ERR,
1741 "bump_nofile: cannot extend file limit, max = %d",
1742 (int)rl.rlim_cur);
1743 return;
1744 }
1745
1746 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
1747 syslog(LOG_ERR, "setrlimit: %m");
1748 return;
1749 }
1750
1751 rlim_ofile_cur = rl.rlim_cur;
1752 return;
1753 }
1754
1755 /*
1756 * Internet services provided internally by inetd:
1757 */
1758 #define BUFSIZE 4096
1759
1760 /* ARGSUSED */
1761 static void
1762 echo_stream(int s, struct servtab *sep) /* Echo service -- echo data back */
1763 {
1764 char buffer[BUFSIZE];
1765 ssize_t i;
1766
1767 inetd_setproctitle(sep->se_service, s);
1768 while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1769 write(s, buffer, (size_t)i) > 0)
1770 ;
1771 }
1772
1773 /* ARGSUSED */
1774 static void
1775 echo_dg(int s, struct servtab *sep) /* Echo service -- echo data back */
1776 {
1777 char buffer[BUFSIZE];
1778 ssize_t i;
1779 socklen_t size;
1780 struct sockaddr_storage ss;
1781 struct sockaddr *sa;
1782
1783 sa = (struct sockaddr *)(void *)&ss;
1784 size = sizeof(ss);
1785 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, sa, &size)) < 0)
1786 return;
1787 if (port_good_dg(sa))
1788 (void) sendto(s, buffer, (size_t)i, 0, sa, size);
1789 }
1790
1791 /* ARGSUSED */
1792 static void
1793 discard_stream(int s, struct servtab *sep) /* Discard service -- ignore data */
1794 {
1795 char buffer[BUFSIZE];
1796
1797 inetd_setproctitle(sep->se_service, s);
1798 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1799 errno == EINTR)
1800 ;
1801 }
1802
1803 /* ARGSUSED */
1804 static void
1805 discard_dg(int s, struct servtab *sep) /* Discard service -- ignore data */
1806
1807 {
1808 char buffer[BUFSIZE];
1809
1810 (void) read(s, buffer, sizeof(buffer));
1811 }
1812
1813 #define LINESIZ 72
1814 char ring[128];
1815 char *endring;
1816
1817 static void
1818 initring(void)
1819 {
1820 int i;
1821
1822 endring = ring;
1823
1824 for (i = 0; i <= 128; ++i)
1825 if (isprint(i))
1826 *endring++ = (char)i;
1827 }
1828
1829 /* ARGSUSED */
1830 static void
1831 chargen_stream(int s, struct servtab *sep) /* Character generator */
1832 {
1833 size_t len;
1834 char *rs, text[LINESIZ+2];
1835
1836 inetd_setproctitle(sep->se_service, s);
1837
1838 if (endring == NULL) {
1839 initring();
1840 rs = ring;
1841 }
1842
1843 text[LINESIZ] = '\r';
1844 text[LINESIZ + 1] = '\n';
1845 for (rs = ring;;) {
1846 if ((len = (size_t)(endring - rs)) >= LINESIZ)
1847 memmove(text, rs, LINESIZ);
1848 else {
1849 memmove(text, rs, len);
1850 memmove(text + len, ring, LINESIZ - len);
1851 }
1852 if (++rs == endring)
1853 rs = ring;
1854 if (write(s, text, sizeof(text)) != sizeof(text))
1855 break;
1856 }
1857 }
1858
1859 /* ARGSUSED */
1860 static void
1861 chargen_dg(int s, struct servtab *sep) /* Character generator */
1862 {
1863 struct sockaddr_storage ss;
1864 struct sockaddr *sa;
1865 static char *rs;
1866 size_t len;
1867 socklen_t size;
1868 char text[LINESIZ+2];
1869
1870 if (endring == 0) {
1871 initring();
1872 rs = ring;
1873 }
1874
1875 sa = (struct sockaddr *)(void *)&ss;
1876 size = sizeof(ss);
1877 if (recvfrom(s, text, sizeof(text), 0, sa, &size) < 0)
1878 return;
1879
1880 if (!port_good_dg(sa))
1881 return;
1882
1883 if ((len = (size_t)(endring - rs)) >= LINESIZ)
1884 memmove(text, rs, LINESIZ);
1885 else {
1886 memmove(text, rs, len);
1887 memmove(text + len, ring, LINESIZ - len);
1888 }
1889 if (++rs == endring)
1890 rs = ring;
1891 text[LINESIZ] = '\r';
1892 text[LINESIZ + 1] = '\n';
1893 (void) sendto(s, text, sizeof(text), 0, sa, size);
1894 }
1895
1896 /*
1897 * Return a machine readable date and time, in the form of the
1898 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday
1899 * returns the number of seconds since midnight, Jan 1, 1970,
1900 * we must add 2208988800 seconds to this figure to make up for
1901 * some seventy years Bell Labs was asleep.
1902 */
1903
1904 static uint32_t
1905 machtime(void)
1906 {
1907 struct timeval tv;
1908
1909 if (gettimeofday(&tv, NULL) < 0) {
1910 DPRINTF("Unable to get time of day");
1911 return (0);
1912 }
1913 #define OFFSET ((uint32_t)25567 * 24*60*60)
1914 return (htonl((uint32_t)(tv.tv_sec + OFFSET)));
1915 #undef OFFSET
1916 }
1917
1918 /* ARGSUSED */
1919 static void
1920 machtime_stream(int s, struct servtab *sep)
1921 {
1922 uint32_t result;
1923
1924 result = machtime();
1925 (void) write(s, &result, sizeof(result));
1926 }
1927
1928 /* ARGSUSED */
1929 void
1930 machtime_dg(int s, struct servtab *sep)
1931 {
1932 uint32_t result;
1933 struct sockaddr_storage ss;
1934 struct sockaddr *sa;
1935 socklen_t size;
1936
1937 sa = (struct sockaddr *)(void *)&ss;
1938 size = sizeof(ss);
1939 if (recvfrom(s, &result, sizeof(result), 0, sa, &size) < 0)
1940 return;
1941 if (!port_good_dg(sa))
1942 return;
1943 result = machtime();
1944 (void)sendto(s, &result, sizeof(result), 0, sa, size);
1945 }
1946
1947 /* ARGSUSED */
1948 static void
1949 daytime_stream(int s,struct servtab *sep)
1950 /* Return human-readable time of day */
1951 {
1952 char buffer[256];
1953 time_t clk;
1954 int len;
1955
1956 clk = time((time_t *) 0);
1957
1958 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
1959 (void) write(s, buffer, (size_t)len);
1960 }
1961
1962 /* ARGSUSED */
1963 void
1964 daytime_dg(int s, struct servtab *sep)
1965 /* Return human-readable time of day */
1966 {
1967 char buffer[256];
1968 time_t clk;
1969 struct sockaddr_storage ss;
1970 struct sockaddr *sa;
1971 socklen_t size;
1972 int len;
1973
1974 clk = time((time_t *) 0);
1975
1976 sa = (struct sockaddr *)(void *)&ss;
1977 size = sizeof(ss);
1978 if (recvfrom(s, buffer, sizeof(buffer), 0, sa, &size) < 0)
1979 return;
1980 if (!port_good_dg(sa))
1981 return;
1982 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
1983 (void) sendto(s, buffer, (size_t)len, 0, sa, size);
1984 }
1985
1986 #ifdef DEBUG_ENABLE
1987 /*
1988 * print_service:
1989 * Dump relevant information to stderr
1990 */
1991 static void
1992 print_service(const char *action, struct servtab *sep)
1993 {
1994
1995 if (isrpcservice(sep))
1996 fprintf(stderr,
1997 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s"
1998 #ifdef IPSEC
1999 " policy=\"%s\""
2000 #endif
2001 "\n",
2002 action, sep->se_service,
2003 sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto,
2004 sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group,
2005 (long)sep->se_bi, sep->se_server
2006 #ifdef IPSEC
2007 , (sep->se_policy != NULL ? sep->se_policy : "")
2008 #endif
2009 );
2010 else
2011 fprintf(stderr,
2012 "%s: %s:%s proto=%s%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s"
2013 #ifdef IPSEC
2014 " policy=%s"
2015 #endif
2016 "\n",
2017 action, sep->se_hostaddr, sep->se_service,
2018 sep->se_type == FAITH_TYPE ? "faith/" : "",
2019 sep->se_proto,
2020 sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group,
2021 (long)sep->se_bi, sep->se_server
2022 #ifdef IPSEC
2023 , (sep->se_policy != NULL ? sep->se_policy : "")
2024 #endif
2025 );
2026 }
2027 #endif
2028
2029 static void
2030 usage(void)
2031 {
2032 #ifdef LIBWRAP
2033 (void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname());
2034 #else
2035 (void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname());
2036 #endif
2037 exit(EXIT_FAILURE);
2038 }
2039
2040
2041 /*
2042 * Based on TCPMUX.C by Mark K. Lottor November 1988
2043 * sri-nic::ps:<mkl>tcpmux.c
2044 */
2045
2046 static int /* # of characters upto \r,\n or \0 */
2047 get_line(int fd, char *buf, int len)
2048 {
2049 int count = 0;
2050 ssize_t n;
2051
2052 do {
2053 n = read(fd, buf, (size_t)(len - count));
2054 if (n == 0)
2055 return (count);
2056 if (n < 0)
2057 return (-1);
2058 while (--n >= 0) {
2059 if (*buf == '\r' || *buf == '\n' || *buf == '\0')
2060 return (count);
2061 count++;
2062 buf++;
2063 }
2064 } while (count < len);
2065 return (count);
2066 }
2067
2068 #define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */
2069
2070 #define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1)
2071
2072 static void
2073 tcpmux(int ctrl, struct servtab *sep)
2074 {
2075 char service[MAX_SERV_LEN+1];
2076 int len;
2077
2078 /* Get requested service name */
2079 if ((len = get_line(ctrl, service, MAX_SERV_LEN)) < 0) {
2080 strwrite(ctrl, "-Error reading service name\r\n");
2081 goto reject;
2082 }
2083 service[len] = '\0';
2084
2085 DPRINTF("tcpmux: %s: service requested", service);
2086
2087 /*
2088 * Help is a required command, and lists available services,
2089 * one per line.
2090 */
2091 if (strcasecmp(service, "help") == 0) {
2092 strwrite(ctrl, "+Available services:\r\n");
2093 strwrite(ctrl, "help\r\n");
2094 for (sep = servtab; sep != NULL; sep = sep->se_next) {
2095 if (!ISMUX(sep))
2096 continue;
2097 (void)write(ctrl, sep->se_service,
2098 strlen(sep->se_service));
2099 strwrite(ctrl, "\r\n");
2100 }
2101 goto reject;
2102 }
2103
2104 /* Try matching a service in inetd.conf with the request */
2105 for (sep = servtab; sep != NULL; sep = sep->se_next) {
2106 if (!ISMUX(sep))
2107 continue;
2108 if (strcasecmp(service, sep->se_service) == 0) {
2109 if (ISMUXPLUS(sep))
2110 strwrite(ctrl, "+Go\r\n");
2111 run_service(ctrl, sep, true /* forked */);
2112 return;
2113 }
2114 }
2115 strwrite(ctrl, "-Service not available\r\n");
2116 reject:
2117 _exit(EXIT_FAILURE);
2118 }
2119
2120 /*
2121 * check if the address/port where send data to is one of the obvious ports
2122 * that are used for denial of service attacks like two echo ports
2123 * just echoing data between them
2124 */
2125 static int
2126 port_good_dg(struct sockaddr *sa)
2127 {
2128 struct in_addr in;
2129 struct sockaddr_in *sin;
2130 #ifdef INET6
2131 struct in6_addr *in6;
2132 struct sockaddr_in6 *sin6;
2133 #endif
2134 u_int16_t port;
2135 int i;
2136 char hbuf[NI_MAXHOST];
2137
2138 switch (sa->sa_family) {
2139 case AF_INET:
2140 sin = (struct sockaddr_in *)(void *)sa;
2141 in.s_addr = ntohl(sin->sin_addr.s_addr);
2142 port = ntohs(sin->sin_port);
2143 #ifdef INET6
2144 v4chk:
2145 #endif
2146 if (IN_MULTICAST(in.s_addr))
2147 goto bad;
2148 switch ((in.s_addr & 0xff000000) >> 24) {
2149 case 0: case 127: case 255:
2150 goto bad;
2151 }
2152 if (dg_broadcast(&in))
2153 goto bad;
2154 break;
2155 #ifdef INET6
2156 case AF_INET6:
2157 sin6 = (struct sockaddr_in6 *)(void *)sa;
2158 in6 = &sin6->sin6_addr;
2159 port = ntohs(sin6->sin6_port);
2160 if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6))
2161 goto bad;
2162 if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) {
2163 memcpy(&in, &in6->s6_addr[12], sizeof(in));
2164 in.s_addr = ntohl(in.s_addr);
2165 goto v4chk;
2166 }
2167 break;
2168 #endif
2169 default:
2170 /* XXX unsupported af, is it safe to assume it to be safe? */
2171 return true;
2172 }
2173
2174 for (i = 0; bad_ports[i] != 0; i++) {
2175 if (port == bad_ports[i])
2176 goto bad;
2177 }
2178
2179 return true;
2180
2181 bad:
2182 if (getnameinfo(sa, sa->sa_len, hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
2183 niflags) != 0)
2184 strlcpy(hbuf, "?", sizeof(hbuf));
2185 syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d",
2186 hbuf, port);
2187 return false;
2188 }
2189
2190 /* XXX need optimization */
2191 static int
2192 dg_broadcast(struct in_addr *in)
2193 {
2194 struct ifaddrs *ifa, *ifap;
2195 struct sockaddr_in *sin;
2196
2197 if (getifaddrs(&ifap) < 0)
2198 return false;
2199 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
2200 if (ifa->ifa_addr->sa_family != AF_INET ||
2201 (ifa->ifa_flags & IFF_BROADCAST) == 0)
2202 continue;
2203 sin = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr;
2204 if (sin->sin_addr.s_addr == in->s_addr) {
2205 freeifaddrs(ifap);
2206 return true;
2207 }
2208 }
2209 freeifaddrs(ifap);
2210 return false;
2211 }
2212
2213 static int
2214 my_kevent(const struct kevent *changelist, size_t nchanges,
2215 struct kevent *eventlist, size_t nevents)
2216 {
2217 int result;
2218
2219 while ((result = kevent(kq, changelist, nchanges, eventlist, nevents,
2220 NULL)) < 0)
2221 if (errno != EINTR) {
2222 syslog(LOG_ERR, "kevent: %m");
2223 exit(EXIT_FAILURE);
2224 }
2225
2226 return (result);
2227 }
2228
2229 static struct kevent *
2230 allocchange(void)
2231 {
2232 if (changes == __arraycount(changebuf)) {
2233 (void) my_kevent(changebuf, __arraycount(changebuf), NULL, 0);
2234 changes = 0;
2235 }
2236
2237 return (&changebuf[changes++]);
2238 }
2239
2240 static void
2241 config_root(void)
2242 {
2243 struct servtab *sep;
2244 /* Uncheck services */
2245 for (sep = servtab; sep != NULL; sep = sep->se_next) {
2246 sep->se_checked = false;
2247 }
2248 defhost = newstr("*");
2249 #ifdef IPSEC
2250 policy = NULL;
2251 #endif
2252 fconfig = NULL;
2253 config();
2254 purge_unchecked();
2255 }
2256
2257 static void
2258 purge_unchecked(void)
2259 {
2260 struct servtab *sep, **sepp = &servtab;
2261 int servtab_count = 0;
2262 while ((sep = *sepp) != NULL) {
2263 if (sep->se_checked) {
2264 sepp = &sep->se_next;
2265 servtab_count++;
2266 continue;
2267 }
2268 *sepp = sep->se_next;
2269 if (sep->se_fd >= 0)
2270 close_sep(sep);
2271 if (isrpcservice(sep))
2272 unregister_rpc(sep);
2273 if (sep->se_family == AF_LOCAL)
2274 (void)unlink(sep->se_service);
2275 #ifdef DEBUG_ENABLE
2276 if (debug)
2277 print_service("FREE", sep);
2278 #endif
2279 freeconfig(sep);
2280 free(sep);
2281 }
2282 DPRINTF("%d service(s) loaded.", servtab_count);
2283 }
2284
2285 static bool
2286 is_same_service(const struct servtab *sep, const struct servtab *cp)
2287 {
2288 return
2289 strcmp(sep->se_service, cp->se_service) == 0 &&
2290 strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 &&
2291 strcmp(sep->se_proto, cp->se_proto) == 0 &&
2292 sep->se_family == cp->se_family &&
2293 ISMUX(sep) == ISMUX(cp);
2294 }
2295
2296 int
2297 parse_protocol(struct servtab *sep)
2298 {
2299 int val;
2300
2301 if (strcmp(sep->se_proto, "unix") == 0) {
2302 sep->se_family = AF_LOCAL;
2303 } else {
2304 val = (int)strlen(sep->se_proto);
2305 if (val == 0) {
2306 ERR("%s: invalid protocol specified",
2307 sep->se_service);
2308 return -1;
2309 }
2310 val = sep->se_proto[val - 1];
2311 switch (val) {
2312 case '4': /*tcp4 or udp4*/
2313 sep->se_family = AF_INET;
2314 break;
2315 #ifdef INET6
2316 case '6': /*tcp6 or udp6*/
2317 sep->se_family = AF_INET6;
2318 break;
2319 #endif
2320 default:
2321 /* Use 'default' IP version which is IPv4, may eventually be
2322 * changed to AF_INET6 */
2323 sep->se_family = AF_INET;
2324 break;
2325 }
2326 if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
2327 #ifdef RPC
2328 char *cp1, *ccp;
2329 cp1 = strchr(sep->se_service, '/');
2330 if (cp1 == 0) {
2331 ERR("%s: no rpc version",
2332 sep->se_service);
2333 return -1;
2334 }
2335 *cp1++ = '\0';
2336 sep->se_rpcversl = sep->se_rpcversh =
2337 (int)strtol(cp1, &ccp, 0);
2338 if (ccp == cp1) {
2339 badafterall:
2340 ERR("%s/%s: bad rpc version",
2341 sep->se_service, cp1);
2342 return -1;
2343 }
2344 if (*ccp == '-') {
2345 cp1 = ccp + 1;
2346 sep->se_rpcversh = (int)strtol(cp1, &ccp, 0);
2347 if (ccp == cp1)
2348 goto badafterall;
2349 }
2350 #else
2351 ERR("%s: rpc services not supported",
2352 sep->se_service);
2353 return -1;
2354 #endif /* RPC */
2355 }
2356 }
2357 return 0;
2358 }
2359
2360 int
2361 parse_wait(struct servtab *sep, int wait)
2362 {
2363 if (!ISMUX(sep)) {
2364 sep->se_wait = wait;
2365 return 0;
2366 }
2367 /*
2368 * Silently enforce "nowait" for TCPMUX services since
2369 * they don't have an assigned port to listen on.
2370 */
2371 sep->se_wait = 0;
2372
2373 if (strncmp(sep->se_proto, "tcp", 3)) {
2374 ERR("bad protocol for tcpmux service %s",
2375 sep->se_service);
2376 return -1;
2377 }
2378 if (sep->se_socktype != SOCK_STREAM) {
2379 ERR("bad socket type for tcpmux service %s",
2380 sep->se_service);
2381 return -1;
2382 }
2383 return 0;
2384 }
2385
2386 int
2387 parse_server(struct servtab *sep, const char *arg){
2388 sep->se_server = newstr(arg);
2389 if (strcmp(sep->se_server, "internal") != 0) {
2390 sep->se_bi = NULL;
2391 return 0;
2392 }
2393 struct biltin *bi;
2394
2395 for (bi = biltins; bi->bi_service; bi++)
2396 if (bi->bi_socktype == sep->se_socktype &&
2397 strcmp(bi->bi_service, sep->se_service) == 0)
2398 break;
2399 if (bi->bi_service == NULL) {
2400 ERR("Internal service %s unknown",
2401 sep->se_service);
2402 return -1;
2403 }
2404 sep->se_bi = bi;
2405 sep->se_wait = bi->bi_wait;
2406 return 0;
2407 }
2408
2409 /* TODO test to make sure accept filter still works */
2410 void
2411 parse_accept_filter(char *arg, struct servtab *sep) {
2412 char *accf, *accf_arg;
2413 /* one and only one accept filter */
2414 accf = strchr(arg, ':');
2415 if (accf == NULL)
2416 return;
2417 if (accf != strrchr(arg, ':') || *(accf + 1) == '\0') {
2418 /* more than one || nothing beyond */
2419 sep->se_socktype = -1;
2420 return;
2421 }
2422
2423 accf++; /* skip delimiter */
2424 strlcpy(sep->se_accf.af_name, accf, sizeof(sep->se_accf.af_name));
2425 accf_arg = strchr(accf, ',');
2426 if (accf_arg == NULL) /* zero or one arg, no more */
2427 return;
2428
2429 if (strrchr(accf, ',') != accf_arg) {
2430 sep->se_socktype = -1;
2431 } else {
2432 accf_arg++;
2433 strlcpy(sep->se_accf.af_arg, accf_arg,
2434 sizeof(sep->se_accf.af_arg));
2435 }
2436 }
2437
2438 void
2439 parse_socktype(char* arg, struct servtab* sep)
2440 {
2441 /* stream socket may have an accept filter, only check first chars */
2442 if (strncmp(arg, "stream", sizeof("stream") - 1) == 0)
2443 sep->se_socktype = SOCK_STREAM;
2444 else if (strcmp(arg, "dgram") == 0)
2445 sep->se_socktype = SOCK_DGRAM;
2446 else if (strcmp(arg, "rdm") == 0)
2447 sep->se_socktype = SOCK_RDM;
2448 else if (strcmp(arg, "seqpacket") == 0)
2449 sep->se_socktype = SOCK_SEQPACKET;
2450 else if (strcmp(arg, "raw") == 0)
2451 sep->se_socktype = SOCK_RAW;
2452 else
2453 sep->se_socktype = -1;
2454 }
2455
2456 static struct servtab
2457 init_servtab(void)
2458 {
2459 /* This does not set every field to default. See enter() as well */
2460 return (struct servtab) {
2461 /*
2462 * Set se_max to non-zero so uninitialized value is not
2463 * a valid value. Useful in v2 syntax parsing.
2464 */
2465 .se_service_max = SERVTAB_UNSPEC_SIZE_T,
2466 .se_ip_max = SERVTAB_UNSPEC_SIZE_T,
2467 .se_wait = SERVTAB_UNSPEC_VAL,
2468 .se_socktype = SERVTAB_UNSPEC_VAL
2469 /* All other fields initialized to 0 or null */
2470 };
2471 }
2472
2473 /* Include directives bookkeeping structure */
2474 struct file_list {
2475 /* Absolute path used for checking for circular references */
2476 char *abs;
2477 /* Pointer to the absolute path of the parent config file,
2478 * on the stack */
2479 struct file_list *next;
2480 } *file_list_head;
2481
2482 static void
2483 include_configs(char *pattern)
2484 {
2485 /* Allocate global per-config state on the thread stack */
2486 const char* save_CONFIG;
2487 FILE *save_fconfig;
2488 size_t save_line_number;
2489 char *save_defhost;
2490 struct file_list new_file;
2491 #ifdef IPSEC
2492 char *save_policy;
2493 #endif
2494
2495 /* Store current globals on the stack */
2496 save_CONFIG = CONFIG;
2497 save_fconfig = fconfig;
2498 save_line_number = line_number;
2499 save_defhost = defhost;
2500 new_file.abs = realpath(CONFIG, NULL);
2501 new_file.next = file_list_head;
2502 #ifdef IPSEC
2503 save_policy = policy;
2504 #endif
2505 /* Put new_file at the top of the config stack */
2506 file_list_head = &new_file;
2507 read_glob_configs(pattern);
2508 free((void *)new_file.abs);
2509 /* Pop new_file off the stack */
2510 file_list_head = new_file.next;
2511
2512 /* Restore global per-config state */
2513 CONFIG = save_CONFIG;
2514 fconfig = save_fconfig;
2515 line_number = save_line_number;
2516 defhost = save_defhost;
2517 #ifdef IPSEC
2518 policy = save_policy;
2519 #endif
2520 }
2521
2522 static void
2523 prepare_next_config(const char *file_name)
2524 {
2525 /* Setup new state that is normally only done in main */
2526 CONFIG = file_name;
2527
2528 /* Inherit default host and IPsec policy */
2529 defhost = newstr(defhost);
2530
2531 #ifdef IPSEC
2532 policy = (policy == NULL) ? NULL : newstr(policy);
2533 #endif
2534 }
2535
2536 static void
2537 read_glob_configs(char *pattern) {
2538 glob_t results;
2539 char *full_pattern;
2540 int glob_result;
2541 full_pattern = gen_file_pattern(CONFIG, pattern);
2542
2543 DPRINTCONF("Found include directive '%s'", full_pattern);
2544
2545 glob_result = glob(full_pattern, GLOB_NOSORT, glob_error, &results);
2546 switch(glob_result) {
2547 case 0:
2548 /* No glob errors */
2549 break;
2550 case GLOB_ABORTED:
2551 ERR("Error while searching for include files");
2552 break;
2553 case GLOB_NOMATCH:
2554 /* It's fine if no files were matched. */
2555 DPRINTCONF("No files matched pattern '%s'", full_pattern);
2556 break;
2557 case GLOB_NOSPACE:
2558 ERR("Error when searching for include files: %s",
2559 strerror(errno));
2560 break;
2561 default:
2562 ERR("Unknown glob(3) error %d", errno);
2563 break;
2564 }
2565 free(full_pattern);
2566
2567 for (size_t i = 0; i < results.gl_pathc; i++) {
2568 include_matched_path(results.gl_pathv[i]);
2569 }
2570
2571 globfree(&results);
2572 }
2573
2574 static void
2575 include_matched_path(char *glob_path)
2576 {
2577 struct stat sb;
2578 char *tmp;
2579
2580 if (lstat(glob_path, &sb) != 0) {
2581 ERR("Error calling stat on path '%s': %s", glob_path,
2582 strerror(errno));
2583 return;
2584 }
2585
2586 if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode)) {
2587 DPRINTCONF("'%s' is not a file.", glob_path);
2588 ERR("The matched path '%s' is not a regular file", glob_path);
2589 return;
2590 }
2591
2592 DPRINTCONF("Include '%s'", glob_path);
2593
2594 if (S_ISLNK(sb.st_mode)) {
2595 tmp = glob_path;
2596 glob_path = realpath(tmp, NULL);
2597 }
2598
2599 /* Ensure the file is not being reincluded .*/
2600 if (check_no_reinclude(glob_path)) {
2601 prepare_next_config(glob_path);
2602 config();
2603 } else {
2604 DPRINTCONF("File '%s' already included in current include "
2605 "chain", glob_path);
2606 WRN("Including file '%s' would cause a circular "
2607 "dependency", glob_path);
2608 }
2609
2610 if (S_ISLNK(sb.st_mode)) {
2611 free(glob_path);
2612 glob_path = tmp;
2613 }
2614 }
2615
2616 static bool
2617 check_no_reinclude(const char *glob_path)
2618 {
2619 struct file_list *cur = file_list_head;
2620 char *abs_path = realpath(glob_path, NULL);
2621
2622 if (abs_path == NULL) {
2623 ERR("Error checking real path for '%s': %s",
2624 glob_path, strerror(errno));
2625 return false;
2626 }
2627
2628 DPRINTCONF("Absolute path '%s'", abs_path);
2629
2630 for (cur = file_list_head; cur != NULL; cur = cur->next) {
2631 if (strcmp(cur->abs, abs_path) == 0) {
2632 /* file included more than once */
2633 /* TODO relative or abs path for logging error? */
2634 free(abs_path);
2635 return false;
2636 }
2637 }
2638 free(abs_path);
2639 return true;
2640 }
2641
2642 /* Resolve the pattern relative to the config file the pattern is from */
2643 static char *
2644 gen_file_pattern(const char *cur_config, const char *pattern)
2645 {
2646 if (pattern[0] == '/') {
2647 /* Absolute paths don't need any normalization */
2648 return newstr(pattern);
2649 }
2650
2651 /* pattern is relative */
2652 /* Find the end of the file's directory */
2653 size_t i, last = 0;
2654 for (i = 0; cur_config[i] != '\0'; i++) {
2655 if (cur_config[i] == '/') {
2656 last = i;
2657 }
2658 }
2659
2660 if (last == 0) {
2661 /* cur_config is just a filename, pattern already correct */
2662 return newstr(pattern);
2663 }
2664
2665 /* Relativize pattern to cur_config file's directory */
2666 char *full_pattern = malloc(last + 1 + strlen(pattern) + 1);
2667 if (full_pattern == NULL) {
2668 syslog(LOG_ERR, "Out of memory.");
2669 exit(EXIT_FAILURE);
2670 }
2671 memcpy(full_pattern, cur_config, last);
2672 full_pattern[last] = '/';
2673 strcpy(&full_pattern[last + 1], pattern);
2674 return full_pattern;
2675 }
2676
2677 static int
2678 glob_error(const char *path, int error)
2679 {
2680 WRN("Error while resolving path '%s': %s", path, strerror(error));
2681 return 0;
2682 }
2683
2684 /* Return 0 on allow, -1 if connection should be blocked */
2685 static int
2686 rl_process(struct servtab *sep, int ctrl)
2687 {
2688 struct se_ip_list_node *node;
2689 time_t now = 0; /* 0 prevents GCC from complaining */
2690 bool istimevalid = false;
2691 char hbuf[NI_MAXHOST];
2692
2693 DPRINTF(SERV_FMT ": processing rate-limiting",
2694 SERV_PARAMS(sep));
2695 DPRINTF(SERV_FMT ": se_service_max "
2696 "%zu and se_count %zu", SERV_PARAMS(sep),
2697 sep->se_service_max, sep->se_count);
2698
2699 /* se_count is incremented if rl_process will return 0 */
2700 if (sep->se_count == 0) {
2701 now = rl_time();
2702 sep->se_time = now;
2703 istimevalid = true;
2704 }
2705
2706 if (sep->se_count >= sep->se_service_max) {
2707 if(!istimevalid) {
2708 now = rl_time();
2709 istimevalid = true;
2710 }
2711
2712 if (now - sep->se_time > CNT_INTVL) {
2713 rl_reset(sep, now);
2714 } else {
2715 syslog(LOG_ERR,
2716 SERV_FMT ": max spawn rate (%zu in %ji seconds) "
2717 "already met, closing until end of timeout in "
2718 "%ju seconds",
2719 SERV_PARAMS(sep),
2720 sep->se_service_max,
2721 (intmax_t)CNT_INTVL,
2722 (uintmax_t)RETRYTIME);
2723
2724 DPRINTF(SERV_FMT ": service not started",
2725 SERV_PARAMS(sep));
2726
2727 rl_drop_connection(sep, ctrl);
2728
2729 /* Close the server for 10 minutes */
2730 close_sep(sep);
2731 if (!timingout) {
2732 timingout = true;
2733 alarm(RETRYTIME);
2734 }
2735
2736 return -1;
2737 }
2738 }
2739
2740 if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) {
2741 rl_get_name(sep, ctrl, hbuf);
2742 node = rl_try_get_ip(sep, hbuf);
2743 if(node == NULL) {
2744 node = rl_add(sep, hbuf);
2745 }
2746
2747 DPRINTF(
2748 SERV_FMT ": se_ip_max %zu and ip_count %zu",
2749 SERV_PARAMS(sep), sep->se_ip_max, node->count);
2750
2751 if (node->count >= sep->se_ip_max) {
2752 if (!istimevalid) {
2753 /*
2754 * Only get the clock time if we didn't
2755 * already
2756 */
2757 now = rl_time();
2758 istimevalid = true;
2759 }
2760
2761 if (now - sep->se_time > CNT_INTVL) {
2762 rl_reset(sep, now);
2763 node = rl_add(sep, hbuf);
2764 } else {
2765 if (debug && node->count == sep->se_ip_max) {
2766 /*
2767 * Only log first failed request to
2768 * prevent DoS attack writing to system
2769 * log
2770 */
2771 syslog(LOG_ERR, SERV_FMT
2772 ": max ip spawn rate (%zu in "
2773 "%ji seconds) for "
2774 "%." TOSTRING(NI_MAXHOST) "s "
2775 "already met; service not started",
2776 SERV_PARAMS(sep),
2777 sep->se_ip_max,
2778 (intmax_t)CNT_INTVL,
2779 node->address);
2780 }
2781
2782 DPRINTF(SERV_FMT ": service not started",
2783 SERV_PARAMS(sep));
2784
2785 rl_drop_connection(sep, ctrl);
2786 /*
2787 * Increment so debug-syslog message will
2788 * trigger only once
2789 */
2790 node->count++;
2791 return -1;
2792 }
2793 }
2794 node->count++;
2795 }
2796
2797 DPRINTF(SERV_FMT ": running service ", SERV_PARAMS(sep));
2798
2799 sep->se_count++;
2800 return 0;
2801 }
2802
2803 /* Get the remote's IP address in textual form into hbuf of size NI_MAXHOST */
2804 static void
2805 rl_get_name(struct servtab *sep, int ctrl, char *hbuf)
2806 {
2807 struct sockaddr_storage addr;
2808 socklen_t len = sizeof(struct sockaddr_storage);
2809 switch (sep->se_socktype) {
2810 case SOCK_STREAM:
2811 if (getpeername(ctrl, (struct sockaddr *)&addr, &len) != 0) {
2812 /* error, log it and skip ip rate limiting */
2813 syslog(LOG_ERR,
2814 SERV_FMT " failed to get peer name of the "
2815 "connection", SERV_PARAMS(sep));
2816 exit(EXIT_FAILURE);
2817 }
2818 break;
2819 case SOCK_DGRAM: {
2820 struct msghdr header = {
2821 .msg_name = &addr,
2822 .msg_namelen = sizeof(struct sockaddr_storage),
2823 /* scatter/gather and control info is null */
2824 };
2825 ssize_t count;
2826
2827 /* Peek so service can still get the packet */
2828 count = recvmsg(ctrl, &header, MSG_PEEK);
2829 if (count == -1) {
2830 syslog(LOG_ERR,
2831 "failed to get dgram source address: %s; exiting",
2832 strerror(errno));
2833 exit(EXIT_FAILURE);
2834 }
2835 break;
2836 }
2837 default:
2838 DPRINTF(SERV_FMT ": ip_max rate limiting not supported for "
2839 "socktype", SERV_PARAMS(sep));
2840 syslog(LOG_ERR, SERV_FMT
2841 ": ip_max rate limiting not supported for socktype",
2842 SERV_PARAMS(sep));
2843 exit(EXIT_FAILURE);
2844 }
2845
2846 if (getnameinfo((struct sockaddr *)&addr,
2847 addr.ss_len, hbuf,
2848 NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) {
2849 /* error, log it and skip ip rate limiting */
2850 syslog(LOG_ERR,
2851 SERV_FMT ": failed to get name info of the incoming "
2852 "connection; exiting",
2853 SERV_PARAMS(sep));
2854 exit(EXIT_FAILURE);
2855 }
2856 }
2857
2858 static void
2859 rl_drop_connection(struct servtab *sep, int ctrl)
2860 {
2861
2862 if (sep->se_wait == 0 && sep->se_socktype == SOCK_STREAM) {
2863 /*
2864 * If the fd isn't a listen socket,
2865 * close the individual connection too.
2866 */
2867 close(ctrl);
2868 return;
2869 }
2870 if (sep->se_socktype != SOCK_DGRAM) {
2871 return;
2872 }
2873 /*
2874 * Drop the single datagram the service would have
2875 * consumed if nowait. If this is a wait service, this
2876 * will consume 1 datagram, and further received packets
2877 * will be removed in the same way.
2878 */
2879 struct msghdr header = {
2880 /* All fields null, just consume one message */
2881 };
2882 ssize_t count;
2883
2884 count = recvmsg(ctrl, &header, 0);
2885 if (count == -1) {
2886 syslog(LOG_ERR,
2887 SERV_FMT ": failed to consume nowait dgram: %s",
2888 SERV_PARAMS(sep), strerror(errno));
2889 exit(EXIT_FAILURE);
2890 }
2891 DPRINTF(SERV_FMT ": dropped dgram message",
2892 SERV_PARAMS(sep));
2893 }
2894
2895 static time_t
2896 rl_time(void)
2897 {
2898 struct timespec time;
2899 if(clock_gettime(CLOCK_MONOTONIC, &time) == -1) {
2900 syslog(LOG_ERR, "clock_gettime for rate limiting failed: %s; "
2901 "exiting", strerror(errno));
2902 /* Exit inetd if rate limiting fails */
2903 exit(EXIT_FAILURE);
2904 }
2905 return time.tv_sec;
2906 }
2907
2908 static struct se_ip_list_node*
2909 rl_add(struct servtab *sep, char* ip)
2910 {
2911 DPRINTF(
2912 SERV_FMT ": add ip %s to rate limiting tracking",
2913 SERV_PARAMS(sep), ip);
2914
2915 /*
2916 * TODO memory could be saved by using a variable length malloc
2917 * with only the length of ip instead of the existing address field
2918 * NI_MAXHOST in length.
2919 */
2920 struct se_ip_list_node* temp = malloc(sizeof(*temp));
2921 if (temp == NULL) {
2922 syslog(LOG_ERR, "Out of memory.");
2923 exit(EXIT_FAILURE);
2924 }
2925 temp->count = 0;
2926 temp->next = NULL;
2927 strlcpy(temp->address, ip, sizeof(temp->address));
2928
2929 if (sep->se_ip_list_head == NULL) {
2930 /* List empty, insert as head */
2931 sep->se_ip_list_head = temp;
2932 } else {
2933 /* List not empty, insert as head, point next to prev head */
2934 temp->next = sep->se_ip_list_head;
2935 sep->se_ip_list_head = temp;
2936 }
2937
2938 return temp;
2939 }
2940
2941 static void
2942 rl_reset(struct servtab *sep, time_t now)
2943 {
2944 DPRINTF(SERV_FMT ": %ji seconds passed; resetting rate limiting ",
2945 SERV_PARAMS(sep), (intmax_t)(now - sep->se_time));
2946
2947 sep->se_count = 0;
2948 sep->se_time = now;
2949 if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) {
2950 clear_ip_list(sep);
2951 }
2952 }
2953
2954 static void
2955 clear_ip_list(struct servtab *sep) {
2956 struct se_ip_list_node *curr, *next;
2957 curr = sep->se_ip_list_head;
2958
2959 while (curr != NULL) {
2960 next = curr->next;
2961 free(curr);
2962 curr = next;
2963 }
2964 sep->se_ip_list_head = NULL;
2965 }
2966
2967 static struct se_ip_list_node *
2968 rl_try_get_ip(struct servtab *sep, char *ip)
2969 {
2970 struct se_ip_list_node *curr;
2971
2972 DPRINTF(
2973 SERV_FMT ": look up ip %s for ip_max rate limiting",
2974 SERV_PARAMS(sep), ip);
2975
2976 for (curr = sep->se_ip_list_head; curr != NULL; curr = curr->next) {
2977 if (!strncmp(curr->address, ip, NI_MAXHOST)) {
2978 /* IP addr match */
2979 return curr;
2980 }
2981 }
2982 return NULL;
2983 }
2984