1 diff -ruN tcp_wrappers_7.6.orig/fix_options.c tcp_wrappers_7.6/fix_options.c
2 --- tcp_wrappers_7.6.orig/fix_options.c 1997-04-08 02:29:19.000000000 +0200
3 +++ tcp_wrappers_7.6/fix_options.c 2004-04-10 19:07:43.000000000 +0200
9 +#include <sys/socket.h>
11 #include <netinet/in.h>
12 #include <netinet/in_systm.h>
13 #include <netinet/ip.h>
19 + struct sockaddr_storage ss;
23 + * check if this is AF_INET socket
27 + if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) {
28 + syslog(LOG_ERR, "getpeername: %m");
29 + clean_exit(request);
31 + if (ss.ss_family != AF_INET)
35 if ((ip = getprotobyname("ip")) != 0)
36 ipproto = ip->p_proto;
37 diff -ruN tcp_wrappers_7.6.orig/hosts_access.5 tcp_wrappers_7.6/hosts_access.5
38 --- tcp_wrappers_7.6.orig/hosts_access.5 2004-04-10 19:22:58.000000000 +0200
39 +++ tcp_wrappers_7.6/hosts_access.5 2004-04-10 19:07:43.000000000 +0200
41 for daemon process names or for client user names.
43 An expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a
44 -`net/mask\' pair. A host address is matched if `net\' is equal to the
45 +`net/mask\' pair. An IPv4 host address is matched if `net\' is equal to the
46 bitwise AND of the address and the `mask\'. For example, the net/mask
47 pattern `131.155.72.0/255.255.254.0\' matches every address in the
48 range `131.155.72.0\' through `131.155.73.255\'.
50 +An expression of the form `[n:n:n:n:n:n:n:n]/m\' is interpreted as a
51 +`[net]/prefixlen\' pair. An IPv6 host address is matched if
52 +`prefixlen\' bits of `net\' is equal to the `prefixlen\' bits of the
53 +address. For example, the [net]/prefixlen pattern
54 +`[3ffe:505:2:1::]/64\' matches every address in the range
55 +`3ffe:505:2:1::\' through `3ffe:505:2:1:ffff:ffff:ffff:ffff\'.
57 Wildcards `*\' and `?\' can be used to match hostnames or IP addresses. This
58 method of matching cannot be used in conjunction with `net/mask\' matching,
59 hostname matching beginning with `.\' or IP address matching ending with `.\'.
60 diff -ruN tcp_wrappers_7.6.orig/hosts_access.c tcp_wrappers_7.6/hosts_access.c
61 --- tcp_wrappers_7.6.orig/hosts_access.c 2004-04-10 19:22:58.000000000 +0200
62 +++ tcp_wrappers_7.6/hosts_access.c 2004-04-10 19:07:43.000000000 +0200
64 /* System libraries. */
66 #include <sys/types.h>
68 + typedef uint32_t u_int32_t;
70 #include <sys/param.h>
72 +#include <sys/socket.h>
74 #include <netinet/in.h>
75 #include <arpa/inet.h>
88 static int host_match();
89 static int string_match();
90 static int masked_match();
92 +static int masked_match4();
93 +static int masked_match6();
96 /* Size of logical line buffer. */
103 + /* convert IPv4 mapped IPv6 address to IPv4 address */
104 + if (STRN_EQ(string, "::ffff:", 7)
105 + && dot_quad_addr(string + 7) != INADDR_NONE) {
109 #ifndef DISABLE_WILDCARD_MATCHING
110 if (strchr(tok, '*') || strchr(tok,'?')) { /* contains '*' or '?' */
111 return (match_pattern_ylo(string,tok));
112 @@ -304,20 +324,72 @@
113 } else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */
114 return (STRN_EQ(tok, string, n));
115 } else { /* exact match */
117 + struct addrinfo hints, *res;
118 + struct sockaddr_in6 pat, addr;
123 + if (*tok == '[' && tok[len - 1] == ']') {
125 + tok[len - 1] = '\0';
126 + memset(&hints, 0, sizeof(hints));
127 + hints.ai_family = AF_INET6;
128 + hints.ai_socktype = SOCK_STREAM;
129 + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
130 + if ((ret = getaddrinfo(tok + 1, NULL, &hints, &res)) == 0) {
131 + memcpy(&pat, res->ai_addr, sizeof(pat));
135 + if (ret != 0 || getaddrinfo(string, NULL, &hints, &res) != 0)
137 + memcpy(&addr, res->ai_addr, sizeof(addr));
139 +#ifdef NI_WITHSCOPEID
140 + if (pat.sin6_scope_id != 0 &&
141 + addr.sin6_scope_id != pat.sin6_scope_id)
144 + return (!memcmp(&pat.sin6_addr, &addr.sin6_addr,
145 + sizeof(struct in6_addr)));
149 return (STR_EQ(tok, string));
153 /* masked_match - match address against netnumber/netmask */
156 static int masked_match(net_tok, mask_tok, string)
161 + return (masked_match4(net_tok, mask_tok, string) ||
162 + masked_match6(net_tok, mask_tok, string));
165 +static int masked_match4(net_tok, mask_tok, string)
167 +static int masked_match(net_tok, mask_tok, string)
184 * Disallow forms other than dotted quad: the treatment that inet_addr()
185 @@ -329,12 +401,78 @@
187 if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
188 || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) {
190 tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
192 return (NO); /* not tcpd_jump() */
194 return ((addr & mask) == net);
198 +static int masked_match6(net_tok, mask_tok, string)
203 + struct addrinfo hints, *res;
204 + struct sockaddr_in6 net, addr;
206 + int len, mask_len, i = 0;
209 + memset(&hints, 0, sizeof(hints));
210 + hints.ai_family = AF_INET6;
211 + hints.ai_socktype = SOCK_STREAM;
212 + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
213 + if (getaddrinfo(string, NULL, &hints, &res) != 0)
215 + memcpy(&addr, res->ai_addr, sizeof(addr));
218 + if (IN6_IS_ADDR_V4MAPPED(&addr.sin6_addr)) {
219 + if ((*(u_int32_t *)&net.sin6_addr.s6_addr[12] = dot_quad_addr(net_tok)) == INADDR_NONE
220 + || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE)
222 + return ((*(u_int32_t *)&addr.sin6_addr.s6_addr[12] & mask) == *(u_int32_t *)&net.sin6_addr.s6_addr[12]);
225 + /* match IPv6 address against netnumber/prefixlen */
226 + len = strlen(net_tok);
227 + if (*net_tok != '[' || net_tok[len - 1] != ']')
229 + ch = net_tok[len - 1];
230 + net_tok[len - 1] = '\0';
231 + if (getaddrinfo(net_tok + 1, NULL, &hints, &res) != 0) {
232 + net_tok[len - 1] = ch;
235 + memcpy(&net, res->ai_addr, sizeof(net));
237 + net_tok[len - 1] = ch;
238 + if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128)
241 +#ifdef NI_WITHSCOPEID
242 + if (net.sin6_scope_id != 0 && addr.sin6_scope_id != net.sin6_scope_id)
245 + while (mask_len > 0) {
246 + if (mask_len < 32) {
247 + mask = htonl(~(0xffffffff >> mask_len));
248 + if ((*(u_int32_t *)&addr.sin6_addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.sin6_addr.s6_addr[i] & mask))
252 + if (*(u_int32_t *)&addr.sin6_addr.s6_addr[i] != *(u_int32_t *)&net.sin6_addr.s6_addr[i])
261 #ifndef DISABLE_WILDCARD_MATCHING
262 /* Note: this feature has been adapted in a pretty straightforward way
263 from Tatu Ylonen's last SSH version under free license by
264 diff -ruN tcp_wrappers_7.6.orig/Makefile tcp_wrappers_7.6/Makefile
265 --- tcp_wrappers_7.6.orig/Makefile 1997-03-21 19:27:21.000000000 +0100
266 +++ tcp_wrappers_7.6/Makefile 2004-04-10 19:22:44.000000000 +0200
268 @echo " dynix epix esix freebsd hpux irix4 irix5 irix6 isc iunix"
269 @echo " linux machten mips(untested) ncrsvr4 netbsd next osf power_unix_211"
270 @echo " ptx-2.x ptx-generic pyramid sco sco-nis sco-od2 sco-os5 sinix sunos4"
271 - @echo " sunos40 sunos5 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2"
272 + @echo " sunos40 sunos5 solaris8 sysv4 tandem ultrix unicos7 unicos8 unixware1 unixware2"
275 @echo "If none of these match your environment, edit the system"
276 @@ -131,20 +131,34 @@
277 NETGROUP=-DNETGROUP TLI= SYSTYPE="-systype bsd43" all
279 # Freebsd and linux by default have no NIS.
280 -386bsd netbsd bsdos:
282 @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
283 LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \
284 EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all
287 @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
288 + LIBS="-L/usr/local/v6/lib -linet6" \
289 LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \
290 - EXTRA_CFLAGS=-DSYS_ERRLIST_DEFINED VSYSLOG= all
291 + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DINET6 -Dss_family=__ss_family -Dss_len=__ss_len" \
295 + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
296 + LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ= NETGROUP= TLI= \
297 + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DINET6 -Dss_family=__ss_family -Dss_len=__ss_len" VSYSLOG= all
300 @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
301 - LIBS= RANLIB=ranlib ARFLAGS=rv AUX_OBJ=setenv.o \
302 - NETGROUP= TLI= EXTRA_CFLAGS="-DBROKEN_SO_LINGER" all
303 + LIBS=-lnsl RANLIB=ranlib ARFLAGS=rv AUX_OBJ= \
304 + NETGROUP="-DNETGROUP" TLI= VSYSLOG= BUGS= \
305 + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DHAVE_STRERROR -DINET6=1 -Dss_family=__ss_family -Dss_len=__ss_len" all
308 + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
309 + LIBS=-lnsl RANLIB=ranlib ARFLAGS=rv AUX_OBJ= \
310 + NETGROUP=-DNETGROUP TLI= VSYSLOG= BUGS= \
311 + EXTRA_CFLAGS="-DSYS_ERRLIST_DEFINED -DHAVE_STRERROR" all
313 # This is good for many SYSV+BSD hybrids with NIS, probably also for HP-UX 7.x.
314 hpux hpux8 hpux9 hpux10:
316 NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \
317 BUGS="$(BUGS) -DSOLARIS_24_GETHOSTBYNAME_BUG" all
319 +# SunOS 5.8 is another SYSV4 variant, but has IPv6 support
321 + @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
322 + LIBS="-lsocket -lnsl" RANLIB=echo ARFLAGS=rv VSYSLOG= \
323 + NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \
324 + EXTRA_CFLAGS="-DINET6 -DNO_CLONE_DEVICE -DINT32_T" all
328 @make REAL_DAEMON_DIR=$(REAL_DAEMON_DIR) STYLE=$(STYLE) \
329 diff -ruN tcp_wrappers_7.6.orig/misc.c tcp_wrappers_7.6/misc.c
330 --- tcp_wrappers_7.6.orig/misc.c 1996-02-11 17:01:30.000000000 +0100
331 +++ tcp_wrappers_7.6/misc.c 2004-04-10 19:07:43.000000000 +0200
339 + for (cp = string; cp && *cp; cp++) {
348 + if (bracket == 0 && *cp == delimiter) {
357 if ((cp = strchr(string, delimiter)) != 0)
363 /* dot_quad_addr - convert dotted quad to internal form */
364 diff -ruN tcp_wrappers_7.6.orig/refuse.c tcp_wrappers_7.6/refuse.c
365 --- tcp_wrappers_7.6.orig/refuse.c 1994-12-28 17:42:40.000000000 +0100
366 +++ tcp_wrappers_7.6/refuse.c 2004-04-10 19:07:43.000000000 +0200
369 struct request_info *request;
372 + syslog(deny_severity, "refused connect from %s (%s)",
373 + eval_client(request), eval_hostaddr(request->client));
375 syslog(deny_severity, "refused connect from %s", eval_client(request));
380 diff -ruN tcp_wrappers_7.6.orig/rfc931.c tcp_wrappers_7.6/rfc931.c
381 --- tcp_wrappers_7.6.orig/rfc931.c 1995-01-02 16:11:34.000000000 +0100
382 +++ tcp_wrappers_7.6/rfc931.c 2004-04-10 19:07:43.000000000 +0200
384 /* rfc931 - return remote user name, given socket structures */
386 void rfc931(rmt_sin, our_sin, dest)
388 +struct sockaddr *rmt_sin;
389 +struct sockaddr *our_sin;
391 struct sockaddr_in *rmt_sin;
392 struct sockaddr_in *our_sin;
399 + struct sockaddr_storage rmt_query_sin;
400 + struct sockaddr_storage our_query_sin;
403 struct sockaddr_in rmt_query_sin;
404 struct sockaddr_in our_query_sin;
406 char user[256]; /* XXX */
407 char buffer[512]; /* XXX */
409 char *result = unknown;
413 + /* address family must be the same */
414 + if (rmt_sin->sa_family != our_sin->sa_family) {
415 + STRN_CPY(dest, result, STRING_LENGTH);
418 + switch (our_sin->sa_family) {
420 + alen = sizeof(struct sockaddr_in);
423 + alen = sizeof(struct sockaddr_in6);
426 + STRN_CPY(dest, result, STRING_LENGTH);
432 * Use one unbuffered stdio stream for writing to and for reading from
433 * the RFC931 etc. server. This is done because of a bug in the SunOS
439 + if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) {
441 if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
443 setbuf(fp, (char *) 0);
447 * addresses from the query socket.
451 + memcpy(&our_query_sin, our_sin, alen);
452 + memcpy(&rmt_query_sin, rmt_sin, alen);
453 + switch (our_sin->sa_family) {
455 + ((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT);
456 + ((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC931_PORT);
459 + ((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT);
460 + ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC931_PORT);
464 + if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
466 + connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
469 our_query_sin = *our_sin;
470 our_query_sin.sin_port = htons(ANY_PORT);
471 rmt_query_sin = *rmt_sin;
473 sizeof(our_query_sin)) >= 0 &&
474 connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
475 sizeof(rmt_query_sin)) >= 0) {
479 * Send query to server. Neglect the risk that a 13-byte
483 fprintf(fp, "%u,%u\r\n",
485 + ntohs(((struct sockaddr_in *)rmt_sin)->sin_port),
486 + ntohs(((struct sockaddr_in *)our_sin)->sin_port));
488 ntohs(rmt_sin->sin_port),
489 ntohs(our_sin->sin_port));
495 && ferror(fp) == 0 && feof(fp) == 0
496 && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
497 &rmt_port, &our_port, user) == 3
499 + && ntohs(((struct sockaddr_in *)rmt_sin)->sin_port) == rmt_port
500 + && ntohs(((struct sockaddr_in *)our_sin)->sin_port) == our_port) {
502 && ntohs(rmt_sin->sin_port) == rmt_port
503 && ntohs(our_sin->sin_port) == our_port) {
507 * Strip trailing carriage return. It is part of the
508 diff -ruN tcp_wrappers_7.6.orig/scaffold.c tcp_wrappers_7.6/scaffold.c
509 --- tcp_wrappers_7.6.orig/scaffold.c 1997-03-21 19:27:24.000000000 +0100
510 +++ tcp_wrappers_7.6/scaffold.c 2004-04-10 19:07:43.000000000 +0200
512 #define INADDR_NONE (-1) /* XXX should be 0xffffffff */
516 extern char *malloc();
519 /* Application-specific. */
522 int deny_severity = LOG_WARNING;
523 int rfc931_timeout = RFC931_TIMEOUT;
526 /* dup_hostent - create hostent in one memory block */
528 static struct hostent *dup_hostent(hp)
535 /* find_inet_addr - find all addresses for this host, result to free() */
538 +struct addrinfo *find_inet_addr(host)
541 + struct addrinfo hints, *res;
543 + memset(&hints, 0, sizeof(hints));
544 + hints.ai_family = PF_UNSPEC;
545 + hints.ai_socktype = SOCK_STREAM;
546 + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
547 + if (getaddrinfo(host, NULL, &hints, &res) == 0)
550 + memset(&hints, 0, sizeof(hints));
551 + hints.ai_family = PF_UNSPEC;
552 + hints.ai_socktype = SOCK_STREAM;
553 + hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
554 + if (getaddrinfo(host, NULL, &hints, &res) != 0) {
555 + tcpd_warn("%s: host not found", host);
558 + if (res->ai_family != AF_INET6 && res->ai_family != AF_INET) {
559 + tcpd_warn("%d: not an internet host", res->ai_family);
563 + if (!res->ai_canonname) {
564 + tcpd_warn("%s: hostname alias", host);
565 + tcpd_warn("(cannot obtain official name)", res->ai_canonname);
566 + } else if (STR_NE(host, res->ai_canonname)) {
567 + tcpd_warn("%s: hostname alias", host);
568 + tcpd_warn("(official name: %.*s)", STRING_LENGTH, res->ai_canonname);
573 struct hostent *find_inet_addr(host)
578 return (dup_hostent(hp));
582 /* check_dns - give each address thorough workout, return address count */
587 struct request_info request;
589 + struct sockaddr_storage sin;
590 + struct addrinfo *hp, *res;
592 struct sockaddr_in sin;
598 @@ -134,11 +180,18 @@
600 request_init(&request, RQ_CLIENT_SIN, &sin, 0);
601 sock_methods(&request);
603 memset((char *) &sin, 0, sizeof(sin));
604 sin.sin_family = AF_INET;
608 + for (res = hp, count = 0; res; res = res->ai_next, count++) {
609 + memcpy(&sin, res->ai_addr, res->ai_addrlen);
611 for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
612 memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr));
616 * Force host name and address conversions. Use the request structure
618 tcpd_warn("host address %s->name lookup failed",
619 eval_hostaddr(request.client));
629 diff -ruN tcp_wrappers_7.6.orig/scaffold.h tcp_wrappers_7.6/scaffold.h
630 --- tcp_wrappers_7.6.orig/scaffold.h 1994-12-31 18:19:20.000000000 +0100
631 +++ tcp_wrappers_7.6/scaffold.h 2004-04-10 19:07:43.000000000 +0200
633 * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
637 +extern struct addrinfo *find_inet_addr();
639 extern struct hostent *find_inet_addr();
641 extern int check_dns();
642 extern int check_path();
643 diff -ruN tcp_wrappers_7.6.orig/socket.c tcp_wrappers_7.6/socket.c
644 --- tcp_wrappers_7.6.orig/socket.c 2004-04-10 19:22:58.000000000 +0200
645 +++ tcp_wrappers_7.6/socket.c 2004-04-10 19:07:43.000000000 +0200
647 #include <sys/types.h>
648 #include <sys/param.h>
649 #include <sys/socket.h>
651 +typedef uint32_t u_int32_t;
653 #include <netinet/in.h>
660 +#ifndef NI_WITHSCOPEID
661 +#define NI_WITHSCOPEID 0
664 extern char *inet_ntoa();
670 void sock_host(request)
671 struct request_info *request;
674 + static struct sockaddr_storage client;
675 + static struct sockaddr_storage server;
677 static struct sockaddr_in client;
678 static struct sockaddr_in server;
682 int fd = request->fd;
684 memset(buf, 0 sizeof(buf));
688 + request->client->sin = (struct sockaddr *)&client;
690 request->client->sin = &client;
694 * Determine the server binding. This is used for client username
696 tcpd_warn("getsockname: %m");
700 + request->server->sin = (struct sockaddr *)&server;
702 request->server->sin = &server;
706 /* sock_hostaddr - map endpoint address to printable form */
707 @@ -130,10 +152,26 @@
708 void sock_hostaddr(host)
709 struct host_info *host;
712 + struct sockaddr *sin = host->sin;
718 + salen = sin->sa_len;
720 + salen = (sin->sa_family == AF_INET) ? sizeof(struct sockaddr_in)
721 + : sizeof(struct sockaddr_in6);
723 + getnameinfo(sin, salen, host->addr, sizeof(host->addr),
724 + NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
726 struct sockaddr_in *sin = host->sin;
729 STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
733 /* sock_hostname - map endpoint address to host name */
734 @@ -141,6 +179,160 @@
735 void sock_hostname(host)
736 struct host_info *host;
739 + struct sockaddr *sin = host->sin;
740 + struct sockaddr_in sin4;
741 + struct addrinfo hints, *res, *res0 = NULL;
742 + int salen, alen, err = 1;
743 + char *ap = NULL, *rap, hname[NI_MAXHOST];
746 + if (sin->sa_family == AF_INET6) {
747 + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sin;
749 + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
750 + memset(&sin4, 0, sizeof(sin4));
752 + sin4.sin_len = sizeof(sin4);
754 + sin4.sin_family = AF_INET;
755 + sin4.sin_port = sin6->sin6_port;
756 + sin4.sin_addr.s_addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12];
757 + sin = (struct sockaddr *)&sin4;
760 + switch (sin->sa_family) {
762 + ap = (char *)&((struct sockaddr_in *)sin)->sin_addr;
763 + alen = sizeof(struct in_addr);
764 + salen = sizeof(struct sockaddr_in);
767 + ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr;
768 + alen = sizeof(struct in6_addr);
769 + salen = sizeof(struct sockaddr_in6);
775 + err = getnameinfo(sin, salen, hname, sizeof(hname),
776 + NULL, 0, NI_WITHSCOPEID | NI_NAMEREQD);
780 + STRN_CPY(host->name, hname, sizeof(host->name));
782 + /* reject numeric addresses */
783 + memset(&hints, 0, sizeof(hints));
784 + hints.ai_family = sin->sa_family;
785 + hints.ai_socktype = SOCK_STREAM;
786 + hints.ai_flags = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST;
787 + if ((err = getaddrinfo(host->name, NULL, &hints, &res0) == 0)) {
788 + freeaddrinfo(res0);
790 + tcpd_warn("host name/name mismatch: "
791 + "reverse lookup results in non-FQDN %s",
793 + strcpy(host->name, paranoid); /* name is bad, clobber it */
798 + /* we are now sure that this is non-numeric */
801 + * Verify that the address is a member of the address list returned
802 + * by gethostbyname(hostname).
804 + * Verify also that gethostbyaddr() and gethostbyname() return the same
805 + * hostname, or rshd and rlogind may still end up being spoofed.
807 + * On some sites, gethostbyname("localhost") returns "localhost.domain".
808 + * This is a DNS artefact. We treat it as a special case. When we
809 + * can't believe the address list from gethostbyname("localhost")
810 + * we're in big trouble anyway.
813 + memset(&hints, 0, sizeof(hints));
814 + hints.ai_family = sin->sa_family;
815 + hints.ai_socktype = SOCK_STREAM;
816 + hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
817 + if (getaddrinfo(host->name, NULL, &hints, &res0) != 0) {
820 + * Unable to verify that the host name matches the address. This
821 + * may be a transient problem or a botched name server setup.
824 + tcpd_warn("can't verify hostname: getaddrinfo(%s, %s) failed",
826 + (sin->sa_family == AF_INET) ? "AF_INET" : "AF_INET6");
828 + } else if ((res0->ai_canonname == NULL
829 + || STR_NE(host->name, res0->ai_canonname))
830 + && STR_NE(host->name, "localhost")) {
833 + * The gethostbyaddr() and gethostbyname() calls did not return
834 + * the same hostname. This could be a nameserver configuration
835 + * problem. It could also be that someone is trying to spoof us.
838 + tcpd_warn("host name/name mismatch: %s != %.*s",
839 + host->name, STRING_LENGTH,
840 + (res0->ai_canonname == NULL) ? "" : res0->ai_canonname);
845 + * The address should be a member of the address list returned by
846 + * gethostbyname(). We should first verify that the h_addrtype
847 + * field is AF_INET, but this program has already caused too much
848 + * grief on systems with broken library code.
851 + for (res = res0; res; res = res->ai_next) {
852 + if (res->ai_family != sin->sa_family)
854 + switch (res->ai_family) {
856 + rap = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr;
859 + /* need to check scope_id */
860 + if (((struct sockaddr_in6 *)sin)->sin6_scope_id !=
861 + ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id) {
864 + rap = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
869 + if (memcmp(rap, ap, alen) == 0) {
870 + freeaddrinfo(res0);
871 + return; /* name is good, keep it */
876 + * The host name does not map to the initial address. Perhaps
877 + * someone has messed up. Perhaps someone compromised a name
881 + getnameinfo(sin, salen, hname, sizeof(hname),
882 + NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
883 + tcpd_warn("host name/address mismatch: %s != %.*s",
884 + hname, STRING_LENGTH,
885 + (res0->ai_canonname == NULL) ? "" : res0->ai_canonname);
887 + strcpy(host->name, paranoid); /* name is bad, clobber it */
889 + freeaddrinfo(res0);
892 struct sockaddr_in *sin = host->sin;
897 strcpy(host->name, paranoid); /* name is bad, clobber it */
902 /* sock_sink - absorb unreceived IP datagram */
908 + struct sockaddr_storage sin;
910 struct sockaddr_in sin;
912 int size = sizeof(sin);
915 diff -ruN tcp_wrappers_7.6.orig/tcpd.c tcp_wrappers_7.6/tcpd.c
916 --- tcp_wrappers_7.6.orig/tcpd.c 1996-02-11 17:01:33.000000000 +0100
917 +++ tcp_wrappers_7.6/tcpd.c 2004-04-10 19:07:43.000000000 +0200
920 /* Report request and invoke the real daemon program. */
923 + syslog(allow_severity, "connect from %s (%s)",
924 + eval_client(&request), eval_hostaddr(request.client));
926 syslog(allow_severity, "connect from %s", eval_client(&request));
929 (void) execv(path, argv);
930 syslog(LOG_ERR, "error: cannot execute %s: %m", path);
931 diff -ruN tcp_wrappers_7.6.orig/tcpdchk.c tcp_wrappers_7.6/tcpdchk.c
932 --- tcp_wrappers_7.6.orig/tcpdchk.c 1997-02-12 02:13:25.000000000 +0100
933 +++ tcp_wrappers_7.6/tcpdchk.c 2004-04-10 19:07:43.000000000 +0200
936 #include <sys/types.h>
937 #include <sys/stat.h>
939 +#include <sys/socket.h>
941 #include <netinet/in.h>
942 #include <arpa/inet.h>
949 +static int is_inet6_addr(pat)
952 + struct addrinfo hints, *res;
959 + if ((ch = pat[len - 1]) != ']')
961 + pat[len - 1] = '\0';
962 + memset(&hints, 0, sizeof(hints));
963 + hints.ai_family = AF_INET6;
964 + hints.ai_socktype = SOCK_STREAM;
965 + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
966 + if ((ret = getaddrinfo(pat + 1, NULL, &hints, &res)) == 0)
973 /* check_host - criticize host pattern */
975 static int check_host(pat)
976 @@ -423,14 +451,27 @@
979 } else if (mask = split_at(pat, '/')) { /* network/netmask */
983 + if ((dot_quad_addr(pat) == INADDR_NONE
984 + || dot_quad_addr(mask) == INADDR_NONE)
985 + && (!is_inet6_addr(pat)
986 + || ((mask_len = atoi(mask)) < 0 || mask_len > 128)))
988 if (dot_quad_addr(pat) == INADDR_NONE
989 || dot_quad_addr(mask) == INADDR_NONE)
991 tcpd_warn("%s/%s: bad net/mask pattern", pat, mask);
992 } else if (STR_EQ(pat, "FAIL")) { /* obsolete */
993 tcpd_warn("FAIL is no longer recognized");
994 tcpd_warn("(use EXCEPT or DENY instead)");
995 } else if (reserved_name(pat)) { /* other reserved */
998 + } else if (is_inet6_addr(pat)) { /* IPv6 address */
1001 } else if (NOT_INADDR(pat)) { /* internet name */
1002 if (pat[strlen(pat) - 1] == '.') {
1003 tcpd_warn("%s: domain or host name ends in dot", pat);
1004 diff -ruN tcp_wrappers_7.6.orig/tcpd.h tcp_wrappers_7.6/tcpd.h
1005 --- tcp_wrappers_7.6.orig/tcpd.h 1996-03-19 16:22:25.000000000 +0100
1006 +++ tcp_wrappers_7.6/tcpd.h 2004-04-10 19:07:43.000000000 +0200
1009 char name[STRING_LENGTH]; /* access via eval_hostname(host) */
1010 char addr[STRING_LENGTH]; /* access via eval_hostaddr(host) */
1012 + struct sockaddr *sin; /* socket address or 0 */
1014 struct sockaddr_in *sin; /* socket address or 0 */
1016 struct t_unitdata *unit; /* TLI transport address or 0 */
1017 struct request_info *request; /* for shared information */
1019 diff -ruN tcp_wrappers_7.6.orig/tcpdmatch.c tcp_wrappers_7.6/tcpdmatch.c
1020 --- tcp_wrappers_7.6.orig/tcpdmatch.c 1996-02-11 17:01:36.000000000 +0100
1021 +++ tcp_wrappers_7.6/tcpdmatch.c 2004-04-10 19:07:43.000000000 +0200
1027 + struct addrinfo hints, *hp, *res;
1031 char *myname = argv[0];
1039 + struct sockaddr_storage server_sin;
1040 + struct sockaddr_storage client_sin;
1042 struct sockaddr_in server_sin;
1043 struct sockaddr_in client_sin;
1048 @@ -172,13 +181,20 @@
1049 if (NOT_INADDR(server) == 0 || HOSTNAME_KNOWN(server)) {
1050 if ((hp = find_inet_addr(server)) == 0)
1053 memset((char *) &server_sin, 0, sizeof(server_sin));
1054 server_sin.sin_family = AF_INET;
1056 request_set(&request, RQ_SERVER_SIN, &server_sin, 0);
1059 + for (res = hp, count = 0; res; res = res->ai_next, count++) {
1060 + memcpy(&server_sin, res->ai_addr, res->ai_addrlen);
1062 for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
1063 memcpy((char *) &server_sin.sin_addr, addr,
1064 sizeof(server_sin.sin_addr));
1068 * Force evaluation of server host name and address. Host name
1069 @@ -194,7 +210,11 @@
1070 fprintf(stderr, "Please specify an address instead\n");
1079 request_set(&request, RQ_SERVER_NAME, server, 0);
1081 @@ -208,6 +228,18 @@
1082 tcpdmatch(&request);
1086 + memset(&hints, 0, sizeof(hints));
1087 + hints.ai_family = AF_INET6;
1088 + hints.ai_socktype = SOCK_STREAM;
1089 + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
1090 + if (getaddrinfo(client, NULL, &hints, &res) == 0) {
1091 + freeaddrinfo(res);
1092 + request_set(&request, RQ_CLIENT_ADDR, client, 0);
1093 + tcpdmatch(&request);
1099 * Perhaps they are testing special client hostname patterns that aren't
1100 @@ -229,6 +261,34 @@
1102 if ((hp = find_inet_addr(client)) == 0)
1105 + request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
1107 + for (res = hp, count = 0; res; res = res->ai_next, count++) {
1108 + memcpy(&client_sin, res->ai_addr, res->ai_addrlen);
1111 + * getnameinfo() doesn't do reverse lookup against link-local
1112 + * address. So, we pass through host name evaluation against
1115 + if (res->ai_family != AF_INET6 ||
1116 + !IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)) {
1118 + * Force evaluation of client host name and address. Host name
1119 + * conflicts will be reported while eval_hostname() does its job.
1121 + request_set(&request, RQ_CLIENT_NAME, "", RQ_CLIENT_ADDR, "", 0);
1122 + if (STR_EQ(eval_hostname(request.client), unknown))
1123 + tcpd_warn("host address %s->name lookup failed",
1124 + eval_hostaddr(request.client));
1126 + tcpdmatch(&request);
1132 memset((char *) &client_sin, 0, sizeof(client_sin));
1133 client_sin.sin_family = AF_INET;
1134 request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
1143 diff -ruN tcp_wrappers_7.6.orig/tli.c tcp_wrappers_7.6/tli.c
1144 --- tcp_wrappers_7.6.orig/tli.c 1997-03-21 19:27:26.000000000 +0100
1145 +++ tcp_wrappers_7.6/tli.c 2004-04-10 19:07:43.000000000 +0200
1147 void tli_host(request)
1148 struct request_info *request;
1151 + static struct sockaddr_storage client;
1152 + static struct sockaddr_storage server;
1154 static struct sockaddr_in client;
1155 static struct sockaddr_in server;
1159 * If we discover that we are using an IP transport, pretend we never
1162 tli_endpoints(request);
1163 if ((request->config = tli_transport(request->fd)) != 0
1165 + && (STR_EQ(request->config->nc_protofmly, "inet") ||
1166 + STR_EQ(request->config->nc_protofmly, "inet6"))) {
1168 && STR_EQ(request->config->nc_protofmly, "inet")) {
1170 if (request->client->unit != 0) {
1172 + client = *(struct sockaddr_storage *) request->client->unit->addr.buf;
1173 + request->client->sin = (struct sockaddr *) &client;
1175 client = *(struct sockaddr_in *) request->client->unit->addr.buf;
1176 request->client->sin = &client;
1179 if (request->server->unit != 0) {
1181 + server = *(struct sockaddr_storage *) request->server->unit->addr.buf;
1182 + request->server->sin = (struct sockaddr *) &server;
1184 server = *(struct sockaddr_in *) request->server->unit->addr.buf;
1185 request->server->sin = &server;
1188 tli_cleanup(request);
1189 sock_methods(request);
1190 @@ -187,7 +207,15 @@
1192 while (config = getnetconfig(handlep)) {
1193 if (stat(config->nc_device, &from_config) == 0) {
1194 +#ifdef NO_CLONE_DEVICE
1196 + * If the network devices are not cloned (as is the case for
1197 + * Solaris 8 Beta), we must compare the major device numbers.
1199 + if (major(from_config.st_rdev) == major(from_client.st_rdev))
1201 if (minor(from_config.st_rdev) == major(from_client.st_rdev))
1206 diff -ruN tcp_wrappers_7.6.orig/update.c tcp_wrappers_7.6/update.c
1207 --- tcp_wrappers_7.6.orig/update.c 1994-12-28 17:42:56.000000000 +0100
1208 +++ tcp_wrappers_7.6/update.c 2004-04-10 19:07:43.000000000 +0200
1210 request->fd = va_arg(ap, int);
1214 + request->client->sin = va_arg(ap, struct sockaddr *);
1216 request->client->sin = va_arg(ap, struct sockaddr_in *);
1221 + request->server->sin = va_arg(ap, struct sockaddr *);
1223 request->server->sin = va_arg(ap, struct sockaddr_in *);
1228 diff -ruN tcp_wrappers_7.6.orig/workarounds.c tcp_wrappers_7.6/workarounds.c
1229 --- tcp_wrappers_7.6.orig/workarounds.c 1996-03-19 16:22:26.000000000 +0100
1230 +++ tcp_wrappers_7.6/workarounds.c 2004-04-10 19:07:43.000000000 +0200
1231 @@ -166,11 +166,22 @@
1236 + struct sockaddr *sin = sa;
1238 struct sockaddr_in *sin = (struct sockaddr_in *) sa;
1241 if ((ret = getpeername(sock, sa, len)) >= 0
1243 + && ((sin->su_si.si_family == AF_INET6
1244 + && IN6_IS_ADDR_UNSPECIFIED(&sin->su_sin6.sin6_addr))
1245 + || (sin->su_si.si_family == AF_INET
1246 + && sin->su_sin.sin_addr.s_addr == 0))) {
1248 && sa->sa_family == AF_INET
1249 && sin->sin_addr.s_addr == 0) {