summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2000-07-14 17:15:34 +0000
committerume <ume@FreeBSD.org>2000-07-14 17:15:34 +0000
commit70f27cd4dd7e1d1d852cba36b094d6dc066d927d (patch)
treef2ea77bde85e774d904c6d9e876c7f0783fca721
parent55485e0103d7b63665f16e41d400e306498c92a8 (diff)
downloadFreeBSD-src-70f27cd4dd7e1d1d852cba36b094d6dc066d927d.zip
FreeBSD-src-70f27cd4dd7e1d1d852cba36b094d6dc066d927d.tar.gz
Add IPv6 scoped address support.
It enables us to control link-local connections by interface like this: ALL : [fe80::%ed0]/10 : allow ALL : [fe80::]/10 : deny
-rw-r--r--contrib/tcp_wrappers/hosts_access.c59
-rw-r--r--contrib/tcp_wrappers/scaffold.c188
-rw-r--r--contrib/tcp_wrappers/scaffold.h6
-rw-r--r--contrib/tcp_wrappers/socket.c257
-rw-r--r--contrib/tcp_wrappers/tcpdchk.c11
-rw-r--r--contrib/tcp_wrappers/tcpdmatch.c94
-rw-r--r--lib/libwrap/Makefile1
-rw-r--r--usr.sbin/tcpdchk/Makefile4
-rw-r--r--usr.sbin/tcpdmatch/Makefile3
9 files changed, 302 insertions, 321 deletions
diff --git a/contrib/tcp_wrappers/hosts_access.c b/contrib/tcp_wrappers/hosts_access.c
index 2b4dcee..24f5753 100644
--- a/contrib/tcp_wrappers/hosts_access.c
+++ b/contrib/tcp_wrappers/hosts_access.c
@@ -41,6 +41,9 @@ static char sccsid[] = "@(#) hosts_access.c 1.21 97/02/12 02:13:22";
#include <errno.h>
#include <setjmp.h>
#include <string.h>
+#ifdef INET6
+#include <netdb.h>
+#endif
extern char *fgets();
extern int errno;
@@ -341,7 +344,8 @@ char *string;
return (STRN_EQ(tok, string, n));
} else { /* exact match */
#ifdef INET6
- struct in6_addr pat, addr;
+ struct addrinfo hints, *res;
+ struct sockaddr_in6 pat, addr;
int len, ret;
char ch;
@@ -349,11 +353,27 @@ char *string;
if (*tok == '[' && tok[len - 1] == ']') {
ch = tok[len - 1];
tok[len - 1] = '\0';
- ret = inet_pton(AF_INET6, tok + 1, pat.s6_addr);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+ if ((ret = getaddrinfo(tok + 1, NULL, &hints, &res)) == 0) {
+ memcpy(&pat, res->ai_addr, sizeof(pat));
+ freeaddrinfo(res);
+ }
tok[len - 1] = ch;
- if (ret != 1 || inet_pton(AF_INET6, string, addr.s6_addr) != 1)
+ if (ret != 0 || getaddrinfo(string, NULL, &hints, &res) != 0)
return NO;
- return (!memcmp(&pat, &addr, sizeof(struct in6_addr)));
+ memcpy(&addr, res->ai_addr, sizeof(addr));
+ freeaddrinfo(res);
+#ifdef NI_WITHSCOPEID
+ if (pat.sin6_scope_id != 0 &&
+ addr.sin6_scope_id != pat.sin6_scope_id)
+ return NO;
+#endif
+ return (!memcmp(&pat.sin6_addr, &addr.sin6_addr,
+ sizeof(struct in6_addr)));
+ return (ret);
}
#endif
return (STR_EQ(tok, string));
@@ -414,19 +434,26 @@ char *net_tok;
char *mask_tok;
char *string;
{
- struct in6_addr net, addr;
+ struct addrinfo hints, *res;
+ struct sockaddr_in6 net, addr;
u_int32_t mask;
int len, mask_len, i = 0;
char ch;
- if (inet_pton(AF_INET6, string, addr.s6_addr) != 1)
- return NO;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+ if (getaddrinfo(string, NULL, &hints, &res) != 0)
+ return NO;
+ memcpy(&addr, res->ai_addr, sizeof(addr));
+ freeaddrinfo(res);
- if (IN6_IS_ADDR_V4MAPPED(&addr)) {
- if ((*(u_int32_t *)&net.s6_addr[12] = dot_quad_addr(net_tok)) == INADDR_NONE
+ if (IN6_IS_ADDR_V4MAPPED(&addr.sin6_addr)) {
+ if ((*(u_int32_t *)&net.sin6_addr.s6_addr[12] = dot_quad_addr(net_tok)) == INADDR_NONE
|| (mask = dot_quad_addr(mask_tok)) == INADDR_NONE)
return (NO);
- return ((*(u_int32_t *)&addr.s6_addr[12] & mask) == *(u_int32_t *)&net.s6_addr[12]);
+ return ((*(u_int32_t *)&addr.sin6_addr.s6_addr[12] & mask) == *(u_int32_t *)&net.sin6_addr.s6_addr[12]);
}
/* match IPv6 address against netnumber/prefixlen */
@@ -435,22 +462,28 @@ char *string;
return NO;
ch = net_tok[len - 1];
net_tok[len - 1] = '\0';
- if (inet_pton(AF_INET6, net_tok + 1, net.s6_addr) != 1) {
+ if (getaddrinfo(net_tok + 1, NULL, &hints, &res) != 0) {
net_tok[len - 1] = ch;
return NO;
}
+ memcpy(&net, res->ai_addr, sizeof(net));
+ freeaddrinfo(res);
net_tok[len - 1] = ch;
if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128)
return NO;
+#ifdef NI_WITHSCOPEID
+ if (net.sin6_scope_id != 0 && addr.sin6_scope_id != net.sin6_scope_id)
+ return NO;
+#endif
while (mask_len > 0) {
if (mask_len < 32) {
mask = htonl(~(0xffffffff >> mask_len));
- if ((*(u_int32_t *)&addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.s6_addr[i] & mask))
+ if ((*(u_int32_t *)&addr.sin6_addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.sin6_addr.s6_addr[i] & mask))
return NO;
break;
}
- if (*(u_int32_t *)&addr.s6_addr[i] != *(u_int32_t *)&net.s6_addr[i])
+ if (*(u_int32_t *)&addr.sin6_addr.s6_addr[i] != *(u_int32_t *)&net.sin6_addr.s6_addr[i])
return NO;
i += 4;
mask_len -= 32;
diff --git a/contrib/tcp_wrappers/scaffold.c b/contrib/tcp_wrappers/scaffold.c
index ea87c5c..8da9df0 100644
--- a/contrib/tcp_wrappers/scaffold.c
+++ b/contrib/tcp_wrappers/scaffold.c
@@ -22,13 +22,14 @@ static char sccs_id[] = "@(#) scaffold.c 1.6 97/03/21 19:27:24";
#include <syslog.h>
#include <setjmp.h>
#include <string.h>
-#include <resolv.h>
#ifndef INADDR_NONE
#define INADDR_NONE (-1) /* XXX should be 0xffffffff */
#endif
+#ifndef INET6
extern char *malloc();
+#endif
/* Application-specific. */
@@ -42,6 +43,7 @@ int allow_severity = SEVERITY;
int deny_severity = LOG_WARNING;
int rfc931_timeout = RFC931_TIMEOUT;
+#ifndef INET6
/* dup_hostent - create hostent in one memory block */
static struct hostent *dup_hostent(hp)
@@ -60,9 +62,6 @@ struct hostent *hp;
/* void */ ;
if ((hb = (struct hostent_block *) malloc(sizeof(struct hostent_block)
-#ifdef INET6
- + strlen(hp->h_name) + 1
-#endif
+ (hp->h_length + sizeof(char *)) * count)) == 0) {
fprintf(stderr, "Sorry, out of memory\n");
exit(1);
@@ -72,11 +71,6 @@ struct hostent *hp;
hb->host.h_addr_list = hb->addr_list;
hb->host.h_addr_list[count] = 0;
data = (char *) (hb->host.h_addr_list + count + 1);
-#ifdef INET6
- hb->host.h_name = data + hp->h_length * count;
- strcpy(hb->host.h_name, hp->h_name);
- hb->host.h_addrtype = hp->h_addrtype;
-#endif
for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
hb->host.h_addr_list[count] = data + hp->h_length * count;
@@ -84,107 +78,46 @@ struct hostent *hp;
}
return (&hb->host);
}
+#endif
-#if defined(INET6) && !defined(USE_GETIPNODEBY)
-/* merge_hostent - merge hostent in one memory block */
+/* find_inet_addr - find all addresses for this host, result to free() */
-static struct hostent *merge_hostent(hp1, hp2)
-struct hostent *hp1, *hp2;
+#ifdef INET6
+struct addrinfo *find_inet_addr(host)
+char *host;
{
- struct hostent_block {
- struct hostent host;
- char *addr_list[1];
- };
- struct hostent_block *hb;
- int count, count2;
- char *data;
- char *addr;
-
- for (count = 0; hp1->h_addr_list[count] != 0; count++)
- /* void */ ;
- for (count2 = 0; hp2->h_addr_list[count2] != 0; count2++)
- /* void */ ;
- count += count2;
-
- if ((hb = (struct hostent_block *) malloc(sizeof(struct hostent_block)
- + strlen(hp1->h_name) + 1
- + (hp1->h_length + sizeof(char *)) * count)) == 0) {
- fprintf(stderr, "Sorry, out of memory\n");
- exit(1);
+ struct addrinfo hints, *res;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+ if (getaddrinfo(host, NULL, &hints, &res) == 0)
+ return (res);
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
+ if (getaddrinfo(host, NULL, &hints, &res) != 0) {
+ tcpd_warn("%s: host not found", host);
+ return (0);
}
- memset((char *) &hb->host, 0, sizeof(hb->host));
- hb->host.h_length = hp1->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);
- hb->host.h_name = data + hp1->h_length * count;
- strcpy(hb->host.h_name, hp1->h_name);
- hb->host.h_addrtype = hp1->h_addrtype;
-
- for (count = 0; (addr = hp1->h_addr_list[count]) != 0; count++) {
- hb->host.h_addr_list[count] = data + hp1->h_length * count;
- memcpy(hb->host.h_addr_list[count], addr, hp1->h_length);
+ if (res->ai_family != AF_INET6 && res->ai_family != AF_INET) {
+ tcpd_warn("%d: not an internet host", res->ai_family);
+ freeaddrinfo(res);
+ return (0);
}
- for (count2 = 0; (addr = hp2->h_addr_list[count2]) != 0; count2++) {
- hb->host.h_addr_list[count] = data + hp1->h_length * count;
- memcpy(hb->host.h_addr_list[count], addr, hp1->h_length);
- ++count;
+ if (!res->ai_canonname) {
+ tcpd_warn("%s: hostname alias", host);
+ tcpd_warn("(cannot obtain official name)", res->ai_canonname);
+ } else if (STR_NE(host, res->ai_canonname)) {
+ tcpd_warn("%s: hostname alias", host);
+ tcpd_warn("(official name: %.*s)", STRING_LENGTH, res->ai_canonname);
}
- return (&hb->host);
+ return (res);
}
-#endif
-
-static struct hostent *gethostbyname64(host)
-char *host;
-{
- struct hostent *hp = NULL, *hp2 = NULL;
-#ifdef USE_GETIPNODEBY
- int h_error;
-
- if ((hp = getipnodebyname(host, AF_INET6,
- AI_V4MAPPED | AI_ADDRCONFIG | AI_ALL,
- &h_error)) != 0) {
- hp2 = dup_hostent(hp);
- freehostent(hp);
- return (hp2);
- }
#else
- struct hostent *hp1;
- u_long res_options;
-
- if ((_res.options & RES_INIT) == 0) {
- if (res_init() < 0) {
- tcpd_warn("%s: res_init() failed", host);
- return (NULL);
- }
- }
- res_options = _res.options;
-#ifdef INET6
- _res.options |= RES_USE_INET6;
- if ((hp1 = gethostbyname2(host, AF_INET6)) != NULL)
- hp1 = dup_hostent(hp1);
-#endif
- if ((hp2 = gethostbyname2(host, AF_INET)) != NULL)
- hp2 = dup_hostent(hp2);
- _res.options = res_options;
-#ifdef INET6
- if (hp1 && hp2) {
- hp = merge_hostent(hp1, hp2);
- free((char *) hp1);
- free((char *) hp2);
- return (hp);
- }
- if (hp1)
- return (hp1);
-#endif
- if (hp2)
- return (hp2);
-#endif
- return (NULL);
-}
-
-/* find_inet_addr - find all addresses for this host, result to free() */
-
struct hostent *find_inet_addr(host)
char *host;
{
@@ -192,7 +125,6 @@ char *host;
struct hostent *hp;
static struct hostent h;
static char *addr_list[2];
- static char hnamebuf[BUFSIZ];
/*
* Host address: translate it to internal form.
@@ -201,11 +133,6 @@ char *host;
h.h_addr_list = addr_list;
h.h_addr_list[0] = (char *) &addr;
h.h_length = sizeof(addr);
-#ifdef INET6
- h.h_addrtype = AF_INET;
- h.h_name = hnamebuf;
- strcpy(h.h_name, host);
-#endif
return (dup_hostent(&h));
}
@@ -219,34 +146,21 @@ char *host;
tcpd_warn("%s: not an internet address", host);
return (0);
}
-#ifdef INET6
- if ((hp = gethostbyname64(host)) == 0) {
-#else
if ((hp = gethostbyname(host)) == 0) {
-#endif
tcpd_warn("%s: host not found", host);
return (0);
}
-#ifdef INET6
- if (hp->h_addrtype != AF_INET6) {
- tcpd_warn("%d: not an internet host", hp->h_addrtype);
- free((char *) hp);
-#else
if (hp->h_addrtype != AF_INET) {
tcpd_warn("%d: not an internet host", hp->h_addrtype);
-#endif
return (0);
}
if (STR_NE(host, hp->h_name)) {
tcpd_warn("%s: hostname alias", host);
tcpd_warn("(official name: %.*s)", STRING_LENGTH, hp->h_name);
}
-#ifdef INET6
- return (hp);
-#else
return (dup_hostent(hp));
-#endif
}
+#endif
/* check_dns - give each address thorough workout, return address count */
@@ -256,12 +170,11 @@ char *host;
struct request_info request;
#ifdef INET6
struct sockaddr_storage sin;
- char *ap;
- int alen;
+ struct addrinfo *hp, *res;
#else
struct sockaddr_in sin;
-#endif
struct hostent *hp;
+#endif
int count;
char *addr;
@@ -269,29 +182,16 @@ char *host;
return (0);
request_init(&request, RQ_CLIENT_SIN, &sin, 0);
sock_methods(&request);
+#ifndef INET6
memset((char *) &sin, 0, sizeof(sin));
-#ifdef INET6
- sin.ss_family = hp->h_addrtype;
- switch (hp->h_addrtype) {
- case AF_INET:
- ap = (char *)&((struct sockaddr_in *)&sin)->sin_addr;
- alen = sizeof(struct sockaddr_in);
- break;
- case AF_INET6:
- ap = (char *)&((struct sockaddr_in6 *)&sin)->sin6_addr;
- alen = sizeof(struct sockaddr_in6);
- break;
- default:
- return (0);
- }
-#else
sin.sin_family = AF_INET;
#endif
- for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
#ifdef INET6
- memcpy(ap, addr, alen);
+ for (res = hp, count = 0; res; res = res->ai_next, count++) {
+ memcpy(&sin, res->ai_addr, res->ai_addrlen);
#else
+ for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr));
#endif
@@ -306,7 +206,11 @@ char *host;
tcpd_warn("host address %s->name lookup failed",
eval_hostaddr(request.client));
}
+#ifdef INET6
+ freeaddrinfo(hp);
+#else
free((char *) hp);
+#endif
return (count);
}
diff --git a/contrib/tcp_wrappers/scaffold.h b/contrib/tcp_wrappers/scaffold.h
index 2273f47..ea568b7 100644
--- a/contrib/tcp_wrappers/scaffold.h
+++ b/contrib/tcp_wrappers/scaffold.h
@@ -2,8 +2,14 @@
* @(#) scaffold.h 1.3 94/12/31 18:19:19
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
+ *
+ * $FreeBSD$
*/
+#ifdef INET6
+extern struct addrinfo *find_inet_addr();
+#else
extern struct hostent *find_inet_addr();
+#endif
extern int check_dns();
extern int check_path();
diff --git a/contrib/tcp_wrappers/socket.c b/contrib/tcp_wrappers/socket.c
index d2370e0..0a24aca 100644
--- a/contrib/tcp_wrappers/socket.c
+++ b/contrib/tcp_wrappers/socket.c
@@ -33,12 +33,12 @@ static char sccsid[] = "@(#) socket.c 1.15 97/03/21 19:27:24";
#include <string.h>
#ifdef INET6
-#ifndef USE_GETIPNODEBY
-#include <resolv.h>
+#ifndef NI_WITHSCOPEID
+#define NI_WITHSCOPEID 0
#endif
-#endif
-
+#else
extern char *inet_ntoa();
+#endif
/* Local stuff. */
@@ -148,25 +148,18 @@ struct host_info *host;
{
#ifdef INET6
struct sockaddr *sin = host->sin;
- char *ap;
- int alen;
+ int salen;
if (!sin)
return;
- switch (sin->sa_family) {
- case AF_INET:
- ap = (char *)&((struct sockaddr_in *)sin)->sin_addr;
- alen = sizeof(struct in_addr);
- break;
- case AF_INET6:
- ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr;
- alen = sizeof(struct in6_addr);
- break;
- default:
- return;
- }
- host->addr[0] = '\0';
- inet_ntop(sin->sa_family, ap, host->addr, sizeof(host->addr));
+#ifdef SIN6_LEN
+ salen = sin->sa_len;
+#else
+ salen = (sin->sa_family == AF_INET) ? sizeof(struct sockaddr_in)
+ : sizeof(struct sockaddr_in6);
+#endif
+ getnameinfo(sin, salen, host->addr, sizeof(host->addr),
+ NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
#else
struct sockaddr_in *sin = host->sin;
@@ -182,19 +175,134 @@ struct host_info *host;
{
#ifdef INET6
struct sockaddr *sin = host->sin;
- char addr[128];
-#ifdef USE_GETIPNODEBY
- int h_error;
-#else
- u_long res_options;
+ struct sockaddr_in sin4;
+ struct addrinfo hints, *res, *res0 = NULL;
+ int salen, alen, err = 1;
+ char *ap = NULL, *rap, hname[NI_MAXHOST];
+
+ if (sin != NULL) {
+ if (sin->sa_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sin;
+
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+ memset(&sin4, 0, sizeof(sin4));
+#ifdef SIN6_LEN
+ sin4.sin_len = sizeof(sin4);
#endif
- struct hostent *hp = NULL;
- char *ap;
- int alen;
-#else
+ sin4.sin_family = AF_INET;
+ sin4.sin_port = sin6->sin6_port;
+ sin4.sin_addr.s_addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12];
+ sin = (struct sockaddr *)&sin4;
+ }
+ }
+ switch (sin->sa_family) {
+ case AF_INET:
+ ap = (char *)&((struct sockaddr_in *)sin)->sin_addr;
+ alen = sizeof(struct in_addr);
+ salen = sizeof(struct sockaddr_in);
+ break;
+ case AF_INET6:
+ ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr;
+ alen = sizeof(struct in6_addr);
+ salen = sizeof(struct sockaddr_in6);
+ break;
+ default:
+ break;
+ }
+ if (ap)
+ err = getnameinfo(sin, salen, hname, sizeof(hname),
+ NULL, 0, NI_WITHSCOPEID | NI_NAMEREQD);
+ }
+ if (!err) {
+
+ STRN_CPY(host->name, hname, sizeof(host->name));
+
+ /*
+ * Verify that the address is a member of the address list returned
+ * by gethostbyname(hostname).
+ *
+ * Verify also that gethostbyaddr() and gethostbyname() return the same
+ * hostname, or rshd and rlogind may still end up being spoofed.
+ *
+ * On some sites, gethostbyname("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")
+ * we're in big trouble anyway.
+ */
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = sin->sa_family;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
+ if (getaddrinfo(host->name, NULL, &hints, &res0) != 0) {
+
+ /*
+ * 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: getaddrinfo(%s, %s) failed",
+ host->name,
+ (sin->sa_family == AF_INET) ? "AF_INET" : "AF_INET6");
+
+ } else if (STR_NE(host->name, res0->ai_canonname)
+ && STR_NE(host->name, "localhost")) {
+
+ /*
+ * The gethostbyaddr() and gethostbyname() 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, res0->ai_canonname);
+
+ } 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.
+ */
+
+ for (res = res0; res; res = res->ai_next) {
+ if (res->ai_family != sin->sa_family)
+ continue;
+ switch (res->ai_family) {
+ case AF_INET:
+ rap = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr;
+ break;
+ case AF_INET6:
+ rap = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
+ break;
+ default:
+ continue;
+ }
+ if (memcmp(rap, ap, alen) == 0) {
+ freeaddrinfo(res0);
+ return; /* name is good, keep it */
+ }
+ }
+
+ /*
+ * The host name does not map to the initial address. Perhaps
+ * someone has messed up. Perhaps someone compromised a name
+ * server.
+ */
+
+ getnameinfo(sin, salen, hname, sizeof(hname),
+ NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
+ tcpd_warn("host name/address mismatch: %s != %.*s",
+ hname, STRING_LENGTH, res0->ai_canonname);
+ }
+ strcpy(host->name, paranoid); /* name is bad, clobber it */
+ if (res0)
+ freeaddrinfo(res0);
+ }
+#else /* INET6 */
struct sockaddr_in *sin = host->sin;
struct hostent *hp;
-#endif
int i;
/*
@@ -204,42 +312,11 @@ struct host_info *host;
* have to special-case 0.0.0.0, in order to avoid false alerts from the
* host name/address checking code below.
*/
-#ifdef INET6
- if (sin != NULL) {
- switch (sin->sa_family) {
- case AF_INET:
- if (((struct sockaddr_in *)sin)->sin_addr.s_addr == 0) {
- strcpy(host->name, paranoid); /* name is bad, clobber it */
- return;
- }
- ap = (char *) &((struct sockaddr_in *)sin)->sin_addr;
- alen = sizeof(struct in_addr);
- break;
- case AF_INET6:
- ap = (char *) &((struct sockaddr_in6 *)sin)->sin6_addr;
- alen = sizeof(struct in6_addr);
- break;
- defalut:
- strcpy(host->name, paranoid); /* name is bad, clobber it */
- return;
- }
-#ifdef USE_GETIPNODEBY
- hp = getipnodebyaddr(ap, alen, sin->sa_family, &h_error);
-#else
- hp = gethostbyaddr(ap, alen, sin->sa_family);
-#endif
- }
- if (hp) {
-#else
if (sin != 0 && sin->sin_addr.s_addr != 0
&& (hp = gethostbyaddr((char *) &(sin->sin_addr),
sizeof(sin->sin_addr), AF_INET)) != 0) {
-#endif
STRN_CPY(host->name, hp->h_name, sizeof(host->name));
-#if defined(INET6) && defined(USE_GETIPNODEBY)
- freehostent(hp);
-#endif
/*
* Verify that the address is a member of the address list returned
@@ -254,53 +331,15 @@ struct host_info *host;
* we're in big trouble anyway.
*/
-#ifdef INET6
-#ifdef USE_GETIPNODEBY
- hp = getipnodebyname(host->name, sin->sa_family,
- AI_V4MAPPED | AI_ADDRCONFIG | AI_ALL, &h_error);
-#else
- if ((_res.options & RES_INIT) == 0) {
- if (res_init() < 0) {
- inet_ntop(sin->sa_family, ap, addr, sizeof(addr));
- tcpd_warn("can't verify hostname: res_init() for %s failed",
- addr);
- strcpy(host->name, paranoid); /* name is bad, clobber it */
- return;
- }
- }
- res_options = _res.options;
- if (sin->sa_family == AF_INET6)
- _res.options |= RES_USE_INET6;
- else
- _res.options &= ~RES_USE_INET6;
- hp = gethostbyname2(host->name,
- (sin->sa_family == AF_INET6 &&
- IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sin)->sin6_addr)) ?
- AF_INET : sin->sa_family);
- _res.options = res_options;
-#endif
- if (!hp) {
-#else
if ((hp = gethostbyname(host->name)) == 0) {
-#endif
/*
* Unable to verify that the host name matches the address. This
* may be a transient problem or a botched name server setup.
*/
-#ifdef INET6
-#ifdef USE_GETIPNODEBY
- tcpd_warn("can't verify hostname: getipnodebyname(%s, %s) failed",
-#else
- tcpd_warn("can't verify hostname: gethostbyname2(%s, %s) failed",
-#endif
- host->name,
- (sin->sa_family == AF_INET) ? "AF_INET" : "AF_INET6");
-#else
tcpd_warn("can't verify hostname: gethostbyname(%s) failed",
host->name);
-#endif
} else if (STR_NE(host->name, hp->h_name)
&& STR_NE(host->name, "localhost")) {
@@ -324,19 +363,10 @@ struct host_info *host;
*/
for (i = 0; hp->h_addr_list[i]; i++) {
-#ifdef INET6
- if (memcmp(hp->h_addr_list[i], ap, alen) == 0) {
-#ifdef USE_GETIPNODEBY
- freehostent(hp);
-#endif
- return; /* name is good, keep it */
- }
-#else
if (memcmp(hp->h_addr_list[i],
(char *) &sin->sin_addr,
sizeof(sin->sin_addr)) == 0)
return; /* name is good, keep it */
-#endif
}
/*
@@ -345,21 +375,12 @@ struct host_info *host;
* server.
*/
-#ifdef INET6
- inet_ntop(sin->sa_family, ap, addr, sizeof(addr));
- tcpd_warn("host name/address mismatch: %s != %.*s",
- addr, STRING_LENGTH, hp->h_name);
-#else
tcpd_warn("host name/address mismatch: %s != %.*s",
inet_ntoa(sin->sin_addr), STRING_LENGTH, hp->h_name);
-#endif
}
strcpy(host->name, paranoid); /* name is bad, clobber it */
-#if defined(INET6) && defined(USE_GETIPNODEBY)
- if (hp)
- freehostent(hp);
-#endif
}
+#endif /* INET6 */
}
/* sock_sink - absorb unreceived IP datagram */
diff --git a/contrib/tcp_wrappers/tcpdchk.c b/contrib/tcp_wrappers/tcpdchk.c
index a2804a2..99ec495 100644
--- a/contrib/tcp_wrappers/tcpdchk.c
+++ b/contrib/tcp_wrappers/tcpdchk.c
@@ -410,7 +410,7 @@ char *pat;
static int is_inet6_addr(pat)
char *pat;
{
- struct in6_addr addr;
+ struct addrinfo hints, *res;
int len, ret;
char ch;
@@ -420,9 +420,14 @@ static int is_inet6_addr(pat)
if ((ch = pat[len - 1]) != ']')
return (0);
pat[len - 1] = '\0';
- ret = inet_pton(AF_INET6, pat + 1, &addr);
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+ if ((ret = getaddrinfo(pat + 1, NULL, &hints, &res)) == 0)
+ freeaddrinfo(res);
pat[len - 1] = ch;
- return (ret == 1);
+ return (ret == 0);
}
#endif
diff --git a/contrib/tcp_wrappers/tcpdmatch.c b/contrib/tcp_wrappers/tcpdmatch.c
index f8c8dc1..94f3e700 100644
--- a/contrib/tcp_wrappers/tcpdmatch.c
+++ b/contrib/tcp_wrappers/tcpdmatch.c
@@ -59,7 +59,11 @@ int main(argc, argv)
int argc;
char **argv;
{
+#ifdef INET6
+ struct addrinfo hints, *hp, *res;
+#else
struct hostent *hp;
+#endif
char *myname = argv[0];
char *client;
char *server;
@@ -73,8 +77,6 @@ char **argv;
#ifdef INET6
struct sockaddr_storage server_sin;
struct sockaddr_storage client_sin;
- char *ap;
- int alen;
#else
struct sockaddr_in server_sin;
struct sockaddr_in client_sin;
@@ -181,33 +183,17 @@ char **argv;
if (NOT_INADDR(server) == 0 || HOSTNAME_KNOWN(server)) {
if ((hp = find_inet_addr(server)) == 0)
exit(1);
+#ifndef INET6
memset((char *) &server_sin, 0, sizeof(server_sin));
-#ifdef INET6
- 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 sockaddr_in);
- break;
- case AF_INET6:
- ap = (char *)&((struct sockaddr_in6 *)&server_sin)->sin6_addr;
- alen = sizeof(struct sockaddr_in6);
- break;
- default:
- exit(1);
- }
-#ifdef SIN6_LEN
- server_sin.ss_len = alen;
-#endif
-#else
server_sin.sin_family = AF_INET;
#endif
request_set(&request, RQ_SERVER_SIN, &server_sin, 0);
- for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
#ifdef INET6
- memcpy(ap, addr, alen);
+ for (res = hp, count = 0; res; res = res->ai_next, count++) {
+ memcpy(&server_sin, res->ai_addr, res->ai_addrlen);
#else
+ for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
memcpy((char *) &server_sin.sin_addr, addr,
sizeof(server_sin.sin_addr));
#endif
@@ -226,7 +212,11 @@ char **argv;
fprintf(stderr, "Please specify an address instead\n");
exit(1);
}
+#ifdef INET6
+ freeaddrinfo(hp);
+#else
free((char *) hp);
+#endif
} else {
request_set(&request, RQ_SERVER_NAME, server, 0);
}
@@ -240,6 +230,18 @@ char **argv;
tcpdmatch(&request);
exit(0);
}
+#ifdef INET6
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+ if (getaddrinfo(client, NULL, &hints, &res) == 0) {
+ freeaddrinfo(res);
+ request_set(&request, RQ_CLIENT_ADDR, client, 0);
+ tcpdmatch(&request);
+ exit(0);
+ }
+#endif
/*
* Perhaps they are testing special client hostname patterns that aren't
@@ -261,36 +263,41 @@ char **argv;
*/
if ((hp = find_inet_addr(client)) == 0)
exit(1);
- memset((char *) &client_sin, 0, sizeof(client_sin));
#ifdef INET6
- 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 sockaddr_in);
- break;
- case AF_INET6:
- ap = (char *)&((struct sockaddr_in6 *)&client_sin)->sin6_addr;
- alen = sizeof(struct sockaddr_in6);
- break;
- default:
- exit(1);
+ request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
+
+ for (res = hp, count = 0; res; res = res->ai_next, count++) {
+ memcpy(&client_sin, res->ai_addr, res->ai_addrlen);
+
+ /*
+ * getnameinfo() doesn't do reverse lookup against link-local
+ * address. So, we pass through host name evaluation against
+ * such addresses.
+ */
+ if (res->ai_family != AF_INET6 ||
+ !IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)) {
+ /*
+ * Force evaluation of client host name and address. Host name
+ * conflicts will be reported while eval_hostname() does its job.
+ */
+ request_set(&request, RQ_CLIENT_NAME, "", RQ_CLIENT_ADDR, "", 0);
+ if (STR_EQ(eval_hostname(request.client), unknown))
+ tcpd_warn("host address %s->name lookup failed",
+ eval_hostaddr(request.client));
+ }
+ tcpdmatch(&request);
+ if (res->ai_next)
+ printf("\n");
}
-#ifdef SIN6_LEN
- client_sin.ss_len = alen;
-#endif
+ freeaddrinfo(hp);
#else
+ memset((char *) &client_sin, 0, sizeof(client_sin));
client_sin.sin_family = AF_INET;
-#endif
request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
-#ifdef INET6
- memcpy(ap, addr, alen);
-#else
memcpy((char *) &client_sin.sin_addr, addr,
sizeof(client_sin.sin_addr));
-#endif
/*
* Force evaluation of client host name and address. Host name
@@ -305,6 +312,7 @@ char **argv;
printf("\n");
}
free((char *) hp);
+#endif
exit(0);
}
diff --git a/lib/libwrap/Makefile b/lib/libwrap/Makefile
index 4422cfa..022da44 100644
--- a/lib/libwrap/Makefile
+++ b/lib/libwrap/Makefile
@@ -17,7 +17,6 @@ CFLAGS+=-DFACILITY=LOG_AUTH -DHOSTS_ACCESS -DNETGROUP -DDAEMON_UMASK=022 \
-DSEVERITY=LOG_INFO -DRFC931_TIMEOUT=10 \
-DHOSTS_DENY=\"/etc/hosts.deny\" -DHOSTS_ALLOW=\"/etc/hosts.allow\" \
-DSYS_ERRLIST_DEFINED -DALWAYS_HOSTNAME
-CFLAGS+=-DUSE_GETIPNODEBY
.if !defined(NOINET6)
CFLAGS+=-DINET6
.endif
diff --git a/usr.sbin/tcpdchk/Makefile b/usr.sbin/tcpdchk/Makefile
index 86639f7..3393011 100644
--- a/usr.sbin/tcpdchk/Makefile
+++ b/usr.sbin/tcpdchk/Makefile
@@ -11,7 +11,9 @@ SRCS= tcpdchk.c fakelog.c inetcf.c scaffold.c
CFLAGS= -DREAL_DAEMON_DIR=\"/usr/libexec\" \
-DSEVERITY=LOG_INFO -DRFC931_TIMEOUT=10 \
-DHOSTS_DENY=\"/etc/hosts.deny\" -DHOSTS_ALLOW=\"/etc/hosts.allow\"
-CFLAGS+=-DINET6 -DUSE_GETIPNODEBY
+.if !defined(NOINET6)
+CFLAGS+=-DINET6
+.endif
DPADD= ${LIBWRAP}
LDADD= -lwrap
diff --git a/usr.sbin/tcpdmatch/Makefile b/usr.sbin/tcpdmatch/Makefile
index c29eb91..e69c050 100644
--- a/usr.sbin/tcpdmatch/Makefile
+++ b/usr.sbin/tcpdmatch/Makefile
@@ -10,6 +10,9 @@ SRCS= tcpdmatch.c fakelog.c inetcf.c scaffold.c
CFLAGS= -DREAL_DAEMON_DIR=\"/usr/libexec\" \
-DSEVERITY=LOG_INFO -DRFC931_TIMEOUT=10
+.if !defined(NOINET6)
+CFLAGS+=-DINET6
+.endif
DPADD= ${LIBWRAP}
LDADD= -lwrap
OpenPOWER on IntegriCloud