commit abbd68b4d322d5eb3cdd3fbeac4e333fd0d926fa
Author: zyppe <210hcl@gmail.com>
Date:   Thu Feb 29 16:02:30 2024 +0800

    Initialize for tcpd

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..59e6073
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+tcp_wrappers_7.6.tar.gz
diff --git a/.tcpd.metadata b/.tcpd.metadata
new file mode 100644
index 0000000..3829458
--- /dev/null
+++ b/.tcpd.metadata
@@ -0,0 +1 @@
+794012172be74df89c5a0131b1c89fa3fe6fb6332d0239fcee1da0b2442338ed tcp_wrappers_7.6.tar.gz
diff --git a/baselibs.conf b/baselibs.conf
new file mode 100644
index 0000000..15f1a2a
--- /dev/null
+++ b/baselibs.conf
@@ -0,0 +1,4 @@
+libwrap0
+    obsoletes "tcpd-<targettype> <= <version>"
+    provides  "tcpd-<targettype> = <version>"
+arch ppc package tcpd-devel
diff --git a/tcp_wrappers_7.6-builtin.diff b/tcp_wrappers_7.6-builtin.diff
new file mode 100644
index 0000000..0f297a5
--- /dev/null
+++ b/tcp_wrappers_7.6-builtin.diff
@@ -0,0 +1,19 @@
+--- scaffold.c.orig
++++ scaffold.c
+@@ -20,6 +20,8 @@ static char sccs_id[] = "@(#) scaffold.c
+ #include <syslog.h>
+ #include <setjmp.h>
+ #include <string.h>
++#include <stdlib.h>
++
+ #if defined(INET6) && !defined(USE_GETIPNODEBY)
+ #include <resolv.h>
+ #endif
+@@ -28,7 +30,6 @@ static char sccs_id[] = "@(#) scaffold.c
+ #define	INADDR_NONE	(-1)		/* XXX should be 0xffffffff */
+ #endif
+ 
+-extern char *malloc();
+ 
+ /* Application-specific. */
+ 
diff --git a/tcp_wrappers_7.6-fedora-bug11881.diff b/tcp_wrappers_7.6-fedora-bug11881.diff
new file mode 100644
index 0000000..3d402a7
--- /dev/null
+++ b/tcp_wrappers_7.6-fedora-bug11881.diff
@@ -0,0 +1,35 @@
+--- eval.c.orig
++++ eval.c
+@@ -111,7 +111,7 @@ struct request_info *request;
+ 	return (hostinfo);
+ #endif
+     if (STR_NE(eval_user(request), unknown)) {
+-	sprintf(both, "%s@%s", request->user, hostinfo);
++	snprintf(both, sizeof(both), "%s@%s", request->user, hostinfo);
+ 	return (both);
+     } else {
+ 	return (hostinfo);
+@@ -128,7 +128,7 @@ struct request_info *request;
+     char   *daemon = eval_daemon(request);
+ 
+     if (STR_NE(host, unknown)) {
+-	sprintf(both, "%s@%s", daemon, host);
++	snprintf(both, sizeof(both), "%s@%s", daemon, host);
+ 	return (both);
+     } else {
+ 	return (daemon);
+--- tcpd.c.orig
++++ tcpd.c
+@@ -61,10 +61,10 @@ char  **argv;
+      */
+ 
+     if (argv[0][0] == '/') {
+-	strcpy(path, argv[0]);
++	strncpy(path, argv[0], sizeof(path));
+ 	argv[0] = strrchr(argv[0], '/') + 1;
+     } else {
+-	sprintf(path, "%s/%s", REAL_DAEMON_DIR, argv[0]);
++	snprintf(path, sizeof(path), "%s/%s", REAL_DAEMON_DIR, argv[0]);
+     }
+ 
+     /*
diff --git a/tcp_wrappers_7.6-fedora-bug141110.diff b/tcp_wrappers_7.6-fedora-bug141110.diff
new file mode 100644
index 0000000..e3f76f3
--- /dev/null
+++ b/tcp_wrappers_7.6-fedora-bug141110.diff
@@ -0,0 +1,20 @@
+--- hosts_access.c.orig
++++ hosts_access.c
+@@ -146,7 +146,7 @@ struct request_info *request;
+     verdict = setjmp(tcpd_buf);
+     if (verdict != 0)
+ 	return (verdict == AC_PERMIT);
+-    if (table_match(hosts_allow_table, request))
++    if (table_match(hosts_allow_table, request) == YES)
+ 	return (YES);
+     if (table_match(hosts_deny_table, request))
+ 	return (NO);
+@@ -195,7 +195,7 @@ struct request_info *request;
+     } else if (errno != ENOENT) {
+ 	tcpd_warn("cannot open %s: %m", table);
+     }
+-    if (match) {
++    if (match == YES) {
+ 	if (hosts_access_verbose > 1)
+ 	    syslog(LOG_DEBUG, "matched:  %s line %d",
+ 		   tcpd_context.file, tcpd_context.line);
diff --git a/tcp_wrappers_7.6-fedora-bug17795.diff b/tcp_wrappers_7.6-fedora-bug17795.diff
new file mode 100644
index 0000000..87dd239
--- /dev/null
+++ b/tcp_wrappers_7.6-fedora-bug17795.diff
@@ -0,0 +1,54 @@
+--- hosts_access.5.orig
++++ hosts_access.5
+@@ -90,6 +90,13 @@ bitwise AND of the address and the `mask
+ pattern `131.155.72.0/255.255.254.0\' matches every address in the
+ range `131.155.72.0\' through `131.155.73.255\'.
+ .IP \(bu
++A string that begins with a `/\' character is treated as a file
++name. A host name or address is matched if it matches any host name
++or address pattern listed in the named file. The file format is
++zero or more lines with zero or more host name or address patterns
++separated by whitespace.  A file name pattern can be used anywhere
++a host name or address pattern can be used.
++.IP \(bu
+ An expression of the form `[n:n:n:n:n:n:n:n]/m\' is interpreted as a
+ `[net]/prefixlen\' pair. A IPv6 host address is matched if
+ `prefixlen\' bits of `net\' is equal to the `prefixlen\' bits of the
+--- hosts_access.c.orig
++++ hosts_access.c
+@@ -273,6 +273,26 @@ struct request_info *request;
+     }
+ }
+ 
++/* hostfile_match - look up host patterns from file */
++
++static int hostfile_match(path, host)
++char   *path;
++struct hosts_info *host;
++{
++    char    tok[BUFSIZ];
++    int     match = NO;
++    FILE   *fp;
++
++    if ((fp = fopen(path, "r")) != 0) {
++	while (fscanf(fp, "%s", tok) == 1 && !(match = host_match(tok, host)))
++	     /* void */ ;
++	fclose(fp);
++    } else if (errno != ENOENT) {
++	tcpd_warn("open %s: %m", path);
++    }
++    return (match);
++}
++
+ /* host_match - match host name and/or address against pattern */
+ 
+ static int host_match(tok, host)
+@@ -300,6 +320,8 @@ struct host_info *host;
+ 	tcpd_warn("netgroup support is disabled");	/* not tcpd_jump() */
+ 	return (NO);
+ #endif
++    } else if (tok[0] == '/') {			/* /file hack */
++	return (hostfile_match(tok, host));
+     } else if (STR_EQ(tok, "KNOWN")) {		/* check address and name */
+ 	char   *name = eval_hostname(host);
+ 	return (STR_NE(eval_hostaddr(host), unknown) && HOSTNAME_KNOWN(name));
diff --git a/tcp_wrappers_7.6-fedora-bug17847.diff b/tcp_wrappers_7.6-fedora-bug17847.diff
new file mode 100644
index 0000000..483c505
--- /dev/null
+++ b/tcp_wrappers_7.6-fedora-bug17847.diff
@@ -0,0 +1,100 @@
+--- hosts_access.5.orig
++++ hosts_access.5
+@@ -103,6 +103,10 @@ An expression of the form `[n:n:n:n:n:n:
+ address. For example, the [net]/prefixlen pattern
+ `[3ffe:505:2:1::]/64\' matches every address in the range
+ `3ffe:505:2:1::\' through `3ffe:505:2:1:ffff:ffff:ffff:ffff\'.
++.IP \(bu
++Wildcards `*\' and `?\' can be used to match hostnames or IP addresses.  This
++method of matching cannot be used in conjunction with `net/mask\' matching,
++hostname matching beginning with `.\' or IP address matching ending with `.\'.
+ .SH WILDCARDS
+ The access control language supports explicit wildcards:
+ .IP ALL
+--- hosts_access.c.orig
++++ hosts_access.c
+@@ -346,6 +346,12 @@ char   *string;
+ {
+     int     n;
+ 
++#ifndef DISABLE_WILDCARD_MATCHING
++    if (strchr(tok, '*') || strchr(tok,'?')) {  /* contains '*' or '?' */
++        return (match_pattern_ylo(string,tok));
++    } else
++#endif
++
+     if (tok[0] == '.') {			/* suffix */
+ 	n = strlen(string) - strlen(tok);
+ 	return (n > 0 && STR_EQ(tok, string + n));
+@@ -454,3 +460,71 @@ char   *string;
+     }
+ #endif
+ }
++
++#ifndef DISABLE_WILDCARD_MATCHING
++/* Note: this feature has been adapted in a pretty straightforward way
++   from Tatu Ylonen's last SSH version under free license by
++   Pekka Savola <pekkas@netcore.fi>.
++
++   Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
++*/
++
++/* Returns true if the given string matches the pattern (which may contain
++   ? and * as wildcards), and zero if it does not match. */
++
++int match_pattern_ylo(const char *s, const char *pattern)
++{
++  while (1)
++    {
++      /* If at end of pattern, accept if also at end of string. */
++      if (!*pattern)
++        return !*s;
++
++      /* Process '*'. */
++      if (*pattern == '*')
++        {
++	  /* Skip the asterisk. */
++	  pattern++;
++
++	  /* If at end of pattern, accept immediately. */
++          if (!*pattern)
++            return 1;
++
++	  /* If next character in pattern is known, optimize. */
++          if (*pattern != '?' && *pattern != '*')
++            {
++	      /* Look instances of the next character in pattern, and try
++		 to match starting from those. */
++              for (; *s; s++)
++                if (*s == *pattern &&
++                    match_pattern_ylo(s + 1, pattern + 1))
++                  return 1;
++	      /* Failed. */
++              return 0;
++            }
++
++	  /* Move ahead one character at a time and try to match at each
++	     position. */
++          for (; *s; s++)
++            if (match_pattern_ylo(s, pattern))
++              return 1;
++	  /* Failed. */
++          return 0;
++        }
++
++      /* There must be at least one more character in the string.  If we are
++	 at the end, fail. */
++      if (!*s)
++        return 0;
++
++      /* Check if the next character of the string is acceptable. */
++      if (*pattern != '?' && *pattern != *s)
++	return 0;
++
++      /* Move to the next character, both in string and in pattern. */
++      s++;
++      pattern++;
++    }
++  /*NOTREACHED*/
++}
++#endif /* DISABLE_WILDCARD_MATCHING */
diff --git a/tcp_wrappers_7.6-fedora-bug220015.diff b/tcp_wrappers_7.6-fedora-bug220015.diff
new file mode 100644
index 0000000..36b5593
--- /dev/null
+++ b/tcp_wrappers_7.6-fedora-bug220015.diff
@@ -0,0 +1,92 @@
+--- hosts_ctl.c.orig
++++ hosts_ctl.c
+@@ -29,10 +29,12 @@ char   *user;
+ {
+     struct request_info request;
+ 
+-    return (hosts_access(request_init(&request,
+-				      RQ_DAEMON, daemon,
+-				      RQ_CLIENT_NAME, name,
+-				      RQ_CLIENT_ADDR, addr,
+-				      RQ_USER, user,
+-				      0)));
++    request_init(&request, RQ_DAEMON, daemon,
++			   RQ_CLIENT_NAME, name,
++			   RQ_CLIENT_ADDR, addr,
++			   RQ_USER, user,
++			   0);
++    sock_hostnofd(&request);
++
++    return (hosts_access(&request));
+ }
+--- socket.c.orig
++++ socket.c
+@@ -140,6 +140,53 @@ struct request_info *request;
+ #endif
+ }
+ 
++
++
++/* sock_hostnofd - look up endpoint addresses and install conversion methods */
++
++void    sock_hostnofd(request)
++struct request_info *request;
++{
++    static struct sockaddr_storage client;
++    struct addrinfo hints, *res;
++    int     ret;
++    char    *host;
++
++    /* If the address field is non-empty and non-unknown and if the hostname
++     * field is empty or unknown, use the address field to get the sockaddr
++     * and hostname. */
++    if (strlen(request->client->addr) &&
++	    HOSTNAME_KNOWN(request->client->addr) &&
++	    (!strlen(request->client->addr) ||
++		!HOSTNAME_KNOWN(request->client->name)))
++	host = request->client->addr;
++    else
++	return;
++
++    memset(&hints, 0, sizeof(hints));
++    hints.ai_family = AF_INET6;
++    hints.ai_socktype = SOCK_STREAM;
++    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
++
++    ret = getaddrinfo(host, NULL, &hints, &res);
++    if (ret != 0) {
++	hints.ai_family = AF_INET;
++	ret = getaddrinfo(host, NULL, &hints, &res);
++    }
++
++    if (ret != 0) {
++	tcpd_warn("can't resolve hostname (%s): %s", host, gai_strerror(ret));
++    } else {
++	sock_methods(request);
++
++	memcpy(&client, res->ai_addr, res->ai_addrlen);
++	request->client->sin = (struct sockaddr *)&client;
++	freeaddrinfo(res);
++
++	request->client->name[0] = 0;
++    }
++}
++
+ /* sock_hostaddr - map endpoint address to printable form */
+ 
+ void    sock_hostaddr(host)
+--- tcpd.h.orig
++++ tcpd.h
+@@ -174,10 +174,12 @@ extern char *eval_server();		/* whatever
+ 
+ #ifdef __STDC__
+ extern void sock_host(struct request_info *);
++extern void sock_hostnofd(struct request_info *);
+ extern void sock_hostname(struct host_info *);
+ extern void sock_hostaddr(struct host_info *);
+ #else
+ extern void sock_host();		/* look up endpoint addresses */
++extern void sock_hostnofd();
+ extern void sock_hostname();		/* translate address to hostname */
+ extern void sock_hostaddr();		/* address to printable address */
+ #endif
diff --git a/tcp_wrappers_7.6-fedora-docu.diff b/tcp_wrappers_7.6-fedora-docu.diff
new file mode 100644
index 0000000..159064b
--- /dev/null
+++ b/tcp_wrappers_7.6-fedora-docu.diff
@@ -0,0 +1,11 @@
+--- hosts_access.5.orig
++++ hosts_access.5
+@@ -329,7 +329,7 @@ in.tftpd: LOCAL, .my.domain
+ /etc/hosts.deny:
+ .in +3
+ .nf
+-in.tftpd: ALL: (/some/where/safe_finger -l @%h | \\
++in.tftpd: ALL: spawn (/some/where/safe_finger -l @%h | \\
+ 	/usr/ucb/mail -s %d-%h root) &
+ .fi
+ .PP
diff --git a/tcp_wrappers_7.6-fedora-fixgethostbyname.diff b/tcp_wrappers_7.6-fedora-fixgethostbyname.diff
new file mode 100644
index 0000000..a415b61
--- /dev/null
+++ b/tcp_wrappers_7.6-fedora-fixgethostbyname.diff
@@ -0,0 +1,25 @@
+--- socket.c.orig
++++ socket.c
+@@ -54,6 +54,7 @@ static struct hostent *gethostbyname_dot
+ char   *name;
+ {
+     char    dot_name[MAXHOSTNAMELEN + 1];
++    struct  hostent *hp;
+ 
+     /*
+      * Don't append dots to unqualified names. Such names are likely to come
+@@ -63,8 +64,12 @@ char   *name;
+     if (strchr(name, '.') == 0 || strlen(name) >= MAXHOSTNAMELEN - 1) {
+     return (gethostbyname(name));
+     } else {
+-    sprintf(dot_name, "%s.", name);
+-    return (gethostbyname(dot_name));
++        sprintf(dot_name, "%s.", name);
++        hp = gethostbyname(dot_name);
++	if (hp)
++	    return hp;
++	else
++	    return (gethostbyname(name));
+     }
+ }
+ 
diff --git a/tcp_wrappers_7.6-fedora-sig.diff b/tcp_wrappers_7.6-fedora-sig.diff
new file mode 100644
index 0000000..d5e8eeb
--- /dev/null
+++ b/tcp_wrappers_7.6-fedora-sig.diff
@@ -0,0 +1,39 @@
+--- hosts_access.c.orig
++++ hosts_access.c
+@@ -63,6 +63,7 @@ static char sep[] = ", \t\r\n";
+ 
+ #define	YES		1
+ #define	NO		0
++#define	ERR		-1
+ 
+  /*
+   * These variables are globally visible so that they can be redirected in
+@@ -125,7 +126,6 @@ int     hosts_access(request)
+ struct request_info *request;
+ {
+     int     verdict;
+-
+     /*
+      * If the (daemon, client) pair is matched by an entry in the file
+      * /etc/hosts.allow, access is granted. Otherwise, if the (daemon,
+@@ -148,9 +148,9 @@ struct request_info *request;
+ 	return (verdict == AC_PERMIT);
+     if (table_match(hosts_allow_table, request) == YES)
+ 	return (YES);
+-    if (table_match(hosts_deny_table, request))
+-	return (NO);
+-    return (YES);
++    if (table_match(hosts_deny_table, request) == NO)
++	return (YES);
++    return (NO);
+ }
+ 
+ /* table_match - match table entries with (daemon, client) pair */
+@@ -194,6 +194,7 @@ struct request_info *request;
+ 	(void) fclose(fp);
+     } else if (errno != ENOENT) {
+ 	tcpd_warn("cannot open %s: %m", table);
++	match = ERR;
+     }
+     if (match == YES) {
+ 	if (hosts_access_verbose > 1)
diff --git a/tcp_wrappers_7.6-fedora-sigalarm.diff b/tcp_wrappers_7.6-fedora-sigalarm.diff
new file mode 100644
index 0000000..204966e
--- /dev/null
+++ b/tcp_wrappers_7.6-fedora-sigalarm.diff
@@ -0,0 +1,36 @@
+--- rfc931.c.orig
++++ rfc931.c
+@@ -92,6 +92,8 @@ char   *dest;
+     char   *cp;
+     char   *result = unknown;
+     FILE   *fp;
++    unsigned saved_timeout;
++    struct sigaction nact, oact;
+ 
+ #ifdef INET6
+     /* address family must be the same */
+@@ -134,7 +136,12 @@ char   *dest;
+ 	 */
+ 
+ 	if (sigsetjmp(timebuf, 1) == 0) {
+-	    signal(SIGALRM, timeout);
++	    /* Save SIGALRM timer and handler. Sudheer Abdul-Salam, SUN. */
++	    saved_timeout = alarm(0);
++	    nact.sa_handler = timeout;
++	    nact.sa_flags = 0;
++	    (void) sigemptyset(&nact.sa_mask);
++	    (void) sigaction(SIGALRM, &nact, &oact);
+ 	    alarm(rfc931_timeout);
+ 
+ 	    /*
+@@ -223,6 +230,10 @@ char   *dest;
+ 	    }
+ 	    alarm(0);
+ 	}
++	/* Restore SIGALRM timer and handler. Sudheer Abdul-Salam, SUN. */
++	(void) sigaction(SIGALRM, &oact, NULL);
++	if (saved_timeout > 0)
++	    alarm(saved_timeout);
+ 	fclose(fp);
+     }
+     STRN_CPY(dest, result, STRING_LENGTH);
diff --git a/tcp_wrappers_7.6-fedora-sigchld.diff b/tcp_wrappers_7.6-fedora-sigchld.diff
new file mode 100644
index 0000000..8ab22b6
--- /dev/null
+++ b/tcp_wrappers_7.6-fedora-sigchld.diff
@@ -0,0 +1,87 @@
+--- shell_cmd.c.orig
++++ shell_cmd.c
+@@ -24,6 +24,11 @@ static char sccsid[] = "@(#) shell_cmd.c
+ #include <unistd.h>
+ #include <syslog.h>
+ #include <string.h>
++#include <errno.h>
++#include <unistd.h>
++#include <sys/wait.h>
++#include <sys/stat.h>
++#include <fcntl.h>
+ 
+ extern void exit();
+ 
+@@ -35,13 +40,42 @@ extern void exit();
+ 
+ static void do_child();
+ 
++/*
++ * The sigchld handler. If there is a SIGCHLD caused by a child other than
++ * ours, we set a flag and raise the signal later.
++ */
++volatile static int foreign_sigchld;
++volatile static int our_child_pid;
++static void sigchld(int sig, siginfo_t *si, void *unused)
++{
++    if (si && si->si_pid != our_child_pid)
++	foreign_sigchld = 1;
++}
++
+ /* shell_cmd - execute shell command */
+ 
+ void    shell_cmd(command)
+ char   *command;
+ {
+     int     child_pid;
+-    int     wait_pid;
++
++    struct sigaction new_action, old_action;
++    sigset_t new_mask, old_mask, empty_mask;
++
++    new_action.sa_sigaction = &sigchld;
++    new_action.sa_flags = SA_SIGINFO;
++    sigemptyset(&new_action.sa_mask);
++    sigemptyset(&new_mask);
++    sigemptyset(&empty_mask);
++    sigaddset(&new_mask, SIGCHLD);
++
++    /*
++     * Set the variables for handler, set the handler and block the signal
++     * until we have the pid.
++     */
++    foreign_sigchld = 0; our_child_pid = 0;
++    sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
++    sigaction(SIGCHLD, &new_action, &old_action);
+ 
+     /*
+      * Most of the work is done within the child process, to minimize the
+@@ -53,12 +87,26 @@ char   *command;
+ 	tcpd_warn("cannot fork: %m");
+ 	break;
+     case 00:					/* child */
++	/* Clear the blocked mask for the child not to be surprised. */
++	sigprocmask(SIG_SETMASK, &empty_mask, 0);
+ 	do_child(command);
+ 	/* NOTREACHED */
+     default:					/* parent */
+-	while ((wait_pid = wait((int *) 0)) != -1 && wait_pid != child_pid)
+-	     /* void */ ;
++	our_child_pid = child_pid;
++	sigprocmask(SIG_UNBLOCK, &new_mask, 0);
++	while (waitpid(child_pid, (int *) 0, 0) == -1 && errno == EINTR);
+     }
++
++    /*
++     * Revert the signal mask and the SIGCHLD handler.
++     */
++    sigprocmask(SIG_SETMASK, &old_mask, 0);
++    sigaction(SIGCHLD, &old_action, 0);
++
++    /* If there was a foreign SIGCHLD, raise it after we have restored the old
++     * mask and handler. */
++    if (foreign_sigchld)
++	raise(SIGCHLD);
+ }
+ 
+ /* do_child - exec command with { stdin, stdout, stderr } to /dev/null */
diff --git a/tcp_wrappers_7.6-fedora-sigjmp.diff b/tcp_wrappers_7.6-fedora-sigjmp.diff
new file mode 100644
index 0000000..0fc8998
--- /dev/null
+++ b/tcp_wrappers_7.6-fedora-sigjmp.diff
@@ -0,0 +1,29 @@
+--- rfc931.c.orig
++++ rfc931.c
+@@ -33,7 +33,7 @@ static char sccsid[] = "@(#) rfc931.c 1.
+ 
+ int     rfc931_timeout = RFC931_TIMEOUT;/* Global so it can be changed */
+ 
+-static jmp_buf timebuf;
++static sigjmp_buf timebuf;
+ 
+ /* fsocket - open stdio stream on top of socket */
+ 
+@@ -62,7 +62,7 @@ int     protocol;
+ static void timeout(sig)
+ int     sig;
+ {
+-    longjmp(timebuf, sig);
++    siglongjmp(timebuf, sig);
+ }
+ 
+ /* rfc931 - return remote user name, given socket structures */
+@@ -133,7 +133,7 @@ char   *dest;
+ 	 * Set up a timer so we won't get stuck while waiting for the server.
+ 	 */
+ 
+-	if (setjmp(timebuf) == 0) {
++	if (sigsetjmp(timebuf, 1) == 0) {
+ 	    signal(SIGALRM, timeout);
+ 	    alarm(rfc931_timeout);
+ 
diff --git a/tcp_wrappers_7.6-fedora-strerror.diff b/tcp_wrappers_7.6-fedora-strerror.diff
new file mode 100644
index 0000000..4bc6ae9
--- /dev/null
+++ b/tcp_wrappers_7.6-fedora-strerror.diff
@@ -0,0 +1,27 @@
+--- percent_m.c.orig
++++ percent_m.c
+@@ -13,7 +13,7 @@ static char sccsid[] = "@(#) percent_m.c
+ #include <string.h>
+ 
+ extern int errno;
+-#ifndef SYS_ERRLIST_DEFINED
++#if !defined(SYS_ERRLIST_DEFINED) && !defined(HAVE_STRERROR)
+ extern char *sys_errlist[];
+ extern int sys_nerr;
+ #endif
+@@ -29,11 +29,15 @@ char   *ibuf;
+ 
+     while (*bp = *cp)
+ 	if (*cp == '%' && cp[1] == 'm') {
++#ifdef HAVE_STRERROR
++            strcpy(bp, strerror(errno));
++#else
+ 	    if (errno < sys_nerr && errno > 0) {
+ 		strcpy(bp, sys_errlist[errno]);
+ 	    } else {
+ 		sprintf(bp, "Unknown error %d", errno);
+ 	    }
++#endif
+ 	    bp += strlen(bp);
+ 	    cp += 2;
+ 	} else {
diff --git a/tcp_wrappers_7.6-fix_options-fix.diff b/tcp_wrappers_7.6-fix_options-fix.diff
new file mode 100644
index 0000000..b263c03
--- /dev/null
+++ b/tcp_wrappers_7.6-fix_options-fix.diff
@@ -0,0 +1,11 @@
+--- fix_options.c.orig
++++ fix_options.c
+@@ -53,7 +53,7 @@ struct request_info *request;
+      * XXX IPv6 support?
+      */
+     sslen = sizeof(ss);
+-    if (getsockname(fd, (struct sockaddr *)&ss, &sslen < 0)) {
++    if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) {
+ 	syslog(LOG_ERR, "getpeername: %m");
+ 	clean_exit(request);
+     }
diff --git a/tcp_wrappers_7.6-host_name_mapping-fix.diff b/tcp_wrappers_7.6-host_name_mapping-fix.diff
new file mode 100644
index 0000000..46e6886
--- /dev/null
+++ b/tcp_wrappers_7.6-host_name_mapping-fix.diff
@@ -0,0 +1,27 @@
+--- socket.c.orig
++++ socket.c
+@@ -270,7 +270,6 @@ sock_hostname(struct host_info *host)
+         res = res->ai_next;
+     }
+ 
+-    freeaddrinfo (resbase);
+ 
+     if (res == NULL)
+     {
+@@ -279,6 +278,7 @@ sock_hostname(struct host_info *host)
+             host->name, 
+             inet_ntop2 (sin6->sin6_family, &sin6->sin6_addr));
+         strncpy(host->name, paranoid, sizeof(host->name));
++	freeaddrinfo (resbase);
+         return;
+     }
+ 
+@@ -289,7 +289,7 @@ sock_hostname(struct host_info *host)
+             host->name, res->ai_canonname,
+             inet_ntop2 (sin6->sin6_family, &sin6->sin6_addr));
+     }
+-    
++    freeaddrinfo (resbase);
+     return;
+ }
+ #else /* INET6 */
diff --git a/tcp_wrappers_7.6-hosts_ctl.diff b/tcp_wrappers_7.6-hosts_ctl.diff
new file mode 100644
index 0000000..5d688ef
--- /dev/null
+++ b/tcp_wrappers_7.6-hosts_ctl.diff
@@ -0,0 +1,10 @@
+--- tcpd.h.orig
++++ tcpd.h
+@@ -128,6 +128,7 @@ extern int resident;			/* > 0 if residen
+ #ifdef __STDC__
+ extern struct request_info *request_init(struct request_info *,...);
+ extern struct request_info *request_set(struct request_info *,...);
++extern int hosts_ctl(char *daemon, char *client_name, char *client_addr, char *client_user);
+ #else
+ extern struct request_info *request_init();	/* initialize request */
+ extern struct request_info *request_set();	/* update request structure */
diff --git a/tcp_wrappers_7.6-implicit-decl.patch b/tcp_wrappers_7.6-implicit-decl.patch
new file mode 100644
index 0000000..03f5053
--- /dev/null
+++ b/tcp_wrappers_7.6-implicit-decl.patch
@@ -0,0 +1,67 @@
+--- rfc931.c.orig
++++ rfc931.c
+@@ -23,7 +23,7 @@ static char sccsid[] = "@(#) rfc931.c 1.
+ #include <setjmp.h>
+ #include <signal.h>
+ #include <string.h>
+-
++#include <unistd.h>
+ /* Local stuff. */
+ 
+ #include "tcpd.h"
+--- safe_finger.c.orig
++++ safe_finger.c
+@@ -19,13 +19,16 @@ static char sccsid[] = "@(#) safe_finger
+ #endif
+ 
+ /* System libraries */
+-
++#include <stdlib.h>
++#include <unistd.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
++#include <sys/wait.h>
+ #include <signal.h>
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <pwd.h>
++#include <fcntl.h>
+ 
+ extern void exit();
+ 
+--- tcpdchk.c.orig
++++ tcpdchk.c
+@@ -20,6 +20,7 @@ static char sccsid[] = "@(#) tcpdchk.c 1
+ 
+ /* System libraries. */
+ 
++#include <stdlib.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #ifdef INET6
+@@ -33,6 +34,7 @@ static char sccsid[] = "@(#) tcpdchk.c 1
+ #include <errno.h>
+ #include <netdb.h>
+ #include <string.h>
++#include <unistd.h>
+ 
+ extern int errno;
+ extern void exit();
+--- tcpdmatch.c.orig
++++ tcpdmatch.c
+@@ -19,6 +19,7 @@ static char sccsid[] = "@(#) tcpdmatch.c
+ 
+ /* System libraries. */
+ 
++#include <stdlib.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <sys/socket.h>
+@@ -29,6 +30,7 @@ static char sccsid[] = "@(#) tcpdmatch.c
+ #include <syslog.h>
+ #include <setjmp.h>
+ #include <string.h>
++#include <unistd.h>
+ 
+ extern void exit();
+ extern int optind;
diff --git a/tcp_wrappers_7.6-ipv6-1.6.diff b/tcp_wrappers_7.6-ipv6-1.6.diff
new file mode 100644
index 0000000..126c7b1
--- /dev/null
+++ b/tcp_wrappers_7.6-ipv6-1.6.diff
@@ -0,0 +1,1146 @@
+;; IPv6 patch for tcp_wrappers_7.6 1.6
+;; Aug 23, 1999 by Hajimu UMEMOTO <ume@mahoroba.org>
+;;
+;; This patch supports IPv4/IPv6 dual stack and IPv4-mapped IPv6 address.
+;; You can replace stock tcpd or libwrap.a with this.
+;; IPv6 address pattern is as a `[net]/prefixlen' pair.
+;; This patch was tested on KAME/FreeBSD, KAME/FreeBSD3, KAME/NetBSD,
+;; RedHat 5.1 with kernel 2.1.126, and RedHat 6.0 with kernel 2.2.10.
+;;
+;; CAUTION:
+;; Back out change for field separater.  Now, field separater is `:'
+;; not `|'.  To specify IPv6 address, enclose IPv6 address with `['
+;; and `]'.
+;;
+;; For Linux users:
+;; If your libc doesn't have sockaddr_storage, try target `linux-old'.
+
+================================================================================
+--- fix_options.c.orig
++++ fix_options.c
+@@ -11,6 +11,9 @@ static char sccsid[] = "@(#) fix_options
+ 
+ #include <sys/types.h>
+ #include <sys/param.h>
++#ifdef INET6
++#include <sys/socket.h>
++#endif
+ #include <netinet/in.h>
+ #include <netinet/in_systm.h>
+ #include <netinet/ip.h>
+@@ -41,6 +44,22 @@ struct request_info *request;
+     unsigned int opt;
+     int     optlen;
+     struct in_addr dummy;
++#ifdef INET6
++    struct sockaddr_storage ss;
++    int sslen;
++
++    /*
++     * check if this is AF_INET socket
++     * XXX IPv6 support?
++     */
++    sslen = sizeof(ss);
++    if (getsockname(fd, (struct sockaddr *)&ss, &sslen < 0)) {
++	syslog(LOG_ERR, "getpeername: %m");
++	clean_exit(request);
++    }
++    if (ss.ss_family != AF_INET)
++	return;
++#endif
+ 
+     if ((ip = getprotobyname("ip")) != 0)
+ 	ipproto = ip->p_proto;
+--- hosts_access.5.orig
++++ hosts_access.5
+@@ -85,10 +85,17 @@ member of the specified netgroup. Netgro
+ for daemon process names or for client user names.
+ .IP \(bu
+ An expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a
+-`net/mask\' pair. A host address is matched if `net\' is equal to the
++`net/mask\' pair. A IPv4 host address is matched if `net\' is equal to the
+ bitwise AND of the address and the `mask\'. For example, the net/mask
+ pattern `131.155.72.0/255.255.254.0\' matches every address in the
+ range `131.155.72.0\' through `131.155.73.255\'.
++.IP \(bu
++An expression of the form `[n:n:n:n:n:n:n:n]/m\' is interpreted as a
++`[net]/prefixlen\' pair. A IPv6 host address is matched if
++`prefixlen\' bits of `net\' is equal to the `prefixlen\' bits of the
++address. For example, the [net]/prefixlen pattern
++`[3ffe:505:2:1::]/64\' matches every address in the range
++`3ffe:505:2:1::\' through `3ffe:505:2:1:ffff:ffff:ffff:ffff\'.
+ .SH WILDCARDS
+ The access control language supports explicit wildcards:
+ .IP ALL
+--- hosts_access.c.orig
++++ hosts_access.c
+@@ -25,6 +25,9 @@ static char sccsid[] = "@(#) hosts_acces
+ 
+ #include <sys/types.h>
+ #include <sys/param.h>
++#ifdef INET6
++#include <sys/socket.h>
++#endif
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <stdio.h>
+@@ -83,6 +86,10 @@ static int client_match();
+ static int host_match();
+ static int string_match();
+ static int masked_match();
++#ifdef INET6
++static int masked_match4();
++static int masked_match6();
++#endif
+ 
+ /* Size of logical line buffer. */
+ 
+@@ -317,6 +324,13 @@ char   *string;
+ {
+     int     n;
+ 
++#ifdef INET6
++    /* convert IPv4 mapped IPv6 address to IPv4 address */
++    if (STRN_EQ(string, "::ffff:", 7)
++	&& dot_quad_addr(string + 7) != INADDR_NONE) {
++	string += 7;
++    }
++#endif
+     if (tok[0] == '.') {			/* suffix */
+ 	n = strlen(string) - strlen(tok);
+ 	return (n > 0 && STR_EQ(tok, string + n));
+@@ -327,20 +341,55 @@ char   *string;
+     } else if (tok[(n = strlen(tok)) - 1] == '.') {	/* prefix */
+ 	return (STRN_EQ(tok, string, n));
+     } else {					/* exact match */
++#ifdef INET6
++	struct in6_addr pat, addr;
++	int len, ret;
++	char ch;
++
++	len = strlen(tok);
++	if (*tok == '[' && tok[len - 1] == ']') {
++	    ch = tok[len - 1];
++	    tok[len - 1] = '\0';
++	    ret = inet_pton(AF_INET6, tok + 1, pat.s6_addr);
++	    tok[len - 1] = ch;
++	    if (ret != 1 || inet_pton(AF_INET6, string, addr.s6_addr) != 1)
++		return NO;
++	    return (!memcmp(&pat, &addr, sizeof(struct in6_addr)));
++	}
++#endif
+ 	return (STR_EQ(tok, string));
+     }
+ }
+ 
+ /* masked_match - match address against netnumber/netmask */
+ 
++#ifdef INET6
+ static int masked_match(net_tok, mask_tok, string)
+ char   *net_tok;
+ char   *mask_tok;
+ char   *string;
+ {
++    return (masked_match4(net_tok, mask_tok, string) ||
++	    masked_match6(net_tok, mask_tok, string));
++}
++
++static int masked_match4(net_tok, mask_tok, string)
++#else
++static int masked_match(net_tok, mask_tok, string)
++#endif
++char   *net_tok;
++char   *mask_tok;
++char   *string;
++{
++#ifdef INET6
++    u_int32_t net;
++    u_int32_t mask;
++    u_int32_t addr;
++#else
+     unsigned long net;
+     unsigned long mask;
+     unsigned long addr;
++#endif
+ 
+     /*
+      * Disallow forms other than dotted quad: the treatment that inet_addr()
+@@ -352,8 +401,61 @@ char   *string;
+ 	return (NO);
+     if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
+ 	|| (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) {
++#ifndef INET6
+ 	tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
++#endif
+ 	return (NO);				/* not tcpd_jump() */
+     }
+     return ((addr & mask) == net);
+ }
++
++#ifdef INET6
++static int masked_match6(net_tok, mask_tok, string)
++char   *net_tok;
++char   *mask_tok;
++char   *string;
++{
++    struct in6_addr 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;
++
++    if (IN6_IS_ADDR_V4MAPPED(&addr)) {
++	if ((*(u_int32_t *)&net.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]);
++    }
++
++    /* match IPv6 address against netnumber/prefixlen */
++    len = strlen(net_tok);
++    if (*net_tok != '[' || net_tok[len - 1] != ']')
++	return NO;
++    ch = net_tok[len - 1];
++    net_tok[len - 1] = '\0';
++    if (inet_pton(AF_INET6, net_tok + 1, net.s6_addr) != 1) {
++	net_tok[len - 1] = ch;
++	return NO;
++    }
++    net_tok[len - 1] = ch;
++    if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128)
++	return NO;
++
++    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))
++		return NO;
++	    break;
++	}
++	if (*(u_int32_t *)&addr.s6_addr[i] != *(u_int32_t *)&net.s6_addr[i])
++	    return NO;
++	i += 4;
++	mask_len -= 32;
++    }
++    return YES;
++}
++#endif /* INET6 */
+--- inetcf.c.orig
++++ inetcf.c
+@@ -26,6 +26,9 @@ extern void exit();
+   * guesses. Shorter names follow longer ones.
+   */
+ char   *inet_files[] = {
++#ifdef INET6
++    "/usr/local/v6/etc/inet6d.conf",	/* KAME */
++#endif
+     "/private/etc/inetd.conf",		/* NEXT */
+     "/etc/inet/inetd.conf",		/* SYSV4 */
+     "/usr/etc/inetd.conf",		/* IRIX?? */
+--- misc.c.orig
++++ misc.c
+@@ -58,9 +58,31 @@ int     delimiter;
+ {
+     char   *cp;
+ 
++#ifdef INET6
++    int bracket = 0;
++
++    for (cp = string; cp && *cp; cp++) {
++	switch (*cp) {
++	case '[':
++	    bracket++;
++	    break;
++	case ']':
++	    bracket--;
++	    break;
++	default:
++	    if (bracket == 0 && *cp == delimiter) {
++		*cp++ = 0;
++		return cp;
++	    }
++	    break;
++	}
++    }
++    return (NULL);
++#else
+     if ((cp = strchr(string, delimiter)) != 0)
+ 	*cp++ = 0;
+     return (cp);
++#endif
+ }
+ 
+ /* dot_quad_addr - convert dotted quad to internal form */
+--- refuse.c.orig
++++ refuse.c
+@@ -25,7 +25,12 @@ static char sccsid[] = "@(#) refuse.c 1.
+ void    refuse(request)
+ struct request_info *request;
+ {
++#ifdef INET6
++    syslog(deny_severity, "refused connect from %s (%s)",
++	   eval_client(request), eval_hostaddr(request->client));
++#else
+     syslog(deny_severity, "refused connect from %s", eval_client(request));
++#endif
+     clean_exit(request);
+     /* NOTREACHED */
+ }
+--- rfc931.c.orig
++++ rfc931.c
+@@ -68,20 +68,50 @@ int     sig;
+ /* rfc931 - return remote user name, given socket structures */
+ 
+ void    rfc931(rmt_sin, our_sin, dest)
++#ifdef INET6
++struct sockaddr *rmt_sin;
++struct sockaddr *our_sin;
++#else
+ struct sockaddr_in *rmt_sin;
+ struct sockaddr_in *our_sin;
++#endif
+ char   *dest;
+ {
+     unsigned rmt_port;
+     unsigned our_port;
++#ifdef INET6
++    struct sockaddr_storage rmt_query_sin;
++    struct sockaddr_storage our_query_sin;
++    int alen;
++#else
+     struct sockaddr_in rmt_query_sin;
+     struct sockaddr_in our_query_sin;
++#endif
+     char    user[256];			/* XXX */
+     char    buffer[512];		/* XXX */
+     char   *cp;
+     char   *result = unknown;
+     FILE   *fp;
+ 
++#ifdef INET6
++    /* address family must be the same */
++    if (rmt_sin->sa_family != our_sin->sa_family) {
++	STRN_CPY(dest, result, STRING_LENGTH);
++	return;
++    }
++    switch (our_sin->sa_family) {
++    case AF_INET:
++	alen = sizeof(struct sockaddr_in);
++	break;
++    case AF_INET6:
++	alen = sizeof(struct sockaddr_in6);
++	break;
++    default:
++	STRN_CPY(dest, result, STRING_LENGTH);
++	return;
++    }
++#endif
++
+     /*
+      * Use one unbuffered stdio stream for writing to and for reading from
+      * the RFC931 etc. server. This is done because of a bug in the SunOS
+@@ -92,7 +122,11 @@ char   *dest;
+      * sockets.
+      */
+ 
++#ifdef INET6
++    if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) {
++#else
+     if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
++#endif
+ 	setbuf(fp, (char *) 0);
+ 
+ 	/*
+@@ -112,6 +146,25 @@ char   *dest;
+ 	     * addresses from the query socket.
+ 	     */
+ 
++#ifdef INET6
++	    memcpy(&our_query_sin, our_sin, alen);
++	    memcpy(&rmt_query_sin, rmt_sin, alen);
++	    switch (our_sin->sa_family) {
++	    case AF_INET:
++		((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT);
++		((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC931_PORT);
++		break;
++	    case AF_INET6:
++		((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT);
++		((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC931_PORT);
++		break;
++	    }
++
++	    if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
++		     alen) >= 0 &&
++		connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
++			alen) >= 0) {
++#else
+ 	    our_query_sin = *our_sin;
+ 	    our_query_sin.sin_port = htons(ANY_PORT);
+ 	    rmt_query_sin = *rmt_sin;
+@@ -121,6 +174,7 @@ char   *dest;
+ 		     sizeof(our_query_sin)) >= 0 &&
+ 		connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
+ 			sizeof(rmt_query_sin)) >= 0) {
++#endif
+ 
+ 		/*
+ 		 * Send query to server. Neglect the risk that a 13-byte
+@@ -129,8 +183,13 @@ char   *dest;
+ 		 */
+ 
+ 		fprintf(fp, "%u,%u\r\n",
++#ifdef INET6
++			ntohs(((struct sockaddr_in *)rmt_sin)->sin_port),
++			ntohs(((struct sockaddr_in *)our_sin)->sin_port));
++#else
+ 			ntohs(rmt_sin->sin_port),
+ 			ntohs(our_sin->sin_port));
++#endif
+ 		fflush(fp);
+ 
+ 		/*
+@@ -144,8 +203,13 @@ char   *dest;
+ 		    && ferror(fp) == 0 && feof(fp) == 0
+ 		    && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
+ 			      &rmt_port, &our_port, user) == 3
++#ifdef INET6
++		    && ntohs(((struct sockaddr_in *)rmt_sin)->sin_port) == rmt_port
++		    && ntohs(((struct sockaddr_in *)our_sin)->sin_port) == our_port) {
++#else
+ 		    && ntohs(rmt_sin->sin_port) == rmt_port
+ 		    && ntohs(our_sin->sin_port) == our_port) {
++#endif
+ 
+ 		    /*
+ 		     * Strip trailing carriage return. It is part of the
+--- scaffold.c.orig
++++ scaffold.c
+@@ -20,6 +20,9 @@ static char sccs_id[] = "@(#) scaffold.c
+ #include <syslog.h>
+ #include <setjmp.h>
+ #include <string.h>
++#if defined(INET6) && !defined(USE_GETIPNODEBY)
++#include <resolv.h>
++#endif
+ 
+ #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,100 @@ 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, *hp2;
++#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;
++    _res.options |= RES_USE_INET6;
++    if ((hp1 = gethostbyname2(host, AF_INET6)) != NULL)
++	hp1 = dup_hostent(hp1);
++    if ((hp2 = gethostbyname2(host, AF_INET)) != NULL)
++	hp2 = dup_hostent(hp2);
++    _res.options = res_options;
++    if (hp1 && hp2) {
++	hp = merge_hostent(hp1, hp2);
++	free((char *) hp1);
++	free((char *) hp2);
++	return (hp);
++    }
++    if (hp1)
++	return (hp1);
++    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)
+@@ -91,6 +196,15 @@ 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 = (char *) malloc(strlen(host)+1);
++	if (! h.h_name){
++	    fprintf(stderr, "Sorry, out of memory\n");
++	    exit(1);
++	}
++	strncpy(h.h_name, host, strlen(host)+1);
++#endif
+ 	return (dup_hostent(&h));
+     }
+ 
+@@ -104,19 +218,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 +253,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 +269,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
+--- socket.c.orig
++++ socket.c
+@@ -30,6 +30,12 @@ static char sccsid[] = "@(#) socket.c 1.
+ #include <syslog.h>
+ #include <string.h>
+ 
++#ifdef INET6
++#ifndef USE_GETIPNODEBY
++#include <resolv.h>
++#endif
++#endif
++
+ extern char *inet_ntoa();
+ 
+ /* Local stuff. */
+@@ -74,8 +80,13 @@ char   *name;
+ void    sock_host(request)
+ struct request_info *request;
+ {
++#ifdef INET6
++    static struct sockaddr_storage client;
++    static struct sockaddr_storage server;
++#else
+     static struct sockaddr_in client;
+     static struct sockaddr_in server;
++#endif
+     int     len;
+     char    buf[BUFSIZ];
+     int     fd = request->fd;
+@@ -104,7 +115,11 @@ struct request_info *request;
+ 	memset(buf, 0 sizeof(buf));
+ #endif
+     }
++#ifdef INET6
++    request->client->sin = (struct sockaddr *)&client;
++#else
+     request->client->sin = &client;
++#endif
+ 
+     /*
+      * Determine the server binding. This is used for client username
+@@ -117,7 +132,11 @@ struct request_info *request;
+ 	tcpd_warn("getsockname: %m");
+ 	return;
+     }
++#ifdef INET6
++    request->server->sin = (struct sockaddr *)&server;
++#else
+     request->server->sin = &server;
++#endif
+ }
+ 
+ /* sock_hostaddr - map endpoint address to printable form */
+@@ -125,10 +144,33 @@ struct request_info *request;
+ void    sock_hostaddr(host)
+ struct host_info *host;
+ {
++#ifdef INET6
++    struct sockaddr *sin = host->sin;
++    char *ap;
++    int alen;
++
++    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));
++#else
+     struct sockaddr_in *sin = host->sin;
+ 
+     if (sin != 0)
+ 	STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
++#endif
+ }
+ 
+ /* sock_hostname - map endpoint address to host name */
+@@ -136,8 +178,21 @@ struct host_info *host;
+ void    sock_hostname(host)
+ 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;
++#endif
++    struct hostent *hp = NULL;
++    char *ap;
++    int alen;
++#else
+     struct sockaddr_in *sin = host->sin;
+     struct hostent *hp;
++#endif
+     int     i;
+ 
+     /*
+@@ -147,11 +202,42 @@ 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
+@@ -166,15 +252,53 @@ 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")) {
+@@ -198,10 +322,19 @@ 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
+ 	    }
+ 
+ 	    /*
+@@ -210,10 +343,20 @@ 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
+     }
+ }
+ 
+@@ -223,7 +366,11 @@ static void sock_sink(fd)
+ int     fd;
+ {
+     char    buf[BUFSIZ];
++#ifdef INET6
++    struct sockaddr_storage sin;
++#else
+     struct sockaddr_in sin;
++#endif
+     int     size = sizeof(sin);
+ 
+     /*
+--- tcpd.c.orig
++++ tcpd.c
+@@ -24,6 +24,7 @@ static char sccsid[] = "@(#) tcpd.c 1.10
+ #include <stdio.h>
+ #include <syslog.h>
+ #include <string.h>
++#include <unistd.h>
+ 
+ #ifndef MAXPATHNAMELEN
+ #define MAXPATHNAMELEN	BUFSIZ
+@@ -120,7 +121,12 @@ char  **argv;
+ 
+     /* Report request and invoke the real daemon program. */
+ 
++#ifdef INET6
++    syslog(allow_severity, "connect from %s (%s)",
++	   eval_client(&request), eval_hostaddr(request.client));
++#else
+     syslog(allow_severity, "connect from %s", eval_client(&request));
++#endif
+     closelog();
+     (void) execv(path, argv);
+     syslog(LOG_ERR, "error: cannot execute %s: %m", path);
+--- tcpd.h.orig
++++ tcpd.h
+@@ -17,7 +17,11 @@
+ struct host_info {
+     char    name[STRING_LENGTH];	/* access via eval_hostname(host) */
+     char    addr[STRING_LENGTH];	/* access via eval_hostaddr(host) */
++#ifdef INET6
++    struct sockaddr *sin;		/* socket address or 0 */
++#else
+     struct sockaddr_in *sin;		/* socket address or 0 */
++#endif
+     struct t_unitdata *unit;		/* TLI transport address or 0 */
+     struct request_info *request;	/* for shared information */
+ };
+--- tcpdchk.c.orig
++++ tcpdchk.c
+@@ -22,6 +22,9 @@ static char sccsid[] = "@(#) tcpdchk.c 1
+ 
+ #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>
+@@ -397,6 +400,26 @@ char   *pat;
+     }
+ }
+ 
++#ifdef INET6
++static int is_inet6_addr(pat)
++    char *pat;
++{
++    struct in6_addr addr;
++    int len, ret;
++    char ch;
++
++    if (*pat != '[')
++	return (0);
++    len = strlen(pat);
++    if ((ch = pat[len - 1]) != ']')
++	return (0);
++    pat[len - 1] = '\0';
++    ret = inet_pton(AF_INET6, pat + 1, &addr);
++    pat[len - 1] = ch;
++    return (ret == 1);
++}
++#endif
++
+ /* check_host - criticize host pattern */
+ 
+ static int check_host(pat)
+@@ -423,14 +446,27 @@ char   *pat;
+ #endif
+ #endif
+     } else if (mask = split_at(pat, '/')) {	/* network/netmask */
++#ifdef INET6
++	int mask_len;
++
++	if ((dot_quad_addr(pat) == INADDR_NONE
++	    || dot_quad_addr(mask) == INADDR_NONE)
++	    && (!is_inet6_addr(pat)
++		|| ((mask_len = atoi(mask)) < 0 || mask_len > 128)))
++#else
+ 	if (dot_quad_addr(pat) == INADDR_NONE
+ 	    || dot_quad_addr(mask) == INADDR_NONE)
++#endif
+ 	    tcpd_warn("%s/%s: bad net/mask pattern", pat, mask);
+     } else if (STR_EQ(pat, "FAIL")) {		/* obsolete */
+ 	tcpd_warn("FAIL is no longer recognized");
+ 	tcpd_warn("(use EXCEPT or DENY instead)");
+     } else if (reserved_name(pat)) {		/* other reserved */
+ 	 /* void */ ;
++#ifdef INET6
++    } else if (is_inet6_addr(pat)) { /* IPv6 address */
++	addr_count = 1;
++#endif
+     } else if (NOT_INADDR(pat)) {		/* internet name */
+ 	if (pat[strlen(pat) - 1] == '.') {
+ 	    tcpd_warn("%s: domain or host name ends in dot", pat);
+--- tcpdmatch.c.orig
++++ tcpdmatch.c
+@@ -68,8 +68,15 @@ char  **argv;
+     int     ch;
+     char   *inetcf = 0;
+     int     count;
++#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;
++#endif
+     struct stat st;
+ 
+     /*
+@@ -173,12 +180,35 @@ char  **argv;
+ 	if ((hp = find_inet_addr(server)) == 0)
+ 	    exit(1);
+ 	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);
++#else
+ 	    memcpy((char *) &server_sin.sin_addr, addr,
+ 		   sizeof(server_sin.sin_addr));
++#endif
+ 
+ 	    /*
+ 	     * Force evaluation of server host name and address. Host name
+@@ -230,12 +260,35 @@ 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);
++    }
++#ifdef SIN6_LEN
++    client_sin.ss_len = alen;
++#endif
++#else
+     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
+--- update.c.orig
++++ update.c
+@@ -46,10 +46,18 @@ va_list ap;
+ 	    request->fd = va_arg(ap, int);
+ 	    continue;
+ 	case RQ_CLIENT_SIN:
++#ifdef INET6
++	    request->client->sin = va_arg(ap, struct sockaddr *);
++#else
+ 	    request->client->sin = va_arg(ap, struct sockaddr_in *);
++#endif
+ 	    continue;
+ 	case RQ_SERVER_SIN:
++#ifdef INET6
++	    request->server->sin = va_arg(ap, struct sockaddr *);
++#else
+ 	    request->server->sin = va_arg(ap, struct sockaddr_in *);
++#endif
+ 	    continue;
+ 
+ 	    /*
+--- workarounds.c.orig
++++ workarounds.c
+@@ -166,11 +166,22 @@ struct sockaddr *sa;
+ int    *len;
+ {
+     int     ret;
++#ifdef INET6
++    struct sockaddr_storage *sin = (struct sockaddr_storage *) sa;
++#else
+     struct sockaddr_in *sin = (struct sockaddr_in *) sa;
++#endif
+ 
+     if ((ret = getpeername(sock, sa, len)) >= 0
++#ifdef INET6
++	&& ((sin->__ss_family == AF_INET6
++	     && IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *)sin)->sin6_addr))
++	    || (sin->ss_family == AF_INET
++		&& ((struct sockaddr_in *)sin)->sin_addr.s_addr == 0))) {
++#else
+ 	&& sa->sa_family == AF_INET
+ 	&& sin->sin_addr.s_addr == 0) {
++#endif
+ 	errno = ENOTCONN;
+ 	return (-1);
+     } else {
diff --git a/tcp_wrappers_7.6-ipv6-fix.diff b/tcp_wrappers_7.6-ipv6-fix.diff
new file mode 100644
index 0000000..a4fb3a0
--- /dev/null
+++ b/tcp_wrappers_7.6-ipv6-fix.diff
@@ -0,0 +1,956 @@
+#
+# This patch makes tcpd/libwrap work with IPv6, IPv4 and
+# mapped IPv4 addresses.
+#
+# The approach is "convert everything to IPv6". It means that
+# any IPv4 address I ever met either in /etc/hosts.* or that I get from
+# the socket is first converted to v4-mapped and then handled as if it was
+# IPv6. This simplifies the logic very much and makes the code much
+# cleaner. Prefixes are also supported in the form [3ffe:ffff::/48] as
+# well as for IPv4 addresses.
+#
+# Made by Michal Ludvig <mludvig@suse.cz>, <michal@logix.cz>
+# November , 2002
+#
+================================================================================
+--- Makefile.orig
++++ Makefile
+@@ -1,5 +1,7 @@
+ # @(#) Makefile 1.23 97/03/21 19:27:20
+ 
++really-all: linux
++
+ what:
+ 	@echo
+ 	@echo "Usage: edit the REAL_DAEMON_DIR definition in the Makefile then:"
+@@ -670,7 +672,7 @@ CFLAGS	= -O2 -pipe -DFACILITY=$(FACILITY
+ LIB_OBJ= hosts_access.o options.o shell_cmd.o rfc931.o eval.o \
+ 	hosts_ctl.o refuse.o percent_x.o clean_exit.o $(AUX_OBJ) \
+ 	$(FROM_OBJ) fix_options.o socket.o tli.o workarounds.o \
+-	update.o misc.o diag.o percent_m.o myvsyslog.o
++	update.o misc.o diag.o percent_m.o myvsyslog.o ip6utils.o
+ 
+ FROM_OBJ= fromhost.o
+ 
+@@ -683,6 +685,7 @@ KIT	= README miscd.c tcpd.c fromhost.c h
+ 	tli-sequent.h misc.c diag.c ncr.c tcpdchk.c percent_m.c \
+ 	myvsyslog.c mystdarg.h printf.ck README.IRIX Banners.Makefile \
+ 	refuse.c tcpdchk.8 setenv.c inetcf.c inetcf.h scaffold.c \
++	ip6utils.c ip6utils.h \
+ 	scaffold.h tcpdmatch.8 README.NIS
+ 
+ LIB	= libwrap.a
+@@ -812,6 +815,7 @@ printfck:
+ 
+ # Internal compilation dependencies.
+ 
++tcpd.h: ip6utils.h
+ clean_exit.o: cflags
+ clean_exit.o: tcpd.h
+ diag.o: cflags
+--- hosts_access.c.orig
++++ hosts_access.c
+@@ -85,11 +85,6 @@ static int server_match();
+ static int client_match();
+ static int host_match();
+ static int string_match();
+-static int masked_match();
+-#ifdef INET6
+-static int masked_match4();
+-static int masked_match6();
+-#endif
+ 
+ /* Size of logical line buffer. */
+ 
+@@ -308,15 +303,17 @@ struct host_info *host;
+     } else if (STR_EQ(tok, "LOCAL")) {		/* local: no dots in name */
+ 	char   *name = eval_hostname(host);
+ 	return (strchr(name, '.') == 0 && HOSTNAME_KNOWN(name));
+-    } else if ((mask = split_at(tok, '/')) != 0) {	/* net/mask */
+-	return (masked_match(tok, mask, eval_hostaddr(host)));
+     } else {					/* anything else */
+ 	return (string_match(tok, eval_hostaddr(host))
+ 	    || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host))));
+     }
+ }
+ 
+-/* string_match - match string against pattern */
++/* string_match - match string against pattern 
++ * 
++ * tok = data read from /etc/hosts.*
++ * string = textual data of actual client
++ */
+ 
+ static int string_match(tok, string)
+ char   *tok;
+@@ -324,13 +321,6 @@ char   *string;
+ {
+     int     n;
+ 
+-#ifdef INET6
+-    /* convert IPv4 mapped IPv6 address to IPv4 address */
+-    if (STRN_EQ(string, "::ffff:", 7)
+-	&& dot_quad_addr(string + 7) != INADDR_NONE) {
+-	string += 7;
+-    }
+-#endif
+     if (tok[0] == '.') {			/* suffix */
+ 	n = strlen(string) - strlen(tok);
+ 	return (n > 0 && STR_EQ(tok, string + n));
+@@ -340,122 +330,65 @@ char   *string;
+ 	return (STR_NE(string, unknown));
+     } else if (tok[(n = strlen(tok)) - 1] == '.') {	/* prefix */
+ 	return (STRN_EQ(tok, string, n));
+-    } else {					/* exact match */
++    } else if (STR_EQ(tok, string))		/* exact match */
++	return (YES);
+ #ifdef INET6
++    else	/* IP addresses match - not needed for IPv4 */
++    {
++	/* For simplicity we convert everything to IPv6 (or v4 mapped) */
+ 	struct in6_addr pat, addr;
+-	int len, ret;
+-	char ch;
+-
++	int len, ret, prefixlen=128;
++	char ch, token[INET6_ADDRSTRLEN+1], *mask;
++	
+ 	len = strlen(tok);
+-	if (*tok == '[' && tok[len - 1] == ']') {
+-	    ch = tok[len - 1];
+-	    tok[len - 1] = '\0';
+-	    ret = inet_pton(AF_INET6, tok + 1, pat.s6_addr);
+-	    tok[len - 1] = ch;
+-	    if (ret != 1 || inet_pton(AF_INET6, string, addr.s6_addr) != 1)
+-		return NO;
+-	    return (!memcmp(&pat, &addr, sizeof(struct in6_addr)));
++	if (*tok == '[' && tok[len - 1] == ']') 
++	{
++		ch = tok[len - 1];
++			tok[len - 1] = '\0';
++			snprintf(token, sizeof(token), "%s", tok+1);
++			tok[len - 1] = ch;
++	}
++	else
++		snprintf(token, sizeof(token), "%s", tok);
++	
++	/* If prefix was given, handle it */
++	if ((mask = split_at(token, '/')) != 0)
++	{
++		if (sscanf(mask, "%d", &prefixlen) != 1 || prefixlen < 0)
++		{
++			tcpd_warn ("Wrong prefix length in %s", tok);
++			return (NO);
++		}
++		
++		if (is_v4_string (token))
++			prefixlen += 96;	/* extend to v4mapped */
++
++		if (prefixlen > 128)
++		{
++			tcpd_warn ("Prefix too long in %s", tok);
++			return (NO);
++		}
++	}
++	
++	memset (&pat, 0, sizeof(pat));
++	memset (&addr, 0, sizeof(addr));
++
++	if (inet_pton_mapped(AF_INET6, token, &pat) != 1)
++		return (NO);
++
++	if (inet_pton_mapped(AF_INET6, string, &addr) != 1)
++	{
++		tcpd_warn("Unable to handle client address: %s", string);
++		return (NO);
+ 	}
+-#endif
+-	return (STR_EQ(tok, string));
+-    }
+-}
+-
+-/* masked_match - match address against netnumber/netmask */
+-
+-#ifdef INET6
+-static int masked_match(net_tok, mask_tok, string)
+-char   *net_tok;
+-char   *mask_tok;
+-char   *string;
+-{
+-    return (masked_match4(net_tok, mask_tok, string) ||
+-	    masked_match6(net_tok, mask_tok, string));
+-}
+-
+-static int masked_match4(net_tok, mask_tok, string)
+-#else
+-static int masked_match(net_tok, mask_tok, string)
+-#endif
+-char   *net_tok;
+-char   *mask_tok;
+-char   *string;
+-{
+-#ifdef INET6
+-    u_int32_t net;
+-    u_int32_t mask;
+-    u_int32_t addr;
+-#else
+-    unsigned long net;
+-    unsigned long mask;
+-    unsigned long addr;
+-#endif
+-
+-    /*
+-     * Disallow forms other than dotted quad: the treatment that inet_addr()
+-     * gives to forms with less than four components is inconsistent with the
+-     * access control language. John P. Rouillard <rouilj@cs.umb.edu>.
+-     */
+-
+-    if ((addr = dot_quad_addr(string)) == INADDR_NONE)
+-	return (NO);
+-    if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
+-	|| (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) {
+-#ifndef INET6
+-	tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
+-#endif
+-	return (NO);				/* not tcpd_jump() */
+-    }
+-    return ((addr & mask) == net);
+-}
+-
+-#ifdef INET6
+-static int masked_match6(net_tok, mask_tok, string)
+-char   *net_tok;
+-char   *mask_tok;
+-char   *string;
+-{
+-    struct in6_addr 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;
+-
+-    if (IN6_IS_ADDR_V4MAPPED(&addr)) {
+-	if ((*(u_int32_t *)&net.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]);
+-    }
+ 
+-    /* match IPv6 address against netnumber/prefixlen */
+-    len = strlen(net_tok);
+-    if (*net_tok != '[' || net_tok[len - 1] != ']')
+-	return NO;
+-    ch = net_tok[len - 1];
+-    net_tok[len - 1] = '\0';
+-    if (inet_pton(AF_INET6, net_tok + 1, net.s6_addr) != 1) {
+-	net_tok[len - 1] = ch;
+-	return NO;
+-    }
+-    net_tok[len - 1] = ch;
+-    if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128)
+-	return NO;
+-
+-    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))
+-		return NO;
+-	    break;
++	if (prefixlen < 128)
++	{
++		apply_v6_prefix (&pat, prefixlen);
++		apply_v6_prefix (&addr, prefixlen);
+ 	}
+-	if (*(u_int32_t *)&addr.s6_addr[i] != *(u_int32_t *)&net.s6_addr[i])
+-	    return NO;
+-	i += 4;
+-	mask_len -= 32;
++
++	return (!memcmp(&pat, &addr, sizeof(struct in6_addr)));
+     }
+-    return YES;
++#endif
+ }
+-#endif /* INET6 */
+--- /dev/null
++++ ip6utils.c
+@@ -0,0 +1,152 @@
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <arpa/inet.h>
++#include <stdio.h>
++#include <errno.h>
++
++#include "ip6utils.h"
++
++/* inet_pton_mapped() 
++   - works like inet_pton(3) but always returns IPv6 address 
++   in dst - either "real" or v4mapped (::ffff:1.2.3.4) in 
++   the case, when src points to IPv4 address (eg. to 1.2.3.4). */
++int
++inet_pton_mapped (int af, const char *src, void *dst)
++{
++	int ret;
++	
++	/* Mapped address is v6. */
++	if (af != AF_INET6)
++	{
++		errno = EAFNOSUPPORT;
++		return -1;
++	}
++
++	/* We must put the result somewhere. */
++	if (!dst)
++	{
++		errno = EFAULT;
++		return -1;
++	}
++
++	/* First try whether the address IPv6. */
++	ret = inet_pton (AF_INET6, src, dst);
++	if (ret > 0)
++		return ret;
++
++	/* Because we're here, it apparently wasn't IPv6. Try IPv4 now. */
++	ret = inet_pton (AF_INET, src, &((struct in6_addr *)dst)->s6_addr32[3]);
++	if (ret > 0)
++	{
++		/* Good, it was IPv4, map it now. */
++		((struct in6_addr *)dst)->s6_addr32[0] = 0;
++		((struct in6_addr *)dst)->s6_addr32[1] = 0;
++		((struct in6_addr *)dst)->s6_addr32[2] = htonl(0x0000ffffL);
++	}
++	return ret;
++}
++
++/* inet_ntop2() 
++   - works like inet_ntop(3) but doesn't need an external 
++     buffer. Usefull eg. for printing addresses via printf(). */
++const char *
++inet_ntop2 (int af, const void *src)
++{
++	static char address[INET6_ADDRSTRLEN];
++	
++	return inet_ntop(af, src, address, sizeof(address));
++}
++
++/* sa_map_v4_to_v6() 
++   - Take an IPv4 address in first argument and map it to 
++     IPv4-mapped (::ffff:1.2.3.4) IPv6 address. */
++struct sockaddr_in6 *
++sa_map_v4_to_v6 (struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
++{
++	/* Both pointers must be not-NULL or we'll segfault. */
++	if (!sin || !sin6)
++	{
++		errno = EFAULT;
++		return NULL;
++	}
++	
++	/* We can map only IPv4 addresses. */
++	if (sin->sin_family != AF_INET)
++		return NULL;
++
++	/* Map it now... */
++	memset(sin6, 0, sizeof(*sin6));
++
++	sin6->sin6_family = AF_INET6;
++	sin6->sin6_port = sin->sin_port;
++	sin6->sin6_addr.s6_addr16[5] = 0xffff;
++	sin6->sin6_addr.s6_addr32[3] = sin->sin_addr.s_addr;
++
++	return sin6;
++}
++
++/* is_v4_string(), is_v6_string() 
++   - Return 1 when src is a string representing a valid 
++     IPv4, resp. IPv6 address.  Return 0 otherwise. */
++int
++is_v4_string (const char *src)
++{
++	struct in_addr result;
++	
++	return (inet_pton (AF_INET, src, &result) > 0);
++}
++
++int
++is_v6_string (const char *src)
++{
++	struct in6_addr result;
++	
++	return (inet_pton (AF_INET6, src, &result) > 0);
++}
++
++/* apply_v6_prefix()
++   - mask the address given in 'src' with 'prefixlen' netmask. Clear
++     all bits not covered by prefixlen. */
++int
++apply_v6_prefix (struct in6_addr *src, int prefixlen)
++{
++	int i;
++
++	/* Check prefix for a valid length. */
++	if (prefixlen < 0 || prefixlen > 128)
++		return -1;
++
++	/* Prefixes will quite often end up on 16b boundary,
++	   so we'll walk thorugh 16b blocks and possibly avoid 
++	   creating bitmasks.  */
++	for (i=0; i<8; i++)
++	{
++		/* Prefix fully covers this block -> leave as is. */
++		if (prefixlen >= (i+1)*16)
++			continue;
++		/* Prefix doesn't cover this block -> zero it. */
++		if (prefixlen <= i*16)
++		{
++			src->s6_addr16[i] = 0;
++			continue;
++		}
++		/* Prefix ends somewhere inside in this block. Let's
++		   build and apply a bitmask for this block. */
++		{
++			uint16_t mask=0;
++			int bits;
++
++			bits = prefixlen - i*16;
++
++			while (bits)
++			{
++				mask |= (1 << (16-bits));
++				bits --;
++			}
++
++			src->s6_addr16[i] &= htons(mask);
++		}
++	}
++
++	return 0;
++}
+--- /dev/null
++++ ip6utils.h
+@@ -0,0 +1,33 @@
++#ifndef IP6UTILS_H
++#define IP6UTILS_H
++
++/* inet_pton_mapped() 
++   - works like inet_pton(3) but always returns IPv6 address 
++   in dst - either "real" or v4mapped (::ffff:1.2.3.4) in 
++   the case, when src points to IPv4 address (eg. to 1.2.3.4). 
++   Return value is as with inet_pton(), dst remains untouched on 
++   an address translation failure. */
++int inet_pton_mapped (int af, const char *src, void *dst);
++
++/* inet_ntop2() 
++   - works like inet_ntop(3) but doesn't need an external 
++     buffer. Usefull eg. for printing addresses via printf(). */
++const char *inet_ntop2 (int af, const void *src);
++
++/* sa_map_v4_to_v6() 
++   - Take an IPv4 address in form 1.2.3.4 and map it to 
++     IPv4-mapped form ::ffff:1.2.3.4 */
++struct sockaddr_in6 *sa_map_v4_to_v6 (struct sockaddr_in *sin, struct sockaddr_in6 *sin6);
++
++/* is_v4_string(), is_v6_string() 
++   - Return 1 when src is a string representing a valid 
++     IPv4, resp. IPv6 address.  Return 0 otherwise. */
++int is_v4_string (const char *src);
++int is_v6_string (const char *src);
++
++/* apply_v6_prefix()
++   - mask the address given in 'src' with 'prefixlen' netmask. Clear
++     all bits not covered by prefixlen. Return -1 on a failure, else 0. */
++int apply_v6_prefix (struct in6_addr *src, int prefixlen);
++
++#endif /* IP6UTILS_H */
+--- socket.c.orig
++++ socket.c
+@@ -25,16 +25,12 @@ static char sccsid[] = "@(#) socket.c 1.
+ #include <sys/param.h>
+ #include <sys/socket.h>
+ #include <netinet/in.h>
++#include <arpa/inet.h>
+ #include <netdb.h>
+ #include <stdio.h>
+ #include <syslog.h>
+ #include <string.h>
+-
+-#ifdef INET6
+-#ifndef USE_GETIPNODEBY
+-#include <resolv.h>
+-#endif
+-#endif
++#include <errno.h>
+ 
+ extern char *inet_ntoa();
+ 
+@@ -65,10 +61,10 @@ char   *name;
+      */
+ 
+     if (strchr(name, '.') == 0 || strlen(name) >= MAXHOSTNAMELEN - 1) {
+-	return (gethostbyname(name));
++    return (gethostbyname(name));
+     } else {
+-	sprintf(dot_name, "%s.", name);
+-	return (gethostbyname(dot_name));
++    sprintf(dot_name, "%s.", name);
++    return (gethostbyname(dot_name));
+     }
+ }
+ 
+@@ -104,15 +100,15 @@ struct request_info *request;
+ 
+     len = sizeof(client);
+     if (getpeername(fd, (struct sockaddr *) & client, &len) < 0) {
+-	request->sink = sock_sink;
+-	len = sizeof(client);
+-	if (recvfrom(fd, buf, sizeof(buf), MSG_PEEK,
+-		     (struct sockaddr *) & client, &len) < 0) {
+-	    tcpd_warn("can't get client address: %m");
+-	    return;				/* give up */
+-	}
++    request->sink = sock_sink;
++    len = sizeof(client);
++    if (recvfrom(fd, buf, sizeof(buf), MSG_PEEK,
++             (struct sockaddr *) & client, &len) < 0) {
++        tcpd_warn("can't get client address: %m");
++        return;             /* give up */
++    }
+ #ifdef really_paranoid
+-	memset(buf, 0 sizeof(buf));
++    memset(buf, 0 sizeof(buf));
+ #endif
+     }
+ #ifdef INET6
+@@ -129,8 +125,8 @@ struct request_info *request;
+ 
+     len = sizeof(server);
+     if (getsockname(fd, (struct sockaddr *) & server, &len) < 0) {
+-	tcpd_warn("getsockname: %m");
+-	return;
++    tcpd_warn("getsockname: %m");
++    return;
+     }
+ #ifdef INET6
+     request->server->sin = (struct sockaddr *)&server;
+@@ -150,18 +146,18 @@ struct host_info *host;
+     int alen;
+ 
+     if (!sin)
+-	return;
++        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;
++        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));
+@@ -169,30 +165,139 @@ struct host_info *host;
+     struct sockaddr_in *sin = host->sin;
+ 
+     if (sin != 0)
+-	STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
++    STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
+ #endif
+ }
+ 
++#ifdef INET6
+ /* sock_hostname - map endpoint address to host name */
++void
++sock_hostname(struct host_info *host)
++{
++    struct addrinfo hints, *res, *resbase;
++    struct sockaddr *sa = host->sin;
++    struct sockaddr_in6 *sin6, sin6buf;
++    int errcode;
++    
++    if (!sa) 
++    {
++            /* Unknown sockaddr => unable to verify */
++            tcpd_warn ("can't verify hostname: sockaddr == NULL");
++            strncpy(host->name, paranoid, sizeof(host->name));
++            return;
++    }
++
++    switch (sa->sa_family)
++    {
++        case AF_INET:
++            if (((struct sockaddr_in *)sa)->sin_addr.s_addr == 0) 
++            {
++                /* Address 0.0.0.0 is invalid. */
++                tcpd_warn ("can't verify hostname of address %s",
++                    inet_ntop2(sa->sa_family, 
++                        &((struct sockaddr_in *)sa)->sin_addr));
++                strncpy(host->name, paranoid, sizeof(host->name));
++                return;
++            }
++            sin6 = sa_map_v4_to_v6 ((struct sockaddr_in *)sa, 
++                    &sin6buf);
++            break;
++        case AF_INET6:
++            sin6 = (struct sockaddr_in6 *)sa;
++            break;
++        default:
++            /* Unknown protocol family. */
++            strncpy(host->name, paranoid, sizeof(host->name));
++            return;
++    }
++    
++    /* First resolve address to name... */
++    if (getnameinfo ((struct sockaddr *)sin6, sizeof(*sin6), 
++                            host->name, sizeof(host->name),
++                            NULL, 0, 0) < 0)
++    {
++        tcpd_warn ("can't verify hostname: getnameinfo(%s): %s", 
++                inet_ntop2(sin6->sin6_family, &sin6->sin6_addr),
++                strerror(errno));
++        strncpy(host->name, paranoid, sizeof(host->name));
++        return;
++    }
++
++    /* Now resolve the name back to the address. Hopefully we'll 
++       get the same one... */
++    
++    memset (&hints, 0, sizeof(hints));
++
++    hints.ai_family = PF_UNSPEC;
++    hints.ai_socktype = SOCK_STREAM;
++    hints.ai_flags |= AI_CANONNAME;
++    
++    errcode = getaddrinfo(host->name, NULL, &hints, &resbase);
++    if(errcode)
++    {
++            tcpd_warn ("can't verify hostname: getaddrinfo(%s): %s",
++                host->name,
++                gai_strerror(errcode));
++            strncpy(host->name, paranoid, sizeof(host->name));
++            return;
++    }
++    
++    res = resbase;
++    
++    /* Now walk through all reutrned addresses and see if at least one
++       is the same (or mmapped-same) as the incoming one.  */
++    while(res)
++    {
++        struct sockaddr_in6 *sin6res, sin6resbuf;
++        
++        switch (res->ai_family)
++        {
++            case AF_INET:
++                sin6res = sa_map_v4_to_v6 ((struct sockaddr_in *)res->ai_addr, &sin6resbuf);
++                break;
++            case AF_INET6:
++                sin6res = (struct sockaddr_in6 *)res->ai_addr;
++                break;
++            default:
++                res = res->ai_next;
++                continue;
++        }
++
++        if (memcmp (&sin6->sin6_addr, &sin6res->sin6_addr, 
++                    sizeof(sin6->sin6_addr)) == 0)
++            break;
++
++        res = res->ai_next;
++    }
++
++    freeaddrinfo (resbase);
++
++    if (res == NULL)
++    {
++        /* We walked through the list but didn't find a matching address. */
++        tcpd_warn ("can't verify hostname: getaddrinfo(%s) didn't return %s",
++            host->name, 
++            inet_ntop2 (sin6->sin6_family, &sin6->sin6_addr));
++        strncpy(host->name, paranoid, sizeof(host->name));
++        return;
++    }
+ 
+-void    sock_hostname(host)
++    if (STR_NE (host->name, res->ai_canonname) && STR_NE(host->name, "localhost"))
++    {
++        /* We don't treat this as an error, though... */
++        tcpd_warn("host name mismatch: %s != %s (%s)",
++            host->name, res->ai_canonname,
++            inet_ntop2 (sin6->sin6_family, &sin6->sin6_addr));
++    }
++    
++    return;
++}
++#else /* INET6 */
++void sock_hostname(host)
+ 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;
+-#endif
+-    struct hostent *hp = NULL;
+-    char *ap;
+-    int alen;
+-#else
+     struct sockaddr_in *sin = host->sin;
+     struct hostent *hp;
+-#endif
+     int     i;
+ 
+     /*
+@@ -202,163 +307,76 @@ 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
++    && (hp = gethostbyaddr((char *) &(sin->sin_addr),
++                   sizeof(sin->sin_addr), AF_INET)) != 0) {
+ 
+-	/*
+-	 * 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.
+-	 */
++    STRN_CPY(host->name, hp->h_name, sizeof(host->name));
+ 
+-#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.
+-	     */
++    /*
++     * 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.
++     */
+ 
+-#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
++    if ((hp = gethostbyname(host->name)) == 0) {
+ 
+-	} else if (STR_NE(host->name, hp->h_name)
+-		   && STR_NE(host->name, "localhost")) {
++        /*
++         * 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: gethostbyname(%s) failed",
++              host->name);
++
++    } else if (STR_NE(host->name, hp->h_name)
++           && 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.
++         */
+ 
+-	    /*
+-	     * 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, hp->h_name);
+-
+-	} 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.
+-	     */
++        tcpd_warn("host name/name mismatch: %s != %.*s",
++              host->name, STRING_LENGTH, hp->h_name);
+ 
+-	    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
+-	    }
++    } else {
+ 
+-	    /*
+-	     * The host name does not map to the initial address. Perhaps
+-	     * someone has messed up. Perhaps someone compromised a name
+-	     * server.
+-	     */
++        /*
++         * 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 (i = 0; hp->h_addr_list[i]; i++) {
++        if (memcmp(hp->h_addr_list[i],
++               (char *) &sin->sin_addr,
++               sizeof(sin->sin_addr)) == 0)
++            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.
++         */
+ 
+-#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
++        tcpd_warn("host name/address mismatch: %s != %.*s",
++              inet_ntoa(sin->sin_addr), STRING_LENGTH, hp->h_name);
++    }
++    strcpy(host->name, paranoid);       /* name is bad, clobber it */
+     }
+ }
++#endif /* INET6 */
+ 
+ /* sock_sink - absorb unreceived IP datagram */
+ 
+--- tcpd.h.orig
++++ tcpd.h
+@@ -10,6 +10,8 @@
+ #include <sys/socket.h>
+ #endif
+ 
++#include "ip6utils.h"
++
+ /* Structure to describe one communications endpoint. */
+ 
+ #define STRING_LENGTH	128		/* hosts, users, processes */
diff --git a/tcp_wrappers_7.6-ipv6-host-match.patch b/tcp_wrappers_7.6-ipv6-host-match.patch
new file mode 100644
index 0000000..bfd786a
--- /dev/null
+++ b/tcp_wrappers_7.6-ipv6-host-match.patch
@@ -0,0 +1,364 @@
+---
+ hosts_access.c |  271 ++++++++++++++++++++++++++++++++++-----------------------
+ misc.c         |   18 +++
+ tcpd.h         |    2 
+ 3 files changed, 183 insertions(+), 108 deletions(-)
+
+Index: tcp_wrappers_7.6/hosts_access.c
+===================================================================
+--- tcp_wrappers_7.6.orig/hosts_access.c
++++ tcp_wrappers_7.6/hosts_access.c
+@@ -88,6 +88,10 @@ static int server_match();
+ static int client_match();
+ static int host_match();
+ static int string_match();
++static int masked_match();
++#ifdef INET6
++static void ipv6_mask();
++#endif
+ 
+ /* Size of logical line buffer. */
+ 
+@@ -293,6 +297,74 @@ struct hosts_info *host;
+     return (match);
+ }
+ 
++static inline int
++host_info_ipv6addr(const struct host_info *host, struct in6_addr *addrbuf)
++{
++  /*
++   * In some cases we don't get the sockaddr, only the addr.
++   * We use inet_pton to convert it to its binary representation
++   * and match against that.
++   */
++  if (host->sin == NULL) {
++    if (host->addr == NULL || inet_pton(AF_INET6, host->addr, addrbuf) != 1)
++      return 0;
++
++    return 1;
++  } else
++  if (host->sin->ss_family == AF_INET6) {
++    *addrbuf = ((struct sockaddr_in6 *) host->sin)->sin6_addr;
++    return 1;
++  }
++  return 0;
++}
++
++static inline int
++token_ipv6addr_and_mask(char *tok, struct in6_addr *addrbuf, unsigned int *maskbits)
++{
++  char *cbr;
++  char *slash;
++
++  if (*tok != '[')
++    return 0;
++
++  *maskbits = 128;
++
++  ++tok; /* now points to the beginning of the IPv6 addr string */
++  if ((cbr = strchr(tok, ']')) == NULL) {
++    tcpd_warn("bad IP6 address specification");
++    return 0;
++  }
++  *cbr++ = '\0';
++
++  /*
++   * A /nnn prefix specifies how many bits of the address we
++   * need to check. 
++   * Note, we support both [x::y/64] and [x::y]/64
++   */
++  if ((slash = strchr(tok, '/')) == NULL && *cbr == '/')
++    slash = cbr;
++
++  if (slash != NULL) {
++    int mask;
++
++    *slash++ = '\0';
++    mask = atoi(slash);
++    if (mask < 0 || mask > 128) {
++      tcpd_warn("bad IP6 prefix specification");
++      return 0;
++    }
++
++    *maskbits = mask;
++  }
++
++  if (inet_pton(AF_INET6, tok, addrbuf) != 1) {
++    tcpd_warn("bad IP6 address specification");
++    return 0;
++  }
++
++  return 1;
++}
++
+ /* host_match - match host name and/or address against pattern */
+ 
+ static int host_match(tok, host)
+@@ -328,12 +400,68 @@ struct host_info *host;
+     } else if (STR_EQ(tok, "LOCAL")) {		/* local: no dots in name */
+ 	char   *name = eval_hostname(host);
+ 	return (strchr(name, '.') == 0 && HOSTNAME_KNOWN(name));
++    } else if (tok[0] == '[') {			/* IPv6 address */
++#ifdef INET6
++      struct in6_addr match_addr, host_addr;
++      unsigned int mask = 128;
++
++      if (!host_info_ipv6addr(host, &host_addr))
++        return (NO);
++
++      if (!token_ipv6addr_and_mask(tok, &match_addr, &mask))
++        return (NO);
++
++      /*
++       * Zero the bits we're not interested in in both addresses
++       * then compare.  Note that we take a copy of the host info
++       * in that case.
++       */
++      if (mask != 128) {
++	ipv6_mask(&match_addr, mask);
++	ipv6_mask(&host_addr, mask);
++      }
++      if (memcmp(&match_addr, &host_addr, sizeof(struct in6_addr)) == 0)
++	return (YES);
++#endif
++      return (NO);
++    } else if ((mask = split_at(tok, '/')) != 0) {	/* net/mask */
++      return (masked_match(tok, mask, eval_hostaddr(host)));
+     } else {					/* anything else */
+-	return (string_match(tok, eval_hostaddr(host))
+-	    || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host))));
++      return (string_match(tok, eval_hostaddr(host))
++           || (NOT_INADDR(tok) && string_match(tok, eval_hostname(host))));
+     }
+ }
+ 
++static int masked_match(net_tok, mask_tok, string)
++char   *net_tok;
++char   *mask_tok;
++char   *string;
++{
++    unsigned long net;
++    unsigned long mask;
++    unsigned long addr;
++ 
++    /*
++     * Disallow forms other than dotted quad: the treatment that inet_addr()
++     * gives to forms with less than four components is inconsistent with the
++     * access control language. John P. Rouillard <rouilj@cs.umb.edu>.
++     */
++ 
++    if ((addr = dot_quad_addr(string)) == INADDR_NONE)
++	return (NO);
++    if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
++	|| ((mask = dot_quad_addr(mask_tok)) == INADDR_NONE
++	    && strcmp(mask_tok, "255.255.255.255")
++	    && (mask = prefix_to_netmask(mask_tok)) == INADDR_NONE
++	    && strcmp(mask_tok, "32"))) {
++	/* 255.255.255.255 == INADDR_NONE, separate check needed. TJ. */
++	/* 32 == INADDR_NONE, separate check needed. philipp */
++	tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
++	return (NO);				/* not tcpd_jump() */
++     }
++    return ((addr & mask) == net);
++}
++ 
+ /* string_match - match string against pattern 
+  * 
+  * tok = data read from /etc/hosts.*
+@@ -359,113 +487,14 @@ char   *string;
+ 	return (YES);
+     } else if (STR_EQ(tok, "KNOWN")) {		/* not unknown */
+ 	return (STR_NE(string, unknown));
+-    } else if (STR_EQ(tok, string))		/* exact match */
+-	return (YES);
+-#ifdef INET6
+-    else	/* IP addresses match - not needed for IPv4 */
+-    {
+-	/* For simplicity we convert everything to IPv6 (or v4 mapped) */
+-	struct in6_addr pat, addr;
+-	int len, ret, prefixlen=128, nof_periods = 0;
+-	char ch, token[INET6_ADDRSTRLEN+1], *mask, *addition;
+-
+-	/* If prefix was given, handle it */
+-	if ((mask = split_at(tok, '/')) != 0)
+-	{
+-		if (strchr(mask, '.') != NULL) /* We have something
+-                                                  like 255.255.0.0  */
+-                {
+-		   int b1, b2, b3, b4;
+-		   uint32_t netmask;
+-
+-		   if (sscanf(mask, "%d.%d.%d.%d", &b1, &b2, &b3, &b4) != 4)
+-		   {
+-			tcpd_warn ("Wrong netmask in %s", tok);
+-			return (NO);
+-		   }
+-		   netmask = (((((b1 * 256) + b2) * 256) + b3) * 256) + b4;
+-		   prefixlen = 0;
+-		   while (netmask > 0)
+-		   {
+-			++prefixlen;
+-			netmask  <<= 1;
+-                   }
+-                }
+-		else if (sscanf(mask, "%d", &prefixlen) != 1 || prefixlen < 0)
+-		{
+-			tcpd_warn ("Wrong prefix length in %s", tok);
+-			return (NO);
+-		}
+-		
+-		if (is_v4_string (tok))
+-			prefixlen += 96;	/* extend to v4mapped */
+-
+-		if (prefixlen > 128)
+-		{
+-			tcpd_warn ("Prefix too long in %s", tok);
+-			return (NO);
+-		}
+-	}
+-
+-	len = strlen(tok);
+-	if (tok[len - 1] == '.') {	/* prefix */
+-	  char *ptok = tok;
+-
+-	  while ((ptok = strchr(ptok, '.')) != NULL){
+-	    nof_periods++;
+-	    ptok++;
+-	  }
+-	  switch(nof_periods){
+-	  case 1:
+-	    addition = "0.0.0";
+-	    prefixlen = 8;
+-	    break;
+-	  case 2:
+-	    addition = "0.0";
+-	    prefixlen = 16;
+-	    break;
+-	  case 3:
+-	    addition = "0";
+-	    prefixlen = 24;
+-	    break;
+-	  default: 
+-	    tcpd_warn ("Wrong prefix %s", tok);
+-	    return (NO);
+-	  }
+-	  snprintf(token, sizeof(token), "%s%s", tok, addition);
+-	  prefixlen += 96;	/* extend to v4mapped */
+-	}	
+-	else if (*tok == '[' && tok[len - 1] == ']') 
+-	{
+-		ch = tok[len - 1];
+-			tok[len - 1] = '\0';
+-			snprintf(token, sizeof(token), "%s", tok+1);
+-			tok[len - 1] = ch;
+-	}
+-	else
+-		snprintf(token, sizeof(token), "%s", tok);
+-	
+-	memset (&pat, 0, sizeof(pat));
+-	memset (&addr, 0, sizeof(addr));
+-
+-	if (inet_pton_mapped(AF_INET6, token, &pat) != 1)
+-		return (NO);
+-
+-	if (inet_pton_mapped(AF_INET6, string, &addr) != 1)
+-	{
+-		tcpd_warn("Unable to handle client address: %s", string);
+-		return (NO);
+-	}
+-
+-	if (prefixlen < 128)
+-	{
+-		apply_v6_prefix (&pat, prefixlen);
+-		apply_v6_prefix (&addr, prefixlen);
+-	}
+-
+-	return (!memcmp(&pat, &addr, sizeof(struct in6_addr)));
++    } else if (tok[(n = strlen(tok)) - 1] == '.') {	/* prefix */
++	return (STRN_EQ(tok, string, n));
++    } else if ((STR_EQ(tok, "localhost") || STR_EQ(tok, "localhost.localdomain"))
++	    && (STR_EQ(string, "localhost") || STR_EQ(string, "localhost.localdomain"))) {
++	return (YES); /* these localhosts are equivalent */
++    } else {					/* exact match */
++	return (STR_EQ(tok, string));
+     }
+-#endif
+ }
+ 
+ #ifndef DISABLE_WILDCARD_MATCHING
+@@ -535,3 +564,29 @@ int match_pattern_ylo(const char *s, con
+   /*NOTREACHED*/
+ }
+ #endif /* DISABLE_WILDCARD_MATCHING */
++
++#ifdef INET6
++/*
++ * Function that zeros all but the first "maskbits" bits of the IPV6 address
++ * This function can be made generic by specifying an address length as
++ * extra parameter. (So Wietse can implement 1.2.3.4/16)
++ */
++static void ipv6_mask(in6p, maskbits)
++struct in6_addr *in6p;
++int maskbits;
++{
++    unsigned char *p = (unsigned char*) in6p;
++
++    if (maskbits < 0 || maskbits >= 128)
++	return;
++
++    p += maskbits / 8;
++    maskbits %= 8;
++
++    if (maskbits != 0)
++	*p++ &= 0xff << (8 - maskbits);
++
++    while (p < (((unsigned char*) in6p)) + sizeof(*in6p))
++	*p++ = 0;
++}
++#endif
+Index: tcp_wrappers_7.6/misc.c
+===================================================================
+--- tcp_wrappers_7.6.orig/misc.c
++++ tcp_wrappers_7.6/misc.c
+@@ -107,3 +107,21 @@ char   *str;
+     }
+     return (runs == 4 ? inet_addr(str) : INADDR_NONE);
+ }
++
++/* prefix_to_netmask - convert prefix (0-32) to netmask */
++
++unsigned long prefix_to_netmask(str)
++char   *str;
++{
++    unsigned long prefix;
++    char *endptr;
++
++    if (!isdigit(str[0]))
++	return INADDR_NONE;
++
++    prefix = strtoul(str, &endptr, 10);
++    if ((endptr == str) || (*endptr != '\0') || (prefix > 32))
++	return INADDR_NONE;
++
++    return htonl(~0UL << (32 - prefix));
++}
+Index: tcp_wrappers_7.6/tcpd.h
+===================================================================
+--- tcp_wrappers_7.6.orig/tcpd.h
++++ tcp_wrappers_7.6/tcpd.h
+@@ -88,6 +88,7 @@ extern void refuse(struct request_info *
+ extern char *xgets(char *, int, FILE *);
+ extern char *split_at(char *, int);
+ extern unsigned long dot_quad_addr(char *);
++extern char *skip_ipv6_addrs(char *);
+ #else
+ extern int hosts_access();		/* access control */
+ extern void shell_cmd();		/* execute shell command */
+@@ -98,6 +99,7 @@ extern void refuse();			/* clean up and
+ extern char *xgets();			/* fgets() on steroids */
+ extern char *split_at();		/* strchr() and split */
+ extern unsigned long dot_quad_addr();	/* restricted inet_addr() */
++extern char *skip_ipv6_addrs();
+ #endif
+ 
+ /* Global variables. */
diff --git a/tcp_wrappers_7.6-ipv6-mapped-v4.patch b/tcp_wrappers_7.6-ipv6-mapped-v4.patch
new file mode 100644
index 0000000..6a58ea9
--- /dev/null
+++ b/tcp_wrappers_7.6-ipv6-mapped-v4.patch
@@ -0,0 +1,56 @@
+---
+ hosts_access.c |    2 +-
+ socket.c       |   14 +++++++++-----
+ 2 files changed, 10 insertions(+), 6 deletions(-)
+
+Index: tcp_wrappers_7.6/hosts_access.c
+===================================================================
+--- tcp_wrappers_7.6.orig/hosts_access.c
++++ tcp_wrappers_7.6/hosts_access.c
+@@ -461,7 +461,7 @@ char   *string;
+      }
+     return ((addr & mask) == net);
+ }
+- 
++
+ /* string_match - match string against pattern 
+  * 
+  * tok = data read from /etc/hosts.*
+Index: tcp_wrappers_7.6/socket.c
+===================================================================
+--- tcp_wrappers_7.6.orig/socket.c
++++ tcp_wrappers_7.6/socket.c
+@@ -187,24 +187,28 @@ struct host_info *host;
+ #ifdef INET6
+     struct sockaddr *sin = (struct sockaddr *) host->sin;
+     char *ap;
+-    int alen;
++    int af;
+ 
+     if (!sin)
+         return;
+-    switch (sin->sa_family) {
++
++    af = sin->sa_family;
++    switch (af) {
+         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);
++	    if (IN6_IS_ADDR_V4MAPPED(ap)) {
++		ap = &((struct in6_addr *) ap)->s6_addr32[3];
++		af = AF_INET;
++	    }
+             break;
+         default:
+             return;
+     }
+     host->addr[0] = '\0';
+-    inet_ntop(sin->sa_family, ap, host->addr, sizeof(host->addr));
++    inet_ntop(af, ap, host->addr, sizeof(host->addr));
+ #else
+     struct sockaddr_in *sin = host->sin;
+ 
diff --git a/tcp_wrappers_7.6-ipv6-sockaddr-storage.patch b/tcp_wrappers_7.6-ipv6-sockaddr-storage.patch
new file mode 100644
index 0000000..96258ee
--- /dev/null
+++ b/tcp_wrappers_7.6-ipv6-sockaddr-storage.patch
@@ -0,0 +1,297 @@
+---
+ ip6utils.h |    2 +
+ rfc931.c   |  101 +++++++++++++++++++++++++++++++++++++++----------------------
+ scaffold.c |    9 +----
+ socket.c   |   14 +-------
+ tcpd.h     |    8 +---
+ update.c   |    4 +-
+ 6 files changed, 76 insertions(+), 62 deletions(-)
+
+Index: tcp_wrappers_7.6/ip6utils.h
+===================================================================
+--- tcp_wrappers_7.6.orig/ip6utils.h
++++ tcp_wrappers_7.6/ip6utils.h
+@@ -1,6 +1,8 @@
+ #ifndef IP6UTILS_H
+ #define IP6UTILS_H
+ 
++#include <netinet/in.h>
++
+ /* inet_pton_mapped() 
+    - works like inet_pton(3) but always returns IPv6 address 
+    in dst - either "real" or v4mapped (::ffff:1.2.3.4) in 
+Index: tcp_wrappers_7.6/rfc931.c
+===================================================================
+--- tcp_wrappers_7.6.orig/rfc931.c
++++ tcp_wrappers_7.6/rfc931.c
+@@ -65,28 +65,69 @@ int     sig;
+     siglongjmp(timebuf, sig);
+ }
+ 
++static inline unsigned int
++sockaddr_len(const struct sockaddr_storage *ap)
++{
++  switch (ap->ss_family) {
++  case AF_INET:
++    return sizeof(struct sockaddr_in);
++
++  case AF_INET6:
++    return sizeof(struct sockaddr_in6);
++
++  }
++
++  return 0;
++}
++
++static inline unsigned short
++sockaddr_port(const struct sockaddr_storage *ap)
++{
++  unsigned short num;
++
++  switch (ap->ss_family) {
++  case AF_INET:
++    num = ((const struct sockaddr_in *) ap)->sin_port;
++    break;
++  case AF_INET6:
++    num = ((const struct sockaddr_in6 *) ap)->sin6_port;
++    break;
++  default:
++    num = 0;
++    break;
++  }
++
++  return ntohs(num);
++}
++
++static inline void
++sockaddr_set_port(struct sockaddr_storage *ap, unsigned short port)
++{
++  unsigned short num = htons(port);
++
++  switch (ap->ss_family) {
++  case AF_INET:
++    ((struct sockaddr_in *) ap)->sin_port = num;
++    break;
++  case AF_INET6:
++    ((struct sockaddr_in6 *) ap)->sin6_port = num;
++    break;
++  }
++}
++
++
+ /* rfc931 - return remote user name, given socket structures */
+ 
+ void    rfc931(rmt_sin, our_sin, dest)
+-#ifdef INET6
+-struct sockaddr *rmt_sin;
+-struct sockaddr *our_sin;
+-#else
+-struct sockaddr_in *rmt_sin;
+-struct sockaddr_in *our_sin;
+-#endif
++struct sockaddr_storage *rmt_sin;
++struct sockaddr_storage *our_sin;
+ char   *dest;
+ {
+     unsigned rmt_port;
+     unsigned our_port;
+-#ifdef INET6
+     struct sockaddr_storage rmt_query_sin;
+     struct sockaddr_storage our_query_sin;
+     int alen;
+-#else
+-    struct sockaddr_in rmt_query_sin;
+-    struct sockaddr_in our_query_sin;
+-#endif
+     char    user[256];			/* XXX */
+     char    buffer[512];		/* XXX */
+     char   *cp;
+@@ -97,18 +138,13 @@ char   *dest;
+ 
+ #ifdef INET6
+     /* address family must be the same */
+-    if (rmt_sin->sa_family != our_sin->sa_family) {
++    if (rmt_sin->ss_family != our_sin->ss_family) {
+ 	STRN_CPY(dest, result, STRING_LENGTH);
+ 	return;
+     }
+-    switch (our_sin->sa_family) {
+-    case AF_INET:
+-	alen = sizeof(struct sockaddr_in);
+-	break;
+-    case AF_INET6:
+-	alen = sizeof(struct sockaddr_in6);
+-	break;
+-    default:
++
++    alen = sockaddr_len(our_sin);
++    if (alen == 0) {
+ 	STRN_CPY(dest, result, STRING_LENGTH);
+ 	return;
+     }
+@@ -125,7 +161,7 @@ char   *dest;
+      */
+ 
+ #ifdef INET6
+-    if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) {
++    if ((fp = fsocket(our_sin->ss_family, SOCK_STREAM, 0)) != 0) {
+ #else
+     if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
+ #endif
+@@ -154,18 +190,11 @@ char   *dest;
+ 	     */
+ 
+ #ifdef INET6
+-	    memcpy(&our_query_sin, our_sin, alen);
+-	    memcpy(&rmt_query_sin, rmt_sin, alen);
+-	    switch (our_sin->sa_family) {
+-	    case AF_INET:
+-		((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT);
+-		((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC931_PORT);
+-		break;
+-	    case AF_INET6:
+-		((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT);
+-		((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC931_PORT);
+-		break;
+-	    }
++	    our_query_sin = *our_sin;
++	    sockaddr_set_port(&our_query_sin, ANY_PORT);
++
++	    rmt_query_sin = *rmt_sin;
++	    sockaddr_set_port(&rmt_query_sin, RFC931_PORT);
+ 
+ 	    if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
+ 		     alen) >= 0 &&
+@@ -191,8 +220,8 @@ char   *dest;
+ 
+ 		fprintf(fp, "%u,%u\r\n",
+ #ifdef INET6
+-			ntohs(((struct sockaddr_in *)rmt_sin)->sin_port),
+-			ntohs(((struct sockaddr_in *)our_sin)->sin_port));
++			sockaddr_port(rmt_sin),
++			sockaddr_port(our_sin));
+ #else
+ 			ntohs(rmt_sin->sin_port),
+ 			ntohs(our_sin->sin_port));
+Index: tcp_wrappers_7.6/scaffold.c
+===================================================================
+--- tcp_wrappers_7.6.orig/scaffold.c
++++ tcp_wrappers_7.6/scaffold.c
+@@ -336,13 +336,8 @@ struct request_info *request;
+ /* ARGSUSED */
+ 
+ void    rfc931(rmt_sin, our_sin, dest)
+-#ifndef INET6
+-struct sockaddr_in *rmt_sin;
+-struct sockaddr_in *our_sin;
+-#else
+-struct sockaddr *rmt_sin;
+-struct sockaddr *our_sin;
+-#endif
++struct sockaddr_storage *rmt_sin;
++struct sockaddr_storage *our_sin;
+ char   *dest;
+ {
+     strcpy(dest, unknown);
+Index: tcp_wrappers_7.6/tcpd.h
+===================================================================
+--- tcp_wrappers_7.6.orig/tcpd.h
++++ tcp_wrappers_7.6/tcpd.h
+@@ -19,11 +19,7 @@
+ struct host_info {
+     char    name[STRING_LENGTH];	/* access via eval_hostname(host) */
+     char    addr[STRING_LENGTH];	/* access via eval_hostaddr(host) */
+-#ifdef INET6
+-    struct sockaddr *sin;		/* socket address or 0 */
+-#else
+-    struct sockaddr_in *sin;		/* socket address or 0 */
+-#endif
++    struct sockaddr_storage *sin;		/* socket address or 0 */
+     struct t_unitdata *unit;		/* TLI transport address or 0 */
+     struct request_info *request;	/* for shared information */
+ };
+@@ -86,7 +82,7 @@ extern void fromhost();			/* get/validat
+ extern int hosts_access(struct request_info *);
+ extern void shell_cmd(char *);
+ extern char *percent_x(char *, int, char *, struct request_info *);
+-extern void rfc931(struct sockaddr *, struct sockaddr *, char *);
++extern void rfc931(struct sockaddr_storage *, struct sockaddr_storage *, char *);
+ extern void clean_exit(struct request_info *);
+ extern void refuse(struct request_info *);
+ extern char *xgets(char *, int, FILE *);
+Index: tcp_wrappers_7.6/socket.c
+===================================================================
+--- tcp_wrappers_7.6.orig/socket.c
++++ tcp_wrappers_7.6/socket.c
+@@ -116,11 +116,7 @@ struct request_info *request;
+     memset(buf, 0 sizeof(buf));
+ #endif
+     }
+-#ifdef INET6
+-    request->client->sin = (struct sockaddr *)&client;
+-#else
+     request->client->sin = &client;
+-#endif
+ 
+     /*
+      * Determine the server binding. This is used for client username
+@@ -133,11 +129,7 @@ struct request_info *request;
+     tcpd_warn("getsockname: %m");
+     return;
+     }
+-#ifdef INET6
+-    request->server->sin = (struct sockaddr *)&server;
+-#else
+     request->server->sin = &server;
+-#endif
+ }
+ 
+ 
+@@ -180,7 +172,7 @@ struct request_info *request;
+ 	sock_methods(request);
+ 
+ 	memcpy(&client, res->ai_addr, res->ai_addrlen);
+-	request->client->sin = (struct sockaddr *)&client;
++	request->client->sin = &client;
+ 	freeaddrinfo(res);
+ 
+ 	request->client->name[0] = 0;
+@@ -193,7 +185,7 @@ void    sock_hostaddr(host)
+ struct host_info *host;
+ {
+ #ifdef INET6
+-    struct sockaddr *sin = host->sin;
++    struct sockaddr *sin = (struct sockaddr *) host->sin;
+     char *ap;
+     int alen;
+ 
+@@ -227,7 +219,7 @@ void
+ sock_hostname(struct host_info *host)
+ {
+     struct addrinfo hints, *res, *resbase;
+-    struct sockaddr *sa = host->sin;
++    struct sockaddr *sa = (struct sockaddr *) host->sin;
+     struct sockaddr_in6 *sin6, sin6buf;
+     int errcode;
+     
+Index: tcp_wrappers_7.6/update.c
+===================================================================
+--- tcp_wrappers_7.6.orig/update.c
++++ tcp_wrappers_7.6/update.c
+@@ -48,14 +48,14 @@ va_list ap;
+ 	    continue;
+ 	case RQ_CLIENT_SIN:
+ #ifdef INET6
+-	    request->client->sin = va_arg(ap, struct sockaddr *);
++	    request->client->sin = va_arg(ap, struct sockaddr_storage *);
+ #else
+ 	    request->client->sin = va_arg(ap, struct sockaddr_in *);
+ #endif
+ 	    continue;
+ 	case RQ_SERVER_SIN:
+ #ifdef INET6
+-	    request->server->sin = va_arg(ap, struct sockaddr *);
++	    request->server->sin = va_arg(ap, struct sockaddr_storage *);
+ #else
+ 	    request->server->sin = va_arg(ap, struct sockaddr_in *);
+ #endif
diff --git a/tcp_wrappers_7.6-ipv6-subnet.diff b/tcp_wrappers_7.6-ipv6-subnet.diff
new file mode 100644
index 0000000..a26c8fb
--- /dev/null
+++ b/tcp_wrappers_7.6-ipv6-subnet.diff
@@ -0,0 +1,101 @@
+--- hosts_access.c	2014/10/11 17:16:13	1.57
++++ hosts_access.c	2014/10/12 16:11:45
+@@ -367,41 +367,10 @@
+ 	/* For simplicity we convert everything to IPv6 (or v4 mapped) */
+ 	struct in6_addr pat, addr;
+ 	int len, ret, prefixlen=128, nof_periods = 0;
+-	char ch, token[INET6_ADDRSTRLEN+1], *mask, *ptok = tok, *addition;
+-	len = strlen(tok);
+-	if (tok[(n = strlen(tok)) - 1] == '.') {	/* prefix */
+-	  while ((ptok = strchr(ptok, '.')) != NULL){
+-	    nof_periods++;
+-	    ptok++;
+-	  }
+-	  switch(nof_periods){
+-	  case 1:
+-	    addition = "0.0.0/8";
+-	    break;
+-	  case 2:
+-	    addition = "0.0/16";
+-	    break;
+-	  case 3:
+-	    addition = "0/24";
+-	    break;
+-	  default: 
+-	    tcpd_warn ("Wrong prefix %s", tok);
+-	    return (NO);
+-	  }
+-	  snprintf(token, sizeof(token), "%s%s", tok, addition);
+-	}	
+-	else if (*tok == '[' && tok[len - 1] == ']') 
+-	{
+-		ch = tok[len - 1];
+-			tok[len - 1] = '\0';
+-			snprintf(token, sizeof(token), "%s", tok+1);
+-			tok[len - 1] = ch;
+-	}
+-	else
+-		snprintf(token, sizeof(token), "%s", tok);
+-	
++	char ch, token[INET6_ADDRSTRLEN+1], *mask, *addition;
++
+ 	/* If prefix was given, handle it */
+-	if ((mask = split_at(token, '/')) != 0)
++	if ((mask = split_at(tok, '/')) != 0)
+ 	{
+ 		if (strchr(mask, '.') != NULL) /* We have something
+                                                   like 255.255.0.0  */
+@@ -428,7 +397,7 @@
+ 			return (NO);
+ 		}
+ 		
+-		if (is_v4_string (token))
++		if (is_v4_string (tok))
+ 			prefixlen += 96;	/* extend to v4mapped */
+ 
+ 		if (prefixlen > 128)
+@@ -437,6 +406,44 @@
+ 			return (NO);
+ 		}
+ 	}
++
++	len = strlen(tok);
++	if (tok[len - 1] == '.') {	/* prefix */
++	  char *ptok = tok;
++
++	  while ((ptok = strchr(ptok, '.')) != NULL){
++	    nof_periods++;
++	    ptok++;
++	  }
++	  switch(nof_periods){
++	  case 1:
++	    addition = "0.0.0";
++	    prefixlen = 8;
++	    break;
++	  case 2:
++	    addition = "0.0";
++	    prefixlen = 16;
++	    break;
++	  case 3:
++	    addition = "0";
++	    prefixlen = 24;
++	    break;
++	  default: 
++	    tcpd_warn ("Wrong prefix %s", tok);
++	    return (NO);
++	  }
++	  snprintf(token, sizeof(token), "%s%s", tok, addition);
++	  prefixlen += 96;	/* extend to v4mapped */
++	}	
++	else if (*tok == '[' && tok[len - 1] == ']') 
++	{
++		ch = tok[len - 1];
++			tok[len - 1] = '\0';
++			snprintf(token, sizeof(token), "%s", tok+1);
++			tok[len - 1] = ch;
++	}
++	else
++		snprintf(token, sizeof(token), "%s", tok);
+ 	
+ 	memset (&pat, 0, sizeof(pat));
+ 	memset (&addr, 0, sizeof(addr));
diff --git a/tcp_wrappers_7.6-ipv6.fix.fix.diff b/tcp_wrappers_7.6-ipv6.fix.fix.diff
new file mode 100644
index 0000000..d6569c3
--- /dev/null
+++ b/tcp_wrappers_7.6-ipv6.fix.fix.diff
@@ -0,0 +1,30 @@
+--- hosts_access.c.orig
++++ hosts_access.c
+@@ -354,7 +354,26 @@ char   *string;
+ 	/* If prefix was given, handle it */
+ 	if ((mask = split_at(token, '/')) != 0)
+ 	{
+-		if (sscanf(mask, "%d", &prefixlen) != 1 || prefixlen < 0)
++		if (strchr(mask, '.') != NULL) /* We have something
++                                                  like 255.255.0.0  */
++                {
++		   int b1, b2, b3, b4;
++		   uint32_t netmask;
++
++		   if (sscanf(mask, "%d.%d.%d.%d", &b1, &b2, &b3, &b4) != 4)
++		   {
++			tcpd_warn ("Wrong netmask in %s", tok);
++			return (NO);
++		   }
++		   netmask = (((((b1 * 256) + b2) * 256) + b3) * 256) + b4;
++		   prefixlen = 0;
++		   while (netmask > 0)
++		   {
++			++prefixlen;
++			netmask  <<= 1;
++                   }
++                }
++		else if (sscanf(mask, "%d", &prefixlen) != 1 || prefixlen < 0)
+ 		{
+ 			tcpd_warn ("Wrong prefix length in %s", tok);
+ 			return (NO);
diff --git a/tcp_wrappers_7.6-ipv6.fix.fix2.diff b/tcp_wrappers_7.6-ipv6.fix.fix2.diff
new file mode 100644
index 0000000..dcffc74
--- /dev/null
+++ b/tcp_wrappers_7.6-ipv6.fix.fix2.diff
@@ -0,0 +1,47 @@
+--- hosts_access.c.orig
++++ hosts_access.c
+@@ -328,8 +328,6 @@ char   *string;
+ 	return (YES);
+     } else if (STR_EQ(tok, "KNOWN")) {		/* not unknown */
+ 	return (STR_NE(string, unknown));
+-    } else if (tok[(n = strlen(tok)) - 1] == '.') {	/* prefix */
+-	return (STRN_EQ(tok, string, n));
+     } else if (STR_EQ(tok, string))		/* exact match */
+ 	return (YES);
+ #ifdef INET6
+@@ -337,11 +335,31 @@ char   *string;
+     {
+ 	/* For simplicity we convert everything to IPv6 (or v4 mapped) */
+ 	struct in6_addr pat, addr;
+-	int len, ret, prefixlen=128;
+-	char ch, token[INET6_ADDRSTRLEN+1], *mask;
+-	
++	int len, ret, prefixlen=128, nof_periods = 0;
++	char ch, token[INET6_ADDRSTRLEN+1], *mask, *ptok = tok, *addition;
+ 	len = strlen(tok);
+-	if (*tok == '[' && tok[len - 1] == ']') 
++	if (tok[(n = strlen(tok)) - 1] == '.') {	/* prefix */
++	  while ((ptok = strchr(ptok, '.')) != NULL){
++	    nof_periods++;
++	    ptok++;
++	  }
++	  switch(nof_periods){
++	  case 1:
++	    addition = "0.0.0/8";
++	    break;
++	  case 2:
++	    addition = "0.0/16";
++	    break;
++	  case 3:
++	    addition = "0/24";
++	    break;
++	  default: 
++	    tcpd_warn ("Wrong prefix %s", tok);
++	    return (NO);
++	  }
++	  snprintf(token, sizeof(token), "%s%s", tok, addition);
++	}	
++	else if (*tok == '[' && tok[len - 1] == ']') 
+ 	{
+ 		ch = tok[len - 1];
+ 			tok[len - 1] = '\0';
diff --git a/tcp_wrappers_7.6-multi_local_interfaces-fix.diff b/tcp_wrappers_7.6-multi_local_interfaces-fix.diff
new file mode 100644
index 0000000..9156b8c
--- /dev/null
+++ b/tcp_wrappers_7.6-multi_local_interfaces-fix.diff
@@ -0,0 +1,11 @@
+--- socket.c.orig
++++ socket.c
+@@ -282,7 +282,7 @@ sock_hostname(struct host_info *host)
+         return;
+     }
+ 
+-    if (STR_NE (host->name, res->ai_canonname) && STR_NE(host->name, "localhost"))
++    if ((!res->ai_canonname || STR_NE (host->name, res->ai_canonname)) && STR_NE(host->name, "localhost"))
+     {
+         /* We don't treat this as an error, though... */
+         tcpd_warn("host name mismatch: %s != %s (%s)",
diff --git a/tcp_wrappers_7.6-nonvoid.diff b/tcp_wrappers_7.6-nonvoid.diff
new file mode 100644
index 0000000..7785d95
--- /dev/null
+++ b/tcp_wrappers_7.6-nonvoid.diff
@@ -0,0 +1,67 @@
+--- fakelog.c.orig
++++ fakelog.c
+@@ -16,7 +16,7 @@ static char sccsid[] = "@(#) fakelog.c 1
+ /* openlog - dummy */
+ 
+ /* ARGSUSED */
+-
++void
+ openlog(name, logopt, facility)
+ char   *name;
+ int     logopt;
+@@ -26,7 +26,7 @@ int     facility;
+ }
+ 
+ /* vsyslog - format one record */
+-
++void
+ vsyslog(severity, fmt, ap)
+ int     severity;
+ char   *fmt;
+@@ -42,7 +42,7 @@ va_list ap;
+ /* syslog - format one record */
+ 
+ /* VARARGS */
+-
++void
+ VARARGS(syslog, int, severity)
+ {
+     va_list ap;
+@@ -55,7 +55,7 @@ VARARGS(syslog, int, severity)
+ }
+ 
+ /* closelog - dummy */
+-
++void
+ closelog()
+ {
+     /* void */
+--- fix_options.c.orig
++++ fix_options.c
+@@ -31,7 +31,7 @@ static char sccsid[] = "@(#) fix_options
+ #define BUFFER_SIZE	512		/* Was: BUFSIZ */
+ 
+ /* fix_options - get rid of IP-level socket options */
+-
++void
+ fix_options(request)
+ struct request_info *request;
+ {
+--- options.c.orig
++++ options.c
+@@ -541,6 +541,7 @@ char   *name;
+ 	    return (t->value);
+     tcpd_jump("bad syslog facility or severity: \"%s\"", name);
+     /* NOTREACHED */
++    return 0;
+ }
+ 
+ /* severity_option - change logging severity for this event (Dave Mitchell) */
+--- tcpd.c.orig
++++ tcpd.c
+@@ -132,4 +132,5 @@ char  **argv;
+     syslog(LOG_ERR, "error: cannot execute %s: %m", path);
+     clean_exit(&request);
+     /* NOTREACHED */
++    return 0;
+ }
diff --git a/tcp_wrappers_7.6-optflags.diff b/tcp_wrappers_7.6-optflags.diff
new file mode 100644
index 0000000..282d753
--- /dev/null
+++ b/tcp_wrappers_7.6-optflags.diff
@@ -0,0 +1,46 @@
+Index: Makefile
+===================================================================
+--- Makefile.orig
++++ Makefile
+@@ -673,7 +673,7 @@ SHLIBFLAGS = -Lshared -lwrap
+ shared/%.o: %.c                                                                
+ 	$(CC) $(CFLAGS) $(SHCFLAGS) -c $< -o $@
+ 
+-CFLAGS	= -O2 -pipe -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \
++CFLAGS	= $(RPM_OPT_FLAGS) $(shell getconf LFS_CFLAGS) -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \
+ 	$(BUGS) $(SYSTYPE) $(AUTH) $(UMASK) \
+ 	-DREAL_DAEMON_DIR=\"$(REAL_DAEMON_DIR)\" $(STYLE) $(KILL_OPT) \
+ 	-DSEVERITY=$(SEVERITY) -DRFC931_TIMEOUT=$(RFC931_TIMEOUT) \
+@@ -730,26 +730,26 @@ $(SHLIB): $(SHLIB_OBJ)
+ 	ln -s $(notdir $(SHLIBSOMAJ)) $(SHLIBSO)
+ 
+ tcpd:	tcpd.o $(SHLIB)
+-	$(CC) $(CFLAGS) -o $@ tcpd.o $(SHLIBFLAGS)
++	$(CC) -pie -o $@ tcpd.o $(SHLIBFLAGS)
+ 
+ miscd:	miscd.o $(SHLIB)
+-	$(CC) $(CFLAGS) -o $@ miscd.o $(SHLIBFLAGS)
++	$(CC) -pie -o $@ miscd.o $(SHLIBFLAGS)
+ 
+ safe_finger: safe_finger.o $(SHLIB)
+-	$(CC) $(CFLAGS) -o $@ safe_finger.o $(SHLIBFLAGS)
++	$(CC) -pie -o $@ safe_finger.o $(SHLIBFLAGS)
+ 
+ TCPDMATCH_OBJ = tcpdmatch.o fakelog.o inetcf.o scaffold.o
+ 
+ tcpdmatch: $(TCPDMATCH_OBJ) $(SHLIB)
+-	$(CC) $(CFLAGS) -o $@ $(TCPDMATCH_OBJ) $(SHLIBFLAGS)
++	$(CC) -pie -o $@ $(TCPDMATCH_OBJ) $(SHLIBFLAGS)
+ 
+ try-from: try-from.o fakelog.o $(SHLIB)
+-	$(CC) $(CFLAGS) -o $@ try-from.o fakelog.o $(SHLIBFLAGS)
++	$(CC) -pie -o $@ try-from.o fakelog.o $(SHLIBFLAGS)
+ 
+ TCPDCHK_OBJ = tcpdchk.o fakelog.o inetcf.o scaffold.o
+ 
+ tcpdchk: $(TCPDCHK_OBJ) $(SHLIB)
+-	$(CC) $(CFLAGS) -o $@ $(TCPDCHK_OBJ) $(SHLIBFLAGS)
++	$(CC) -pie -o $@ $(TCPDCHK_OBJ) $(SHLIBFLAGS)
+ 
+ shar:	$(KIT)
+ 	@shar $(KIT)
diff --git a/tcp_wrappers_7.6-prototypes.diff b/tcp_wrappers_7.6-prototypes.diff
new file mode 100644
index 0000000..7208370
--- /dev/null
+++ b/tcp_wrappers_7.6-prototypes.diff
@@ -0,0 +1,91 @@
+--- clean_exit.c.orig
++++ clean_exit.c
+@@ -13,6 +13,8 @@ static char sccsid[] = "@(#) clean_exit.
+ #endif
+ 
+ #include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
+ 
+ extern void exit();
+ 
+--- hosts_access.c.orig
++++ hosts_access.c
+@@ -31,6 +31,8 @@ static char sccsid[] = "@(#) hosts_acces
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <stdio.h>
++#include <unistd.h>
++#include <netdb.h>
+ #include <syslog.h>
+ #include <ctype.h>
+ #include <errno.h>
+--- inetcf.c.orig
++++ inetcf.c
+@@ -88,7 +88,7 @@ char   *conf;
+     } else {
+ 	for (i = 0; inet_files[i] && (fp = fopen(inet_files[i], "r")) == 0; i++)
+ 	     /* void */ ;
+-	if (fp == 0) {
++	if (!fp) {
+ 	    fprintf(stderr, "Cannot find your inetd.conf or tlid.conf file.\n");
+ 	    fprintf(stderr, "Please specify its location.\n");
+ 	    exit(1);
+--- ip6utils.c.orig
++++ ip6utils.c
+@@ -2,6 +2,7 @@
+ #include <sys/socket.h>
+ #include <arpa/inet.h>
+ #include <stdio.h>
++#include <string.h>
+ #include <errno.h>
+ 
+ #include "ip6utils.h"
+--- options.c.orig
++++ options.c
+@@ -41,6 +41,8 @@ static char sccsid[] = "@(#) options.c 1
+ #include <netinet/in.h>
+ #include <netdb.h>
+ #include <stdio.h>
++#include <unistd.h>
++#include <stdlib.h>
+ #include <syslog.h>
+ #include <pwd.h>
+ #include <grp.h>
+--- percent_x.c.orig
++++ percent_x.c
+@@ -18,6 +18,8 @@ static char sccsid[] = "@(#) percent_x.c
+ 
+ #include <stdio.h>
+ #include <syslog.h>
++#include <stdlib.h>
++#include <unistd.h>
+ #include <string.h>
+ 
+ extern void exit();
+--- shell_cmd.c.orig
++++ shell_cmd.c
+@@ -15,9 +15,13 @@ static char sccsid[] = "@(#) shell_cmd.c
+ /* System libraries. */
+ 
+ #include <sys/types.h>
++#include <sys/wait.h>
+ #include <sys/param.h>
+ #include <signal.h>
+ #include <stdio.h>
++#include <stdlib.h>
++#include <fcntl.h>
++#include <unistd.h>
+ #include <syslog.h>
+ #include <string.h>
+ 
+--- update.c.orig
++++ update.c
+@@ -21,6 +21,7 @@ static char sccsid[] = "@(#) update.c 1.
+ 
+ #include <stdio.h>
+ #include <syslog.h>
++#include <unistd.h>
+ #include <string.h>
+ 
+ /* Local stuff. */
diff --git a/tcp_wrappers_7.6-shared-lib.diff b/tcp_wrappers_7.6-shared-lib.diff
new file mode 100644
index 0000000..c4f4997
--- /dev/null
+++ b/tcp_wrappers_7.6-shared-lib.diff
@@ -0,0 +1,163 @@
+--- Makefile.orig
++++ Makefile
+@@ -145,9 +145,9 @@ freebsd:
+ 
+ linux:
+ 	@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
+-	LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= \
++	LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ=weak_symbols.o \
+ 	NETGROUP=-DNETGROUP TLI= \
+-	EXTRA_CFLAGS="-fPIC -DSYS_ERRLIST_DEFINED -DINET6=1 -Dss_family=__ss_family" all
++	EXTRA_CFLAGS="-fPIC -DSYS_ERRLIST_DEFINED -DINET6=1 -Dss_family=__ss_family -DHAVE_WEAKSYMS -D_REENTRANT" all
+ 
+ # This is good for many SYSV+BSD hybrids with NIS, probably also for HP-UX 7.x.
+ hpux hpux8 hpux9 hpux10:
+@@ -660,7 +660,18 @@ HOSTNAME= -DALWAYS_HOSTNAME
+ # Protection against weird shells or weird make programs.
+ 
+ SHELL	= /bin/sh
+-.c.o:;	$(CC) $(CFLAGS) -c $*.c
++.c.o:;	$(CC) $(CFLAGS) -o $*.o -c $*.c
++
++SOMAJOR = 0
++SOMINOR = 7.6
++LIB	= libwrap.a
++SHLIB	= shared/libwrap.so.$(SOMAJOR).$(SOMINOR)
++SHLIBSOMAJ = shared/libwrap.so.$(SOMAJOR)
++SHLIBSO	= shared/libwrap.so
++SHLIBFLAGS = -Lshared -lwrap
++
++shared/%.o: %.c                                                                
++	$(CC) $(CFLAGS) $(SHCFLAGS) -c $< -o $@
+ 
+ CFLAGS	= -O2 -pipe -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \
+ 	$(BUGS) $(SYSTYPE) $(AUTH) $(UMASK) \
+@@ -669,11 +680,16 @@ CFLAGS	= -O2 -pipe -DFACILITY=$(FACILITY
+ 	$(UCHAR) $(TABLES) $(STRINGS) $(TLI) $(EXTRA_CFLAGS) $(DOT) \
+ 	$(VSYSLOG)
+ 
++SHLINKFLAGS = -shared -Xlinker -soname -Xlinker libwrap.so.$(SOMAJOR) -lc $(LIBS)
++SHCFLAGS = -fPIC -shared -D_REENTRANT
++
+ LIB_OBJ= hosts_access.o options.o shell_cmd.o rfc931.o eval.o \
+ 	hosts_ctl.o refuse.o percent_x.o clean_exit.o $(AUX_OBJ) \
+ 	$(FROM_OBJ) fix_options.o socket.o tli.o workarounds.o \
+ 	update.o misc.o diag.o percent_m.o myvsyslog.o ip6utils.o
+ 
++SHLIB_OBJ= $(addprefix shared/, $(LIB_OBJ));
++
+ FROM_OBJ= fromhost.o
+ 
+ KIT	= README miscd.c tcpd.c fromhost.c hosts_access.c shell_cmd.c \
+@@ -688,9 +704,8 @@ KIT	= README miscd.c tcpd.c fromhost.c h
+ 	ip6utils.c ip6utils.h \
+ 	scaffold.h tcpdmatch.8 README.NIS
+ 
+-LIB	= libwrap.a
++all other: config-check tcpd tcpdmatch try-from safe_finger tcpdchk $(LIB)
+ 
+-all other: config-check tcpd tcpdmatch try-from safe_finger tcpdchk
+ 
+ # Invalidate all object files when the compiler options (CFLAGS) have changed.
+ 
+@@ -701,33 +716,40 @@ config-check:
+ 	then rm /tmp/cflags.$$$$ ; \
+ 	else mv /tmp/cflags.$$$$ cflags ; \
+ 	fi >/dev/null 2>/dev/null
++	@if [ ! -d shared ]; then mkdir shared; fi
+ 
+ $(LIB):	$(LIB_OBJ)
+ 	rm -f $(LIB)
+ 	$(AR) $(ARFLAGS) $(LIB) $(LIB_OBJ)
+ 	-$(RANLIB) $(LIB)
+ 
+-tcpd:	tcpd.o $(LIB)
+-	$(CC) $(CFLAGS) -o $@ tcpd.o $(LIB) $(LIBS)
++$(SHLIB): $(SHLIB_OBJ)
++	rm -f $(SHLIB)
++	$(CC) -o $(SHLIB) $(SHLINKFLAGS) $(SHLIB_OBJ)
++	ln -s $(notdir $(SHLIB)) $(SHLIBSOMAJ)
++	ln -s $(notdir $(SHLIBSOMAJ)) $(SHLIBSO)
++
++tcpd:	tcpd.o $(SHLIB)
++	$(CC) $(CFLAGS) -o $@ tcpd.o $(SHLIBFLAGS)
+ 
+-miscd:	miscd.o $(LIB)
+-	$(CC) $(CFLAGS) -o $@ miscd.o $(LIB) $(LIBS)
++miscd:	miscd.o $(SHLIB)
++	$(CC) $(CFLAGS) -o $@ miscd.o $(SHLIBFLAGS)
+ 
+-safe_finger: safe_finger.o $(LIB)
+-	$(CC) $(CFLAGS) -o $@ safe_finger.o $(LIB) $(LIBS)
++safe_finger: safe_finger.o $(SHLIB)
++	$(CC) $(CFLAGS) -o $@ safe_finger.o $(SHLIBFLAGS)
+ 
+ TCPDMATCH_OBJ = tcpdmatch.o fakelog.o inetcf.o scaffold.o
+ 
+-tcpdmatch: $(TCPDMATCH_OBJ) $(LIB)
+-	$(CC) $(CFLAGS) -o $@ $(TCPDMATCH_OBJ) $(LIB) $(LIBS)
++tcpdmatch: $(TCPDMATCH_OBJ) $(SHLIB)
++	$(CC) $(CFLAGS) -o $@ $(TCPDMATCH_OBJ) $(SHLIBFLAGS)
+ 
+-try-from: try-from.o fakelog.o $(LIB)
+-	$(CC) $(CFLAGS) -o $@ try-from.o fakelog.o $(LIB) $(LIBS)
++try-from: try-from.o fakelog.o $(SHLIB)
++	$(CC) $(CFLAGS) -o $@ try-from.o fakelog.o $(SHLIBFLAGS)
+ 
+ TCPDCHK_OBJ = tcpdchk.o fakelog.o inetcf.o scaffold.o
+ 
+-tcpdchk: $(TCPDCHK_OBJ) $(LIB)
+-	$(CC) $(CFLAGS) -o $@ $(TCPDCHK_OBJ) $(LIB) $(LIBS)
++tcpdchk: $(TCPDCHK_OBJ) $(SHLIB)
++	$(CC) $(CFLAGS) -o $@ $(TCPDCHK_OBJ) $(SHLIBFLAGS)
+ 
+ shar:	$(KIT)
+ 	@shar $(KIT)
+@@ -743,7 +765,8 @@ archive:
+ 
+ clean:
+ 	rm -f tcpd miscd safe_finger tcpdmatch tcpdchk try-from *.[oa] core \
+-	cflags
++	cflags libwrap*.so*
++	rm -rf shared
+ 
+ tidy:	clean
+ 	chmod -R a+r .
+@@ -890,5 +913,6 @@ update.o: cflags
+ update.o: mystdarg.h
+ update.o: tcpd.h
+ vfprintf.o: cflags
++weak_symbols.o: tcpd.h
+ workarounds.o: cflags
+ workarounds.o: tcpd.h
+--- tcpd.h.orig
++++ tcpd.h
+@@ -106,8 +106,14 @@ extern unsigned long dot_quad_addr();	/*
+ 
+ /* Global variables. */
+ 
++#ifdef HAVE_WEAKSYMS
++extern int allow_severity __attribute__ ((weak)); /* for connection logging */
++extern int deny_severity __attribute__ ((weak)); /* for connection logging */
++#else
+ extern int allow_severity;		/* for connection logging */
+ extern int deny_severity;		/* for connection logging */
++#endif
++
+ extern char *hosts_allow_table;		/* for verification mode redirection */
+ extern char *hosts_deny_table;		/* for verification mode redirection */
+ extern int hosts_access_verbose;	/* for verbose matching mode */
+--- /dev/null
++++ weak_symbols.c
+@@ -0,0 +1,11 @@
++/*
++ * @(#) weak_symbols.h 1.5 99/12/29 23:50
++ * 
++ * Author: Anthony Towns <ajt@debian.org>
++ */
++
++#ifdef HAVE_WEAKSYMS
++#include <syslog.h>
++int deny_severity = LOG_WARNING;
++int allow_severity = SEVERITY;
++#endif
diff --git a/tcp_wrappers_7.6-shared-lib2.diff b/tcp_wrappers_7.6-shared-lib2.diff
new file mode 100644
index 0000000..f24f1e2
--- /dev/null
+++ b/tcp_wrappers_7.6-shared-lib2.diff
@@ -0,0 +1,18 @@
+--- tcpd.h.orig
++++ tcpd.h
+@@ -126,10 +126,15 @@ extern int resident;			/* > 0 if residen
+   */
+ 
+ #ifdef __STDC__
++extern int hosts_access(struct request_info *request);
++extern int hosts_ctl(char *daemon, char *client_name, char *client_addr,
++                     char *client_user);
+ extern struct request_info *request_init(struct request_info *,...);
+ extern struct request_info *request_set(struct request_info *,...);
+ extern int hosts_ctl(char *daemon, char *client_name, char *client_addr, char *client_user);
+ #else
++extern int hosts_access();
++extern int hosts_ctl();
+ extern struct request_info *request_init();	/* initialize request */
+ extern struct request_info *request_set();	/* update request structure */
+ #endif
diff --git a/tcp_wrappers_7.6-uninitialized.diff b/tcp_wrappers_7.6-uninitialized.diff
new file mode 100644
index 0000000..9e87f7c
--- /dev/null
+++ b/tcp_wrappers_7.6-uninitialized.diff
@@ -0,0 +1,11 @@
+--- inetcf.c.orig
++++ inetcf.c
+@@ -61,7 +61,7 @@ char   *inet_cfg(conf)
+ char   *conf;
+ {
+     char    buf[BUFSIZ];
+-    FILE   *fp;
++    FILE   *fp = NULL;
+     char   *service;
+     char   *protocol;
+     char   *user;
diff --git a/tcp_wrappers_7.6.diff b/tcp_wrappers_7.6.diff
new file mode 100644
index 0000000..8b68b18
--- /dev/null
+++ b/tcp_wrappers_7.6.diff
@@ -0,0 +1,364 @@
+--- Makefile.orig
++++ Makefile
+@@ -44,7 +44,7 @@ what:
+ #REAL_DAEMON_DIR=/usr/etc
+ #
+ # SysV.4 Solaris 2.x OSF AIX
+-#REAL_DAEMON_DIR=/usr/sbin
++REAL_DAEMON_DIR=/usr/sbin
+ #
+ # BSD 4.4
+ #REAL_DAEMON_DIR=/usr/libexec
+@@ -143,8 +143,9 @@ freebsd:
+ 
+ linux:
+ 	@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
+-	LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o \
+-	NETGROUP= TLI= EXTRA_CFLAGS="-DBROKEN_SO_LINGER" all
++	LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= \
++	NETGROUP=-DNETGROUP TLI= \
++	EXTRA_CFLAGS="-fPIC -DSYS_ERRLIST_DEFINED -DINET6=1 -Dss_family=__ss_family" all
+ 
+ # This is good for many SYSV+BSD hybrids with NIS, probably also for HP-UX 7.x.
+ hpux hpux8 hpux9 hpux10:
+@@ -229,7 +230,7 @@ tandem:
+ 
+ # Amdahl UTS 2.1.5 (Richard.Richmond@bridge.bst.bls.com)
+ uts215:
+-	@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \   
++	@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
+ 	LIBS="-lsocket" RANLIB=echo \
+ 	ARFLAGS=rv AUX_OBJ=setenv.o NETGROUP=-DNO_NETGROUP TLI= all
+ 
+@@ -472,7 +473,7 @@ BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS
+ # If your system supports vsyslog(), comment out the following definition.
+ # If in doubt leave it in, it won't harm.
+ 
+-VSYSLOG	= -Dvsyslog=myvsyslog
++#VSYSLOG	= -Dvsyslog=myvsyslog
+ 
+ # End of the system dependencies.
+ #################################
+@@ -491,7 +492,7 @@ VSYSLOG	= -Dvsyslog=myvsyslog
+ # Uncomment the next definition to turn on the language extensions
+ # (examples: allow, deny, banners, twist and spawn).
+ # 
+-#STYLE	= -DPROCESS_OPTIONS	# Enable language extensions.
++STYLE	= -DPROCESS_OPTIONS	# Enable language extensions.
+ 
+ ################################################################
+ # Optional: Changing the default disposition of logfile records
+@@ -514,7 +515,7 @@ VSYSLOG	= -Dvsyslog=myvsyslog
+ #
+ # The LOG_XXX names below are taken from the /usr/include/syslog.h file.
+ 
+-FACILITY= LOG_MAIL	# LOG_MAIL is what most sendmail daemons use
++FACILITY= LOG_AUTHPRIV	# LOG_MAIL is what most sendmail daemons use
+ 
+ # The syslog priority at which successful connections are logged.
+ 
+@@ -531,7 +532,7 @@ SEVERITY= LOG_INFO	# LOG_INFO is normall
+ # and with Solaris < 2.4. APPEND_DOT will not work with hostnames taken
+ # from /etc/hosts or from NIS maps. It does work with DNS through NIS.
+ #
+-# DOT= -DAPPEND_DOT
++DOT= -DAPPEND_DOT
+ 
+ ##################################################
+ # Optional: Always attempt remote username lookups
+@@ -610,7 +611,7 @@ TABLES	= -DHOSTS_DENY=\"/etc/hosts.deny\
+ # Paranoid mode implies hostname lookup. In order to disable hostname
+ # lookups altogether, see the next section.
+ 
+-PARANOID= -DPARANOID
++#PARANOID= -DPARANOID
+ 
+ ########################################
+ # Optional: turning off hostname lookups
+@@ -649,7 +650,7 @@ HOSTNAME= -DALWAYS_HOSTNAME
+ # source-routed traffic in the kernel. Examples: 4.4BSD derivatives,
+ # Solaris 2.x, and Linux. See your system documentation for details.
+ #
+-# KILL_OPT= -DKILL_IP_OPTIONS
++#KILL_OPT= -DKILL_IP_OPTIONS
+ 
+ ## End configuration options
+ ############################
+@@ -659,12 +660,12 @@ HOSTNAME= -DALWAYS_HOSTNAME
+ SHELL	= /bin/sh
+ .c.o:;	$(CC) $(CFLAGS) -c $*.c
+ 
+-CFLAGS	= -O -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \
++CFLAGS	= -O2 -pipe -DFACILITY=$(FACILITY) $(ACCESS) $(PARANOID) $(NETGROUP) \
+ 	$(BUGS) $(SYSTYPE) $(AUTH) $(UMASK) \
+ 	-DREAL_DAEMON_DIR=\"$(REAL_DAEMON_DIR)\" $(STYLE) $(KILL_OPT) \
+ 	-DSEVERITY=$(SEVERITY) -DRFC931_TIMEOUT=$(RFC931_TIMEOUT) \
+ 	$(UCHAR) $(TABLES) $(STRINGS) $(TLI) $(EXTRA_CFLAGS) $(DOT) \
+-	$(VSYSLOG) $(HOSTNAME)
++	$(VSYSLOG)
+ 
+ LIB_OBJ= hosts_access.o options.o shell_cmd.o rfc931.o eval.o \
+ 	hosts_ctl.o refuse.o percent_x.o clean_exit.o $(AUX_OBJ) \
+--- /dev/null
++++ README.ipv6
+@@ -0,0 +1,17 @@
++;; IPv6 patch for tcp_wrappers_7.6 1.6
++;; Aug 23, 1999 by Hajimu UMEMOTO <ume@mahoroba.org>
++;;
++;; This patch supports IPv4/IPv6 dual stack and IPv4-mapped IPv6 address.
++;; You can replace stock tcpd or libwrap.a with this.
++;; IPv6 address pattern is as a `[net]/prefixlen' pair.
++;; This patch was tested on KAME/FreeBSD, KAME/FreeBSD3, KAME/NetBSD,
++;; RedHat 5.1 with kernel 2.1.126, and RedHat 6.0 with kernel 2.2.10.
++;;
++;; CAUTION:
++;; Back out change for field separater.  Now, field separater is `:'
++;; not `|'.  To specify IPv6 address, enclose IPv6 address with `['
++;; and `]'.
++;;
++;; For Linux users:
++;; If your libc doesn't have sockaddr_storage, try target `linux-old'.
++
+--- hosts_access.c.orig
++++ hosts_access.c
+@@ -89,6 +90,33 @@ static int masked_match();
+ 
+ /* hosts_access - host access control facility */
+ 
++static int
++yp_get_default_domain (char **outdomain)
++{
++  static char __ypdomainname[1025] = "\0";
++  int result = 0;
++  *outdomain = NULL;
++
++  if (__ypdomainname[0] == '\0')
++    {
++      if (getdomainname (__ypdomainname, 1024))
++        result = 1;
++      else if (strcmp (__ypdomainname, "(none)") == 0)
++        {
++          /* If domainname is not set, some Systems will return "(none)" */
++          __ypdomainname[0] = '\0';
++          result = 1;
++        }
++      else
++        *outdomain = __ypdomainname;
++    }
++  else
++    *outdomain = __ypdomainname;
++
++  return result;
++}
++
++
+ int     hosts_access(request)
+ struct request_info *request;
+ {
+--- safe_finger.c.orig
++++ safe_finger.c
+@@ -31,7 +31,7 @@ extern void exit();
+ 
+ /* Local stuff */
+ 
+-char    path[] = "PATH=/bin:/usr/bin:/usr/ucb:/usr/bsd:/etc:/usr/etc:/usr/sbin";
++char    path[] = "PATH=/bin:/usr/bin:/usr/sbin";
+ 
+ #define	TIME_LIMIT	60		/* Do not keep listinging forever */
+ #define	INPUT_LENGTH	100000		/* Do not keep listinging forever */
+--- scaffold.c.orig
++++ scaffold.c
+@@ -180,10 +180,17 @@ struct request_info *request;
+ 
+ /* ARGSUSED */
+ 
+-void    rfc931(request)
+-struct request_info *request;
++void    rfc931(rmt_sin, our_sin, dest)
++#ifndef INET6
++struct sockaddr_in *rmt_sin;
++struct sockaddr_in *our_sin;
++#else
++struct sockaddr *rmt_sin;
++struct sockaddr *our_sin;
++#endif
++char   *dest;
+ {
+-    strcpy(request->user, unknown);
++    strcpy(dest, unknown);
+ }
+ 
+ /* check_path - examine accessibility */
+--- tcpd.h.orig
++++ tcpd.h
+@@ -4,6 +4,12 @@
+   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
+   */
+ 
++#ifdef __STDC__
++#include <stdio.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#endif
++
+ /* Structure to describe one communications endpoint. */
+ 
+ #define STRING_LENGTH	128		/* hosts, users, processes */
+@@ -61,11 +67,26 @@ extern char paranoid[];
+ /* Global functions. */
+ 
+ #if defined(TLI) || defined(PTX) || defined(TLI_SEQUENT)
++#ifdef __STDC__
++extern void fromhost(struct request_info *);
++#else
+ extern void fromhost();			/* get/validate client host info */
++#endif
+ #else
+ #define fromhost sock_host		/* no TLI support needed */
+ #endif
+ 
++#ifdef __STDC__
++extern int hosts_access(struct request_info *);
++extern void shell_cmd(char *);
++extern char *percent_x(char *, int, char *, struct request_info *);
++extern void rfc931(struct sockaddr *, struct sockaddr *, char *);
++extern void clean_exit(struct request_info *);
++extern void refuse(struct request_info *);
++extern char *xgets(char *, int, FILE *);
++extern char *split_at(char *, int);
++extern unsigned long dot_quad_addr(char *);
++#else
+ extern int hosts_access();		/* access control */
+ extern void shell_cmd();		/* execute shell command */
+ extern char *percent_x();		/* do %<char> expansion */
+@@ -75,6 +96,7 @@ extern void refuse();			/* clean up and
+ extern char *xgets();			/* fgets() on steroids */
+ extern char *split_at();		/* strchr() and split */
+ extern unsigned long dot_quad_addr();	/* restricted inet_addr() */
++#endif
+ 
+ /* Global variables. */
+ 
+@@ -117,28 +139,47 @@ extern struct request_info *request_set(
+   * host_info structures serve as caches for the lookup results.
+   */
+ 
++#ifdef __STDC__
++extern char *eval_user(struct request_info *);
++extern char *eval_hostname(struct host_info *);
++extern char *eval_hostaddr(struct host_info *);
++extern char *eval_hostinfo(struct host_info *);
++extern char *eval_client(struct request_info *);
++extern char *eval_server(struct request_info *);
++#else
+ extern char *eval_user();		/* client user */
+ extern char *eval_hostname();		/* printable hostname */
+ extern char *eval_hostaddr();		/* printable host address */
+ extern char *eval_hostinfo();		/* host name or address */
+ extern char *eval_client();		/* whatever is available */
+ extern char *eval_server();		/* whatever is available */
++#endif
+ #define eval_daemon(r)	((r)->daemon)	/* daemon process name */
+ #define eval_pid(r)	((r)->pid)	/* process id */
+ 
+ /* Socket-specific methods, including DNS hostname lookups. */
+ 
++#ifdef __STDC__
++extern void sock_host(struct request_info *);
++extern void sock_hostname(struct host_info *);
++extern void sock_hostaddr(struct host_info *);
++#else
+ extern void sock_host();		/* look up endpoint addresses */
+ extern void sock_hostname();		/* translate address to hostname */
+ extern void sock_hostaddr();		/* address to printable address */
++#endif
+ #define sock_methods(r) \
+ 	{ (r)->hostname = sock_hostname; (r)->hostaddr = sock_hostaddr; }
+ 
+ /* The System V Transport-Level Interface (TLI) interface. */
+ 
+ #if defined(TLI) || defined(PTX) || defined(TLI_SEQUENT)
++#ifdef __STDC__
++extern void tli_host(struct request_info *);
++#else
+ extern void tli_host();			/* look up endpoint addresses etc. */
+ #endif
++#endif
+ 
+  /*
+   * Problem reporting interface. Additional file/line context is reported
+@@ -178,42 +219,74 @@ extern struct tcpd_context tcpd_context;
+   * behavior.
+   */
+ 
++#ifdef __STDC__
++extern void process_options(char *, struct request_info *);
++#else
+ extern void process_options();		/* execute options */
++#endif
+ extern int dry_run;			/* verification flag */
+ 
+ /* Bug workarounds. */
+ 
+ #ifdef INET_ADDR_BUG			/* inet_addr() returns struct */
+ #define inet_addr fix_inet_addr
++#ifdef __STDC__
++extern long fix_inet_addr(char *);
++#else
+ extern long fix_inet_addr();
+ #endif
++#endif
+ 
+ #ifdef BROKEN_FGETS			/* partial reads from sockets */
+ #define fgets fix_fgets
++#ifdef __STDC__
++extern char *fix_fgets(char *, int, FILE *);
++#else
+ extern char *fix_fgets();
+ #endif
++#endif
+ 
+ #ifdef RECVFROM_BUG			/* no address family info */
+ #define recvfrom fix_recvfrom
++#ifdef __STDC__
++extern int fix_recvfrom(int, char *, int, int, struct sockaddr *, int *);
++#else
+ extern int fix_recvfrom();
+ #endif
++#endif
+ 
+ #ifdef GETPEERNAME_BUG			/* claims success with UDP */
+ #define getpeername fix_getpeername
++#ifdef __STDC__
++extern int fix_getpeername(int, struct sockaddr *, int *);
++#else
+ extern int fix_getpeername();
+ #endif
++#endif
+ 
+ #ifdef SOLARIS_24_GETHOSTBYNAME_BUG	/* lists addresses as aliases */
+ #define gethostbyname fix_gethostbyname
++#ifdef __STDC__
++extern struct hostent *fix_gethostbyname(char *);
++#else
+ extern struct hostent *fix_gethostbyname();
+ #endif
++#endif
+ 
+ #ifdef USE_STRSEP			/* libc calls strtok() */
+ #define strtok	fix_strtok
++#ifdef __STDC__
++extern char *fix_strtok(char *, char *);
++#else
+ extern char *fix_strtok();
+ #endif
++#endif
+ 
+ #ifdef LIBC_CALLS_STRTOK		/* libc calls strtok() */
+ #define strtok	my_strtok
++#ifdef __STDC__
++extern char *my_strtok(char *, char *);
++#else
+ extern char *my_strtok();
+ #endif
++#endif
diff --git a/tcpd-ocloexec.patch b/tcpd-ocloexec.patch
new file mode 100644
index 0000000..99bee9f
--- /dev/null
+++ b/tcpd-ocloexec.patch
@@ -0,0 +1,70 @@
+--- rfc931.c.orig
++++ rfc931.c
+@@ -45,7 +45,7 @@ int     protocol;
+     int     s;
+     FILE   *fp;
+ 
+-    if ((s = socket(domain, type, protocol)) < 0) {
++    if ((s = socket(domain, type | SOCK_CLOEXEC, protocol)) < 0) {
+ 	tcpd_warn("socket: %m");
+ 	return (0);
+     } else {
+--- tcpdchk.c.orig
++++ tcpdchk.c
+@@ -210,7 +210,7 @@ struct request_info *request;
+ 
+     saved_context = tcpd_context;		/* stupid compilers */
+ 
+-    if (fp = fopen(table, "r")) {
++    if (fp = fopen(table, "re")) {
+ 	tcpd_context.file = table;
+ 	tcpd_context.line = 0;
+ 	while (xgets(sv_list, sizeof(sv_list), fp)) {
+--- inetcf.c.orig
++++ inetcf.c
+@@ -81,12 +81,12 @@ char   *conf;
+      * guesses.
+      */
+     if (conf != 0) {
+-	if ((fp = fopen(conf, "r")) == 0) {
++	if ((fp = fopen(conf, "re")) == 0) {
+ 	    fprintf(stderr, percent_m(buf, "open %s: %m\n"), conf);
+ 	    exit(1);
+ 	}
+     } else {
+-	for (i = 0; inet_files[i] && (fp = fopen(inet_files[i], "r")) == 0; i++)
++	for (i = 0; inet_files[i] && (fp = fopen(inet_files[i], "re")) == 0; i++)
+ 	     /* void */ ;
+ 	if (!fp) {
+ 	    fprintf(stderr, "Cannot find your inetd.conf or tlid.conf file.\n");
+--- options.c.orig
++++ options.c
+@@ -227,7 +227,7 @@ struct request_info *request;
+     FILE   *fp;
+ 
+     sprintf(path, "%s/%s", value, eval_daemon(request));
+-    if ((fp = fopen(path, "r")) != 0) {
++    if ((fp = fopen(path, "re")) != 0) {
+ 	while ((ch = fgetc(fp)) == 0)
+ 	    write(request->fd, "", 1);
+ 	ungetc(ch, fp);
+--- hosts_access.c.orig
++++ hosts_access.c
+@@ -173,7 +173,7 @@ struct request_info *request;
+      * file descriptor leaks.
+      */
+ 
+-    if ((fp = fopen(table, "r")) != 0) {
++    if ((fp = fopen(table, "re")) != 0) {
+ 	tcpd_context.file = table;
+ 	tcpd_context.line = 0;
+ 	while (match == NO && xgets(sv_list, sizeof(sv_list), fp) != 0) {
+@@ -283,7 +283,7 @@ struct hosts_info *host;
+     int     match = NO;
+     FILE   *fp;
+ 
+-    if ((fp = fopen(path, "r")) != 0) {
++    if ((fp = fopen(path, "re")) != 0) {
+ 	while (fscanf(fp, "%s", tok) == 1 && !(match = host_match(tok, host)))
+ 	     /* void */ ;
+ 	fclose(fp);
diff --git a/tcpd.changes b/tcpd.changes
new file mode 100644
index 0000000..2a55ea6
--- /dev/null
+++ b/tcpd.changes
@@ -0,0 +1,121 @@
+* Sat Jun  3 2017 meissner@suse.com
+- tcp_wrappers_7.6-optflags.diff: enable PIE for all binaries
+  directly.
+* Wed Apr  6 2016 kukuk@suse.de
+- tcp_wrappers_7.6.diff: don't use public headers for own
+  functions, make own yp_get_default_domain static.
+* Mon Jul 20 2015 okir@suse.com
+- Fix breakage of IPv6 address handling [bsc#914527, bsc#899185]
+  Added patches:
+  tcp_wrappers_7.6-ipv6-sockaddr-storage.patch
+  tcp_wrappers_7.6-ipv6-subnet.diff
+  tcp_wrappers_7.6-ipv6-host-match.patch
+  tcp_wrappers_7.6-ipv6-mapped-v4.patch
+- Re-added static library
+* Fri Nov 28 2014 tchvatal@suse.com
+- Cleanup with spec-cleaner
+- Remove obsolete sections of provides from 2k6
+- Remove static library
+* Mon Aug 18 2014 fcrozat@suse.com
+- Add obsoletes/provides to baselibs.conf
+* Mon Jun  3 2013 crrodriguez@opensuse.org
+- tcpd-ocloexec.patch: Use O_CLOEXEC whenever neccesary,
+  otherwise fd leaks will follow.
+* Fri Apr  5 2013 idonmez@suse.com
+- Cleanup spec file
+- Add Source URL, see https://en.opensuse.org/SourceUrls
+* Sun Jan 20 2013 jengelh@inai.de
+- Implement shared library packaging guidelines (split libwrap0)
+- Parallel build with %%_smp_mflags instead of %%jobs
+- Remove redundant %%clean sections
+* Sun Apr 22 2012 crrodriguez@opensuse.org
+- Refresh all patches
+- Also, pass getconf LFS_CFLAGS into CFLAGS
+* Wed Oct  5 2011 uli@suse.com
+- cross-build fix: use %%__cc macro
+* Mon Feb  1 2010 jengelh@medozas.de
+- remove not-needed sparcv9 baselib exception
+* Sun Dec 13 2009 jengelh@medozas.de
+- add baselibs.conf as a source
+- add baselibs for SPARC
+- enable parallel building
+* Fri Oct 30 2009 crrodriguez@opensuse.org
+- fix build
+* Wed Jan  7 2009 olh@suse.de
+- obsolete old -XXbit packages (bnc#437293)
+* Tue Nov 11 2008 ro@suse.de
+- SLE-11 uses PPC64 instead of PPC, adapt baselibs.conf
+* Mon Oct 13 2008 prusnak@suse.cz
+- applied patches from Fedora package
+  * fedora-bug11881.diff - replace sprintf with snprintf
+  * fedora-bug17795.diff - add hostfile matching
+  * fedora-bug17847.diff - add wildcard matching
+  * fedora-bug141110.diff - fix table_match usage
+  * fedora-bug220015.diff - add sock_hostnofd function
+  * fedora-docu.diff - fix manpage
+  * fedora-fixgethostbyname.diff - fix gethostbyname usage
+  * fedora-sig.diff - fix signal usage
+  * fedora-sigalarm.diff - fix signal usage
+  * fedora-sigchld.diff - fix signal usage
+  * fedora-sigjmp.diff - fix signal usage
+  * fedora-strerror.diff - fix strerror usage
+* Thu Apr 10 2008 ro@suse.de
+- added baselibs.conf file to build xxbit packages
+  for multilib support
+* Tue May 30 2006 lmichnovic@suse.cz
+- fixed uninitilized filepointer (uninitialized.diff) [#178636]
+* Fri Mar 31 2006 lmichnovic@suse.cz
+- fixed missing definition of hosts_ctl() in tcpd.h (hosts_ctl.diff)
+  [#162303]
+* Wed Jan 25 2006 mls@suse.de
+- converted neededforbuild to BuildRequires
+* Sun Jan 15 2006 schwab@suse.de
+- Don't strip binaries.
+* Fri Sep 16 2005 meissner@suse.de
+- fixed all implicit warnings.
+* Fri Jun 24 2005 ro@suse.de
+- build with fPIE/pie
+- really use RPM_OPT_FLAGS
+- fix some non-void-return warnings
+* Thu Jan 13 2005 postadal@suse.cz
+- fixed crashing on system with more than one network interface [#49368]
+* Wed Sep 15 2004 aj@suse.de
+- Fix warnings about implicit functions to compile with GCC 4.0.
+* Mon Mar 22 2004 ro@suse.de
+- installed shared lib to /%%_lib, not /usr/%%_lib
+  and add symlinks (fix for part of #36514)
+* Thu Feb 12 2004 kukuk@suse.de
+- Create subpackage "tcpd-devel"
+* Mon Feb  9 2004 postadal@suse.cz
+- added support for compiling as shared library with soname of libwrap0 (version 7.6)
+* Sun Jan 11 2004 adrian@suse.de
+- build as user
+* Fri Oct 31 2003 postadal@suse.cz
+- fixed invalid warning about "host name mismatch" [#26519, #32772]
+* Wed Sep 10 2003 postadal@suse.cz
+- fixed handling patterns ending with period [#27322]
+* Sat Mar 15 2003 kukuk@suse.de
+- Don't handle IPv4 netmask as Prefix length [#25409]
+* Mon Dec 16 2002 postadal@suse.cz
+- added ip6utils.h to filelist [#22487]
+* Fri Dec 13 2002 postadal@suse.cz
+- fixed fix_options function in libwrap.a [#22000]
+- included patch ipv6-fix.diff of mludvig@suse.cz to make tcpd work
+  with IPv4 and mapped IPv4 addresses. [#16162]
+- turned off remote username lookups (allways_rfc931) [#22013]
+* Thu Jan 10 2002 cihlar@suse.cz
+- use %%{_libdir}
+* Tue Nov 20 2001 cihlar@suse.cz
+- fixed SEGFAULT in tcpdchk [#12135]
+* Thu Sep  6 2001 schwab@suse.de
+- Compile with -fPIC so that it can be included in a shared library.
+* Wed Sep  5 2001 schwab@suse.de
+- Add prototypes for C++.
+* Thu Mar 22 2001 ro@suse.de
+- added split-aliases as provides
+* Tue Feb 27 2001 cihlar@suse.cz
+- fixed %%files
+- clean up spec file
+- bzipped sources
+* Tue Apr 11 2000 kukuk@suse.de
+- Split from nkitb
diff --git a/tcpd.spec b/tcpd.spec
new file mode 100644
index 0000000..b7d49e9
--- /dev/null
+++ b/tcpd.spec
@@ -0,0 +1,169 @@
+#
+# spec file for package tcpd
+#
+# Copyright (c) 2022-2023 ZhuningOS
+#
+
+
+%define lname	libwrap0
+
+Name:           tcpd
+Version:        7.6
+Release:        1.433
+Summary:        A security wrapper for TCP daemons
+License:        BSD-3-Clause
+Group:          Productivity/Networking/System
+Url:            ftp://ftp.porcupine.org/pub/security/index.html
+Source:         ftp://ftp.porcupine.org/pub/security/tcp_wrappers_%{version}.tar.gz
+Source2:        baselibs.conf
+Patch0:         tcp_wrappers_%{version}.diff
+Patch1:         tcp_wrappers_%{version}-ipv6-1.6.diff
+Patch2:         tcp_wrappers_%{version}-ipv6-fix.diff
+Patch3:         tcp_wrappers_%{version}-ipv6.fix.fix.diff
+Patch4:         tcp_wrappers_%{version}-ipv6.fix.fix2.diff
+Patch5:         tcp_wrappers_%{version}-host_name_mapping-fix.diff
+Patch6:         tcp_wrappers_%{version}-fix_options-fix.diff
+Patch7:         tcp_wrappers_%{version}-shared-lib.diff
+Patch8:         tcp_wrappers_%{version}-builtin.diff
+Patch9:         tcp_wrappers_%{version}-multi_local_interfaces-fix.diff
+Patch10:        tcp_wrappers_%{version}-optflags.diff
+Patch11:        tcp_wrappers_%{version}-nonvoid.diff
+Patch12:        tcp_wrappers_%{version}-prototypes.diff
+Patch13:        tcp_wrappers_%{version}-hosts_ctl.diff
+Patch14:        tcp_wrappers_%{version}-uninitialized.diff
+Patch15:        tcp_wrappers_%{version}-fedora-bug11881.diff
+Patch16:        tcp_wrappers_%{version}-fedora-bug141110.diff
+Patch17:        tcp_wrappers_%{version}-fedora-docu.diff
+Patch18:        tcp_wrappers_%{version}-fedora-sig.diff
+Patch19:        tcp_wrappers_%{version}-fedora-sigchld.diff
+Patch20:        tcp_wrappers_%{version}-fedora-sigjmp.diff
+Patch21:        tcp_wrappers_%{version}-fedora-sigalarm.diff
+Patch22:        tcp_wrappers_%{version}-fedora-strerror.diff
+Patch23:        tcp_wrappers_%{version}-fedora-fixgethostbyname.diff
+Patch24:        tcp_wrappers_%{version}-fedora-bug220015.diff
+Patch25:        tcp_wrappers_%{version}-shared-lib2.diff
+Patch26:        tcp_wrappers_%{version}-fedora-bug17795.diff
+Patch27:        tcp_wrappers_%{version}-fedora-bug17847.diff
+Patch28:        tcp_wrappers_7.6-implicit-decl.patch
+Patch29:        tcpd-ocloexec.patch
+Patch30:        tcp_wrappers_%{version}-ipv6-sockaddr-storage.patch
+Patch31:        tcp_wrappers_%{version}-ipv6-subnet.diff
+Patch32:        tcp_wrappers_%{version}-ipv6-host-match.patch
+Patch33:        tcp_wrappers_%{version}-ipv6-mapped-v4.patch
+BuildRequires:  linux-kernel-headers
+Provides:       nkitb:%{_sbindir}/tcpd
+# bug437293
+%ifarch ppc64
+Obsoletes:      tcpd-64bit
+%endif
+BuildRoot:      %{_tmppath}/%{name}-%{version}-build
+
+%description
+This package contains a small daemon program that can monitor and
+filter incoming requests for finger, ftp, telnet, rlogin, rsh, exec,
+tftp, talk, and other network services.
+
+%package -n %{lname}
+Summary:        The TCP wrapper library
+Group:          System/Libraries
+
+%description -n %{lname}
+This package contains a library which implements classifying incoming
+requests (connections) based upon rule exclusion files (%{_sysconfdir}/hosts.*).
+
+%package devel
+Summary:        Include Files and Libraries for the TCP wrapper library
+Group:          Development/Languages/C and C++
+Requires:       %{lname} = %{version}
+Requires:       glibc-devel
+# bug437293
+%ifarch ppc64
+Obsoletes:      tcpd-devel-64bit
+%endif
+#
+
+%description devel
+This package contains the library and header files, which are necessary
+to compile and link programs against the TCP wrapper library.
+
+%prep
+%setup -q -n tcp_wrappers_%{version}
+%patch0
+%patch1
+%patch2
+%patch3
+%patch4
+%patch5
+%patch6
+%patch7
+%patch8
+%patch9
+%patch10
+%patch11
+%patch12
+%patch13
+%patch14
+%patch15
+%patch16
+%patch17
+%patch18
+%patch19
+%patch20
+%patch21
+%patch22
+%patch23
+%patch24
+%patch25
+%patch26
+%patch27
+%patch28
+%patch29
+%patch30 -p1
+%patch31
+%patch32 -p1
+%patch33 -p1
+
+%build
+make %{?_smp_mflags} linux CC="cc"
+
+%install
+install -d -m 755 %{buildroot}%{_includedir}
+install -d -m 755 %{buildroot}%{_libdir}
+install -d -m 755 %{buildroot}%{_sbindir}
+install -d -m 755 %{buildroot}%{_mandir}/man{1,3,5,8}
+install -d -m 755 %{buildroot}/%{_lib}
+install -m 644 ip6utils.h tcpd.h %{buildroot}%{_includedir}
+install -m 644 libwrap.a %{buildroot}/%{_libdir}
+install -m 755 safe_finger tcpd tcpdchk tcpdmatch try-from %{buildroot}%{_sbindir}
+install -m 644 hosts_access.3 %{buildroot}%{_mandir}/man3
+install -m 644 hosts_access.5 hosts_options.5 %{buildroot}%{_mandir}/man5
+install -m 644 tcpd.8 tcpdchk.8 tcpdmatch.8 %{buildroot}%{_mandir}/man8
+install -m 644 shared/libwrap.so.0.%{version} %{buildroot}/%{_lib}
+cd %{buildroot}/%{_lib}
+ln -sf libwrap.so.0.%{version} libwrap.so.0
+cd %{buildroot}%{_libdir}
+ln -sf /%{_lib}/libwrap.so.0.%{version} libwrap.so
+
+%post -n %{lname} -p /sbin/ldconfig
+
+%postun -n %{lname} -p /sbin/ldconfig
+
+%files
+%defattr(644,root,root,755)
+%doc BLURB CHANGES DISCLAIMER README README.ipv6 README.NIS
+%doc %{_mandir}/man?/*
+%attr(755,root,root) %{_sbindir}/*
+
+%files -n %{lname}
+%defattr(-,root,root)
+%doc DISCLAIMER
+%attr(755,root,root) /%{_lib}/libwrap.so.0*
+
+%files devel
+%defattr(644,root,root,755)
+%{_includedir}/tcpd.h
+%{_includedir}/ip6utils.h
+%{_libdir}/libwrap.a
+%{_libdir}/libwrap.so
+
+%changelog