summaryrefslogtreecommitdiffstats
path: root/usr.sbin/inetd
diff options
context:
space:
mode:
authorshin <shin@FreeBSD.org>2000-01-25 14:52:10 +0000
committershin <shin@FreeBSD.org>2000-01-25 14:52:10 +0000
commitfc29f7bcf7236935ba5c171ea553ac7dca533e8c (patch)
tree13e93b815761d57bc661099e5a2b7bcb2882b762 /usr.sbin/inetd
parent4497b0fbabcff52472040173a4ea879ec212ecaa (diff)
downloadFreeBSD-src-fc29f7bcf7236935ba5c171ea553ac7dca533e8c.zip
FreeBSD-src-fc29f7bcf7236935ba5c171ea553ac7dca533e8c.tar.gz
several tcp apps IPv6 update
-inetd -rshd -rlogind -telnetd -rsh -rlogin Reviewed by: freebsd-arch, cvs-committers Obtained from: KAME project
Diffstat (limited to 'usr.sbin/inetd')
-rw-r--r--usr.sbin/inetd/Makefile5
-rw-r--r--usr.sbin/inetd/builtins.c88
-rw-r--r--usr.sbin/inetd/inetd.877
-rw-r--r--usr.sbin/inetd/inetd.c616
-rw-r--r--usr.sbin/inetd/inetd.h27
5 files changed, 702 insertions, 111 deletions
diff --git a/usr.sbin/inetd/Makefile b/usr.sbin/inetd/Makefile
index 0df9755..738bbed 100644
--- a/usr.sbin/inetd/Makefile
+++ b/usr.sbin/inetd/Makefile
@@ -10,7 +10,8 @@ MAINTAINER=des@freebsd.org
COPTS+= -Wall -DLOGIN_CAP
#COPTS+= -DSANITY_CHECK
-DPADD+= ${LIBUTIL} ${LIBWRAP}
-LDADD+= -lutil -lwrap
+CFLAGS+=-DINET6 -DIPSEC
+DPADD+= ${LIBUTIL} ${LIBWRAP} ${LIBIPSEC}
+LDADD+= -lutil -lwrap -lipsec
.include <bsd.prog.mk>
diff --git a/usr.sbin/inetd/builtins.c b/usr.sbin/inetd/builtins.c
index 6ba404c..f05971f 100644
--- a/usr.sbin/inetd/builtins.c
+++ b/usr.sbin/inetd/builtins.c
@@ -57,7 +57,7 @@ extern struct servtab *servtab;
char ring[128];
char *endring;
-int check_loop __P((struct sockaddr_in *, struct servtab *sep));
+int check_loop __P((struct sockaddr *, struct servtab *sep));
void inetd_setproctitle __P((char *, int));
struct biltin biltins[] = {
@@ -111,7 +111,7 @@ chargen_dg(s, sep) /* Character generator */
int s;
struct servtab *sep;
{
- struct sockaddr_in sin;
+ struct sockaddr_storage ss;
static char *rs;
int len, size;
char text[LINESIZ+2];
@@ -121,12 +121,12 @@ chargen_dg(s, sep) /* Character generator */
rs = ring;
}
- size = sizeof(sin);
+ size = sizeof(ss);
if (recvfrom(s, text, sizeof(text), 0,
- (struct sockaddr *)&sin, &size) < 0)
+ (struct sockaddr *)&ss, &size) < 0)
return;
- if (check_loop(&sin, sep))
+ if (check_loop((struct sockaddr *)&ss, sep))
return;
if ((len = endring - rs) >= LINESIZ)
@@ -140,7 +140,7 @@ chargen_dg(s, sep) /* Character generator */
text[LINESIZ] = '\r';
text[LINESIZ + 1] = '\n';
(void) sendto(s, text, sizeof(text), 0,
- (struct sockaddr *)&sin, sizeof(sin));
+ (struct sockaddr *)&ss, sizeof(ss));
}
/* ARGSUSED */
@@ -189,22 +189,22 @@ daytime_dg(s, sep) /* Return human-readable time of day */
{
char buffer[256];
time_t clock;
- struct sockaddr_in sin;
+ struct sockaddr_storage ss;
int size;
clock = time((time_t *) 0);
- size = sizeof(sin);
+ size = sizeof(ss);
if (recvfrom(s, buffer, sizeof(buffer), 0,
- (struct sockaddr *)&sin, &size) < 0)
+ (struct sockaddr *)&ss, &size) < 0)
return;
- if (check_loop(&sin, sep))
+ if (check_loop((struct sockaddr *)&ss, sep))
return;
(void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
(void) sendto(s, buffer, strlen(buffer), 0,
- (struct sockaddr *)&sin, sizeof(sin));
+ (struct sockaddr *)&ss, sizeof(ss));
}
/* ARGSUSED */
@@ -270,18 +270,18 @@ echo_dg(s, sep) /* Echo service -- echo data back */
{
char buffer[BUFSIZE];
int i, size;
- struct sockaddr_in sin;
+ struct sockaddr_storage ss;
- size = sizeof(sin);
+ size = sizeof(ss);
if ((i = recvfrom(s, buffer, sizeof(buffer), 0,
- (struct sockaddr *)&sin, &size)) < 0)
+ (struct sockaddr *)&ss, &size)) < 0)
return;
- if (check_loop(&sin, sep))
+ if (check_loop((struct sockaddr *)&ss, sep))
return;
- (void) sendto(s, buffer, i, 0, (struct sockaddr *)&sin,
- sizeof(sin));
+ (void) sendto(s, buffer, i, 0, (struct sockaddr *)&ss,
+ sizeof(ss));
}
/* ARGSUSED */
@@ -335,6 +335,8 @@ ident_stream(s, sep) /* Ident service (AKA "auth") */
struct utsname un;
struct stat sb;
struct sockaddr_in sin[2];
+ struct sockaddr_in6 sin6[2];
+ struct sockaddr_storage ss[2];
struct ucred uc;
struct timeval tv = {
10,
@@ -345,7 +347,7 @@ ident_stream(s, sep) /* Ident service (AKA "auth") */
char buf[BUFSIZE], *cp = NULL, *p, **av, *osname = NULL, garbage[7];
char *fallback = NULL;
int len, c, fflag = 0, nflag = 0, rflag = 0, argc = 0, usedfallback = 0;
- int gflag = 0, Rflag = 0;
+ int gflag = 0, Rflag = 0, getcredfail = 0;
u_short lport, fport;
inetd_setproctitle(sep->se_service, s);
@@ -434,11 +436,11 @@ ident_stream(s, sep) /* Ident service (AKA "auth") */
iderror(0, 0, s, errno);
osname = un.sysname;
}
- len = sizeof(sin[0]);
- if (getsockname(s, (struct sockaddr *)&sin[0], &len) == -1)
+ len = sizeof(ss[0]);
+ if (getsockname(s, (struct sockaddr *)&ss[0], &len) == -1)
iderror(0, 0, s, errno);
- len = sizeof(sin[1]);
- if (getpeername(s, (struct sockaddr *)&sin[1], &len) == -1)
+ len = sizeof(ss[1]);
+ if (getpeername(s, (struct sockaddr *)&ss[1], &len) == -1)
iderror(0, 0, s, errno);
/*
* We're going to prepare for and execute reception of a
@@ -476,11 +478,35 @@ ident_stream(s, sep) /* Ident service (AKA "auth") */
* arrays have been filled in above via get{peer,sock}name(),
* so right here we are only setting the ports.
*/
- sin[0].sin_port = htons(lport);
- sin[1].sin_port = htons(fport);
+ if (ss[0].ss_family != ss[1].ss_family)
+ iderror(lport, fport, s, errno);
len = sizeof(uc);
- if (sysctlbyname("net.inet.tcp.getcred", &uc, &len, sin,
- sizeof(sin)) == -1) {
+ switch (ss[0].ss_family) {
+ case AF_INET:
+ sin[0] = *(struct sockaddr_in *)&ss[0];
+ sin[0].sin_port = htons(lport);
+ sin[1] = *(struct sockaddr_in *)&ss[1];
+ sin[1].sin_port = htons(fport);
+ if (sysctlbyname("net.inet.tcp.getcred", &uc, &len, sin,
+ sizeof(sin)) == -1)
+ getcredfail = 1;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ sin6[0] = *(struct sockaddr_in6 *)&ss[0];
+ sin6[0].sin6_port = htons(lport);
+ sin6[1] = *(struct sockaddr_in6 *)&ss[1];
+ sin6[1].sin6_port = htons(fport);
+ if (sysctlbyname("net.inet6.tcp6.getcred", &uc, &len, sin6,
+ sizeof(sin6)) == -1)
+ getcredfail = 1;
+ break;
+#endif
+ default: /* should not reach here */
+ getcredfail = 1;
+ break;
+ }
+ if (getcredfail != 0) {
if (fallback == NULL) /* Use a default, if asked to */
iderror(lport, fport, s, errno);
usedfallback = 1;
@@ -611,20 +637,20 @@ machtime_dg(s, sep)
struct servtab *sep;
{
unsigned long result;
- struct sockaddr_in sin;
+ struct sockaddr_storage ss;
int size;
- size = sizeof(sin);
+ size = sizeof(ss);
if (recvfrom(s, (char *)&result, sizeof(result), 0,
- (struct sockaddr *)&sin, &size) < 0)
+ (struct sockaddr *)&ss, &size) < 0)
return;
- if (check_loop(&sin, sep))
+ if (check_loop((struct sockaddr *)&ss, sep))
return;
result = machtime();
(void) sendto(s, (char *) &result, sizeof(result), 0,
- (struct sockaddr *)&sin, sizeof(sin));
+ (struct sockaddr *)&ss, sizeof(ss));
}
/* ARGSUSED */
diff --git a/usr.sbin/inetd/inetd.8 b/usr.sbin/inetd/inetd.8
index 2a3b411..66584d6 100644
--- a/usr.sbin/inetd/inetd.8
+++ b/usr.sbin/inetd/inetd.8
@@ -47,7 +47,7 @@
.Op Fl W
.Op Fl c Ar maximum
.Op Fl C Ar rate
-.Op Fl a Ar address
+.Op Fl a Ar address|hostname
.Op Fl p Ar filename
.Op Fl R Ar rate
.Op Ar configuration file
@@ -101,6 +101,22 @@ Specify the maximum number of times a service can be invoked
in one minute; the default is 256.
.It Fl a
Specify a specific IP address to bind to.
+Or a hostname can also be specified, and then an IP address and/or an
+IPv6 address corresponds to the hostname is used. Usually hostname
+specification is used in conjunction with
+.Xr jail 8 ,
+where the hostname corresponds to a jail environment.
+
+When hostname specification is used and either of IPv4 bind and IPv6
+bind is desired, you need to specify 2 entry for each service, one for
+IPv4 and one for IPv6, in /etc/inetd.conf.
+For example,
+.Bd -literal
+telnet stream tcp4 nowait root /usr/libexec/telnetd telnetd
+telnet stream tcp6 nowait root /usr/libexec/telnetd telnetd
+.Ed
+
+See explanation for protocol field in /etc/inetd.conf for details.
.It Fl p
Specify an alternate file in which to store the process ID.
.El
@@ -221,14 +237,39 @@ Examples might be
.Dq tcp
or
.Dq udp .
+In this case, this entry only accept IPv4 to keep backword
+compatibility.
+The names
+.Dq tcp4 ,
+.Dq udp4
+specialized the entry to IPv4 only.
+The names
+.Dq tcp6 ,
+.Dq udp6
+specialized the entry to IPv6 only.
+The names
+.Dq tcp46 ,
+.Dq udp46
+let the entry accept each of IPv4 and IPv6 via AF_INET6 wildcard binded socket.
If it is desired that the service is reachable via T/TCP, one should
specify
.Dq tcp/ttcp .
+This entry only accept IPv4 to keep backword compatibility.
+The name
+.Dq tcp4/ttcp ,
+specialized the entry to IPv4 only.
+The name
+.Dq tcp6/ttcp ,
+specialized the entry to IPv6 only.
+The name
+.Dq tcp46/ttcp ,
+let the entry accept each of IPv4 and IPv6 via AF_INET6 wildcard binded socket.
Rpc based services are specified with the
.Dq rpc/tcp
or
.Dq rpc/udp
service type.
+Currently only IPv4 is supported for rpc services.
TCPMUX services must use
.Dq tcp .
.Pp
@@ -436,6 +477,9 @@ in
tcpmux stream tcp nowait root internal
.Ed
.Pp
+Or if you wish to provide TCPMUX services also over IPv6, you can
+specify tcp46 or tcp6 instead of tcp above.
+.Pp
When given the
.Fl l
option
@@ -528,6 +572,30 @@ causes
.Nm
to list TCPMUX services in
.Pa inetd.conf .
+.Sh IPSEC
+The implementation includes tiny hack to support IPsec policy setting for
+each of the socket.
+A special form of comment line, starting with
+.Dq Li "#@" ,
+will work as policy specifier.
+The content of the above comment line will be treated as IPsec policy string,
+as described in
+.Xr ipsec_set_policy 3 .
+A
+.Li "#@"
+line will affect all the following lines in
+.Pa inetd.conf ,
+so you may want to reset IPsec policy by using a comment line with
+.Li "#@"
+only
+.Pq with no policy string .
+.Pp
+If invalid IPsec policy string appears on
+.Pa inetd.conf ,
+.Nm
+will leave error message using
+.Xr syslog 3 ,
+and terminates itself.
.Sh "FILES"
.Bl -tag -width /var/run/inetd.pid -compact
.It Pa /etc/inetd.conf
@@ -546,9 +614,14 @@ Here are several example service entries for the various types of services:
.Bd -literal
ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l
ntalk dgram udp wait root /usr/libexec/ntalkd ntalkd
+telnet stream tcp6 nowait root /usr/libexec/telnetd telnetd
+shell stream tcp46 nowait root /usr/libexec/rshd rshd
tcpmux/+date stream tcp nowait guest /bin/date date
tcpmux/phonebook stream tcp nowait guest /usr/local/bin/phonebook phonebook
rstatd/1-3 dgram rpc/udp wait root /usr/libexec/rpc.rstatd rpc.rstatd
+#@ ipsec ah/require
+chargen stream tcp nowait root internal
+#@
.Ed
.Sh "ERROR MESSAGES"
The
@@ -632,6 +705,7 @@ socket but was unable to.
.Sh SEE ALSO
.Xr hosts_access 5 ,
.Xr hosts_options 5 ,
+.Xr ipsec_set_policy 3 ,
.Xr login.conf 5 ,
.Xr passwd 5 ,
.Xr rpc 5 ,
@@ -662,6 +736,7 @@ based services is modeled after that
provided by
.Tn SunOS
4.1.
+IPsec hack was made by KAME project, in 1999.
The
.Tn FreeBSD
TCP Wrappers support first appeared in
diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c
index 3378753..06bad40 100644
--- a/usr.sbin/inetd/inetd.c
+++ b/usr.sbin/inetd/inetd.c
@@ -102,6 +102,13 @@ static const char rcsid[] =
* server program arguments maximum of MAXARGS
*
* Comment lines are indicated by a `#' in column 1.
+ *
+ * #ifdef IPSEC
+ * Comment lines that start with "#@" denote IPsec policy string, as described
+ * in ipsec_set_policy(3). This will affect all the following items in
+ * inetd.conf(8). To reset the policy, just use "#@" line. By default,
+ * there's no IPsec policy.
+ * #endif
*/
#include <sys/param.h>
#include <sys/ioctl.h>
@@ -130,10 +137,23 @@ static const char rcsid[] =
#include <unistd.h>
#include <libutil.h>
#include <sysexits.h>
+#include <ctype.h>
#include "inetd.h"
#include "pathnames.h"
+#ifdef IPSEC
+#include <netinet6/ipsec.h>
+#ifndef IPSEC_POLICY_IPSEC /* no ipsec support on old ipsec */
+#undef IPSEC
+#endif
+#endif
+
+/* wrapper for KAME-special getnameinfo() */
+#ifndef NI_WITHSCOPEID
+#define NI_WITHSCOPEID 0
+#endif
+
#ifndef LIBWRAP_ALLOW_FACILITY
# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
#endif
@@ -193,7 +213,13 @@ int maxchild = MAXCHILD;
int maxcpm = MAXCPM;
struct servent *sp;
struct rpcent *rpc;
-struct in_addr bind_address;
+char *hostname = NULL;
+struct sockaddr_in *bind_sa4;
+int no_v4bind = 1;
+#ifdef INET6
+struct sockaddr_in6 *bind_sa6;
+int no_v6bind = 1;
+#endif
int signalpipe[2];
#ifdef SANITY_CHECK
int nsock;
@@ -248,8 +274,20 @@ main(argc, argv, envp)
int denied;
char *service = NULL;
char *pnm;
- struct sockaddr_in peer;
+ union {
+ struct sockaddr peer_un;
+ struct sockaddr_in peer_un4;
+ struct sockaddr_in6 peer_un6;
+ struct sockaddr_storage peer_max;
+ } p_un;
+#define peer p_un.peer_un
+#define peer4 p_un.peer_un4
+#define peer6 p_un.peer_un6
+#define peermax p_un.peer_max
int i;
+ struct addrinfo hints, *res;
+ char *servname;
+ int error;
#ifdef OLD_SETPROCTITLE
@@ -263,7 +301,6 @@ main(argc, argv, envp)
openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
- bind_address.s_addr = htonl(INADDR_ANY);
while ((ch = getopt(argc, argv, "dlwWR:a:c:C:p:")) != -1)
switch(ch) {
case 'd':
@@ -286,11 +323,7 @@ main(argc, argv, envp)
"-C %s: bad value for maximum children/minute");
break;
case 'a':
- if (!inet_aton(optarg, &bind_address)) {
- syslog(LOG_ERR,
- "-a %s: invalid IP address", optarg);
- exit(EX_USAGE);
- }
+ hostname = optarg;
break;
case 'p':
pid_file = optarg;
@@ -309,6 +342,66 @@ main(argc, argv, envp)
" [-p pidfile] [conf-file]");
exit(EX_USAGE);
}
+ /*
+ * Initialize Bind Addrs.
+ * When hostname is NULL, wild card bind addrs are obtained from
+ * getaddrinfo(). But getaddrinfo() requires at least one of
+ * hostname or servname is non NULL.
+ * So when hostname is NULL, set dummy value to servname.
+ */
+ servname = (hostname == NULL) ? "discard" /* dummy */ : NULL;
+
+ bzero(&hints, sizeof(struct addrinfo));
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = AF_UNSPEC;
+ error = getaddrinfo(hostname, servname, &hints, &res);
+ if (error != 0) {
+ syslog(LOG_ERR, "-a %s: %s", hostname, gai_strerror(error));
+ if (error == EAI_SYSTEM)
+ syslog(LOG_ERR, "%s", strerror(errno));
+ exit(EX_USAGE);
+ }
+ do {
+ if (res->ai_addr == NULL) {
+ syslog(LOG_ERR, "-a %s: getaddrinfo failed", hostname);
+ exit(EX_USAGE);
+ }
+ switch (res->ai_addr->sa_family) {
+ case AF_INET:
+ if (no_v4bind == 0)
+ continue;
+ bind_sa4 = (struct sockaddr_in *)res->ai_addr;
+ /* init port num in case servname is dummy */
+ bind_sa4->sin_port = 0;
+ no_v4bind = 0;
+ continue;
+#ifdef INET6
+ case AF_INET6:
+ if (no_v6bind == 0)
+ continue;
+ bind_sa6 = (struct sockaddr_in6 *)res->ai_addr;
+ /* init port num in case servname is dummy */
+ bind_sa6->sin6_port = 0;
+ no_v6bind = 0;
+ continue;
+#endif
+ }
+ if (no_v4bind == 0
+#ifdef INET6
+ && no_v6bind == 0
+#endif
+ )
+ break;
+ } while ((res = res->ai_next) != NULL);
+ if (no_v4bind != 0
+#ifdef INET6
+ && no_v6bind != 0
+#endif
+ ) {
+ syslog(LOG_ERR, "-a %s: unknown address family", hostname);
+ exit(EX_USAGE);
+ }
+
argc -= optind;
argv += optind;
@@ -457,18 +550,33 @@ main(argc, argv, envp)
} else
ctrl = sep->se_fd;
if (log && !ISWRAP(sep)) {
+ char pname[INET6_ADDRSTRLEN];
pnm = "unknown";
- i = sizeof peer;
+ i = sizeof peermax;
if (getpeername(ctrl, (struct sockaddr *)
- &peer, &i)) {
- i = sizeof peer;
+ &peermax, &i)) {
+ i = sizeof peermax;
if (recvfrom(ctrl, buf, sizeof(buf),
MSG_PEEK,
- (struct sockaddr *)&peer, &i) >= 0)
- pnm = inet_ntoa(peer.sin_addr);
+ (struct sockaddr *)&peermax,
+ &i) >= 0) {
+ getnameinfo((struct sockaddr *)&peermax,
+ sizeof(peermax),
+ pname, sizeof(pname),
+ NULL, 0,
+ NI_NUMERICHOST|
+ NI_WITHSCOPEID);
+ pnm = pname;
+ }
+ } else {
+ getnameinfo((struct sockaddr *)&peermax,
+ sizeof(peermax),
+ pname, sizeof(pname),
+ NULL, 0,
+ NI_NUMERICHOST|
+ NI_WITHSCOPEID);
+ pnm = pname;
}
- else
- pnm = inet_ntoa(peer.sin_addr);
syslog(LOG_INFO,"%s from %s", sep->se_service, pnm);
}
(void) sigblock(SIGBLOCK);
@@ -783,13 +891,18 @@ void config()
#endif
for (sep = servtab; sep; sep = sep->se_next)
if (strcmp(sep->se_service, new->se_service) == 0 &&
- strcmp(sep->se_proto, new->se_proto) == 0)
+ strcmp(sep->se_proto, new->se_proto) == 0 &&
+ sep->se_family == new->se_family)
break;
if (sep != 0) {
int i;
#define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
omask = sigblock(SIGBLOCK);
+ if (sep->se_nomapped != new->se_nomapped) {
+ sep->se_nomapped = new->se_nomapped;
+ sep->se_reset = 1;
+ }
/* copy over outstanding child pids */
if (sep->se_maxchild && new->se_maxchild) {
new->se_numchild = sep->se_numchild;
@@ -823,6 +936,10 @@ void config()
SWAP(sep->se_server_name, new->se_server_name);
for (i = 0; i < MAXARGV; i++)
SWAP(sep->se_argv[i], new->se_argv[i]);
+#ifdef IPSEC
+ SWAP(sep->se_policy, new->se_policy);
+ ipsecsetup(sep);
+#endif
sigsetmask(omask);
freeconfig(new);
if (debug)
@@ -837,21 +954,63 @@ void config()
sep->se_fd = -1;
continue;
}
+ switch (sep->se_family) {
+ case AF_INET:
+ if (no_v4bind != 0) {
+ sep->se_fd = -1;
+ continue;
+ }
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (no_v6bind != 0) {
+ sep->se_fd = -1;
+ continue;
+ }
+ break;
+#endif
+ }
if (!sep->se_rpc) {
sp = getservbyname(sep->se_service, sep->se_proto);
if (sp == 0) {
syslog(LOG_ERR, "%s/%s: unknown service",
- sep->se_service, sep->se_proto);
+ sep->se_service, sep->se_proto);
sep->se_checked = 0;
continue;
}
- if (sp->s_port != sep->se_ctrladdr.sin_port) {
- sep->se_ctrladdr.sin_family = AF_INET;
- sep->se_ctrladdr.sin_addr = bind_address;
- sep->se_ctrladdr.sin_port = sp->s_port;
- if (sep->se_fd >= 0)
- close_sep(sep);
+ switch (sep->se_family) {
+ case AF_INET:
+ if (sep->se_ctladdrinitok == 0) {
+ memcpy(&sep->se_ctrladdr4, bind_sa4,
+ sizeof(sep->se_ctrladdr4));
+ sep->se_ctrladdr_size =
+ sizeof(sep->se_ctrladdr4);
+ }
+ if (sp->s_port != sep->se_ctrladdr4.sin_port) {
+ sep->se_ctrladdr4.sin_port =
+ sp->s_port;
+ sep->se_reset = 1;
+ }
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (sep->se_ctladdrinitok == 0) {
+ memcpy(&sep->se_ctrladdr6, bind_sa6,
+ sizeof(sep->se_ctrladdr6));
+ sep->se_ctrladdr_size =
+ sizeof(sep->se_ctrladdr6);
+ }
+ if (sp->s_port !=
+ sep->se_ctrladdr6.sin6_port) {
+ sep->se_ctrladdr6.sin6_port =
+ sp->s_port;
+ sep->se_reset = 1;
+ }
+ break;
+#endif
}
+ if (sep->se_reset != 0 && sep->se_fd >= 0)
+ close_sep(sep);
} else {
rpc = getrpcbyname(sep->se_service);
if (rpc == 0) {
@@ -950,7 +1109,7 @@ setup(sep)
{
int on = 1;
- if ((sep->se_fd = socket(AF_INET, sep->se_socktype, 0)) < 0) {
+ if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
if (debug)
warn("socket failed on %s/%s",
sep->se_service, sep->se_proto);
@@ -969,13 +1128,38 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
if (turnon(sep->se_fd, SO_PRIVSTATE) < 0)
syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m");
#endif
+ /* tftpd opens a new connection then needs more infos */
+ if ((sep->se_family == AF_INET6) &&
+ (strcmp(sep->se_proto, "udp") == 0) &&
+ (sep->se_accept == 0) &&
+ (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_PKTINFO,
+ (char *)&on, sizeof (on)) < 0))
+ syslog(LOG_ERR, "setsockopt (IPV6_RECVPKTINFO): %m");
+#ifdef IPV6_BINDV6ONLY
+ if ((sep->se_family == AF_INET6) &&
+ (sep->se_nomapped != 0) &&
+ (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_BINDV6ONLY,
+ (char *)&on, sizeof (on)) < 0))
+ syslog(LOG_ERR, "setsockopt (IPV6_BINDV6ONLY): %m");
+#endif /* IPV6_BINDV6ONLY */
#undef turnon
if (sep->se_type == TTCP_TYPE)
if (setsockopt(sep->se_fd, IPPROTO_TCP, TCP_NOPUSH,
(char *)&on, sizeof (on)) < 0)
syslog(LOG_ERR, "setsockopt (TCP_NOPUSH): %m");
+#ifdef IPV6_FAITH
+ if (sep->se_type == FAITH_TYPE) {
+ if (setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_FAITH, &on,
+ sizeof(on)) < 0) {
+ syslog(LOG_ERR, "setsockopt (IPV6_FAITH): %m");
+ }
+ }
+#endif
+#ifdef IPSEC
+ ipsecsetup(sep);
+#endif
if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
- sizeof (sep->se_ctrladdr)) < 0) {
+ sep->se_ctrladdr_size) < 0) {
if (debug)
warn("bind failed on %s/%s",
sep->se_service, sep->se_proto);
@@ -990,8 +1174,16 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
return;
}
if (sep->se_rpc) {
- int i, len = sizeof(struct sockaddr);
+ int i, len = sep->se_ctrladdr_size;
+ if (sep->se_family != AF_INET) {
+ syslog(LOG_ERR,
+ "%s/%s: unsupported address family for rpc",
+ sep->se_service, sep->se_proto);
+ (void) close(sep->se_fd);
+ sep->se_fd = -1;
+ return;
+ }
if (getsockname(sep->se_fd,
(struct sockaddr*)&sep->se_ctrladdr, &len) < 0){
syslog(LOG_ERR, "%s/%s: getsockname: %m",
@@ -1007,9 +1199,8 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
pmap_set(sep->se_rpc_prog, i,
(sep->se_socktype == SOCK_DGRAM)
? IPPROTO_UDP : IPPROTO_TCP,
- ntohs(sep->se_ctrladdr.sin_port));
+ ntohs(sep->se_ctrladdr4.sin_port));
}
-
}
if (sep->se_socktype == SOCK_STREAM)
listen(sep->se_fd, 64);
@@ -1020,6 +1211,80 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
}
}
+#ifdef IPSEC
+void
+ipsecsetup(sep)
+ struct servtab *sep;
+{
+ char *buf;
+ char *policy_in = NULL;
+ char *policy_out = NULL;
+ int level;
+ int opt;
+
+ switch (sep->se_family) {
+ case AF_INET:
+ level = IPPROTO_IP;
+ opt = IP_IPSEC_POLICY;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ level = IPPROTO_IPV6;
+ opt = IPV6_IPSEC_POLICY;
+ break;
+#endif
+ default:
+ return;
+ }
+
+ if (!sep->se_policy || sep->se_policy[0] == '\0') {
+ policy_in = "in entrust";
+ policy_out = "out entrust";
+ } else {
+ if (!strncmp("in", sep->se_policy, 2))
+ policy_in = sep->se_policy;
+ else if (!strncmp("out", sep->se_policy, 3))
+ policy_out = sep->se_policy;
+ else {
+ syslog(LOG_ERR, "invalid security policy \"%s\"",
+ sep->se_policy);
+ return;
+ }
+ }
+
+ if (policy_in != NULL) {
+ buf = ipsec_set_policy(policy_in, strlen(policy_in));
+ if (buf != NULL) {
+ if (setsockopt(sep->se_fd, level, opt,
+ buf, ipsec_get_policylen(buf)) < 0) {
+ syslog(LOG_ERR,
+ "%s/%s: ipsec initialization failed; %s",
+ sep->se_service, sep->se_proto,
+ policy_in);
+ }
+ free(buf);
+ } else
+ syslog(LOG_ERR, "invalid security policy \"%s\"",
+ policy_in);
+ }
+ if (policy_out != NULL) {
+ buf = ipsec_set_policy(policy_out, strlen(policy_out));
+ if (buf != NULL) {
+ if (setsockopt(sep->se_fd, level, opt,
+ buf, ipsec_get_policylen(buf)) < 0) {
+ syslog(LOG_ERR,
+ "%s/%s: ipsec initialization failed; %s",
+ sep->se_service, sep->se_proto,
+ policy_out);
+ }
+ free(buf);
+ } else
+ syslog(LOG_ERR, "invalid security policy \"%s\"",
+ policy_out);
+ }
+}
+#endif
+
/*
* Finish with a service and its socket.
*/
@@ -1173,10 +1438,42 @@ getconfigent()
char *versp;
static char TCPMUX_TOKEN[] = "tcpmux/";
#define MUX_LEN (sizeof(TCPMUX_TOKEN)-1)
+#ifdef IPSEC
+ char *policy = NULL;
+#endif
+ int v4bind = 0;
+#ifdef INET6
+ int v6bind = 0;
+#endif
more:
- while ((cp = nextline(fconfig)) && (*cp == '#' || *cp == '\0'))
- ;
+ while ((cp = nextline(fconfig)) != NULL) {
+#ifdef IPSEC
+ /* lines starting with #@ is not a comment, but the policy */
+ if (cp[0] == '#' && cp[1] == '@') {
+ char *p;
+ for (p = cp + 2; p && *p && isspace(*p); p++)
+ ;
+ if (*p == '\0') {
+ if (policy)
+ free(policy);
+ policy = NULL;
+ } else if (ipsec_get_policylen(p) >= 0) {
+ if (policy)
+ free(policy);
+ policy = newstr(p);
+ } else {
+ syslog(LOG_ERR,
+ "%s: invalid ipsec policy \"%s\"",
+ CONFIG, p);
+ exit(EX_CONFIG);
+ }
+ }
+#endif
+ if (*cp == '#' || *cp == '\0')
+ continue;
+ break;
+ }
if (cp == NULL)
return ((struct servtab *)0);
/*
@@ -1216,21 +1513,29 @@ more:
sep->se_socktype = -1;
arg = sskip(&cp);
- if (strcmp(arg, "tcp/ttcp") == 0) {
- sep->se_type = TTCP_TYPE;
- sep->se_proto = newstr("tcp");
- } else {
+ if (strncmp(arg, "tcp", 3) == 0) {
+ sep->se_proto = newstr(strsep(&arg, "/"));
+ if (arg != NULL) {
+ if (strcmp(arg, "ttcp") == 0)
+ sep->se_type = TTCP_TYPE;
+ else if (strcmp(arg, "faith") == 0)
+ sep->se_type = FAITH_TYPE;
+ }
+ } else
sep->se_proto = newstr(arg);
- }
if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
+ if (sep->se_family != AF_INET) {
+ syslog(LOG_ERR, "IPv6 for RPC is not supported yet");
+ freeconfig(sep);
+ goto more;
+ }
memmove(sep->se_proto, sep->se_proto + 4,
strlen(sep->se_proto) + 1 - 4);
sep->se_rpc = 1;
sep->se_rpc_prog = sep->se_rpc_lowvers =
sep->se_rpc_lowvers = 0;
- sep->se_ctrladdr.sin_family = AF_INET;
- sep->se_ctrladdr.sin_port = 0;
- sep->se_ctrladdr.sin_addr = bind_address;
+ memcpy(&sep->se_ctrladdr4, bind_sa4,
+ sizeof(sep->se_ctrladdr4));
if ((versp = rindex(sep->se_service, '/'))) {
*versp++ = '\0';
switch (sscanf(versp, "%d-%d",
@@ -1255,6 +1560,64 @@ more:
sep->se_rpc_highvers = 1;
}
}
+ sep->se_nomapped = 0;
+ while (isdigit(sep->se_proto[strlen(sep->se_proto) - 1])) {
+#ifdef INET6
+ if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') {
+ if (no_v6bind != 0) {
+ syslog(LOG_INFO, "IPv6 bind is ignored for %s",
+ sep->se_service);
+ freeconfig(sep);
+ goto more;
+ }
+ sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
+ v6bind = 1;
+ continue;
+ }
+#endif
+ if (sep->se_proto[strlen(sep->se_proto) - 1] == '4') {
+ sep->se_proto[strlen(sep->se_proto) - 1] = '\0';
+ v4bind = 1;
+ continue;
+ }
+ /* illegal version num */
+ syslog(LOG_ERR, "bad IP version for %s", sep->se_proto);
+ freeconfig(sep);
+ goto more;
+ }
+#ifdef INET6
+ if (v6bind != 0) {
+ sep->se_family = AF_INET6;
+ if (v4bind == 0 || no_v4bind != 0)
+ sep->se_nomapped = 1;
+ }
+#endif
+ else { /* default to v4 bind if not v6 bind */
+ if (no_v4bind != 0) {
+ syslog(LOG_INFO, "IPv4 bind is ignored for %s",
+ sep->se_service);
+ freeconfig(sep);
+ goto more;
+ }
+ sep->se_family = AF_INET;
+ }
+ /* init ctladdr */
+ switch(sep->se_family) {
+ case AF_INET:
+ memcpy(&sep->se_ctrladdr4, bind_sa4,
+ sizeof(sep->se_ctrladdr4));
+ sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr4);
+ sep->se_ctladdrinitok = 1;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ memcpy(&sep->se_ctrladdr6, bind_sa6,
+ sizeof(sep->se_ctrladdr6));
+ sep->se_ctrladdr_size = sizeof(sep->se_ctrladdr6);
+ sep->se_ctladdrinitok = 1;
+ break;
+#endif
+ }
arg = sskip(&cp);
if (!strncmp(arg, "wait", 4))
sep->se_accept = 0;
@@ -1372,6 +1735,9 @@ more:
}
while (argc <= MAXARGV)
sep->se_argv[argc++] = NULL;
+#ifdef IPSEC
+ sep->se_policy = policy ? newstr(policy) : NULL;
+#endif
return (sep);
}
@@ -1400,6 +1766,10 @@ freeconfig(cp)
for (i = 0; i < MAXARGV; i++)
if (cp->se_argv[i])
free(cp->se_argv[i]);
+#ifdef IPSEC
+ if (cp->se_policy)
+ free(cp->se_policy);
+#endif
}
@@ -1490,14 +1860,16 @@ inetd_setproctitle(a, s)
{
int size;
char *cp;
- struct sockaddr_in sin;
- char buf[80];
+ struct sockaddr_storage ss;
+ char buf[80], pbuf[INET6_ADDRSTRLEN];
cp = Argv[0];
- size = sizeof(sin);
- if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
- (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr));
- else
+ size = sizeof(ss);
+ if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
+ getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf),
+ NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID);
+ (void) sprintf(buf, "-%s [%s]", a, pbuf);
+ } else
(void) sprintf(buf, "-%s", a);
strncpy(cp, buf, LastArg - cp);
cp += strlen(cp);
@@ -1511,13 +1883,15 @@ inetd_setproctitle(a, s)
int s;
{
int size;
- struct sockaddr_in sin;
- char buf[80];
-
- size = sizeof(sin);
- if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
- (void) sprintf(buf, "%s [%s]", a, inet_ntoa(sin.sin_addr));
- else
+ struct sockaddr_storage ss;
+ char buf[80], pbuf[INET6_ADDRSTRLEN];
+
+ size = sizeof(ss);
+ if (getpeername(s, (struct sockaddr *)&ss, &size) == 0) {
+ getnameinfo((struct sockaddr *)&ss, size, pbuf, sizeof(pbuf),
+ NULL, 0, NI_NUMERICHOST|NI_WITHSCOPEID);
+ (void) sprintf(buf, "%s [%s]", a, pbuf);
+ } else
(void) sprintf(buf, "%s", a);
setproctitle("%s", buf);
}
@@ -1528,24 +1902,41 @@ inetd_setproctitle(a, s)
* Internet services provided internally by inetd:
*/
-int check_loop(sin, sep)
- struct sockaddr_in *sin;
+int check_loop(sa, sep)
+ struct sockaddr *sa;
struct servtab *sep;
{
struct servtab *se2;
+ char pname[INET6_ADDRSTRLEN];
for (se2 = servtab; se2; se2 = se2->se_next) {
if (!se2->se_bi || se2->se_socktype != SOCK_DGRAM)
continue;
- if (sin->sin_port == se2->se_ctrladdr.sin_port) {
- syslog(LOG_WARNING,
- "%s/%s:%s/%s loop request REFUSED from %s",
- sep->se_service, sep->se_proto,
- se2->se_service, se2->se_proto,
- inet_ntoa(sin->sin_addr));
- return 1;
+ switch (se2->se_family) {
+ case AF_INET:
+ if (((struct sockaddr_in *)sa)->sin_port ==
+ se2->se_ctrladdr4.sin_port)
+ goto isloop;
+ continue;
+#ifdef INET6
+ case AF_INET6:
+ if (((struct sockaddr_in *)sa)->sin_port ==
+ se2->se_ctrladdr4.sin_port)
+ goto isloop;
+ continue;
+#endif
+ default:
+ continue;
}
+ isloop:
+ getnameinfo(sa, sa->sa_len, pname, sizeof(pname), NULL, 0,
+ NI_NUMERICHOST|NI_WITHSCOPEID);
+ syslog(LOG_WARNING, "%s/%s:%s/%s loop request REFUSED from %s",
+ sep->se_service, sep->se_proto,
+ se2->se_service, se2->se_proto,
+ pname);
+ return 1;
}
return 0;
}
@@ -1560,17 +1951,25 @@ print_service(action, sep)
struct servtab *sep;
{
fprintf(stderr,
+ "%s: %s proto=%s accept=%d max=%d user=%s group=%s"
#ifdef LOGIN_CAP
- "%s: %s proto=%s accept=%d max=%d user=%s group=%s class=%s builtin=%p server=%s\n",
-#else
- "%s: %s proto=%s accept=%d max=%d user=%s group=%s builtin=%p server=%s\n",
+ "class=%s"
+#endif
+ " builtin=%p server=%s"
+#ifdef IPSEC
+ " policy=\"%s\""
#endif
+ "\n",
action, sep->se_service, sep->se_proto,
sep->se_accept, sep->se_maxchild, sep->se_user, sep->se_group,
#ifdef LOGIN_CAP
sep->se_class,
#endif
- (void *) sep->se_bi, sep->se_server);
+ (void *) sep->se_bi, sep->se_server
+#ifdef IPSEC
+ , (sep->se_policy ? sep->se_policy : "")
+#endif
+ );
}
#define CPMHSIZE 256
@@ -1584,7 +1983,13 @@ typedef struct CTime {
} CTime;
typedef struct CHash {
- struct in_addr ch_Addr;
+ union {
+ struct in_addr c4_Addr;
+ struct in6_addr c6_Addr;
+ } cu_Addr;
+#define ch_Addr4 cu_Addr.c4_Addr
+#define ch_Addr6 cu_Addr.c6_Addr
+ int ch_Family;
time_t ch_LTime;
char *ch_Service;
CTime ch_Times[CHTSIZE];
@@ -1597,8 +2002,8 @@ cpmip(sep, ctrl)
struct servtab *sep;
int ctrl;
{
- struct sockaddr_in rsin;
- int rsinLen = sizeof(rsin);
+ struct sockaddr_storage rss;
+ int rssLen = sizeof(rss);
int r = 0;
/*
@@ -1607,21 +2012,43 @@ cpmip(sep, ctrl)
*/
if (sep->se_maxcpm > 0 &&
- getpeername(ctrl, (struct sockaddr *)&rsin, &rsinLen) == 0 ) {
+ getpeername(ctrl, (struct sockaddr *)&rss, &rssLen) == 0 ) {
time_t t = time(NULL);
int hv = 0xABC3D20F;
int i;
int cnt = 0;
CHash *chBest = NULL;
unsigned int ticks = t / CHTGRAN;
+ struct sockaddr_in *sin;
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+#endif
+ sin = (struct sockaddr_in *)&rss;
+#ifdef INET6
+ sin6 = (struct sockaddr_in6 *)&rss;
+#endif
{
char *p;
- int i;
+ int i, addrlen;
- for (i = 0, p = (char *)&rsin.sin_addr;
- i < sizeof(rsin.sin_addr);
- ++i, ++p) {
+ switch (rss.ss_family) {
+ case AF_INET:
+ p = (char *)&sin->sin_addr;
+ addrlen = sizeof(struct in_addr);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ p = (char *)&sin6->sin6_addr;
+ addrlen = sizeof(struct in6_addr);
+ break;
+#endif
+ default:
+ /* should not happen */
+ return -1;
+ }
+
+ for (i = 0; i < addrlen; ++i, ++p) {
hv = (hv << 5) ^ (hv >> 23) ^ *p;
}
hv = (hv ^ (hv >> 16));
@@ -1629,26 +2056,57 @@ cpmip(sep, ctrl)
for (i = 0; i < 5; ++i) {
CHash *ch = &CHashAry[(hv + i) & CPMHMASK];
- if (rsin.sin_addr.s_addr == ch->ch_Addr.s_addr &&
+ if (rss.ss_family == AF_INET &&
+ ch->ch_Family == AF_INET &&
+ sin->sin_addr.s_addr == ch->ch_Addr4.s_addr &&
ch->ch_Service && strcmp(sep->se_service,
ch->ch_Service) == 0) {
chBest = ch;
break;
}
+#ifdef INET6
+ if (rss.ss_family == AF_INET6 &&
+ ch->ch_Family == AF_INET6 &&
+ IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
+ &ch->ch_Addr6) != 0 &&
+ ch->ch_Service && strcmp(sep->se_service,
+ ch->ch_Service) == 0) {
+ chBest = ch;
+ break;
+ }
+#endif
if (chBest == NULL || ch->ch_LTime == 0 ||
ch->ch_LTime < chBest->ch_LTime) {
chBest = ch;
}
}
- if (rsin.sin_addr.s_addr != chBest->ch_Addr.s_addr ||
+ if ((rss.ss_family == AF_INET &&
+ (chBest->ch_Family != AF_INET ||
+ sin->sin_addr.s_addr != chBest->ch_Addr4.s_addr)) ||
chBest->ch_Service == NULL ||
strcmp(sep->se_service, chBest->ch_Service) != 0) {
- chBest->ch_Addr = rsin.sin_addr;
+ chBest->ch_Family = sin->sin_family;
+ chBest->ch_Addr4 = sin->sin_addr;
if (chBest->ch_Service)
free(chBest->ch_Service);
chBest->ch_Service = strdup(sep->se_service);
bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
}
+#ifdef INET6
+ if ((rss.ss_family == AF_INET6 &&
+ (chBest->ch_Family != AF_INET6 ||
+ IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
+ &chBest->ch_Addr6) == 0)) ||
+ chBest->ch_Service == NULL ||
+ strcmp(sep->se_service, chBest->ch_Service) != 0) {
+ chBest->ch_Family = sin6->sin6_family;
+ chBest->ch_Addr6 = sin6->sin6_addr;
+ if (chBest->ch_Service)
+ free(chBest->ch_Service);
+ chBest->ch_Service = strdup(sep->se_service);
+ bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
+ }
+#endif
chBest->ch_LTime = t;
{
CTime *ct = &chBest->ch_Times[ticks % CHTSIZE];
@@ -1666,10 +2124,16 @@ cpmip(sep, ctrl)
}
}
if (cnt * (CHTSIZE * CHTGRAN) / 60 > sep->se_maxcpm) {
+ char pname[INET6_ADDRSTRLEN];
+
+ getnameinfo((struct sockaddr *)&rss,
+ ((struct sockaddr *)&rss)->sa_len,
+ pname, sizeof(pname), NULL, 0,
+ NI_NUMERICHOST|NI_WITHSCOPEID);
r = -1;
syslog(LOG_ERR,
"%s from %s exceeded counts/min (limit %d/min)",
- sep->se_service, inet_ntoa(rsin.sin_addr),
+ sep->se_service, pname,
sep->se_maxcpm);
}
}
diff --git a/usr.sbin/inetd/inetd.h b/usr.sbin/inetd/inetd.h
index ab78c73..f956c1a 100644
--- a/usr.sbin/inetd/inetd.h
+++ b/usr.sbin/inetd/inetd.h
@@ -47,6 +47,7 @@
#define MUX_TYPE 1
#define MUXPLUS_TYPE 2
#define TTCP_TYPE 3
+#define FAITH_TYPE 4
#define ISMUX(sep) (((sep)->se_type == MUX_TYPE) || \
((sep)->se_type == MUXPLUS_TYPE))
#define ISMUXPLUS(sep) ((sep)->se_type == MUXPLUS_TYPE)
@@ -55,6 +56,7 @@
struct servtab {
char *se_service; /* name of service */
int se_socktype; /* type of socket to use */
+ int se_family; /* address family */
char *se_proto; /* protocol used */
int se_maxchild; /* max number of children */
int se_maxcpm; /* max connects per IP per minute */
@@ -70,8 +72,19 @@ struct servtab {
char *se_server_name; /* server program without path */
#define MAXARGV 20
char *se_argv[MAXARGV+1]; /* program arguments */
+#ifdef IPSEC
+ char *se_policy; /* IPsec poilcy string */
+#endif
int se_fd; /* open descriptor */
- struct sockaddr_in se_ctrladdr;/* bound address */
+ union { /* bound address */
+ struct sockaddr se_un_ctrladdr;
+ struct sockaddr_in se_un_ctrladdr4;
+ struct sockaddr_in6 se_un_ctrladdr6;
+ } se_un;
+#define se_ctrladdr se_un.se_un_ctrladdr
+#define se_ctrladdr4 se_un.se_un_ctrladdr4
+#define se_ctrladdr6 se_un.se_un_ctrladdr6
+ int se_ctrladdr_size;
u_char se_type; /* type: normal, mux, or mux+ */
u_char se_checked; /* looked at during merge */
u_char se_accept; /* i.e., wait/nowait mode */
@@ -82,8 +95,17 @@ struct servtab {
int se_count; /* number started since se_time */
struct timeval se_time; /* start of se_count */
struct servtab *se_next;
+ struct se_flags {
+ u_int se_nomapped : 1;
+ u_int se_ctladdrinitok : 1;
+ u_int se_reset : 1;
+ } se_flags;
};
+#define se_nomapped se_flags.se_nomapped
+#define se_ctladdrinitok se_flags.se_ctladdrinitok
+#define se_reset se_flags.se_reset
+
void chargen_dg __P((int, struct servtab *));
void chargen_stream __P((int, struct servtab *));
void close_sep __P((struct servtab *));
@@ -117,6 +139,9 @@ void flag_retry __P((int));
void retry __P((void));
int setconfig __P((void));
void setup __P((struct servtab *));
+#ifdef IPSEC
+void ipsecsetup __P((struct servtab *));
+#endif
char *sskip __P((char **));
char *skip __P((char **));
struct servtab *tcpmux __P((int));
OpenPOWER on IntegriCloud