inetd.c revision 1.132 1 /* $NetBSD: inetd.c,v 1.132 2021/08/31 19:34:42 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.132 2021/08/31 19:34:42 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, 1, 0, echo_stream },
341 { "echo", SOCK_DGRAM, 0, 0, echo_dg },
342
343 /* Internet /dev/null */
344 { "discard", SOCK_STREAM, 1, 0, discard_stream },
345 { "discard", SOCK_DGRAM, 0, 0, discard_dg },
346
347 /* Return 32 bit time since 1970 */
348 { "time", SOCK_STREAM, 0, 0, machtime_stream },
349 { "time", SOCK_DGRAM, 0, 0, machtime_dg },
350
351 /* Return human-readable time */
352 { "daytime", SOCK_STREAM, 0, 0, daytime_stream },
353 { "daytime", SOCK_DGRAM, 0, 0, daytime_dg },
354
355 /* Familiar character generator */
356 { "chargen", SOCK_STREAM, 1, 0, chargen_stream },
357 { "chargen", SOCK_DGRAM, 0, 0, chargen_dg },
358
359 { "tcpmux", SOCK_STREAM, 1, 0, tcpmux },
360
361 { NULL, 0, 0, 0, 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 = 1;
393 options |= SO_DEBUG;
394 break;
395 #ifdef LIBWRAP
396 case 'l':
397 lflag = 1;
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 = 0;
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 = 1;
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 && 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 = 1;
512 #else
513 dofork = (sep->se_bi == 0 || 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 && sep->se_socktype == SOCK_STREAM)
523 close(ctrl);
524 sleep(1);
525 return;
526 }
527 if (pid != 0 && sep->se_wait) {
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 && 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 && sep->se_socktype == SOCK_STREAM) {
572 request_init(&req, RQ_DAEMON, sep->se_argv[0] ?
573 sep->se_argv[0] : sep->se_service, RQ_FILE, ctrl, NULL);
574 fromhost(&req);
575 denied = !hosts_access(&req);
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) {
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) {
607 if (didfork) {
608 for (s = servtab; s; 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 &&
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) {
628 if (sep->se_group)
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) {
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 = 0;
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, "*"))
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) {
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 = 0;
860 continue;
861 }
862 if (res->ai_next) {
863 syslog(LOG_ERR,
864 SERV_FMT ": %s: resolved to multiple addr",
865 SERV_PARAMS(sep),
866 sep->se_hostaddr);
867 sep->se_checked = 0;
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 = 0;
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 = 0;
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 = 1;
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))
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))
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) {
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 /*NOTREACHED*/ \
1416 } while (/*CONSTCOND*/0)
1417
1418 #define GETVAL(arg) \
1419 do { \
1420 if (!isdigit((unsigned char)*(arg))) \
1421 MALFORMED(arg); \
1422 val = (int)strtol((arg), &cp0, 10); \
1423 if (cp0 != NULL) { \
1424 if (cp0[1] != '\0') \
1425 MALFORMED((arg)); \
1426 if (cp0[0] == 'k') \
1427 val *= 1024; \
1428 if (cp0[0] == 'm') \
1429 val *= 1024 * 1024; \
1430 } \
1431 if (val < 1) { \
1432 ERR("%s: invalid buffer size `%s'", \
1433 sep->se_service, (arg)); \
1434 freeconfig(sep); \
1435 goto more; \
1436 } \
1437 /*NOTREACHED*/ \
1438 } while (/*CONSTCOND*/0)
1439
1440 #define ASSIGN(arg) \
1441 do { \
1442 if (strcmp((arg), "sndbuf") == 0) \
1443 sep->se_sndbuf = val; \
1444 else if (strcmp((arg), "rcvbuf") == 0) \
1445 sep->se_rcvbuf = val; \
1446 else \
1447 MALFORMED((arg)); \
1448 } while (/*CONSTCOND*/0)
1449
1450 /*
1451 * Extract the send and receive buffer sizes before parsing
1452 * the protocol.
1453 */
1454 sep->se_sndbuf = sep->se_rcvbuf = 0;
1455 buf0 = buf1 = sz0 = sz1 = NULL;
1456 if ((buf0 = strchr(sep->se_proto, ',')) != NULL) {
1457 /* Not meaningful for Tcpmux services. */
1458 if (ISMUX(sep)) {
1459 ERR("%s: can't specify buffer sizes for "
1460 "tcpmux services", sep->se_service);
1461 goto more;
1462 }
1463
1464 /* Skip the , */
1465 *buf0++ = '\0';
1466
1467 /* Check to see if another socket buffer size was specified. */
1468 if ((buf1 = strchr(buf0, ',')) != NULL) {
1469 /* Skip the , */
1470 *buf1++ = '\0';
1471
1472 /* Make sure a 3rd one wasn't specified. */
1473 if (strchr(buf1, ',') != NULL) {
1474 ERR("%s: too many buffer sizes", sep->se_service);
1475 goto more;
1476 }
1477
1478 /* Locate the size. */
1479 if ((sz1 = strchr(buf1, '=')) == NULL)
1480 MALFORMED(buf1);
1481
1482 /* Skip the = */
1483 *sz1++ = '\0';
1484 }
1485
1486 /* Locate the size. */
1487 if ((sz0 = strchr(buf0, '=')) == NULL)
1488 MALFORMED(buf0);
1489
1490 /* Skip the = */
1491 *sz0++ = '\0';
1492
1493 GETVAL(sz0);
1494 ASSIGN(buf0);
1495
1496 if (buf1 != NULL) {
1497 GETVAL(sz1);
1498 ASSIGN(buf1);
1499 }
1500 }
1501
1502 #undef ASSIGN
1503 #undef GETVAL
1504 #undef MALFORMED
1505
1506 if (parse_protocol(sep)) {
1507 freeconfig(sep);
1508 goto more;
1509 }
1510
1511 /* wait/nowait:max */
1512 arg = skip(&cp);
1513 if (arg == NULL) {
1514 LOG_TOO_FEW_ARGS();
1515 freeconfig(sep);
1516 goto more;
1517 }
1518
1519 /* Rate limiting parsing */ {
1520 char *cp1;
1521 if ((cp1 = strchr(arg, ':')) == NULL)
1522 cp1 = strchr(arg, '.');
1523 if (cp1 != NULL) {
1524 int rstatus;
1525 *cp1++ = '\0';
1526 sep->se_service_max = (size_t)strtou(cp1, NULL, 10, 0,
1527 SERVTAB_COUNT_MAX, &rstatus);
1528
1529 if (rstatus != 0) {
1530 if (rstatus != ERANGE) {
1531 /* For compatibility with atoi parsing */
1532 sep->se_service_max = 0;
1533 }
1534
1535 WRN("Improper \"max\" value '%s', "
1536 "using '%zu' instead: %s",
1537 cp1,
1538 sep->se_service_max,
1539 strerror(rstatus));
1540 }
1541
1542 } else
1543 sep->se_service_max = TOOMANY;
1544 }
1545 if (parse_wait(sep, strcmp(arg, "wait") == 0)) {
1546 freeconfig(sep);
1547 goto more;
1548 }
1549
1550 /* Parse user:group token */
1551 arg = skip(&cp);
1552 if(arg == NULL) {
1553 LOG_TOO_FEW_ARGS();
1554 freeconfig(sep);
1555 goto more;
1556 }
1557 char* separator = strchr(arg, ':');
1558 if (separator == NULL) {
1559 /* Backwards compatibility, allow dot instead of colon */
1560 separator = strchr(arg, '.');
1561 }
1562
1563 if (separator == NULL) {
1564 /* Only user was specified */
1565 sep->se_group = NULL;
1566 } else {
1567 *separator = '\0';
1568 sep->se_group = newstr(separator + 1);
1569 }
1570
1571 sep->se_user = newstr(arg);
1572
1573 /* Parser server-program (path to binary or "internal") */
1574 arg = skip(&cp);
1575 if (arg == NULL) {
1576 LOG_TOO_FEW_ARGS();
1577 freeconfig(sep);
1578 goto more;
1579 }
1580 if (parse_server(sep, arg)) {
1581 freeconfig(sep);
1582 goto more;
1583 }
1584
1585 argc = 0;
1586 for (arg = skip(&cp); cp; arg = skip(&cp)) {
1587 if (argc < MAXARGV)
1588 sep->se_argv[argc++] = newstr(arg);
1589 }
1590 while (argc <= MAXARGV)
1591 sep->se_argv[argc++] = NULL;
1592 #ifdef IPSEC
1593 sep->se_policy = policy ? newstr(policy) : NULL;
1594 #endif
1595 /* getconfigent read a positional service def, move to next line */
1596 *current_pos = nextline(fconfig);
1597 return (sep);
1598 }
1599
1600 void
1601 freeconfig(struct servtab *cp)
1602 {
1603 int i;
1604
1605 if (cp->se_hostaddr)
1606 free(cp->se_hostaddr);
1607 if (cp->se_service)
1608 free(cp->se_service);
1609 if (cp->se_proto)
1610 free(cp->se_proto);
1611 if (cp->se_user)
1612 free(cp->se_user);
1613 if(cp->se_group)
1614 free(cp->se_group);
1615 if (cp->se_server)
1616 free(cp->se_server);
1617 for (i = 0; i < MAXARGV; i++)
1618 if (cp->se_argv[i])
1619 free(cp->se_argv[i]);
1620 #ifdef IPSEC
1621 if (cp->se_policy)
1622 free(cp->se_policy);
1623 #endif
1624 }
1625
1626 /*
1627 * Get next token *in the current service definition* from config file.
1628 * Allows multi-line parse if single space or single tab-indented.
1629 * Things in quotes are considered single token.
1630 * Advances cp to next token.
1631 */
1632 static char *
1633 skip(char **cpp)
1634 {
1635 char *cp = *cpp;
1636 char *start;
1637 char quote;
1638
1639 if (*cpp == NULL)
1640 return (NULL);
1641
1642 again:
1643 while (*cp == ' ' || *cp == '\t')
1644 cp++;
1645 if (*cp == '\0') {
1646 int c;
1647
1648 c = getc(fconfig);
1649 (void) ungetc(c, fconfig);
1650 if (c == ' ' || c == '\t')
1651 if ((cp = nextline(fconfig)) != NULL)
1652 goto again;
1653 *cpp = NULL;
1654 return (NULL);
1655 }
1656 start = cp;
1657 /* Parse shell-style quotes */
1658 quote = '\0';
1659 while (*cp && (quote || (*cp != ' ' && *cp != '\t'))) {
1660 if (*cp == '\'' || *cp == '"') {
1661 if (quote && *cp != quote)
1662 cp++;
1663 else {
1664 if (quote)
1665 quote = '\0';
1666 else
1667 quote = *cp;
1668 memmove(cp, cp+1, strlen(cp));
1669 }
1670 } else
1671 cp++;
1672 }
1673 if (*cp != '\0')
1674 *cp++ = '\0';
1675 *cpp = cp;
1676 return (start);
1677 }
1678
1679 char *
1680 nextline(FILE *fd)
1681 {
1682 char *cp;
1683
1684 if (fgets(line, (int)sizeof(line), fd) == NULL) {
1685 if (ferror(fd)) {
1686 ERR("Error when reading next line: %s", strerror(errno));
1687 }
1688 return NULL;
1689 }
1690 cp = strchr(line, '\n');
1691 if (cp)
1692 *cp = '\0';
1693 line_number++;
1694 return line;
1695 }
1696
1697 char *
1698 newstr(const char *cp)
1699 {
1700 char *dp;
1701 if ((dp = strdup((cp != NULL) ? cp : "")) != NULL)
1702 return (dp);
1703 syslog(LOG_ERR, "strdup: %m");
1704 exit(EXIT_FAILURE);
1705 /*NOTREACHED*/
1706 }
1707
1708 static void
1709 inetd_setproctitle(char *a, int s)
1710 {
1711 socklen_t size;
1712 struct sockaddr_storage ss;
1713 char hbuf[NI_MAXHOST];
1714 const char *hp;
1715 struct sockaddr *sa;
1716
1717 size = sizeof(ss);
1718 sa = (struct sockaddr *)(void *)&ss;
1719 if (getpeername(s, sa, &size) == 0) {
1720 if (getnameinfo(sa, size, hbuf, (socklen_t)sizeof(hbuf), NULL,
1721 0, niflags) != 0)
1722 hp = "?";
1723 else
1724 hp = hbuf;
1725 setproctitle("-%s [%s]", a, hp);
1726 } else
1727 setproctitle("-%s", a);
1728 }
1729
1730 static void
1731 bump_nofile(void)
1732 {
1733 #define FD_CHUNK 32
1734 struct rlimit rl;
1735
1736 if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
1737 syslog(LOG_ERR, "getrlimit: %m");
1738 return;
1739 }
1740 rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
1741 if (rl.rlim_cur <= rlim_ofile_cur) {
1742 syslog(LOG_ERR,
1743 "bump_nofile: cannot extend file limit, max = %d",
1744 (int)rl.rlim_cur);
1745 return;
1746 }
1747
1748 if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
1749 syslog(LOG_ERR, "setrlimit: %m");
1750 return;
1751 }
1752
1753 rlim_ofile_cur = rl.rlim_cur;
1754 return;
1755 }
1756
1757 /*
1758 * Internet services provided internally by inetd:
1759 */
1760 #define BUFSIZE 4096
1761
1762 /* ARGSUSED */
1763 static void
1764 echo_stream(int s, struct servtab *sep) /* Echo service -- echo data back */
1765 {
1766 char buffer[BUFSIZE];
1767 ssize_t i;
1768
1769 inetd_setproctitle(sep->se_service, s);
1770 while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
1771 write(s, buffer, (size_t)i) > 0)
1772 ;
1773 }
1774
1775 /* ARGSUSED */
1776 static void
1777 echo_dg(int s, struct servtab *sep) /* Echo service -- echo data back */
1778 {
1779 char buffer[BUFSIZE];
1780 ssize_t i;
1781 socklen_t size;
1782 struct sockaddr_storage ss;
1783 struct sockaddr *sa;
1784
1785 sa = (struct sockaddr *)(void *)&ss;
1786 size = sizeof(ss);
1787 if ((i = recvfrom(s, buffer, sizeof(buffer), 0, sa, &size)) < 0)
1788 return;
1789 if (port_good_dg(sa))
1790 (void) sendto(s, buffer, (size_t)i, 0, sa, size);
1791 }
1792
1793 /* ARGSUSED */
1794 static void
1795 discard_stream(int s, struct servtab *sep) /* Discard service -- ignore data */
1796 {
1797 char buffer[BUFSIZE];
1798
1799 inetd_setproctitle(sep->se_service, s);
1800 while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
1801 errno == EINTR)
1802 ;
1803 }
1804
1805 /* ARGSUSED */
1806 static void
1807 discard_dg(int s, struct servtab *sep) /* Discard service -- ignore data */
1808
1809 {
1810 char buffer[BUFSIZE];
1811
1812 (void) read(s, buffer, sizeof(buffer));
1813 }
1814
1815 #define LINESIZ 72
1816 char ring[128];
1817 char *endring;
1818
1819 static void
1820 initring(void)
1821 {
1822 int i;
1823
1824 endring = ring;
1825
1826 for (i = 0; i <= 128; ++i)
1827 if (isprint(i))
1828 *endring++ = (char)i;
1829 }
1830
1831 /* ARGSUSED */
1832 static void
1833 chargen_stream(int s, struct servtab *sep) /* Character generator */
1834 {
1835 size_t len;
1836 char *rs, text[LINESIZ+2];
1837
1838 inetd_setproctitle(sep->se_service, s);
1839
1840 if (!endring) {
1841 initring();
1842 rs = ring;
1843 }
1844
1845 text[LINESIZ] = '\r';
1846 text[LINESIZ + 1] = '\n';
1847 for (rs = ring;;) {
1848 if ((len = (size_t)(endring - rs)) >= LINESIZ)
1849 memmove(text, rs, LINESIZ);
1850 else {
1851 memmove(text, rs, len);
1852 memmove(text + len, ring, LINESIZ - len);
1853 }
1854 if (++rs == endring)
1855 rs = ring;
1856 if (write(s, text, sizeof(text)) != sizeof(text))
1857 break;
1858 }
1859 }
1860
1861 /* ARGSUSED */
1862 static void
1863 chargen_dg(int s, struct servtab *sep) /* Character generator */
1864 {
1865 struct sockaddr_storage ss;
1866 struct sockaddr *sa;
1867 static char *rs;
1868 size_t len;
1869 socklen_t size;
1870 char text[LINESIZ+2];
1871
1872 if (endring == 0) {
1873 initring();
1874 rs = ring;
1875 }
1876
1877 sa = (struct sockaddr *)(void *)&ss;
1878 size = sizeof(ss);
1879 if (recvfrom(s, text, sizeof(text), 0, sa, &size) < 0)
1880 return;
1881
1882 if (!port_good_dg(sa))
1883 return;
1884
1885 if ((len = (size_t)(endring - rs)) >= LINESIZ)
1886 memmove(text, rs, LINESIZ);
1887 else {
1888 memmove(text, rs, len);
1889 memmove(text + len, ring, LINESIZ - len);
1890 }
1891 if (++rs == endring)
1892 rs = ring;
1893 text[LINESIZ] = '\r';
1894 text[LINESIZ + 1] = '\n';
1895 (void) sendto(s, text, sizeof(text), 0, sa, size);
1896 }
1897
1898 /*
1899 * Return a machine readable date and time, in the form of the
1900 * number of seconds since midnight, Jan 1, 1900. Since gettimeofday
1901 * returns the number of seconds since midnight, Jan 1, 1970,
1902 * we must add 2208988800 seconds to this figure to make up for
1903 * some seventy years Bell Labs was asleep.
1904 */
1905
1906 static uint32_t
1907 machtime(void)
1908 {
1909 struct timeval tv;
1910
1911 if (gettimeofday(&tv, NULL) < 0) {
1912 DPRINTF("Unable to get time of day");
1913 return (0);
1914 }
1915 #define OFFSET ((uint32_t)25567 * 24*60*60)
1916 return (htonl((uint32_t)(tv.tv_sec + OFFSET)));
1917 #undef OFFSET
1918 }
1919
1920 /* ARGSUSED */
1921 static void
1922 machtime_stream(int s, struct servtab *sep)
1923 {
1924 uint32_t result;
1925
1926 result = machtime();
1927 (void) write(s, &result, sizeof(result));
1928 }
1929
1930 /* ARGSUSED */
1931 void
1932 machtime_dg(int s, struct servtab *sep)
1933 {
1934 uint32_t result;
1935 struct sockaddr_storage ss;
1936 struct sockaddr *sa;
1937 socklen_t size;
1938
1939 sa = (struct sockaddr *)(void *)&ss;
1940 size = sizeof(ss);
1941 if (recvfrom(s, &result, sizeof(result), 0, sa, &size) < 0)
1942 return;
1943 if (!port_good_dg(sa))
1944 return;
1945 result = machtime();
1946 (void)sendto(s, &result, sizeof(result), 0, sa, size);
1947 }
1948
1949 /* ARGSUSED */
1950 static void
1951 daytime_stream(int s,struct servtab *sep)
1952 /* Return human-readable time of day */
1953 {
1954 char buffer[256];
1955 time_t clk;
1956 int len;
1957
1958 clk = time((time_t *) 0);
1959
1960 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
1961 (void) write(s, buffer, (size_t)len);
1962 }
1963
1964 /* ARGSUSED */
1965 void
1966 daytime_dg(int s, struct servtab *sep)
1967 /* Return human-readable time of day */
1968 {
1969 char buffer[256];
1970 time_t clk;
1971 struct sockaddr_storage ss;
1972 struct sockaddr *sa;
1973 socklen_t size;
1974 int len;
1975
1976 clk = time((time_t *) 0);
1977
1978 sa = (struct sockaddr *)(void *)&ss;
1979 size = sizeof(ss);
1980 if (recvfrom(s, buffer, sizeof(buffer), 0, sa, &size) < 0)
1981 return;
1982 if (!port_good_dg(sa))
1983 return;
1984 len = snprintf(buffer, sizeof buffer, "%.24s\r\n", ctime(&clk));
1985 (void) sendto(s, buffer, (size_t)len, 0, sa, size);
1986 }
1987
1988 #ifdef DEBUG_ENABLE
1989 /*
1990 * print_service:
1991 * Dump relevant information to stderr
1992 */
1993 static void
1994 print_service(const char *action, struct servtab *sep)
1995 {
1996
1997 if (isrpcservice(sep))
1998 fprintf(stderr,
1999 "%s: %s rpcprog=%d, rpcvers = %d/%d, proto=%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s"
2000 #ifdef IPSEC
2001 " policy=\"%s\""
2002 #endif
2003 "\n",
2004 action, sep->se_service,
2005 sep->se_rpcprog, sep->se_rpcversh, sep->se_rpcversl, sep->se_proto,
2006 sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group,
2007 (long)sep->se_bi, sep->se_server
2008 #ifdef IPSEC
2009 , (sep->se_policy ? sep->se_policy : "")
2010 #endif
2011 );
2012 else
2013 fprintf(stderr,
2014 "%s: %s:%s proto=%s%s, wait.max=%d.%zu, user:group=%s:%s builtin=%lx server=%s"
2015 #ifdef IPSEC
2016 " policy=%s"
2017 #endif
2018 "\n",
2019 action, sep->se_hostaddr, sep->se_service,
2020 sep->se_type == FAITH_TYPE ? "faith/" : "",
2021 sep->se_proto,
2022 sep->se_wait, sep->se_service_max, sep->se_user, sep->se_group,
2023 (long)sep->se_bi, sep->se_server
2024 #ifdef IPSEC
2025 , (sep->se_policy ? sep->se_policy : "")
2026 #endif
2027 );
2028 }
2029 #endif
2030
2031 static void
2032 usage(void)
2033 {
2034 #ifdef LIBWRAP
2035 (void)fprintf(stderr, "usage: %s [-dl] [conf]\n", getprogname());
2036 #else
2037 (void)fprintf(stderr, "usage: %s [-d] [conf]\n", getprogname());
2038 #endif
2039 exit(EXIT_FAILURE);
2040 }
2041
2042
2043 /*
2044 * Based on TCPMUX.C by Mark K. Lottor November 1988
2045 * sri-nic::ps:<mkl>tcpmux.c
2046 */
2047
2048 static int /* # of characters upto \r,\n or \0 */
2049 get_line(int fd, char *buf, int len)
2050 {
2051 int count = 0;
2052 ssize_t n;
2053
2054 do {
2055 n = read(fd, buf, (size_t)(len - count));
2056 if (n == 0)
2057 return (count);
2058 if (n < 0)
2059 return (-1);
2060 while (--n >= 0) {
2061 if (*buf == '\r' || *buf == '\n' || *buf == '\0')
2062 return (count);
2063 count++;
2064 buf++;
2065 }
2066 } while (count < len);
2067 return (count);
2068 }
2069
2070 #define MAX_SERV_LEN (256+2) /* 2 bytes for \r\n */
2071
2072 #define strwrite(fd, buf) (void) write(fd, buf, sizeof(buf)-1)
2073
2074 static void
2075 tcpmux(int ctrl, struct servtab *sep)
2076 {
2077 char service[MAX_SERV_LEN+1];
2078 int len;
2079
2080 /* Get requested service name */
2081 if ((len = get_line(ctrl, service, MAX_SERV_LEN)) < 0) {
2082 strwrite(ctrl, "-Error reading service name\r\n");
2083 goto reject;
2084 }
2085 service[len] = '\0';
2086
2087 DPRINTF("tcpmux: %s: service requested", service);
2088
2089 /*
2090 * Help is a required command, and lists available services,
2091 * one per line.
2092 */
2093 if (!strcasecmp(service, "help")) {
2094 strwrite(ctrl, "+Available services:\r\n");
2095 strwrite(ctrl, "help\r\n");
2096 for (sep = servtab; sep != NULL; sep = sep->se_next) {
2097 if (!ISMUX(sep))
2098 continue;
2099 (void)write(ctrl, sep->se_service,
2100 strlen(sep->se_service));
2101 strwrite(ctrl, "\r\n");
2102 }
2103 goto reject;
2104 }
2105
2106 /* Try matching a service in inetd.conf with the request */
2107 for (sep = servtab; sep != NULL; sep = sep->se_next) {
2108 if (!ISMUX(sep))
2109 continue;
2110 if (!strcasecmp(service, sep->se_service)) {
2111 if (ISMUXPLUS(sep))
2112 strwrite(ctrl, "+Go\r\n");
2113 run_service(ctrl, sep, 1 /* forked */);
2114 return;
2115 }
2116 }
2117 strwrite(ctrl, "-Service not available\r\n");
2118 reject:
2119 _exit(EXIT_FAILURE);
2120 }
2121
2122 /*
2123 * check if the address/port where send data to is one of the obvious ports
2124 * that are used for denial of service attacks like two echo ports
2125 * just echoing data between them
2126 */
2127 static int
2128 port_good_dg(struct sockaddr *sa)
2129 {
2130 struct in_addr in;
2131 struct sockaddr_in *sin;
2132 #ifdef INET6
2133 struct in6_addr *in6;
2134 struct sockaddr_in6 *sin6;
2135 #endif
2136 u_int16_t port;
2137 int i;
2138 char hbuf[NI_MAXHOST];
2139
2140 switch (sa->sa_family) {
2141 case AF_INET:
2142 sin = (struct sockaddr_in *)(void *)sa;
2143 in.s_addr = ntohl(sin->sin_addr.s_addr);
2144 port = ntohs(sin->sin_port);
2145 #ifdef INET6
2146 v4chk:
2147 #endif
2148 if (IN_MULTICAST(in.s_addr))
2149 goto bad;
2150 switch ((in.s_addr & 0xff000000) >> 24) {
2151 case 0: case 127: case 255:
2152 goto bad;
2153 }
2154 if (dg_broadcast(&in))
2155 goto bad;
2156 break;
2157 #ifdef INET6
2158 case AF_INET6:
2159 sin6 = (struct sockaddr_in6 *)(void *)sa;
2160 in6 = &sin6->sin6_addr;
2161 port = ntohs(sin6->sin6_port);
2162 if (IN6_IS_ADDR_MULTICAST(in6) || IN6_IS_ADDR_UNSPECIFIED(in6))
2163 goto bad;
2164 if (IN6_IS_ADDR_V4MAPPED(in6) || IN6_IS_ADDR_V4COMPAT(in6)) {
2165 memcpy(&in, &in6->s6_addr[12], sizeof(in));
2166 in.s_addr = ntohl(in.s_addr);
2167 goto v4chk;
2168 }
2169 break;
2170 #endif
2171 default:
2172 /* XXX unsupported af, is it safe to assume it to be safe? */
2173 return (1);
2174 }
2175
2176 for (i = 0; bad_ports[i] != 0; i++) {
2177 if (port == bad_ports[i])
2178 goto bad;
2179 }
2180
2181 return (1);
2182
2183 bad:
2184 if (getnameinfo(sa, sa->sa_len, hbuf, (socklen_t)sizeof(hbuf), NULL, 0,
2185 niflags) != 0)
2186 strlcpy(hbuf, "?", sizeof(hbuf));
2187 syslog(LOG_WARNING,"Possible DoS attack from %s, Port %d",
2188 hbuf, port);
2189 return (0);
2190 }
2191
2192 /* XXX need optimization */
2193 static int
2194 dg_broadcast(struct in_addr *in)
2195 {
2196 struct ifaddrs *ifa, *ifap;
2197 struct sockaddr_in *sin;
2198
2199 if (getifaddrs(&ifap) < 0)
2200 return (0);
2201 for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2202 if (ifa->ifa_addr->sa_family != AF_INET ||
2203 (ifa->ifa_flags & IFF_BROADCAST) == 0)
2204 continue;
2205 sin = (struct sockaddr_in *)(void *)ifa->ifa_broadaddr;
2206 if (sin->sin_addr.s_addr == in->s_addr) {
2207 freeifaddrs(ifap);
2208 return (1);
2209 }
2210 }
2211 freeifaddrs(ifap);
2212 return (0);
2213 }
2214
2215 static int
2216 my_kevent(const struct kevent *changelist, size_t nchanges,
2217 struct kevent *eventlist, size_t nevents)
2218 {
2219 int result;
2220
2221 while ((result = kevent(kq, changelist, nchanges, eventlist, nevents,
2222 NULL)) < 0)
2223 if (errno != EINTR) {
2224 syslog(LOG_ERR, "kevent: %m");
2225 exit(EXIT_FAILURE);
2226 }
2227
2228 return (result);
2229 }
2230
2231 static struct kevent *
2232 allocchange(void)
2233 {
2234 if (changes == __arraycount(changebuf)) {
2235 (void) my_kevent(changebuf, __arraycount(changebuf), NULL, 0);
2236 changes = 0;
2237 }
2238
2239 return (&changebuf[changes++]);
2240 }
2241
2242 static void
2243 config_root(void)
2244 {
2245 struct servtab *sep;
2246 /* Uncheck services */
2247 for (sep = servtab; sep != NULL; sep = sep->se_next) {
2248 sep->se_checked = 0;
2249 }
2250 defhost = newstr("*");
2251 #ifdef IPSEC
2252 policy = NULL;
2253 #endif
2254 fconfig = NULL;
2255 config();
2256 purge_unchecked();
2257 }
2258
2259 static void
2260 purge_unchecked(void)
2261 {
2262 struct servtab *sep, **sepp = &servtab;
2263 int servtab_count = 0;
2264 while ((sep = *sepp) != NULL) {
2265 if (sep->se_checked) {
2266 sepp = &sep->se_next;
2267 servtab_count++;
2268 continue;
2269 }
2270 *sepp = sep->se_next;
2271 if (sep->se_fd >= 0)
2272 close_sep(sep);
2273 if (isrpcservice(sep))
2274 unregister_rpc(sep);
2275 if (sep->se_family == AF_LOCAL)
2276 (void)unlink(sep->se_service);
2277 #ifdef DEBUG_ENABLE
2278 if (debug)
2279 print_service("FREE", sep);
2280 #endif
2281 freeconfig(sep);
2282 free(sep);
2283 }
2284 DPRINTF("%d service(s) loaded.", servtab_count);
2285 }
2286
2287 static bool
2288 is_same_service(const struct servtab *sep, const struct servtab *cp)
2289 {
2290 return
2291 strcmp(sep->se_service, cp->se_service) == 0 &&
2292 strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 &&
2293 strcmp(sep->se_proto, cp->se_proto) == 0 &&
2294 sep->se_family == cp->se_family &&
2295 ISMUX(sep) == ISMUX(cp);
2296 }
2297
2298 int
2299 parse_protocol(struct servtab *sep)
2300 {
2301 int val;
2302
2303 if (strcmp(sep->se_proto, "unix") == 0) {
2304 sep->se_family = AF_LOCAL;
2305 } else {
2306 val = (int)strlen(sep->se_proto);
2307 if (!val) {
2308 ERR("%s: invalid protocol specified",
2309 sep->se_service);
2310 return -1;
2311 }
2312 val = sep->se_proto[val - 1];
2313 switch (val) {
2314 case '4': /*tcp4 or udp4*/
2315 sep->se_family = AF_INET;
2316 break;
2317 #ifdef INET6
2318 case '6': /*tcp6 or udp6*/
2319 sep->se_family = AF_INET6;
2320 break;
2321 #endif
2322 default:
2323 /* Use 'default' IP version which is IPv4, may eventually be
2324 * changed to AF_INET6 */
2325 sep->se_family = AF_INET;
2326 break;
2327 }
2328 if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
2329 #ifdef RPC
2330 char *cp1, *ccp;
2331 cp1 = strchr(sep->se_service, '/');
2332 if (cp1 == 0) {
2333 ERR("%s: no rpc version",
2334 sep->se_service);
2335 return -1;
2336 }
2337 *cp1++ = '\0';
2338 sep->se_rpcversl = sep->se_rpcversh =
2339 (int)strtol(cp1, &ccp, 0);
2340 if (ccp == cp1) {
2341 badafterall:
2342 ERR("%s/%s: bad rpc version",
2343 sep->se_service, cp1);
2344 return -1;
2345 }
2346 if (*ccp == '-') {
2347 cp1 = ccp + 1;
2348 sep->se_rpcversh = (int)strtol(cp1, &ccp, 0);
2349 if (ccp == cp1)
2350 goto badafterall;
2351 }
2352 #else
2353 ERR("%s: rpc services not supported",
2354 sep->se_service);
2355 return -1;
2356 #endif /* RPC */
2357 }
2358 }
2359 return 0;
2360 }
2361
2362 int
2363 parse_wait(struct servtab *sep, int wait)
2364 {
2365 if (!ISMUX(sep)) {
2366 sep->se_wait = wait;
2367 return 0;
2368 }
2369 /*
2370 * Silently enforce "nowait" for TCPMUX services since
2371 * they don't have an assigned port to listen on.
2372 */
2373 sep->se_wait = 0;
2374
2375 if (strncmp(sep->se_proto, "tcp", 3)) {
2376 ERR("bad protocol for tcpmux service %s",
2377 sep->se_service);
2378 return -1;
2379 }
2380 if (sep->se_socktype != SOCK_STREAM) {
2381 ERR("bad socket type for tcpmux service %s",
2382 sep->se_service);
2383 return -1;
2384 }
2385 return 0;
2386 }
2387
2388 int
2389 parse_server(struct servtab *sep, const char *arg){
2390 sep->se_server = newstr(arg);
2391 if (strcmp(sep->se_server, "internal") != 0) {
2392 sep->se_bi = NULL;
2393 return 0;
2394 }
2395 struct biltin *bi;
2396
2397 for (bi = biltins; bi->bi_service; bi++)
2398 if (bi->bi_socktype == sep->se_socktype &&
2399 strcmp(bi->bi_service, sep->se_service) == 0)
2400 break;
2401 if (bi->bi_service == NULL) {
2402 ERR("Internal service %s unknown",
2403 sep->se_service);
2404 return -1;
2405 }
2406 sep->se_bi = bi;
2407 sep->se_wait = bi->bi_wait;
2408 return 0;
2409 }
2410
2411 /* TODO test to make sure accept filter still works */
2412 void
2413 parse_accept_filter(char *arg, struct servtab *sep) {
2414 char *accf, *accf_arg;
2415 /* one and only one accept filter */
2416 accf = strchr(arg, ':');
2417 if (!accf)
2418 return;
2419 if (accf != strrchr(arg, ':') || *(accf + 1) == '\0') {
2420 /* more than one || nothing beyond */
2421 sep->se_socktype = -1;
2422 return;
2423 }
2424
2425 accf++; /* skip delimiter */
2426 strlcpy(sep->se_accf.af_name, accf, sizeof(sep->se_accf.af_name));
2427 accf_arg = strchr(accf, ',');
2428 if (!accf_arg) /* zero or one arg, no more */
2429 return;
2430
2431 if (strrchr(accf, ',') != accf_arg) {
2432 sep->se_socktype = -1;
2433 } else {
2434 accf_arg++;
2435 strlcpy(sep->se_accf.af_arg, accf_arg,
2436 sizeof(sep->se_accf.af_arg));
2437 }
2438 }
2439
2440 void
2441 parse_socktype(char* arg, struct servtab* sep)
2442 {
2443 /* stream socket may have an accept filter, only check first chars */
2444 if (strncmp(arg, "stream", sizeof("stream") - 1) == 0)
2445 sep->se_socktype = SOCK_STREAM;
2446 else if (strcmp(arg, "dgram") == 0)
2447 sep->se_socktype = SOCK_DGRAM;
2448 else if (strcmp(arg, "rdm") == 0)
2449 sep->se_socktype = SOCK_RDM;
2450 else if (strcmp(arg, "seqpacket") == 0)
2451 sep->se_socktype = SOCK_SEQPACKET;
2452 else if (strcmp(arg, "raw") == 0)
2453 sep->se_socktype = SOCK_RAW;
2454 else
2455 sep->se_socktype = -1;
2456 }
2457
2458 static struct servtab
2459 init_servtab(void)
2460 {
2461 /* This does not set every field to default. See enter() as well */
2462 return (struct servtab) {
2463 /*
2464 * Set se_max to non-zero so uninitialized value is not
2465 * a valid value. Useful in v2 syntax parsing.
2466 */
2467 .se_service_max = SERVTAB_UNSPEC_SIZE_T,
2468 .se_ip_max = SERVTAB_UNSPEC_SIZE_T,
2469 .se_wait = SERVTAB_UNSPEC_VAL,
2470 .se_socktype = SERVTAB_UNSPEC_VAL
2471 /* All other fields initialized to 0 or null */
2472 };
2473 }
2474
2475 /* Include directives bookkeeping structure */
2476 struct file_list {
2477 /* Absolute path used for checking for circular references */
2478 char *abs;
2479 /* Pointer to the absolute path of the parent config file,
2480 * on the stack */
2481 struct file_list *next;
2482 } *file_list_head;
2483
2484 static void
2485 include_configs(char *pattern)
2486 {
2487 /* Allocate global per-config state on the thread stack */
2488 const char* save_CONFIG;
2489 FILE *save_fconfig;
2490 size_t save_line_number;
2491 char *save_defhost;
2492 struct file_list new_file;
2493 #ifdef IPSEC
2494 char *save_policy;
2495 #endif
2496
2497 /* Store current globals on the stack */
2498 save_CONFIG = CONFIG;
2499 save_fconfig = fconfig;
2500 save_line_number = line_number;
2501 save_defhost = defhost;
2502 new_file.abs = realpath(CONFIG, NULL);
2503 new_file.next = file_list_head;
2504 #ifdef IPSEC
2505 save_policy = policy;
2506 #endif
2507 /* Put new_file at the top of the config stack */
2508 file_list_head = &new_file;
2509 read_glob_configs(pattern);
2510 free((void *)new_file.abs);
2511 /* Pop new_file off the stack */
2512 file_list_head = new_file.next;
2513
2514 /* Restore global per-config state */
2515 CONFIG = save_CONFIG;
2516 fconfig = save_fconfig;
2517 line_number = save_line_number;
2518 defhost = save_defhost;
2519 #ifdef IPSEC
2520 policy = save_policy;
2521 #endif
2522 }
2523
2524 static void
2525 prepare_next_config(const char *file_name)
2526 {
2527 /* Setup new state that is normally only done in main */
2528 CONFIG = file_name;
2529
2530 /* Inherit default host and IPsec policy */
2531 defhost = newstr(defhost);
2532
2533 #ifdef IPSEC
2534 policy = (policy == NULL) ? NULL : newstr(policy);
2535 #endif
2536 }
2537
2538 static void
2539 read_glob_configs(char *pattern) {
2540 glob_t results;
2541 char *full_pattern;
2542 int glob_result;
2543 full_pattern = gen_file_pattern(CONFIG, pattern);
2544
2545 DPRINTCONF("Found include directive '%s'", full_pattern);
2546
2547 glob_result = glob(full_pattern, GLOB_NOSORT, glob_error, &results);
2548 switch(glob_result) {
2549 case 0:
2550 /* No glob errors */
2551 break;
2552 case GLOB_ABORTED:
2553 ERR("Error while searching for include files");
2554 break;
2555 case GLOB_NOMATCH:
2556 /* It's fine if no files were matched. */
2557 DPRINTCONF("No files matched pattern '%s'", full_pattern);
2558 break;
2559 case GLOB_NOSPACE:
2560 ERR("Error when searching for include files: %s",
2561 strerror(errno));
2562 break;
2563 default:
2564 ERR("Unknown glob(3) error %d", errno);
2565 break;
2566 }
2567 free(full_pattern);
2568
2569 for (size_t i = 0; i < results.gl_pathc; i++) {
2570 include_matched_path(results.gl_pathv[i]);
2571 }
2572
2573 globfree(&results);
2574 }
2575
2576 static void
2577 include_matched_path(char *glob_path)
2578 {
2579 struct stat sb;
2580 char *tmp;
2581
2582 if (lstat(glob_path, &sb)) {
2583 ERR("Error calling stat on path '%s': %s", glob_path,
2584 strerror(errno));
2585 return;
2586 }
2587
2588 if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode)) {
2589 DPRINTCONF("'%s' is not a file.", glob_path);
2590 ERR("The matched path '%s' is not a regular file", glob_path);
2591 return;
2592 }
2593
2594 DPRINTCONF("Include '%s'", glob_path);
2595
2596 if (S_ISLNK(sb.st_mode)) {
2597 tmp = glob_path;
2598 glob_path = realpath(tmp, NULL);
2599 }
2600
2601 /* Ensure the file is not being reincluded .*/
2602 if (check_no_reinclude(glob_path)) {
2603 prepare_next_config(glob_path);
2604 config();
2605 } else {
2606 DPRINTCONF("File '%s' already included in current include "
2607 "chain", glob_path);
2608 WRN("Including file '%s' would cause a circular "
2609 "dependency", glob_path);
2610 }
2611
2612 if (S_ISLNK(sb.st_mode)) {
2613 free(glob_path);
2614 glob_path = tmp;
2615 }
2616 }
2617
2618 static bool
2619 check_no_reinclude(const char *glob_path)
2620 {
2621 struct file_list *cur = file_list_head;
2622 char *abs_path = realpath(glob_path, NULL);
2623
2624 if (abs_path == NULL) {
2625 ERR("Error checking real path for '%s': %s",
2626 glob_path, strerror(errno));
2627 return false;
2628 }
2629
2630 DPRINTCONF("Absolute path '%s'", abs_path);
2631
2632 for (cur = file_list_head; cur != NULL; cur = cur->next) {
2633 if (strcmp(cur->abs, abs_path) == 0) {
2634 /* file included more than once */
2635 /* TODO relative or abs path for logging error? */
2636 free(abs_path);
2637 return false;
2638 }
2639 }
2640 free(abs_path);
2641 return true;
2642 }
2643
2644 /* Resolve the pattern relative to the config file the pattern is from */
2645 static char *
2646 gen_file_pattern(const char *cur_config, const char *pattern)
2647 {
2648 if (pattern[0] == '/') {
2649 /* Absolute paths don't need any normalization */
2650 return newstr(pattern);
2651 }
2652
2653 /* pattern is relative */
2654 /* Find the end of the file's directory */
2655 size_t i, last = 0;
2656 for (i = 0; cur_config[i] != '\0'; i++) {
2657 if (cur_config[i] == '/') {
2658 last = i;
2659 }
2660 }
2661
2662 if (last == 0) {
2663 /* cur_config is just a filename, pattern already correct */
2664 return newstr(pattern);
2665 }
2666
2667 /* Relativize pattern to cur_config file's directory */
2668 char *full_pattern = malloc(last + 1 + strlen(pattern) + 1);
2669 if (full_pattern == NULL) {
2670 syslog(LOG_ERR, "Out of memory.");
2671 exit(EXIT_FAILURE);
2672 }
2673 memcpy(full_pattern, cur_config, last);
2674 full_pattern[last] = '/';
2675 strcpy(&full_pattern[last + 1], pattern);
2676 return full_pattern;
2677 }
2678
2679 static int
2680 glob_error(const char *path, int error)
2681 {
2682 WRN("Error while resolving path '%s': %s", path, strerror(error));
2683 return 0;
2684 }
2685
2686 /* Return 0 on allow, -1 if connection should be blocked */
2687 static int
2688 rl_process(struct servtab *sep, int ctrl)
2689 {
2690 struct se_ip_list_node *node;
2691 time_t now = 0; /* 0 prevents GCC from complaining */
2692 bool istimevalid = false;
2693 char hbuf[NI_MAXHOST];
2694
2695 DPRINTF(SERV_FMT ": processing rate-limiting",
2696 SERV_PARAMS(sep));
2697 DPRINTF(SERV_FMT ": se_service_max "
2698 "%zu and se_count %zu", SERV_PARAMS(sep),
2699 sep->se_service_max, sep->se_count);
2700
2701 /* se_count is incremented if rl_process will return 0 */
2702 if (sep->se_count == 0) {
2703 now = rl_time();
2704 sep->se_time = now;
2705 istimevalid = true;
2706 }
2707
2708 if (sep->se_count >= sep->se_service_max) {
2709 if(!istimevalid) {
2710 now = rl_time();
2711 istimevalid = true;
2712 }
2713
2714 if (now - sep->se_time > CNT_INTVL) {
2715 rl_reset(sep, now);
2716 } else {
2717 syslog(LOG_ERR,
2718 SERV_FMT ": max spawn rate (%zu in %ji seconds) "
2719 "already met, closing until end of timeout in "
2720 "%ju seconds",
2721 SERV_PARAMS(sep),
2722 sep->se_service_max,
2723 (intmax_t)CNT_INTVL,
2724 (uintmax_t)RETRYTIME);
2725
2726 DPRINTF(SERV_FMT ": service not started",
2727 SERV_PARAMS(sep));
2728
2729 rl_drop_connection(sep, ctrl);
2730
2731 /* Close the server for 10 minutes */
2732 close_sep(sep);
2733 if (!timingout) {
2734 timingout = 1;
2735 alarm(RETRYTIME);
2736 }
2737
2738 return -1;
2739 }
2740 }
2741
2742 if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) {
2743 rl_get_name(sep, ctrl, hbuf);
2744 node = rl_try_get_ip(sep, hbuf);
2745 if(node == NULL) {
2746 node = rl_add(sep, hbuf);
2747 }
2748
2749 DPRINTF(
2750 SERV_FMT ": se_ip_max %zu and ip_count %zu",
2751 SERV_PARAMS(sep), sep->se_ip_max, node->count);
2752
2753 if (node->count >= sep->se_ip_max) {
2754 if (!istimevalid) {
2755 /*
2756 * Only get the clock time if we didn't
2757 * already
2758 */
2759 now = rl_time();
2760 istimevalid = true;
2761 }
2762
2763 if (now - sep->se_time > CNT_INTVL) {
2764 rl_reset(sep, now);
2765 node = rl_add(sep, hbuf);
2766 } else {
2767 if (debug && node->count == sep->se_ip_max) {
2768 /*
2769 * Only log first failed request to
2770 * prevent DoS attack writing to system
2771 * log
2772 */
2773 syslog(LOG_ERR, SERV_FMT
2774 ": max ip spawn rate (%zu in "
2775 "%ji seconds) for "
2776 "%." TOSTRING(NI_MAXHOST) "s "
2777 "already met; service not started",
2778 SERV_PARAMS(sep),
2779 sep->se_ip_max,
2780 (intmax_t)CNT_INTVL,
2781 node->address);
2782 }
2783
2784 DPRINTF(SERV_FMT ": service not started",
2785 SERV_PARAMS(sep));
2786
2787 rl_drop_connection(sep, ctrl);
2788 /*
2789 * Increment so debug-syslog message will
2790 * trigger only once
2791 */
2792 node->count++;
2793 return -1;
2794 }
2795 }
2796 node->count++;
2797 }
2798
2799 DPRINTF(SERV_FMT ": running service ", SERV_PARAMS(sep));
2800
2801 sep->se_count++;
2802 return 0;
2803 }
2804
2805 /* Get the remote's IP address in textual form into hbuf of size NI_MAXHOST */
2806 static void
2807 rl_get_name(struct servtab *sep, int ctrl, char *hbuf)
2808 {
2809 struct sockaddr_storage addr;
2810 socklen_t len = sizeof(struct sockaddr_storage);
2811 switch (sep->se_socktype) {
2812 case SOCK_STREAM:
2813 if (getpeername(ctrl, (struct sockaddr *)&addr, &len)) {
2814 /* error, log it and skip ip rate limiting */
2815 syslog(LOG_ERR,
2816 SERV_FMT " failed to get peer name of the "
2817 "connection", SERV_PARAMS(sep));
2818 exit(EXIT_FAILURE);
2819 }
2820 break;
2821 case SOCK_DGRAM: {
2822 struct msghdr header = {
2823 .msg_name = &addr,
2824 .msg_namelen = sizeof(struct sockaddr_storage),
2825 /* scatter/gather and control info is null */
2826 };
2827 ssize_t count;
2828
2829 /* Peek so service can still get the packet */
2830 count = recvmsg(ctrl, &header, MSG_PEEK);
2831 if (count == -1) {
2832 syslog(LOG_ERR,
2833 "failed to get dgram source address: %s; exiting",
2834 strerror(errno));
2835 exit(EXIT_FAILURE);
2836 }
2837 break;
2838 }
2839 default:
2840 DPRINTF(SERV_FMT ": ip_max rate limiting not supported for "
2841 "socktype", SERV_PARAMS(sep));
2842 syslog(LOG_ERR, SERV_FMT
2843 ": ip_max rate limiting not supported for socktype",
2844 SERV_PARAMS(sep));
2845 exit(EXIT_FAILURE);
2846 }
2847
2848 if (getnameinfo((struct sockaddr *)&addr,
2849 addr.ss_len, hbuf,
2850 NI_MAXHOST, NULL, 0, NI_NUMERICHOST)) {
2851 /* error, log it and skip ip rate limiting */
2852 syslog(LOG_ERR,
2853 SERV_FMT ": failed to get name info of the incoming "
2854 "connection; exiting",
2855 SERV_PARAMS(sep));
2856 exit(EXIT_FAILURE);
2857 }
2858 }
2859
2860 static void
2861 rl_drop_connection(struct servtab *sep, int ctrl)
2862 {
2863
2864 if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
2865 /*
2866 * If the fd isn't a listen socket,
2867 * close the individual connection too.
2868 */
2869 close(ctrl);
2870 return;
2871 }
2872 if (sep->se_socktype != SOCK_DGRAM) {
2873 return;
2874 }
2875 /*
2876 * Drop the single datagram the service would have
2877 * consumed if nowait. If this is a wait service, this
2878 * will consume 1 datagram, and further received packets
2879 * will be removed in the same way.
2880 */
2881 struct msghdr header = {
2882 /* All fields null, just consume one message */
2883 };
2884 ssize_t count;
2885
2886 count = recvmsg(ctrl, &header, 0);
2887 if (count == -1) {
2888 syslog(LOG_ERR,
2889 SERV_FMT ": failed to consume nowait dgram: %s",
2890 SERV_PARAMS(sep), strerror(errno));
2891 exit(EXIT_FAILURE);
2892 }
2893 DPRINTF(SERV_FMT ": dropped dgram message",
2894 SERV_PARAMS(sep));
2895 }
2896
2897 static time_t
2898 rl_time(void)
2899 {
2900 struct timespec time;
2901 if(clock_gettime(CLOCK_MONOTONIC, &time) == -1) {
2902 syslog(LOG_ERR, "clock_gettime for rate limiting failed: %s; "
2903 "exiting", strerror(errno));
2904 /* Exit inetd if rate limiting fails */
2905 exit(EXIT_FAILURE);
2906 }
2907 return time.tv_sec;
2908 }
2909
2910 static struct se_ip_list_node*
2911 rl_add(struct servtab *sep, char* ip)
2912 {
2913 DPRINTF(
2914 SERV_FMT ": add ip %s to rate limiting tracking",
2915 SERV_PARAMS(sep), ip);
2916
2917 /*
2918 * TODO memory could be saved by using a variable length malloc
2919 * with only the length of ip instead of the existing address field
2920 * NI_MAXHOST in length.
2921 */
2922 struct se_ip_list_node* temp = malloc(sizeof(*temp));
2923 if (temp == NULL) {
2924 syslog(LOG_ERR, "Out of memory.");
2925 exit(EXIT_FAILURE);
2926 }
2927 temp->count = 0;
2928 temp->next = NULL;
2929 strlcpy(temp->address, ip, sizeof(temp->address));
2930
2931 if (sep->se_ip_list_head == NULL) {
2932 /* List empty, insert as head */
2933 sep->se_ip_list_head = temp;
2934 } else {
2935 /* List not empty, insert as head, point next to prev head */
2936 temp->next = sep->se_ip_list_head;
2937 sep->se_ip_list_head = temp;
2938 }
2939
2940 return temp;
2941 }
2942
2943 static void
2944 rl_reset(struct servtab *sep, time_t now)
2945 {
2946 DPRINTF(SERV_FMT ": %ji seconds passed; resetting rate limiting ",
2947 SERV_PARAMS(sep), (intmax_t)(now - sep->se_time));
2948
2949 sep->se_count = 0;
2950 sep->se_time = now;
2951 if (sep->se_ip_max != SERVTAB_UNSPEC_SIZE_T) {
2952 clear_ip_list(sep);
2953 }
2954 }
2955
2956 static void
2957 clear_ip_list(struct servtab *sep) {
2958 struct se_ip_list_node *curr, *next;
2959 curr = sep->se_ip_list_head;
2960
2961 while (curr != NULL) {
2962 next = curr->next;
2963 free(curr);
2964 curr = next;
2965 }
2966 sep->se_ip_list_head = NULL;
2967 }
2968
2969 static struct se_ip_list_node *
2970 rl_try_get_ip(struct servtab *sep, char *ip)
2971 {
2972 struct se_ip_list_node *curr;
2973
2974 DPRINTF(
2975 SERV_FMT ": look up ip %s for ip_max rate limiting",
2976 SERV_PARAMS(sep), ip);
2977
2978 for (curr = sep->se_ip_list_head; curr != NULL; curr = curr->next) {
2979 if (!strncmp(curr->address, ip, NI_MAXHOST)) {
2980 /* IP addr match */
2981 return curr;
2982 }
2983 }
2984 return NULL;
2985 }
2986