Deleted Added
full compact
inetd.c (135823) inetd.c (146187)
1/*
2 * Copyright (c) 1983, 1991, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#ifndef lint
31static const char copyright[] =
32"@(#) Copyright (c) 1983, 1991, 1993, 1994\n\
33 The Regents of the University of California. All rights reserved.\n";
34#endif /* not lint */
35
36#ifndef lint
37#if 0
38static char sccsid[] = "@(#)from: inetd.c 8.4 (Berkeley) 4/13/94";
39#endif
40#endif /* not lint */
41
42#include <sys/cdefs.h>
1/*
2 * Copyright (c) 1983, 1991, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#ifndef lint
31static const char copyright[] =
32"@(#) Copyright (c) 1983, 1991, 1993, 1994\n\
33 The Regents of the University of California. All rights reserved.\n";
34#endif /* not lint */
35
36#ifndef lint
37#if 0
38static char sccsid[] = "@(#)from: inetd.c 8.4 (Berkeley) 4/13/94";
39#endif
40#endif /* not lint */
41
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/usr.sbin/inetd/inetd.c 135823 2004-09-26 13:47:25Z stefanf $");
43__FBSDID("$FreeBSD: head/usr.sbin/inetd/inetd.c 146187 2005-05-13 16:31:11Z ume $");
44
45/*
46 * Inetd - Internet super-server
47 *
48 * This program invokes all internet services as needed. Connection-oriented
49 * services are invoked each time a connection is made, by creating a process.
50 * This process is passed the connection as file descriptor 0 and is expected
51 * to do a getpeername to find out the source host and port.
52 *
53 * Datagram oriented services are invoked when a datagram
54 * arrives; a process is created and passed a pending message
55 * on file descriptor 0. Datagram servers may either connect
56 * to their peer, freeing up the original socket for inetd
57 * to receive further messages on, or ``take over the socket'',
58 * processing all arriving datagrams and, eventually, timing
59 * out. The first type of server is said to be ``multi-threaded'';
60 * the second type of server ``single-threaded''.
61 *
62 * Inetd uses a configuration file which is read at startup
63 * and, possibly, at some later time in response to a hangup signal.
64 * The configuration file is ``free format'' with fields given in the
65 * order shown below. Continuation lines for an entry must begin with
66 * a space or tab. All fields must be present in each entry.
67 *
68 * service name must be in /etc/services
69 * or name a tcpmux service
70 * or specify a unix domain socket
71 * socket type stream/dgram/raw/rdm/seqpacket
72 * protocol tcp[4][6][/faith,ttcp], udp[4][6], unix
73 * wait/nowait single-threaded/multi-threaded
74 * user user to run daemon as
75 * server program full path name
76 * server program arguments maximum of MAXARGS (20)
77 *
78 * TCP services without official port numbers are handled with the
79 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
80 * requests. When a connection is made from a foreign host, the service
81 * requested is passed to tcpmux, which looks it up in the servtab list
82 * and returns the proper entry for the service. Tcpmux returns a
83 * negative reply if the service doesn't exist, otherwise the invoked
84 * server is expected to return the positive reply if the service type in
85 * inetd.conf file has the prefix "tcpmux/". If the service type has the
86 * prefix "tcpmux/+", tcpmux will return the positive reply for the
87 * process; this is for compatibility with older server code, and also
88 * allows you to invoke programs that use stdin/stdout without putting any
89 * special server code in them. Services that use tcpmux are "nowait"
90 * because they do not have a well-known port and hence cannot listen
91 * for new requests.
92 *
93 * For RPC services
94 * service name/version must be in /etc/rpc
95 * socket type stream/dgram/raw/rdm/seqpacket
96 * protocol rpc/tcp[4][6], rpc/udp[4][6]
97 * wait/nowait single-threaded/multi-threaded
98 * user user to run daemon as
99 * server program full path name
100 * server program arguments maximum of MAXARGS
101 *
102 * Comment lines are indicated by a `#' in column 1.
103 *
104 * #ifdef IPSEC
105 * Comment lines that start with "#@" denote IPsec policy string, as described
106 * in ipsec_set_policy(3). This will affect all the following items in
107 * inetd.conf(8). To reset the policy, just use "#@" line. By default,
108 * there's no IPsec policy.
109 * #endif
110 */
111#include <sys/param.h>
112#include <sys/ioctl.h>
113#include <sys/wait.h>
114#include <sys/time.h>
115#include <sys/resource.h>
116#include <sys/stat.h>
117#include <sys/un.h>
118
119#include <netinet/in.h>
120#include <netinet/tcp.h>
121#include <arpa/inet.h>
122#include <rpc/rpc.h>
123#include <rpc/pmap_clnt.h>
124
125#include <ctype.h>
126#include <errno.h>
127#include <err.h>
128#include <fcntl.h>
129#include <grp.h>
130#include <libutil.h>
131#include <limits.h>
132#include <netdb.h>
133#include <pwd.h>
134#include <signal.h>
135#include <stdio.h>
136#include <stdlib.h>
137#include <string.h>
138#include <sysexits.h>
139#include <syslog.h>
140#include <tcpd.h>
141#include <unistd.h>
142
143#include "inetd.h"
144#include "pathnames.h"
145
146#ifdef IPSEC
147#include <netinet6/ipsec.h>
148#ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */
149#undef IPSEC
150#endif
151#endif
152
44
45/*
46 * Inetd - Internet super-server
47 *
48 * This program invokes all internet services as needed. Connection-oriented
49 * services are invoked each time a connection is made, by creating a process.
50 * This process is passed the connection as file descriptor 0 and is expected
51 * to do a getpeername to find out the source host and port.
52 *
53 * Datagram oriented services are invoked when a datagram
54 * arrives; a process is created and passed a pending message
55 * on file descriptor 0. Datagram servers may either connect
56 * to their peer, freeing up the original socket for inetd
57 * to receive further messages on, or ``take over the socket'',
58 * processing all arriving datagrams and, eventually, timing
59 * out. The first type of server is said to be ``multi-threaded'';
60 * the second type of server ``single-threaded''.
61 *
62 * Inetd uses a configuration file which is read at startup
63 * and, possibly, at some later time in response to a hangup signal.
64 * The configuration file is ``free format'' with fields given in the
65 * order shown below. Continuation lines for an entry must begin with
66 * a space or tab. All fields must be present in each entry.
67 *
68 * service name must be in /etc/services
69 * or name a tcpmux service
70 * or specify a unix domain socket
71 * socket type stream/dgram/raw/rdm/seqpacket
72 * protocol tcp[4][6][/faith,ttcp], udp[4][6], unix
73 * wait/nowait single-threaded/multi-threaded
74 * user user to run daemon as
75 * server program full path name
76 * server program arguments maximum of MAXARGS (20)
77 *
78 * TCP services without official port numbers are handled with the
79 * RFC1078-based tcpmux internal service. Tcpmux listens on port 1 for
80 * requests. When a connection is made from a foreign host, the service
81 * requested is passed to tcpmux, which looks it up in the servtab list
82 * and returns the proper entry for the service. Tcpmux returns a
83 * negative reply if the service doesn't exist, otherwise the invoked
84 * server is expected to return the positive reply if the service type in
85 * inetd.conf file has the prefix "tcpmux/". If the service type has the
86 * prefix "tcpmux/+", tcpmux will return the positive reply for the
87 * process; this is for compatibility with older server code, and also
88 * allows you to invoke programs that use stdin/stdout without putting any
89 * special server code in them. Services that use tcpmux are "nowait"
90 * because they do not have a well-known port and hence cannot listen
91 * for new requests.
92 *
93 * For RPC services
94 * service name/version must be in /etc/rpc
95 * socket type stream/dgram/raw/rdm/seqpacket
96 * protocol rpc/tcp[4][6], rpc/udp[4][6]
97 * wait/nowait single-threaded/multi-threaded
98 * user user to run daemon as
99 * server program full path name
100 * server program arguments maximum of MAXARGS
101 *
102 * Comment lines are indicated by a `#' in column 1.
103 *
104 * #ifdef IPSEC
105 * Comment lines that start with "#@" denote IPsec policy string, as described
106 * in ipsec_set_policy(3). This will affect all the following items in
107 * inetd.conf(8). To reset the policy, just use "#@" line. By default,
108 * there's no IPsec policy.
109 * #endif
110 */
111#include <sys/param.h>
112#include <sys/ioctl.h>
113#include <sys/wait.h>
114#include <sys/time.h>
115#include <sys/resource.h>
116#include <sys/stat.h>
117#include <sys/un.h>
118
119#include <netinet/in.h>
120#include <netinet/tcp.h>
121#include <arpa/inet.h>
122#include <rpc/rpc.h>
123#include <rpc/pmap_clnt.h>
124
125#include <ctype.h>
126#include <errno.h>
127#include <err.h>
128#include <fcntl.h>
129#include <grp.h>
130#include <libutil.h>
131#include <limits.h>
132#include <netdb.h>
133#include <pwd.h>
134#include <signal.h>
135#include <stdio.h>
136#include <stdlib.h>
137#include <string.h>
138#include <sysexits.h>
139#include <syslog.h>
140#include <tcpd.h>
141#include <unistd.h>
142
143#include "inetd.h"
144#include "pathnames.h"
145
146#ifdef IPSEC
147#include <netinet6/ipsec.h>
148#ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */
149#undef IPSEC
150#endif
151#endif
152
153/* wrapper for KAME-special getnameinfo() */
154#ifndef NI_WITHSCOPEID
155#define NI_WITHSCOPEID 0
156#endif
157
158#ifndef LIBWRAP_ALLOW_FACILITY
159# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
160#endif
161#ifndef LIBWRAP_ALLOW_SEVERITY
162# define LIBWRAP_ALLOW_SEVERITY LOG_INFO
163#endif
164#ifndef LIBWRAP_DENY_FACILITY
165# define LIBWRAP_DENY_FACILITY LOG_AUTH
166#endif
167#ifndef LIBWRAP_DENY_SEVERITY
168# define LIBWRAP_DENY_SEVERITY LOG_WARNING
169#endif
170
171#define ISWRAP(sep) \
172 ( ((wrap_ex && !(sep)->se_bi) || (wrap_bi && (sep)->se_bi)) \
173 && (sep->se_family == AF_INET || sep->se_family == AF_INET6) \
174 && ( ((sep)->se_accept && (sep)->se_socktype == SOCK_STREAM) \
175 || (sep)->se_socktype == SOCK_DGRAM))
176
177#ifdef LOGIN_CAP
178#include <login_cap.h>
179
180/* see init.c */
181#define RESOURCE_RC "daemon"
182
183#endif
184
185#ifndef MAXCHILD
186#define MAXCHILD -1 /* maximum number of this service
187 < 0 = no limit */
188#endif
189
190#ifndef MAXCPM
191#define MAXCPM -1 /* rate limit invocations from a
192 single remote address,
193 < 0 = no limit */
194#endif
195
196#ifndef MAXPERIP
197#define MAXPERIP -1 /* maximum number of this service
198 from a single remote address,
199 < 0 = no limit */
200#endif
201
202#ifndef TOOMANY
203#define TOOMANY 256 /* don't start more than TOOMANY */
204#endif
205#define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
206#define RETRYTIME (60*10) /* retry after bind or server fail */
207#define MAX_MAXCHLD 32767 /* max allowable max children */
208
209#define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
210
211void close_sep(struct servtab *);
212void flag_signal(int);
213void flag_config(int);
214void config(void);
215int cpmip(const struct servtab *, int);
216void endconfig(void);
217struct servtab *enter(struct servtab *);
218void freeconfig(struct servtab *);
219struct servtab *getconfigent(void);
220int matchservent(const char *, const char *, const char *);
221char *nextline(FILE *);
222void addchild(struct servtab *, int);
223void flag_reapchild(int);
224void reapchild(void);
225void enable(struct servtab *);
226void disable(struct servtab *);
227void flag_retry(int);
228void retry(void);
229int setconfig(void);
230void setup(struct servtab *);
231#ifdef IPSEC
232void ipsecsetup(struct servtab *);
233#endif
234void unregisterrpc(register struct servtab *sep);
235static struct conninfo *search_conn(struct servtab *sep, int ctrl);
236static int room_conn(struct servtab *sep, struct conninfo *conn);
237static void addchild_conn(struct conninfo *conn, pid_t pid);
238static void reapchild_conn(pid_t pid);
239static void free_conn(struct conninfo *conn);
240static void resize_conn(struct servtab *sep, int maxperip);
241static void free_connlist(struct servtab *sep);
242static void free_proc(struct procinfo *);
243static struct procinfo *search_proc(pid_t pid, int add);
244static int hashval(char *p, int len);
245
246int allow_severity;
247int deny_severity;
248int wrap_ex = 0;
249int wrap_bi = 0;
250int debug = 0;
251int dolog = 0;
252int maxsock; /* highest-numbered descriptor */
253fd_set allsock;
254int options;
255int timingout;
256int toomany = TOOMANY;
257int maxchild = MAXCHILD;
258int maxcpm = MAXCPM;
259int maxperip = MAXPERIP;
260struct servent *sp;
261struct rpcent *rpc;
262char *hostname = NULL;
263struct sockaddr_in *bind_sa4;
264int v4bind_ok = 0;
265#ifdef INET6
266struct sockaddr_in6 *bind_sa6;
267int v6bind_ok = 0;
268#endif
269int signalpipe[2];
270#ifdef SANITY_CHECK
271int nsock;
272#endif
273uid_t euid;
274gid_t egid;
275mode_t mask;
276
277struct servtab *servtab;
278
279extern struct biltin biltins[];
280
281const char *CONFIG = _PATH_INETDCONF;
282const char *pid_file = _PATH_INETDPID;
283
284struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf;
285
286static LIST_HEAD(, procinfo) proctable[PERIPSIZE];
287
288int
289getvalue(const char *arg, int *value, const char *whine)
290{
291 int tmp;
292 char *p;
293
294 tmp = strtol(arg, &p, 0);
295 if (tmp < 0 || *p) {
296 syslog(LOG_ERR, whine, arg);
297 return 1; /* failure */
298 }
299 *value = tmp;
300 return 0; /* success */
301}
302
303static sa_family_t
304whichaf(struct request_info *req)
305{
306 struct sockaddr *sa;
307
308 sa = (struct sockaddr *)req->client->sin;
309 if (sa == NULL)
310 return AF_UNSPEC;
311 if (sa->sa_family == AF_INET6 &&
312 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr))
313 return AF_INET;
314 return sa->sa_family;
315}
316
317int
318main(int argc, char **argv)
319{
320 struct servtab *sep;
321 struct passwd *pwd;
322 struct group *grp;
323 struct sigaction sa, saalrm, sachld, sahup, sapipe;
324 int ch, dofork;
325 pid_t pid;
326 char buf[50];
327#ifdef LOGIN_CAP
328 login_cap_t *lc = NULL;
329#endif
330 struct request_info req;
331 int denied;
332 char *service = NULL;
333 union {
334 struct sockaddr peer_un;
335 struct sockaddr_in peer_un4;
336 struct sockaddr_in6 peer_un6;
337 struct sockaddr_storage peer_max;
338 } p_un;
339#define peer p_un.peer_un
340#define peer4 p_un.peer_un4
341#define peer6 p_un.peer_un6
342#define peermax p_un.peer_max
343 int i;
344 struct addrinfo hints, *res;
345 const char *servname;
346 int error;
347 struct conninfo *conn;
348
349 openlog("inetd", LOG_PID | LOG_NOWAIT | LOG_PERROR, LOG_DAEMON);
350
351 while ((ch = getopt(argc, argv, "dlwWR:a:c:C:p:s:")) != -1)
352 switch(ch) {
353 case 'd':
354 debug = 1;
355 options |= SO_DEBUG;
356 break;
357 case 'l':
358 dolog = 1;
359 break;
360 case 'R':
361 getvalue(optarg, &toomany,
362 "-R %s: bad value for service invocation rate");
363 break;
364 case 'c':
365 getvalue(optarg, &maxchild,
366 "-c %s: bad value for maximum children");
367 break;
368 case 'C':
369 getvalue(optarg, &maxcpm,
370 "-C %s: bad value for maximum children/minute");
371 break;
372 case 'a':
373 hostname = optarg;
374 break;
375 case 'p':
376 pid_file = optarg;
377 break;
378 case 's':
379 getvalue(optarg, &maxperip,
380 "-s %s: bad value for maximum children per source address");
381 break;
382 case 'w':
383 wrap_ex++;
384 break;
385 case 'W':
386 wrap_bi++;
387 break;
388 case '?':
389 default:
390 syslog(LOG_ERR,
391 "usage: inetd [-dlwW] [-a address] [-R rate]"
392 " [-c maximum] [-C rate]"
393 " [-p pidfile] [conf-file]");
394 exit(EX_USAGE);
395 }
396 /*
397 * Initialize Bind Addrs.
398 * When hostname is NULL, wild card bind addrs are obtained from
399 * getaddrinfo(). But getaddrinfo() requires at least one of
400 * hostname or servname is non NULL.
401 * So when hostname is NULL, set dummy value to servname.
402 * Since getaddrinfo() doesn't accept numeric servname, and
403 * we doesn't use ai_socktype of struct addrinfo returned
404 * from getaddrinfo(), we set dummy value to ai_socktype.
405 */
406 servname = (hostname == NULL) ? "0" /* dummy */ : NULL;
407
408 bzero(&hints, sizeof(struct addrinfo));
409 hints.ai_flags = AI_PASSIVE;
410 hints.ai_family = AF_UNSPEC;
411 hints.ai_socktype = SOCK_STREAM; /* dummy */
412 error = getaddrinfo(hostname, servname, &hints, &res);
413 if (error != 0) {
414 syslog(LOG_ERR, "-a %s: %s", hostname, gai_strerror(error));
415 if (error == EAI_SYSTEM)
416 syslog(LOG_ERR, "%s", strerror(errno));
417 exit(EX_USAGE);
418 }
419 do {
420 if (res->ai_addr == NULL) {
421 syslog(LOG_ERR, "-a %s: getaddrinfo failed", hostname);
422 exit(EX_USAGE);
423 }
424 switch (res->ai_addr->sa_family) {
425 case AF_INET:
426 if (v4bind_ok)
427 continue;
428 bind_sa4 = (struct sockaddr_in *)res->ai_addr;
429 /* init port num in case servname is dummy */
430 bind_sa4->sin_port = 0;
431 v4bind_ok = 1;
432 continue;
433#ifdef INET6
434 case AF_INET6:
435 if (v6bind_ok)
436 continue;
437 bind_sa6 = (struct sockaddr_in6 *)res->ai_addr;
438 /* init port num in case servname is dummy */
439 bind_sa6->sin6_port = 0;
440 v6bind_ok = 1;
441 continue;
442#endif
443 }
444 if (v4bind_ok
445#ifdef INET6
446 && v6bind_ok
447#endif
448 )
449 break;
450 } while ((res = res->ai_next) != NULL);
451 if (!v4bind_ok
452#ifdef INET6
453 && !v6bind_ok
454#endif
455 ) {
456 syslog(LOG_ERR, "-a %s: unknown address family", hostname);
457 exit(EX_USAGE);
458 }
459
460 euid = geteuid();
461 egid = getegid();
462 umask(mask = umask(0777));
463
464 argc -= optind;
465 argv += optind;
466
467 if (argc > 0)
468 CONFIG = argv[0];
469 if (access(CONFIG, R_OK) < 0)
470 syslog(LOG_ERR, "Accessing %s: %m, continuing anyway.", CONFIG);
471 if (debug == 0) {
472 FILE *fp;
473 if (daemon(0, 0) < 0) {
474 syslog(LOG_WARNING, "daemon(0,0) failed: %m");
475 }
476 /* From now on we don't want syslog messages going to stderr. */
477 closelog();
478 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
479 /*
480 * In case somebody has started inetd manually, we need to
481 * clear the logname, so that old servers run as root do not
482 * get the user's logname..
483 */
484 if (setlogin("") < 0) {
485 syslog(LOG_WARNING, "cannot clear logname: %m");
486 /* no big deal if it fails.. */
487 }
488 pid = getpid();
489 fp = fopen(pid_file, "w");
490 if (fp) {
491 fprintf(fp, "%ld\n", (long)pid);
492 fclose(fp);
493 } else {
494 syslog(LOG_WARNING, "%s: %m", pid_file);
495 }
496 }
497
498 for (i = 0; i < PERIPSIZE; ++i)
499 LIST_INIT(&proctable[i]);
500
501 if (v4bind_ok) {
502 udpconf = getnetconfigent("udp");
503 tcpconf = getnetconfigent("tcp");
504 if (udpconf == NULL || tcpconf == NULL) {
505 syslog(LOG_ERR, "unknown rpc/udp or rpc/tcp");
506 exit(EX_USAGE);
507 }
508 }
509#ifdef INET6
510 if (v6bind_ok) {
511 udp6conf = getnetconfigent("udp6");
512 tcp6conf = getnetconfigent("tcp6");
513 if (udp6conf == NULL || tcp6conf == NULL) {
514 syslog(LOG_ERR, "unknown rpc/udp6 or rpc/tcp6");
515 exit(EX_USAGE);
516 }
517 }
518#endif
519
520 sa.sa_flags = 0;
521 sigemptyset(&sa.sa_mask);
522 sigaddset(&sa.sa_mask, SIGALRM);
523 sigaddset(&sa.sa_mask, SIGCHLD);
524 sigaddset(&sa.sa_mask, SIGHUP);
525 sa.sa_handler = flag_retry;
526 sigaction(SIGALRM, &sa, &saalrm);
527 config();
528 sa.sa_handler = flag_config;
529 sigaction(SIGHUP, &sa, &sahup);
530 sa.sa_handler = flag_reapchild;
531 sigaction(SIGCHLD, &sa, &sachld);
532 sa.sa_handler = SIG_IGN;
533 sigaction(SIGPIPE, &sa, &sapipe);
534
535 {
536 /* space for daemons to overwrite environment for ps */
537#define DUMMYSIZE 100
538 char dummy[DUMMYSIZE];
539
540 (void)memset(dummy, 'x', DUMMYSIZE - 1);
541 dummy[DUMMYSIZE - 1] = '\0';
542 (void)setenv("inetd_dummy", dummy, 1);
543 }
544
545 if (pipe(signalpipe) != 0) {
546 syslog(LOG_ERR, "pipe: %m");
547 exit(EX_OSERR);
548 }
549 if (fcntl(signalpipe[0], F_SETFD, FD_CLOEXEC) < 0 ||
550 fcntl(signalpipe[1], F_SETFD, FD_CLOEXEC) < 0) {
551 syslog(LOG_ERR, "signalpipe: fcntl (F_SETFD, FD_CLOEXEC): %m");
552 exit(EX_OSERR);
553 }
554 FD_SET(signalpipe[0], &allsock);
555#ifdef SANITY_CHECK
556 nsock++;
557#endif
558 if (signalpipe[0] > maxsock)
559 maxsock = signalpipe[0];
560 if (signalpipe[1] > maxsock)
561 maxsock = signalpipe[1];
562
563 for (;;) {
564 int n, ctrl;
565 fd_set readable;
566
567#ifdef SANITY_CHECK
568 if (nsock == 0) {
569 syslog(LOG_ERR, "%s: nsock=0", __func__);
570 exit(EX_SOFTWARE);
571 }
572#endif
573 readable = allsock;
574 if ((n = select(maxsock + 1, &readable, (fd_set *)0,
575 (fd_set *)0, (struct timeval *)0)) <= 0) {
576 if (n < 0 && errno != EINTR) {
577 syslog(LOG_WARNING, "select: %m");
578 sleep(1);
579 }
580 continue;
581 }
582 /* handle any queued signal flags */
583 if (FD_ISSET(signalpipe[0], &readable)) {
584 int nsig;
585 if (ioctl(signalpipe[0], FIONREAD, &nsig) != 0) {
586 syslog(LOG_ERR, "ioctl: %m");
587 exit(EX_OSERR);
588 }
589 while (--nsig >= 0) {
590 char c;
591 if (read(signalpipe[0], &c, 1) != 1) {
592 syslog(LOG_ERR, "read: %m");
593 exit(EX_OSERR);
594 }
595 if (debug)
596 warnx("handling signal flag %c", c);
597 switch(c) {
598 case 'A': /* sigalrm */
599 retry();
600 break;
601 case 'C': /* sigchld */
602 reapchild();
603 break;
604 case 'H': /* sighup */
605 config();
606 break;
607 }
608 }
609 }
610 for (sep = servtab; n && sep; sep = sep->se_next)
611 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
612 n--;
613 if (debug)
614 warnx("someone wants %s", sep->se_service);
615 dofork = !sep->se_bi || sep->se_bi->bi_fork || ISWRAP(sep);
616 conn = NULL;
617 if (sep->se_accept && sep->se_socktype == SOCK_STREAM) {
618 i = 1;
619 if (ioctl(sep->se_fd, FIONBIO, &i) < 0)
620 syslog(LOG_ERR, "ioctl (FIONBIO, 1): %m");
621 ctrl = accept(sep->se_fd, (struct sockaddr *)0,
622 (socklen_t *)0);
623 if (debug)
624 warnx("accept, ctrl %d", ctrl);
625 if (ctrl < 0) {
626 if (errno != EINTR)
627 syslog(LOG_WARNING,
628 "accept (for %s): %m",
629 sep->se_service);
630 if (sep->se_accept &&
631 sep->se_socktype == SOCK_STREAM)
632 close(ctrl);
633 continue;
634 }
635 i = 0;
636 if (ioctl(sep->se_fd, FIONBIO, &i) < 0)
637 syslog(LOG_ERR, "ioctl1(FIONBIO, 0): %m");
638 if (ioctl(ctrl, FIONBIO, &i) < 0)
639 syslog(LOG_ERR, "ioctl2(FIONBIO, 0): %m");
640 if (cpmip(sep, ctrl) < 0) {
641 close(ctrl);
642 continue;
643 }
644 if (dofork &&
645 (conn = search_conn(sep, ctrl)) != NULL &&
646 !room_conn(sep, conn)) {
647 close(ctrl);
648 continue;
649 }
650 } else
651 ctrl = sep->se_fd;
652 if (dolog && !ISWRAP(sep)) {
653 char pname[INET6_ADDRSTRLEN] = "unknown";
654 socklen_t sl;
655 sl = sizeof peermax;
656 if (getpeername(ctrl, (struct sockaddr *)
657 &peermax, &sl)) {
658 sl = sizeof peermax;
659 if (recvfrom(ctrl, buf, sizeof(buf),
660 MSG_PEEK,
661 (struct sockaddr *)&peermax,
662 &sl) >= 0) {
663 getnameinfo((struct sockaddr *)&peermax,
664 peer.sa_len,
665 pname, sizeof(pname),
153#ifndef LIBWRAP_ALLOW_FACILITY
154# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
155#endif
156#ifndef LIBWRAP_ALLOW_SEVERITY
157# define LIBWRAP_ALLOW_SEVERITY LOG_INFO
158#endif
159#ifndef LIBWRAP_DENY_FACILITY
160# define LIBWRAP_DENY_FACILITY LOG_AUTH
161#endif
162#ifndef LIBWRAP_DENY_SEVERITY
163# define LIBWRAP_DENY_SEVERITY LOG_WARNING
164#endif
165
166#define ISWRAP(sep) \
167 ( ((wrap_ex && !(sep)->se_bi) || (wrap_bi && (sep)->se_bi)) \
168 && (sep->se_family == AF_INET || sep->se_family == AF_INET6) \
169 && ( ((sep)->se_accept && (sep)->se_socktype == SOCK_STREAM) \
170 || (sep)->se_socktype == SOCK_DGRAM))
171
172#ifdef LOGIN_CAP
173#include <login_cap.h>
174
175/* see init.c */
176#define RESOURCE_RC "daemon"
177
178#endif
179
180#ifndef MAXCHILD
181#define MAXCHILD -1 /* maximum number of this service
182 < 0 = no limit */
183#endif
184
185#ifndef MAXCPM
186#define MAXCPM -1 /* rate limit invocations from a
187 single remote address,
188 < 0 = no limit */
189#endif
190
191#ifndef MAXPERIP
192#define MAXPERIP -1 /* maximum number of this service
193 from a single remote address,
194 < 0 = no limit */
195#endif
196
197#ifndef TOOMANY
198#define TOOMANY 256 /* don't start more than TOOMANY */
199#endif
200#define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
201#define RETRYTIME (60*10) /* retry after bind or server fail */
202#define MAX_MAXCHLD 32767 /* max allowable max children */
203
204#define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
205
206void close_sep(struct servtab *);
207void flag_signal(int);
208void flag_config(int);
209void config(void);
210int cpmip(const struct servtab *, int);
211void endconfig(void);
212struct servtab *enter(struct servtab *);
213void freeconfig(struct servtab *);
214struct servtab *getconfigent(void);
215int matchservent(const char *, const char *, const char *);
216char *nextline(FILE *);
217void addchild(struct servtab *, int);
218void flag_reapchild(int);
219void reapchild(void);
220void enable(struct servtab *);
221void disable(struct servtab *);
222void flag_retry(int);
223void retry(void);
224int setconfig(void);
225void setup(struct servtab *);
226#ifdef IPSEC
227void ipsecsetup(struct servtab *);
228#endif
229void unregisterrpc(register struct servtab *sep);
230static struct conninfo *search_conn(struct servtab *sep, int ctrl);
231static int room_conn(struct servtab *sep, struct conninfo *conn);
232static void addchild_conn(struct conninfo *conn, pid_t pid);
233static void reapchild_conn(pid_t pid);
234static void free_conn(struct conninfo *conn);
235static void resize_conn(struct servtab *sep, int maxperip);
236static void free_connlist(struct servtab *sep);
237static void free_proc(struct procinfo *);
238static struct procinfo *search_proc(pid_t pid, int add);
239static int hashval(char *p, int len);
240
241int allow_severity;
242int deny_severity;
243int wrap_ex = 0;
244int wrap_bi = 0;
245int debug = 0;
246int dolog = 0;
247int maxsock; /* highest-numbered descriptor */
248fd_set allsock;
249int options;
250int timingout;
251int toomany = TOOMANY;
252int maxchild = MAXCHILD;
253int maxcpm = MAXCPM;
254int maxperip = MAXPERIP;
255struct servent *sp;
256struct rpcent *rpc;
257char *hostname = NULL;
258struct sockaddr_in *bind_sa4;
259int v4bind_ok = 0;
260#ifdef INET6
261struct sockaddr_in6 *bind_sa6;
262int v6bind_ok = 0;
263#endif
264int signalpipe[2];
265#ifdef SANITY_CHECK
266int nsock;
267#endif
268uid_t euid;
269gid_t egid;
270mode_t mask;
271
272struct servtab *servtab;
273
274extern struct biltin biltins[];
275
276const char *CONFIG = _PATH_INETDCONF;
277const char *pid_file = _PATH_INETDPID;
278
279struct netconfig *udpconf, *tcpconf, *udp6conf, *tcp6conf;
280
281static LIST_HEAD(, procinfo) proctable[PERIPSIZE];
282
283int
284getvalue(const char *arg, int *value, const char *whine)
285{
286 int tmp;
287 char *p;
288
289 tmp = strtol(arg, &p, 0);
290 if (tmp < 0 || *p) {
291 syslog(LOG_ERR, whine, arg);
292 return 1; /* failure */
293 }
294 *value = tmp;
295 return 0; /* success */
296}
297
298static sa_family_t
299whichaf(struct request_info *req)
300{
301 struct sockaddr *sa;
302
303 sa = (struct sockaddr *)req->client->sin;
304 if (sa == NULL)
305 return AF_UNSPEC;
306 if (sa->sa_family == AF_INET6 &&
307 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr))
308 return AF_INET;
309 return sa->sa_family;
310}
311
312int
313main(int argc, char **argv)
314{
315 struct servtab *sep;
316 struct passwd *pwd;
317 struct group *grp;
318 struct sigaction sa, saalrm, sachld, sahup, sapipe;
319 int ch, dofork;
320 pid_t pid;
321 char buf[50];
322#ifdef LOGIN_CAP
323 login_cap_t *lc = NULL;
324#endif
325 struct request_info req;
326 int denied;
327 char *service = NULL;
328 union {
329 struct sockaddr peer_un;
330 struct sockaddr_in peer_un4;
331 struct sockaddr_in6 peer_un6;
332 struct sockaddr_storage peer_max;
333 } p_un;
334#define peer p_un.peer_un
335#define peer4 p_un.peer_un4
336#define peer6 p_un.peer_un6
337#define peermax p_un.peer_max
338 int i;
339 struct addrinfo hints, *res;
340 const char *servname;
341 int error;
342 struct conninfo *conn;
343
344 openlog("inetd", LOG_PID | LOG_NOWAIT | LOG_PERROR, LOG_DAEMON);
345
346 while ((ch = getopt(argc, argv, "dlwWR:a:c:C:p:s:")) != -1)
347 switch(ch) {
348 case 'd':
349 debug = 1;
350 options |= SO_DEBUG;
351 break;
352 case 'l':
353 dolog = 1;
354 break;
355 case 'R':
356 getvalue(optarg, &toomany,
357 "-R %s: bad value for service invocation rate");
358 break;
359 case 'c':
360 getvalue(optarg, &maxchild,
361 "-c %s: bad value for maximum children");
362 break;
363 case 'C':
364 getvalue(optarg, &maxcpm,
365 "-C %s: bad value for maximum children/minute");
366 break;
367 case 'a':
368 hostname = optarg;
369 break;
370 case 'p':
371 pid_file = optarg;
372 break;
373 case 's':
374 getvalue(optarg, &maxperip,
375 "-s %s: bad value for maximum children per source address");
376 break;
377 case 'w':
378 wrap_ex++;
379 break;
380 case 'W':
381 wrap_bi++;
382 break;
383 case '?':
384 default:
385 syslog(LOG_ERR,
386 "usage: inetd [-dlwW] [-a address] [-R rate]"
387 " [-c maximum] [-C rate]"
388 " [-p pidfile] [conf-file]");
389 exit(EX_USAGE);
390 }
391 /*
392 * Initialize Bind Addrs.
393 * When hostname is NULL, wild card bind addrs are obtained from
394 * getaddrinfo(). But getaddrinfo() requires at least one of
395 * hostname or servname is non NULL.
396 * So when hostname is NULL, set dummy value to servname.
397 * Since getaddrinfo() doesn't accept numeric servname, and
398 * we doesn't use ai_socktype of struct addrinfo returned
399 * from getaddrinfo(), we set dummy value to ai_socktype.
400 */
401 servname = (hostname == NULL) ? "0" /* dummy */ : NULL;
402
403 bzero(&hints, sizeof(struct addrinfo));
404 hints.ai_flags = AI_PASSIVE;
405 hints.ai_family = AF_UNSPEC;
406 hints.ai_socktype = SOCK_STREAM; /* dummy */
407 error = getaddrinfo(hostname, servname, &hints, &res);
408 if (error != 0) {
409 syslog(LOG_ERR, "-a %s: %s", hostname, gai_strerror(error));
410 if (error == EAI_SYSTEM)
411 syslog(LOG_ERR, "%s", strerror(errno));
412 exit(EX_USAGE);
413 }
414 do {
415 if (res->ai_addr == NULL) {
416 syslog(LOG_ERR, "-a %s: getaddrinfo failed", hostname);
417 exit(EX_USAGE);
418 }
419 switch (res->ai_addr->sa_family) {
420 case AF_INET:
421 if (v4bind_ok)
422 continue;
423 bind_sa4 = (struct sockaddr_in *)res->ai_addr;
424 /* init port num in case servname is dummy */
425 bind_sa4->sin_port = 0;
426 v4bind_ok = 1;
427 continue;
428#ifdef INET6
429 case AF_INET6:
430 if (v6bind_ok)
431 continue;
432 bind_sa6 = (struct sockaddr_in6 *)res->ai_addr;
433 /* init port num in case servname is dummy */
434 bind_sa6->sin6_port = 0;
435 v6bind_ok = 1;
436 continue;
437#endif
438 }
439 if (v4bind_ok
440#ifdef INET6
441 && v6bind_ok
442#endif
443 )
444 break;
445 } while ((res = res->ai_next) != NULL);
446 if (!v4bind_ok
447#ifdef INET6
448 && !v6bind_ok
449#endif
450 ) {
451 syslog(LOG_ERR, "-a %s: unknown address family", hostname);
452 exit(EX_USAGE);
453 }
454
455 euid = geteuid();
456 egid = getegid();
457 umask(mask = umask(0777));
458
459 argc -= optind;
460 argv += optind;
461
462 if (argc > 0)
463 CONFIG = argv[0];
464 if (access(CONFIG, R_OK) < 0)
465 syslog(LOG_ERR, "Accessing %s: %m, continuing anyway.", CONFIG);
466 if (debug == 0) {
467 FILE *fp;
468 if (daemon(0, 0) < 0) {
469 syslog(LOG_WARNING, "daemon(0,0) failed: %m");
470 }
471 /* From now on we don't want syslog messages going to stderr. */
472 closelog();
473 openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
474 /*
475 * In case somebody has started inetd manually, we need to
476 * clear the logname, so that old servers run as root do not
477 * get the user's logname..
478 */
479 if (setlogin("") < 0) {
480 syslog(LOG_WARNING, "cannot clear logname: %m");
481 /* no big deal if it fails.. */
482 }
483 pid = getpid();
484 fp = fopen(pid_file, "w");
485 if (fp) {
486 fprintf(fp, "%ld\n", (long)pid);
487 fclose(fp);
488 } else {
489 syslog(LOG_WARNING, "%s: %m", pid_file);
490 }
491 }
492
493 for (i = 0; i < PERIPSIZE; ++i)
494 LIST_INIT(&proctable[i]);
495
496 if (v4bind_ok) {
497 udpconf = getnetconfigent("udp");
498 tcpconf = getnetconfigent("tcp");
499 if (udpconf == NULL || tcpconf == NULL) {
500 syslog(LOG_ERR, "unknown rpc/udp or rpc/tcp");
501 exit(EX_USAGE);
502 }
503 }
504#ifdef INET6
505 if (v6bind_ok) {
506 udp6conf = getnetconfigent("udp6");
507 tcp6conf = getnetconfigent("tcp6");
508 if (udp6conf == NULL || tcp6conf == NULL) {
509 syslog(LOG_ERR, "unknown rpc/udp6 or rpc/tcp6");
510 exit(EX_USAGE);
511 }
512 }
513#endif
514
515 sa.sa_flags = 0;
516 sigemptyset(&sa.sa_mask);
517 sigaddset(&sa.sa_mask, SIGALRM);
518 sigaddset(&sa.sa_mask, SIGCHLD);
519 sigaddset(&sa.sa_mask, SIGHUP);
520 sa.sa_handler = flag_retry;
521 sigaction(SIGALRM, &sa, &saalrm);
522 config();
523 sa.sa_handler = flag_config;
524 sigaction(SIGHUP, &sa, &sahup);
525 sa.sa_handler = flag_reapchild;
526 sigaction(SIGCHLD, &sa, &sachld);
527 sa.sa_handler = SIG_IGN;
528 sigaction(SIGPIPE, &sa, &sapipe);
529
530 {
531 /* space for daemons to overwrite environment for ps */
532#define DUMMYSIZE 100
533 char dummy[DUMMYSIZE];
534
535 (void)memset(dummy, 'x', DUMMYSIZE - 1);
536 dummy[DUMMYSIZE - 1] = '\0';
537 (void)setenv("inetd_dummy", dummy, 1);
538 }
539
540 if (pipe(signalpipe) != 0) {
541 syslog(LOG_ERR, "pipe: %m");
542 exit(EX_OSERR);
543 }
544 if (fcntl(signalpipe[0], F_SETFD, FD_CLOEXEC) < 0 ||
545 fcntl(signalpipe[1], F_SETFD, FD_CLOEXEC) < 0) {
546 syslog(LOG_ERR, "signalpipe: fcntl (F_SETFD, FD_CLOEXEC): %m");
547 exit(EX_OSERR);
548 }
549 FD_SET(signalpipe[0], &allsock);
550#ifdef SANITY_CHECK
551 nsock++;
552#endif
553 if (signalpipe[0] > maxsock)
554 maxsock = signalpipe[0];
555 if (signalpipe[1] > maxsock)
556 maxsock = signalpipe[1];
557
558 for (;;) {
559 int n, ctrl;
560 fd_set readable;
561
562#ifdef SANITY_CHECK
563 if (nsock == 0) {
564 syslog(LOG_ERR, "%s: nsock=0", __func__);
565 exit(EX_SOFTWARE);
566 }
567#endif
568 readable = allsock;
569 if ((n = select(maxsock + 1, &readable, (fd_set *)0,
570 (fd_set *)0, (struct timeval *)0)) <= 0) {
571 if (n < 0 && errno != EINTR) {
572 syslog(LOG_WARNING, "select: %m");
573 sleep(1);
574 }
575 continue;
576 }
577 /* handle any queued signal flags */
578 if (FD_ISSET(signalpipe[0], &readable)) {
579 int nsig;
580 if (ioctl(signalpipe[0], FIONREAD, &nsig) != 0) {
581 syslog(LOG_ERR, "ioctl: %m");
582 exit(EX_OSERR);
583 }
584 while (--nsig >= 0) {
585 char c;
586 if (read(signalpipe[0], &c, 1) != 1) {
587 syslog(LOG_ERR, "read: %m");
588 exit(EX_OSERR);
589 }
590 if (debug)
591 warnx("handling signal flag %c", c);
592 switch(c) {
593 case 'A': /* sigalrm */
594 retry();
595 break;
596 case 'C': /* sigchld */
597 reapchild();
598 break;
599 case 'H': /* sighup */
600 config();
601 break;
602 }
603 }
604 }
605 for (sep = servtab; n && sep; sep = sep->se_next)
606 if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
607 n--;
608 if (debug)
609 warnx("someone wants %s", sep->se_service);
610 dofork = !sep->se_bi || sep->se_bi->bi_fork || ISWRAP(sep);
611 conn = NULL;
612 if (sep->se_accept && sep->se_socktype == SOCK_STREAM) {
613 i = 1;
614 if (ioctl(sep->se_fd, FIONBIO, &i) < 0)
615 syslog(LOG_ERR, "ioctl (FIONBIO, 1): %m");
616 ctrl = accept(sep->se_fd, (struct sockaddr *)0,
617 (socklen_t *)0);
618 if (debug)
619 warnx("accept, ctrl %d", ctrl);
620 if (ctrl < 0) {
621 if (errno != EINTR)
622 syslog(LOG_WARNING,
623 "accept (for %s): %m",
624 sep->se_service);
625 if (sep->se_accept &&
626 sep->se_socktype == SOCK_STREAM)
627 close(ctrl);
628 continue;
629 }
630 i = 0;
631 if (ioctl(sep->se_fd, FIONBIO, &i) < 0)
632 syslog(LOG_ERR, "ioctl1(FIONBIO, 0): %m");
633 if (ioctl(ctrl, FIONBIO, &i) < 0)
634 syslog(LOG_ERR, "ioctl2(FIONBIO, 0): %m");
635 if (cpmip(sep, ctrl) < 0) {
636 close(ctrl);
637 continue;
638 }
639 if (dofork &&
640 (conn = search_conn(sep, ctrl)) != NULL &&
641 !room_conn(sep, conn)) {
642 close(ctrl);
643 continue;
644 }
645 } else
646 ctrl = sep->se_fd;
647 if (dolog && !ISWRAP(sep)) {
648 char pname[INET6_ADDRSTRLEN] = "unknown";
649 socklen_t sl;
650 sl = sizeof peermax;
651 if (getpeername(ctrl, (struct sockaddr *)
652 &peermax, &sl)) {
653 sl = sizeof peermax;
654 if (recvfrom(ctrl, buf, sizeof(buf),
655 MSG_PEEK,
656 (struct sockaddr *)&peermax,
657 &sl) >= 0) {
658 getnameinfo((struct sockaddr *)&peermax,
659 peer.sa_len,
660 pname, sizeof(pname),
666 NULL, 0,
667 NI_NUMERICHOST|
668 NI_WITHSCOPEID);
661 NULL, 0, NI_NUMERICHOST);
669 }
670 } else {
671 getnameinfo((struct sockaddr *)&peermax,
672 peer.sa_len,
673 pname, sizeof(pname),
662 }
663 } else {
664 getnameinfo((struct sockaddr *)&peermax,
665 peer.sa_len,
666 pname, sizeof(pname),
674 NULL, 0,
675 NI_NUMERICHOST|
676 NI_WITHSCOPEID);
667 NULL, 0, NI_NUMERICHOST);
677 }
678 syslog(LOG_INFO,"%s from %s", sep->se_service, pname);
679 }
680 (void) sigblock(SIGBLOCK);
681 pid = 0;
682 /*
683 * Fork for all external services, builtins which need to
684 * fork and anything we're wrapping (as wrapping might
685 * block or use hosts_options(5) twist).
686 */
687 if (dofork) {
688 if (sep->se_count++ == 0)
689 (void)gettimeofday(&sep->se_time, (struct timezone *)NULL);
690 else if (toomany > 0 && sep->se_count >= toomany) {
691 struct timeval now;
692
693 (void)gettimeofday(&now, (struct timezone *)NULL);
694 if (now.tv_sec - sep->se_time.tv_sec >
695 CNT_INTVL) {
696 sep->se_time = now;
697 sep->se_count = 1;
698 } else {
699 syslog(LOG_ERR,
700 "%s/%s server failing (looping), service terminated",
701 sep->se_service, sep->se_proto);
702 if (sep->se_accept &&
703 sep->se_socktype == SOCK_STREAM)
704 close(ctrl);
705 close_sep(sep);
706 free_conn(conn);
707 sigsetmask(0L);
708 if (!timingout) {
709 timingout = 1;
710 alarm(RETRYTIME);
711 }
712 continue;
713 }
714 }
715 pid = fork();
716 }
717 if (pid < 0) {
718 syslog(LOG_ERR, "fork: %m");
719 if (sep->se_accept &&
720 sep->se_socktype == SOCK_STREAM)
721 close(ctrl);
722 free_conn(conn);
723 sigsetmask(0L);
724 sleep(1);
725 continue;
726 }
727 if (pid) {
728 addchild_conn(conn, pid);
729 addchild(sep, pid);
730 }
731 sigsetmask(0L);
732 if (pid == 0) {
733 if (dofork) {
734 sigaction(SIGALRM, &saalrm, (struct sigaction *)0);
735 sigaction(SIGCHLD, &sachld, (struct sigaction *)0);
736 sigaction(SIGHUP, &sahup, (struct sigaction *)0);
737 /* SIGPIPE reset before exec */
738 }
739 /*
740 * Call tcpmux to find the real service to exec.
741 */
742 if (sep->se_bi &&
743 sep->se_bi->bi_fn == (bi_fn_t *) tcpmux) {
744 sep = tcpmux(ctrl);
745 if (sep == NULL) {
746 close(ctrl);
747 _exit(0);
748 }
749 }
750 if (ISWRAP(sep)) {
751 inetd_setproctitle("wrapping", ctrl);
752 service = sep->se_server_name ?
753 sep->se_server_name : sep->se_service;
754 request_init(&req, RQ_DAEMON, service, RQ_FILE, ctrl, 0);
755 fromhost(&req);
756 deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
757 allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
758 denied = !hosts_access(&req);
759 if (denied) {
760 syslog(deny_severity,
761 "refused connection from %.500s, service %s (%s%s)",
762 eval_client(&req), service, sep->se_proto,
763 (whichaf(&req) == AF_INET6) ? "6" : "");
764 if (sep->se_socktype != SOCK_STREAM)
765 recv(ctrl, buf, sizeof (buf), 0);
766 if (dofork) {
767 sleep(1);
768 _exit(0);
769 }
770 }
771 if (dolog) {
772 syslog(allow_severity,
773 "connection from %.500s, service %s (%s%s)",
774 eval_client(&req), service, sep->se_proto,
775 (whichaf(&req) == AF_INET6) ? "6" : "");
776 }
777 }
778 if (sep->se_bi) {
779 (*sep->se_bi->bi_fn)(ctrl, sep);
780 } else {
781 if (debug)
782 warnx("%d execl %s",
783 getpid(), sep->se_server);
784 /* Clear close-on-exec. */
785 if (fcntl(ctrl, F_SETFD, 0) < 0) {
786 syslog(LOG_ERR,
787 "%s/%s: fcntl (F_SETFD, 0): %m",
788 sep->se_service, sep->se_proto);
789 _exit(EX_OSERR);
790 }
791 if (ctrl != 0) {
792 dup2(ctrl, 0);
793 close(ctrl);
794 }
795 dup2(0, 1);
796 dup2(0, 2);
797 if ((pwd = getpwnam(sep->se_user)) == NULL) {
798 syslog(LOG_ERR,
799 "%s/%s: %s: no such user",
800 sep->se_service, sep->se_proto,
801 sep->se_user);
802 if (sep->se_socktype != SOCK_STREAM)
803 recv(0, buf, sizeof (buf), 0);
804 _exit(EX_NOUSER);
805 }
806 grp = NULL;
807 if ( sep->se_group != NULL
808 && (grp = getgrnam(sep->se_group)) == NULL
809 ) {
810 syslog(LOG_ERR,
811 "%s/%s: %s: no such group",
812 sep->se_service, sep->se_proto,
813 sep->se_group);
814 if (sep->se_socktype != SOCK_STREAM)
815 recv(0, buf, sizeof (buf), 0);
816 _exit(EX_NOUSER);
817 }
818 if (grp != NULL)
819 pwd->pw_gid = grp->gr_gid;
820#ifdef LOGIN_CAP
821 if ((lc = login_getclass(sep->se_class)) == NULL) {
822 /* error syslogged by getclass */
823 syslog(LOG_ERR,
824 "%s/%s: %s: login class error",
825 sep->se_service, sep->se_proto,
826 sep->se_class);
827 if (sep->se_socktype != SOCK_STREAM)
828 recv(0, buf, sizeof (buf), 0);
829 _exit(EX_NOUSER);
830 }
831#endif
832 if (setsid() < 0) {
833 syslog(LOG_ERR,
834 "%s: can't setsid(): %m",
835 sep->se_service);
836 /* _exit(EX_OSERR); not fatal yet */
837 }
838#ifdef LOGIN_CAP
839 if (setusercontext(lc, pwd, pwd->pw_uid,
840 LOGIN_SETALL & ~LOGIN_SETMAC)
841 != 0) {
842 syslog(LOG_ERR,
843 "%s: can't setusercontext(..%s..): %m",
844 sep->se_service, sep->se_user);
845 _exit(EX_OSERR);
846 }
847 login_close(lc);
848#else
849 if (pwd->pw_uid) {
850 if (setlogin(sep->se_user) < 0) {
851 syslog(LOG_ERR,
852 "%s: can't setlogin(%s): %m",
853 sep->se_service, sep->se_user);
854 /* _exit(EX_OSERR); not yet */
855 }
856 if (setgid(pwd->pw_gid) < 0) {
857 syslog(LOG_ERR,
858 "%s: can't set gid %d: %m",
859 sep->se_service, pwd->pw_gid);
860 _exit(EX_OSERR);
861 }
862 (void) initgroups(pwd->pw_name,
863 pwd->pw_gid);
864 if (setuid(pwd->pw_uid) < 0) {
865 syslog(LOG_ERR,
866 "%s: can't set uid %d: %m",
867 sep->se_service, pwd->pw_uid);
868 _exit(EX_OSERR);
869 }
870 }
871#endif
872 sigaction(SIGPIPE, &sapipe,
873 (struct sigaction *)0);
874 execv(sep->se_server, sep->se_argv);
875 syslog(LOG_ERR,
876 "cannot execute %s: %m", sep->se_server);
877 if (sep->se_socktype != SOCK_STREAM)
878 recv(0, buf, sizeof (buf), 0);
879 }
880 if (dofork)
881 _exit(0);
882 }
883 if (sep->se_accept && sep->se_socktype == SOCK_STREAM)
884 close(ctrl);
885 }
886 }
887}
888
889/*
890 * Add a signal flag to the signal flag queue for later handling
891 */
892
893void
894flag_signal(int c)
895{
896 char ch = c;
897
898 if (write(signalpipe[1], &ch, 1) != 1) {
899 syslog(LOG_ERR, "write: %m");
900 _exit(EX_OSERR);
901 }
902}
903
904/*
905 * Record a new child pid for this service. If we've reached the
906 * limit on children, then stop accepting incoming requests.
907 */
908
909void
910addchild(struct servtab *sep, pid_t pid)
911{
912 if (sep->se_maxchild <= 0)
913 return;
914#ifdef SANITY_CHECK
915 if (sep->se_numchild >= sep->se_maxchild) {
916 syslog(LOG_ERR, "%s: %d >= %d",
917 __func__, sep->se_numchild, sep->se_maxchild);
918 exit(EX_SOFTWARE);
919 }
920#endif
921 sep->se_pids[sep->se_numchild++] = pid;
922 if (sep->se_numchild == sep->se_maxchild)
923 disable(sep);
924}
925
926/*
927 * Some child process has exited. See if it's on somebody's list.
928 */
929
930void
931flag_reapchild(int signo __unused)
932{
933 flag_signal('C');
934}
935
936void
937reapchild(void)
938{
939 int k, status;
940 pid_t pid;
941 struct servtab *sep;
942
943 for (;;) {
944 pid = wait3(&status, WNOHANG, (struct rusage *)0);
945 if (pid <= 0)
946 break;
947 if (debug)
948 warnx("%d reaped, %s %u", pid,
949 WIFEXITED(status) ? "status" : "signal",
950 WIFEXITED(status) ? WEXITSTATUS(status)
951 : WTERMSIG(status));
952 for (sep = servtab; sep; sep = sep->se_next) {
953 for (k = 0; k < sep->se_numchild; k++)
954 if (sep->se_pids[k] == pid)
955 break;
956 if (k == sep->se_numchild)
957 continue;
958 if (sep->se_numchild == sep->se_maxchild)
959 enable(sep);
960 sep->se_pids[k] = sep->se_pids[--sep->se_numchild];
961 if (WIFSIGNALED(status) || WEXITSTATUS(status))
962 syslog(LOG_WARNING,
963 "%s[%d]: exited, %s %u",
964 sep->se_server, pid,
965 WIFEXITED(status) ? "status" : "signal",
966 WIFEXITED(status) ? WEXITSTATUS(status)
967 : WTERMSIG(status));
968 break;
969 }
970 reapchild_conn(pid);
971 }
972}
973
974void
975flag_config(int signo __unused)
976{
977 flag_signal('H');
978}
979
980void
981config(void)
982{
983 struct servtab *sep, *new, **sepp;
984 long omask;
985 int new_nomapped;
986#ifdef LOGIN_CAP
987 login_cap_t *lc = NULL;
988#endif
989
990 if (!setconfig()) {
991 syslog(LOG_ERR, "%s: %m", CONFIG);
992 return;
993 }
994 for (sep = servtab; sep; sep = sep->se_next)
995 sep->se_checked = 0;
996 while ((new = getconfigent())) {
997 if (getpwnam(new->se_user) == NULL) {
998 syslog(LOG_ERR,
999 "%s/%s: no such user '%s', service ignored",
1000 new->se_service, new->se_proto, new->se_user);
1001 continue;
1002 }
1003 if (new->se_group && getgrnam(new->se_group) == NULL) {
1004 syslog(LOG_ERR,
1005 "%s/%s: no such group '%s', service ignored",
1006 new->se_service, new->se_proto, new->se_group);
1007 continue;
1008 }
1009#ifdef LOGIN_CAP
1010 if ((lc = login_getclass(new->se_class)) == NULL) {
1011 /* error syslogged by getclass */
1012 syslog(LOG_ERR,
1013 "%s/%s: %s: login class error, service ignored",
1014 new->se_service, new->se_proto, new->se_class);
1015 continue;
1016 }
1017 login_close(lc);
1018#endif
1019 new_nomapped = new->se_nomapped;
1020 for (sep = servtab; sep; sep = sep->se_next)
1021 if (strcmp(sep->se_service, new->se_service) == 0 &&
1022 strcmp(sep->se_proto, new->se_proto) == 0 &&
1023 sep->se_rpc == new->se_rpc &&
1024 sep->se_socktype == new->se_socktype &&
1025 sep->se_family == new->se_family)
1026 break;
1027 if (sep != 0) {
1028 int i;
1029
1030#define SWAP(t,a, b) { t c = a; a = b; b = c; }
1031 omask = sigblock(SIGBLOCK);
1032 if (sep->se_nomapped != new->se_nomapped) {
1033 /* for rpc keep old nommaped till unregister */
1034 if (!sep->se_rpc)
1035 sep->se_nomapped = new->se_nomapped;
1036 sep->se_reset = 1;
1037 }
1038 /* copy over outstanding child pids */
1039 if (sep->se_maxchild > 0 && new->se_maxchild > 0) {
1040 new->se_numchild = sep->se_numchild;
1041 if (new->se_numchild > new->se_maxchild)
1042 new->se_numchild = new->se_maxchild;
1043 memcpy(new->se_pids, sep->se_pids,
1044 new->se_numchild * sizeof(*new->se_pids));
1045 }
1046 SWAP(pid_t *, sep->se_pids, new->se_pids);
1047 sep->se_maxchild = new->se_maxchild;
1048 sep->se_numchild = new->se_numchild;
1049 sep->se_maxcpm = new->se_maxcpm;
1050 resize_conn(sep, new->se_maxperip);
1051 sep->se_maxperip = new->se_maxperip;
1052 sep->se_bi = new->se_bi;
1053 /* might need to turn on or off service now */
1054 if (sep->se_fd >= 0) {
1055 if (sep->se_maxchild > 0
1056 && sep->se_numchild == sep->se_maxchild) {
1057 if (FD_ISSET(sep->se_fd, &allsock))
1058 disable(sep);
1059 } else {
1060 if (!FD_ISSET(sep->se_fd, &allsock))
1061 enable(sep);
1062 }
1063 }
1064 sep->se_accept = new->se_accept;
1065 SWAP(char *, sep->se_user, new->se_user);
1066 SWAP(char *, sep->se_group, new->se_group);
1067#ifdef LOGIN_CAP
1068 SWAP(char *, sep->se_class, new->se_class);
1069#endif
1070 SWAP(char *, sep->se_server, new->se_server);
1071 SWAP(char *, sep->se_server_name, new->se_server_name);
1072 for (i = 0; i < MAXARGV; i++)
1073 SWAP(char *, sep->se_argv[i], new->se_argv[i]);
1074#ifdef IPSEC
1075 SWAP(char *, sep->se_policy, new->se_policy);
1076 ipsecsetup(sep);
1077#endif
1078 sigsetmask(omask);
1079 freeconfig(new);
1080 if (debug)
1081 print_service("REDO", sep);
1082 } else {
1083 sep = enter(new);
1084 if (debug)
1085 print_service("ADD ", sep);
1086 }
1087 sep->se_checked = 1;
1088 if (ISMUX(sep)) {
1089 sep->se_fd = -1;
1090 continue;
1091 }
1092 switch (sep->se_family) {
1093 case AF_INET:
1094 if (!v4bind_ok) {
1095 sep->se_fd = -1;
1096 continue;
1097 }
1098 break;
1099#ifdef INET6
1100 case AF_INET6:
1101 if (!v6bind_ok) {
1102 sep->se_fd = -1;
1103 continue;
1104 }
1105 break;
1106#endif
1107 }
1108 if (!sep->se_rpc) {
1109 if (sep->se_family != AF_UNIX) {
1110 sp = getservbyname(sep->se_service, sep->se_proto);
1111 if (sp == 0) {
1112 syslog(LOG_ERR, "%s/%s: unknown service",
1113 sep->se_service, sep->se_proto);
1114 sep->se_checked = 0;
1115 continue;
1116 }
1117 }
1118 switch (sep->se_family) {
1119 case AF_INET:
1120 if (sp->s_port != sep->se_ctrladdr4.sin_port) {
1121 sep->se_ctrladdr4.sin_port =
1122 sp->s_port;
1123 sep->se_reset = 1;
1124 }
1125 break;
1126#ifdef INET6
1127 case AF_INET6:
1128 if (sp->s_port !=
1129 sep->se_ctrladdr6.sin6_port) {
1130 sep->se_ctrladdr6.sin6_port =
1131 sp->s_port;
1132 sep->se_reset = 1;
1133 }
1134 break;
1135#endif
1136 }
1137 if (sep->se_reset != 0 && sep->se_fd >= 0)
1138 close_sep(sep);
1139 } else {
1140 rpc = getrpcbyname(sep->se_service);
1141 if (rpc == 0) {
1142 syslog(LOG_ERR, "%s/%s unknown RPC service",
1143 sep->se_service, sep->se_proto);
1144 if (sep->se_fd != -1)
1145 (void) close(sep->se_fd);
1146 sep->se_fd = -1;
1147 continue;
1148 }
1149 if (sep->se_reset != 0 ||
1150 rpc->r_number != sep->se_rpc_prog) {
1151 if (sep->se_rpc_prog)
1152 unregisterrpc(sep);
1153 sep->se_rpc_prog = rpc->r_number;
1154 if (sep->se_fd != -1)
1155 (void) close(sep->se_fd);
1156 sep->se_fd = -1;
1157 }
1158 sep->se_nomapped = new_nomapped;
1159 }
1160 sep->se_reset = 0;
1161 if (sep->se_fd == -1)
1162 setup(sep);
1163 }
1164 endconfig();
1165 /*
1166 * Purge anything not looked at above.
1167 */
1168 omask = sigblock(SIGBLOCK);
1169 sepp = &servtab;
1170 while ((sep = *sepp)) {
1171 if (sep->se_checked) {
1172 sepp = &sep->se_next;
1173 continue;
1174 }
1175 *sepp = sep->se_next;
1176 if (sep->se_fd >= 0)
1177 close_sep(sep);
1178 if (debug)
1179 print_service("FREE", sep);
1180 if (sep->se_rpc && sep->se_rpc_prog > 0)
1181 unregisterrpc(sep);
1182 freeconfig(sep);
1183 free(sep);
1184 }
1185 (void) sigsetmask(omask);
1186}
1187
1188void
1189unregisterrpc(struct servtab *sep)
1190{
1191 u_int i;
1192 struct servtab *sepp;
1193 long omask;
1194 struct netconfig *netid4, *netid6;
1195
1196 omask = sigblock(SIGBLOCK);
1197 netid4 = sep->se_socktype == SOCK_DGRAM ? udpconf : tcpconf;
1198 netid6 = sep->se_socktype == SOCK_DGRAM ? udp6conf : tcp6conf;
1199 if (sep->se_family == AF_INET)
1200 netid6 = NULL;
1201 else if (sep->se_nomapped)
1202 netid4 = NULL;
1203 /*
1204 * Conflict if same prog and protocol - In that case one should look
1205 * to versions, but it is not interesting: having separate servers for
1206 * different versions does not work well.
1207 * Therefore one do not unregister if there is a conflict.
1208 * There is also transport conflict if destroying INET when INET46
1209 * exists, or destroying INET46 when INET exists
1210 */
1211 for (sepp = servtab; sepp; sepp = sepp->se_next) {
1212 if (sepp == sep)
1213 continue;
1214 if (sepp->se_checked == 0 ||
1215 !sepp->se_rpc ||
1216 strcmp(sep->se_proto, sepp->se_proto) != 0 ||
1217 sep->se_rpc_prog != sepp->se_rpc_prog)
1218 continue;
1219 if (sepp->se_family == AF_INET)
1220 netid4 = NULL;
1221 if (sepp->se_family == AF_INET6) {
1222 netid6 = NULL;
1223 if (!sep->se_nomapped)
1224 netid4 = NULL;
1225 }
1226 if (netid4 == NULL && netid6 == NULL)
1227 return;
1228 }
1229 if (debug)
1230 print_service("UNREG", sep);
1231 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) {
1232 if (netid4)
1233 rpcb_unset(sep->se_rpc_prog, i, netid4);
1234 if (netid6)
1235 rpcb_unset(sep->se_rpc_prog, i, netid6);
1236 }
1237 if (sep->se_fd != -1)
1238 (void) close(sep->se_fd);
1239 sep->se_fd = -1;
1240 (void) sigsetmask(omask);
1241}
1242
1243void
1244flag_retry(int signo __unused)
1245{
1246 flag_signal('A');
1247}
1248
1249void
1250retry(void)
1251{
1252 struct servtab *sep;
1253
1254 timingout = 0;
1255 for (sep = servtab; sep; sep = sep->se_next)
1256 if (sep->se_fd == -1 && !ISMUX(sep))
1257 setup(sep);
1258}
1259
1260void
1261setup(struct servtab *sep)
1262{
1263 int on = 1;
1264
1265 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
1266 if (debug)
1267 warn("socket failed on %s/%s",
1268 sep->se_service, sep->se_proto);
1269 syslog(LOG_ERR, "%s/%s: socket: %m",
1270 sep->se_service, sep->se_proto);
1271 return;
1272 }
1273 /* Set all listening sockets to close-on-exec. */
1274 if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) {
1275 syslog(LOG_ERR, "%s/%s: fcntl (F_SETFD, FD_CLOEXEC): %m",
1276 sep->se_service, sep->se_proto);
1277 close(sep->se_fd);
1278 return;
1279 }
1280#define turnon(fd, opt) \
1281setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1282 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
1283 turnon(sep->se_fd, SO_DEBUG) < 0)
1284 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
1285 if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
1286 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
1287#ifdef SO_PRIVSTATE
1288 if (turnon(sep->se_fd, SO_PRIVSTATE) < 0)
1289 syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m");
1290#endif
1291 /* tftpd opens a new connection then needs more infos */
1292 if ((sep->se_family == AF_INET6) &&
1293 (strcmp(sep->se_proto, "udp") == 0) &&
1294 (sep->se_accept == 0) &&
1295 (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
1296 (char *)&on, sizeof (on)) < 0))
1297 syslog(LOG_ERR, "setsockopt (IPV6_RECVPKTINFO): %m");
1298 if (sep->se_family == AF_INET6) {
1299 int flag = sep->se_nomapped ? 1 : 0;
1300 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_V6ONLY,
1301 (char *)&flag, sizeof (flag)) < 0)
1302 syslog(LOG_ERR, "setsockopt (IPV6_V6ONLY): %m");
1303 }
1304#undef turnon
1305 if (sep->se_type == TTCP_TYPE)
1306 if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH,
1307 (char *)&on, sizeof (on)) < 0)
1308 syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m");
1309#ifdef IPV6_FAITH
1310 if (sep->se_type == FAITH_TYPE) {
1311 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, &on,
1312 sizeof(on)) < 0) {
1313 syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
1314 }
1315 }
1316#endif
1317#ifdef IPSEC
1318 ipsecsetup(sep);
1319#endif
1320 if (sep->se_family == AF_UNIX) {
1321 (void) unlink(sep->se_ctrladdr_un.sun_path);
1322 umask(0777); /* Make socket with conservative permissions */
1323 }
1324 if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
1325 sep->se_ctrladdr_size) < 0) {
1326 if (debug)
1327 warn("bind failed on %s/%s",
1328 sep->se_service, sep->se_proto);
1329 syslog(LOG_ERR, "%s/%s: bind: %m",
1330 sep->se_service, sep->se_proto);
1331 (void) close(sep->se_fd);
1332 sep->se_fd = -1;
1333 if (!timingout) {
1334 timingout = 1;
1335 alarm(RETRYTIME);
1336 }
1337 if (sep->se_family == AF_UNIX)
1338 umask(mask);
1339 return;
1340 }
1341 if (sep->se_family == AF_UNIX) {
1342 /* Ick - fch{own,mod} don't work on Unix domain sockets */
1343 if (chown(sep->se_service, sep->se_sockuid, sep->se_sockgid) < 0)
1344 syslog(LOG_ERR, "chown socket: %m");
1345 if (chmod(sep->se_service, sep->se_sockmode) < 0)
1346 syslog(LOG_ERR, "chmod socket: %m");
1347 umask(mask);
1348 }
1349 if (sep->se_rpc) {
1350 u_int i;
1351 socklen_t len = sep->se_ctrladdr_size;
1352 struct netconfig *netid, *netid2 = NULL;
1353 struct sockaddr_in sock;
1354 struct netbuf nbuf, nbuf2;
1355
1356 if (getsockname(sep->se_fd,
1357 (struct sockaddr*)&sep->se_ctrladdr, &len) < 0){
1358 syslog(LOG_ERR, "%s/%s: getsockname: %m",
1359 sep->se_service, sep->se_proto);
1360 (void) close(sep->se_fd);
1361 sep->se_fd = -1;
1362 return;
1363 }
1364 nbuf.buf = &sep->se_ctrladdr;
1365 nbuf.len = sep->se_ctrladdr.sa_len;
1366 if (sep->se_family == AF_INET)
1367 netid = sep->se_socktype==SOCK_DGRAM? udpconf:tcpconf;
1368 else {
1369 netid = sep->se_socktype==SOCK_DGRAM? udp6conf:tcp6conf;
1370 if (!sep->se_nomapped) { /* INET and INET6 */
1371 netid2 = netid==udp6conf? udpconf:tcpconf;
1372 memset(&sock, 0, sizeof sock); /* ADDR_ANY */
1373 nbuf2.buf = &sock;
1374 nbuf2.len = sock.sin_len = sizeof sock;
1375 sock.sin_family = AF_INET;
1376 sock.sin_port = sep->se_ctrladdr6.sin6_port;
1377 }
1378 }
1379 if (debug)
1380 print_service("REG ", sep);
1381 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) {
1382 rpcb_unset(sep->se_rpc_prog, i, netid);
1383 rpcb_set(sep->se_rpc_prog, i, netid, &nbuf);
1384 if (netid2) {
1385 rpcb_unset(sep->se_rpc_prog, i, netid2);
1386 rpcb_set(sep->se_rpc_prog, i, netid2, &nbuf2);
1387 }
1388 }
1389 }
1390 if (sep->se_socktype == SOCK_STREAM)
1391 listen(sep->se_fd, 64);
1392 enable(sep);
1393 if (debug) {
1394 warnx("registered %s on %d",
1395 sep->se_server, sep->se_fd);
1396 }
1397}
1398
1399#ifdef IPSEC
1400void
1401ipsecsetup(sep)
1402 struct servtab *sep;
1403{
1404 char *buf;
1405 char *policy_in = NULL;
1406 char *policy_out = NULL;
1407 int level;
1408 int opt;
1409
1410 switch (sep->se_family) {
1411 case AF_INET:
1412 level = IPPROTO_IP;
1413 opt = IP_IPSEC_POLICY;
1414 break;
1415#ifdef INET6
1416 case AF_INET6:
1417 level = IPPROTO_IPV6;
1418 opt = IPV6_IPSEC_POLICY;
1419 break;
1420#endif
1421 default:
1422 return;
1423 }
1424
1425 if (!sep->se_policy || sep->se_policy[0] == '\0') {
1426 static char def_in[] = "in entrust", def_out[] = "out entrust";
1427 policy_in = def_in;
1428 policy_out = def_out;
1429 } else {
1430 if (!strncmp("in", sep->se_policy, 2))
1431 policy_in = sep->se_policy;
1432 else if (!strncmp("out", sep->se_policy, 3))
1433 policy_out = sep->se_policy;
1434 else {
1435 syslog(LOG_ERR, "invalid security policy \"%s\"",
1436 sep->se_policy);
1437 return;
1438 }
1439 }
1440
1441 if (policy_in != NULL) {
1442 buf = ipsec_set_policy(policy_in, strlen(policy_in));
1443 if (buf != NULL) {
1444 if (setsockopt(sep->se_fd, level, opt,
1445 buf, ipsec_get_policylen(buf)) < 0 &&
1446 debug != 0)
1447 warnx("%s/%s: ipsec initialization failed; %s",
1448 sep->se_service, sep->se_proto,
1449 policy_in);
1450 free(buf);
1451 } else
1452 syslog(LOG_ERR, "invalid security policy \"%s\"",
1453 policy_in);
1454 }
1455 if (policy_out != NULL) {
1456 buf = ipsec_set_policy(policy_out, strlen(policy_out));
1457 if (buf != NULL) {
1458 if (setsockopt(sep->se_fd, level, opt,
1459 buf, ipsec_get_policylen(buf)) < 0 &&
1460 debug != 0)
1461 warnx("%s/%s: ipsec initialization failed; %s",
1462 sep->se_service, sep->se_proto,
1463 policy_out);
1464 free(buf);
1465 } else
1466 syslog(LOG_ERR, "invalid security policy \"%s\"",
1467 policy_out);
1468 }
1469}
1470#endif
1471
1472/*
1473 * Finish with a service and its socket.
1474 */
1475void
1476close_sep(struct servtab *sep)
1477{
1478 if (sep->se_fd >= 0) {
1479 if (FD_ISSET(sep->se_fd, &allsock))
1480 disable(sep);
1481 (void) close(sep->se_fd);
1482 sep->se_fd = -1;
1483 }
1484 sep->se_count = 0;
1485 sep->se_numchild = 0; /* forget about any existing children */
1486}
1487
1488int
1489matchservent(const char *name1, const char *name2, const char *proto)
1490{
1491 char **alias, *p;
1492 struct servent *se;
1493
1494 if (strcmp(proto, "unix") == 0) {
1495 if ((p = strrchr(name1, '/')) != NULL)
1496 name1 = p + 1;
1497 if ((p = strrchr(name2, '/')) != NULL)
1498 name2 = p + 1;
1499 }
1500 if (strcmp(name1, name2) == 0)
1501 return(1);
1502 if ((se = getservbyname(name1, proto)) != NULL) {
1503 if (strcmp(name2, se->s_name) == 0)
1504 return(1);
1505 for (alias = se->s_aliases; *alias; alias++)
1506 if (strcmp(name2, *alias) == 0)
1507 return(1);
1508 }
1509 return(0);
1510}
1511
1512struct servtab *
1513enter(struct servtab *cp)
1514{
1515 struct servtab *sep;
1516 long omask;
1517
1518 sep = (struct servtab *)malloc(sizeof (*sep));
1519 if (sep == (struct servtab *)0) {
1520 syslog(LOG_ERR, "malloc: %m");
1521 exit(EX_OSERR);
1522 }
1523 *sep = *cp;
1524 sep->se_fd = -1;
1525 omask = sigblock(SIGBLOCK);
1526 sep->se_next = servtab;
1527 servtab = sep;
1528 sigsetmask(omask);
1529 return (sep);
1530}
1531
1532void
1533enable(struct servtab *sep)
1534{
1535 if (debug)
1536 warnx(
1537 "enabling %s, fd %d", sep->se_service, sep->se_fd);
1538#ifdef SANITY_CHECK
1539 if (sep->se_fd < 0) {
1540 syslog(LOG_ERR,
1541 "%s: %s: bad fd", __func__, sep->se_service);
1542 exit(EX_SOFTWARE);
1543 }
1544 if (ISMUX(sep)) {
1545 syslog(LOG_ERR,
1546 "%s: %s: is mux", __func__, sep->se_service);
1547 exit(EX_SOFTWARE);
1548 }
1549 if (FD_ISSET(sep->se_fd, &allsock)) {
1550 syslog(LOG_ERR,
1551 "%s: %s: not off", __func__, sep->se_service);
1552 exit(EX_SOFTWARE);
1553 }
1554 nsock++;
1555#endif
1556 FD_SET(sep->se_fd, &allsock);
1557 if (sep->se_fd > maxsock)
1558 maxsock = sep->se_fd;
1559}
1560
1561void
1562disable(struct servtab *sep)
1563{
1564 if (debug)
1565 warnx(
1566 "disabling %s, fd %d", sep->se_service, sep->se_fd);
1567#ifdef SANITY_CHECK
1568 if (sep->se_fd < 0) {
1569 syslog(LOG_ERR,
1570 "%s: %s: bad fd", __func__, sep->se_service);
1571 exit(EX_SOFTWARE);
1572 }
1573 if (ISMUX(sep)) {
1574 syslog(LOG_ERR,
1575 "%s: %s: is mux", __func__, sep->se_service);
1576 exit(EX_SOFTWARE);
1577 }
1578 if (!FD_ISSET(sep->se_fd, &allsock)) {
1579 syslog(LOG_ERR,
1580 "%s: %s: not on", __func__, sep->se_service);
1581 exit(EX_SOFTWARE);
1582 }
1583 if (nsock == 0) {
1584 syslog(LOG_ERR, "%s: nsock=0", __func__);
1585 exit(EX_SOFTWARE);
1586 }
1587 nsock--;
1588#endif
1589 FD_CLR(sep->se_fd, &allsock);
1590 if (sep->se_fd == maxsock)
1591 maxsock--;
1592}
1593
1594FILE *fconfig = NULL;
1595struct servtab serv;
1596char line[LINE_MAX];
1597
1598int
1599setconfig(void)
1600{
1601
1602 if (fconfig != NULL) {
1603 fseek(fconfig, 0L, SEEK_SET);
1604 return (1);
1605 }
1606 fconfig = fopen(CONFIG, "r");
1607 return (fconfig != NULL);
1608}
1609
1610void
1611endconfig(void)
1612{
1613 if (fconfig) {
1614 (void) fclose(fconfig);
1615 fconfig = NULL;
1616 }
1617}
1618
1619struct servtab *
1620getconfigent(void)
1621{
1622 struct servtab *sep = &serv;
1623 int argc;
1624 char *cp, *arg, *s;
1625 char *versp;
1626 static char TCPMUX_TOKEN[] = "tcpmux/";
1627#define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
1628#ifdef IPSEC
1629 char *policy;
1630#endif
1631 int v4bind;
1632#ifdef INET6
1633 int v6bind;
1634#endif
1635 int i;
1636
1637#ifdef IPSEC
1638 policy = NULL;
1639#endif
1640more:
1641 v4bind = 0;
1642#ifdef INET6
1643 v6bind = 0;
1644#endif
1645 while ((cp = nextline(fconfig)) != NULL) {
1646#ifdef IPSEC
1647 /* lines starting with #@ is not a comment, but the policy */
1648 if (cp[0] == '#' && cp[1] == '@') {
1649 char *p;
1650 for (p = cp + 2; p && *p && isspace(*p); p++)
1651 ;
1652 if (*p == '\0') {
1653 if (policy)
1654 free(policy);
1655 policy = NULL;
1656 } else if (ipsec_get_policylen(p) >= 0) {
1657 if (policy)
1658 free(policy);
1659 policy = newstr(p);
1660 } else {
1661 syslog(LOG_ERR,
1662 "%s: invalid ipsec policy \"%s\"",
1663 CONFIG, p);
1664 exit(EX_CONFIG);
1665 }
1666 }
1667#endif
1668 if (*cp == '#' || *cp == '\0')
1669 continue;
1670 break;
1671 }
1672 if (cp == NULL)
1673 return ((struct servtab *)0);
1674 /*
1675 * clear the static buffer, since some fields (se_ctrladdr,
1676 * for example) don't get initialized here.
1677 */
1678 memset(sep, 0, sizeof *sep);
1679 arg = skip(&cp);
1680 if (cp == NULL) {
1681 /* got an empty line containing just blanks/tabs. */
1682 goto more;
1683 }
1684 if (arg[0] == ':') { /* :user:group:perm: */
1685 char *user, *group, *perm;
1686 struct passwd *pw;
1687 struct group *gr;
1688 user = arg+1;
1689 if ((group = strchr(user, ':')) == NULL) {
1690 syslog(LOG_ERR, "no group after user '%s'", user);
1691 goto more;
1692 }
1693 *group++ = '\0';
1694 if ((perm = strchr(group, ':')) == NULL) {
1695 syslog(LOG_ERR, "no mode after group '%s'", group);
1696 goto more;
1697 }
1698 *perm++ = '\0';
1699 if ((pw = getpwnam(user)) == NULL) {
1700 syslog(LOG_ERR, "no such user '%s'", user);
1701 goto more;
1702 }
1703 sep->se_sockuid = pw->pw_uid;
1704 if ((gr = getgrnam(group)) == NULL) {
1705 syslog(LOG_ERR, "no such user '%s'", group);
1706 goto more;
1707 }
1708 sep->se_sockgid = gr->gr_gid;
1709 sep->se_sockmode = strtol(perm, &arg, 8);
1710 if (*arg != ':') {
1711 syslog(LOG_ERR, "bad mode '%s'", perm);
1712 goto more;
1713 }
1714 *arg++ = '\0';
1715 } else {
1716 sep->se_sockuid = euid;
1717 sep->se_sockgid = egid;
1718 sep->se_sockmode = 0200;
1719 }
1720 if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1721 char *c = arg + MUX_LEN;
1722 if (*c == '+') {
1723 sep->se_type = MUXPLUS_TYPE;
1724 c++;
1725 } else
1726 sep->se_type = MUX_TYPE;
1727 sep->se_service = newstr(c);
1728 } else {
1729 sep->se_service = newstr(arg);
1730 sep->se_type = NORM_TYPE;
1731 }
1732 arg = sskip(&cp);
1733 if (strcmp(arg, "stream") == 0)
1734 sep->se_socktype = SOCK_STREAM;
1735 else if (strcmp(arg, "dgram") == 0)
1736 sep->se_socktype = SOCK_DGRAM;
1737 else if (strcmp(arg, "rdm") == 0)
1738 sep->se_socktype = SOCK_RDM;
1739 else if (strcmp(arg, "seqpacket") == 0)
1740 sep->se_socktype = SOCK_SEQPACKET;
1741 else if (strcmp(arg, "raw") == 0)
1742 sep->se_socktype = SOCK_RAW;
1743 else
1744 sep->se_socktype = -1;
1745
1746 arg = sskip(&cp);
1747 if (strncmp(arg, "tcp", 3) == 0) {
1748 sep->se_proto = newstr(strsep(&arg, "/"));
1749 if (arg != NULL) {
1750 if (strcmp(arg, "ttcp") == 0)
1751 sep->se_type = TTCP_TYPE;
1752 else if (strcmp(arg, "faith") == 0)
1753 sep->se_type = FAITH_TYPE;
1754 }
1755 } else {
1756 if (sep->se_type == NORM_TYPE &&
1757 strncmp(arg, "faith/", 6) == 0) {
1758 arg += 6;
1759 sep->se_type = FAITH_TYPE;
1760 }
1761 sep->se_proto = newstr(arg);
1762 }
1763 if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1764 memmove(sep->se_proto, sep->se_proto + 4,
1765 strlen(sep->se_proto) + 1 - 4);
1766 sep->se_rpc = 1;
1767 sep->se_rpc_prog = sep->se_rpc_lowvers =
1768 sep->se_rpc_lowvers = 0;
1769 memcpy(&sep->se_ctrladdr4, bind_sa4,
1770 sizeof(sep->se_ctrladdr4));
1771 if ((versp = rindex(sep->se_service, '/'))) {
1772 *versp++ = '\0';
1773 switch (sscanf(versp, "%u-%u",
1774 &sep->se_rpc_lowvers,
1775 &sep->se_rpc_highvers)) {
1776 case 2:
1777 break;
1778 case 1:
1779 sep->se_rpc_highvers =
1780 sep->se_rpc_lowvers;
1781 break;
1782 default:
1783 syslog(LOG_ERR,
1784 "bad RPC version specifier; %s",
1785 sep->se_service);
1786 freeconfig(sep);
1787 goto more;
1788 }
1789 }
1790 else {
1791 sep->se_rpc_lowvers =
1792 sep->se_rpc_highvers = 1;
1793 }
1794 }
1795 sep->se_nomapped = 0;
1796 if (strcmp(sep->se_proto, "unix") == 0) {
1797 sep->se_family = AF_UNIX;
1798 } else {
1799 while (isdigit(sep->se_proto[strlen(sep->se_proto) - 1])) {
1800#ifdef INET6
1801 if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') {
1802 sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
1803 v6bind = 1;
1804 continue;
1805 }
1806#endif
1807 if (sep->se_proto[strlen(sep->se_proto) - 1] == '4') {
1808 sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
1809 v4bind = 1;
1810 continue;
1811 }
1812 /* illegal version num */
1813 syslog(LOG_ERR, "bad IP version for %s", sep->se_proto);
1814 freeconfig(sep);
1815 goto more;
1816 }
1817#ifdef INET6
1818 if (v6bind && !v6bind_ok) {
1819 syslog(LOG_INFO, "IPv6 bind is ignored for %s",
1820 sep->se_service);
1821 if (v4bind && v4bind_ok)
1822 v6bind = 0;
1823 else {
1824 freeconfig(sep);
1825 goto more;
1826 }
1827 }
1828 if (v6bind) {
1829 sep->se_family = AF_INET6;
1830 if (!v4bind || !v4bind_ok)
1831 sep->se_nomapped = 1;
1832 } else
1833#endif
1834 { /* default to v4 bind if not v6 bind */
1835 if (!v4bind_ok) {
1836 syslog(LOG_NOTICE, "IPv4 bind is ignored for %s",
1837 sep->se_service);
1838 freeconfig(sep);
1839 goto more;
1840 }
1841 sep->se_family = AF_INET;
1842 }
1843 }
1844 /* init ctladdr */
1845 switch(sep->se_family) {
1846 case AF_INET:
1847 memcpy(&sep->se_ctrladdr4, bind_sa4,
1848 sizeof(sep->se_ctrladdr4));
1849 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr4);
1850 break;
1851#ifdef INET6
1852 case AF_INET6:
1853 memcpy(&sep->se_ctrladdr6, bind_sa6,
1854 sizeof(sep->se_ctrladdr6));
1855 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr6);
1856 break;
1857#endif
1858 case AF_UNIX:
1859 if (strlen(sep->se_service) >= sizeof(sep->se_ctrladdr_un.sun_path)) {
1860 syslog(LOG_ERR,
1861 "domain socket pathname too long for service %s",
1862 sep->se_service);
1863 goto more;
1864 }
1865 memset(&sep->se_ctrladdr, 0, sizeof(sep->se_ctrladdr));
1866 sep->se_ctrladdr_un.sun_family = sep->se_family;
1867 sep->se_ctrladdr_un.sun_len = strlen(sep->se_service);
1868 strcpy(sep->se_ctrladdr_un.sun_path, sep->se_service);
1869 sep->se_ctrladdr_size = SUN_LEN(&sep->se_ctrladdr_un);
1870 }
1871 arg = sskip(&cp);
1872 if (!strncmp(arg, "wait", 4))
1873 sep->se_accept = 0;
1874 else if (!strncmp(arg, "nowait", 6))
1875 sep->se_accept = 1;
1876 else {
1877 syslog(LOG_ERR,
1878 "%s: bad wait/nowait for service %s",
1879 CONFIG, sep->se_service);
1880 goto more;
1881 }
1882 sep->se_maxchild = -1;
1883 sep->se_maxcpm = -1;
1884 sep->se_maxperip = -1;
1885 if ((s = strchr(arg, '/')) != NULL) {
1886 char *eptr;
1887 u_long val;
1888
1889 val = strtoul(s + 1, &eptr, 10);
1890 if (eptr == s + 1 || val > MAX_MAXCHLD) {
1891 syslog(LOG_ERR,
1892 "%s: bad max-child for service %s",
1893 CONFIG, sep->se_service);
1894 goto more;
1895 }
1896 if (debug)
1897 if (!sep->se_accept && val != 1)
1898 warnx("maxchild=%lu for wait service %s"
1899 " not recommended", val, sep->se_service);
1900 sep->se_maxchild = val;
1901 if (*eptr == '/')
1902 sep->se_maxcpm = strtol(eptr + 1, &eptr, 10);
1903 if (*eptr == '/')
1904 sep->se_maxperip = strtol(eptr + 1, &eptr, 10);
1905 /*
1906 * explicitly do not check for \0 for future expansion /
1907 * backwards compatibility
1908 */
1909 }
1910 if (ISMUX(sep)) {
1911 /*
1912 * Silently enforce "nowait" mode for TCPMUX services
1913 * since they don't have an assigned port to listen on.
1914 */
1915 sep->se_accept = 1;
1916 if (strcmp(sep->se_proto, "tcp")) {
1917 syslog(LOG_ERR,
1918 "%s: bad protocol for tcpmux service %s",
1919 CONFIG, sep->se_service);
1920 goto more;
1921 }
1922 if (sep->se_socktype != SOCK_STREAM) {
1923 syslog(LOG_ERR,
1924 "%s: bad socket type for tcpmux service %s",
1925 CONFIG, sep->se_service);
1926 goto more;
1927 }
1928 }
1929 sep->se_user = newstr(sskip(&cp));
1930#ifdef LOGIN_CAP
1931 if ((s = strrchr(sep->se_user, '/')) != NULL) {
1932 *s = '\0';
1933 sep->se_class = newstr(s + 1);
1934 } else
1935 sep->se_class = newstr(RESOURCE_RC);
1936#endif
1937 if ((s = strrchr(sep->se_user, ':')) != NULL) {
1938 *s = '\0';
1939 sep->se_group = newstr(s + 1);
1940 } else
1941 sep->se_group = NULL;
1942 sep->se_server = newstr(sskip(&cp));
1943 if ((sep->se_server_name = rindex(sep->se_server, '/')))
1944 sep->se_server_name++;
1945 if (strcmp(sep->se_server, "internal") == 0) {
1946 struct biltin *bi;
1947
1948 for (bi = biltins; bi->bi_service; bi++)
1949 if (bi->bi_socktype == sep->se_socktype &&
1950 matchservent(bi->bi_service, sep->se_service,
1951 sep->se_proto))
1952 break;
1953 if (bi->bi_service == 0) {
1954 syslog(LOG_ERR, "internal service %s unknown",
1955 sep->se_service);
1956 goto more;
1957 }
1958 sep->se_accept = 1; /* force accept mode for built-ins */
1959 sep->se_bi = bi;
1960 } else
1961 sep->se_bi = NULL;
1962 if (sep->se_maxperip < 0)
1963 sep->se_maxperip = maxperip;
1964 if (sep->se_maxcpm < 0)
1965 sep->se_maxcpm = maxcpm;
1966 if (sep->se_maxchild < 0) { /* apply default max-children */
1967 if (sep->se_bi && sep->se_bi->bi_maxchild >= 0)
1968 sep->se_maxchild = sep->se_bi->bi_maxchild;
1969 else if (sep->se_accept)
1970 sep->se_maxchild = maxchild > 0 ? maxchild : 0;
1971 else
1972 sep->se_maxchild = 1;
1973 }
1974 if (sep->se_maxchild > 0) {
1975 sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids));
1976 if (sep->se_pids == NULL) {
1977 syslog(LOG_ERR, "malloc: %m");
1978 exit(EX_OSERR);
1979 }
1980 }
1981 argc = 0;
1982 for (arg = skip(&cp); cp; arg = skip(&cp))
1983 if (argc < MAXARGV) {
1984 sep->se_argv[argc++] = newstr(arg);
1985 } else {
1986 syslog(LOG_ERR,
1987 "%s: too many arguments for service %s",
1988 CONFIG, sep->se_service);
1989 goto more;
1990 }
1991 while (argc <= MAXARGV)
1992 sep->se_argv[argc++] = NULL;
1993 for (i = 0; i < PERIPSIZE; ++i)
1994 LIST_INIT(&sep->se_conn[i]);
1995#ifdef IPSEC
1996 sep->se_policy = policy ? newstr(policy) : NULL;
1997#endif
1998 return (sep);
1999}
2000
2001void
2002freeconfig(struct servtab *cp)
2003{
2004 int i;
2005
2006 if (cp->se_service)
2007 free(cp->se_service);
2008 if (cp->se_proto)
2009 free(cp->se_proto);
2010 if (cp->se_user)
2011 free(cp->se_user);
2012 if (cp->se_group)
2013 free(cp->se_group);
2014#ifdef LOGIN_CAP
2015 if (cp->se_class)
2016 free(cp->se_class);
2017#endif
2018 if (cp->se_server)
2019 free(cp->se_server);
2020 if (cp->se_pids)
2021 free(cp->se_pids);
2022 for (i = 0; i < MAXARGV; i++)
2023 if (cp->se_argv[i])
2024 free(cp->se_argv[i]);
2025 free_connlist(cp);
2026#ifdef IPSEC
2027 if (cp->se_policy)
2028 free(cp->se_policy);
2029#endif
2030}
2031
2032
2033/*
2034 * Safe skip - if skip returns null, log a syntax error in the
2035 * configuration file and exit.
2036 */
2037char *
2038sskip(char **cpp)
2039{
2040 char *cp;
2041
2042 cp = skip(cpp);
2043 if (cp == NULL) {
2044 syslog(LOG_ERR, "%s: syntax error", CONFIG);
2045 exit(EX_DATAERR);
2046 }
2047 return (cp);
2048}
2049
2050char *
2051skip(char **cpp)
2052{
2053 char *cp = *cpp;
2054 char *start;
2055 char quote = '\0';
2056
2057again:
2058 while (*cp == ' ' || *cp == '\t')
2059 cp++;
2060 if (*cp == '\0') {
2061 int c;
2062
2063 c = getc(fconfig);
2064 (void) ungetc(c, fconfig);
2065 if (c == ' ' || c == '\t')
2066 if ((cp = nextline(fconfig)))
2067 goto again;
2068 *cpp = (char *)0;
2069 return ((char *)0);
2070 }
2071 if (*cp == '"' || *cp == '\'')
2072 quote = *cp++;
2073 start = cp;
2074 if (quote)
2075 while (*cp && *cp != quote)
2076 cp++;
2077 else
2078 while (*cp && *cp != ' ' && *cp != '\t')
2079 cp++;
2080 if (*cp != '\0')
2081 *cp++ = '\0';
2082 *cpp = cp;
2083 return (start);
2084}
2085
2086char *
2087nextline(FILE *fd)
2088{
2089 char *cp;
2090
2091 if (fgets(line, sizeof (line), fd) == NULL)
2092 return ((char *)0);
2093 cp = strchr(line, '\n');
2094 if (cp)
2095 *cp = '\0';
2096 return (line);
2097}
2098
2099char *
2100newstr(const char *cp)
2101{
2102 char *cr;
2103
2104 if ((cr = strdup(cp != NULL ? cp : "")))
2105 return (cr);
2106 syslog(LOG_ERR, "strdup: %m");
2107 exit(EX_OSERR);
2108}
2109
2110void
2111inetd_setproctitle(const char *a, int s)
2112{
2113 socklen_t size;
2114 struct sockaddr_storage ss;
2115 char buf[80], pbuf[INET6_ADDRSTRLEN];
2116
2117 size = sizeof(ss);
2118 if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
2119 getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf),
668 }
669 syslog(LOG_INFO,"%s from %s", sep->se_service, pname);
670 }
671 (void) sigblock(SIGBLOCK);
672 pid = 0;
673 /*
674 * Fork for all external services, builtins which need to
675 * fork and anything we're wrapping (as wrapping might
676 * block or use hosts_options(5) twist).
677 */
678 if (dofork) {
679 if (sep->se_count++ == 0)
680 (void)gettimeofday(&sep->se_time, (struct timezone *)NULL);
681 else if (toomany > 0 && sep->se_count >= toomany) {
682 struct timeval now;
683
684 (void)gettimeofday(&now, (struct timezone *)NULL);
685 if (now.tv_sec - sep->se_time.tv_sec >
686 CNT_INTVL) {
687 sep->se_time = now;
688 sep->se_count = 1;
689 } else {
690 syslog(LOG_ERR,
691 "%s/%s server failing (looping), service terminated",
692 sep->se_service, sep->se_proto);
693 if (sep->se_accept &&
694 sep->se_socktype == SOCK_STREAM)
695 close(ctrl);
696 close_sep(sep);
697 free_conn(conn);
698 sigsetmask(0L);
699 if (!timingout) {
700 timingout = 1;
701 alarm(RETRYTIME);
702 }
703 continue;
704 }
705 }
706 pid = fork();
707 }
708 if (pid < 0) {
709 syslog(LOG_ERR, "fork: %m");
710 if (sep->se_accept &&
711 sep->se_socktype == SOCK_STREAM)
712 close(ctrl);
713 free_conn(conn);
714 sigsetmask(0L);
715 sleep(1);
716 continue;
717 }
718 if (pid) {
719 addchild_conn(conn, pid);
720 addchild(sep, pid);
721 }
722 sigsetmask(0L);
723 if (pid == 0) {
724 if (dofork) {
725 sigaction(SIGALRM, &saalrm, (struct sigaction *)0);
726 sigaction(SIGCHLD, &sachld, (struct sigaction *)0);
727 sigaction(SIGHUP, &sahup, (struct sigaction *)0);
728 /* SIGPIPE reset before exec */
729 }
730 /*
731 * Call tcpmux to find the real service to exec.
732 */
733 if (sep->se_bi &&
734 sep->se_bi->bi_fn == (bi_fn_t *) tcpmux) {
735 sep = tcpmux(ctrl);
736 if (sep == NULL) {
737 close(ctrl);
738 _exit(0);
739 }
740 }
741 if (ISWRAP(sep)) {
742 inetd_setproctitle("wrapping", ctrl);
743 service = sep->se_server_name ?
744 sep->se_server_name : sep->se_service;
745 request_init(&req, RQ_DAEMON, service, RQ_FILE, ctrl, 0);
746 fromhost(&req);
747 deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
748 allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
749 denied = !hosts_access(&req);
750 if (denied) {
751 syslog(deny_severity,
752 "refused connection from %.500s, service %s (%s%s)",
753 eval_client(&req), service, sep->se_proto,
754 (whichaf(&req) == AF_INET6) ? "6" : "");
755 if (sep->se_socktype != SOCK_STREAM)
756 recv(ctrl, buf, sizeof (buf), 0);
757 if (dofork) {
758 sleep(1);
759 _exit(0);
760 }
761 }
762 if (dolog) {
763 syslog(allow_severity,
764 "connection from %.500s, service %s (%s%s)",
765 eval_client(&req), service, sep->se_proto,
766 (whichaf(&req) == AF_INET6) ? "6" : "");
767 }
768 }
769 if (sep->se_bi) {
770 (*sep->se_bi->bi_fn)(ctrl, sep);
771 } else {
772 if (debug)
773 warnx("%d execl %s",
774 getpid(), sep->se_server);
775 /* Clear close-on-exec. */
776 if (fcntl(ctrl, F_SETFD, 0) < 0) {
777 syslog(LOG_ERR,
778 "%s/%s: fcntl (F_SETFD, 0): %m",
779 sep->se_service, sep->se_proto);
780 _exit(EX_OSERR);
781 }
782 if (ctrl != 0) {
783 dup2(ctrl, 0);
784 close(ctrl);
785 }
786 dup2(0, 1);
787 dup2(0, 2);
788 if ((pwd = getpwnam(sep->se_user)) == NULL) {
789 syslog(LOG_ERR,
790 "%s/%s: %s: no such user",
791 sep->se_service, sep->se_proto,
792 sep->se_user);
793 if (sep->se_socktype != SOCK_STREAM)
794 recv(0, buf, sizeof (buf), 0);
795 _exit(EX_NOUSER);
796 }
797 grp = NULL;
798 if ( sep->se_group != NULL
799 && (grp = getgrnam(sep->se_group)) == NULL
800 ) {
801 syslog(LOG_ERR,
802 "%s/%s: %s: no such group",
803 sep->se_service, sep->se_proto,
804 sep->se_group);
805 if (sep->se_socktype != SOCK_STREAM)
806 recv(0, buf, sizeof (buf), 0);
807 _exit(EX_NOUSER);
808 }
809 if (grp != NULL)
810 pwd->pw_gid = grp->gr_gid;
811#ifdef LOGIN_CAP
812 if ((lc = login_getclass(sep->se_class)) == NULL) {
813 /* error syslogged by getclass */
814 syslog(LOG_ERR,
815 "%s/%s: %s: login class error",
816 sep->se_service, sep->se_proto,
817 sep->se_class);
818 if (sep->se_socktype != SOCK_STREAM)
819 recv(0, buf, sizeof (buf), 0);
820 _exit(EX_NOUSER);
821 }
822#endif
823 if (setsid() < 0) {
824 syslog(LOG_ERR,
825 "%s: can't setsid(): %m",
826 sep->se_service);
827 /* _exit(EX_OSERR); not fatal yet */
828 }
829#ifdef LOGIN_CAP
830 if (setusercontext(lc, pwd, pwd->pw_uid,
831 LOGIN_SETALL & ~LOGIN_SETMAC)
832 != 0) {
833 syslog(LOG_ERR,
834 "%s: can't setusercontext(..%s..): %m",
835 sep->se_service, sep->se_user);
836 _exit(EX_OSERR);
837 }
838 login_close(lc);
839#else
840 if (pwd->pw_uid) {
841 if (setlogin(sep->se_user) < 0) {
842 syslog(LOG_ERR,
843 "%s: can't setlogin(%s): %m",
844 sep->se_service, sep->se_user);
845 /* _exit(EX_OSERR); not yet */
846 }
847 if (setgid(pwd->pw_gid) < 0) {
848 syslog(LOG_ERR,
849 "%s: can't set gid %d: %m",
850 sep->se_service, pwd->pw_gid);
851 _exit(EX_OSERR);
852 }
853 (void) initgroups(pwd->pw_name,
854 pwd->pw_gid);
855 if (setuid(pwd->pw_uid) < 0) {
856 syslog(LOG_ERR,
857 "%s: can't set uid %d: %m",
858 sep->se_service, pwd->pw_uid);
859 _exit(EX_OSERR);
860 }
861 }
862#endif
863 sigaction(SIGPIPE, &sapipe,
864 (struct sigaction *)0);
865 execv(sep->se_server, sep->se_argv);
866 syslog(LOG_ERR,
867 "cannot execute %s: %m", sep->se_server);
868 if (sep->se_socktype != SOCK_STREAM)
869 recv(0, buf, sizeof (buf), 0);
870 }
871 if (dofork)
872 _exit(0);
873 }
874 if (sep->se_accept && sep->se_socktype == SOCK_STREAM)
875 close(ctrl);
876 }
877 }
878}
879
880/*
881 * Add a signal flag to the signal flag queue for later handling
882 */
883
884void
885flag_signal(int c)
886{
887 char ch = c;
888
889 if (write(signalpipe[1], &ch, 1) != 1) {
890 syslog(LOG_ERR, "write: %m");
891 _exit(EX_OSERR);
892 }
893}
894
895/*
896 * Record a new child pid for this service. If we've reached the
897 * limit on children, then stop accepting incoming requests.
898 */
899
900void
901addchild(struct servtab *sep, pid_t pid)
902{
903 if (sep->se_maxchild <= 0)
904 return;
905#ifdef SANITY_CHECK
906 if (sep->se_numchild >= sep->se_maxchild) {
907 syslog(LOG_ERR, "%s: %d >= %d",
908 __func__, sep->se_numchild, sep->se_maxchild);
909 exit(EX_SOFTWARE);
910 }
911#endif
912 sep->se_pids[sep->se_numchild++] = pid;
913 if (sep->se_numchild == sep->se_maxchild)
914 disable(sep);
915}
916
917/*
918 * Some child process has exited. See if it's on somebody's list.
919 */
920
921void
922flag_reapchild(int signo __unused)
923{
924 flag_signal('C');
925}
926
927void
928reapchild(void)
929{
930 int k, status;
931 pid_t pid;
932 struct servtab *sep;
933
934 for (;;) {
935 pid = wait3(&status, WNOHANG, (struct rusage *)0);
936 if (pid <= 0)
937 break;
938 if (debug)
939 warnx("%d reaped, %s %u", pid,
940 WIFEXITED(status) ? "status" : "signal",
941 WIFEXITED(status) ? WEXITSTATUS(status)
942 : WTERMSIG(status));
943 for (sep = servtab; sep; sep = sep->se_next) {
944 for (k = 0; k < sep->se_numchild; k++)
945 if (sep->se_pids[k] == pid)
946 break;
947 if (k == sep->se_numchild)
948 continue;
949 if (sep->se_numchild == sep->se_maxchild)
950 enable(sep);
951 sep->se_pids[k] = sep->se_pids[--sep->se_numchild];
952 if (WIFSIGNALED(status) || WEXITSTATUS(status))
953 syslog(LOG_WARNING,
954 "%s[%d]: exited, %s %u",
955 sep->se_server, pid,
956 WIFEXITED(status) ? "status" : "signal",
957 WIFEXITED(status) ? WEXITSTATUS(status)
958 : WTERMSIG(status));
959 break;
960 }
961 reapchild_conn(pid);
962 }
963}
964
965void
966flag_config(int signo __unused)
967{
968 flag_signal('H');
969}
970
971void
972config(void)
973{
974 struct servtab *sep, *new, **sepp;
975 long omask;
976 int new_nomapped;
977#ifdef LOGIN_CAP
978 login_cap_t *lc = NULL;
979#endif
980
981 if (!setconfig()) {
982 syslog(LOG_ERR, "%s: %m", CONFIG);
983 return;
984 }
985 for (sep = servtab; sep; sep = sep->se_next)
986 sep->se_checked = 0;
987 while ((new = getconfigent())) {
988 if (getpwnam(new->se_user) == NULL) {
989 syslog(LOG_ERR,
990 "%s/%s: no such user '%s', service ignored",
991 new->se_service, new->se_proto, new->se_user);
992 continue;
993 }
994 if (new->se_group && getgrnam(new->se_group) == NULL) {
995 syslog(LOG_ERR,
996 "%s/%s: no such group '%s', service ignored",
997 new->se_service, new->se_proto, new->se_group);
998 continue;
999 }
1000#ifdef LOGIN_CAP
1001 if ((lc = login_getclass(new->se_class)) == NULL) {
1002 /* error syslogged by getclass */
1003 syslog(LOG_ERR,
1004 "%s/%s: %s: login class error, service ignored",
1005 new->se_service, new->se_proto, new->se_class);
1006 continue;
1007 }
1008 login_close(lc);
1009#endif
1010 new_nomapped = new->se_nomapped;
1011 for (sep = servtab; sep; sep = sep->se_next)
1012 if (strcmp(sep->se_service, new->se_service) == 0 &&
1013 strcmp(sep->se_proto, new->se_proto) == 0 &&
1014 sep->se_rpc == new->se_rpc &&
1015 sep->se_socktype == new->se_socktype &&
1016 sep->se_family == new->se_family)
1017 break;
1018 if (sep != 0) {
1019 int i;
1020
1021#define SWAP(t,a, b) { t c = a; a = b; b = c; }
1022 omask = sigblock(SIGBLOCK);
1023 if (sep->se_nomapped != new->se_nomapped) {
1024 /* for rpc keep old nommaped till unregister */
1025 if (!sep->se_rpc)
1026 sep->se_nomapped = new->se_nomapped;
1027 sep->se_reset = 1;
1028 }
1029 /* copy over outstanding child pids */
1030 if (sep->se_maxchild > 0 && new->se_maxchild > 0) {
1031 new->se_numchild = sep->se_numchild;
1032 if (new->se_numchild > new->se_maxchild)
1033 new->se_numchild = new->se_maxchild;
1034 memcpy(new->se_pids, sep->se_pids,
1035 new->se_numchild * sizeof(*new->se_pids));
1036 }
1037 SWAP(pid_t *, sep->se_pids, new->se_pids);
1038 sep->se_maxchild = new->se_maxchild;
1039 sep->se_numchild = new->se_numchild;
1040 sep->se_maxcpm = new->se_maxcpm;
1041 resize_conn(sep, new->se_maxperip);
1042 sep->se_maxperip = new->se_maxperip;
1043 sep->se_bi = new->se_bi;
1044 /* might need to turn on or off service now */
1045 if (sep->se_fd >= 0) {
1046 if (sep->se_maxchild > 0
1047 && sep->se_numchild == sep->se_maxchild) {
1048 if (FD_ISSET(sep->se_fd, &allsock))
1049 disable(sep);
1050 } else {
1051 if (!FD_ISSET(sep->se_fd, &allsock))
1052 enable(sep);
1053 }
1054 }
1055 sep->se_accept = new->se_accept;
1056 SWAP(char *, sep->se_user, new->se_user);
1057 SWAP(char *, sep->se_group, new->se_group);
1058#ifdef LOGIN_CAP
1059 SWAP(char *, sep->se_class, new->se_class);
1060#endif
1061 SWAP(char *, sep->se_server, new->se_server);
1062 SWAP(char *, sep->se_server_name, new->se_server_name);
1063 for (i = 0; i < MAXARGV; i++)
1064 SWAP(char *, sep->se_argv[i], new->se_argv[i]);
1065#ifdef IPSEC
1066 SWAP(char *, sep->se_policy, new->se_policy);
1067 ipsecsetup(sep);
1068#endif
1069 sigsetmask(omask);
1070 freeconfig(new);
1071 if (debug)
1072 print_service("REDO", sep);
1073 } else {
1074 sep = enter(new);
1075 if (debug)
1076 print_service("ADD ", sep);
1077 }
1078 sep->se_checked = 1;
1079 if (ISMUX(sep)) {
1080 sep->se_fd = -1;
1081 continue;
1082 }
1083 switch (sep->se_family) {
1084 case AF_INET:
1085 if (!v4bind_ok) {
1086 sep->se_fd = -1;
1087 continue;
1088 }
1089 break;
1090#ifdef INET6
1091 case AF_INET6:
1092 if (!v6bind_ok) {
1093 sep->se_fd = -1;
1094 continue;
1095 }
1096 break;
1097#endif
1098 }
1099 if (!sep->se_rpc) {
1100 if (sep->se_family != AF_UNIX) {
1101 sp = getservbyname(sep->se_service, sep->se_proto);
1102 if (sp == 0) {
1103 syslog(LOG_ERR, "%s/%s: unknown service",
1104 sep->se_service, sep->se_proto);
1105 sep->se_checked = 0;
1106 continue;
1107 }
1108 }
1109 switch (sep->se_family) {
1110 case AF_INET:
1111 if (sp->s_port != sep->se_ctrladdr4.sin_port) {
1112 sep->se_ctrladdr4.sin_port =
1113 sp->s_port;
1114 sep->se_reset = 1;
1115 }
1116 break;
1117#ifdef INET6
1118 case AF_INET6:
1119 if (sp->s_port !=
1120 sep->se_ctrladdr6.sin6_port) {
1121 sep->se_ctrladdr6.sin6_port =
1122 sp->s_port;
1123 sep->se_reset = 1;
1124 }
1125 break;
1126#endif
1127 }
1128 if (sep->se_reset != 0 && sep->se_fd >= 0)
1129 close_sep(sep);
1130 } else {
1131 rpc = getrpcbyname(sep->se_service);
1132 if (rpc == 0) {
1133 syslog(LOG_ERR, "%s/%s unknown RPC service",
1134 sep->se_service, sep->se_proto);
1135 if (sep->se_fd != -1)
1136 (void) close(sep->se_fd);
1137 sep->se_fd = -1;
1138 continue;
1139 }
1140 if (sep->se_reset != 0 ||
1141 rpc->r_number != sep->se_rpc_prog) {
1142 if (sep->se_rpc_prog)
1143 unregisterrpc(sep);
1144 sep->se_rpc_prog = rpc->r_number;
1145 if (sep->se_fd != -1)
1146 (void) close(sep->se_fd);
1147 sep->se_fd = -1;
1148 }
1149 sep->se_nomapped = new_nomapped;
1150 }
1151 sep->se_reset = 0;
1152 if (sep->se_fd == -1)
1153 setup(sep);
1154 }
1155 endconfig();
1156 /*
1157 * Purge anything not looked at above.
1158 */
1159 omask = sigblock(SIGBLOCK);
1160 sepp = &servtab;
1161 while ((sep = *sepp)) {
1162 if (sep->se_checked) {
1163 sepp = &sep->se_next;
1164 continue;
1165 }
1166 *sepp = sep->se_next;
1167 if (sep->se_fd >= 0)
1168 close_sep(sep);
1169 if (debug)
1170 print_service("FREE", sep);
1171 if (sep->se_rpc && sep->se_rpc_prog > 0)
1172 unregisterrpc(sep);
1173 freeconfig(sep);
1174 free(sep);
1175 }
1176 (void) sigsetmask(omask);
1177}
1178
1179void
1180unregisterrpc(struct servtab *sep)
1181{
1182 u_int i;
1183 struct servtab *sepp;
1184 long omask;
1185 struct netconfig *netid4, *netid6;
1186
1187 omask = sigblock(SIGBLOCK);
1188 netid4 = sep->se_socktype == SOCK_DGRAM ? udpconf : tcpconf;
1189 netid6 = sep->se_socktype == SOCK_DGRAM ? udp6conf : tcp6conf;
1190 if (sep->se_family == AF_INET)
1191 netid6 = NULL;
1192 else if (sep->se_nomapped)
1193 netid4 = NULL;
1194 /*
1195 * Conflict if same prog and protocol - In that case one should look
1196 * to versions, but it is not interesting: having separate servers for
1197 * different versions does not work well.
1198 * Therefore one do not unregister if there is a conflict.
1199 * There is also transport conflict if destroying INET when INET46
1200 * exists, or destroying INET46 when INET exists
1201 */
1202 for (sepp = servtab; sepp; sepp = sepp->se_next) {
1203 if (sepp == sep)
1204 continue;
1205 if (sepp->se_checked == 0 ||
1206 !sepp->se_rpc ||
1207 strcmp(sep->se_proto, sepp->se_proto) != 0 ||
1208 sep->se_rpc_prog != sepp->se_rpc_prog)
1209 continue;
1210 if (sepp->se_family == AF_INET)
1211 netid4 = NULL;
1212 if (sepp->se_family == AF_INET6) {
1213 netid6 = NULL;
1214 if (!sep->se_nomapped)
1215 netid4 = NULL;
1216 }
1217 if (netid4 == NULL && netid6 == NULL)
1218 return;
1219 }
1220 if (debug)
1221 print_service("UNREG", sep);
1222 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) {
1223 if (netid4)
1224 rpcb_unset(sep->se_rpc_prog, i, netid4);
1225 if (netid6)
1226 rpcb_unset(sep->se_rpc_prog, i, netid6);
1227 }
1228 if (sep->se_fd != -1)
1229 (void) close(sep->se_fd);
1230 sep->se_fd = -1;
1231 (void) sigsetmask(omask);
1232}
1233
1234void
1235flag_retry(int signo __unused)
1236{
1237 flag_signal('A');
1238}
1239
1240void
1241retry(void)
1242{
1243 struct servtab *sep;
1244
1245 timingout = 0;
1246 for (sep = servtab; sep; sep = sep->se_next)
1247 if (sep->se_fd == -1 && !ISMUX(sep))
1248 setup(sep);
1249}
1250
1251void
1252setup(struct servtab *sep)
1253{
1254 int on = 1;
1255
1256 if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
1257 if (debug)
1258 warn("socket failed on %s/%s",
1259 sep->se_service, sep->se_proto);
1260 syslog(LOG_ERR, "%s/%s: socket: %m",
1261 sep->se_service, sep->se_proto);
1262 return;
1263 }
1264 /* Set all listening sockets to close-on-exec. */
1265 if (fcntl(sep->se_fd, F_SETFD, FD_CLOEXEC) < 0) {
1266 syslog(LOG_ERR, "%s/%s: fcntl (F_SETFD, FD_CLOEXEC): %m",
1267 sep->se_service, sep->se_proto);
1268 close(sep->se_fd);
1269 return;
1270 }
1271#define turnon(fd, opt) \
1272setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
1273 if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
1274 turnon(sep->se_fd, SO_DEBUG) < 0)
1275 syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
1276 if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
1277 syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
1278#ifdef SO_PRIVSTATE
1279 if (turnon(sep->se_fd, SO_PRIVSTATE) < 0)
1280 syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m");
1281#endif
1282 /* tftpd opens a new connection then needs more infos */
1283 if ((sep->se_family == AF_INET6) &&
1284 (strcmp(sep->se_proto, "udp") == 0) &&
1285 (sep->se_accept == 0) &&
1286 (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
1287 (char *)&on, sizeof (on)) < 0))
1288 syslog(LOG_ERR, "setsockopt (IPV6_RECVPKTINFO): %m");
1289 if (sep->se_family == AF_INET6) {
1290 int flag = sep->se_nomapped ? 1 : 0;
1291 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_V6ONLY,
1292 (char *)&flag, sizeof (flag)) < 0)
1293 syslog(LOG_ERR, "setsockopt (IPV6_V6ONLY): %m");
1294 }
1295#undef turnon
1296 if (sep->se_type == TTCP_TYPE)
1297 if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH,
1298 (char *)&on, sizeof (on)) < 0)
1299 syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m");
1300#ifdef IPV6_FAITH
1301 if (sep->se_type == FAITH_TYPE) {
1302 if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, &on,
1303 sizeof(on)) < 0) {
1304 syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
1305 }
1306 }
1307#endif
1308#ifdef IPSEC
1309 ipsecsetup(sep);
1310#endif
1311 if (sep->se_family == AF_UNIX) {
1312 (void) unlink(sep->se_ctrladdr_un.sun_path);
1313 umask(0777); /* Make socket with conservative permissions */
1314 }
1315 if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
1316 sep->se_ctrladdr_size) < 0) {
1317 if (debug)
1318 warn("bind failed on %s/%s",
1319 sep->se_service, sep->se_proto);
1320 syslog(LOG_ERR, "%s/%s: bind: %m",
1321 sep->se_service, sep->se_proto);
1322 (void) close(sep->se_fd);
1323 sep->se_fd = -1;
1324 if (!timingout) {
1325 timingout = 1;
1326 alarm(RETRYTIME);
1327 }
1328 if (sep->se_family == AF_UNIX)
1329 umask(mask);
1330 return;
1331 }
1332 if (sep->se_family == AF_UNIX) {
1333 /* Ick - fch{own,mod} don't work on Unix domain sockets */
1334 if (chown(sep->se_service, sep->se_sockuid, sep->se_sockgid) < 0)
1335 syslog(LOG_ERR, "chown socket: %m");
1336 if (chmod(sep->se_service, sep->se_sockmode) < 0)
1337 syslog(LOG_ERR, "chmod socket: %m");
1338 umask(mask);
1339 }
1340 if (sep->se_rpc) {
1341 u_int i;
1342 socklen_t len = sep->se_ctrladdr_size;
1343 struct netconfig *netid, *netid2 = NULL;
1344 struct sockaddr_in sock;
1345 struct netbuf nbuf, nbuf2;
1346
1347 if (getsockname(sep->se_fd,
1348 (struct sockaddr*)&sep->se_ctrladdr, &len) < 0){
1349 syslog(LOG_ERR, "%s/%s: getsockname: %m",
1350 sep->se_service, sep->se_proto);
1351 (void) close(sep->se_fd);
1352 sep->se_fd = -1;
1353 return;
1354 }
1355 nbuf.buf = &sep->se_ctrladdr;
1356 nbuf.len = sep->se_ctrladdr.sa_len;
1357 if (sep->se_family == AF_INET)
1358 netid = sep->se_socktype==SOCK_DGRAM? udpconf:tcpconf;
1359 else {
1360 netid = sep->se_socktype==SOCK_DGRAM? udp6conf:tcp6conf;
1361 if (!sep->se_nomapped) { /* INET and INET6 */
1362 netid2 = netid==udp6conf? udpconf:tcpconf;
1363 memset(&sock, 0, sizeof sock); /* ADDR_ANY */
1364 nbuf2.buf = &sock;
1365 nbuf2.len = sock.sin_len = sizeof sock;
1366 sock.sin_family = AF_INET;
1367 sock.sin_port = sep->se_ctrladdr6.sin6_port;
1368 }
1369 }
1370 if (debug)
1371 print_service("REG ", sep);
1372 for (i = sep->se_rpc_lowvers; i <= sep->se_rpc_highvers; i++) {
1373 rpcb_unset(sep->se_rpc_prog, i, netid);
1374 rpcb_set(sep->se_rpc_prog, i, netid, &nbuf);
1375 if (netid2) {
1376 rpcb_unset(sep->se_rpc_prog, i, netid2);
1377 rpcb_set(sep->se_rpc_prog, i, netid2, &nbuf2);
1378 }
1379 }
1380 }
1381 if (sep->se_socktype == SOCK_STREAM)
1382 listen(sep->se_fd, 64);
1383 enable(sep);
1384 if (debug) {
1385 warnx("registered %s on %d",
1386 sep->se_server, sep->se_fd);
1387 }
1388}
1389
1390#ifdef IPSEC
1391void
1392ipsecsetup(sep)
1393 struct servtab *sep;
1394{
1395 char *buf;
1396 char *policy_in = NULL;
1397 char *policy_out = NULL;
1398 int level;
1399 int opt;
1400
1401 switch (sep->se_family) {
1402 case AF_INET:
1403 level = IPPROTO_IP;
1404 opt = IP_IPSEC_POLICY;
1405 break;
1406#ifdef INET6
1407 case AF_INET6:
1408 level = IPPROTO_IPV6;
1409 opt = IPV6_IPSEC_POLICY;
1410 break;
1411#endif
1412 default:
1413 return;
1414 }
1415
1416 if (!sep->se_policy || sep->se_policy[0] == '\0') {
1417 static char def_in[] = "in entrust", def_out[] = "out entrust";
1418 policy_in = def_in;
1419 policy_out = def_out;
1420 } else {
1421 if (!strncmp("in", sep->se_policy, 2))
1422 policy_in = sep->se_policy;
1423 else if (!strncmp("out", sep->se_policy, 3))
1424 policy_out = sep->se_policy;
1425 else {
1426 syslog(LOG_ERR, "invalid security policy \"%s\"",
1427 sep->se_policy);
1428 return;
1429 }
1430 }
1431
1432 if (policy_in != NULL) {
1433 buf = ipsec_set_policy(policy_in, strlen(policy_in));
1434 if (buf != NULL) {
1435 if (setsockopt(sep->se_fd, level, opt,
1436 buf, ipsec_get_policylen(buf)) < 0 &&
1437 debug != 0)
1438 warnx("%s/%s: ipsec initialization failed; %s",
1439 sep->se_service, sep->se_proto,
1440 policy_in);
1441 free(buf);
1442 } else
1443 syslog(LOG_ERR, "invalid security policy \"%s\"",
1444 policy_in);
1445 }
1446 if (policy_out != NULL) {
1447 buf = ipsec_set_policy(policy_out, strlen(policy_out));
1448 if (buf != NULL) {
1449 if (setsockopt(sep->se_fd, level, opt,
1450 buf, ipsec_get_policylen(buf)) < 0 &&
1451 debug != 0)
1452 warnx("%s/%s: ipsec initialization failed; %s",
1453 sep->se_service, sep->se_proto,
1454 policy_out);
1455 free(buf);
1456 } else
1457 syslog(LOG_ERR, "invalid security policy \"%s\"",
1458 policy_out);
1459 }
1460}
1461#endif
1462
1463/*
1464 * Finish with a service and its socket.
1465 */
1466void
1467close_sep(struct servtab *sep)
1468{
1469 if (sep->se_fd >= 0) {
1470 if (FD_ISSET(sep->se_fd, &allsock))
1471 disable(sep);
1472 (void) close(sep->se_fd);
1473 sep->se_fd = -1;
1474 }
1475 sep->se_count = 0;
1476 sep->se_numchild = 0; /* forget about any existing children */
1477}
1478
1479int
1480matchservent(const char *name1, const char *name2, const char *proto)
1481{
1482 char **alias, *p;
1483 struct servent *se;
1484
1485 if (strcmp(proto, "unix") == 0) {
1486 if ((p = strrchr(name1, '/')) != NULL)
1487 name1 = p + 1;
1488 if ((p = strrchr(name2, '/')) != NULL)
1489 name2 = p + 1;
1490 }
1491 if (strcmp(name1, name2) == 0)
1492 return(1);
1493 if ((se = getservbyname(name1, proto)) != NULL) {
1494 if (strcmp(name2, se->s_name) == 0)
1495 return(1);
1496 for (alias = se->s_aliases; *alias; alias++)
1497 if (strcmp(name2, *alias) == 0)
1498 return(1);
1499 }
1500 return(0);
1501}
1502
1503struct servtab *
1504enter(struct servtab *cp)
1505{
1506 struct servtab *sep;
1507 long omask;
1508
1509 sep = (struct servtab *)malloc(sizeof (*sep));
1510 if (sep == (struct servtab *)0) {
1511 syslog(LOG_ERR, "malloc: %m");
1512 exit(EX_OSERR);
1513 }
1514 *sep = *cp;
1515 sep->se_fd = -1;
1516 omask = sigblock(SIGBLOCK);
1517 sep->se_next = servtab;
1518 servtab = sep;
1519 sigsetmask(omask);
1520 return (sep);
1521}
1522
1523void
1524enable(struct servtab *sep)
1525{
1526 if (debug)
1527 warnx(
1528 "enabling %s, fd %d", sep->se_service, sep->se_fd);
1529#ifdef SANITY_CHECK
1530 if (sep->se_fd < 0) {
1531 syslog(LOG_ERR,
1532 "%s: %s: bad fd", __func__, sep->se_service);
1533 exit(EX_SOFTWARE);
1534 }
1535 if (ISMUX(sep)) {
1536 syslog(LOG_ERR,
1537 "%s: %s: is mux", __func__, sep->se_service);
1538 exit(EX_SOFTWARE);
1539 }
1540 if (FD_ISSET(sep->se_fd, &allsock)) {
1541 syslog(LOG_ERR,
1542 "%s: %s: not off", __func__, sep->se_service);
1543 exit(EX_SOFTWARE);
1544 }
1545 nsock++;
1546#endif
1547 FD_SET(sep->se_fd, &allsock);
1548 if (sep->se_fd > maxsock)
1549 maxsock = sep->se_fd;
1550}
1551
1552void
1553disable(struct servtab *sep)
1554{
1555 if (debug)
1556 warnx(
1557 "disabling %s, fd %d", sep->se_service, sep->se_fd);
1558#ifdef SANITY_CHECK
1559 if (sep->se_fd < 0) {
1560 syslog(LOG_ERR,
1561 "%s: %s: bad fd", __func__, sep->se_service);
1562 exit(EX_SOFTWARE);
1563 }
1564 if (ISMUX(sep)) {
1565 syslog(LOG_ERR,
1566 "%s: %s: is mux", __func__, sep->se_service);
1567 exit(EX_SOFTWARE);
1568 }
1569 if (!FD_ISSET(sep->se_fd, &allsock)) {
1570 syslog(LOG_ERR,
1571 "%s: %s: not on", __func__, sep->se_service);
1572 exit(EX_SOFTWARE);
1573 }
1574 if (nsock == 0) {
1575 syslog(LOG_ERR, "%s: nsock=0", __func__);
1576 exit(EX_SOFTWARE);
1577 }
1578 nsock--;
1579#endif
1580 FD_CLR(sep->se_fd, &allsock);
1581 if (sep->se_fd == maxsock)
1582 maxsock--;
1583}
1584
1585FILE *fconfig = NULL;
1586struct servtab serv;
1587char line[LINE_MAX];
1588
1589int
1590setconfig(void)
1591{
1592
1593 if (fconfig != NULL) {
1594 fseek(fconfig, 0L, SEEK_SET);
1595 return (1);
1596 }
1597 fconfig = fopen(CONFIG, "r");
1598 return (fconfig != NULL);
1599}
1600
1601void
1602endconfig(void)
1603{
1604 if (fconfig) {
1605 (void) fclose(fconfig);
1606 fconfig = NULL;
1607 }
1608}
1609
1610struct servtab *
1611getconfigent(void)
1612{
1613 struct servtab *sep = &serv;
1614 int argc;
1615 char *cp, *arg, *s;
1616 char *versp;
1617 static char TCPMUX_TOKEN[] = "tcpmux/";
1618#define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
1619#ifdef IPSEC
1620 char *policy;
1621#endif
1622 int v4bind;
1623#ifdef INET6
1624 int v6bind;
1625#endif
1626 int i;
1627
1628#ifdef IPSEC
1629 policy = NULL;
1630#endif
1631more:
1632 v4bind = 0;
1633#ifdef INET6
1634 v6bind = 0;
1635#endif
1636 while ((cp = nextline(fconfig)) != NULL) {
1637#ifdef IPSEC
1638 /* lines starting with #@ is not a comment, but the policy */
1639 if (cp[0] == '#' && cp[1] == '@') {
1640 char *p;
1641 for (p = cp + 2; p && *p && isspace(*p); p++)
1642 ;
1643 if (*p == '\0') {
1644 if (policy)
1645 free(policy);
1646 policy = NULL;
1647 } else if (ipsec_get_policylen(p) >= 0) {
1648 if (policy)
1649 free(policy);
1650 policy = newstr(p);
1651 } else {
1652 syslog(LOG_ERR,
1653 "%s: invalid ipsec policy \"%s\"",
1654 CONFIG, p);
1655 exit(EX_CONFIG);
1656 }
1657 }
1658#endif
1659 if (*cp == '#' || *cp == '\0')
1660 continue;
1661 break;
1662 }
1663 if (cp == NULL)
1664 return ((struct servtab *)0);
1665 /*
1666 * clear the static buffer, since some fields (se_ctrladdr,
1667 * for example) don't get initialized here.
1668 */
1669 memset(sep, 0, sizeof *sep);
1670 arg = skip(&cp);
1671 if (cp == NULL) {
1672 /* got an empty line containing just blanks/tabs. */
1673 goto more;
1674 }
1675 if (arg[0] == ':') { /* :user:group:perm: */
1676 char *user, *group, *perm;
1677 struct passwd *pw;
1678 struct group *gr;
1679 user = arg+1;
1680 if ((group = strchr(user, ':')) == NULL) {
1681 syslog(LOG_ERR, "no group after user '%s'", user);
1682 goto more;
1683 }
1684 *group++ = '\0';
1685 if ((perm = strchr(group, ':')) == NULL) {
1686 syslog(LOG_ERR, "no mode after group '%s'", group);
1687 goto more;
1688 }
1689 *perm++ = '\0';
1690 if ((pw = getpwnam(user)) == NULL) {
1691 syslog(LOG_ERR, "no such user '%s'", user);
1692 goto more;
1693 }
1694 sep->se_sockuid = pw->pw_uid;
1695 if ((gr = getgrnam(group)) == NULL) {
1696 syslog(LOG_ERR, "no such user '%s'", group);
1697 goto more;
1698 }
1699 sep->se_sockgid = gr->gr_gid;
1700 sep->se_sockmode = strtol(perm, &arg, 8);
1701 if (*arg != ':') {
1702 syslog(LOG_ERR, "bad mode '%s'", perm);
1703 goto more;
1704 }
1705 *arg++ = '\0';
1706 } else {
1707 sep->se_sockuid = euid;
1708 sep->se_sockgid = egid;
1709 sep->se_sockmode = 0200;
1710 }
1711 if (strncmp(arg, TCPMUX_TOKEN, MUX_LEN) == 0) {
1712 char *c = arg + MUX_LEN;
1713 if (*c == '+') {
1714 sep->se_type = MUXPLUS_TYPE;
1715 c++;
1716 } else
1717 sep->se_type = MUX_TYPE;
1718 sep->se_service = newstr(c);
1719 } else {
1720 sep->se_service = newstr(arg);
1721 sep->se_type = NORM_TYPE;
1722 }
1723 arg = sskip(&cp);
1724 if (strcmp(arg, "stream") == 0)
1725 sep->se_socktype = SOCK_STREAM;
1726 else if (strcmp(arg, "dgram") == 0)
1727 sep->se_socktype = SOCK_DGRAM;
1728 else if (strcmp(arg, "rdm") == 0)
1729 sep->se_socktype = SOCK_RDM;
1730 else if (strcmp(arg, "seqpacket") == 0)
1731 sep->se_socktype = SOCK_SEQPACKET;
1732 else if (strcmp(arg, "raw") == 0)
1733 sep->se_socktype = SOCK_RAW;
1734 else
1735 sep->se_socktype = -1;
1736
1737 arg = sskip(&cp);
1738 if (strncmp(arg, "tcp", 3) == 0) {
1739 sep->se_proto = newstr(strsep(&arg, "/"));
1740 if (arg != NULL) {
1741 if (strcmp(arg, "ttcp") == 0)
1742 sep->se_type = TTCP_TYPE;
1743 else if (strcmp(arg, "faith") == 0)
1744 sep->se_type = FAITH_TYPE;
1745 }
1746 } else {
1747 if (sep->se_type == NORM_TYPE &&
1748 strncmp(arg, "faith/", 6) == 0) {
1749 arg += 6;
1750 sep->se_type = FAITH_TYPE;
1751 }
1752 sep->se_proto = newstr(arg);
1753 }
1754 if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
1755 memmove(sep->se_proto, sep->se_proto + 4,
1756 strlen(sep->se_proto) + 1 - 4);
1757 sep->se_rpc = 1;
1758 sep->se_rpc_prog = sep->se_rpc_lowvers =
1759 sep->se_rpc_lowvers = 0;
1760 memcpy(&sep->se_ctrladdr4, bind_sa4,
1761 sizeof(sep->se_ctrladdr4));
1762 if ((versp = rindex(sep->se_service, '/'))) {
1763 *versp++ = '\0';
1764 switch (sscanf(versp, "%u-%u",
1765 &sep->se_rpc_lowvers,
1766 &sep->se_rpc_highvers)) {
1767 case 2:
1768 break;
1769 case 1:
1770 sep->se_rpc_highvers =
1771 sep->se_rpc_lowvers;
1772 break;
1773 default:
1774 syslog(LOG_ERR,
1775 "bad RPC version specifier; %s",
1776 sep->se_service);
1777 freeconfig(sep);
1778 goto more;
1779 }
1780 }
1781 else {
1782 sep->se_rpc_lowvers =
1783 sep->se_rpc_highvers = 1;
1784 }
1785 }
1786 sep->se_nomapped = 0;
1787 if (strcmp(sep->se_proto, "unix") == 0) {
1788 sep->se_family = AF_UNIX;
1789 } else {
1790 while (isdigit(sep->se_proto[strlen(sep->se_proto) - 1])) {
1791#ifdef INET6
1792 if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') {
1793 sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
1794 v6bind = 1;
1795 continue;
1796 }
1797#endif
1798 if (sep->se_proto[strlen(sep->se_proto) - 1] == '4') {
1799 sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
1800 v4bind = 1;
1801 continue;
1802 }
1803 /* illegal version num */
1804 syslog(LOG_ERR, "bad IP version for %s", sep->se_proto);
1805 freeconfig(sep);
1806 goto more;
1807 }
1808#ifdef INET6
1809 if (v6bind && !v6bind_ok) {
1810 syslog(LOG_INFO, "IPv6 bind is ignored for %s",
1811 sep->se_service);
1812 if (v4bind && v4bind_ok)
1813 v6bind = 0;
1814 else {
1815 freeconfig(sep);
1816 goto more;
1817 }
1818 }
1819 if (v6bind) {
1820 sep->se_family = AF_INET6;
1821 if (!v4bind || !v4bind_ok)
1822 sep->se_nomapped = 1;
1823 } else
1824#endif
1825 { /* default to v4 bind if not v6 bind */
1826 if (!v4bind_ok) {
1827 syslog(LOG_NOTICE, "IPv4 bind is ignored for %s",
1828 sep->se_service);
1829 freeconfig(sep);
1830 goto more;
1831 }
1832 sep->se_family = AF_INET;
1833 }
1834 }
1835 /* init ctladdr */
1836 switch(sep->se_family) {
1837 case AF_INET:
1838 memcpy(&sep->se_ctrladdr4, bind_sa4,
1839 sizeof(sep->se_ctrladdr4));
1840 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr4);
1841 break;
1842#ifdef INET6
1843 case AF_INET6:
1844 memcpy(&sep->se_ctrladdr6, bind_sa6,
1845 sizeof(sep->se_ctrladdr6));
1846 sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr6);
1847 break;
1848#endif
1849 case AF_UNIX:
1850 if (strlen(sep->se_service) >= sizeof(sep->se_ctrladdr_un.sun_path)) {
1851 syslog(LOG_ERR,
1852 "domain socket pathname too long for service %s",
1853 sep->se_service);
1854 goto more;
1855 }
1856 memset(&sep->se_ctrladdr, 0, sizeof(sep->se_ctrladdr));
1857 sep->se_ctrladdr_un.sun_family = sep->se_family;
1858 sep->se_ctrladdr_un.sun_len = strlen(sep->se_service);
1859 strcpy(sep->se_ctrladdr_un.sun_path, sep->se_service);
1860 sep->se_ctrladdr_size = SUN_LEN(&sep->se_ctrladdr_un);
1861 }
1862 arg = sskip(&cp);
1863 if (!strncmp(arg, "wait", 4))
1864 sep->se_accept = 0;
1865 else if (!strncmp(arg, "nowait", 6))
1866 sep->se_accept = 1;
1867 else {
1868 syslog(LOG_ERR,
1869 "%s: bad wait/nowait for service %s",
1870 CONFIG, sep->se_service);
1871 goto more;
1872 }
1873 sep->se_maxchild = -1;
1874 sep->se_maxcpm = -1;
1875 sep->se_maxperip = -1;
1876 if ((s = strchr(arg, '/')) != NULL) {
1877 char *eptr;
1878 u_long val;
1879
1880 val = strtoul(s + 1, &eptr, 10);
1881 if (eptr == s + 1 || val > MAX_MAXCHLD) {
1882 syslog(LOG_ERR,
1883 "%s: bad max-child for service %s",
1884 CONFIG, sep->se_service);
1885 goto more;
1886 }
1887 if (debug)
1888 if (!sep->se_accept && val != 1)
1889 warnx("maxchild=%lu for wait service %s"
1890 " not recommended", val, sep->se_service);
1891 sep->se_maxchild = val;
1892 if (*eptr == '/')
1893 sep->se_maxcpm = strtol(eptr + 1, &eptr, 10);
1894 if (*eptr == '/')
1895 sep->se_maxperip = strtol(eptr + 1, &eptr, 10);
1896 /*
1897 * explicitly do not check for \0 for future expansion /
1898 * backwards compatibility
1899 */
1900 }
1901 if (ISMUX(sep)) {
1902 /*
1903 * Silently enforce "nowait" mode for TCPMUX services
1904 * since they don't have an assigned port to listen on.
1905 */
1906 sep->se_accept = 1;
1907 if (strcmp(sep->se_proto, "tcp")) {
1908 syslog(LOG_ERR,
1909 "%s: bad protocol for tcpmux service %s",
1910 CONFIG, sep->se_service);
1911 goto more;
1912 }
1913 if (sep->se_socktype != SOCK_STREAM) {
1914 syslog(LOG_ERR,
1915 "%s: bad socket type for tcpmux service %s",
1916 CONFIG, sep->se_service);
1917 goto more;
1918 }
1919 }
1920 sep->se_user = newstr(sskip(&cp));
1921#ifdef LOGIN_CAP
1922 if ((s = strrchr(sep->se_user, '/')) != NULL) {
1923 *s = '\0';
1924 sep->se_class = newstr(s + 1);
1925 } else
1926 sep->se_class = newstr(RESOURCE_RC);
1927#endif
1928 if ((s = strrchr(sep->se_user, ':')) != NULL) {
1929 *s = '\0';
1930 sep->se_group = newstr(s + 1);
1931 } else
1932 sep->se_group = NULL;
1933 sep->se_server = newstr(sskip(&cp));
1934 if ((sep->se_server_name = rindex(sep->se_server, '/')))
1935 sep->se_server_name++;
1936 if (strcmp(sep->se_server, "internal") == 0) {
1937 struct biltin *bi;
1938
1939 for (bi = biltins; bi->bi_service; bi++)
1940 if (bi->bi_socktype == sep->se_socktype &&
1941 matchservent(bi->bi_service, sep->se_service,
1942 sep->se_proto))
1943 break;
1944 if (bi->bi_service == 0) {
1945 syslog(LOG_ERR, "internal service %s unknown",
1946 sep->se_service);
1947 goto more;
1948 }
1949 sep->se_accept = 1; /* force accept mode for built-ins */
1950 sep->se_bi = bi;
1951 } else
1952 sep->se_bi = NULL;
1953 if (sep->se_maxperip < 0)
1954 sep->se_maxperip = maxperip;
1955 if (sep->se_maxcpm < 0)
1956 sep->se_maxcpm = maxcpm;
1957 if (sep->se_maxchild < 0) { /* apply default max-children */
1958 if (sep->se_bi && sep->se_bi->bi_maxchild >= 0)
1959 sep->se_maxchild = sep->se_bi->bi_maxchild;
1960 else if (sep->se_accept)
1961 sep->se_maxchild = maxchild > 0 ? maxchild : 0;
1962 else
1963 sep->se_maxchild = 1;
1964 }
1965 if (sep->se_maxchild > 0) {
1966 sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids));
1967 if (sep->se_pids == NULL) {
1968 syslog(LOG_ERR, "malloc: %m");
1969 exit(EX_OSERR);
1970 }
1971 }
1972 argc = 0;
1973 for (arg = skip(&cp); cp; arg = skip(&cp))
1974 if (argc < MAXARGV) {
1975 sep->se_argv[argc++] = newstr(arg);
1976 } else {
1977 syslog(LOG_ERR,
1978 "%s: too many arguments for service %s",
1979 CONFIG, sep->se_service);
1980 goto more;
1981 }
1982 while (argc <= MAXARGV)
1983 sep->se_argv[argc++] = NULL;
1984 for (i = 0; i < PERIPSIZE; ++i)
1985 LIST_INIT(&sep->se_conn[i]);
1986#ifdef IPSEC
1987 sep->se_policy = policy ? newstr(policy) : NULL;
1988#endif
1989 return (sep);
1990}
1991
1992void
1993freeconfig(struct servtab *cp)
1994{
1995 int i;
1996
1997 if (cp->se_service)
1998 free(cp->se_service);
1999 if (cp->se_proto)
2000 free(cp->se_proto);
2001 if (cp->se_user)
2002 free(cp->se_user);
2003 if (cp->se_group)
2004 free(cp->se_group);
2005#ifdef LOGIN_CAP
2006 if (cp->se_class)
2007 free(cp->se_class);
2008#endif
2009 if (cp->se_server)
2010 free(cp->se_server);
2011 if (cp->se_pids)
2012 free(cp->se_pids);
2013 for (i = 0; i < MAXARGV; i++)
2014 if (cp->se_argv[i])
2015 free(cp->se_argv[i]);
2016 free_connlist(cp);
2017#ifdef IPSEC
2018 if (cp->se_policy)
2019 free(cp->se_policy);
2020#endif
2021}
2022
2023
2024/*
2025 * Safe skip - if skip returns null, log a syntax error in the
2026 * configuration file and exit.
2027 */
2028char *
2029sskip(char **cpp)
2030{
2031 char *cp;
2032
2033 cp = skip(cpp);
2034 if (cp == NULL) {
2035 syslog(LOG_ERR, "%s: syntax error", CONFIG);
2036 exit(EX_DATAERR);
2037 }
2038 return (cp);
2039}
2040
2041char *
2042skip(char **cpp)
2043{
2044 char *cp = *cpp;
2045 char *start;
2046 char quote = '\0';
2047
2048again:
2049 while (*cp == ' ' || *cp == '\t')
2050 cp++;
2051 if (*cp == '\0') {
2052 int c;
2053
2054 c = getc(fconfig);
2055 (void) ungetc(c, fconfig);
2056 if (c == ' ' || c == '\t')
2057 if ((cp = nextline(fconfig)))
2058 goto again;
2059 *cpp = (char *)0;
2060 return ((char *)0);
2061 }
2062 if (*cp == '"' || *cp == '\'')
2063 quote = *cp++;
2064 start = cp;
2065 if (quote)
2066 while (*cp && *cp != quote)
2067 cp++;
2068 else
2069 while (*cp && *cp != ' ' && *cp != '\t')
2070 cp++;
2071 if (*cp != '\0')
2072 *cp++ = '\0';
2073 *cpp = cp;
2074 return (start);
2075}
2076
2077char *
2078nextline(FILE *fd)
2079{
2080 char *cp;
2081
2082 if (fgets(line, sizeof (line), fd) == NULL)
2083 return ((char *)0);
2084 cp = strchr(line, '\n');
2085 if (cp)
2086 *cp = '\0';
2087 return (line);
2088}
2089
2090char *
2091newstr(const char *cp)
2092{
2093 char *cr;
2094
2095 if ((cr = strdup(cp != NULL ? cp : "")))
2096 return (cr);
2097 syslog(LOG_ERR, "strdup: %m");
2098 exit(EX_OSERR);
2099}
2100
2101void
2102inetd_setproctitle(const char *a, int s)
2103{
2104 socklen_t size;
2105 struct sockaddr_storage ss;
2106 char buf[80], pbuf[INET6_ADDRSTRLEN];
2107
2108 size = sizeof(ss);
2109 if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
2110 getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf),
2120 NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID);
2111 NULL, 0, NI_NUMERICHOST);
2121 (void) sprintf(buf, "%s [%s]", a, pbuf);
2122 } else
2123 (void) sprintf(buf, "%s", a);
2124 setproctitle("%s", buf);
2125}
2126
2127int
2128check_loop(const struct sockaddr *sa, const struct servtab *sep)
2129{
2130 struct servtab *se2;
2131 char pname[INET6_ADDRSTRLEN];
2132
2133 for (se2 = servtab; se2; se2 = se2->se_next) {
2134 if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM)
2135 continue;
2136
2137 switch (se2->se_family) {
2138 case AF_INET:
2139 if (((const struct sockaddr_in *)sa)->sin_port ==
2140 se2->se_ctrladdr4.sin_port)
2141 goto isloop;
2142 continue;
2143#ifdef INET6
2144 case AF_INET6:
2145 if (((const struct sockaddr_in *)sa)->sin_port ==
2146 se2->se_ctrladdr4.sin_port)
2147 goto isloop;
2148 continue;
2149#endif
2150 default:
2151 continue;
2152 }
2153 isloop:
2154 getnameinfo(sa, sa->sa_len, pname, sizeof(pname), NULL, 0,
2112 (void) sprintf(buf, "%s [%s]", a, pbuf);
2113 } else
2114 (void) sprintf(buf, "%s", a);
2115 setproctitle("%s", buf);
2116}
2117
2118int
2119check_loop(const struct sockaddr *sa, const struct servtab *sep)
2120{
2121 struct servtab *se2;
2122 char pname[INET6_ADDRSTRLEN];
2123
2124 for (se2 = servtab; se2; se2 = se2->se_next) {
2125 if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM)
2126 continue;
2127
2128 switch (se2->se_family) {
2129 case AF_INET:
2130 if (((const struct sockaddr_in *)sa)->sin_port ==
2131 se2->se_ctrladdr4.sin_port)
2132 goto isloop;
2133 continue;
2134#ifdef INET6
2135 case AF_INET6:
2136 if (((const struct sockaddr_in *)sa)->sin_port ==
2137 se2->se_ctrladdr4.sin_port)
2138 goto isloop;
2139 continue;
2140#endif
2141 default:
2142 continue;
2143 }
2144 isloop:
2145 getnameinfo(sa, sa->sa_len, pname, sizeof(pname), NULL, 0,
2155 NI_NUMERICHOST|NI_WITHSCOPEID);
2146 NI_NUMERICHOST);
2156 syslog(LOG_WARNING, "%s/%s:%s/%s loop request REFUSED from %s",
2157 sep->se_service, sep->se_proto,
2158 se2->se_service, se2->se_proto,
2159 pname);
2160 return 1;
2161 }
2162 return 0;
2163}
2164
2165/*
2166 * print_service:
2167 * Dump relevant information to stderr
2168 */
2169void
2170print_service(const char *action, const struct servtab *sep)
2171{
2172 fprintf(stderr,
2173 "%s: %s proto=%s accept=%d max=%d user=%s group=%s"
2174#ifdef LOGIN_CAP
2175 "class=%s"
2176#endif
2177 " builtin=%p server=%s"
2178#ifdef IPSEC
2179 " policy=\"%s\""
2180#endif
2181 "\n",
2182 action, sep->se_service, sep->se_proto,
2183 sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group,
2184#ifdef LOGIN_CAP
2185 sep->se_class,
2186#endif
2187 (void *) sep->se_bi, sep->se_server
2188#ifdef IPSEC
2189 , (sep->se_policy ? sep->se_policy : "")
2190#endif
2191 );
2192}
2193
2194#define CPMHSIZE 256
2195#define CPMHMASK (CPMHSIZE-1)
2196#define CHTGRAN 10
2197#define CHTSIZE 6
2198
2199typedef struct CTime {
2200 unsigned long ct_Ticks;
2201 int ct_Count;
2202} CTime;
2203
2204typedef struct CHash {
2205 union {
2206 struct in_addr c4_Addr;
2207 struct in6_addr c6_Addr;
2208 } cu_Addr;
2209#define ch_Addr4 cu_Addr.c4_Addr
2210#define ch_Addr6 cu_Addr.c6_Addr
2211 int ch_Family;
2212 time_t ch_LTime;
2213 char *ch_Service;
2214 CTime ch_Times[CHTSIZE];
2215} CHash;
2216
2217CHash CHashAry[CPMHSIZE];
2218
2219int
2220cpmip(const struct servtab *sep, int ctrl)
2221{
2222 struct sockaddr_storage rss;
2223 socklen_t rssLen = sizeof(rss);
2224 int r = 0;
2225
2226 /*
2227 * If getpeername() fails, just let it through (if logging is
2228 * enabled the condition is caught elsewhere)
2229 */
2230
2231 if (sep->se_maxcpm > 0 &&
2232 getpeername(ctrl, (struct sockaddr *)&rss, &rssLen) == 0 ) {
2233 time_t t = time(NULL);
2234 int hv = 0xABC3D20F;
2235 int i;
2236 int cnt = 0;
2237 CHash *chBest = NULL;
2238 unsigned int ticks = t / CHTGRAN;
2239 struct sockaddr_in *sin4;
2240#ifdef INET6
2241 struct sockaddr_in6 *sin6;
2242#endif
2243
2244 sin4 = (struct sockaddr_in *)&rss;
2245#ifdef INET6
2246 sin6 = (struct sockaddr_in6 *)&rss;
2247#endif
2248 {
2249 char *p;
2250 int addrlen;
2251
2252 switch (rss.ss_family) {
2253 case AF_INET:
2254 p = (char *)&sin4->sin_addr;
2255 addrlen = sizeof(struct in_addr);
2256 break;
2257#ifdef INET6
2258 case AF_INET6:
2259 p = (char *)&sin6->sin6_addr;
2260 addrlen = sizeof(struct in6_addr);
2261 break;
2262#endif
2263 default:
2264 /* should not happen */
2265 return -1;
2266 }
2267
2268 for (i = 0; i < addrlen; ++i, ++p) {
2269 hv = (hv << 5) ^ (hv >> 23) ^ *p;
2270 }
2271 hv = (hv ^ (hv >> 16));
2272 }
2273 for (i = 0; i < 5; ++i) {
2274 CHash *ch = &CHashAry[(hv + i) & CPMHMASK];
2275
2276 if (rss.ss_family == AF_INET &&
2277 ch->ch_Family == AF_INET &&
2278 sin4->sin_addr.s_addr == ch->ch_Addr4.s_addr &&
2279 ch->ch_Service && strcmp(sep->se_service,
2280 ch->ch_Service) == 0) {
2281 chBest = ch;
2282 break;
2283 }
2284#ifdef INET6
2285 if (rss.ss_family == AF_INET6 &&
2286 ch->ch_Family == AF_INET6 &&
2287 IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2288 &ch->ch_Addr6) != 0 &&
2289 ch->ch_Service && strcmp(sep->se_service,
2290 ch->ch_Service) == 0) {
2291 chBest = ch;
2292 break;
2293 }
2294#endif
2295 if (chBest == NULL || ch->ch_LTime == 0 ||
2296 ch->ch_LTime < chBest->ch_LTime) {
2297 chBest = ch;
2298 }
2299 }
2300 if ((rss.ss_family == AF_INET &&
2301 (chBest->ch_Family != AF_INET ||
2302 sin4->sin_addr.s_addr != chBest->ch_Addr4.s_addr)) ||
2303 chBest->ch_Service == NULL ||
2304 strcmp(sep->se_service, chBest->ch_Service) != 0) {
2305 chBest->ch_Family = sin4->sin_family;
2306 chBest->ch_Addr4 = sin4->sin_addr;
2307 if (chBest->ch_Service)
2308 free(chBest->ch_Service);
2309 chBest->ch_Service = strdup(sep->se_service);
2310 bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2311 }
2312#ifdef INET6
2313 if ((rss.ss_family == AF_INET6 &&
2314 (chBest->ch_Family != AF_INET6 ||
2315 IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2316 &chBest->ch_Addr6) == 0)) ||
2317 chBest->ch_Service == NULL ||
2318 strcmp(sep->se_service, chBest->ch_Service) != 0) {
2319 chBest->ch_Family = sin6->sin6_family;
2320 chBest->ch_Addr6 = sin6->sin6_addr;
2321 if (chBest->ch_Service)
2322 free(chBest->ch_Service);
2323 chBest->ch_Service = strdup(sep->se_service);
2324 bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2325 }
2326#endif
2327 chBest->ch_LTime = t;
2328 {
2329 CTime *ct = &chBest->ch_Times[ticks % CHTSIZE];
2330 if (ct->ct_Ticks != ticks) {
2331 ct->ct_Ticks = ticks;
2332 ct->ct_Count = 0;
2333 }
2334 ++ct->ct_Count;
2335 }
2336 for (i = 0; i < CHTSIZE; ++i) {
2337 CTime *ct = &chBest->ch_Times[i];
2338 if (ct->ct_Ticks <= ticks &&
2339 ct->ct_Ticks >= ticks - CHTSIZE) {
2340 cnt += ct->ct_Count;
2341 }
2342 }
2343 if ((cnt * 60) / (CHTSIZE * CHTGRAN) > sep->se_maxcpm) {
2344 char pname[INET6_ADDRSTRLEN];
2345
2346 getnameinfo((struct sockaddr *)&rss,
2347 ((struct sockaddr *)&rss)->sa_len,
2348 pname, sizeof(pname), NULL, 0,
2147 syslog(LOG_WARNING, "%s/%s:%s/%s loop request REFUSED from %s",
2148 sep->se_service, sep->se_proto,
2149 se2->se_service, se2->se_proto,
2150 pname);
2151 return 1;
2152 }
2153 return 0;
2154}
2155
2156/*
2157 * print_service:
2158 * Dump relevant information to stderr
2159 */
2160void
2161print_service(const char *action, const struct servtab *sep)
2162{
2163 fprintf(stderr,
2164 "%s: %s proto=%s accept=%d max=%d user=%s group=%s"
2165#ifdef LOGIN_CAP
2166 "class=%s"
2167#endif
2168 " builtin=%p server=%s"
2169#ifdef IPSEC
2170 " policy=\"%s\""
2171#endif
2172 "\n",
2173 action, sep->se_service, sep->se_proto,
2174 sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group,
2175#ifdef LOGIN_CAP
2176 sep->se_class,
2177#endif
2178 (void *) sep->se_bi, sep->se_server
2179#ifdef IPSEC
2180 , (sep->se_policy ? sep->se_policy : "")
2181#endif
2182 );
2183}
2184
2185#define CPMHSIZE 256
2186#define CPMHMASK (CPMHSIZE-1)
2187#define CHTGRAN 10
2188#define CHTSIZE 6
2189
2190typedef struct CTime {
2191 unsigned long ct_Ticks;
2192 int ct_Count;
2193} CTime;
2194
2195typedef struct CHash {
2196 union {
2197 struct in_addr c4_Addr;
2198 struct in6_addr c6_Addr;
2199 } cu_Addr;
2200#define ch_Addr4 cu_Addr.c4_Addr
2201#define ch_Addr6 cu_Addr.c6_Addr
2202 int ch_Family;
2203 time_t ch_LTime;
2204 char *ch_Service;
2205 CTime ch_Times[CHTSIZE];
2206} CHash;
2207
2208CHash CHashAry[CPMHSIZE];
2209
2210int
2211cpmip(const struct servtab *sep, int ctrl)
2212{
2213 struct sockaddr_storage rss;
2214 socklen_t rssLen = sizeof(rss);
2215 int r = 0;
2216
2217 /*
2218 * If getpeername() fails, just let it through (if logging is
2219 * enabled the condition is caught elsewhere)
2220 */
2221
2222 if (sep->se_maxcpm > 0 &&
2223 getpeername(ctrl, (struct sockaddr *)&rss, &rssLen) == 0 ) {
2224 time_t t = time(NULL);
2225 int hv = 0xABC3D20F;
2226 int i;
2227 int cnt = 0;
2228 CHash *chBest = NULL;
2229 unsigned int ticks = t / CHTGRAN;
2230 struct sockaddr_in *sin4;
2231#ifdef INET6
2232 struct sockaddr_in6 *sin6;
2233#endif
2234
2235 sin4 = (struct sockaddr_in *)&rss;
2236#ifdef INET6
2237 sin6 = (struct sockaddr_in6 *)&rss;
2238#endif
2239 {
2240 char *p;
2241 int addrlen;
2242
2243 switch (rss.ss_family) {
2244 case AF_INET:
2245 p = (char *)&sin4->sin_addr;
2246 addrlen = sizeof(struct in_addr);
2247 break;
2248#ifdef INET6
2249 case AF_INET6:
2250 p = (char *)&sin6->sin6_addr;
2251 addrlen = sizeof(struct in6_addr);
2252 break;
2253#endif
2254 default:
2255 /* should not happen */
2256 return -1;
2257 }
2258
2259 for (i = 0; i < addrlen; ++i, ++p) {
2260 hv = (hv << 5) ^ (hv >> 23) ^ *p;
2261 }
2262 hv = (hv ^ (hv >> 16));
2263 }
2264 for (i = 0; i < 5; ++i) {
2265 CHash *ch = &CHashAry[(hv + i) & CPMHMASK];
2266
2267 if (rss.ss_family == AF_INET &&
2268 ch->ch_Family == AF_INET &&
2269 sin4->sin_addr.s_addr == ch->ch_Addr4.s_addr &&
2270 ch->ch_Service && strcmp(sep->se_service,
2271 ch->ch_Service) == 0) {
2272 chBest = ch;
2273 break;
2274 }
2275#ifdef INET6
2276 if (rss.ss_family == AF_INET6 &&
2277 ch->ch_Family == AF_INET6 &&
2278 IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2279 &ch->ch_Addr6) != 0 &&
2280 ch->ch_Service && strcmp(sep->se_service,
2281 ch->ch_Service) == 0) {
2282 chBest = ch;
2283 break;
2284 }
2285#endif
2286 if (chBest == NULL || ch->ch_LTime == 0 ||
2287 ch->ch_LTime < chBest->ch_LTime) {
2288 chBest = ch;
2289 }
2290 }
2291 if ((rss.ss_family == AF_INET &&
2292 (chBest->ch_Family != AF_INET ||
2293 sin4->sin_addr.s_addr != chBest->ch_Addr4.s_addr)) ||
2294 chBest->ch_Service == NULL ||
2295 strcmp(sep->se_service, chBest->ch_Service) != 0) {
2296 chBest->ch_Family = sin4->sin_family;
2297 chBest->ch_Addr4 = sin4->sin_addr;
2298 if (chBest->ch_Service)
2299 free(chBest->ch_Service);
2300 chBest->ch_Service = strdup(sep->se_service);
2301 bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2302 }
2303#ifdef INET6
2304 if ((rss.ss_family == AF_INET6 &&
2305 (chBest->ch_Family != AF_INET6 ||
2306 IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2307 &chBest->ch_Addr6) == 0)) ||
2308 chBest->ch_Service == NULL ||
2309 strcmp(sep->se_service, chBest->ch_Service) != 0) {
2310 chBest->ch_Family = sin6->sin6_family;
2311 chBest->ch_Addr6 = sin6->sin6_addr;
2312 if (chBest->ch_Service)
2313 free(chBest->ch_Service);
2314 chBest->ch_Service = strdup(sep->se_service);
2315 bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
2316 }
2317#endif
2318 chBest->ch_LTime = t;
2319 {
2320 CTime *ct = &chBest->ch_Times[ticks % CHTSIZE];
2321 if (ct->ct_Ticks != ticks) {
2322 ct->ct_Ticks = ticks;
2323 ct->ct_Count = 0;
2324 }
2325 ++ct->ct_Count;
2326 }
2327 for (i = 0; i < CHTSIZE; ++i) {
2328 CTime *ct = &chBest->ch_Times[i];
2329 if (ct->ct_Ticks <= ticks &&
2330 ct->ct_Ticks >= ticks - CHTSIZE) {
2331 cnt += ct->ct_Count;
2332 }
2333 }
2334 if ((cnt * 60) / (CHTSIZE * CHTGRAN) > sep->se_maxcpm) {
2335 char pname[INET6_ADDRSTRLEN];
2336
2337 getnameinfo((struct sockaddr *)&rss,
2338 ((struct sockaddr *)&rss)->sa_len,
2339 pname, sizeof(pname), NULL, 0,
2349 NI_NUMERICHOST|NI_WITHSCOPEID);
2340 NI_NUMERICHOST);
2350 r = -1;
2351 syslog(LOG_ERR,
2352 "%s from %s exceeded counts/min (limit %d/min)",
2353 sep->se_service, pname,
2354 sep->se_maxcpm);
2355 }
2356 }
2357 return(r);
2358}
2359
2360static struct conninfo *
2361search_conn(struct servtab *sep, int ctrl)
2362{
2363 struct sockaddr_storage ss;
2364 socklen_t sslen = sizeof(ss);
2365 struct conninfo *conn;
2366 int hv;
2367 char pname[NI_MAXHOST], pname2[NI_MAXHOST];
2368
2369 if (sep->se_maxperip <= 0)
2370 return NULL;
2371
2372 /*
2373 * If getpeername() fails, just let it through (if logging is
2374 * enabled the condition is caught elsewhere)
2375 */
2376 if (getpeername(ctrl, (struct sockaddr *)&ss, &sslen) != 0)
2377 return NULL;
2378
2379 switch (ss.ss_family) {
2380 case AF_INET:
2381 hv = hashval((char *)&((struct sockaddr_in *)&ss)->sin_addr,
2382 sizeof(struct in_addr));
2383 break;
2384#ifdef INET6
2385 case AF_INET6:
2386 hv = hashval((char *)&((struct sockaddr_in6 *)&ss)->sin6_addr,
2387 sizeof(struct in6_addr));
2388 break;
2389#endif
2390 default:
2391 /*
2392 * Since we only support AF_INET and AF_INET6, just
2393 * let other than AF_INET and AF_INET6 through.
2394 */
2395 return NULL;
2396 }
2397
2398 if (getnameinfo((struct sockaddr *)&ss, sslen, pname, sizeof(pname),
2341 r = -1;
2342 syslog(LOG_ERR,
2343 "%s from %s exceeded counts/min (limit %d/min)",
2344 sep->se_service, pname,
2345 sep->se_maxcpm);
2346 }
2347 }
2348 return(r);
2349}
2350
2351static struct conninfo *
2352search_conn(struct servtab *sep, int ctrl)
2353{
2354 struct sockaddr_storage ss;
2355 socklen_t sslen = sizeof(ss);
2356 struct conninfo *conn;
2357 int hv;
2358 char pname[NI_MAXHOST], pname2[NI_MAXHOST];
2359
2360 if (sep->se_maxperip <= 0)
2361 return NULL;
2362
2363 /*
2364 * If getpeername() fails, just let it through (if logging is
2365 * enabled the condition is caught elsewhere)
2366 */
2367 if (getpeername(ctrl, (struct sockaddr *)&ss, &sslen) != 0)
2368 return NULL;
2369
2370 switch (ss.ss_family) {
2371 case AF_INET:
2372 hv = hashval((char *)&((struct sockaddr_in *)&ss)->sin_addr,
2373 sizeof(struct in_addr));
2374 break;
2375#ifdef INET6
2376 case AF_INET6:
2377 hv = hashval((char *)&((struct sockaddr_in6 *)&ss)->sin6_addr,
2378 sizeof(struct in6_addr));
2379 break;
2380#endif
2381 default:
2382 /*
2383 * Since we only support AF_INET and AF_INET6, just
2384 * let other than AF_INET and AF_INET6 through.
2385 */
2386 return NULL;
2387 }
2388
2389 if (getnameinfo((struct sockaddr *)&ss, sslen, pname, sizeof(pname),
2399 NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID) != 0)
2390 NULL, 0, NI_NUMERICHOST) != 0)
2400 return NULL;
2401
2402 LIST_FOREACH(conn, &sep->se_conn[hv], co_link) {
2403 if (getnameinfo((struct sockaddr *)&conn->co_addr,
2404 conn->co_addr.ss_len, pname2, sizeof(pname2), NULL, 0,
2391 return NULL;
2392
2393 LIST_FOREACH(conn, &sep->se_conn[hv], co_link) {
2394 if (getnameinfo((struct sockaddr *)&conn->co_addr,
2395 conn->co_addr.ss_len, pname2, sizeof(pname2), NULL, 0,
2405 NI_NUMERICHOST | NI_WITHSCOPEID) == 0 &&
2396 NI_NUMERICHOST) == 0 &&
2406 strcmp(pname, pname2) == 0)
2407 break;
2408 }
2409
2410 if (conn == NULL) {
2411 if ((conn = malloc(sizeof(struct conninfo))) == NULL) {
2412 syslog(LOG_ERR, "malloc: %m");
2413 exit(EX_OSERR);
2414 }
2415 conn->co_proc = malloc(sep->se_maxperip * sizeof(*conn->co_proc));
2416 if (conn->co_proc == NULL) {
2417 syslog(LOG_ERR, "malloc: %m");
2418 exit(EX_OSERR);
2419 }
2420 memcpy(&conn->co_addr, (struct sockaddr *)&ss, sslen);
2421 conn->co_numchild = 0;
2422 LIST_INSERT_HEAD(&sep->se_conn[hv], conn, co_link);
2423 }
2424
2425 /*
2426 * Since a child process is not invoked yet, we cannot
2427 * determine a pid of a child. So, co_proc and co_numchild
2428 * should be filled leter.
2429 */
2430
2431 return conn;
2432}
2433
2434static int
2435room_conn(struct servtab *sep, struct conninfo *conn)
2436{
2437 char pname[NI_MAXHOST];
2438
2439 if (conn->co_numchild >= sep->se_maxperip) {
2440 getnameinfo((struct sockaddr *)&conn->co_addr,
2441 conn->co_addr.ss_len, pname, sizeof(pname), NULL, 0,
2397 strcmp(pname, pname2) == 0)
2398 break;
2399 }
2400
2401 if (conn == NULL) {
2402 if ((conn = malloc(sizeof(struct conninfo))) == NULL) {
2403 syslog(LOG_ERR, "malloc: %m");
2404 exit(EX_OSERR);
2405 }
2406 conn->co_proc = malloc(sep->se_maxperip * sizeof(*conn->co_proc));
2407 if (conn->co_proc == NULL) {
2408 syslog(LOG_ERR, "malloc: %m");
2409 exit(EX_OSERR);
2410 }
2411 memcpy(&conn->co_addr, (struct sockaddr *)&ss, sslen);
2412 conn->co_numchild = 0;
2413 LIST_INSERT_HEAD(&sep->se_conn[hv], conn, co_link);
2414 }
2415
2416 /*
2417 * Since a child process is not invoked yet, we cannot
2418 * determine a pid of a child. So, co_proc and co_numchild
2419 * should be filled leter.
2420 */
2421
2422 return conn;
2423}
2424
2425static int
2426room_conn(struct servtab *sep, struct conninfo *conn)
2427{
2428 char pname[NI_MAXHOST];
2429
2430 if (conn->co_numchild >= sep->se_maxperip) {
2431 getnameinfo((struct sockaddr *)&conn->co_addr,
2432 conn->co_addr.ss_len, pname, sizeof(pname), NULL, 0,
2442 NI_NUMERICHOST | NI_WITHSCOPEID);
2433 NI_NUMERICHOST);
2443 syslog(LOG_ERR, "%s from %s exceeded counts (limit %d)",
2444 sep->se_service, pname, sep->se_maxperip);
2445 return 0;
2446 }
2447 return 1;
2448}
2449
2450static void
2451addchild_conn(struct conninfo *conn, pid_t pid)
2452{
2453 struct procinfo *proc;
2454
2455 if (conn == NULL)
2456 return;
2457
2458 if ((proc = search_proc(pid, 1)) != NULL) {
2459 if (proc->pr_conn != NULL) {
2460 syslog(LOG_ERR,
2461 "addchild_conn: child already on process list");
2462 exit(EX_OSERR);
2463 }
2464 proc->pr_conn = conn;
2465 }
2466
2467 conn->co_proc[conn->co_numchild++] = proc;
2468}
2469
2470static void
2471reapchild_conn(pid_t pid)
2472{
2473 struct procinfo *proc;
2474 struct conninfo *conn;
2475 int i;
2476
2477 if ((proc = search_proc(pid, 0)) == NULL)
2478 return;
2479 if ((conn = proc->pr_conn) == NULL)
2480 return;
2481 for (i = 0; i < conn->co_numchild; ++i)
2482 if (conn->co_proc[i] == proc) {
2483 conn->co_proc[i] = conn->co_proc[--conn->co_numchild];
2484 break;
2485 }
2486 free_proc(proc);
2487 free_conn(conn);
2488}
2489
2490static void
2491resize_conn(struct servtab *sep, int maxpip)
2492{
2493 struct conninfo *conn;
2494 int i, j;
2495
2496 if (sep->se_maxperip <= 0)
2497 return;
2498 if (maxpip <= 0) {
2499 free_connlist(sep);
2500 return;
2501 }
2502 for (i = 0; i < PERIPSIZE; ++i) {
2503 LIST_FOREACH(conn, &sep->se_conn[i], co_link) {
2504 for (j = maxpip; j < conn->co_numchild; ++j)
2505 free_proc(conn->co_proc[j]);
2506 conn->co_proc = realloc(conn->co_proc,
2507 maxpip * sizeof(*conn->co_proc));
2508 if (conn->co_proc == NULL) {
2509 syslog(LOG_ERR, "realloc: %m");
2510 exit(EX_OSERR);
2511 }
2512 if (conn->co_numchild > maxpip)
2513 conn->co_numchild = maxpip;
2514 }
2515 }
2516}
2517
2518static void
2519free_connlist(struct servtab *sep)
2520{
2521 struct conninfo *conn;
2522 int i, j;
2523
2524 for (i = 0; i < PERIPSIZE; ++i) {
2525 while ((conn = LIST_FIRST(&sep->se_conn[i])) != NULL) {
2526 for (j = 0; j < conn->co_numchild; ++j)
2527 free_proc(conn->co_proc[j]);
2528 conn->co_numchild = 0;
2529 free_conn(conn);
2530 }
2531 }
2532}
2533
2534static void
2535free_conn(struct conninfo *conn)
2536{
2537 if (conn == NULL)
2538 return;
2539 if (conn->co_numchild <= 0) {
2540 LIST_REMOVE(conn, co_link);
2541 free(conn->co_proc);
2542 free(conn);
2543 }
2544}
2545
2546static struct procinfo *
2547search_proc(pid_t pid, int add)
2548{
2549 struct procinfo *proc;
2550 int hv;
2551
2552 hv = hashval((char *)&pid, sizeof(pid));
2553 LIST_FOREACH(proc, &proctable[hv], pr_link) {
2554 if (proc->pr_pid == pid)
2555 break;
2556 }
2557 if (proc == NULL && add) {
2558 if ((proc = malloc(sizeof(struct procinfo))) == NULL) {
2559 syslog(LOG_ERR, "malloc: %m");
2560 exit(EX_OSERR);
2561 }
2562 proc->pr_pid = pid;
2563 proc->pr_conn = NULL;
2564 LIST_INSERT_HEAD(&proctable[hv], proc, pr_link);
2565 }
2566 return proc;
2567}
2568
2569static void
2570free_proc(struct procinfo *proc)
2571{
2572 if (proc == NULL)
2573 return;
2574 LIST_REMOVE(proc, pr_link);
2575 free(proc);
2576}
2577
2578static int
2579hashval(char *p, int len)
2580{
2581 int i, hv = 0xABC3D20F;
2582
2583 for (i = 0; i < len; ++i, ++p)
2584 hv = (hv << 5) ^ (hv >> 23) ^ *p;
2585 hv = (hv ^ (hv >> 16)) & (PERIPSIZE - 1);
2586 return hv;
2587}
2434 syslog(LOG_ERR, "%s from %s exceeded counts (limit %d)",
2435 sep->se_service, pname, sep->se_maxperip);
2436 return 0;
2437 }
2438 return 1;
2439}
2440
2441static void
2442addchild_conn(struct conninfo *conn, pid_t pid)
2443{
2444 struct procinfo *proc;
2445
2446 if (conn == NULL)
2447 return;
2448
2449 if ((proc = search_proc(pid, 1)) != NULL) {
2450 if (proc->pr_conn != NULL) {
2451 syslog(LOG_ERR,
2452 "addchild_conn: child already on process list");
2453 exit(EX_OSERR);
2454 }
2455 proc->pr_conn = conn;
2456 }
2457
2458 conn->co_proc[conn->co_numchild++] = proc;
2459}
2460
2461static void
2462reapchild_conn(pid_t pid)
2463{
2464 struct procinfo *proc;
2465 struct conninfo *conn;
2466 int i;
2467
2468 if ((proc = search_proc(pid, 0)) == NULL)
2469 return;
2470 if ((conn = proc->pr_conn) == NULL)
2471 return;
2472 for (i = 0; i < conn->co_numchild; ++i)
2473 if (conn->co_proc[i] == proc) {
2474 conn->co_proc[i] = conn->co_proc[--conn->co_numchild];
2475 break;
2476 }
2477 free_proc(proc);
2478 free_conn(conn);
2479}
2480
2481static void
2482resize_conn(struct servtab *sep, int maxpip)
2483{
2484 struct conninfo *conn;
2485 int i, j;
2486
2487 if (sep->se_maxperip <= 0)
2488 return;
2489 if (maxpip <= 0) {
2490 free_connlist(sep);
2491 return;
2492 }
2493 for (i = 0; i < PERIPSIZE; ++i) {
2494 LIST_FOREACH(conn, &sep->se_conn[i], co_link) {
2495 for (j = maxpip; j < conn->co_numchild; ++j)
2496 free_proc(conn->co_proc[j]);
2497 conn->co_proc = realloc(conn->co_proc,
2498 maxpip * sizeof(*conn->co_proc));
2499 if (conn->co_proc == NULL) {
2500 syslog(LOG_ERR, "realloc: %m");
2501 exit(EX_OSERR);
2502 }
2503 if (conn->co_numchild > maxpip)
2504 conn->co_numchild = maxpip;
2505 }
2506 }
2507}
2508
2509static void
2510free_connlist(struct servtab *sep)
2511{
2512 struct conninfo *conn;
2513 int i, j;
2514
2515 for (i = 0; i < PERIPSIZE; ++i) {
2516 while ((conn = LIST_FIRST(&sep->se_conn[i])) != NULL) {
2517 for (j = 0; j < conn->co_numchild; ++j)
2518 free_proc(conn->co_proc[j]);
2519 conn->co_numchild = 0;
2520 free_conn(conn);
2521 }
2522 }
2523}
2524
2525static void
2526free_conn(struct conninfo *conn)
2527{
2528 if (conn == NULL)
2529 return;
2530 if (conn->co_numchild <= 0) {
2531 LIST_REMOVE(conn, co_link);
2532 free(conn->co_proc);
2533 free(conn);
2534 }
2535}
2536
2537static struct procinfo *
2538search_proc(pid_t pid, int add)
2539{
2540 struct procinfo *proc;
2541 int hv;
2542
2543 hv = hashval((char *)&pid, sizeof(pid));
2544 LIST_FOREACH(proc, &proctable[hv], pr_link) {
2545 if (proc->pr_pid == pid)
2546 break;
2547 }
2548 if (proc == NULL && add) {
2549 if ((proc = malloc(sizeof(struct procinfo))) == NULL) {
2550 syslog(LOG_ERR, "malloc: %m");
2551 exit(EX_OSERR);
2552 }
2553 proc->pr_pid = pid;
2554 proc->pr_conn = NULL;
2555 LIST_INSERT_HEAD(&proctable[hv], proc, pr_link);
2556 }
2557 return proc;
2558}
2559
2560static void
2561free_proc(struct procinfo *proc)
2562{
2563 if (proc == NULL)
2564 return;
2565 LIST_REMOVE(proc, pr_link);
2566 free(proc);
2567}
2568
2569static int
2570hashval(char *p, int len)
2571{
2572 int i, hv = 0xABC3D20F;
2573
2574 for (i = 0; i < len; ++i, ++p)
2575 hv = (hv << 5) ^ (hv >> 23) ^ *p;
2576 hv = (hv ^ (hv >> 16)) & (PERIPSIZE - 1);
2577 return hv;
2578}