summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2002-06-07 03:32:05 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>2002-06-07 03:32:05 +0000
commit7ab586a39aaba2282184b2e377a64b5c3d16ace5 (patch)
tree435bf7f430d17a473dd290ade0e70f3bd43c3148
parente06010752854f5ea2eeb25c2b5694b82be59c2ea (diff)
support scoped IPv6 address.
no visible API change, old config files work just fine. now you can use expressions like "ALL: [fe80::%lo0/64]". theo ok
-rw-r--r--lib/libwrap/hosts_access.c220
-rw-r--r--lib/libwrap/misc.c16
-rw-r--r--lib/libwrap/socket.c177
-rw-r--r--libexec/tcpd/tcpdchk/scaffold.c163
-rw-r--r--libexec/tcpd/tcpdchk/scaffold.h4
-rw-r--r--libexec/tcpd/tcpdchk/tcpdchk.c57
-rw-r--r--libexec/tcpd/tcpdmatch/tcpdmatch.c100
7 files changed, 329 insertions, 408 deletions
diff --git a/lib/libwrap/hosts_access.c b/lib/libwrap/hosts_access.c
index b1d183b06f6..1043d6d811f 100644
--- a/lib/libwrap/hosts_access.c
+++ b/lib/libwrap/hosts_access.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hosts_access.c,v 1.7 2001/12/13 17:44:47 beck Exp $ */
+/* $OpenBSD: hosts_access.c,v 1.8 2002/06/07 03:32:04 itojun Exp $ */
/*
* This module implements a simple access control language that is based on
@@ -23,7 +23,7 @@
#if 0
static char sccsid[] = "@(#) hosts_access.c 1.21 97/02/12 02:13:22";
#else
-static char rcsid[] = "$OpenBSD: hosts_access.c,v 1.7 2001/12/13 17:44:47 beck Exp $";
+static char rcsid[] = "$OpenBSD: hosts_access.c,v 1.8 2002/06/07 03:32:04 itojun Exp $";
#endif
#endif
@@ -45,12 +45,9 @@ static char rcsid[] = "$OpenBSD: hosts_access.c,v 1.7 2001/12/13 17:44:47 beck E
#ifdef NETGROUP
#include <netgroup.h>
#endif
+#include <netdb.h>
-#ifndef INADDR_NONE
-#define INADDR_NONE (-1) /* XXX should be 0xffffffff */
-#endif
-
/* Local stuff. */
#include "tcpd.h"
@@ -85,16 +82,17 @@ int resident = (-1); /* -1, 0: unknown; +1: yes */
/* Forward declarations. */
-static int table_match();
-static int list_match();
-static int server_match();
-static int client_match();
-static int host_match();
-static int string_match();
-static int masked_match();
-static int masked_match4();
+static int table_match(char *, struct request_info *);
+static int list_match(char *, struct request_info *,
+ int (*)(char *, struct request_info *));
+static int server_match(char *, struct request_info *);
+static int client_match(char *, struct request_info *);
+static int host_match(char *, struct host_info *);
+static int string_match(char *, char *);
+static int masked_match(char *, char *, char *);
+static int masked_match4(char *, char *, char *);
#ifdef INET6
-static int masked_match6();
+static int masked_match6(char *, char *, char *);
#endif
/* Size of logical line buffer. */
@@ -199,7 +197,7 @@ struct request_info *request;
static int list_match(list, request, match_fn)
char *list;
struct request_info *request;
-int (*match_fn) ();
+int (*match_fn)(char *, struct request_info *);
{
char *tok;
int l;
@@ -333,9 +331,14 @@ char *string;
#ifndef INET6
return masked_match4(net_tok, mask_tok, string);
#else
- if (dot_quad_addr_new(net_tok, NULL)
- && dot_quad_addr_new(mask_tok, NULL)
- && dot_quad_addr_new(string, NULL)) {
+ /*
+ * masked_match4() is kept just for supporting shortened IPv4 address form.
+ * If we could get rid of shortened IPv4 form, we could just always use
+ * masked_match6().
+ */
+ if (dot_quad_addr_new(net_tok, NULL) &&
+ dot_quad_addr_new(mask_tok, NULL) &&
+ dot_quad_addr_new(string, NULL)) {
return masked_match4(net_tok, mask_tok, string);
} else
return masked_match6(net_tok, mask_tok, string);
@@ -360,81 +363,152 @@ char *string;
if (!dot_quad_addr_new(string, &addr))
return (NO);
if (!dot_quad_addr_new(net_tok, &net) ||
- !dot_quad_addr_new(mask_tok, &mask)) {
+ !dot_quad_addr_new(mask_tok, &mask)) {
tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
return (NO); /* not tcpd_jump() */
}
+
+ if ((net & ~mask) != 0)
+ tcpd_warn("host bits not all zero in %s/%s", net_tok, mask_tok);
+
return ((addr & mask) == net);
}
#ifdef INET6
-/* Ugly because it covers IPv4 mapped address. I hate mapped addresses. */
static int masked_match6(net_tok, mask_tok, string)
char *net_tok;
char *mask_tok;
char *string;
{
- struct in6_addr net;
- struct in6_addr mask;
- struct in6_addr addr;
- u_long masklen;
- int fail;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ } net, mask, addr;
+ struct addrinfo hints, *res;
+ unsigned long masklen;
+ char *ep;
int i;
- int maskoff;
- int netaf;
- char *p;
- const int sizoff64 = sizeof(struct in6_addr) - sizeof(struct in_addr);
-
- memset(&addr, 0, sizeof(addr));
- if (inet_pton(AF_INET6, string, &addr) == 1)
- ; /* okay */
- else if (inet_pton(AF_INET, string, &addr.s6_addr[sizoff64]) == 1)
- addr.s6_addr[10] = addr.s6_addr[11] = 0xff;
- else
- return NO;
-
- memset(&net, 0, sizeof(net));
- if (inet_pton(AF_INET6, net_tok, &net) == 1) {
- netaf = AF_INET6;
- maskoff = 0;
- } else if (inet_pton(AF_INET, net_tok, &net.s6_addr[sizoff64]) == 1) {
- netaf = AF_INET;
- maskoff = sizoff64;
- net.s6_addr[10] = net.s6_addr[11] = 0xff;
+ char *np, *mp, *ap;
+ int alen;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(net_tok, "0", &hints, &res) == 0) {
+ if (res->ai_addrlen > sizeof(net) || res->ai_next) {
+ freeaddrinfo(res);
+ return NO;
+ }
+ memcpy(&net, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
} else
return NO;
- fail = 0;
- if (mask_tok[strspn(mask_tok, "0123456789")] == '\0') {
- errno = 0;
- masklen = strtoul(mask_tok, &p, 10);
- if (!*mask_tok || *p || (errno == ERANGE && masklen == ULONG_MAX))
- goto bogusmask;
- masklen += maskoff * 8;
- if (0 <= masklen && masklen <= 128) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = net.sa.sa_family;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ hints.ai_flags = AI_NUMERICHOST;
+ ep = NULL;
+ if (getaddrinfo(mask_tok, "0", &hints, &res) == 0) {
+ if (res->ai_family == AF_INET6 &&
+ ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id) {
+ freeaddrinfo(res);
+ return NO;
+ }
+ if (res->ai_addrlen > sizeof(mask) || res->ai_next) {
+ freeaddrinfo(res);
+ return NO;
+ }
+ memcpy(&mask, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ } else {
+ ep = NULL;
+ masklen = strtoul(mask_tok, &ep, 10);
+ if (ep && !*ep) {
memset(&mask, 0, sizeof(mask));
- memset(&mask, 0xff, masklen / 8);
- if (masklen % 8) {
- ((u_char *)&mask)[masklen / 8] =
- (0xff00 >> (masklen % 8)) & 0xff;
+ mask.sa.sa_family = net.sa.sa_family;
+ mask.sa.sa_len = net.sa.sa_len;
+ switch (mask.sa.sa_family) {
+ case AF_INET:
+ mp = (char *)&mask.sin.sin_addr;
+ alen = sizeof(mask.sin.sin_addr);
+ break;
+ case AF_INET6:
+ mp = (char *)&mask.sin6.sin6_addr;
+ alen = sizeof(mask.sin6.sin6_addr);
+ break;
+ default:
+ return NO;
}
+ if (masklen / 8 > alen)
+ return NO;
+ memset(mp, 0xff, masklen / 8);
+ if (masklen % 8)
+ mp[masklen / 8] = 0xff00 >> (masklen % 8);
+ } else
+ return NO;
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(string, "0", &hints, &res) == 0) {
+ if (res->ai_addrlen > sizeof(addr) || res->ai_next) {
+ freeaddrinfo(res);
+ return NO;
+ }
+ /* special case - IPv4 mapped address */
+ if (net.sa.sa_family == AF_INET && res->ai_family == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)) {
+ memset(&addr, 0, sizeof(addr));
+ addr.sa.sa_family = net.sa.sa_family;
+ addr.sa.sa_len = net.sa.sa_len;
+ memcpy(&addr.sin.sin_addr,
+ &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr.s6_addr[12],
+ sizeof(addr.sin.sin_addr));
} else
- fail++;
- } else if (netaf == AF_INET6 && inet_pton(AF_INET6, mask_tok, &mask) == 1)
- ; /* okay */
- else if (netaf == AF_INET
- && inet_pton(AF_INET, mask_tok, &mask.s6_addr[12]) == 1) {
- memset(&mask, 0xff, sizoff64);
+ memcpy(&addr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
} else
-bogusmask:
- fail++;
- if (fail) {
- tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
- return (NO); /* not tcpd_jump() */
+ return NO;
+
+ if (net.sa.sa_family != mask.sa.sa_family ||
+ net.sa.sa_family != addr.sa.sa_family) {
+ return NO;
}
+
+ switch (net.sa.sa_family) {
+ case AF_INET:
+ np = (char *)&net.sin.sin_addr;
+ mp = (char *)&mask.sin.sin_addr;
+ ap = (char *)&addr.sin.sin_addr;
+ alen = sizeof(net.sin.sin_addr);
+ break;
+ case AF_INET6:
+ np = (char *)&net.sin6.sin6_addr;
+ mp = (char *)&mask.sin6.sin6_addr;
+ ap = (char *)&addr.sin6.sin6_addr;
+ alen = sizeof(net.sin6.sin6_addr);
+ break;
+ default:
+ return NO;
+ }
+
+ for (i = 0; i < alen; i++)
+ if (np[i] & ~mp[i]) {
+ tcpd_warn("host bits not all zero in %s/%s", net_tok, mask_tok);
+ break;
+ }
+
+ for (i = 0; i < alen; i++)
+ ap[i] &= mp[i];
- for (i = 0; i < sizeof(addr); i++)
- addr.s6_addr[i] &= mask.s6_addr[i];
- return (memcmp(&addr, &net, sizeof(addr)) == 0);
+ if (addr.sa.sa_family == AF_INET6 && addr.sin6.sin6_scope_id &&
+ addr.sin6.sin6_scope_id != net.sin6.sin6_scope_id)
+ return NO;
+ return (memcmp(ap, np, alen) == 0);
}
#endif
diff --git a/lib/libwrap/misc.c b/lib/libwrap/misc.c
index 3ba0caaf023..8c5294cc795 100644
--- a/lib/libwrap/misc.c
+++ b/lib/libwrap/misc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: misc.c,v 1.4 2000/10/14 00:56:15 itojun Exp $ */
+/* $OpenBSD: misc.c,v 1.5 2002/06/07 03:32:04 itojun Exp $ */
/*
* Misc routines that are used by tcpd and by tcpdchk.
@@ -10,7 +10,7 @@
#if 0
static char sccsic[] = "@(#) misc.c 1.2 96/02/11 17:01:29";
#else
-static char rcsid[] = "$OpenBSD: misc.c,v 1.4 2000/10/14 00:56:15 itojun Exp $";
+static char rcsid[] = "$OpenBSD: misc.c,v 1.5 2002/06/07 03:32:04 itojun Exp $";
#endif
#endif
@@ -23,10 +23,6 @@ static char rcsid[] = "$OpenBSD: misc.c,v 1.4 2000/10/14 00:56:15 itojun Exp $";
#include "tcpd.h"
-#ifndef INADDR_NONE
-#define INADDR_NONE (-1) /* XXX should be 0xffffffff */
-#endif
-
/* xgets - fgets() with backslash-newline stripping */
char *xgets(ptr, len, fp)
@@ -60,13 +56,6 @@ char *split_at(string, delimiter)
char *string;
int delimiter;
{
-#if 0
- char *cp;
-
- if ((cp = strchr(string, delimiter)) != 0)
- *cp++ = 0;
- return (cp);
-#else
char *cp;
int bracket;
@@ -88,7 +77,6 @@ int delimiter;
}
}
return NULL;
-#endif
}
/* dot_quad_addr_new - convert dotted quad to internal form */
diff --git a/lib/libwrap/socket.c b/lib/libwrap/socket.c
index 6e5532f8401..4ca3461c466 100644
--- a/lib/libwrap/socket.c
+++ b/lib/libwrap/socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: socket.c,v 1.4 2001/11/07 18:49:21 deraadt Exp $ */
+/* $OpenBSD: socket.c,v 1.5 2002/06/07 03:32:04 itojun Exp $ */
/*
* This module determines the type of socket (datagram, stream), the client
@@ -21,7 +21,7 @@
#if 0
static char sccsid[] = "@(#) socket.c 1.15 97/03/21 19:27:24";
#else
-static char rcsid[] = "$OpenBSD: socket.c,v 1.4 2001/11/07 18:49:21 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: socket.c,v 1.5 2002/06/07 03:32:04 itojun Exp $";
#endif
#endif
@@ -43,35 +43,35 @@ static char rcsid[] = "$OpenBSD: socket.c,v 1.4 2001/11/07 18:49:21 deraadt Exp
/* Forward declarations. */
-static void sock_sink();
-
#ifdef APPEND_DOT
+static const char *append_dot(const char *);
+#endif
+static void sock_sink(int);
+#ifdef APPEND_DOT
/*
* Speed up DNS lookups by terminating the host name with a dot. Should be
* done with care. The speedup can give problems with lookups from sources
* that lack DNS-style trailing dot magic, such as local files or NIS maps.
*/
-static struct hostent *gethostbyname_dot(name)
-char *name;
+static const char *
+append_dot(name)
+const char *name;
{
- char dot_name[MAXHOSTNAMELEN + 1];
+ static char hbuf[MAXHOSTNAMELEN + 1];
/*
* Don't append dots to unqualified names. Such names are likely to come
* from local hosts files or from NIS.
*/
- if (strchr(name, '.') == 0 || strlen(name) >= MAXHOSTNAMELEN - 1) {
- return (gethostbyname(name));
- } else {
- snprintf(dot_name, sizeof(dot_name), "%s.", name);
- return (gethostbyname(dot_name));
- }
+ if (strchr(name, '.') == 0 || strlen(name) + 2 > sizeof(hbuf))
+ strlcpy(hbuf, name, sizeof(hbuf));
+ else
+ snprintf(hbuf, sizeof(hbuf), "%s.", name);
+ return hbuf;
}
-
-#define gethostbyname gethostbyname_dot
#endif
/* sock_host - look up endpoint addresses and install conversion methods */
@@ -133,27 +133,12 @@ void sock_hostaddr(host)
struct host_info *host;
{
struct sockaddr *sa = host->sin;
- int alen, af;
- char *ap;
if (!sa)
return;
- switch (af = sa->sa_family) {
- case AF_INET:
- ap = (char *)&((struct sockaddr_in *)sa)->sin_addr;
- alen = sizeof(struct in_addr);
- break;
-#ifdef INET6
- case AF_INET6:
- ap = (char *)&((struct sockaddr_in6 *)sa)->sin6_addr;
- alen = sizeof(struct in6_addr);
- break;
-#endif
- default:
- return;
- }
host->addr[0] = '\0';
- inet_ntop(af, ap, host->addr, sizeof(host->addr));
+ getnameinfo(sa, sa->sa_len, host->addr, sizeof(host->addr),
+ NULL, 0, NI_NUMERICHOST);
}
/* sock_hostname - map endpoint address to host name */
@@ -161,95 +146,89 @@ struct host_info *host;
void sock_hostname(host)
struct host_info *host;
{
- struct sockaddr *sin = host->sin;
- struct hostent *hp;
- int i;
- int af, alen;
- char *ap;
- char hbuf[MAXHOSTNAMELEN];
+ struct sockaddr *sa = host->sin;
+ char h1[NI_MAXHOST], h2[NI_MAXHOST];
+ struct addrinfo hints, *res, *res0;
+#ifdef INET6
+ struct sockaddr_in tmp;
+#endif
- /*
- * On some systems, for example Solaris 2.3, gethostbyaddr(0.0.0.0) does
- * not fail. Instead it returns "INADDR_ANY". Unfortunately, this does
- * not work the other way around: gethostbyname("INADDR_ANY") fails. We
- * have to special-case 0.0.0.0, in order to avoid false alerts from the
- * host name/address checking code below.
- */
- if (!sin)
+ if (!sa)
return;
- switch (af = sin->sa_family) {
- case AF_INET:
- if (((struct sockaddr_in *)sin)->sin_addr.s_addr == 0)
- return;
- ap = (char *)&((struct sockaddr_in *)sin)->sin_addr;
- alen = sizeof(struct in_addr);
- break;
#ifdef INET6
- case AF_INET6:
- ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr;
- alen = sizeof(struct in6_addr);
- /* special case on reverse lookup: mapped addr. I hate it */
- if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
- af = AF_INET;
- ap += (sizeof(struct in6_addr) - sizeof(struct in_addr));
- alen = sizeof(struct in_addr);
- }
- break;
+ /* special case on reverse lookup: mapped addr. I hate it */
+ if (sa->sa_family == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sa)->sin6_addr)) {
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.sin_family = AF_INET;
+ tmp.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&tmp.sin_addr,
+ &((struct sockaddr_in6 *)sa)->sin6_addr.s6_addr[12], 4);
+ sa = (struct sockaddr *)&tmp;
+ }
#endif
- default:
+ if (getnameinfo(sa, sa->sa_len, h1, sizeof(h1), NULL, 0,
+ NI_NUMERICHOST) != 0) {
return;
}
- if ((hp = gethostbyaddr(ap, alen, af)) != 0) {
-
- strlcpy(host->name, hp->h_name, sizeof(host->name));
-
+ if (getnameinfo(sa, sa->sa_len, host->name, sizeof(host->name), NULL, 0,
+ NI_NAMEREQD) == 0) {
/*
* Verify that the address is a member of the address list returned
- * by gethostbyname(hostname).
+ * by getaddrinfo(hostname).
*
- * Verify also that gethostbyaddr() and gethostbyname() return the same
+ * Verify also that getnameinfo() and getaddrinfo() return the same
* hostname, or rshd and rlogind may still end up being spoofed.
*
- * On some sites, gethostbyname("localhost") returns "localhost.domain".
+ * On some sites, getaddrinfo("localhost") returns "localhost.domain".
* This is a DNS artefact. We treat it as a special case. When we
- * can't believe the address list from gethostbyname("localhost")
+ * can't believe the address list from getaddrinfo("localhost")
* we're in big trouble anyway.
*/
-
- if ((hp = gethostbyname2(host->name, af)) == 0) {
-
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = sa->sa_family;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ hints.ai_flags = AI_CANONNAME;
+#ifdef APPEND_DOT
+ if (getaddrinfo(append_dot(host->name), "0", &hints, &res0) != 0)
+#else
+ if (getaddrinfo(host->name, "0", &hints, &res0) != 0)
+#endif
+ {
/*
* Unable to verify that the host name matches the address. This
* may be a transient problem or a botched name server setup.
*/
- tcpd_warn("can't verify hostname: gethostbyname2(%s, %d) failed",
- host->name, af);
-
- } else if (STR_NE(host->name, hp->h_name)
- && STR_NE(host->name, "localhost")) {
-
+ tcpd_warn("can't verify hostname: getaddrinfo(%s, %d) failed",
+ host->name, hints.ai_family);
+ } else if (res0->ai_canonname &&
+ STR_NE(host->name, res0->ai_canonname) &&
+ STR_NE(host->name, "localhost")) {
/*
- * The gethostbyaddr() and gethostbyname() calls did not return
+ * The getnameinfo() and getaddrinfo() calls did not return
* the same hostname. This could be a nameserver configuration
* problem. It could also be that someone is trying to spoof us.
*/
- tcpd_warn("host name/name mismatch: %s != %.*s",
- host->name, STRING_LENGTH, hp->h_name);
-
+ tcpd_warn("host name/name mismatch: %s != %s",
+ host->name, res0->ai_canonname);
+ freeaddrinfo(res0);
} else {
-
/*
* The address should be a member of the address list returned by
- * gethostbyname(). We should first verify that the h_addrtype
- * field is AF_INET, but this program has already caused too much
- * grief on systems with broken library code.
+ * getaddrinfo().
*/
- for (i = 0; hp->h_addr_list[i]; i++) {
- if (memcmp(hp->h_addr_list[i], (char *) ap, alen) == 0)
- return; /* name is good, keep it */
+ for (res = res0; res; res = res->ai_next) {
+ if (getnameinfo(res->ai_addr, res->ai_addrlen, h2, sizeof(h2),
+ NULL, 0, NI_NUMERICHOST) != 0) {
+ continue;
+ }
+ if (STR_EQ(h1, h2)) {
+ freeaddrinfo(res0);
+ return;
+ }
}
/*
@@ -258,11 +237,11 @@ struct host_info *host;
* server.
*/
- tcpd_warn("host name/address mismatch: %s != %.*s",
- inet_ntop(af, ap, hbuf, sizeof(hbuf)),
- STRING_LENGTH, hp->h_name);
- }
+ tcpd_warn("host name/address mismatch: %s != %s", h1,
+ res0->ai_canonname ? res0->ai_canonname : "?");
+ freeaddrinfo(res0);
+ }
/* name is bad, clobber it */
strlcpy(host->name, paranoid, sizeof(host->name));
}
@@ -274,13 +253,13 @@ static void sock_sink(fd)
int fd;
{
char buf[BUFSIZ];
- struct sockaddr_storage sin;
- int size = sizeof(sin);
+ struct sockaddr_storage ss;
+ int size = sizeof(ss);
/*
* Eat up the not-yet received datagram. Some systems insist on a
* non-zero source address argument in the recvfrom() call below.
*/
- (void) recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *) & sin, &size);
+ (void) recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *) & ss, &size);
}
diff --git a/libexec/tcpd/tcpdchk/scaffold.c b/libexec/tcpd/tcpdchk/scaffold.c
index 46a4797e1e4..582cea1d173 100644
--- a/libexec/tcpd/tcpdchk/scaffold.c
+++ b/libexec/tcpd/tcpdchk/scaffold.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: scaffold.c,v 1.5 2002/05/07 23:01:07 deraadt Exp $ */
+/* $OpenBSD: scaffold.c,v 1.6 2002/06/07 03:32:04 itojun Exp $ */
/*
* Routines for testing only. Not really industrial strength.
@@ -10,7 +10,7 @@
#if 0
static char sccs_id[] = "@(#) scaffold.c 1.5 95/01/03 09:13:48";
#else
-static char rcsid[] = "$OpenBSD: scaffold.c,v 1.5 2002/05/07 23:01:07 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: scaffold.c,v 1.6 2002/06/07 03:32:04 itojun Exp $";
#endif
#endif
@@ -43,119 +43,31 @@ static char rcsid[] = "$OpenBSD: scaffold.c,v 1.5 2002/05/07 23:01:07 deraadt Ex
*/
int allow_severity = SEVERITY;
int deny_severity = LOG_WARNING;
-int rfc931_timeout = RFC931_TIMEOUT;
-
-/* dup_hostent - create hostent in one memory block */
-
-static struct hostent *dup_hostent(hp)
-struct hostent *hp;
-{
- struct hostent_block {
- struct hostent host;
- char *addr_list[1];
- };
- struct hostent_block *hb;
- int count;
- char *data;
- char *addr;
-
- for (count = 0; hp->h_addr_list[count] != 0; count++)
- /* void */ ;
-
- if ((hb = (struct hostent_block *) malloc(sizeof(struct hostent_block)
- + (hp->h_length + sizeof(char *)) * count)) == 0) {
- fprintf(stderr, "Sorry, out of memory\n");
- exit(1);
- }
- memset((char *) &hb->host, 0, sizeof(hb->host));
- hb->host.h_addrtype = hp->h_addrtype;
- hb->host.h_length = hp->h_length;
- hb->host.h_addr_list = hb->addr_list;
- hb->host.h_addr_list[count] = 0;
- data = (char *) (hb->host.h_addr_list + count + 1);
-
- for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
- hb->host.h_addr_list[count] = data + hp->h_length * count;
- memcpy(hb->host.h_addr_list[count], addr, hp->h_length);
- }
- return (&hb->host);
-}
+int rfc931_timeout = RFC931_TIMEOUT;
/* find_inet_addr - find all addresses for this host, result to free() */
-struct hostent *find_inet_addr(host)
+struct addrinfo *find_inet_addr(host, flags)
char *host;
+int flags;
{
- struct in_addr addr;
- struct hostent *hp;
- static struct hostent h;
- static char *addr_list[2];
-#ifdef INET6
- static struct in6_addr in6;
-#endif
-
- /*
- * Host address: translate it to internal form.
- */
- if (dot_quad_addr_new(host, &addr.s_addr)) {
- h.h_addr_list = addr_list;
- h.h_addr_list[0] = (char *) &addr;
- h.h_length = sizeof(addr);
- h.h_addrtype = AF_INET;
- return (dup_hostent(&h));
- }
-#ifdef INET6
- if (inet_pton(AF_INET6, host, &in6) == 1) {
- h.h_addr_list = addr_list;
- h.h_addr_list[0] = (char *) &in6;
- h.h_length = sizeof(in6);
- h.h_addrtype = AF_INET6;
- return (dup_hostent(&h));
- }
-#endif
-
- /*
- * Map host name to a series of addresses. Watch out for non-internet
- * forms or aliases. The NOT_INADDR() is here in case gethostbyname() has
- * been "enhanced" to accept numeric addresses. Make a copy of the
- * address list so that later gethostbyXXX() calls will not clobber it.
- */
-#ifdef INET6
- if (NOT_INADDR(host) == 0 && inet_pton(AF_INET6, host, &in6) == 1)
-#else
- if (NOT_INADDR(host) == 0)
-#endif
- {
- tcpd_warn("%s: not an internet address", host);
- return (0);
- }
-#ifdef INET6
- /*
- * XXX this behavior may, or may not be desirable.
- * - we may better use getipnodebyname() to addresses of get both AFs,
- * however, getipnodebyname() is not widely implemented.
- * - it may be better to have a way to specify the AF to use.
- */
- if ((hp = gethostbyname2(host, AF_INET)) == 0
- && (hp = gethostbyname2(host, AF_INET6)) == 0) {
- tcpd_warn("%s: host not found", host);
- return (0);
- }
-#else
- if ((hp = gethostbyname(host)) == 0) {
- tcpd_warn("%s: host not found", host);
+ struct addrinfo hints, *res;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_CANONNAME | flags;
+ error = getaddrinfo(host, "0", &hints, &res);
+ if (error) {
+ tcpd_warn("%s: %s", host, gai_strerror(error));
return (0);
}
- if (hp->h_addrtype != AF_INET) {
- tcpd_warn("%d: not an internet host", hp->h_addrtype);
- return (0);
- }
-#endif
- if (STR_NE(host, hp->h_name)) {
+
+ if (res->ai_canonname && STR_NE(host, res->ai_canonname)) {
tcpd_warn("%s: hostname alias", host);
- tcpd_warn("(official name: %s)", hp->h_name);
+ tcpd_warn("(official name: %.*s)", STRING_LENGTH, res->ai_canonname);
}
- return (dup_hostent(hp));
+ return (res);
}
/* check_dns - give each address thorough workout, return address count */
@@ -164,36 +76,22 @@ int check_dns(host)
char *host;
{
struct request_info request;
- struct sockaddr_storage sin;
- struct hostent *hp;
+ struct sockaddr_storage ss;
+ struct addrinfo *res0, *res;
int count;
- char *addr;
- char *ap;
- int alen;
- if ((hp = find_inet_addr(host)) == 0)
+ if ((res0 = find_inet_addr(host, 0)) == NULL)
return (0);
- request_init(&request, RQ_CLIENT_SIN, &sin, 0);
+ memset(&ss, 0, sizeof(ss));
+ request_init(&request, RQ_CLIENT_SIN, &ss, 0);
sock_methods(&request);
- memset((char *) &sin, 0, sizeof(sin));
- sin.ss_family = hp->h_addrtype;
- switch (hp->h_addrtype) {
- case AF_INET:
- ap = (char *)&((struct sockaddr_in *)&sin)->sin_addr;
- alen = sizeof(struct in_addr);
- break;
-#ifdef INET6
- case AF_INET6:
- ap = (char *)&((struct sockaddr_in6 *)&sin)->sin6_addr;
- alen = sizeof(struct in6_addr);
- break;
-#endif
- default:
- return (0);
- }
- for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
- memcpy(ap, addr, alen);
+ count = 0;
+ for (res = res0; res; res = res->ai_next) {
+ count++;
+ if (res->ai_addrlen > sizeof(ss))
+ continue;
+ memcpy(&ss, res->ai_addr, res->ai_addrlen);
/*
* Force host name and address conversions. Use the request structure
@@ -205,8 +103,9 @@ char *host;
if (STR_EQ(eval_hostname(request.client), unknown))
tcpd_warn("host address %s->name lookup failed",
eval_hostaddr(request.client));
+ tcpd_warn("%s %s", eval_hostname(request.client), unknown);
}
- free((char *) hp);
+ freeaddrinfo(res0);
return (count);
}
diff --git a/libexec/tcpd/tcpdchk/scaffold.h b/libexec/tcpd/tcpdchk/scaffold.h
index 2450d24ca10..7bb69bc18a2 100644
--- a/libexec/tcpd/tcpdchk/scaffold.h
+++ b/libexec/tcpd/tcpdchk/scaffold.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: scaffold.h,v 1.2 2002/02/16 21:27:31 millert Exp $ */
+/* $OpenBSD: scaffold.h,v 1.3 2002/06/07 03:32:04 itojun Exp $ */
/*
* @(#) scaffold.h 1.3 94/12/31 18:19:19
@@ -9,7 +9,7 @@
#include <sys/cdefs.h>
__BEGIN_DECLS
-extern struct hostent *find_inet_addr(char *);
+extern struct addrinfo *find_inet_addr(char *, int);
extern int check_dns(char *);
extern int check_path(char *, struct stat *);
__END_DECLS
diff --git a/libexec/tcpd/tcpdchk/tcpdchk.c b/libexec/tcpd/tcpdchk/tcpdchk.c
index ec605da57da..ebe74dafcc7 100644
--- a/libexec/tcpd/tcpdchk/tcpdchk.c
+++ b/libexec/tcpd/tcpdchk/tcpdchk.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcpdchk.c,v 1.5 2001/07/08 21:18:13 deraadt Exp $ */
+/* $OpenBSD: tcpdchk.c,v 1.6 2002/06/07 03:32:04 itojun Exp $ */
/*
* tcpdchk - examine all tcpd access control rules and inetd.conf entries
@@ -20,7 +20,7 @@
#if 0
static char sccsid[] = "@(#) tcpdchk.c 1.8 97/02/12 02:13:25";
#else
-static char rcsid[] = "$OpenBSD: tcpdchk.c,v 1.5 2001/07/08 21:18:13 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: tcpdchk.c,v 1.6 2002/06/07 03:32:04 itojun Exp $";
#endif
#endif
@@ -28,9 +28,6 @@ static char rcsid[] = "$OpenBSD: tcpdchk.c,v 1.5 2001/07/08 21:18:13 deraadt Exp
#include <sys/types.h>
#include <sys/stat.h>
-#ifdef INET6
-#include <sys/socket.h>
-#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
@@ -76,15 +73,18 @@ extern jmp_buf tcpd_buf;
/*
* Local stuff.
*/
-static void usage();
-static void parse_table();
-static void print_list();
-static void check_daemon_list();
-static void check_client_list();
-static void check_daemon();
-static void check_user();
-static int check_host();
-static int reserved_name();
+static void usage(void);
+static void parse_table(char *, struct request_info *);
+static void print_list(char *, char *);
+static void check_daemon_list(char *);
+static void check_client_list(char *);
+static void check_daemon(char *);
+static void check_user(char *);
+#ifdef INET6
+static int check_inet_addr(char *);
+#endif
+static int check_host(char *);
+static int reserved_name(char *);
#define PERMIT 1
#define DENY 0
@@ -419,8 +419,22 @@ char *pat;
}
}
-/* check_host - criticize host pattern */
+#ifdef INET6
+static int check_inet_addr(pat)
+char *pat;
+{
+ struct addrinfo *res;
+
+ res = find_inet_addr(pat, AI_NUMERICHOST);
+ if (res) {
+ freeaddrinfo(res);
+ return 1;
+ } else
+ return 0;
+}
+#endif
+/* check_host - criticize host pattern */
static int check_host(pat)
char *pat;
{
@@ -446,18 +460,15 @@ char *pat;
#endif
} else if ((mask = split_at(pat, '/')) != NULL) { /* network/netmask */
#ifdef INET6
- struct in6_addr in6;
+ char *ep;
#endif
- if (dot_quad_addr_new(pat, NULL)
- && dot_quad_addr_new(mask, NULL))
+ if (dot_quad_addr_new(pat, NULL) && dot_quad_addr_new(mask, NULL))
; /*okay*/
#ifdef INET6
- else if (inet_pton(AF_INET6, pat, &in6) == 1
- && inet_pton(AF_INET6, mask, &in6) == 1)
+ else if (check_inet_addr(pat) && check_inet_addr(mask))
; /*okay*/
- else if (inet_pton(AF_INET6, pat, &in6) == 1
- && strchr(mask, ':') == NULL
- && 0 <= atoi(mask) && atoi(mask) <= 128)
+ else if (check_inet_addr(pat) &&
+ (ep = NULL, strtoul(mask, &ep, 10), ep && !*ep))
; /*okay*/
#endif
else
diff --git a/libexec/tcpd/tcpdmatch/tcpdmatch.c b/libexec/tcpd/tcpdmatch/tcpdmatch.c
index f9de6575da6..de15e410663 100644
--- a/libexec/tcpd/tcpdmatch/tcpdmatch.c
+++ b/libexec/tcpd/tcpdmatch/tcpdmatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcpdmatch.c,v 1.5 2000/10/14 00:56:15 itojun Exp $ */
+/* $OpenBSD: tcpdmatch.c,v 1.6 2002/06/07 03:32:04 itojun Exp $ */
/*
* tcpdmatch - explain what tcpd would do in a specific case
@@ -19,7 +19,7 @@
#if 0
static char sccsid[] = "@(#) tcpdmatch.c 1.5 96/02/11 17:01:36";
#else
-static char rcsid[] = "$OpenBSD: tcpdmatch.c,v 1.5 2000/10/14 00:56:15 itojun Exp $";
+static char rcsid[] = "$OpenBSD: tcpdmatch.c,v 1.6 2002/06/07 03:32:04 itojun Exp $";
#endif
#endif
@@ -53,8 +53,9 @@ static char rcsid[] = "$OpenBSD: tcpdmatch.c,v 1.5 2000/10/14 00:56:15 itojun Ex
#include "inetcf.h"
#include "scaffold.h"
-static void usage();
-static void tcpdmatch();
+static void usage(char *);
+static void expand(char *, char *, struct request_info *);
+static void tcpdmatch(struct request_info *);
/* The main program */
@@ -62,25 +63,19 @@ int main(argc, argv)
int argc;
char **argv;
{
- struct hostent *hp;
+ struct addrinfo *res, *res0;
char *myname = argv[0];
char *client;
char *server;
- char *addr;
char *user;
char *daemon;
struct request_info request;
int ch;
char *inetcf = 0;
int count;
- struct sockaddr_storage server_sin;
- struct sockaddr_storage client_sin;
+ struct sockaddr_storage server_ss;
+ struct sockaddr_storage client_ss;
struct stat st;
- char *ap;
- int alen;
-#ifdef INET6
- struct sockaddr_in6 in6;
-#endif
/*
* Show what rule actually matched.
@@ -180,28 +175,17 @@ char **argv;
* address and name conversion results.
*/
if (NOT_INADDR(server) == 0 || HOSTNAME_KNOWN(server)) {
- if ((hp = find_inet_addr(server)) == 0)
- exit(1);
- memset((char *) &server_sin, 0, sizeof(server_sin));
- server_sin.ss_family = hp->h_addrtype;
- switch (hp->h_addrtype) {
- case AF_INET:
- ap = (char *)&((struct sockaddr_in *)&server_sin)->sin_addr;
- alen = sizeof(struct in_addr);
- break;
-#ifdef INET6
- case AF_INET6:
- ap = (char *)&((struct sockaddr_in6 *)&server_sin)->sin6_addr;
- alen = sizeof(struct in6_addr);
- break;
-#endif
- default:
+ if ((res0 = find_inet_addr(server, 0)) == NULL)
exit(1);
- }
- request_set(&request, RQ_SERVER_SIN, &server_sin, 0);
+ memset((char *) &server_ss, 0, sizeof(server_ss));
+ request_set(&request, RQ_SERVER_SIN, &server_ss, 0);
- for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
- memcpy(ap, addr, alen);
+ count = 0;
+ for (res = res0; res; res = res->ai_next) {
+ count++;
+ if (res->ai_addrlen > sizeof(server_ss))
+ continue;
+ memcpy(&server_ss, res->ai_addr, res->ai_addrlen);
/*
* Force evaluation of server host name and address. Host name
@@ -217,7 +201,7 @@ char **argv;
fprintf(stderr, "Please specify an address instead\n");
exit(1);
}
- free((char *) hp);
+ freeaddrinfo(res0);
} else {
request_set(&request, RQ_SERVER_NAME, server, 0);
}
@@ -226,18 +210,15 @@ char **argv;
* If a client address is specified, we simulate the effect of client
* hostname lookup failure.
*/
- if (dot_quad_addr_new(client, NULL)) {
- request_set(&request, RQ_CLIENT_ADDR, client, 0);
- tcpdmatch(&request);
- exit(0);
- }
-#ifdef INET6
- if (inet_pton(AF_INET6, client, &in6) == 1) {
- request_set(&request, RQ_CLIENT_ADDR, client, 0);
+ res0 = find_inet_addr(client, AI_NUMERICHOST);
+ if (res0 && !res0->ai_next) {
+ request_set(&request, RQ_CLIENT_SIN, res0->ai_addr);
tcpdmatch(&request);
+ freeaddrinfo(res0);
exit(0);
}
-#endif
+ if (res0)
+ freeaddrinfo(res0);
/*
* Perhaps they are testing special client hostname patterns that aren't
@@ -257,28 +238,17 @@ char **argv;
* using the request.client structure as a cache for host name and
* address conversion results.
*/
- if ((hp = find_inet_addr(client)) == 0)
- exit(1);
- memset((char *) &client_sin, 0, sizeof(client_sin));
- client_sin.ss_family = hp->h_addrtype;
- switch (hp->h_addrtype) {
- case AF_INET:
- ap = (char *)&((struct sockaddr_in *)&client_sin)->sin_addr;
- alen = sizeof(struct in_addr);
- break;
-#ifdef INET6
- case AF_INET6:
- ap = (char *)&((struct sockaddr_in6 *)&client_sin)->sin6_addr;
- alen = sizeof(struct in6_addr);
- break;
-#endif
- default:
+ if ((res0 = find_inet_addr(client, 0)) == NULL)
exit(1);
- }
- request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
+ memset((char *) &client_ss, 0, sizeof(client_ss));
+ request_set(&request, RQ_CLIENT_SIN, &client_ss, 0);
- for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
- memcpy(ap, addr, alen);
+ count = 0;
+ for (res = res0; res; res = res->ai_next) {
+ count++;
+ if (res->ai_addrlen > sizeof(client_ss))
+ continue;
+ memcpy(&client_ss, res->ai_addr, res->ai_addrlen);
/*
* Force evaluation of client host name and address. Host name
@@ -289,10 +259,10 @@ char **argv;
tcpd_warn("host address %s->name lookup failed",
eval_hostaddr(request.client));
tcpdmatch(&request);
- if (hp->h_addr_list[count + 1])
+ if (res->ai_next)
printf("\n");
}
- free((char *) hp);
+ freeaddrinfo(res0);
exit(0);
}