xref: /OK3568_Linux_fs/yocto/poky/meta/recipes-extended/tcp-wrappers/tcp-wrappers-7.6/10_usagi-ipv6.patch (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593SmuzhiyunUpstream-Status: Backport
2*4882a593Smuzhiyun
3*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/fix_options.c tcp_wrappers_7.6/fix_options.c
4*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/fix_options.c	1997-04-08 02:29:19.000000000 +0200
5*4882a593Smuzhiyun+++ tcp_wrappers_7.6/fix_options.c	2004-04-10 19:07:43.000000000 +0200
6*4882a593Smuzhiyun@@ -11,6 +11,9 @@
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <sys/types.h>
9*4882a593Smuzhiyun #include <sys/param.h>
10*4882a593Smuzhiyun+#ifdef INET6
11*4882a593Smuzhiyun+#include <sys/socket.h>
12*4882a593Smuzhiyun+#endif
13*4882a593Smuzhiyun #include <netinet/in.h>
14*4882a593Smuzhiyun #include <netinet/in_systm.h>
15*4882a593Smuzhiyun #include <netinet/ip.h>
16*4882a593Smuzhiyun@@ -41,6 +44,22 @@
17*4882a593Smuzhiyun     unsigned int opt;
18*4882a593Smuzhiyun     int     optlen;
19*4882a593Smuzhiyun     struct in_addr dummy;
20*4882a593Smuzhiyun+#ifdef INET6
21*4882a593Smuzhiyun+    struct sockaddr_storage ss;
22*4882a593Smuzhiyun+    int sslen;
23*4882a593Smuzhiyun+
24*4882a593Smuzhiyun+    /*
25*4882a593Smuzhiyun+     * check if this is AF_INET socket
26*4882a593Smuzhiyun+     * XXX IPv6 support?
27*4882a593Smuzhiyun+     */
28*4882a593Smuzhiyun+    sslen = sizeof(ss);
29*4882a593Smuzhiyun+    if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) {
30*4882a593Smuzhiyun+	syslog(LOG_ERR, "getpeername: %m");
31*4882a593Smuzhiyun+	clean_exit(request);
32*4882a593Smuzhiyun+    }
33*4882a593Smuzhiyun+    if (ss.ss_family != AF_INET)
34*4882a593Smuzhiyun+	return;
35*4882a593Smuzhiyun+#endif
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun     if ((ip = getprotobyname("ip")) != 0)
38*4882a593Smuzhiyun 	ipproto = ip->p_proto;
39*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/hosts_access.5 tcp_wrappers_7.6/hosts_access.5
40*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/hosts_access.5	2004-04-10 19:22:58.000000000 +0200
41*4882a593Smuzhiyun+++ tcp_wrappers_7.6/hosts_access.5	2004-04-10 19:07:43.000000000 +0200
42*4882a593Smuzhiyun@@ -85,11 +85,18 @@
43*4882a593Smuzhiyun for daemon process names or for client user names.
44*4882a593Smuzhiyun .IP \(bu
45*4882a593Smuzhiyun An expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a
46*4882a593Smuzhiyun-`net/mask\' pair. A host address is matched if `net\' is equal to the
47*4882a593Smuzhiyun+`net/mask\' pair. An IPv4 host address is matched if `net\' is equal to the
48*4882a593Smuzhiyun bitwise AND of the address and the `mask\'. For example, the net/mask
49*4882a593Smuzhiyun pattern `131.155.72.0/255.255.254.0\' matches every address in the
50*4882a593Smuzhiyun range `131.155.72.0\' through `131.155.73.255\'.
51*4882a593Smuzhiyun .IP \(bu
52*4882a593Smuzhiyun+An expression of the form `[n:n:n:n:n:n:n:n]/m\' is interpreted as a
53*4882a593Smuzhiyun+`[net]/prefixlen\' pair. An IPv6 host address is matched if
54*4882a593Smuzhiyun+`prefixlen\' bits of `net\' is equal to the `prefixlen\' bits of the
55*4882a593Smuzhiyun+address. For example, the [net]/prefixlen pattern
56*4882a593Smuzhiyun+`[3ffe:505:2:1::]/64\' matches every address in the range
57*4882a593Smuzhiyun+`3ffe:505:2:1::\' through `3ffe:505:2:1:ffff:ffff:ffff:ffff\'.
58*4882a593Smuzhiyun+.IP \(bu
59*4882a593Smuzhiyun Wildcards `*\' and `?\' can be used to match hostnames or IP addresses.  This
60*4882a593Smuzhiyun method of matching cannot be used in conjunction with `net/mask\' matching,
61*4882a593Smuzhiyun hostname matching beginning with `.\' or IP address matching ending with `.\'.
62*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/hosts_access.c tcp_wrappers_7.6/hosts_access.c
63*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/hosts_access.c	2004-04-10 19:22:58.000000000 +0200
64*4882a593Smuzhiyun+++ tcp_wrappers_7.6/hosts_access.c	2004-04-10 19:07:43.000000000 +0200
65*4882a593Smuzhiyun@@ -24,7 +24,13 @@
66*4882a593Smuzhiyun /* System libraries. */
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun #include <sys/types.h>
69*4882a593Smuzhiyun+#ifdef INT32_T
70*4882a593Smuzhiyun+    typedef uint32_t u_int32_t;
71*4882a593Smuzhiyun+#endif
72*4882a593Smuzhiyun #include <sys/param.h>
73*4882a593Smuzhiyun+#ifdef INET6
74*4882a593Smuzhiyun+#include <sys/socket.h>
75*4882a593Smuzhiyun+#endif
76*4882a593Smuzhiyun #include <netinet/in.h>
77*4882a593Smuzhiyun #include <arpa/inet.h>
78*4882a593Smuzhiyun #include <stdio.h>
79*4882a593Smuzhiyun@@ -33,6 +39,9 @@
80*4882a593Smuzhiyun #include <errno.h>
81*4882a593Smuzhiyun #include <setjmp.h>
82*4882a593Smuzhiyun #include <string.h>
83*4882a593Smuzhiyun+#ifdef INET6
84*4882a593Smuzhiyun+#include <netdb.h>
85*4882a593Smuzhiyun+#endif
86*4882a593Smuzhiyun
87*4882a593Smuzhiyun extern char *fgets();
88*4882a593Smuzhiyun extern int errno;
89*4882a593Smuzhiyun@@ -82,6 +91,10 @@
90*4882a593Smuzhiyun static int host_match();
91*4882a593Smuzhiyun static int string_match();
92*4882a593Smuzhiyun static int masked_match();
93*4882a593Smuzhiyun+#ifdef INET6
94*4882a593Smuzhiyun+static int masked_match4();
95*4882a593Smuzhiyun+static int masked_match6();
96*4882a593Smuzhiyun+#endif
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /* Size of logical line buffer. */
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun@@ -289,6 +302,13 @@
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun     int     n;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun+#ifdef INET6
105*4882a593Smuzhiyun+    /* convert IPv4 mapped IPv6 address to IPv4 address */
106*4882a593Smuzhiyun+    if (STRN_EQ(string, "::ffff:", 7)
107*4882a593Smuzhiyun+      && dot_quad_addr(string + 7) != INADDR_NONE) {
108*4882a593Smuzhiyun+      string += 7;
109*4882a593Smuzhiyun+    }
110*4882a593Smuzhiyun+#endif
111*4882a593Smuzhiyun #ifndef DISABLE_WILDCARD_MATCHING
112*4882a593Smuzhiyun     if (strchr(tok, '*') || strchr(tok,'?')) {  /* contains '*' or '?' */
113*4882a593Smuzhiyun         return (match_pattern_ylo(string,tok));
114*4882a593Smuzhiyun@@ -304,20 +324,72 @@
115*4882a593Smuzhiyun     } else if (tok[(n = strlen(tok)) - 1] == '.') {	/* prefix */
116*4882a593Smuzhiyun 	return (STRN_EQ(tok, string, n));
117*4882a593Smuzhiyun     } else {					/* exact match */
118*4882a593Smuzhiyun+#ifdef INET6
119*4882a593Smuzhiyun+	struct addrinfo hints, *res;
120*4882a593Smuzhiyun+	struct sockaddr_in6 pat, addr;
121*4882a593Smuzhiyun+	int len, ret;
122*4882a593Smuzhiyun+	char ch;
123*4882a593Smuzhiyun+
124*4882a593Smuzhiyun+	len = strlen(tok);
125*4882a593Smuzhiyun+	if (*tok == '[' && tok[len - 1] == ']') {
126*4882a593Smuzhiyun+	    ch = tok[len - 1];
127*4882a593Smuzhiyun+	    tok[len - 1] = '\0';
128*4882a593Smuzhiyun+	    memset(&hints, 0, sizeof(hints));
129*4882a593Smuzhiyun+	    hints.ai_family = AF_INET6;
130*4882a593Smuzhiyun+	    hints.ai_socktype = SOCK_STREAM;
131*4882a593Smuzhiyun+	    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
132*4882a593Smuzhiyun+	    if ((ret = getaddrinfo(tok + 1, NULL, &hints, &res)) == 0) {
133*4882a593Smuzhiyun+		memcpy(&pat, res->ai_addr, sizeof(pat));
134*4882a593Smuzhiyun+		freeaddrinfo(res);
135*4882a593Smuzhiyun+	    }
136*4882a593Smuzhiyun+	    tok[len - 1] = ch;
137*4882a593Smuzhiyun+	    if (ret != 0 || getaddrinfo(string, NULL, &hints, &res) != 0)
138*4882a593Smuzhiyun+		return NO;
139*4882a593Smuzhiyun+	    memcpy(&addr, res->ai_addr, sizeof(addr));
140*4882a593Smuzhiyun+	    freeaddrinfo(res);
141*4882a593Smuzhiyun+#ifdef NI_WITHSCOPEID
142*4882a593Smuzhiyun+	    if (pat.sin6_scope_id != 0 &&
143*4882a593Smuzhiyun+		addr.sin6_scope_id != pat.sin6_scope_id)
144*4882a593Smuzhiyun+		return NO;
145*4882a593Smuzhiyun+#endif
146*4882a593Smuzhiyun+	    return (!memcmp(&pat.sin6_addr, &addr.sin6_addr,
147*4882a593Smuzhiyun+			    sizeof(struct in6_addr)));
148*4882a593Smuzhiyun+	    return (ret);
149*4882a593Smuzhiyun+	}
150*4882a593Smuzhiyun+#endif
151*4882a593Smuzhiyun 	return (STR_EQ(tok, string));
152*4882a593Smuzhiyun     }
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /* masked_match - match address against netnumber/netmask */
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun+#ifdef INET6
158*4882a593Smuzhiyun static int masked_match(net_tok, mask_tok, string)
159*4882a593Smuzhiyun char   *net_tok;
160*4882a593Smuzhiyun char   *mask_tok;
161*4882a593Smuzhiyun char   *string;
162*4882a593Smuzhiyun {
163*4882a593Smuzhiyun+    return (masked_match4(net_tok, mask_tok, string) ||
164*4882a593Smuzhiyun+	    masked_match6(net_tok, mask_tok, string));
165*4882a593Smuzhiyun+}
166*4882a593Smuzhiyun+
167*4882a593Smuzhiyun+static int masked_match4(net_tok, mask_tok, string)
168*4882a593Smuzhiyun+#else
169*4882a593Smuzhiyun+static int masked_match(net_tok, mask_tok, string)
170*4882a593Smuzhiyun+#endif
171*4882a593Smuzhiyun+char   *net_tok;
172*4882a593Smuzhiyun+char   *mask_tok;
173*4882a593Smuzhiyun+char   *string;
174*4882a593Smuzhiyun+{
175*4882a593Smuzhiyun+#ifdef INET6
176*4882a593Smuzhiyun+    u_int32_t net;
177*4882a593Smuzhiyun+    u_int32_t mask;
178*4882a593Smuzhiyun+    u_int32_t addr;
179*4882a593Smuzhiyun+#else
180*4882a593Smuzhiyun     unsigned long net;
181*4882a593Smuzhiyun     unsigned long mask;
182*4882a593Smuzhiyun     unsigned long addr;
183*4882a593Smuzhiyun+#endif
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun     /*
186*4882a593Smuzhiyun      * Disallow forms other than dotted quad: the treatment that inet_addr()
187*4882a593Smuzhiyun@@ -329,12 +401,78 @@
188*4882a593Smuzhiyun 	return (NO);
189*4882a593Smuzhiyun     if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
190*4882a593Smuzhiyun 	|| (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) {
191*4882a593Smuzhiyun+#ifndef INET6
192*4882a593Smuzhiyun 	tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
193*4882a593Smuzhiyun+#endif
194*4882a593Smuzhiyun 	return (NO);				/* not tcpd_jump() */
195*4882a593Smuzhiyun     }
196*4882a593Smuzhiyun     return ((addr & mask) == net);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun+#ifdef INET6
200*4882a593Smuzhiyun+static int masked_match6(net_tok, mask_tok, string)
201*4882a593Smuzhiyun+char   *net_tok;
202*4882a593Smuzhiyun+char   *mask_tok;
203*4882a593Smuzhiyun+char   *string;
204*4882a593Smuzhiyun+{
205*4882a593Smuzhiyun+    struct addrinfo hints, *res;
206*4882a593Smuzhiyun+    struct sockaddr_in6 net, addr;
207*4882a593Smuzhiyun+    u_int32_t mask;
208*4882a593Smuzhiyun+    int len, mask_len, i = 0;
209*4882a593Smuzhiyun+    char ch;
210*4882a593Smuzhiyun+
211*4882a593Smuzhiyun+    memset(&hints, 0, sizeof(hints));
212*4882a593Smuzhiyun+    hints.ai_family = AF_INET6;
213*4882a593Smuzhiyun+    hints.ai_socktype = SOCK_STREAM;
214*4882a593Smuzhiyun+    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
215*4882a593Smuzhiyun+    if (getaddrinfo(string, NULL, &hints, &res) != 0)
216*4882a593Smuzhiyun+	return NO;
217*4882a593Smuzhiyun+    memcpy(&addr, res->ai_addr, sizeof(addr));
218*4882a593Smuzhiyun+    freeaddrinfo(res);
219*4882a593Smuzhiyun+
220*4882a593Smuzhiyun+    if (IN6_IS_ADDR_V4MAPPED(&addr.sin6_addr)) {
221*4882a593Smuzhiyun+	if ((*(u_int32_t *)&net.sin6_addr.s6_addr[12] = dot_quad_addr(net_tok)) == INADDR_NONE
222*4882a593Smuzhiyun+	 || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE)
223*4882a593Smuzhiyun+	    return (NO);
224*4882a593Smuzhiyun+	return ((*(u_int32_t *)&addr.sin6_addr.s6_addr[12] & mask) == *(u_int32_t *)&net.sin6_addr.s6_addr[12]);
225*4882a593Smuzhiyun+    }
226*4882a593Smuzhiyun+
227*4882a593Smuzhiyun+    /* match IPv6 address against netnumber/prefixlen */
228*4882a593Smuzhiyun+    len = strlen(net_tok);
229*4882a593Smuzhiyun+    if (*net_tok != '[' || net_tok[len - 1] != ']')
230*4882a593Smuzhiyun+	return NO;
231*4882a593Smuzhiyun+    ch = net_tok[len - 1];
232*4882a593Smuzhiyun+    net_tok[len - 1] = '\0';
233*4882a593Smuzhiyun+    if (getaddrinfo(net_tok + 1, NULL, &hints, &res) != 0) {
234*4882a593Smuzhiyun+	net_tok[len - 1] = ch;
235*4882a593Smuzhiyun+	return NO;
236*4882a593Smuzhiyun+    }
237*4882a593Smuzhiyun+    memcpy(&net, res->ai_addr, sizeof(net));
238*4882a593Smuzhiyun+    freeaddrinfo(res);
239*4882a593Smuzhiyun+    net_tok[len - 1] = ch;
240*4882a593Smuzhiyun+    if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128)
241*4882a593Smuzhiyun+	return NO;
242*4882a593Smuzhiyun+
243*4882a593Smuzhiyun+#ifdef NI_WITHSCOPEID
244*4882a593Smuzhiyun+    if (net.sin6_scope_id != 0 && addr.sin6_scope_id != net.sin6_scope_id)
245*4882a593Smuzhiyun+	return NO;
246*4882a593Smuzhiyun+#endif
247*4882a593Smuzhiyun+    while (mask_len > 0) {
248*4882a593Smuzhiyun+	if (mask_len < 32) {
249*4882a593Smuzhiyun+	    mask = htonl(~(0xffffffff >> mask_len));
250*4882a593Smuzhiyun+	    if ((*(u_int32_t *)&addr.sin6_addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.sin6_addr.s6_addr[i] & mask))
251*4882a593Smuzhiyun+		return NO;
252*4882a593Smuzhiyun+	    break;
253*4882a593Smuzhiyun+	}
254*4882a593Smuzhiyun+	if (*(u_int32_t *)&addr.sin6_addr.s6_addr[i] != *(u_int32_t *)&net.sin6_addr.s6_addr[i])
255*4882a593Smuzhiyun+	    return NO;
256*4882a593Smuzhiyun+	i += 4;
257*4882a593Smuzhiyun+	mask_len -= 32;
258*4882a593Smuzhiyun+    }
259*4882a593Smuzhiyun+    return YES;
260*4882a593Smuzhiyun+}
261*4882a593Smuzhiyun+#endif /* INET6 */
262*4882a593Smuzhiyun+
263*4882a593Smuzhiyun #ifndef DISABLE_WILDCARD_MATCHING
264*4882a593Smuzhiyun /* Note: this feature has been adapted in a pretty straightforward way
265*4882a593Smuzhiyun    from Tatu Ylonen's last SSH version under free license by
266*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/Makefile tcp_wrappers_7.6/Makefile
267*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/Makefile	1997-03-21 19:27:21.000000000 +0100
268*4882a593Smuzhiyun+++ tcp_wrappers_7.6/Makefile	2004-04-10 19:22:44.000000000 +0200
269*4882a593Smuzhiyun@@ -21,7 +21,7 @@
270*4882a593Smuzhiyun 	@echo "	dynix epix esix freebsd hpux irix4 irix5 irix6 isc iunix"
271*4882a593Smuzhiyun 	@echo "	linux machten mips(untested) ncrsvr4 netbsd next osf power_unix_211"
272*4882a593Smuzhiyun 	@echo "	ptx-2.x ptx-generic pyramid sco sco-nis sco-od2 sco-os5 sinix sunos4"
273*4882a593Smuzhiyun-	@echo "	sunos40 sunos5 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2"
274*4882a593Smuzhiyun+	@echo "	sunos40 sunos5 solaris8 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2"
275*4882a593Smuzhiyun 	@echo "	uts215 uxp"
276*4882a593Smuzhiyun 	@echo
277*4882a593Smuzhiyun 	@echo "If none of these match your environment, edit the system"
278*4882a593Smuzhiyun@@ -131,20 +131,34 @@
279*4882a593Smuzhiyun 	NETGROUP=-DNETGROUP TLI= SYSTYPE="-systype bsd43" all
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun # Freebsd and linux by default have no NIS.
282*4882a593Smuzhiyun-386bsd netbsd bsdos:
283*4882a593Smuzhiyun+386bsd bsdos:
284*4882a593Smuzhiyun 	@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
285*4882a593Smuzhiyun 	LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \
286*4882a593Smuzhiyun 	EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun freebsd:
289*4882a593Smuzhiyun 	@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
290*4882a593Smuzhiyun+	LIBS="-L/usr/local/v6/lib -linet6" \
291*4882a593Smuzhiyun 	LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \
292*4882a593Smuzhiyun-	EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all
293*4882a593Smuzhiyun+	EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DINET6 -Dss_family=__ss_family -Dss_len=__ss_len" \
294*4882a593Smuzhiyun+	VSYSLOG= all
295*4882a593Smuzhiyun+
296*4882a593Smuzhiyun+netbsd:
297*4882a593Smuzhiyun+	@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
298*4882a593Smuzhiyun+	LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \
299*4882a593Smuzhiyun+	EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DINET6 -Dss_family=__ss_family -Dss_len=__ss_len" VSYSLOG= all
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun linux:
302*4882a593Smuzhiyun 	@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
303*4882a593Smuzhiyun-	LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o \
304*4882a593Smuzhiyun-	NETGROUP= TLI= EXTRA_CFLAGS="-DBROKEN_SO_LINGER" all
305*4882a593Smuzhiyun+	LIBS=-lnsl RANLIB=ranlib ARFLAGS=rv AUX_OBJ= \
306*4882a593Smuzhiyun+	NETGROUP="-DNETGROUP" TLI= VSYSLOG= BUGS= \
307*4882a593Smuzhiyun+	EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DHAVE_STRERROR -DINET6=1 -Dss_family=__ss_family -Dss_len=__ss_len" all
308*4882a593Smuzhiyun+
309*4882a593Smuzhiyun+gnu:
310*4882a593Smuzhiyun+	@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
311*4882a593Smuzhiyun+	LIBS=-lnsl RANLIB=ranlib ARFLAGS=rv AUX_OBJ= \
312*4882a593Smuzhiyun+	NETGROUP=-DNETGROUP TLI= VSYSLOG= BUGS= \
313*4882a593Smuzhiyun+	EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DHAVE_STRERROR" all
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun # This is good for many SYSV+BSD hybrids with NIS, probably also for HP-UX 7.x.
316*4882a593Smuzhiyun hpux hpux8 hpux9 hpux10:
317*4882a593Smuzhiyun@@ -196,6 +210,13 @@
318*4882a593Smuzhiyun 	NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \
319*4882a593Smuzhiyun 	BUGS="$(BUGS) -DSOLARIS_24_GETHOSTBYNAME_BUG" all
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun+# SunOS 5.8 is another SYSV4 variant, but has IPv6 support
322*4882a593Smuzhiyun+solaris8:
323*4882a593Smuzhiyun+	@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
324*4882a593Smuzhiyun+	LIBS="-lsocket -lnsl" RANLIB=echo ARFLAGS=rv VSYSLOG= \
325*4882a593Smuzhiyun+	NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \
326*4882a593Smuzhiyun+	EXTRA_CFLAGS="-DINET6 -DNO_CLONE_DEVICE -DINT32_T" all
327*4882a593Smuzhiyun+
328*4882a593Smuzhiyun # Generic SYSV40
329*4882a593Smuzhiyun esix sysv4:
330*4882a593Smuzhiyun 	@make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
331*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/misc.c tcp_wrappers_7.6/misc.c
332*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/misc.c	1996-02-11 17:01:30.000000000 +0100
333*4882a593Smuzhiyun+++ tcp_wrappers_7.6/misc.c	2004-04-10 19:07:43.000000000 +0200
334*4882a593Smuzhiyun@@ -58,9 +58,31 @@
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun     char   *cp;
337*4882a593Smuzhiyun
338*4882a593Smuzhiyun+#ifdef INET6
339*4882a593Smuzhiyun+    int bracket = 0;
340*4882a593Smuzhiyun+
341*4882a593Smuzhiyun+    for (cp = string; cp && *cp; cp++) {
342*4882a593Smuzhiyun+	switch (*cp) {
343*4882a593Smuzhiyun+	case '[':
344*4882a593Smuzhiyun+	    bracket++;
345*4882a593Smuzhiyun+	    break;
346*4882a593Smuzhiyun+	case ']':
347*4882a593Smuzhiyun+	    bracket--;
348*4882a593Smuzhiyun+	    break;
349*4882a593Smuzhiyun+	default:
350*4882a593Smuzhiyun+	    if (bracket == 0 && *cp == delimiter) {
351*4882a593Smuzhiyun+		*cp++ = 0;
352*4882a593Smuzhiyun+		return cp;
353*4882a593Smuzhiyun+	    }
354*4882a593Smuzhiyun+	    break;
355*4882a593Smuzhiyun+	}
356*4882a593Smuzhiyun+    }
357*4882a593Smuzhiyun+    return (NULL);
358*4882a593Smuzhiyun+#else
359*4882a593Smuzhiyun     if ((cp = strchr(string, delimiter)) != 0)
360*4882a593Smuzhiyun 	*cp++ = 0;
361*4882a593Smuzhiyun     return (cp);
362*4882a593Smuzhiyun+#endif
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun
365*4882a593Smuzhiyun /* dot_quad_addr - convert dotted quad to internal form */
366*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/refuse.c tcp_wrappers_7.6/refuse.c
367*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/refuse.c	1994-12-28 17:42:40.000000000 +0100
368*4882a593Smuzhiyun+++ tcp_wrappers_7.6/refuse.c	2004-04-10 19:07:43.000000000 +0200
369*4882a593Smuzhiyun@@ -25,7 +25,12 @@
370*4882a593Smuzhiyun void    refuse(request)
371*4882a593Smuzhiyun struct request_info *request;
372*4882a593Smuzhiyun {
373*4882a593Smuzhiyun+#ifdef INET6
374*4882a593Smuzhiyun+    syslog(deny_severity, "refused connect from %s (%s)",
375*4882a593Smuzhiyun+	   eval_client(request), eval_hostaddr(request->client));
376*4882a593Smuzhiyun+#else
377*4882a593Smuzhiyun     syslog(deny_severity, "refused connect from %s", eval_client(request));
378*4882a593Smuzhiyun+#endif
379*4882a593Smuzhiyun     clean_exit(request);
380*4882a593Smuzhiyun     /* NOTREACHED */
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/rfc931.c tcp_wrappers_7.6/rfc931.c
383*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/rfc931.c	1995-01-02 16:11:34.000000000 +0100
384*4882a593Smuzhiyun+++ tcp_wrappers_7.6/rfc931.c	2004-04-10 19:07:43.000000000 +0200
385*4882a593Smuzhiyun@@ -68,20 +68,50 @@
386*4882a593Smuzhiyun /* rfc931 - return remote user name, given socket structures */
387*4882a593Smuzhiyun
388*4882a593Smuzhiyun void    rfc931(rmt_sin, our_sin, dest)
389*4882a593Smuzhiyun+#ifdef INET6
390*4882a593Smuzhiyun+struct sockaddr *rmt_sin;
391*4882a593Smuzhiyun+struct sockaddr *our_sin;
392*4882a593Smuzhiyun+#else
393*4882a593Smuzhiyun struct sockaddr_in *rmt_sin;
394*4882a593Smuzhiyun struct sockaddr_in *our_sin;
395*4882a593Smuzhiyun+#endif
396*4882a593Smuzhiyun char   *dest;
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun     unsigned rmt_port;
399*4882a593Smuzhiyun     unsigned our_port;
400*4882a593Smuzhiyun+#ifdef INET6
401*4882a593Smuzhiyun+    struct sockaddr_storage rmt_query_sin;
402*4882a593Smuzhiyun+    struct sockaddr_storage our_query_sin;
403*4882a593Smuzhiyun+    int alen;
404*4882a593Smuzhiyun+#else
405*4882a593Smuzhiyun     struct sockaddr_in rmt_query_sin;
406*4882a593Smuzhiyun     struct sockaddr_in our_query_sin;
407*4882a593Smuzhiyun+#endif
408*4882a593Smuzhiyun     char    user[256];			/* XXX */
409*4882a593Smuzhiyun     char    buffer[512];		/* XXX */
410*4882a593Smuzhiyun     char   *cp;
411*4882a593Smuzhiyun     char   *result = unknown;
412*4882a593Smuzhiyun     FILE   *fp;
413*4882a593Smuzhiyun
414*4882a593Smuzhiyun+#ifdef INET6
415*4882a593Smuzhiyun+    /* address family must be the same */
416*4882a593Smuzhiyun+    if (rmt_sin->sa_family != our_sin->sa_family) {
417*4882a593Smuzhiyun+	STRN_CPY(dest, result, STRING_LENGTH);
418*4882a593Smuzhiyun+	return;
419*4882a593Smuzhiyun+    }
420*4882a593Smuzhiyun+    switch (our_sin->sa_family) {
421*4882a593Smuzhiyun+    case AF_INET:
422*4882a593Smuzhiyun+	alen = sizeof(struct sockaddr_in);
423*4882a593Smuzhiyun+	break;
424*4882a593Smuzhiyun+    case AF_INET6:
425*4882a593Smuzhiyun+	alen = sizeof(struct sockaddr_in6);
426*4882a593Smuzhiyun+	break;
427*4882a593Smuzhiyun+    default:
428*4882a593Smuzhiyun+	STRN_CPY(dest, result, STRING_LENGTH);
429*4882a593Smuzhiyun+	return;
430*4882a593Smuzhiyun+    }
431*4882a593Smuzhiyun+#endif
432*4882a593Smuzhiyun+
433*4882a593Smuzhiyun     /*
434*4882a593Smuzhiyun      * Use one unbuffered stdio stream for writing to and for reading from
435*4882a593Smuzhiyun      * the RFC931 etc. server. This is done because of a bug in the SunOS
436*4882a593Smuzhiyun@@ -92,7 +122,11 @@
437*4882a593Smuzhiyun      * sockets.
438*4882a593Smuzhiyun      */
439*4882a593Smuzhiyun
440*4882a593Smuzhiyun+#ifdef INET6
441*4882a593Smuzhiyun+    if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) {
442*4882a593Smuzhiyun+#else
443*4882a593Smuzhiyun     if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
444*4882a593Smuzhiyun+#endif
445*4882a593Smuzhiyun 	setbuf(fp, (char *) 0);
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun 	/*
448*4882a593Smuzhiyun@@ -112,6 +146,25 @@
449*4882a593Smuzhiyun 	     * addresses from the query socket.
450*4882a593Smuzhiyun 	     */
451*4882a593Smuzhiyun
452*4882a593Smuzhiyun+#ifdef INET6
453*4882a593Smuzhiyun+	    memcpy(&our_query_sin, our_sin, alen);
454*4882a593Smuzhiyun+	    memcpy(&rmt_query_sin, rmt_sin, alen);
455*4882a593Smuzhiyun+	    switch (our_sin->sa_family) {
456*4882a593Smuzhiyun+	    case AF_INET:
457*4882a593Smuzhiyun+		((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT);
458*4882a593Smuzhiyun+		((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC931_PORT);
459*4882a593Smuzhiyun+		break;
460*4882a593Smuzhiyun+	    case AF_INET6:
461*4882a593Smuzhiyun+		((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT);
462*4882a593Smuzhiyun+		((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC931_PORT);
463*4882a593Smuzhiyun+		break;
464*4882a593Smuzhiyun+	    }
465*4882a593Smuzhiyun+
466*4882a593Smuzhiyun+	    if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
467*4882a593Smuzhiyun+		     alen) >= 0 &&
468*4882a593Smuzhiyun+		connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
469*4882a593Smuzhiyun+			alen) >= 0) {
470*4882a593Smuzhiyun+#else
471*4882a593Smuzhiyun 	    our_query_sin = *our_sin;
472*4882a593Smuzhiyun 	    our_query_sin.sin_port = htons(ANY_PORT);
473*4882a593Smuzhiyun 	    rmt_query_sin = *rmt_sin;
474*4882a593Smuzhiyun@@ -121,6 +174,7 @@
475*4882a593Smuzhiyun 		     sizeof(our_query_sin)) >= 0 &&
476*4882a593Smuzhiyun 		connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
477*4882a593Smuzhiyun 			sizeof(rmt_query_sin)) >= 0) {
478*4882a593Smuzhiyun+#endif
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun 		/*
481*4882a593Smuzhiyun 		 * Send query to server. Neglect the risk that a 13-byte
482*4882a593Smuzhiyun@@ -129,8 +183,13 @@
483*4882a593Smuzhiyun 		 */
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun 		fprintf(fp, "%u,%u\r\n",
486*4882a593Smuzhiyun+#ifdef INET6
487*4882a593Smuzhiyun+			ntohs(((struct sockaddr_in *)rmt_sin)->sin_port),
488*4882a593Smuzhiyun+			ntohs(((struct sockaddr_in *)our_sin)->sin_port));
489*4882a593Smuzhiyun+#else
490*4882a593Smuzhiyun 			ntohs(rmt_sin->sin_port),
491*4882a593Smuzhiyun 			ntohs(our_sin->sin_port));
492*4882a593Smuzhiyun+#endif
493*4882a593Smuzhiyun 		fflush(fp);
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun 		/*
496*4882a593Smuzhiyun@@ -144,8 +203,13 @@
497*4882a593Smuzhiyun 		    && ferror(fp) == 0 && feof(fp) == 0
498*4882a593Smuzhiyun 		    && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
499*4882a593Smuzhiyun 			      &rmt_port, &our_port, user) == 3
500*4882a593Smuzhiyun+#ifdef INET6
501*4882a593Smuzhiyun+		    && ntohs(((struct sockaddr_in *)rmt_sin)->sin_port) == rmt_port
502*4882a593Smuzhiyun+		    && ntohs(((struct sockaddr_in *)our_sin)->sin_port) == our_port) {
503*4882a593Smuzhiyun+#else
504*4882a593Smuzhiyun 		    && ntohs(rmt_sin->sin_port) == rmt_port
505*4882a593Smuzhiyun 		    && ntohs(our_sin->sin_port) == our_port) {
506*4882a593Smuzhiyun+#endif
507*4882a593Smuzhiyun
508*4882a593Smuzhiyun 		    /*
509*4882a593Smuzhiyun 		     * Strip trailing carriage return. It is part of the
510*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/scaffold.c tcp_wrappers_7.6/scaffold.c
511*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/scaffold.c	1997-03-21 19:27:24.000000000 +0100
512*4882a593Smuzhiyun+++ tcp_wrappers_7.6/scaffold.c	2004-04-10 19:07:43.000000000 +0200
513*4882a593Smuzhiyun@@ -25,7 +25,9 @@
514*4882a593Smuzhiyun #define	INADDR_NONE	(-1)		/* XXX should be 0xffffffff */
515*4882a593Smuzhiyun #endif
516*4882a593Smuzhiyun
517*4882a593Smuzhiyun+#ifndef INET6
518*4882a593Smuzhiyun extern char *malloc();
519*4882a593Smuzhiyun+#endif
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun /* Application-specific. */
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun@@ -39,6 +41,7 @@
524*4882a593Smuzhiyun int     deny_severity = LOG_WARNING;
525*4882a593Smuzhiyun int     rfc931_timeout = RFC931_TIMEOUT;
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun+#ifndef INET6
528*4882a593Smuzhiyun /* dup_hostent - create hostent in one memory block */
529*4882a593Smuzhiyun
530*4882a593Smuzhiyun static struct hostent *dup_hostent(hp)
531*4882a593Smuzhiyun@@ -73,9 +76,46 @@
532*4882a593Smuzhiyun     }
533*4882a593Smuzhiyun     return (&hb->host);
534*4882a593Smuzhiyun }
535*4882a593Smuzhiyun+#endif
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun /* find_inet_addr - find all addresses for this host, result to free() */
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun+#ifdef INET6
540*4882a593Smuzhiyun+struct addrinfo *find_inet_addr(host)
541*4882a593Smuzhiyun+char   *host;
542*4882a593Smuzhiyun+{
543*4882a593Smuzhiyun+    struct addrinfo hints, *res;
544*4882a593Smuzhiyun+
545*4882a593Smuzhiyun+    memset(&hints, 0, sizeof(hints));
546*4882a593Smuzhiyun+    hints.ai_family = PF_UNSPEC;
547*4882a593Smuzhiyun+    hints.ai_socktype = SOCK_STREAM;
548*4882a593Smuzhiyun+    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
549*4882a593Smuzhiyun+    if (getaddrinfo(host, NULL, &hints, &res) == 0)
550*4882a593Smuzhiyun+	return (res);
551*4882a593Smuzhiyun+
552*4882a593Smuzhiyun+    memset(&hints, 0, sizeof(hints));
553*4882a593Smuzhiyun+    hints.ai_family = PF_UNSPEC;
554*4882a593Smuzhiyun+    hints.ai_socktype = SOCK_STREAM;
555*4882a593Smuzhiyun+    hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
556*4882a593Smuzhiyun+    if (getaddrinfo(host, NULL, &hints, &res) != 0) {
557*4882a593Smuzhiyun+	tcpd_warn("%s: host not found", host);
558*4882a593Smuzhiyun+	return (0);
559*4882a593Smuzhiyun+    }
560*4882a593Smuzhiyun+    if (res->ai_family != AF_INET6 && res->ai_family != AF_INET) {
561*4882a593Smuzhiyun+	tcpd_warn("%d: not an internet host", res->ai_family);
562*4882a593Smuzhiyun+	freeaddrinfo(res);
563*4882a593Smuzhiyun+	return (0);
564*4882a593Smuzhiyun+    }
565*4882a593Smuzhiyun+    if (!res->ai_canonname) {
566*4882a593Smuzhiyun+	tcpd_warn("%s: hostname alias", host);
567*4882a593Smuzhiyun+	tcpd_warn("(cannot obtain official name)", res->ai_canonname);
568*4882a593Smuzhiyun+    } else if (STR_NE(host, res->ai_canonname)) {
569*4882a593Smuzhiyun+	tcpd_warn("%s: hostname alias", host);
570*4882a593Smuzhiyun+	tcpd_warn("(official name: %.*s)", STRING_LENGTH, res->ai_canonname);
571*4882a593Smuzhiyun+    }
572*4882a593Smuzhiyun+    return (res);
573*4882a593Smuzhiyun+}
574*4882a593Smuzhiyun+#else
575*4882a593Smuzhiyun struct hostent *find_inet_addr(host)
576*4882a593Smuzhiyun char   *host;
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun@@ -118,6 +158,7 @@
579*4882a593Smuzhiyun     }
580*4882a593Smuzhiyun     return (dup_hostent(hp));
581*4882a593Smuzhiyun }
582*4882a593Smuzhiyun+#endif
583*4882a593Smuzhiyun
584*4882a593Smuzhiyun /* check_dns - give each address thorough workout, return address count */
585*4882a593Smuzhiyun
586*4882a593Smuzhiyun@@ -125,8 +166,13 @@
587*4882a593Smuzhiyun char   *host;
588*4882a593Smuzhiyun {
589*4882a593Smuzhiyun     struct request_info request;
590*4882a593Smuzhiyun+#ifdef INET6
591*4882a593Smuzhiyun+    struct sockaddr_storage sin;
592*4882a593Smuzhiyun+    struct addrinfo *hp, *res;
593*4882a593Smuzhiyun+#else
594*4882a593Smuzhiyun     struct sockaddr_in sin;
595*4882a593Smuzhiyun     struct hostent *hp;
596*4882a593Smuzhiyun+#endif
597*4882a593Smuzhiyun     int     count;
598*4882a593Smuzhiyun     char   *addr;
599*4882a593Smuzhiyun
600*4882a593Smuzhiyun@@ -134,11 +180,18 @@
601*4882a593Smuzhiyun 	return (0);
602*4882a593Smuzhiyun     request_init(&request, RQ_CLIENT_SIN, &sin, 0);
603*4882a593Smuzhiyun     sock_methods(&request);
604*4882a593Smuzhiyun+#ifndef INET6
605*4882a593Smuzhiyun     memset((char *) &sin, 0, sizeof(sin));
606*4882a593Smuzhiyun     sin.sin_family = AF_INET;
607*4882a593Smuzhiyun+#endif
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun+#ifdef INET6
610*4882a593Smuzhiyun+    for (res = hp, count = 0; res; res = res->ai_next, count++) {
611*4882a593Smuzhiyun+	memcpy(&sin, res->ai_addr, res->ai_addrlen);
612*4882a593Smuzhiyun+#else
613*4882a593Smuzhiyun     for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
614*4882a593Smuzhiyun 	memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr));
615*4882a593Smuzhiyun+#endif
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun 	/*
618*4882a593Smuzhiyun 	 * Force host name and address conversions. Use the request structure
619*4882a593Smuzhiyun@@ -151,7 +204,11 @@
620*4882a593Smuzhiyun 	    tcpd_warn("host address %s->name lookup failed",
621*4882a593Smuzhiyun 		      eval_hostaddr(request.client));
622*4882a593Smuzhiyun     }
623*4882a593Smuzhiyun+#ifdef INET6
624*4882a593Smuzhiyun+    freeaddrinfo(hp);
625*4882a593Smuzhiyun+#else
626*4882a593Smuzhiyun     free((char *) hp);
627*4882a593Smuzhiyun+#endif
628*4882a593Smuzhiyun     return (count);
629*4882a593Smuzhiyun }
630*4882a593Smuzhiyun
631*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/scaffold.h tcp_wrappers_7.6/scaffold.h
632*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/scaffold.h	1994-12-31 18:19:20.000000000 +0100
633*4882a593Smuzhiyun+++ tcp_wrappers_7.6/scaffold.h	2004-04-10 19:07:43.000000000 +0200
634*4882a593Smuzhiyun@@ -4,6 +4,10 @@
635*4882a593Smuzhiyun   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
636*4882a593Smuzhiyun   */
637*4882a593Smuzhiyun
638*4882a593Smuzhiyun+#ifdef INET6
639*4882a593Smuzhiyun+extern struct addrinfo *find_inet_addr();
640*4882a593Smuzhiyun+#else
641*4882a593Smuzhiyun extern struct hostent *find_inet_addr();
642*4882a593Smuzhiyun+#endif
643*4882a593Smuzhiyun extern int check_dns();
644*4882a593Smuzhiyun extern int check_path();
645*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/socket.c tcp_wrappers_7.6/socket.c
646*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/socket.c	2004-04-10 19:22:58.000000000 +0200
647*4882a593Smuzhiyun+++ tcp_wrappers_7.6/socket.c	2004-04-10 19:07:43.000000000 +0200
648*4882a593Smuzhiyun@@ -24,13 +24,22 @@
649*4882a593Smuzhiyun #include <sys/types.h>
650*4882a593Smuzhiyun #include <sys/param.h>
651*4882a593Smuzhiyun #include <sys/socket.h>
652*4882a593Smuzhiyun+#ifdef INT32_T
653*4882a593Smuzhiyun+typedef uint32_t u_int32_t;
654*4882a593Smuzhiyun+#endif
655*4882a593Smuzhiyun #include <netinet/in.h>
656*4882a593Smuzhiyun #include <netdb.h>
657*4882a593Smuzhiyun #include <stdio.h>
658*4882a593Smuzhiyun #include <syslog.h>
659*4882a593Smuzhiyun #include <string.h>
660*4882a593Smuzhiyun
661*4882a593Smuzhiyun+#ifdef INET6
662*4882a593Smuzhiyun+#ifndef NI_WITHSCOPEID
663*4882a593Smuzhiyun+#define NI_WITHSCOPEID	0
664*4882a593Smuzhiyun+#endif
665*4882a593Smuzhiyun+#else
666*4882a593Smuzhiyun extern char *inet_ntoa();
667*4882a593Smuzhiyun+#endif
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun /* Local stuff. */
670*4882a593Smuzhiyun
671*4882a593Smuzhiyun@@ -79,8 +88,13 @@
672*4882a593Smuzhiyun void    sock_host(request)
673*4882a593Smuzhiyun struct request_info *request;
674*4882a593Smuzhiyun {
675*4882a593Smuzhiyun+#ifdef INET6
676*4882a593Smuzhiyun+    static struct sockaddr_storage client;
677*4882a593Smuzhiyun+    static struct sockaddr_storage server;
678*4882a593Smuzhiyun+#else
679*4882a593Smuzhiyun     static struct sockaddr_in client;
680*4882a593Smuzhiyun     static struct sockaddr_in server;
681*4882a593Smuzhiyun+#endif
682*4882a593Smuzhiyun     int     len;
683*4882a593Smuzhiyun     char    buf[BUFSIZ];
684*4882a593Smuzhiyun     int     fd = request->fd;
685*4882a593Smuzhiyun@@ -109,7 +123,11 @@
686*4882a593Smuzhiyun 	memset(buf, 0 sizeof(buf));
687*4882a593Smuzhiyun #endif
688*4882a593Smuzhiyun     }
689*4882a593Smuzhiyun+#ifdef INET6
690*4882a593Smuzhiyun+    request->client->sin = (struct sockaddr *)&client;
691*4882a593Smuzhiyun+#else
692*4882a593Smuzhiyun     request->client->sin = &client;
693*4882a593Smuzhiyun+#endif
694*4882a593Smuzhiyun
695*4882a593Smuzhiyun     /*
696*4882a593Smuzhiyun      * Determine the server binding. This is used for client username
697*4882a593Smuzhiyun@@ -122,7 +140,11 @@
698*4882a593Smuzhiyun 	tcpd_warn("getsockname: %m");
699*4882a593Smuzhiyun 	return;
700*4882a593Smuzhiyun     }
701*4882a593Smuzhiyun+#ifdef INET6
702*4882a593Smuzhiyun+    request->server->sin = (struct sockaddr *)&server;
703*4882a593Smuzhiyun+#else
704*4882a593Smuzhiyun     request->server->sin = &server;
705*4882a593Smuzhiyun+#endif
706*4882a593Smuzhiyun }
707*4882a593Smuzhiyun
708*4882a593Smuzhiyun /* sock_hostaddr - map endpoint address to printable form */
709*4882a593Smuzhiyun@@ -130,10 +152,26 @@
710*4882a593Smuzhiyun void    sock_hostaddr(host)
711*4882a593Smuzhiyun struct host_info *host;
712*4882a593Smuzhiyun {
713*4882a593Smuzhiyun+#ifdef INET6
714*4882a593Smuzhiyun+    struct sockaddr *sin = host->sin;
715*4882a593Smuzhiyun+    int salen;
716*4882a593Smuzhiyun+
717*4882a593Smuzhiyun+    if (!sin)
718*4882a593Smuzhiyun+	return;
719*4882a593Smuzhiyun+#ifdef SIN6_LEN
720*4882a593Smuzhiyun+    salen = sin->sa_len;
721*4882a593Smuzhiyun+#else
722*4882a593Smuzhiyun+    salen = (sin->sa_family == AF_INET) ? sizeof(struct sockaddr_in)
723*4882a593Smuzhiyun+					: sizeof(struct sockaddr_in6);
724*4882a593Smuzhiyun+#endif
725*4882a593Smuzhiyun+    getnameinfo(sin, salen, host->addr, sizeof(host->addr),
726*4882a593Smuzhiyun+		NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
727*4882a593Smuzhiyun+#else
728*4882a593Smuzhiyun     struct sockaddr_in *sin = host->sin;
729*4882a593Smuzhiyun
730*4882a593Smuzhiyun     if (sin != 0)
731*4882a593Smuzhiyun 	STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
732*4882a593Smuzhiyun+#endif
733*4882a593Smuzhiyun }
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun /* sock_hostname - map endpoint address to host name */
736*4882a593Smuzhiyun@@ -141,6 +179,160 @@
737*4882a593Smuzhiyun void    sock_hostname(host)
738*4882a593Smuzhiyun struct host_info *host;
739*4882a593Smuzhiyun {
740*4882a593Smuzhiyun+#ifdef INET6
741*4882a593Smuzhiyun+    struct sockaddr *sin = host->sin;
742*4882a593Smuzhiyun+    struct sockaddr_in sin4;
743*4882a593Smuzhiyun+    struct addrinfo hints, *res, *res0 = NULL;
744*4882a593Smuzhiyun+    int salen, alen, err = 1;
745*4882a593Smuzhiyun+    char *ap = NULL, *rap, hname[NI_MAXHOST];
746*4882a593Smuzhiyun+
747*4882a593Smuzhiyun+    if (sin != NULL) {
748*4882a593Smuzhiyun+	if (sin->sa_family == AF_INET6) {
749*4882a593Smuzhiyun+	    struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sin;
750*4882a593Smuzhiyun+
751*4882a593Smuzhiyun+	    if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
752*4882a593Smuzhiyun+		memset(&sin4, 0, sizeof(sin4));
753*4882a593Smuzhiyun+#ifdef SIN6_LEN
754*4882a593Smuzhiyun+		sin4.sin_len = sizeof(sin4);
755*4882a593Smuzhiyun+#endif
756*4882a593Smuzhiyun+		sin4.sin_family = AF_INET;
757*4882a593Smuzhiyun+		sin4.sin_port = sin6->sin6_port;
758*4882a593Smuzhiyun+		sin4.sin_addr.s_addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12];
759*4882a593Smuzhiyun+		sin = (struct sockaddr *)&sin4;
760*4882a593Smuzhiyun+	    }
761*4882a593Smuzhiyun+	}
762*4882a593Smuzhiyun+	switch (sin->sa_family) {
763*4882a593Smuzhiyun+	case AF_INET:
764*4882a593Smuzhiyun+	    ap = (char *)&((struct sockaddr_in *)sin)->sin_addr;
765*4882a593Smuzhiyun+	    alen = sizeof(struct in_addr);
766*4882a593Smuzhiyun+	    salen = sizeof(struct sockaddr_in);
767*4882a593Smuzhiyun+	    break;
768*4882a593Smuzhiyun+	case AF_INET6:
769*4882a593Smuzhiyun+	    ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr;
770*4882a593Smuzhiyun+	    alen = sizeof(struct in6_addr);
771*4882a593Smuzhiyun+	    salen = sizeof(struct sockaddr_in6);
772*4882a593Smuzhiyun+	    break;
773*4882a593Smuzhiyun+	default:
774*4882a593Smuzhiyun+	    break;
775*4882a593Smuzhiyun+	}
776*4882a593Smuzhiyun+	if (ap)
777*4882a593Smuzhiyun+	    err = getnameinfo(sin, salen, hname, sizeof(hname),
778*4882a593Smuzhiyun+			      NULL, 0, NI_WITHSCOPEID | NI_NAMEREQD);
779*4882a593Smuzhiyun+    }
780*4882a593Smuzhiyun+    if (!err) {
781*4882a593Smuzhiyun+
782*4882a593Smuzhiyun+	STRN_CPY(host->name, hname, sizeof(host->name));
783*4882a593Smuzhiyun+
784*4882a593Smuzhiyun+	/* reject numeric addresses */
785*4882a593Smuzhiyun+	memset(&hints, 0, sizeof(hints));
786*4882a593Smuzhiyun+	hints.ai_family = sin->sa_family;
787*4882a593Smuzhiyun+	hints.ai_socktype = SOCK_STREAM;
788*4882a593Smuzhiyun+	hints.ai_flags = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST;
789*4882a593Smuzhiyun+	if ((err = getaddrinfo(host->name, NULL, &hints, &res0) == 0)) {
790*4882a593Smuzhiyun+	    freeaddrinfo(res0);
791*4882a593Smuzhiyun+	    res0 = NULL;
792*4882a593Smuzhiyun+	    tcpd_warn("host name/name mismatch: "
793*4882a593Smuzhiyun+		      "reverse lookup results in non-FQDN %s",
794*4882a593Smuzhiyun+		      host->name);
795*4882a593Smuzhiyun+	    strcpy(host->name, paranoid);	/* name is bad, clobber it */
796*4882a593Smuzhiyun+	}
797*4882a593Smuzhiyun+	err = !err;
798*4882a593Smuzhiyun+    }
799*4882a593Smuzhiyun+    if (!err) {
800*4882a593Smuzhiyun+	/* we are now sure that this is non-numeric */
801*4882a593Smuzhiyun+
802*4882a593Smuzhiyun+	/*
803*4882a593Smuzhiyun+	 * Verify that the address is a member of the address list returned
804*4882a593Smuzhiyun+	 * by gethostbyname(hostname).
805*4882a593Smuzhiyun+	 *
806*4882a593Smuzhiyun+	 * Verify also that gethostbyaddr() and gethostbyname() return the same
807*4882a593Smuzhiyun+	 * hostname, or rshd and rlogind may still end up being spoofed.
808*4882a593Smuzhiyun+	 *
809*4882a593Smuzhiyun+	 * On some sites, gethostbyname("localhost") returns "localhost.domain".
810*4882a593Smuzhiyun+	 * This is a DNS artefact. We treat it as a special case. When we
811*4882a593Smuzhiyun+	 * can't believe the address list from gethostbyname("localhost")
812*4882a593Smuzhiyun+	 * we're in big trouble anyway.
813*4882a593Smuzhiyun+	 */
814*4882a593Smuzhiyun+
815*4882a593Smuzhiyun+	memset(&hints, 0, sizeof(hints));
816*4882a593Smuzhiyun+	hints.ai_family = sin->sa_family;
817*4882a593Smuzhiyun+	hints.ai_socktype = SOCK_STREAM;
818*4882a593Smuzhiyun+	hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
819*4882a593Smuzhiyun+	if (getaddrinfo(host->name, NULL, &hints, &res0) != 0) {
820*4882a593Smuzhiyun+
821*4882a593Smuzhiyun+	    /*
822*4882a593Smuzhiyun+	     * Unable to verify that the host name matches the address. This
823*4882a593Smuzhiyun+	     * may be a transient problem or a botched name server setup.
824*4882a593Smuzhiyun+	     */
825*4882a593Smuzhiyun+
826*4882a593Smuzhiyun+	    tcpd_warn("can't verify hostname: getaddrinfo(%s, %s) failed",
827*4882a593Smuzhiyun+		      host->name,
828*4882a593Smuzhiyun+		      (sin->sa_family == AF_INET) ? "AF_INET" : "AF_INET6");
829*4882a593Smuzhiyun+
830*4882a593Smuzhiyun+	} else if ((res0->ai_canonname == NULL
831*4882a593Smuzhiyun+		    || STR_NE(host->name, res0->ai_canonname))
832*4882a593Smuzhiyun+		   && STR_NE(host->name, "localhost")) {
833*4882a593Smuzhiyun+
834*4882a593Smuzhiyun+	    /*
835*4882a593Smuzhiyun+	     * The gethostbyaddr() and gethostbyname() calls did not return
836*4882a593Smuzhiyun+	     * the same hostname. This could be a nameserver configuration
837*4882a593Smuzhiyun+	     * problem. It could also be that someone is trying to spoof us.
838*4882a593Smuzhiyun+	     */
839*4882a593Smuzhiyun+
840*4882a593Smuzhiyun+	    tcpd_warn("host name/name mismatch: %s != %.*s",
841*4882a593Smuzhiyun+		      host->name, STRING_LENGTH,
842*4882a593Smuzhiyun+		      (res0->ai_canonname == NULL) ? "" : res0->ai_canonname);
843*4882a593Smuzhiyun+
844*4882a593Smuzhiyun+	} else {
845*4882a593Smuzhiyun+
846*4882a593Smuzhiyun+	    /*
847*4882a593Smuzhiyun+	     * The address should be a member of the address list returned by
848*4882a593Smuzhiyun+	     * gethostbyname(). We should first verify that the h_addrtype
849*4882a593Smuzhiyun+	     * field is AF_INET, but this program has already caused too much
850*4882a593Smuzhiyun+	     * grief on systems with broken library code.
851*4882a593Smuzhiyun+	     */
852*4882a593Smuzhiyun+
853*4882a593Smuzhiyun+	    for (res = res0; res; res = res->ai_next) {
854*4882a593Smuzhiyun+		if (res->ai_family != sin->sa_family)
855*4882a593Smuzhiyun+		    continue;
856*4882a593Smuzhiyun+		switch (res->ai_family) {
857*4882a593Smuzhiyun+		case AF_INET:
858*4882a593Smuzhiyun+		    rap = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr;
859*4882a593Smuzhiyun+		    break;
860*4882a593Smuzhiyun+		case AF_INET6:
861*4882a593Smuzhiyun+		    /* need to check scope_id */
862*4882a593Smuzhiyun+		    if (((struct sockaddr_in6 *)sin)->sin6_scope_id !=
863*4882a593Smuzhiyun+		        ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id) {
864*4882a593Smuzhiyun+			continue;
865*4882a593Smuzhiyun+		    }
866*4882a593Smuzhiyun+		    rap = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
867*4882a593Smuzhiyun+		    break;
868*4882a593Smuzhiyun+		default:
869*4882a593Smuzhiyun+		    continue;
870*4882a593Smuzhiyun+		}
871*4882a593Smuzhiyun+		if (memcmp(rap, ap, alen) == 0) {
872*4882a593Smuzhiyun+		    freeaddrinfo(res0);
873*4882a593Smuzhiyun+		    return;			/* name is good, keep it */
874*4882a593Smuzhiyun+		}
875*4882a593Smuzhiyun+	    }
876*4882a593Smuzhiyun+
877*4882a593Smuzhiyun+	    /*
878*4882a593Smuzhiyun+	     * The host name does not map to the initial address. Perhaps
879*4882a593Smuzhiyun+	     * someone has messed up. Perhaps someone compromised a name
880*4882a593Smuzhiyun+	     * server.
881*4882a593Smuzhiyun+	     */
882*4882a593Smuzhiyun+
883*4882a593Smuzhiyun+	    getnameinfo(sin, salen, hname, sizeof(hname),
884*4882a593Smuzhiyun+			NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
885*4882a593Smuzhiyun+	    tcpd_warn("host name/address mismatch: %s != %.*s",
886*4882a593Smuzhiyun+		      hname, STRING_LENGTH,
887*4882a593Smuzhiyun+		      (res0->ai_canonname == NULL) ? "" : res0->ai_canonname);
888*4882a593Smuzhiyun+	}
889*4882a593Smuzhiyun+	strcpy(host->name, paranoid);		/* name is bad, clobber it */
890*4882a593Smuzhiyun+	if (res0)
891*4882a593Smuzhiyun+	    freeaddrinfo(res0);
892*4882a593Smuzhiyun+    }
893*4882a593Smuzhiyun+#else /* INET6 */
894*4882a593Smuzhiyun     struct sockaddr_in *sin = host->sin;
895*4882a593Smuzhiyun     struct hostent *hp;
896*4882a593Smuzhiyun     int     i;
897*4882a593Smuzhiyun@@ -220,6 +412,7 @@
898*4882a593Smuzhiyun 	}
899*4882a593Smuzhiyun 	strcpy(host->name, paranoid);		/* name is bad, clobber it */
900*4882a593Smuzhiyun     }
901*4882a593Smuzhiyun+#endif /* INET6 */
902*4882a593Smuzhiyun }
903*4882a593Smuzhiyun
904*4882a593Smuzhiyun /* sock_sink - absorb unreceived IP datagram */
905*4882a593Smuzhiyun@@ -228,7 +421,11 @@
906*4882a593Smuzhiyun int     fd;
907*4882a593Smuzhiyun {
908*4882a593Smuzhiyun     char    buf[BUFSIZ];
909*4882a593Smuzhiyun+#ifdef INET6
910*4882a593Smuzhiyun+    struct sockaddr_storage sin;
911*4882a593Smuzhiyun+#else
912*4882a593Smuzhiyun     struct sockaddr_in sin;
913*4882a593Smuzhiyun+#endif
914*4882a593Smuzhiyun     int     size = sizeof(sin);
915*4882a593Smuzhiyun
916*4882a593Smuzhiyun     /*
917*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/tcpd.c tcp_wrappers_7.6/tcpd.c
918*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/tcpd.c	1996-02-11 17:01:33.000000000 +0100
919*4882a593Smuzhiyun+++ tcp_wrappers_7.6/tcpd.c	2004-04-10 19:07:43.000000000 +0200
920*4882a593Smuzhiyun@@ -120,7 +120,12 @@
921*4882a593Smuzhiyun
922*4882a593Smuzhiyun     /* Report request and invoke the real daemon program. */
923*4882a593Smuzhiyun
924*4882a593Smuzhiyun+#ifdef INET6
925*4882a593Smuzhiyun+    syslog(allow_severity, "connect from %s (%s)",
926*4882a593Smuzhiyun+	   eval_client(&request), eval_hostaddr(request.client));
927*4882a593Smuzhiyun+#else
928*4882a593Smuzhiyun     syslog(allow_severity, "connect from %s", eval_client(&request));
929*4882a593Smuzhiyun+#endif
930*4882a593Smuzhiyun     closelog();
931*4882a593Smuzhiyun     (void) execv(path, argv);
932*4882a593Smuzhiyun     syslog(LOG_ERR, "error: cannot execute %s: %m", path);
933*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/tcpdchk.c tcp_wrappers_7.6/tcpdchk.c
934*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/tcpdchk.c	1997-02-12 02:13:25.000000000 +0100
935*4882a593Smuzhiyun+++ tcp_wrappers_7.6/tcpdchk.c	2004-04-10 19:07:43.000000000 +0200
936*4882a593Smuzhiyun@@ -22,6 +22,9 @@
937*4882a593Smuzhiyun
938*4882a593Smuzhiyun #include <sys/types.h>
939*4882a593Smuzhiyun #include <sys/stat.h>
940*4882a593Smuzhiyun+#ifdef INET6
941*4882a593Smuzhiyun+#include <sys/socket.h>
942*4882a593Smuzhiyun+#endif
943*4882a593Smuzhiyun #include <netinet/in.h>
944*4882a593Smuzhiyun #include <arpa/inet.h>
945*4882a593Smuzhiyun #include <stdio.h>
946*4882a593Smuzhiyun@@ -397,6 +400,31 @@
947*4882a593Smuzhiyun     }
948*4882a593Smuzhiyun }
949*4882a593Smuzhiyun
950*4882a593Smuzhiyun+#ifdef INET6
951*4882a593Smuzhiyun+static int is_inet6_addr(pat)
952*4882a593Smuzhiyun+    char *pat;
953*4882a593Smuzhiyun+{
954*4882a593Smuzhiyun+    struct addrinfo hints, *res;
955*4882a593Smuzhiyun+    int len, ret;
956*4882a593Smuzhiyun+    char ch;
957*4882a593Smuzhiyun+
958*4882a593Smuzhiyun+    if (*pat != '[')
959*4882a593Smuzhiyun+	return (0);
960*4882a593Smuzhiyun+    len = strlen(pat);
961*4882a593Smuzhiyun+    if ((ch = pat[len - 1]) != ']')
962*4882a593Smuzhiyun+	return (0);
963*4882a593Smuzhiyun+    pat[len - 1] = '\0';
964*4882a593Smuzhiyun+    memset(&hints, 0, sizeof(hints));
965*4882a593Smuzhiyun+    hints.ai_family = AF_INET6;
966*4882a593Smuzhiyun+    hints.ai_socktype = SOCK_STREAM;
967*4882a593Smuzhiyun+    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
968*4882a593Smuzhiyun+    if ((ret = getaddrinfo(pat + 1, NULL, &hints, &res)) == 0)
969*4882a593Smuzhiyun+	freeaddrinfo(res);
970*4882a593Smuzhiyun+    pat[len - 1] = ch;
971*4882a593Smuzhiyun+    return (ret == 0);
972*4882a593Smuzhiyun+}
973*4882a593Smuzhiyun+#endif
974*4882a593Smuzhiyun+
975*4882a593Smuzhiyun /* check_host - criticize host pattern */
976*4882a593Smuzhiyun
977*4882a593Smuzhiyun static int check_host(pat)
978*4882a593Smuzhiyun@@ -423,14 +451,27 @@
979*4882a593Smuzhiyun #endif
980*4882a593Smuzhiyun #endif
981*4882a593Smuzhiyun     } else if (mask = split_at(pat, '/')) {	/* network/netmask */
982*4882a593Smuzhiyun+#ifdef INET6
983*4882a593Smuzhiyun+	int mask_len;
984*4882a593Smuzhiyun+
985*4882a593Smuzhiyun+	if ((dot_quad_addr(pat) == INADDR_NONE
986*4882a593Smuzhiyun+	    || dot_quad_addr(mask) == INADDR_NONE)
987*4882a593Smuzhiyun+	    && (!is_inet6_addr(pat)
988*4882a593Smuzhiyun+		|| ((mask_len = atoi(mask)) < 0 || mask_len > 128)))
989*4882a593Smuzhiyun+#else
990*4882a593Smuzhiyun 	if (dot_quad_addr(pat) == INADDR_NONE
991*4882a593Smuzhiyun 	    || dot_quad_addr(mask) == INADDR_NONE)
992*4882a593Smuzhiyun+#endif
993*4882a593Smuzhiyun 	    tcpd_warn("%s/%s: bad net/mask pattern", pat, mask);
994*4882a593Smuzhiyun     } else if (STR_EQ(pat, "FAIL")) {		/* obsolete */
995*4882a593Smuzhiyun 	tcpd_warn("FAIL is no longer recognized");
996*4882a593Smuzhiyun 	tcpd_warn("(use EXCEPT or DENY instead)");
997*4882a593Smuzhiyun     } else if (reserved_name(pat)) {		/* other reserved */
998*4882a593Smuzhiyun 	 /* void */ ;
999*4882a593Smuzhiyun+#ifdef INET6
1000*4882a593Smuzhiyun+    } else if (is_inet6_addr(pat)) { /* IPv6 address */
1001*4882a593Smuzhiyun+	addr_count = 1;
1002*4882a593Smuzhiyun+#endif
1003*4882a593Smuzhiyun     } else if (NOT_INADDR(pat)) {		/* internet name */
1004*4882a593Smuzhiyun 	if (pat[strlen(pat) - 1] == '.') {
1005*4882a593Smuzhiyun 	    tcpd_warn("%s: domain or host name ends in dot", pat);
1006*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/tcpd.h tcp_wrappers_7.6/tcpd.h
1007*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/tcpd.h	1996-03-19 16:22:25.000000000 +0100
1008*4882a593Smuzhiyun+++ tcp_wrappers_7.6/tcpd.h	2004-04-10 19:07:43.000000000 +0200
1009*4882a593Smuzhiyun@@ -11,7 +11,11 @@
1010*4882a593Smuzhiyun struct host_info {
1011*4882a593Smuzhiyun     char    name[STRING_LENGTH];	/* access via eval_hostname(host) */
1012*4882a593Smuzhiyun     char    addr[STRING_LENGTH];	/* access via eval_hostaddr(host) */
1013*4882a593Smuzhiyun+#ifdef INET6
1014*4882a593Smuzhiyun+    struct sockaddr *sin;		/* socket address or 0 */
1015*4882a593Smuzhiyun+#else
1016*4882a593Smuzhiyun     struct sockaddr_in *sin;		/* socket address or 0 */
1017*4882a593Smuzhiyun+#endif
1018*4882a593Smuzhiyun     struct t_unitdata *unit;		/* TLI transport address or 0 */
1019*4882a593Smuzhiyun     struct request_info *request;	/* for shared information */
1020*4882a593Smuzhiyun };
1021*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/tcpdmatch.c tcp_wrappers_7.6/tcpdmatch.c
1022*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/tcpdmatch.c	1996-02-11 17:01:36.000000000 +0100
1023*4882a593Smuzhiyun+++ tcp_wrappers_7.6/tcpdmatch.c	2004-04-10 19:07:43.000000000 +0200
1024*4882a593Smuzhiyun@@ -57,7 +57,11 @@
1025*4882a593Smuzhiyun int     argc;
1026*4882a593Smuzhiyun char  **argv;
1027*4882a593Smuzhiyun {
1028*4882a593Smuzhiyun+#ifdef INET6
1029*4882a593Smuzhiyun+    struct addrinfo hints, *hp, *res;
1030*4882a593Smuzhiyun+#else
1031*4882a593Smuzhiyun     struct hostent *hp;
1032*4882a593Smuzhiyun+#endif
1033*4882a593Smuzhiyun     char   *myname = argv[0];
1034*4882a593Smuzhiyun     char   *client;
1035*4882a593Smuzhiyun     char   *server;
1036*4882a593Smuzhiyun@@ -68,8 +72,13 @@
1037*4882a593Smuzhiyun     int     ch;
1038*4882a593Smuzhiyun     char   *inetcf = 0;
1039*4882a593Smuzhiyun     int     count;
1040*4882a593Smuzhiyun+#ifdef INET6
1041*4882a593Smuzhiyun+    struct sockaddr_storage server_sin;
1042*4882a593Smuzhiyun+    struct sockaddr_storage client_sin;
1043*4882a593Smuzhiyun+#else
1044*4882a593Smuzhiyun     struct sockaddr_in server_sin;
1045*4882a593Smuzhiyun     struct sockaddr_in client_sin;
1046*4882a593Smuzhiyun+#endif
1047*4882a593Smuzhiyun     struct stat st;
1048*4882a593Smuzhiyun
1049*4882a593Smuzhiyun     /*
1050*4882a593Smuzhiyun@@ -172,13 +181,20 @@
1051*4882a593Smuzhiyun     if (NOT_INADDR(server) == 0 || HOSTNAME_KNOWN(server)) {
1052*4882a593Smuzhiyun 	if ((hp = find_inet_addr(server)) == 0)
1053*4882a593Smuzhiyun 	    exit(1);
1054*4882a593Smuzhiyun+#ifndef INET6
1055*4882a593Smuzhiyun 	memset((char *) &server_sin, 0, sizeof(server_sin));
1056*4882a593Smuzhiyun 	server_sin.sin_family = AF_INET;
1057*4882a593Smuzhiyun+#endif
1058*4882a593Smuzhiyun 	request_set(&request, RQ_SERVER_SIN, &server_sin, 0);
1059*4882a593Smuzhiyun
1060*4882a593Smuzhiyun+#ifdef INET6
1061*4882a593Smuzhiyun+	for (res = hp, count = 0; res; res = res->ai_next, count++) {
1062*4882a593Smuzhiyun+	    memcpy(&server_sin, res->ai_addr, res->ai_addrlen);
1063*4882a593Smuzhiyun+#else
1064*4882a593Smuzhiyun 	for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
1065*4882a593Smuzhiyun 	    memcpy((char *) &server_sin.sin_addr, addr,
1066*4882a593Smuzhiyun 		   sizeof(server_sin.sin_addr));
1067*4882a593Smuzhiyun+#endif
1068*4882a593Smuzhiyun
1069*4882a593Smuzhiyun 	    /*
1070*4882a593Smuzhiyun 	     * Force evaluation of server host name and address. Host name
1071*4882a593Smuzhiyun@@ -194,7 +210,11 @@
1072*4882a593Smuzhiyun 	    fprintf(stderr, "Please specify an address instead\n");
1073*4882a593Smuzhiyun 	    exit(1);
1074*4882a593Smuzhiyun 	}
1075*4882a593Smuzhiyun+#ifdef INET6
1076*4882a593Smuzhiyun+	freeaddrinfo(hp);
1077*4882a593Smuzhiyun+#else
1078*4882a593Smuzhiyun 	free((char *) hp);
1079*4882a593Smuzhiyun+#endif
1080*4882a593Smuzhiyun     } else {
1081*4882a593Smuzhiyun 	request_set(&request, RQ_SERVER_NAME, server, 0);
1082*4882a593Smuzhiyun     }
1083*4882a593Smuzhiyun@@ -208,6 +228,18 @@
1084*4882a593Smuzhiyun 	tcpdmatch(&request);
1085*4882a593Smuzhiyun 	exit(0);
1086*4882a593Smuzhiyun     }
1087*4882a593Smuzhiyun+#ifdef INET6
1088*4882a593Smuzhiyun+    memset(&hints, 0, sizeof(hints));
1089*4882a593Smuzhiyun+    hints.ai_family = AF_INET6;
1090*4882a593Smuzhiyun+    hints.ai_socktype = SOCK_STREAM;
1091*4882a593Smuzhiyun+    hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1092*4882a593Smuzhiyun+    if (getaddrinfo(client, NULL, &hints, &res) == 0) {
1093*4882a593Smuzhiyun+	freeaddrinfo(res);
1094*4882a593Smuzhiyun+	request_set(&request, RQ_CLIENT_ADDR, client, 0);
1095*4882a593Smuzhiyun+	tcpdmatch(&request);
1096*4882a593Smuzhiyun+	exit(0);
1097*4882a593Smuzhiyun+    }
1098*4882a593Smuzhiyun+#endif
1099*4882a593Smuzhiyun
1100*4882a593Smuzhiyun     /*
1101*4882a593Smuzhiyun      * Perhaps they are testing special client hostname patterns that aren't
1102*4882a593Smuzhiyun@@ -229,6 +261,34 @@
1103*4882a593Smuzhiyun      */
1104*4882a593Smuzhiyun     if ((hp = find_inet_addr(client)) == 0)
1105*4882a593Smuzhiyun 	exit(1);
1106*4882a593Smuzhiyun+#ifdef INET6
1107*4882a593Smuzhiyun+    request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
1108*4882a593Smuzhiyun+
1109*4882a593Smuzhiyun+    for (res = hp, count = 0; res; res = res->ai_next, count++) {
1110*4882a593Smuzhiyun+	memcpy(&client_sin, res->ai_addr, res->ai_addrlen);
1111*4882a593Smuzhiyun+
1112*4882a593Smuzhiyun+	/*
1113*4882a593Smuzhiyun+	 * getnameinfo() doesn't do reverse lookup against link-local
1114*4882a593Smuzhiyun+	 * address.  So, we pass through host name evaluation against
1115*4882a593Smuzhiyun+	 * such addresses.
1116*4882a593Smuzhiyun+	 */
1117*4882a593Smuzhiyun+	if (res->ai_family != AF_INET6 ||
1118*4882a593Smuzhiyun+	    !IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)) {
1119*4882a593Smuzhiyun+	    /*
1120*4882a593Smuzhiyun+	     * Force evaluation of client host name and address. Host name
1121*4882a593Smuzhiyun+	     * conflicts will be reported while eval_hostname() does its job.
1122*4882a593Smuzhiyun+	     */
1123*4882a593Smuzhiyun+	    request_set(&request, RQ_CLIENT_NAME, "", RQ_CLIENT_ADDR, "", 0);
1124*4882a593Smuzhiyun+	    if (STR_EQ(eval_hostname(request.client), unknown))
1125*4882a593Smuzhiyun+		tcpd_warn("host address %s->name lookup failed",
1126*4882a593Smuzhiyun+			  eval_hostaddr(request.client));
1127*4882a593Smuzhiyun+	}
1128*4882a593Smuzhiyun+	tcpdmatch(&request);
1129*4882a593Smuzhiyun+	if (res->ai_next)
1130*4882a593Smuzhiyun+	    printf("\n");
1131*4882a593Smuzhiyun+    }
1132*4882a593Smuzhiyun+    freeaddrinfo(hp);
1133*4882a593Smuzhiyun+#else
1134*4882a593Smuzhiyun     memset((char *) &client_sin, 0, sizeof(client_sin));
1135*4882a593Smuzhiyun     client_sin.sin_family = AF_INET;
1136*4882a593Smuzhiyun     request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
1137*4882a593Smuzhiyun@@ -250,6 +310,7 @@
1138*4882a593Smuzhiyun 	    printf("\n");
1139*4882a593Smuzhiyun     }
1140*4882a593Smuzhiyun     free((char *) hp);
1141*4882a593Smuzhiyun+#endif
1142*4882a593Smuzhiyun     exit(0);
1143*4882a593Smuzhiyun }
1144*4882a593Smuzhiyun
1145*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/tli.c tcp_wrappers_7.6/tli.c
1146*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/tli.c	1997-03-21 19:27:26.000000000 +0100
1147*4882a593Smuzhiyun+++ tcp_wrappers_7.6/tli.c	2004-04-10 19:07:43.000000000 +0200
1148*4882a593Smuzhiyun@@ -65,8 +65,13 @@
1149*4882a593Smuzhiyun void    tli_host(request)
1150*4882a593Smuzhiyun struct request_info *request;
1151*4882a593Smuzhiyun {
1152*4882a593Smuzhiyun+#ifdef INET6
1153*4882a593Smuzhiyun+    static struct sockaddr_storage client;
1154*4882a593Smuzhiyun+    static struct sockaddr_storage server;
1155*4882a593Smuzhiyun+#else
1156*4882a593Smuzhiyun     static struct sockaddr_in client;
1157*4882a593Smuzhiyun     static struct sockaddr_in server;
1158*4882a593Smuzhiyun+#endif
1159*4882a593Smuzhiyun
1160*4882a593Smuzhiyun     /*
1161*4882a593Smuzhiyun      * If we discover that we are using an IP transport, pretend we never
1162*4882a593Smuzhiyun@@ -76,14 +81,29 @@
1163*4882a593Smuzhiyun
1164*4882a593Smuzhiyun     tli_endpoints(request);
1165*4882a593Smuzhiyun     if ((request->config = tli_transport(request->fd)) != 0
1166*4882a593Smuzhiyun+#ifdef INET6
1167*4882a593Smuzhiyun+	&& (STR_EQ(request->config->nc_protofmly, "inet") ||
1168*4882a593Smuzhiyun+	    STR_EQ(request->config->nc_protofmly, "inet6"))) {
1169*4882a593Smuzhiyun+#else
1170*4882a593Smuzhiyun 	&& STR_EQ(request->config->nc_protofmly, "inet")) {
1171*4882a593Smuzhiyun+#endif
1172*4882a593Smuzhiyun 	if (request->client->unit != 0) {
1173*4882a593Smuzhiyun+#ifdef INET6
1174*4882a593Smuzhiyun+	    client = *(struct sockaddr_storage *) request->client->unit->addr.buf;
1175*4882a593Smuzhiyun+	    request->client->sin = (struct sockaddr *) &client;
1176*4882a593Smuzhiyun+#else
1177*4882a593Smuzhiyun 	    client = *(struct sockaddr_in *) request->client->unit->addr.buf;
1178*4882a593Smuzhiyun 	    request->client->sin = &client;
1179*4882a593Smuzhiyun+#endif
1180*4882a593Smuzhiyun 	}
1181*4882a593Smuzhiyun 	if (request->server->unit != 0) {
1182*4882a593Smuzhiyun+#ifdef INET6
1183*4882a593Smuzhiyun+	    server = *(struct sockaddr_storage *) request->server->unit->addr.buf;
1184*4882a593Smuzhiyun+	    request->server->sin = (struct sockaddr *) &server;
1185*4882a593Smuzhiyun+#else
1186*4882a593Smuzhiyun 	    server = *(struct sockaddr_in *) request->server->unit->addr.buf;
1187*4882a593Smuzhiyun 	    request->server->sin = &server;
1188*4882a593Smuzhiyun+#endif
1189*4882a593Smuzhiyun 	}
1190*4882a593Smuzhiyun 	tli_cleanup(request);
1191*4882a593Smuzhiyun 	sock_methods(request);
1192*4882a593Smuzhiyun@@ -187,7 +207,15 @@
1193*4882a593Smuzhiyun     }
1194*4882a593Smuzhiyun     while (config = getnetconfig(handlep)) {
1195*4882a593Smuzhiyun 	if (stat(config->nc_device, &from_config) == 0) {
1196*4882a593Smuzhiyun+#ifdef NO_CLONE_DEVICE
1197*4882a593Smuzhiyun+	/*
1198*4882a593Smuzhiyun+	 * If the network devices are not cloned (as is the case for
1199*4882a593Smuzhiyun+	 * Solaris 8 Beta), we must compare the major device numbers.
1200*4882a593Smuzhiyun+	 */
1201*4882a593Smuzhiyun+	    if (major(from_config.st_rdev) == major(from_client.st_rdev))
1202*4882a593Smuzhiyun+#else
1203*4882a593Smuzhiyun 	    if (minor(from_config.st_rdev) == major(from_client.st_rdev))
1204*4882a593Smuzhiyun+#endif
1205*4882a593Smuzhiyun 		break;
1206*4882a593Smuzhiyun 	}
1207*4882a593Smuzhiyun     }
1208*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/update.c tcp_wrappers_7.6/update.c
1209*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/update.c	1994-12-28 17:42:56.000000000 +0100
1210*4882a593Smuzhiyun+++ tcp_wrappers_7.6/update.c	2004-04-10 19:07:43.000000000 +0200
1211*4882a593Smuzhiyun@@ -46,10 +46,18 @@
1212*4882a593Smuzhiyun 	    request->fd = va_arg(ap, int);
1213*4882a593Smuzhiyun 	    continue;
1214*4882a593Smuzhiyun 	case RQ_CLIENT_SIN:
1215*4882a593Smuzhiyun+#ifdef INET6
1216*4882a593Smuzhiyun+	    request->client->sin = va_arg(ap, struct sockaddr *);
1217*4882a593Smuzhiyun+#else
1218*4882a593Smuzhiyun 	    request->client->sin = va_arg(ap, struct sockaddr_in *);
1219*4882a593Smuzhiyun+#endif
1220*4882a593Smuzhiyun 	    continue;
1221*4882a593Smuzhiyun 	case RQ_SERVER_SIN:
1222*4882a593Smuzhiyun+#ifdef INET6
1223*4882a593Smuzhiyun+	    request->server->sin = va_arg(ap, struct sockaddr *);
1224*4882a593Smuzhiyun+#else
1225*4882a593Smuzhiyun 	    request->server->sin = va_arg(ap, struct sockaddr_in *);
1226*4882a593Smuzhiyun+#endif
1227*4882a593Smuzhiyun 	    continue;
1228*4882a593Smuzhiyun
1229*4882a593Smuzhiyun 	    /*
1230*4882a593Smuzhiyundiff -ruN tcp_wrappers_7.6.orig/workarounds.c tcp_wrappers_7.6/workarounds.c
1231*4882a593Smuzhiyun--- tcp_wrappers_7.6.orig/workarounds.c	1996-03-19 16:22:26.000000000 +0100
1232*4882a593Smuzhiyun+++ tcp_wrappers_7.6/workarounds.c	2004-04-10 19:07:43.000000000 +0200
1233*4882a593Smuzhiyun@@ -166,11 +166,22 @@
1234*4882a593Smuzhiyun int    *len;
1235*4882a593Smuzhiyun {
1236*4882a593Smuzhiyun     int     ret;
1237*4882a593Smuzhiyun+#ifdef INET6
1238*4882a593Smuzhiyun+    struct sockaddr *sin = sa;
1239*4882a593Smuzhiyun+#else
1240*4882a593Smuzhiyun     struct sockaddr_in *sin = (struct sockaddr_in *) sa;
1241*4882a593Smuzhiyun+#endif
1242*4882a593Smuzhiyun
1243*4882a593Smuzhiyun     if ((ret = getpeername(sock, sa, len)) >= 0
1244*4882a593Smuzhiyun+#ifdef INET6
1245*4882a593Smuzhiyun+	&& ((sin->su_si.si_family == AF_INET6
1246*4882a593Smuzhiyun+	     && IN6_IS_ADDR_UNSPECIFIED(&sin->su_sin6.sin6_addr))
1247*4882a593Smuzhiyun+	    || (sin->su_si.si_family == AF_INET
1248*4882a593Smuzhiyun+		&& sin->su_sin.sin_addr.s_addr == 0))) {
1249*4882a593Smuzhiyun+#else
1250*4882a593Smuzhiyun 	&& sa->sa_family == AF_INET
1251*4882a593Smuzhiyun 	&& sin->sin_addr.s_addr == 0) {
1252*4882a593Smuzhiyun+#endif
1253*4882a593Smuzhiyun 	errno = ENOTCONN;
1254*4882a593Smuzhiyun 	return (-1);
1255*4882a593Smuzhiyun     } else {
1256