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