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