summaryrefslogtreecommitdiffstats
path: root/contrib/tcp_wrappers/scaffold.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/tcp_wrappers/scaffold.c')
-rw-r--r--contrib/tcp_wrappers/scaffold.c155
1 files changed, 155 insertions, 0 deletions
diff --git a/contrib/tcp_wrappers/scaffold.c b/contrib/tcp_wrappers/scaffold.c
index afce15a..ea87c5c 100644
--- a/contrib/tcp_wrappers/scaffold.c
+++ b/contrib/tcp_wrappers/scaffold.c
@@ -2,6 +2,8 @@
* Routines for testing only. Not really industrial strength.
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
+ *
+ * $FreeBSD$
*/
#ifndef lint
@@ -20,6 +22,7 @@ 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 */
@@ -57,6 +60,9 @@ 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);
@@ -66,6 +72,11 @@ 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;
@@ -74,6 +85,104 @@ struct hostent *hp;
return (&hb->host);
}
+#if defined(INET6) && !defined(USE_GETIPNODEBY)
+/* merge_hostent - merge hostent in one memory block */
+
+static struct hostent *merge_hostent(hp1, hp2)
+struct hostent *hp1, *hp2;
+{
+ 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);
+ }
+ 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);
+ }
+ 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;
+ }
+ return (&hb->host);
+}
+#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)
@@ -83,6 +192,7 @@ 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.
@@ -91,6 +201,11 @@ 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));
}
@@ -104,19 +219,33 @@ 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
}
/* check_dns - give each address thorough workout, return address count */
@@ -125,7 +254,13 @@ int check_dns(host)
char *host;
{
struct request_info request;
+#ifdef INET6
+ struct sockaddr_storage sin;
+ char *ap;
+ int alen;
+#else
struct sockaddr_in sin;
+#endif
struct hostent *hp;
int count;
char *addr;
@@ -135,10 +270,30 @@ char *host;
request_init(&request, RQ_CLIENT_SIN, &sin, 0);
sock_methods(&request);
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);
+#else
memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr));
+#endif
/*
* Force host name and address conversions. Use the request structure
OpenPOWER on IntegriCloud