]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/tcp-wrappers/tcp-wrappers-7.6/10_usagi-ipv6
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / tcp-wrappers / tcp-wrappers-7.6 / 10_usagi-ipv6
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
4 @@ -11,6 +11,9 @@
5  
6  #include <sys/types.h>
7  #include <sys/param.h>
8 +#ifdef INET6
9 +#include <sys/socket.h>
10 +#endif
11  #include <netinet/in.h>
12  #include <netinet/in_systm.h>
13  #include <netinet/ip.h>
14 @@ -41,6 +44,22 @@
15      unsigned int opt;
16      int     optlen;
17      struct in_addr dummy;
18 +#ifdef INET6
19 +    struct sockaddr_storage ss;
20 +    int sslen;
21 +
22 +    /*
23 +     * check if this is AF_INET socket
24 +     * XXX IPv6 support?
25 +     */
26 +    sslen = sizeof(ss);
27 +    if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) {
28 +       syslog(LOG_ERR, "getpeername: %m");
29 +       clean_exit(request);
30 +    }
31 +    if (ss.ss_family != AF_INET)
32 +       return;
33 +#endif
34  
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
40 @@ -85,11 +85,18 @@
41  for daemon process names or for client user names.
42  .IP \(bu
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\'.
49  .IP \(bu
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\'.
56 +.IP \(bu
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
63 @@ -24,7 +24,13 @@
64  /* System libraries. */
65  
66  #include <sys/types.h>
67 +#ifdef INT32_T
68 +    typedef uint32_t u_int32_t;
69 +#endif
70  #include <sys/param.h>
71 +#ifdef INET6
72 +#include <sys/socket.h>
73 +#endif
74  #include <netinet/in.h>
75  #include <arpa/inet.h>
76  #include <stdio.h>
77 @@ -33,6 +39,9 @@
78  #include <errno.h>
79  #include <setjmp.h>
80  #include <string.h>
81 +#ifdef INET6
82 +#include <netdb.h>
83 +#endif
84  
85  extern char *fgets();
86  extern int errno;
87 @@ -82,6 +91,10 @@
88  static int host_match();
89  static int string_match();
90  static int masked_match();
91 +#ifdef INET6
92 +static int masked_match4();
93 +static int masked_match6();
94 +#endif
95  
96  /* Size of logical line buffer. */
97  
98 @@ -289,6 +302,13 @@
99  {
100      int     n;
101  
102 +#ifdef INET6
103 +    /* convert IPv4 mapped IPv6 address to IPv4 address */
104 +    if (STRN_EQ(string, "::ffff:", 7)
105 +      && dot_quad_addr(string + 7) != INADDR_NONE) {
106 +      string += 7;
107 +    }
108 +#endif    
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 */
116 +#ifdef INET6
117 +       struct addrinfo hints, *res;
118 +       struct sockaddr_in6 pat, addr;
119 +       int len, ret;
120 +       char ch;
121 +
122 +       len = strlen(tok);
123 +       if (*tok == '[' && tok[len - 1] == ']') {
124 +           ch = 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));
132 +               freeaddrinfo(res);
133 +           }
134 +           tok[len - 1] = ch;
135 +           if (ret != 0 || getaddrinfo(string, NULL, &hints, &res) != 0)
136 +               return NO;
137 +           memcpy(&addr, res->ai_addr, sizeof(addr));
138 +           freeaddrinfo(res);
139 +#ifdef NI_WITHSCOPEID
140 +           if (pat.sin6_scope_id != 0 &&
141 +               addr.sin6_scope_id != pat.sin6_scope_id)
142 +               return NO;
143 +#endif
144 +           return (!memcmp(&pat.sin6_addr, &addr.sin6_addr,
145 +                           sizeof(struct in6_addr)));
146 +           return (ret);
147 +       }
148 +#endif
149         return (STR_EQ(tok, string));
150      }
151  }
152  
153  /* masked_match - match address against netnumber/netmask */
154  
155 +#ifdef INET6
156  static int masked_match(net_tok, mask_tok, string)
157  char   *net_tok;
158  char   *mask_tok;
159  char   *string;
160  {
161 +    return (masked_match4(net_tok, mask_tok, string) ||
162 +           masked_match6(net_tok, mask_tok, string));
163 +}
164 +
165 +static int masked_match4(net_tok, mask_tok, string)
166 +#else
167 +static int masked_match(net_tok, mask_tok, string)
168 +#endif
169 +char   *net_tok;
170 +char   *mask_tok;
171 +char   *string;
172 +{
173 +#ifdef INET6
174 +    u_int32_t net;
175 +    u_int32_t mask;
176 +    u_int32_t addr;
177 +#else
178      unsigned long net;
179      unsigned long mask;
180      unsigned long addr;
181 +#endif
182  
183      /*
184       * Disallow forms other than dotted quad: the treatment that inet_addr()
185 @@ -329,12 +401,78 @@
186         return (NO);
187      if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
188         || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) {
189 +#ifndef INET6
190         tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
191 +#endif
192         return (NO);                            /* not tcpd_jump() */
193      }
194      return ((addr & mask) == net);
195  }
196  
197 +#ifdef INET6
198 +static int masked_match6(net_tok, mask_tok, string)
199 +char   *net_tok;
200 +char   *mask_tok;
201 +char   *string;
202 +{
203 +    struct addrinfo hints, *res;
204 +    struct sockaddr_in6 net, addr;
205 +    u_int32_t mask;
206 +    int len, mask_len, i = 0;
207 +    char ch;
208 +
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)
214 +       return NO;
215 +    memcpy(&addr, res->ai_addr, sizeof(addr));
216 +    freeaddrinfo(res);
217 +
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)
221 +           return (NO);
222 +       return ((*(u_int32_t *)&addr.sin6_addr.s6_addr[12] & mask) == *(u_int32_t *)&net.sin6_addr.s6_addr[12]);
223 +    }
224 +
225 +    /* match IPv6 address against netnumber/prefixlen */
226 +    len = strlen(net_tok);
227 +    if (*net_tok != '[' || net_tok[len - 1] != ']')
228 +       return NO;
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;
233 +       return NO;
234 +    }
235 +    memcpy(&net, res->ai_addr, sizeof(net));
236 +    freeaddrinfo(res);
237 +    net_tok[len - 1] = ch;
238 +    if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128)
239 +       return NO;
240 +
241 +#ifdef NI_WITHSCOPEID
242 +    if (net.sin6_scope_id != 0 && addr.sin6_scope_id != net.sin6_scope_id)
243 +       return NO;
244 +#endif
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))
249 +               return NO;
250 +           break;
251 +       }
252 +       if (*(u_int32_t *)&addr.sin6_addr.s6_addr[i] != *(u_int32_t *)&net.sin6_addr.s6_addr[i])
253 +           return NO;
254 +       i += 4;
255 +       mask_len -= 32;
256 +    }
257 +    return YES;
258 +}
259 +#endif /* INET6 */
260 +
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
267 @@ -21,7 +21,7 @@
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"
273         @echo " uts215 uxp"
274         @echo
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
278  
279  # Freebsd and linux by default have no NIS.
280 -386bsd netbsd bsdos:
281 +386bsd 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
285  
286  freebsd:
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" \
292 +       VSYSLOG= all
293 +
294 +netbsd:
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
298  
299  linux:
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
306 +
307 +gnu:
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
312  
313  # This is good for many SYSV+BSD hybrids with NIS, probably also for HP-UX 7.x.
314  hpux hpux8 hpux9 hpux10:
315 @@ -196,6 +210,13 @@
316         NETGROUP=-DNETGROUP AUX_OBJ=setenv.o TLI=-DTLI \
317         BUGS="$(BUGS) -DSOLARIS_24_GETHOSTBYNAME_BUG" all
318  
319 +# SunOS 5.8 is another SYSV4 variant, but has IPv6 support
320 +solaris8:
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
325 +
326  # Generic SYSV40
327  esix sysv4:
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
332 @@ -58,9 +58,31 @@
333  {
334      char   *cp;
335  
336 +#ifdef INET6
337 +    int bracket = 0;
338 +
339 +    for (cp = string; cp && *cp; cp++) {
340 +       switch (*cp) {
341 +       case '[':
342 +           bracket++;
343 +           break;
344 +       case ']':
345 +           bracket--;
346 +           break;
347 +       default:
348 +           if (bracket == 0 && *cp == delimiter) {
349 +               *cp++ = 0;
350 +               return cp;
351 +           }
352 +           break;
353 +       }
354 +    }
355 +    return (NULL);
356 +#else
357      if ((cp = strchr(string, delimiter)) != 0)
358         *cp++ = 0;
359      return (cp);
360 +#endif
361  }
362  
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
367 @@ -25,7 +25,12 @@
368  void    refuse(request)
369  struct request_info *request;
370  {
371 +#ifdef INET6
372 +    syslog(deny_severity, "refused connect from %s (%s)",
373 +          eval_client(request), eval_hostaddr(request->client));
374 +#else
375      syslog(deny_severity, "refused connect from %s", eval_client(request));
376 +#endif
377      clean_exit(request);
378      /* NOTREACHED */
379  }
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
383 @@ -68,20 +68,50 @@
384  /* rfc931 - return remote user name, given socket structures */
385  
386  void    rfc931(rmt_sin, our_sin, dest)
387 +#ifdef INET6
388 +struct sockaddr *rmt_sin;
389 +struct sockaddr *our_sin;
390 +#else
391  struct sockaddr_in *rmt_sin;
392  struct sockaddr_in *our_sin;
393 +#endif
394  char   *dest;
395  {
396      unsigned rmt_port;
397      unsigned our_port;
398 +#ifdef INET6
399 +    struct sockaddr_storage rmt_query_sin;
400 +    struct sockaddr_storage our_query_sin;
401 +    int alen;
402 +#else
403      struct sockaddr_in rmt_query_sin;
404      struct sockaddr_in our_query_sin;
405 +#endif
406      char    user[256];                 /* XXX */
407      char    buffer[512];               /* XXX */
408      char   *cp;
409      char   *result = unknown;
410      FILE   *fp;
411  
412 +#ifdef INET6
413 +    /* address family must be the same */
414 +    if (rmt_sin->sa_family != our_sin->sa_family) {
415 +       STRN_CPY(dest, result, STRING_LENGTH);
416 +       return;
417 +    }
418 +    switch (our_sin->sa_family) {
419 +    case AF_INET:
420 +       alen = sizeof(struct sockaddr_in);
421 +       break;
422 +    case AF_INET6:
423 +       alen = sizeof(struct sockaddr_in6);
424 +       break;
425 +    default:
426 +       STRN_CPY(dest, result, STRING_LENGTH);
427 +       return;
428 +    }
429 +#endif
430 +
431      /*
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
434 @@ -92,7 +122,11 @@
435       * sockets.
436       */
437  
438 +#ifdef INET6
439 +    if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) {
440 +#else
441      if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
442 +#endif
443         setbuf(fp, (char *) 0);
444  
445         /*
446 @@ -112,6 +146,25 @@
447              * addresses from the query socket.
448              */
449  
450 +#ifdef INET6
451 +           memcpy(&our_query_sin, our_sin, alen);
452 +           memcpy(&rmt_query_sin, rmt_sin, alen);
453 +           switch (our_sin->sa_family) {
454 +           case AF_INET:
455 +               ((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT);
456 +               ((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC931_PORT);
457 +               break;
458 +           case AF_INET6:
459 +               ((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT);
460 +               ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC931_PORT);
461 +               break;
462 +           }
463 +
464 +           if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
465 +                    alen) >= 0 &&
466 +               connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
467 +                       alen) >= 0) {
468 +#else
469             our_query_sin = *our_sin;
470             our_query_sin.sin_port = htons(ANY_PORT);
471             rmt_query_sin = *rmt_sin;
472 @@ -121,6 +174,7 @@
473                      sizeof(our_query_sin)) >= 0 &&
474                 connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
475                         sizeof(rmt_query_sin)) >= 0) {
476 +#endif
477  
478                 /*
479                  * Send query to server. Neglect the risk that a 13-byte
480 @@ -129,8 +183,13 @@
481                  */
482  
483                 fprintf(fp, "%u,%u\r\n",
484 +#ifdef INET6
485 +                       ntohs(((struct sockaddr_in *)rmt_sin)->sin_port),
486 +                       ntohs(((struct sockaddr_in *)our_sin)->sin_port));
487 +#else
488                         ntohs(rmt_sin->sin_port),
489                         ntohs(our_sin->sin_port));
490 +#endif
491                 fflush(fp);
492  
493                 /*
494 @@ -144,8 +203,13 @@
495                     && ferror(fp) == 0 && feof(fp) == 0
496                     && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
497                               &rmt_port, &our_port, user) == 3
498 +#ifdef INET6
499 +                   && ntohs(((struct sockaddr_in *)rmt_sin)->sin_port) == rmt_port
500 +                   && ntohs(((struct sockaddr_in *)our_sin)->sin_port) == our_port) {
501 +#else
502                     && ntohs(rmt_sin->sin_port) == rmt_port
503                     && ntohs(our_sin->sin_port) == our_port) {
504 +#endif
505  
506                     /*
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
511 @@ -25,7 +25,9 @@
512  #define        INADDR_NONE     (-1)            /* XXX should be 0xffffffff */
513  #endif
514  
515 +#ifndef INET6
516  extern char *malloc();
517 +#endif
518  
519  /* Application-specific. */
520  
521 @@ -39,6 +41,7 @@
522  int     deny_severity = LOG_WARNING;
523  int     rfc931_timeout = RFC931_TIMEOUT;
524  
525 +#ifndef INET6
526  /* dup_hostent - create hostent in one memory block */
527  
528  static struct hostent *dup_hostent(hp)
529 @@ -73,9 +76,46 @@
530      }
531      return (&hb->host);
532  }
533 +#endif
534  
535  /* find_inet_addr - find all addresses for this host, result to free() */
536  
537 +#ifdef INET6
538 +struct addrinfo *find_inet_addr(host)
539 +char   *host;
540 +{
541 +    struct addrinfo hints, *res;
542 +
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)
548 +       return (res);
549 +
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);
556 +       return (0);
557 +    }
558 +    if (res->ai_family != AF_INET6 && res->ai_family != AF_INET) {
559 +       tcpd_warn("%d: not an internet host", res->ai_family);
560 +       freeaddrinfo(res);
561 +       return (0);
562 +    }
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);
569 +    }
570 +    return (res);
571 +}
572 +#else
573  struct hostent *find_inet_addr(host)
574  char   *host;
575  {
576 @@ -118,6 +158,7 @@
577      }
578      return (dup_hostent(hp));
579  }
580 +#endif
581  
582  /* check_dns - give each address thorough workout, return address count */
583  
584 @@ -125,8 +166,13 @@
585  char   *host;
586  {
587      struct request_info request;
588 +#ifdef INET6
589 +    struct sockaddr_storage sin;
590 +    struct addrinfo *hp, *res;
591 +#else
592      struct sockaddr_in sin;
593      struct hostent *hp;
594 +#endif
595      int     count;
596      char   *addr;
597  
598 @@ -134,11 +180,18 @@
599         return (0);
600      request_init(&request, RQ_CLIENT_SIN, &sin, 0);
601      sock_methods(&request);
602 +#ifndef INET6
603      memset((char *) &sin, 0, sizeof(sin));
604      sin.sin_family = AF_INET;
605 +#endif
606  
607 +#ifdef INET6
608 +    for (res = hp, count = 0; res; res = res->ai_next, count++) {
609 +       memcpy(&sin, res->ai_addr, res->ai_addrlen);
610 +#else
611      for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
612         memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr));
613 +#endif
614  
615         /*
616          * Force host name and address conversions. Use the request structure
617 @@ -151,7 +204,11 @@
618             tcpd_warn("host address %s->name lookup failed",
619                       eval_hostaddr(request.client));
620      }
621 +#ifdef INET6
622 +    freeaddrinfo(hp);
623 +#else
624      free((char *) hp);
625 +#endif
626      return (count);
627  }
628  
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
632 @@ -4,6 +4,10 @@
633    * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
634    */
635  
636 +#ifdef INET6
637 +extern struct addrinfo *find_inet_addr();
638 +#else
639  extern struct hostent *find_inet_addr();
640 +#endif
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
646 @@ -24,13 +24,22 @@
647  #include <sys/types.h>
648  #include <sys/param.h>
649  #include <sys/socket.h>
650 +#ifdef INT32_T
651 +typedef uint32_t u_int32_t;
652 +#endif
653  #include <netinet/in.h>
654  #include <netdb.h>
655  #include <stdio.h>
656  #include <syslog.h>
657  #include <string.h>
658  
659 +#ifdef INET6
660 +#ifndef NI_WITHSCOPEID
661 +#define NI_WITHSCOPEID 0
662 +#endif
663 +#else
664  extern char *inet_ntoa();
665 +#endif
666  
667  /* Local stuff. */
668  
669 @@ -79,8 +88,13 @@
670  void    sock_host(request)
671  struct request_info *request;
672  {
673 +#ifdef INET6
674 +    static struct sockaddr_storage client;
675 +    static struct sockaddr_storage server;
676 +#else
677      static struct sockaddr_in client;
678      static struct sockaddr_in server;
679 +#endif
680      int     len;
681      char    buf[BUFSIZ];
682      int     fd = request->fd;
683 @@ -109,7 +123,11 @@
684         memset(buf, 0 sizeof(buf));
685  #endif
686      }
687 +#ifdef INET6
688 +    request->client->sin = (struct sockaddr *)&client;
689 +#else
690      request->client->sin = &client;
691 +#endif
692  
693      /*
694       * Determine the server binding. This is used for client username
695 @@ -122,7 +140,11 @@
696         tcpd_warn("getsockname: %m");
697         return;
698      }
699 +#ifdef INET6
700 +    request->server->sin = (struct sockaddr *)&server;
701 +#else
702      request->server->sin = &server;
703 +#endif
704  }
705  
706  /* sock_hostaddr - map endpoint address to printable form */
707 @@ -130,10 +152,26 @@
708  void    sock_hostaddr(host)
709  struct host_info *host;
710  {
711 +#ifdef INET6
712 +    struct sockaddr *sin = host->sin;
713 +    int salen;
714 +
715 +    if (!sin)
716 +       return;
717 +#ifdef SIN6_LEN
718 +    salen = sin->sa_len;
719 +#else
720 +    salen = (sin->sa_family == AF_INET) ? sizeof(struct sockaddr_in)
721 +                                       : sizeof(struct sockaddr_in6);
722 +#endif
723 +    getnameinfo(sin, salen, host->addr, sizeof(host->addr),
724 +               NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
725 +#else
726      struct sockaddr_in *sin = host->sin;
727  
728      if (sin != 0)
729         STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
730 +#endif
731  }
732  
733  /* sock_hostname - map endpoint address to host name */
734 @@ -141,6 +179,160 @@
735  void    sock_hostname(host)
736  struct host_info *host;
737  {
738 +#ifdef INET6
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];
744 +
745 +    if (sin != NULL) {
746 +       if (sin->sa_family == AF_INET6) {
747 +           struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sin;
748 +
749 +           if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
750 +               memset(&sin4, 0, sizeof(sin4));
751 +#ifdef SIN6_LEN
752 +               sin4.sin_len = sizeof(sin4);
753 +#endif
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;
758 +           }
759 +       }
760 +       switch (sin->sa_family) {
761 +       case AF_INET:
762 +           ap = (char *)&((struct sockaddr_in *)sin)->sin_addr;
763 +           alen = sizeof(struct in_addr);
764 +           salen = sizeof(struct sockaddr_in);
765 +           break;
766 +       case AF_INET6:
767 +           ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr;
768 +           alen = sizeof(struct in6_addr);
769 +           salen = sizeof(struct sockaddr_in6);
770 +           break;
771 +       default:
772 +           break;
773 +       }
774 +       if (ap)
775 +           err = getnameinfo(sin, salen, hname, sizeof(hname),
776 +                             NULL, 0, NI_WITHSCOPEID | NI_NAMEREQD);
777 +    }
778 +    if (!err) {
779 +
780 +       STRN_CPY(host->name, hname, sizeof(host->name));
781 +
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);
789 +           res0 = NULL;
790 +           tcpd_warn("host name/name mismatch: "
791 +                     "reverse lookup results in non-FQDN %s",
792 +                     host->name);
793 +           strcpy(host->name, paranoid);       /* name is bad, clobber it */
794 +       }
795 +       err = !err;
796 +    }
797 +    if (!err) {
798 +       /* we are now sure that this is non-numeric */
799 +
800 +       /*
801 +        * Verify that the address is a member of the address list returned
802 +        * by gethostbyname(hostname).
803 +        * 
804 +        * Verify also that gethostbyaddr() and gethostbyname() return the same
805 +        * hostname, or rshd and rlogind may still end up being spoofed.
806 +        * 
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.
811 +        */
812 +
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) {
818 +
819 +           /*
820 +            * Unable to verify that the host name matches the address. This
821 +            * may be a transient problem or a botched name server setup.
822 +            */
823 +
824 +           tcpd_warn("can't verify hostname: getaddrinfo(%s, %s) failed",
825 +                     host->name,
826 +                     (sin->sa_family == AF_INET) ? "AF_INET" : "AF_INET6");
827 +
828 +       } else if ((res0->ai_canonname == NULL
829 +                   || STR_NE(host->name, res0->ai_canonname))
830 +                  && STR_NE(host->name, "localhost")) {
831 +
832 +           /*
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.
836 +            */
837 +
838 +           tcpd_warn("host name/name mismatch: %s != %.*s",
839 +                     host->name, STRING_LENGTH,
840 +                     (res0->ai_canonname == NULL) ? "" : res0->ai_canonname);
841 +
842 +       } else {
843 +
844 +           /*
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.
849 +            */
850 +
851 +           for (res = res0; res; res = res->ai_next) {
852 +               if (res->ai_family != sin->sa_family)
853 +                   continue;
854 +               switch (res->ai_family) {
855 +               case AF_INET:
856 +                   rap = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr;
857 +                   break;
858 +               case AF_INET6:
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) {
862 +                       continue;
863 +                   }
864 +                   rap = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
865 +                   break;
866 +               default:
867 +                   continue;
868 +               }
869 +               if (memcmp(rap, ap, alen) == 0) {
870 +                   freeaddrinfo(res0);
871 +                   return;                     /* name is good, keep it */
872 +               }
873 +           }
874 +
875 +           /*
876 +            * The host name does not map to the initial address. Perhaps
877 +            * someone has messed up. Perhaps someone compromised a name
878 +            * server.
879 +            */
880 +
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);
886 +       }
887 +       strcpy(host->name, paranoid);           /* name is bad, clobber it */
888 +       if (res0)
889 +           freeaddrinfo(res0);
890 +    }
891 +#else /* INET6 */
892      struct sockaddr_in *sin = host->sin;
893      struct hostent *hp;
894      int     i;
895 @@ -220,6 +412,7 @@
896         }
897         strcpy(host->name, paranoid);           /* name is bad, clobber it */
898      }
899 +#endif /* INET6 */
900  }
901  
902  /* sock_sink - absorb unreceived IP datagram */
903 @@ -228,7 +421,11 @@
904  int     fd;
905  {
906      char    buf[BUFSIZ];
907 +#ifdef INET6
908 +    struct sockaddr_storage sin;
909 +#else
910      struct sockaddr_in sin;
911 +#endif
912      int     size = sizeof(sin);
913  
914      /*
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
918 @@ -120,7 +120,12 @@
919  
920      /* Report request and invoke the real daemon program. */
921  
922 +#ifdef INET6
923 +    syslog(allow_severity, "connect from %s (%s)",
924 +          eval_client(&request), eval_hostaddr(request.client));
925 +#else
926      syslog(allow_severity, "connect from %s", eval_client(&request));
927 +#endif
928      closelog();
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
934 @@ -22,6 +22,9 @@
935  
936  #include <sys/types.h>
937  #include <sys/stat.h>
938 +#ifdef INET6
939 +#include <sys/socket.h>
940 +#endif
941  #include <netinet/in.h>
942  #include <arpa/inet.h>
943  #include <stdio.h>
944 @@ -397,6 +400,31 @@
945      }
946  }
947  
948 +#ifdef INET6
949 +static int is_inet6_addr(pat)
950 +    char *pat;
951 +{
952 +    struct addrinfo hints, *res;
953 +    int len, ret;
954 +    char ch;
955 +
956 +    if (*pat != '[')
957 +       return (0);
958 +    len = strlen(pat);
959 +    if ((ch = pat[len - 1]) != ']')
960 +       return (0);
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)
967 +       freeaddrinfo(res);
968 +    pat[len - 1] = ch;
969 +    return (ret == 0);
970 +}
971 +#endif
972 +
973  /* check_host - criticize host pattern */
974  
975  static int check_host(pat)
976 @@ -423,14 +451,27 @@
977  #endif
978  #endif
979      } else if (mask = split_at(pat, '/')) {    /* network/netmask */
980 +#ifdef INET6
981 +       int mask_len;
982 +
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)))
987 +#else
988         if (dot_quad_addr(pat) == INADDR_NONE
989             || dot_quad_addr(mask) == INADDR_NONE)
990 +#endif
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 */
996          /* void */ ;
997 +#ifdef INET6
998 +    } else if (is_inet6_addr(pat)) { /* IPv6 address */
999 +       addr_count = 1;
1000 +#endif
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
1007 @@ -11,7 +11,11 @@
1008  struct host_info {
1009      char    name[STRING_LENGTH];       /* access via eval_hostname(host) */
1010      char    addr[STRING_LENGTH];       /* access via eval_hostaddr(host) */
1011 +#ifdef INET6
1012 +    struct sockaddr *sin;              /* socket address or 0 */
1013 +#else
1014      struct sockaddr_in *sin;           /* socket address or 0 */
1015 +#endif
1016      struct t_unitdata *unit;           /* TLI transport address or 0 */
1017      struct request_info *request;      /* for shared information */
1018  };
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
1022 @@ -57,7 +57,11 @@
1023  int     argc;
1024  char  **argv;
1025  {
1026 +#ifdef INET6
1027 +    struct addrinfo hints, *hp, *res;
1028 +#else
1029      struct hostent *hp;
1030 +#endif
1031      char   *myname = argv[0];
1032      char   *client;
1033      char   *server;
1034 @@ -68,8 +72,13 @@
1035      int     ch;
1036      char   *inetcf = 0;
1037      int     count;
1038 +#ifdef INET6
1039 +    struct sockaddr_storage server_sin;
1040 +    struct sockaddr_storage client_sin;
1041 +#else
1042      struct sockaddr_in server_sin;
1043      struct sockaddr_in client_sin;
1044 +#endif
1045      struct stat st;
1046  
1047      /*
1048 @@ -172,13 +181,20 @@
1049      if (NOT_INADDR(server) == 0 || HOSTNAME_KNOWN(server)) {
1050         if ((hp = find_inet_addr(server)) == 0)
1051             exit(1);
1052 +#ifndef INET6
1053         memset((char *) &server_sin, 0, sizeof(server_sin));
1054         server_sin.sin_family = AF_INET;
1055 +#endif
1056         request_set(&request, RQ_SERVER_SIN, &server_sin, 0);
1057  
1058 +#ifdef INET6
1059 +       for (res = hp, count = 0; res; res = res->ai_next, count++) {
1060 +           memcpy(&server_sin, res->ai_addr, res->ai_addrlen);
1061 +#else
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));
1065 +#endif
1066  
1067             /*
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");
1071             exit(1);
1072         }
1073 +#ifdef INET6
1074 +       freeaddrinfo(hp);
1075 +#else
1076         free((char *) hp);
1077 +#endif
1078      } else {
1079         request_set(&request, RQ_SERVER_NAME, server, 0);
1080      }
1081 @@ -208,6 +228,18 @@
1082         tcpdmatch(&request);
1083         exit(0);
1084      }
1085 +#ifdef INET6
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);
1094 +       exit(0);
1095 +    }
1096 +#endif
1097  
1098      /*
1099       * Perhaps they are testing special client hostname patterns that aren't
1100 @@ -229,6 +261,34 @@
1101       */
1102      if ((hp = find_inet_addr(client)) == 0)
1103         exit(1);
1104 +#ifdef INET6
1105 +    request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
1106 +
1107 +    for (res = hp, count = 0; res; res = res->ai_next, count++) {
1108 +       memcpy(&client_sin, res->ai_addr, res->ai_addrlen);
1109 +
1110 +       /*
1111 +        * getnameinfo() doesn't do reverse lookup against link-local
1112 +        * address.  So, we pass through host name evaluation against
1113 +        * such addresses.
1114 +        */
1115 +       if (res->ai_family != AF_INET6 ||
1116 +           !IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)) {
1117 +           /*
1118 +            * Force evaluation of client host name and address. Host name
1119 +            * conflicts will be reported while eval_hostname() does its job.
1120 +            */
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));
1125 +       }
1126 +       tcpdmatch(&request);
1127 +       if (res->ai_next)
1128 +           printf("\n");
1129 +    }
1130 +    freeaddrinfo(hp);
1131 +#else
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);
1135 @@ -250,6 +310,7 @@
1136             printf("\n");
1137      }
1138      free((char *) hp);
1139 +#endif
1140      exit(0);
1141  }
1142  
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
1146 @@ -65,8 +65,13 @@
1147  void    tli_host(request)
1148  struct request_info *request;
1149  {
1150 +#ifdef INET6
1151 +    static struct sockaddr_storage client;
1152 +    static struct sockaddr_storage server;
1153 +#else
1154      static struct sockaddr_in client;
1155      static struct sockaddr_in server;
1156 +#endif
1157  
1158      /*
1159       * If we discover that we are using an IP transport, pretend we never
1160 @@ -76,14 +81,29 @@
1161  
1162      tli_endpoints(request);
1163      if ((request->config = tli_transport(request->fd)) != 0
1164 +#ifdef INET6
1165 +       && (STR_EQ(request->config->nc_protofmly, "inet") ||
1166 +           STR_EQ(request->config->nc_protofmly, "inet6"))) {
1167 +#else
1168         && STR_EQ(request->config->nc_protofmly, "inet")) {
1169 +#endif
1170         if (request->client->unit != 0) {
1171 +#ifdef INET6
1172 +           client = *(struct sockaddr_storage *) request->client->unit->addr.buf;
1173 +           request->client->sin = (struct sockaddr *) &client;
1174 +#else
1175             client = *(struct sockaddr_in *) request->client->unit->addr.buf;
1176             request->client->sin = &client;
1177 +#endif
1178         }
1179         if (request->server->unit != 0) {
1180 +#ifdef INET6
1181 +           server = *(struct sockaddr_storage *) request->server->unit->addr.buf;
1182 +           request->server->sin = (struct sockaddr *) &server;
1183 +#else
1184             server = *(struct sockaddr_in *) request->server->unit->addr.buf;
1185             request->server->sin = &server;
1186 +#endif
1187         }
1188         tli_cleanup(request);
1189         sock_methods(request);
1190 @@ -187,7 +207,15 @@
1191      }
1192      while (config = getnetconfig(handlep)) {
1193         if (stat(config->nc_device, &from_config) == 0) {
1194 +#ifdef NO_CLONE_DEVICE
1195 +       /*
1196 +        * If the network devices are not cloned (as is the case for
1197 +        * Solaris 8 Beta), we must compare the major device numbers.
1198 +        */
1199 +           if (major(from_config.st_rdev) == major(from_client.st_rdev))
1200 +#else
1201             if (minor(from_config.st_rdev) == major(from_client.st_rdev))
1202 +#endif
1203                 break;
1204         }
1205      }
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
1209 @@ -46,10 +46,18 @@
1210             request->fd = va_arg(ap, int);
1211             continue;
1212         case RQ_CLIENT_SIN:
1213 +#ifdef INET6
1214 +           request->client->sin = va_arg(ap, struct sockaddr *);
1215 +#else
1216             request->client->sin = va_arg(ap, struct sockaddr_in *);
1217 +#endif
1218             continue;
1219         case RQ_SERVER_SIN:
1220 +#ifdef INET6
1221 +           request->server->sin = va_arg(ap, struct sockaddr *);
1222 +#else
1223             request->server->sin = va_arg(ap, struct sockaddr_in *);
1224 +#endif
1225             continue;
1226  
1227             /*
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 @@
1232  int    *len;
1233  {
1234      int     ret;
1235 +#ifdef INET6
1236 +    struct sockaddr *sin = sa;
1237 +#else
1238      struct sockaddr_in *sin = (struct sockaddr_in *) sa;
1239 +#endif
1240  
1241      if ((ret = getpeername(sock, sa, len)) >= 0
1242 +#ifdef INET6
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))) {
1247 +#else
1248         && sa->sa_family == AF_INET
1249         && sin->sin_addr.s_addr == 0) {
1250 +#endif
1251         errno = ENOTCONN;
1252         return (-1);
1253      } else {