summaryrefslogtreecommitdiff
path: root/usr.sbin/inetd
diff options
context:
space:
mode:
authordenny <denny@cvs.openbsd.org>1997-06-17 05:26:23 +0000
committerdenny <denny@cvs.openbsd.org>1997-06-17 05:26:23 +0000
commit173ecdc0f97ef47f48bcb1b4276974e1e990f7df (patch)
tree3b0be20787e881abeb9b1cdcae5df6408a9140b1 /usr.sbin/inetd
parentd9ca1896a1a2d718477658ae3fb0423025bbb969 (diff)
Add per-interface binding, based on der Mouse's code in netbsd.
Diffstat (limited to 'usr.sbin/inetd')
-rw-r--r--usr.sbin/inetd/inetd.c119
1 files changed, 114 insertions, 5 deletions
diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c
index d6a18881c14..a6ef9980a7f 100644
--- a/usr.sbin/inetd/inetd.c
+++ b/usr.sbin/inetd/inetd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: inetd.c,v 1.27 1997/06/04 11:07:05 deraadt Exp $ */
+/* $OpenBSD: inetd.c,v 1.28 1997/06/17 05:26:22 denny Exp $ */
/* $NetBSD: inetd.c,v 1.11 1996/02/22 11:14:41 mycroft Exp $ */
/*
* Copyright (c) 1983,1991 The Regents of the University of California.
@@ -41,7 +41,7 @@ char copyright[] =
#ifndef lint
/*static char sccsid[] = "from: @(#)inetd.c 5.30 (Berkeley) 6/3/91";*/
-static char rcsid[] = "$OpenBSD: inetd.c,v 1.27 1997/06/04 11:07:05 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: inetd.c,v 1.28 1997/06/17 05:26:22 denny Exp $";
#endif /* not lint */
/*
@@ -86,6 +86,30 @@ static char rcsid[] = "$OpenBSD: inetd.c,v 1.27 1997/06/04 11:07:05 deraadt Exp
* server program full path name
* server program arguments maximum of MAXARGS (20)
*
+ * For non-RPC services, the "service name" can be of the form
+ * hostaddress:servicename, in which case the hostaddress is used
+ * as the host portion of the address to listen on. If hostaddress
+ * consists of a single `*' character, INADDR_ANY is used.
+ *
+ * A line can also consist of just
+ * hostaddress:
+ * where hostaddress is as in the preceding paragraph. Such a line must
+ * have no further fields; the specified hostaddress is remembered and
+ * used for all further lines that have no hostaddress specified,
+ * until the next such line (or EOF). (This is why * is provided to
+ * allow explicit specification of INADDR_ANY.) A line
+ * *:
+ * is implicitly in effect at the beginning of the file.
+ *
+ * The hostaddress specifier may (and often will) contain dots;
+ * the service name must not.
+ *
+ * For RPC services, host-address specifiers are accepted and will
+ * work to some extent; however, because of limitations in the
+ * portmapper interface, it will not work to try to give more than
+ * one line for any given RPC service, even if the host-address
+ * specifiers are different.
+ *
* Comment lines are indicated by a `#' in column 1.
*/
@@ -178,6 +202,7 @@ struct rlimit rlim_ofile;
#endif
struct servtab {
+ char *se_hostaddr; /* host address to listen on */
char *se_service; /* name of service */
int se_socktype; /* type of socket to use */
int se_family; /* address family */
@@ -612,6 +637,7 @@ config(sig)
while ((cp = getconfigent())) {
for (sep = servtab; sep; sep = sep->se_next)
if (strcmp(sep->se_service, cp->se_service) == 0 &&
+ strcmp(sep->se_hostaddr, cp->se_hostaddr) == 0 &&
strcmp(sep->se_proto, cp->se_proto) == 0)
break;
if (sep != 0) {
@@ -667,6 +693,55 @@ config(sig)
break;
case AF_INET:
sep->se_ctrladdr_in.sin_family = AF_INET;
+ if (!strcmp(sep->se_hostaddr,"*"))
+ sep->se_ctrladdr_in.sin_addr.s_addr =
+ INADDR_ANY;
+ else if (!inet_aton(sep->se_hostaddr,
+ &sep->se_ctrladdr_in.sin_addr)) {
+ /*
+ * Do we really want to support hostname
+ * lookups here?
+ */
+ struct hostent *hp;
+ hp = gethostbyname(sep->se_hostaddr);
+ if (hp == 0) {
+ syslog(LOG_ERR, "%s: unknown host",
+ sep->se_hostaddr);
+ sep->se_checked = 0;
+ continue;
+ } else if (hp->h_addrtype != AF_INET) {
+ syslog(LOG_ERR,
+ "%s: address isn't an Internet "
+ "address",
+ sep->se_hostaddr);
+ sep->se_checked = 0;
+ continue;
+ } else if (hp->h_length != sizeof(struct in_addr)) {
+ syslog(LOG_ERR,
+ "%s: address size wrong (under DNS corruption attack?)",
+ sep->se_hostaddr);
+ sep->se_checked = 0;
+ continue;
+ } else {
+ /*
+ * What to do about multi-homed hosts?
+ *
+ * The resolver may be doing
+ * random load balancing. Somehow
+ * this doesn't seem like what the
+ * user intended.
+ */
+ if (hp->h_addr_list[1] != NULL) {
+ syslog(LOG_WARNING,
+ "%s has multiple addresses, using the first",
+ sep->se_hostaddr);
+ }
+
+ bcopy(hp->h_addr_list[0],
+ &sep->se_ctrladdr_in.sin_addr,
+ sizeof(struct in_addr));
+ }
+ }
sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in;
if (isrpcservice(sep)) {
struct rpcent *rp;
@@ -939,6 +1014,7 @@ enter(cp)
FILE *fconfig = NULL;
struct servtab serv;
char line[1024];
+char *defhost;
char *skip __P((char **));
char *nextline __P((FILE *));
char *newstr __P((char *));
@@ -946,7 +1022,8 @@ char *newstr __P((char *));
int
setconfig()
{
-
+ if (defhost) free(defhost);
+ defhost = newstr("*");
if (fconfig != NULL) {
fseek(fconfig, 0L, L_SET);
return (1);
@@ -962,6 +1039,10 @@ endconfig()
(void) fclose(fconfig);
fconfig = NULL;
}
+ if (defhost) {
+ free(defhost);
+ defhost = 0;
+ }
}
struct servtab *
@@ -970,6 +1051,7 @@ getconfigent()
register struct servtab *sep = &serv;
int argc;
char *cp, *arg;
+ char *hostdelim;
more:
#ifdef MULOG
@@ -1007,10 +1089,35 @@ more:
if (cp == NULL)
return ((struct servtab *)0);
bzero((char *)sep, sizeof *sep);
- sep->se_service = newstr(skip(&cp));
arg = skip(&cp);
- if (arg == NULL)
+ if (arg == NULL) {
+ /* A blank line. */
goto more;
+ }
+
+ /* Check for a host name. */
+ hostdelim = strrchr(arg, ':');
+ if (hostdelim) {
+ *hostdelim = '\0';
+ sep->se_hostaddr = newstr(arg);
+ arg = hostdelim + 1;
+ /*
+ * If the line is of the form `host:', then just change the
+ * default host for the following lines.
+ */
+ if (*arg == '\0') {
+ arg = skip(&cp);
+ if (cp == NULL) {
+ free(defhost);
+ defhost = sep->se_hostaddr;
+ goto more;
+ }
+ }
+ } else
+ sep->se_hostaddr = newstr(defhost);
+
+ sep->se_service = newstr(arg);
+ arg = skip(&cp);
if (strcmp(arg, "stream") == 0)
sep->se_socktype = SOCK_STREAM;
@@ -1134,6 +1241,8 @@ freeconfig(cp)
{
int i;
+ if (cp->se_hostaddr)
+ free(cp->se_hostaddr);
if (cp->se_service)
free(cp->se_service);
if (cp->se_proto)