]> git.pld-linux.org Git - packages/postfix.git/blob - postfix-ipv6.patch
- fixes in v6 patch:
[packages/postfix.git] / postfix-ipv6.patch
1 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/IPV6_README snapshot-20010525/IPV6_README
2 --- snapshot-20010525.noipv6/IPV6_README        Thu Jan  1 01:00:00 1970
3 +++ snapshot-20010525/IPV6_README       Tue May 29 18:23:16 2001
4 @@ -0,0 +1,33 @@
5 +$Id$
6 +
7 +                   ALPHA IPv6 patch for Postfix.
8 +
9 +       You can use IPv6 addresses in configuration file but
10 +you must enclose them with [] for example: [3ffe:902:12::10].
11 +
12 +Probably not all things work properly, yet.
13 +
14 + INFO:
15 +  - all previous versions of this patch (dated before 15 January
16 +  2000) was against postfix-19991231-pl02 with pfixtls patch
17 +  applied (see ftp://ftp.aet.tu-cottbus.de/pub/pfixtls/ for more).
18 +  All newer patches are created against clean postfix version.
19 +
20 + BUGS && PROBLEMS:
21 + - getaddrinfo call in smtp_addr_one() function doesn't always
22 +   return proper ai_addr structure (fixed).
23 + - lmtp code isn't IPv6 ready (not fixed).
24 +
25 +Please send all comments and patches to:
26 +           Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>, PLD GNU/Linux
27 +           Artur Frysiak <wiget@pld.org.pl>, PLD GNU/Linux
28 +
29 +Newest version of this patch can be found at:
30 +           http://www.misiek.eu.org/ipv6/
31 +
32 +Thanks to:
33 +- Mark Huizer <xaa@timewasters.nl>
34 +       author of first IPv6 patch for postfix
35 +- KAME Team <core@kame.net>
36 +       fixes to Mark's patch
37 +diff -ruN --exclude *.orig --exclude *~ snapshot-20010329.noipv6/makedefs snapshot-20010329/makedefs
38 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/makedefs snapshot-20010525/makedefs
39 --- snapshot-20010525.noipv6/makedefs   Tue May  1 01:16:07 2001
40 +++ snapshot-20010525/makedefs  Tue May 29 18:23:16 2001
41 @@ -52,6 +52,21 @@
42  SYSTEM=`(uname -s) 2>/dev/null`
43  RELEASE=`(uname -r) 2>/dev/null`
44  VERSION=`(uname -v) 2>/dev/null`
45 +if test -f /usr/include/netinet6/in6.h; then
46 +       grep __KAME__ /usr/include/netinet6/in6.h 2>&1 >/dev/null
47 +       if [ $?  = 1 ]; then
48 +               INET6=
49 +       else
50 +               if [ -f /usr/local/v6/lib/libinet6.a ]; then
51 +                       INET6=kame
52 +               else
53 +                       INET6=kame-merged
54 +               fi
55 +       fi
56 +fi
57 +if [ -z "$INET6" -a -f /usr/include/netinet/ip6.h -a -f /usr/include/linux/icmpv6.h ]; then
58 +       INET6=linux
59 +fi
60  
61  case "$VERSION" in
62   dcosx*) SYSTEM=$VERSION;;
63 @@ -275,6 +290,26 @@
64  esac
65  
66  : ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk}
67 +
68 +case "$INET6" in
69 +kame)
70 +       CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family -D__ss_len=ss_len"
71 +       if test -f /usr/local/v6/lib/libinet6.a; then
72 +               SYSLIBS="$SYSLIBS -L/usr/local/v6/lib -linet6"
73 +       fi
74 +       ;;
75 +kame-merged)
76 +       CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family -D__ss_len=ss_len"
77 +       ;;
78 +linux)
79 +       CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family"
80 +       if test -f /usr/include/libinet6/netinet/ip6.h -a \
81 +               -f /usr/lib/libinet6.a; then 
82 +               CCARGS="$CCARGS -I/usr/include/libinet6 -DUSAGI_LIBINET6"
83 +               SYSLIBS="$SYSLIBS -linet6"
84 +       fi
85 +       ;;
86 +esac
87  
88  export SYSTYPE AR ARFL RANLIB SYSLIBS CC OPT DEBUG AWK OPTS
89  
90 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/dns/dns_lookup.c snapshot-20010525/src/dns/dns_lookup.c
91 --- snapshot-20010525.noipv6/src/dns/dns_lookup.c       Sun Feb  4 19:16:20 2001
92 +++ snapshot-20010525/src/dns/dns_lookup.c      Tue May 29 18:23:16 2001
93 @@ -132,6 +132,9 @@
94  } DNS_REPLY;
95  
96  #define INET_ADDR_LEN  4               /* XXX */
97 +#ifdef INET6
98 +#define INET6_ADDR_LEN 16
99 +#endif
100  
101  /* dns_query - query name server and pre-parse the reply */
102  
103 @@ -337,6 +340,19 @@
104         memcpy(temp, pos, fixed->length);
105         data_len = fixed->length;
106         break;
107 +#ifdef INET6
108 +    case T_AAAA:
109 +       if (fixed->length != INET6_ADDR_LEN) {
110 +           msg_warn("extract_answer: bad IPv6 address length: %d", fixed->length);
111 +           return (0);
112 +       }
113 +       if (fixed->length > sizeof(temp))
114 +           msg_panic("dns_get_rr: length %d > DNS_NAME_LEN",
115 +                     fixed->length);
116 +       memcpy(temp, pos, fixed->length);
117 +       data_len = fixed->length;
118 +       break;
119 +#endif
120      case T_TXT:
121         data_len = MIN2(pos[0] + 1, MIN2(fixed->length + 1, sizeof(temp)));
122         for (src = pos + 1, dst = (unsigned char *) (temp);
123 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/global/Makefile.in snapshot-20010525/src/global/Makefile.in
124 --- snapshot-20010525.noipv6/src/global/Makefile.in     Tue May 29 16:03:38 2001
125 +++ snapshot-20010525/src/global/Makefile.in    Tue May 29 18:23:16 2001
126 @@ -19,7 +19,7 @@
127         timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \
128         tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \
129         flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \
130 -       pfixtls.c
131 +       pfixtls.c wildcard_inet_addr.c
132  OBJS   = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
133         debug_peer.o debug_process.o defer.o deliver_completed.o \
134         deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \
135 @@ -40,7 +40,7 @@
136         timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \
137         tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \
138         flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \
139 -       pfixtls.o
140 +       pfixtls.o wildcard_inet_addr.o
141  HDRS   = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
142         config.h debug_peer.h debug_process.h defer.h deliver_completed.h \
143         deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \
144 @@ -56,7 +56,7 @@
145         recipient_list.h record.h resolve_clnt.h resolve_local.h \
146         rewrite_clnt.h sent.h smtp_stream.h split_addr.h string_list.h \
147         sys_exits.h timed_ipc.h tok822.h xtext.h bounce_log.h flush_clnt.h \
148 -       mbox_conf.h mbox_open.h abounce.h pfixtls.h
149 +       mbox_conf.h mbox_open.h abounce.h pfixtls.h wildcard_inet_addr.h
150  TESTSRC        = rec2stream.c stream2rec.c recdump.c
151  WARN   = -W -Wformat -Wimplicit -Wmissing-prototypes \
152         -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized \
153 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/global/mynetworks.c snapshot-20010525/src/global/mynetworks.c
154 --- snapshot-20010525.noipv6/src/global/mynetworks.c    Sun Feb 25 02:46:07 2001
155 +++ snapshot-20010525/src/global/mynetworks.c   Tue May 29 18:23:16 2001
156 @@ -50,6 +50,11 @@
157  #include <vstring.h>
158  #include <inet_addr_list.h>
159  #include <name_mask.h>
160 +#ifdef INET6
161 +#include <sys/socket.h>
162 +#include <netinet/in.h>
163 +#include <netdb.h>
164 +#endif
165  
166  /* Global library. */
167  
168 @@ -75,6 +80,9 @@
169  const char *mynetworks(void)
170  {
171      static VSTRING *result;
172 +#ifdef INET6
173 +    char hbuf[NI_MAXHOST];
174 +#endif
175  
176      if (result == 0) {
177         char   *myname = "mynetworks";
178 @@ -87,6 +95,9 @@
179         int     junk;
180         int     i;
181         int     mask_style;
182 +#ifdef INET6
183 +       struct sockaddr *sa;
184 +#endif
185  
186         mask_style = name_mask("mynetworks mask style", mask_styles,
187                                var_mynetworks_style);
188 @@ -96,8 +107,18 @@
189         my_mask_list = own_inet_mask_list();
190  
191         for (i = 0; i < my_addr_list->used; i++) {
192 +#ifdef INET6
193 +           sa = (struct sockaddr *)&my_addr_list->addrs[i];
194 +           if (sa->sa_family != AF_INET) {
195 +               vstring_sprintf_append(result, "XAATODOmynetworks ");
196 +               continue;
197 +           }
198 +           addr = ntohl(((struct sockaddr_in *)sa)->sin_addr.s_addr);
199 +           mask = ntohl(((struct sockaddr_in *)&my_mask_list->addrs[i])->sin_addr.s_addr);
200 +#else
201             addr = ntohl(my_addr_list->addrs[i].s_addr);
202             mask = ntohl(my_mask_list->addrs[i].s_addr);
203 +#endif
204  
205             switch (mask_style) {
206  
207 @@ -119,8 +140,15 @@
208                     mask = IN_CLASSD_NET;
209                     shift = IN_CLASSD_NSHIFT;
210                 } else {
211 +#ifdef INET6
212 +                   if (getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf), NULL, 0,
213 +                           NI_NUMERICHOST))
214 +                       strncpy(hbuf, "???", sizeof(hbuf));
215 +                   msg_fatal("%s: bad address class: %s", myname, hbuf);
216 +#else
217                     msg_fatal("%s: bad address class: %s",
218                               myname, inet_ntoa(my_addr_list->addrs[i]));
219 +#endif
220                 }
221                 break;
222  
223 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/global/own_inet_addr.c snapshot-20010525/src/global/own_inet_addr.c
224 --- snapshot-20010525.noipv6/src/global/own_inet_addr.c Sun Feb 25 02:51:39 2001
225 +++ snapshot-20010525/src/global/own_inet_addr.c        Tue May 29 18:23:16 2001
226 @@ -39,6 +39,10 @@
227  #include <netinet/in.h>
228  #include <arpa/inet.h>
229  #include <string.h>
230 +#ifdef INET6
231 +#include <sys/socket.h>
232 +#include <netdb.h>
233 +#endif
234  
235  #ifdef STRCASECMP_IN_STRINGS_H
236  #include <strings.h>
237 @@ -101,10 +105,11 @@
238       */
239      else {
240         bufp = hosts = mystrdup(var_inet_interfaces);
241 -       while ((host = mystrtok(&bufp, sep)) != 0)
242 +       while ((host = mystrtok(&bufp, sep)) != 0) {
243             if (inet_addr_host(addr_list, host) == 0)
244                 msg_fatal("config variable %s: host not found: %s",
245                           VAR_INET_INTERFACES, host);
246 +       }
247         myfree(hosts);
248  
249         inet_addr_list_init(&local_addrs);
250 @@ -113,15 +118,39 @@
251             msg_fatal("could not find any active network interfaces");
252         for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) {
253             for (nlocal = 0; /* see below */ ; nlocal++) {
254 -               if (nlocal >= local_addrs.used)
255 +               if (nlocal >= local_addrs.used) {
256 +#ifdef INET6
257 +                   char hbuf[NI_MAXHOST];
258 +                   if (getnameinfo((struct sockaddr *)&addr_list->addrs[nvirtual],
259 +                       SS_LEN(addr_list->addrs[nvirtual]), hbuf,
260 +                       sizeof(hbuf), NULL, 0, NI_NUMERICHOST) != 0)
261 +                       strncpy(hbuf, "???", sizeof(hbuf));
262 +                   msg_fatal("parameter %s: no local interface found for %s",
263 +                             VAR_INET_INTERFACES, hbuf);
264 +#else
265                     msg_fatal("parameter %s: no local interface found for %s",
266                               VAR_INET_INTERFACES,
267                               inet_ntoa(addr_list->addrs[nvirtual]));
268 +#endif
269 +               }
270 +#ifdef INET6
271 +               if (addr_list->addrs[nvirtual].ss_family == 
272 +                   local_addrs.addrs[nlocal].ss_family &&
273 +                   SS_LEN(addr_list->addrs[nvirtual]) == 
274 +                   SS_LEN(local_addrs.addrs[nlocal]) &&
275 +                   memcmp(&addr_list->addrs[nvirtual],
276 +                   &local_addrs.addrs[nlocal],
277 +                   SS_LEN(local_addrs.addrs[nlocal])) == 0) {
278 +                   inet_addr_list_append(mask_list, (struct sockaddr *)&local_masks.addrs[nlocal]);
279 +                   break;
280 +               }
281 +#else
282                 if (addr_list->addrs[nvirtual].s_addr
283                     == local_addrs.addrs[nlocal].s_addr) {
284                     inet_addr_list_append(mask_list, &local_masks.addrs[nlocal]);
285                     break;
286                 }
287 +#endif
288             }
289         }
290         inet_addr_list_free(&local_addrs);
291 @@ -131,6 +160,42 @@
292  
293  /* own_inet_addr - is this my own internet address */
294  
295 +#ifdef INET6
296 +int     own_inet_addr(struct sockaddr * addr)
297 +{
298 +    int     i;
299 +    char *p, *q;
300 +    int l;
301 +    struct sockaddr *sa;
302 +
303 +    if (addr_list.used == 0)
304 +       own_inet_addr_init(&addr_list, &mask_list);
305 +
306 +    for (i = 0; i < addr_list.used; i++) {
307 +       sa = (struct sockaddr *)&addr_list.addrs[i];
308 +       if (addr->sa_family != sa->sa_family)
309 +           continue;
310 +       switch (addr->sa_family) {
311 +       case AF_INET:
312 +           p = (char *)&((struct sockaddr_in *)addr)->sin_addr;
313 +           q = (char *)&((struct sockaddr_in *)&addr_list.addrs[i])->sin_addr;
314 +           l = sizeof(struct in_addr);
315 +           break;
316 +       case AF_INET6:
317 +           /* XXX scope */
318 +           p = (char *)&((struct sockaddr_in6 *)addr)->sin6_addr;
319 +           q = (char *)&((struct sockaddr_in6 *)&addr_list.addrs[i])->sin6_addr;
320 +           l = sizeof(struct in6_addr);
321 +           break;
322 +       default:
323 +           continue;
324 +       }
325 +       if (memcmp(p, q, l) == 0)
326 +           return (1);
327 +    }
328 +    return (0);
329 +}
330 +#else
331  int     own_inet_addr(struct in_addr * addr)
332  {
333      int     i;
334 @@ -141,8 +206,8 @@
335      for (i = 0; i < addr_list.used; i++)
336         if (addr->s_addr == addr_list.addrs[i].s_addr)
337             return (1);
338 -    return (0);
339  }
340 +#endif
341  
342  /* own_inet_addr_list - return list of addresses */
343  
344 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/global/own_inet_addr.h snapshot-20010525/src/global/own_inet_addr.h
345 --- snapshot-20010525.noipv6/src/global/own_inet_addr.h Sat Feb 24 02:25:32 2001
346 +++ snapshot-20010525/src/global/own_inet_addr.h        Tue May 29 18:23:16 2001
347 @@ -15,11 +15,18 @@
348    * System library.
349    */
350  #include <netinet/in.h>
351 +#ifdef INET6
352 +#include <sys/socket.h>
353 +#endif
354  
355   /*
356    * External interface.
357    */
358 +#ifdef INET6
359 +extern int own_inet_addr(struct sockaddr *);
360 +#else
361  extern int own_inet_addr(struct in_addr *);
362 +#endif
363  extern struct INET_ADDR_LIST *own_inet_addr_list(void);
364  extern struct INET_ADDR_LIST *own_inet_mask_list(void);
365  
366 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/global/peer_name.c snapshot-20010525/src/global/peer_name.c
367 --- snapshot-20010525.noipv6/src/global/peer_name.c     Sun Jan 28 16:23:02 2001
368 +++ snapshot-20010525/src/global/peer_name.c    Tue May 29 18:23:16 2001
369 @@ -69,12 +69,32 @@
370  PEER_NAME *peer_name(int sock)
371  {
372      static PEER_NAME peer;
373 -    struct sockaddr_in sin;
374 -    SOCKADDR_SIZE len = sizeof(sin);
375 +    union sockunion {
376 +       struct {
377 +           u_char si_len;
378 +           u_char si_family;
379 +           u_short si_port;
380 +       } su_si;
381 +       struct sockaddr peer_un;
382 +       struct sockaddr_in peer_un4;
383 +#ifdef INET6
384 +       struct sockaddr_in6 peer_un6;
385 +#endif
386 +    } p_un;
387 +#define sun p_un.peer_un
388 +#define sin p_un.peer_un4
389 +#ifdef INET6
390 +#define sin6 p_un.peer_un6
391 +    static char hbuf[NI_MAXHOST];
392 +    static char abuf[NI_MAXHOST];
393 +#else
394      struct hostent *hp;
395 +#endif
396 +    SOCKADDR_SIZE len = sizeof(p_un);
397  
398 -    if (getpeername(sock, (struct sockaddr *) & sin, &len) == 0) {
399 -       switch (sin.sin_family) {
400 +    if (getpeername(sock, (struct sockaddr *)&p_un, &len) == 0) {
401 +       switch (p_un.peer_un.sa_family) {
402 +#ifndef INET6
403         case AF_INET:
404             peer.type = PEER_TYPE_INET;
405             hp = gethostbyaddr((char *) &(sin.sin_addr),
406 @@ -83,6 +103,24 @@
407                          hp->h_name : "unknown");
408             peer.addr = inet_ntoa(sin.sin_addr);
409             return (&peer);
410 +#else
411 +       case AF_INET:
412 +           peer.type = PEER_TYPE_INET;
413 +           if (getnameinfo(&sun, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) != 0)
414 +               peer.name = "unknown";
415 +           else
416 +               peer.name = hbuf;
417 +           peer.addr = abuf;
418 +           return (&peer);
419 +       case AF_INET6:
420 +           peer.type = PEER_TYPE_INET6;
421 +           if (getnameinfo(&sun, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) != 0)
422 +               peer.name = "unknown";
423 +           else
424 +               peer.name = hbuf;
425 +           peer.addr = abuf;
426 +           return (&peer);
427 +#endif
428         case AF_UNSPEC:
429         case AF_UNIX:
430             peer.type = PEER_TYPE_LOCAL;
431 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/global/peer_name.h snapshot-20010525/src/global/peer_name.h
432 --- snapshot-20010525.noipv6/src/global/peer_name.h     Fri Dec 11 19:55:32 1998
433 +++ snapshot-20010525/src/global/peer_name.h    Tue May 29 18:23:16 2001
434 @@ -22,6 +22,9 @@
435  #define PEER_TYPE_UNKNOWN      0
436  #define PEER_TYPE_INET         1
437  #define PEER_TYPE_LOCAL                2
438 +#ifdef INET6
439 +#define PEER_TYPE_INET6                3
440 +#endif
441  
442  extern PEER_NAME *peer_name(int);
443  
444 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/global/resolve_local.c snapshot-20010525/src/global/resolve_local.c
445 --- snapshot-20010525.noipv6/src/global/resolve_local.c Mon Apr 26 00:05:42 1999
446 +++ snapshot-20010525/src/global/resolve_local.c        Tue May 29 18:23:16 2001
447 @@ -42,6 +42,7 @@
448  #include <netinet/in.h>
449  #include <arpa/inet.h>
450  #include <string.h>
451 +#include <netdb.h>
452  
453  #ifndef INADDR_NONE
454  #define INADDR_NONE 0xffffffff
455 @@ -78,7 +79,12 @@
456  {
457      char   *saved_addr = mystrdup(addr);
458      char   *dest;
459 +#ifdef INET6
460 +    struct addrinfo hints, *res, *res0;
461 +    int error;
462 +#else
463      struct in_addr ipaddr;
464 +#endif
465      int     len;
466  
467  #define RETURN(x) { myfree(saved_addr); return(x); }
468 @@ -108,9 +114,25 @@
469      if (*dest == '[' && dest[len - 1] == ']') {
470         dest++;
471         dest[len -= 2] = 0;
472 +#ifdef INET6
473 +       memset(&hints, 0, sizeof(hints));
474 +       hints.ai_family = PF_UNSPEC;
475 +       hints.ai_socktype = SOCK_DGRAM;
476 +       error = getaddrinfo(dest, NULL, &hints, &res0);
477 +       if (!error) {
478 +           for (res = res0; res; res = res->ai_next) {
479 +               if (own_inet_addr(res->ai_addr)) {
480 +                   freeaddrinfo(res0);
481 +                   RETURN(1);
482 +               }
483 +           }
484 +           freeaddrinfo(res0);
485 +       }
486 +#else
487         if ((ipaddr.s_addr = inet_addr(dest)) != INADDR_NONE
488             && own_inet_addr(&ipaddr))
489             RETURN(1);
490 +#endif
491      }
492  
493      /*
494 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/global/wildcard_inet_addr.c snapshot-20010525/src/global/wildcard_inet_addr.c
495 --- snapshot-20010525.noipv6/src/global/wildcard_inet_addr.c    Thu Jan  1 01:00:00 1970
496 +++ snapshot-20010525/src/global/wildcard_inet_addr.c   Tue May 29 18:23:16 2001
497 @@ -0,0 +1,82 @@
498 +/* System library. */
499 +
500 +#include <sys_defs.h>
501 +#include <netinet/in.h>
502 +#include <arpa/inet.h>
503 +#include <string.h>
504 +#ifdef INET6
505 +#include <sys/socket.h>
506 +#endif
507 +#include <netdb.h>
508 +
509 +#ifdef STRCASECMP_IN_STRINGS_H
510 +#include <strings.h>
511 +#endif
512 +
513 +/* Utility library. */
514 +
515 +#include <msg.h>
516 +#include <mymalloc.h>
517 +#include <inet_addr_list.h>
518 +#include <inet_addr_local.h>
519 +#include <inet_addr_host.h>
520 +#include <stringops.h>
521 +
522 +/* Global library. */
523 +
524 +#include <mail_params.h>
525 +#include <wildcard_inet_addr.h>
526 +
527 +/* Application-specific. */
528 +static INET_ADDR_LIST addr_list;
529 +
530 +/* wildcard_inet_addr_init - initialize my own address list */
531 +
532 +static void wildcard_inet_addr_init(INET_ADDR_LIST *addr_list)
533 +{
534 +#ifdef INET6
535 +    struct addrinfo hints, *res, *res0;
536 +    char hbuf[NI_MAXHOST];
537 +    int error;
538 +#ifdef NI_WITHSCOPEID
539 +    const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
540 +#else
541 +    const int niflags = NI_NUMERICHOST;
542 +#endif
543 +
544 +    inet_addr_list_init(addr_list);
545 +
546 +    memset(&hints, 0, sizeof(hints));
547 +    hints.ai_family = PF_UNSPEC;
548 +    hints.ai_socktype = SOCK_STREAM;
549 +    hints.ai_flags = AI_PASSIVE;
550 +    error = getaddrinfo(NULL, "0", &hints, &res0);
551 +    if (error)
552 +       msg_fatal("could not get list of wildcard addresses");
553 +    for (res = res0; res; res = res->ai_next) {
554 +       if (res->ai_family != AF_INET && res->ai_family != AF_INET6)
555 +           continue;
556 +       if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
557 +           NULL, 0, niflags) != 0)
558 +           continue;
559 +       if (inet_addr_host(addr_list, hbuf) == 0)
560 +           continue; /* msg_fatal("config variable %s: host not found: %s",
561 +                     VAR_INET_INTERFACES, hbuf); */
562 +    }
563 +    freeaddrinfo(res0);
564 +#else
565 +    if (inet_addr_host(addr_list, "0.0.0.0") == 0)
566 +       msg_fatal("config variable %s: host not found: %s",
567 +                 VAR_INET_INTERFACES, "0.0.0.0");
568 +#endif
569 +}
570 +
571 +/* wildcard_inet_addr_list - return list of addresses */
572 +
573 +INET_ADDR_LIST *wildcard_inet_addr_list(void)
574 +{
575 +    if (addr_list.used == 0)
576 +       wildcard_inet_addr_init(&addr_list);
577 +
578 +    return (&addr_list);
579 +}
580 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/global/wildcard_inet_addr.h snapshot-20010525/src/global/wildcard_inet_addr.h
581 --- snapshot-20010525.noipv6/src/global/wildcard_inet_addr.h    Thu Jan  1 01:00:00 1970
582 +++ snapshot-20010525/src/global/wildcard_inet_addr.h   Tue May 29 18:23:16 2001
583 @@ -0,0 +1,36 @@
584 +#ifndef _WILDCARD_INET_ADDR_H_INCLUDED_
585 +#define _WILDCARD_INET_ADDR_H_INCLUDED_
586 +
587 +/*++
588 +/* NAME
589 +/*     wildcard_inet_addr_list 3h
590 +/* SUMMARY
591 +/*     grab the list of wildcard IP addresses.
592 +/* SYNOPSIS
593 +/*     #include <own_inet_addr.h>
594 +/* DESCRIPTION
595 +/* .nf
596 +/*--*/
597 +
598 + /*
599 +  * System library.
600 +  */
601 +#include <netinet/in.h>
602 +#ifdef INET6
603 +#include <sys/socket.h>
604 +#endif
605 +
606 + /*
607 +  * External interface.
608 +  */
609 +extern struct INET_ADDR_LIST *wildcard_inet_addr_list(void);
610 +
611 +/* LICENSE
612 +/* .ad
613 +/* .fi
614 +/*     foo
615 +/* AUTHOR(S)
616 +/*     Jun-ichiro itojun Hagino
617 +/*--*/
618 +
619 +#endif
620 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/master/master_ent.c snapshot-20010525/src/master/master_ent.c
621 --- snapshot-20010525.noipv6/src/master/master_ent.c    Tue May  1 00:45:54 2001
622 +++ snapshot-20010525/src/master/master_ent.c   Tue May 29 18:30:51 2001
623 @@ -284,8 +284,13 @@
624             inet_addr_host(MASTER_INET_ADDRLIST(serv), host);
625             serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
626         } else if (strcasecmp(var_inet_interfaces, DEF_INET_INTERFACES) == 0) {
627 +#ifdef INET6
628 +               MASTER_INET_ADDRLIST(serv) = wildcard_inet_addr_list();
629 +               serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
630 +#else
631             MASTER_INET_ADDRLIST(serv) = 0;     /* wild-card */
632             serv->listen_fd_count = 1;
633 +#endif
634         } else {
635             MASTER_INET_ADDRLIST(serv) = own_inet_addr_list();  /* virtual */
636             serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
637 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/master/master_listen.c snapshot-20010525/src/master/master_listen.c
638 --- snapshot-20010525.noipv6/src/master/master_listen.c Tue May  1 00:47:57 2001
639 +++ snapshot-20010525/src/master/master_listen.c        Tue May 29 18:24:18 2001
640 @@ -64,6 +64,11 @@
641  
642  #include "master.h"
643  
644 +#ifdef INET6
645 +#include <netdb.h>
646 +#include <stdio.h>
647 +#endif 
648 +
649  /* master_listen_init - enable connection requests */
650  
651  void    master_listen_init(MASTER_SERV *serv)
652 @@ -71,6 +76,10 @@
653      char   *myname = "master_listen_init";
654      char   *end_point;
655      int     n;
656 +#ifdef INET6
657 +    char hbuf[NI_MAXHOST];
658 +    SOCKADDR_SIZE salen;
659 +#endif
660  
661      /*
662       * Find out what transport we should use, then create one or more
663 @@ -115,8 +124,17 @@
664             close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
665         } else {                                /* virtual or host:port */
666             for (n = 0; n < serv->listen_fd_count; n++) {
667 +#ifdef INET6
668 +               if (getnameinfo((struct sockaddr *)&MASTER_INET_ADDRLIST(serv)->addrs[n],
669 +                       SA_LEN((struct sockaddr *)&MASTER_INET_ADDRLIST(serv)->addrs[n]), 
670 +                       hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) {
671 +                   strncpy(hbuf, "?????", sizeof(hbuf));
672 +               }
673 +               end_point = concatenate(hbuf, ":", MASTER_INET_PORT(serv), (char *) 0);
674 +#else
675                 end_point = concatenate(inet_ntoa(MASTER_INET_ADDRLIST(serv)->addrs[n]),
676                                    ":", MASTER_INET_PORT(serv), (char *) 0);
677 +#endif
678                 serv->listen_fd[n]
679                     = inet_listen(end_point, serv->max_proc > var_proc_limit ?
680                              serv->max_proc : var_proc_limit, NON_BLOCKING);
681 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/qmgr/qmgr_message.c snapshot-20010525/src/qmgr/qmgr_message.c
682 --- snapshot-20010525.noipv6/src/qmgr/qmgr_message.c    Tue Feb 27 00:49:31 2001
683 +++ snapshot-20010525/src/qmgr/qmgr_message.c   Tue May 29 18:23:16 2001
684 @@ -460,7 +460,11 @@
685          * every front-ent program.
686          */
687         if ((at = strrchr(recipient->address, '@')) != 0
688 +#ifdef INET6
689 +           && (at + 1)[strspn(at + 1, "[]0123456789.:abcdef")] != 0
690 +#else
691             && (at + 1)[strspn(at + 1, "[]0123456789.")] != 0
692 +#endif
693             && valid_hostname(at + 1, DONT_GRIPE) == 0) {
694             qmgr_bounce_recipient(message, recipient,
695                                   "bad host/domain syntax: \"%s\"", at + 1);
696 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/smtp/Makefile.in snapshot-20010525/src/smtp/Makefile.in
697 --- snapshot-20010525.noipv6/src/smtp/Makefile.in       Tue May 29 16:03:38 2001
698 +++ snapshot-20010525/src/smtp/Makefile.in      Tue May 29 18:23:16 2001
699 @@ -139,6 +139,7 @@
700  smtp_connect.o: ../../include/mail_params.h
701  smtp_connect.o: ../../include/own_inet_addr.h
702  smtp_connect.o: ../../include/dns.h
703 +smtp_connect.o: ../../include/get_port.h
704  smtp_connect.o: smtp.h
705  smtp_connect.o: ../../include/argv.h
706  smtp_connect.o: ../../include/deliver_request.h
707 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/smtp/smtp_addr.c snapshot-20010525/src/smtp/smtp_addr.c
708 --- snapshot-20010525.noipv6/src/smtp/smtp_addr.c       Sat May  5 14:55:36 2001
709 +++ snapshot-20010525/src/smtp/smtp_addr.c      Tue May 29 18:23:16 2001
710 @@ -112,18 +112,68 @@
711  static void smtp_print_addr(char *what, DNS_RR *addr_list)
712  {
713      DNS_RR *addr;
714 -    struct in_addr in_addr;
715 +#ifdef INET6
716 +    struct sockaddr_storage ss;
717 +#else
718 +    struct sockaddr ss;
719 +#endif
720 +    struct sockaddr_in *sin;
721 +#ifdef INET6
722 +    struct sockaddr_in6 *sin6;
723 +    char   hbuf[NI_MAXHOST];
724 +#else
725 +    char   hbuf[sizeof("255.255.255.255") + 1];
726 +#endif
727  
728      msg_info("begin %s address list", what);
729      for (addr = addr_list; addr; addr = addr->next) {
730 -       if (addr->data_len > sizeof(addr)) {
731 -           msg_warn("skipping address length %d", addr->data_len);
732 -       } else {
733 -           memcpy((char *) &in_addr, addr->data, sizeof(in_addr));
734 -           msg_info("pref %4d host %s/%s",
735 -                    addr->pref, addr->name,
736 -                    inet_ntoa(in_addr));
737 +       if (addr->class != C_IN) {
738 +           msg_warn("skipping unsupported address (class=%u)", addr->class);
739 +           continue;
740         }
741 +       switch (addr->type) {
742 +       case T_A:
743 +           if (addr->data_len != sizeof(sin->sin_addr)) {
744 +               msg_warn("skipping invalid address (AAAA, len=%u)",
745 +                   addr->data_len);
746 +               continue;
747 +           }
748 +           sin = (struct sockaddr_in *)&ss;
749 +           memset(sin, 0, sizeof(*sin));
750 +           sin->sin_family = AF_INET;
751 +#ifdef HAS_SA_LEN
752 +           sin->sin_len = sizeof(*sin);
753 +#endif
754 +           memcpy(&sin->sin_addr, addr->data, sizeof(sin->sin_addr));
755 +           break;
756 +#ifdef INET6
757 +       case T_AAAA:
758 +           if (addr->data_len != sizeof(sin6->sin6_addr)) {
759 +               msg_warn("skipping invalid address (AAAA, len=%u)",
760 +                   addr->data_len);
761 +               continue;
762 +           }
763 +           sin6 = (struct sockaddr_in6 *)&ss;
764 +           memset(sin6, 0, sizeof(*sin6));
765 +           sin6->sin6_family = AF_INET6;
766 +#ifdef HAS_SA_LEN
767 +           sin6->sin6_len = sizeof(*sin6);
768 +#endif
769 +           memcpy(&sin6->sin6_addr, addr->data, sizeof(sin6->sin6_addr));
770 +           break;
771 +#endif
772 +       default:
773 +           msg_warn("skipping unsupported address (type=%u)", addr->type);
774 +           continue;
775 +       }
776 +
777 +#ifdef INET6
778 +       (void)getnameinfo((struct sockaddr *)&ss, SS_LEN(ss),
779 +           hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
780 +#else
781 +       (void)inet_ntop(AF_INET, &sin->sin_addr, hbuf, sizeof(hbuf));
782 +#endif
783 +       msg_info("pref %4d host %s/%s", addr->pref, addr->name, hbuf);
784      }
785      msg_info("end %s address list", what);
786  }
787 @@ -133,15 +183,23 @@
788  static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRING *why)
789  {
790      char   *myname = "smtp_addr_one";
791 +#ifndef INET6
792      struct in_addr inaddr;
793 -    DNS_FIXED fixed;
794      DNS_RR *addr = 0;
795      DNS_RR *rr;
796      struct hostent *hp;
797 +#else
798 +    struct addrinfo hints, *res0, *res;
799 +    int error = -1;
800 +    char *addr;
801 +    size_t addrlen;
802 +#endif
803 +    DNS_FIXED fixed;
804  
805      if (msg_verbose)
806         msg_info("%s: host %s", myname, host);
807  
808 +#ifndef INET6
809      /*
810       * Interpret a numerical name as an address.
811       */
812 @@ -194,6 +252,48 @@
813         smtp_errno = SMTP_FAIL;
814         break;
815      }
816 +#else
817 +    memset(&hints, 0, sizeof(hints));
818 +    hints.ai_family = PF_UNSPEC;
819 +    hints.ai_socktype = SOCK_STREAM;
820 +    error = getaddrinfo(host, NULL, &hints, &res0);
821 +    if (error) {
822 +       switch (error) {
823 +       case EAI_AGAIN:
824 +           smtp_errno = SMTP_RETRY;
825 +           break;
826 +       default:
827 +           vstring_sprintf(why, "[%s]: %s",host,gai_strerror(error));
828 +           smtp_errno = SMTP_FAIL;
829 +           break;
830 +       }
831 +       return (addr_list);
832 +    }
833 +    for (res = res0; res; res = res->ai_next) {
834 +       memset((char *) &fixed, 0, sizeof(fixed));
835 +       switch(res->ai_family) {
836 +       case AF_INET6:
837 +           /* XXX not scope friendly */
838 +           fixed.type = T_AAAA;
839 +           addr = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
840 +           addrlen = sizeof(struct in6_addr);
841 +           break;
842 +       case AF_INET:
843 +           fixed.type = T_A;
844 +           addr = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr;
845 +           addrlen = sizeof(struct in_addr);
846 +           break;
847 +       default:
848 +           msg_warn("%s: unknown address family %d for %s",
849 +               myname, res->ai_family, host);
850 +           continue;
851 +       }
852 +       addr_list = dns_rr_append(addr_list,
853 +           dns_rr_create(host, &fixed, pref, addr, addrlen));
854 +    }
855 +    if (res0)
856 +       freeaddrinfo(res0);
857 +#endif
858      return (addr_list);
859  }
860  
861 @@ -229,6 +329,9 @@
862      INET_ADDR_LIST *self;
863      DNS_RR *addr;
864      int     i;
865 +#ifdef INET6
866 +    struct sockaddr *sa;
867 +#endif
868  
869      /*
870       * Find the first address that lists any address that this mail system is
871 @@ -238,12 +341,36 @@
872  
873      self = own_inet_addr_list();
874      for (addr = addr_list; addr; addr = addr->next) {
875 -       for (i = 0; i < self->used; i++)
876 +       for (i = 0; i < self->used; i++) {
877 +#ifdef INET6
878 +           sa = (struct sockaddr *)&self->addrs[i];
879 +           switch(addr->type) {
880 +           case T_AAAA:
881 +               /* XXX scope */
882 +               if (sa->sa_family != AF_INET6)
883 +                   break;
884 +               if (memcmp(&((struct sockaddr_in6 *)sa)->sin6_addr,
885 +                       addr->data, sizeof(struct in6_addr)) == 0) {
886 +                   return(addr);
887 +               }
888 +               break;
889 +           case T_A:
890 +               if (sa->sa_family != AF_INET)
891 +                   break;
892 +               if (memcmp(&((struct sockaddr_in *)sa)->sin_addr,
893 +                       addr->data, sizeof(struct in_addr)) == 0) {
894 +                   return(addr);
895 +               }
896 +               break;
897 +           }
898 +#else
899             if (INADDRP(addr->data)->s_addr == self->addrs[i].s_addr) {
900                 if (msg_verbose)
901                     msg_info("%s: found at pref %d", myname, addr->pref);
902                 return (addr);
903             }
904 +#endif
905 +       }
906      }
907  
908      /*
909 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/smtp/smtp_connect.c snapshot-20010525/src/smtp/smtp_connect.c
910 --- snapshot-20010525.noipv6/src/smtp/smtp_connect.c    Tue May 29 16:03:38 2001
911 +++ snapshot-20010525/src/smtp/smtp_connect.c   Tue May 29 18:23:16 2001
912 @@ -81,6 +81,7 @@
913  /* System library. */
914  
915  #include <sys_defs.h>
916 +#include <stdlib.h>
917  #include <sys/socket.h>
918  #include <netinet/in.h>
919  #include <arpa/inet.h>
920 @@ -110,6 +111,7 @@
921  #include <inet_addr_list.h>
922  #include <iostuff.h>
923  #include <timed_connect.h>
924 +#include <get_port.h>
925  #include <stringops.h>
926  
927  /* Global library. */
928 @@ -133,19 +135,45 @@
929                                                VSTRING *why)
930  {
931      char   *myname = "smtp_connect_addr";
932 -    struct sockaddr_in sin;
933 -    int     sock;
934 +#ifdef INET6
935 +    struct sockaddr_storage ss;
936 +#else
937 +    struct sockaddr ss;
938 +#endif
939 +    struct sockaddr *sa;
940 +    struct sockaddr_in *sin;
941 +#ifdef INET6
942 +    struct sockaddr_in6 *sin6;
943 +#endif
944 +    SOCKADDR_SIZE salen;
945 +#ifdef INET6
946 +    char hbuf[NI_MAXHOST];
947 +#else
948 +    char hbuf[sizeof("255.255.255.255") + 1];
949 +#endif
950 +    int     sock = -1;
951      INET_ADDR_LIST *addr_list;
952      int     conn_stat;
953      int     saved_errno;
954      VSTREAM *stream;
955      int     ch;
956 -    unsigned long inaddr;
957 +
958 +    sa = (struct sockaddr *)&ss;
959 +    sin = (struct sockaddr_in *)&ss;
960 +#ifdef INET6
961 +    sin6 = (struct sockaddr_in6 *)&ss;
962 +#endif
963  
964      /*
965       * Sanity checks.
966       */
967 -    if (addr->data_len > sizeof(sin.sin_addr)) {
968 +#ifdef INET6
969 +    if (((addr->type==T_A) && (addr->data_len > sizeof(sin->sin_addr))) ||
970 +       ((addr->type==T_AAAA) && (addr->data_len > sizeof(sin6->sin6_addr))))
971 +#else
972 +    if (addr->data_len > sizeof(sin->sin_addr))
973 +#endif
974 +    {
975         msg_warn("%s: skip address with length %d", myname, addr->data_len);
976         smtp_errno = SMTP_RETRY;
977         return (0);
978 @@ -154,17 +182,39 @@
979      /*
980       * Initialize.
981       */
982 -    memset((char *) &sin, 0, sizeof(sin));
983 -    sin.sin_family = AF_INET;
984 -
985 -    if ((sock = socket(sin.sin_family, SOCK_STREAM, 0)) < 0)
986 -       msg_fatal("%s: socket: %m", myname);
987 -
988 +    switch (addr->type) {
989 +#ifdef INET6
990 +    case T_AAAA:
991 +       memset(sin6, 0, sizeof(*sin6));
992 +       sin6->sin6_family = AF_INET6;
993 +       salen = sizeof(*sin6);
994 +       break;
995 +#endif
996 +    default: /* T_A: */
997 +       memset(sin, 0, sizeof(*sin));
998 +       sin->sin_family = AF_INET;
999 +       salen = sizeof(*sin);
1000 +       break;
1001 +    }
1002 +#ifdef HAS_SA_LEN
1003 +    sa->sa_len = salen;
1004 +#endif
1005 +    if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
1006 +       msg_warn("%s: socket: %m", myname);
1007 +                   
1008      /*
1009       * Allow the sysadmin to specify the source address, for example, as "-o
1010       * smtp_bind_address=x.x.x.x" in the master.cf file.
1011       */
1012      if (*var_smtp_bind_addr) {
1013 +#ifndef INET6
1014 +       struct sockaddr_in sin;
1015 +
1016 +       memset(&sin, 0, sizeof(sin));
1017 +       sin.sin_family = AF_INET;
1018 +#ifdef HAS_SA_LEN
1019 +       sin.sin_len = sizeof(sin);
1020 +#endif
1021         sin.sin_addr.s_addr = inet_addr(var_smtp_bind_addr);
1022         if (sin.sin_addr.s_addr == INADDR_NONE)
1023             msg_fatal("%s: bad %s parameter: %s",
1024 @@ -173,6 +223,25 @@
1025             msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
1026         if (msg_verbose)
1027             msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
1028 +#else
1029 +       char hbufl[NI_MAXHOST];
1030 +       struct addrinfo hints, *res;
1031 +
1032 +       memset(&hints, 0, sizeof(hints));
1033 +       hints.ai_family = sa->sa_family;
1034 +       hints.ai_socktype = SOCK_STREAM;
1035 +       hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST;
1036 +       snprintf(hbufl, sizeof(hbufl)-1, "%s", var_smtp_bind_addr);
1037 +       if (getaddrinfo(hbufl, NULL, &hints, &res) == 0) {
1038 +           (void)getnameinfo(res->ai_addr, res->ai_addrlen, hbufl,
1039 +               sizeof(hbufl), NULL, 0, NI_NUMERICHOST);
1040 +           if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
1041 +               msg_warn("%s: bind %s: %m", myname, hbufl);
1042 +           freeaddrinfo(res);
1043 +           if (msg_verbose)
1044 +               msg_info("%s: bind %s", myname, hbufl);
1045 +       }
1046 +#endif
1047      }
1048  
1049      /*
1050 @@ -180,8 +249,17 @@
1051       * the mail appears to come from the "right" machine address.
1052       */
1053      else if ((addr_list = own_inet_addr_list())->used == 1) {
1054 +#ifndef INET6
1055 +       struct sockaddr_in sin;
1056 +       unsigned long inaddr;   /*XXX BAD!*/
1057 +
1058 +       memset(&sin, 0, sizeof(sin));
1059 +       sin.sin_family = AF_INET;
1060 +#ifdef HAS_SA_LEN
1061 +       sin.sin_len = sizeof(sin);
1062 +#endif
1063         memcpy((char *) &sin.sin_addr, addr_list->addrs, sizeof(sin.sin_addr));
1064 -       inaddr = ntohl(sin.sin_addr.s_addr);
1065 +       inaddr = (unsigned long)ntohl(sin.sin_addr.s_addr);
1066         if (!IN_CLASSA(inaddr)
1067             || !(((inaddr & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)) {
1068             if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
1069 @@ -189,30 +267,85 @@
1070             if (msg_verbose)
1071                 msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
1072         }
1073 +#else
1074 +       char hbufl[NI_MAXHOST];
1075 +       struct addrinfo hints, *res = NULL, *loopback = NULL;
1076 +
1077 +       memset(&hints, 0, sizeof(hints));
1078 +       hints.ai_family = sa->sa_family;
1079 +       hints.ai_socktype = SOCK_STREAM;
1080 +       if (getaddrinfo(NULL, "0", &hints, &loopback) != 0)
1081 +           loopback = NULL;
1082 +
1083 +       /*
1084 +        * getnameinfo -> getaddrinfo loop is here so that we can
1085 +        * get rid of port.
1086 +        */
1087 +       (void)getnameinfo((struct sockaddr *)addr_list->addrs, SA_LEN((struct sockaddr *)addr_list->addrs),
1088 +           hbufl, sizeof(hbufl), NULL, 0, NI_NUMERICHOST);
1089 +       hbufl[sizeof(hbufl)-1] = 0;
1090 +       memset(&hints, 0, sizeof(hints));
1091 +       hints.ai_family = sa->sa_family;
1092 +       hints.ai_socktype = SOCK_STREAM;
1093 +       hints.ai_flags = AI_PASSIVE|AI_NUMERICHOST;
1094 +       if (getaddrinfo(hbufl, NULL, &hints, &res) == 0 &&
1095 +           !(res->ai_addrlen == loopback->ai_addrlen &&
1096 +             memcmp(res->ai_addr, loopback->ai_addr, res->ai_addrlen) == 0)) {
1097 +           if (bind(sock, res->ai_addr, res->ai_addrlen) < 0)
1098 +               msg_warn("%s: bind %s: %m", myname, hbufl);
1099 +           if (msg_verbose)
1100 +               msg_info("%s: bind %s", myname, hbufl);
1101 +       }
1102 +       if (res)
1103 +           freeaddrinfo(res);
1104 +       if (loopback)
1105 +           freeaddrinfo(loopback);
1106 +#endif
1107      }
1108  
1109      /*
1110       * Connect to the SMTP server.
1111       */
1112 -    sin.sin_port = port;
1113 -    memcpy((char *) &sin.sin_addr, addr->data, sizeof(sin.sin_addr));
1114 +    switch (addr->type) {
1115 +#ifdef INET6
1116 +    case T_AAAA:
1117 +       /* XXX scope unfriendly */
1118 +       memset(sin6, 0, sizeof(*sin6));
1119 +       sin6->sin6_port = port;
1120 +       sin6->sin6_family = AF_INET6;
1121 +       salen = sizeof(*sin6);
1122 +       memcpy(&sin6->sin6_addr, addr->data, sizeof(sin6->sin6_addr));
1123 +       inet_ntop(AF_INET6, &sin6->sin6_addr, hbuf, sizeof(hbuf));
1124 +       break;
1125 +#endif
1126 +    default: /* T_A */
1127 +       memset(sin, 0, sizeof(*sin));
1128 +       sin->sin_port = port;
1129 +       sin->sin_family = AF_INET;
1130 +       salen = sizeof(*sin);
1131 +       memcpy(&sin->sin_addr, addr->data, sizeof(sin->sin_addr));
1132 +       inet_ntop(AF_INET, &sin->sin_addr, hbuf, sizeof(hbuf));
1133 +       break;
1134 +    }
1135 +#ifdef HAS_SA_LEN
1136 +    sa->sa_len = salen;
1137 +#endif
1138  
1139      if (msg_verbose)
1140         msg_info("%s: trying: %s[%s] port %d...",
1141 -                myname, addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
1142 +                myname, addr->name, hbuf, ntohs(port));
1143      if (var_smtp_conn_tmout > 0) {
1144         non_blocking(sock, NON_BLOCKING);
1145 -       conn_stat = timed_connect(sock, (struct sockaddr *) & sin,
1146 -                                 sizeof(sin), var_smtp_conn_tmout);
1147 +       conn_stat = timed_connect(sock, sa, salen, var_smtp_conn_tmout);
1148         saved_errno = errno;
1149         non_blocking(sock, BLOCKING);
1150         errno = saved_errno;
1151      } else {
1152 -       conn_stat = connect(sock, (struct sockaddr *) & sin, sizeof(sin));
1153 +       conn_stat = connect(sock, sa, salen);
1154      }
1155      if (conn_stat < 0) {
1156         vstring_sprintf(why, "connect to %s[%s]: %m",
1157 -                       addr->name, inet_ntoa(sin.sin_addr));
1158 +                       addr->name, hbuf);
1159         smtp_errno = SMTP_RETRY;
1160         close(sock);
1161         return (0);
1162 @@ -222,8 +355,8 @@
1163       * Skip this host if it takes no action within some time limit.
1164       */
1165      if (read_wait(sock, var_smtp_helo_tmout) < 0) {
1166 -       vstring_sprintf(why, "connect to %s[%s]: read timeout",
1167 -                       addr->name, inet_ntoa(sin.sin_addr));
1168 +       vstring_sprintf(why, "connect to %s [%s]: read timeout",
1169 +                       addr->name, hbuf);
1170         smtp_errno = SMTP_RETRY;
1171         close(sock);
1172         return (0);
1173 @@ -234,8 +367,8 @@
1174       */
1175      stream = vstream_fdopen(sock, O_RDWR);
1176      if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
1177 -       vstring_sprintf(why, "connect to %s[%s]: server dropped connection",
1178 -                       addr->name, inet_ntoa(sin.sin_addr));
1179 +       vstring_sprintf(why, "connect to %s [%s]: server dropped connection",
1180 +                       addr->name, hbuf);
1181         smtp_errno = SMTP_RETRY;
1182         vstream_fclose(stream);
1183         return (0);
1184 @@ -247,7 +380,7 @@
1185       */
1186      if (ch == '4' && var_smtp_skip_4xx_greeting) {
1187         vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
1188 -                       addr->name, inet_ntoa(sin.sin_addr));
1189 +                       addr->name, hbuf);
1190         smtp_errno = SMTP_RETRY;
1191         vstream_fclose(stream);
1192         return (0);
1193 @@ -258,12 +391,12 @@
1194       */
1195      if (ch == '5' && var_smtp_skip_5xx_greeting) {
1196         vstring_sprintf(why, "connect to %s[%s]: server refused mail service",
1197 -                       addr->name, inet_ntoa(sin.sin_addr));
1198 +                       addr->name, hbuf);
1199         smtp_errno = SMTP_RETRY;
1200         vstream_fclose(stream);
1201         return (0);
1202      }
1203 -    return (smtp_session_alloc(dest, stream, addr->name, inet_ntoa(sin.sin_addr)));
1204 +    return (smtp_session_alloc(dest, stream, addr->name, hbuf));
1205  }
1206  
1207  /* smtp_connect_host - direct connection to host */
1208 @@ -273,7 +406,7 @@
1209      SMTP_SESSION *session = 0;
1210      DNS_RR *addr_list;
1211      DNS_RR *addr;
1212 -
1213 +    
1214      /*
1215       * Try each address in the specified order until we find one that works.
1216       * The addresses belong to the same A record, so we have no information
1217 @@ -380,6 +513,7 @@
1218             msg_fatal("unknown service: %s/%s", service, protocol);
1219         *portp = sp->s_port;
1220      }
1221 +
1222      return (buf);
1223  }
1224  
1225 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/smtp/smtp_unalias.c snapshot-20010525/src/smtp/smtp_unalias.c
1226 --- snapshot-20010525.noipv6/src/smtp/smtp_unalias.c    Thu Sep 28 19:06:09 2000
1227 +++ snapshot-20010525/src/smtp/smtp_unalias.c   Tue May 29 18:23:16 2001
1228 @@ -86,7 +86,11 @@
1229      if ((result = htable_find(cache, name)) == 0) {
1230         fqdn = vstring_alloc(10);
1231         if (dns_lookup_types(name, smtp_unalias_flags, (DNS_RR **) 0,
1232 -                            fqdn, (VSTRING *) 0, T_MX, T_A, 0) != DNS_OK)
1233 +                            fqdn, (VSTRING *) 0, T_MX, T_A,
1234 +#ifdef INET6
1235 +                            T_AAAA,
1236 +#endif
1237 +                            0) != DNS_OK)
1238             vstring_strcpy(fqdn, name);
1239         htable_enter(cache, name, result = vstring_export(fqdn));
1240      }
1241 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/smtpd/smtpd_check.c snapshot-20010525/src/smtpd/smtpd_check.c
1242 --- snapshot-20010525.noipv6/src/smtpd/smtpd_check.c    Tue May 29 16:03:38 2001
1243 +++ snapshot-20010525/src/smtpd/smtpd_check.c   Tue May 29 18:23:16 2001
1244 @@ -812,7 +812,11 @@
1245         msg_info("%s: %s", myname, name);
1246  
1247      dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
1248 -                                 (VSTRING *) 0, T_A, T_MX, 0);
1249 +                                 (VSTRING *) 0, T_A, T_MX,
1250 +#ifdef INET6
1251 +                                 T_AAAA,
1252 +#endif
1253 +                                 0);
1254      if (dns_status != DNS_OK)
1255         return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
1256                                    "%d <%s>: %s odrzucony/rejected: Host not found",
1257 @@ -834,7 +838,11 @@
1258         msg_info("%s: %s", myname, name);
1259  
1260      dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
1261 -                                 (VSTRING *) 0, T_A, T_MX, 0);
1262 +                                 (VSTRING *) 0, T_A, T_MX,
1263 +#ifdef INET6
1264 +                                 T_AAAA,
1265 +#endif
1266 +                                 0);
1267      if (dns_status != DNS_OK)
1268         return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
1269                                    "%d <%s>: %s odrzucony/rejected: Domain not found",
1270 @@ -1003,6 +1011,49 @@
1271  
1272  static int has_my_addr(char *host)
1273  {
1274 +#ifdef INET6
1275 +    char   *myname = "has_my_addr";
1276 +    struct addrinfo hints, *res, *res0;
1277 +    int error;
1278 +    char hbuf[NI_MAXHOST];
1279 +
1280 +    if (msg_verbose)
1281 +       msg_info("%s: host %s", myname, host);
1282 +
1283 +    /*
1284 +     * If we can't lookup the host, play safe and assume it is OK.
1285 +     */
1286 +#define YUP    1
1287 +#define NOPE   0
1288 +
1289 +    memset(&hints, 0, sizeof(hints));
1290 +    hints.ai_family = PF_UNSPEC;
1291 +    hints.ai_socktype = SOCK_DGRAM;
1292 +    error = getaddrinfo(host, NULL, &hints, &res0);
1293 +    if (error) {
1294 +       if (msg_verbose)
1295 +           msg_info("%s: host %s: %s", myname, host, gai_strerror(error));
1296 +       return (YUP);
1297 +    }
1298 +    for (res = res0; res; res = res->ai_next) {
1299 +       if (msg_verbose) {
1300 +           if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
1301 +                   NULL, 0, NI_NUMERICHOST)) {
1302 +               strncpy(hbuf, "???", sizeof(hbuf));
1303 +           }
1304 +           msg_info("%s: addr %s", myname, hbuf);
1305 +       }
1306 +       if (own_inet_addr(res->ai_addr)) {
1307 +           freeaddrinfo(res0);
1308 +           return (YUP);
1309 +       }
1310 +    }
1311 +    freeaddrinfo(res0);
1312 +    if (msg_verbose)
1313 +       msg_info("%s: host %s: no match", myname, host);
1314 +
1315 +    return (NOPE);
1316 +#else
1317      char   *myname = "has_my_addr";
1318      struct in_addr addr;
1319      char  **cpp;
1320 @@ -1038,6 +1089,7 @@
1321         msg_info("%s: host %s: no match", myname, host);
1322  
1323      return (NOPE);
1324 +#endif
1325  }
1326  
1327  /* permit_mx_backup - permit use of me as MX backup for recipient domain */
1328 @@ -1544,9 +1596,14 @@
1329      int     dns_status = DNS_FAIL;
1330      int     i;
1331      int     result;
1332 +    struct in_addr a;
1333  
1334      if (msg_verbose)
1335         msg_info("%s: %s", myname, state->addr);
1336 +
1337 +    /* IPv4 only for now */
1338 +    if (inet_pton(AF_INET, state->addr, &a) != 1)
1339 +       return SMTPD_CHECK_DUNNO;
1340  
1341      /*
1342       * IPv4 only for now
1343 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/smtpd/smtpd_peer.c snapshot-20010525/src/smtpd/smtpd_peer.c
1344 --- snapshot-20010525.noipv6/src/smtpd/smtpd_peer.c     Sun Jan 28 16:24:56 2001
1345 +++ snapshot-20010525/src/smtpd/smtpd_peer.c    Tue May 29 18:40:28 2001
1346 @@ -63,6 +63,15 @@
1347  #include <netdb.h>
1348  #include <string.h>
1349  
1350 +/* Utility library. */
1351 +
1352 +#include <msg.h>
1353 +#include <mymalloc.h>
1354 +#include <valid_hostname.h>
1355 +#include <stringops.h>
1356 +
1357 +/* Global library. */
1358 +
1359   /*
1360    * Older systems don't have h_errno. Even modern systems don't have
1361    * hstrerror().
1362 @@ -84,16 +93,11 @@
1363      )
1364  #endif
1365  
1366 -/* Utility library. */
1367 -
1368 -#include <msg.h>
1369 -#include <mymalloc.h>
1370 -#include <valid_hostname.h>
1371 -#include <stringops.h>
1372 -
1373 -/* Global library. */
1374 -
1375 -
1376 +#ifdef INET6
1377 +#define GAI_STRERROR(error) \
1378 +       ((error = EAI_SYSTEM) ? gai_strerror(error) : strerror(errno))
1379 +#endif
1380 +       
1381  /* Application-specific. */
1382  
1383  #include "smtpd.h"
1384 @@ -102,16 +106,23 @@
1385  
1386  void    smtpd_peer_init(SMTPD_STATE *state)
1387  {
1388 -    struct sockaddr_in sin;
1389 -    SOCKADDR_SIZE len = sizeof(sin);
1390 +#ifdef INET6
1391 +    struct sockaddr_storage ss;
1392 +#else
1393 +    struct sockaddr ss;
1394 +    struct in_addr *in;
1395      struct hostent *hp;
1396 -    int     i;
1397 +#endif
1398 +    struct sockaddr *sa;
1399 +    SOCKADDR_SIZE len;
1400 +
1401 +    sa = (struct sockaddr *)&ss;
1402 +    len = sizeof(ss);
1403  
1404      /*
1405       * Look up the peer address information.
1406       */
1407 -    if (getpeername(vstream_fileno(state->client),
1408 -                   (struct sockaddr *) & sin, &len) >= 0) {
1409 +    if (getpeername(vstream_fileno(state->client), sa, &len) >= 0) {
1410         errno = 0;
1411      }
1412  
1413 @@ -128,18 +139,51 @@
1414      /*
1415       * Look up and "verify" the client hostname.
1416       */
1417 -    else if (errno == 0 && sin.sin_family == AF_INET) {
1418 -       state->addr = mystrdup(inet_ntoa(sin.sin_addr));
1419 -       hp = gethostbyaddr((char *) &(sin.sin_addr),
1420 -                          sizeof(sin.sin_addr), AF_INET);
1421 -       if (hp == 0) {
1422 +    else if (errno == 0 && (sa->sa_family == AF_INET
1423 +#ifdef INET6
1424 +                           || sa->sa_family == AF_INET6
1425 +#endif
1426 +                   )) {
1427 +#ifdef INET6
1428 +       char hbuf[NI_MAXHOST];
1429 +       char abuf[NI_MAXHOST];
1430 +       struct addrinfo hints, *rnull = NULL;
1431 +#else
1432 +       char abuf[sizeof("255.255.255.255") + 1];
1433 +       char *hbuf;
1434 +#endif
1435 +       int error = -1;
1436 +
1437 +#ifdef INET6
1438 +       (void)getnameinfo(sa, len, abuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
1439 +#else
1440 +       in = &((struct sockaddr_in *)sa)->sin_addr;
1441 +       inet_ntop(AF_INET, in, abuf, sizeof(hbuf));
1442 +#endif
1443 +       state->addr = mystrdup(abuf);
1444 +#ifdef INET6
1445 +       error = getnameinfo(sa, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD);
1446 +#else
1447 +       hbuf = NULL;
1448 +       hp = gethostbyaddr((char *)in, sizeof(*in), AF_INET);
1449 +       if (hp) {
1450 +           error = 0;
1451 +               hbuf = mystrdup(hp->h_name);
1452 +       } else
1453 +           error = 1;
1454 +#endif
1455 +       if (error) {
1456             state->name = mystrdup("unknown");
1457 +#ifdef INET6
1458 +               state->peer_code = (error == EAI_AGAIN ? 4 : 5);
1459 +#else
1460             state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5);
1461 -       } else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
1462 +#endif
1463 +       } else if (!valid_hostname(hbuf, DONT_GRIPE)) {
1464             state->name = mystrdup("unknown");
1465             state->peer_code = 5;
1466         } else {
1467 -           state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
1468 +           state->name = mystrdup(hbuf);       /* hp->name is clobbered!! */
1469             state->peer_code = 2;
1470  
1471             /*
1472 @@ -151,16 +195,31 @@
1473         state->peer_code = code; \
1474      }
1475  
1476 +#ifdef INET6
1477 +           memset(&hints, 0, sizeof(hints));
1478 +           hints.ai_family = AF_UNSPEC;
1479 +           hints.ai_socktype = SOCK_STREAM;
1480 +           error = getaddrinfo(state->name, NULL, &hints, &rnull);
1481 +           if (error) {
1482 +               msg_warn("%s: hostname %s verification failed: %s",
1483 +                        state->addr, state->name, GAI_STRERROR(error));
1484 +               REJECT_PEER_NAME(state, (error == EAI_AGAIN ? 4 : 5));
1485 +           }
1486 +           /* memcmp() isn't needed if we use getaddrinfo */
1487 +           if (rnull)
1488 +               freeaddrinfo(rnull);
1489 +#else
1490             hp = gethostbyname(state->name);    /* clobbers hp->name!! */
1491             if (hp == 0) {
1492                 msg_warn("%s: hostname %s verification failed: %s",
1493                          state->addr, state->name, HSTRERROR(h_errno));
1494                 REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ? 4 : 5));
1495 -           } else if (hp->h_length != sizeof(sin.sin_addr)) {
1496 +           } else if (hp->h_length != sizeof(*in)) {
1497                 msg_warn("%s: hostname %s verification failed: bad address size %d",
1498                          state->addr, state->name, hp->h_length);
1499                 REJECT_PEER_NAME(state, 5);
1500             } else {
1501 +               int i;
1502                 for (i = 0; /* void */ ; i++) {
1503                     if (hp->h_addr_list[i] == 0) {
1504                         msg_warn("%s: address not listed for hostname %s",
1505 @@ -168,13 +227,12 @@
1506                         REJECT_PEER_NAME(state, 5);
1507                         break;
1508                     }
1509 -                   if (memcmp(hp->h_addr_list[i],
1510 -                              (char *) &sin.sin_addr,
1511 -                              sizeof(sin.sin_addr)) == 0)
1512 +                   if (memcmp(hp->h_addr_list[i], (char *)in, sizeof(*in)) == 0)
1513                         break;                  /* keep peer name */
1514                 }
1515             }
1516 +#endif
1517         }
1518      }
1519  
1520      /*
1521 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/Makefile.in snapshot-20010525/src/util/Makefile.in
1522 --- snapshot-20010525.noipv6/src/util/Makefile.in       Tue May 29 16:03:38 2001
1523 +++ snapshot-20010525/src/util/Makefile.in      Tue May 29 18:23:16 2001
1524 @@ -5,6 +5,7 @@
1525         dict_nisplus.c dict_open.c dir_forest.c doze.c environ.c \
1526         events.c exec_command.c fifo_listen.c fifo_trigger.c file_limit.c \
1527         find_inet.c fsspace.c fullname.c get_domainname.c get_hostname.c \
1528 +       get_port.c \
1529         htable.c inet_addr_host.c inet_addr_list.c inet_addr_local.c \
1530         inet_connect.c inet_listen.c inet_trigger.c inet_util.c \
1531         line_wrap.c lowercase.c lstat_as.c mac_parse.c make_dirs.c \
1532 @@ -30,6 +31,7 @@
1533         dict_nisplus.o dict_open.o dir_forest.o doze.o environ.o \
1534         events.o exec_command.o fifo_listen.o fifo_trigger.o file_limit.o \
1535         find_inet.o fsspace.o fullname.o get_domainname.o get_hostname.o \
1536 +       get_port.o \
1537         htable.o inet_addr_host.o inet_addr_list.o inet_addr_local.o \
1538         inet_connect.o inet_listen.o inet_trigger.o inet_util.o \
1539         line_wrap.o lowercase.o lstat_as.o mac_parse.o make_dirs.o \
1540 @@ -53,6 +55,7 @@
1541         dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \
1542         dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \
1543         exec_command.h find_inet.h fsspace.h fullname.h get_domainname.h \
1544 +       get_port.h \
1545         get_hostname.h htable.h inet_addr_host.h inet_addr_list.h \
1546         inet_addr_local.h inet_util.h iostuff.h line_wrap.h listen.h lstat_as.h \
1547         mac_parse.h make_dirs.h match_list.h match_ops.h msg.h msg_output.h \
1548 @@ -590,6 +593,7 @@
1549  get_domainname.o: mymalloc.h
1550  get_domainname.o: get_hostname.h
1551  get_domainname.o: get_domainname.h
1552 +get_port.o: sys_defs.h
1553  get_hostname.o: get_hostname.c
1554  get_hostname.o: sys_defs.h
1555  get_hostname.o: mymalloc.h
1556 @@ -701,6 +705,7 @@
1557  match_list.o: stringops.h
1558  match_list.o: argv.h
1559  match_list.o: dict.h
1560 +match_list.o: inet_util.h
1561  match_list.o: match_list.h
1562  match_ops.o: match_ops.c
1563  match_ops.o: sys_defs.h
1564 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/get_port.c snapshot-20010525/src/util/get_port.c
1565 --- snapshot-20010525.noipv6/src/util/get_port.c        Thu Jan  1 01:00:00 1970
1566 +++ snapshot-20010525/src/util/get_port.c       Tue May 29 18:23:16 2001
1567 @@ -0,0 +1,65 @@
1568 +/*++
1569 +/* NAME
1570 +/*     get_port 3
1571 +/* SUMMARY
1572 +/*     trivial host and port extracter
1573 +/* SYNOPSIS
1574 +/*     #include <get_port.h>
1575 +/*
1576 +/*     char    *get_port(data)
1577 +/*     char    *data;
1578 +/*
1579 +/* DESCRIPTION
1580 +/*     get_port() extract host name or ip address from
1581 +/*     strings such as [3ffe:902:12::10]:25, [::1]
1582 +/*     or 192.168.0.1:25, and null-terminates the
1583 +/*     \fIdata\fR at the first occurrence of port separator.
1584 +/* DIAGNOSTICS
1585 +/*     If port not found return null pointer.
1586 +/* LICENSE
1587 +/* .ad
1588 +/* .fi
1589 +/*     BSD Style (or BSD like) license.
1590 +/* AUTHOR(S)
1591 +/*     Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
1592 +/*     Wroclaw, POLAND
1593 +/*--*/
1594 +
1595 +/* System libraries */
1596 +
1597 +#include <sys_defs.h>
1598 +#include <string.h>
1599 +
1600 +/* Utility library. */
1601 +
1602 +#include "get_port.h"
1603 +
1604 +/* get_port - extract port number from string */
1605 +
1606 +char *get_port(char *data)
1607 +{
1608 +       const char *escl=strchr(data,'[');
1609 +       const char *sepl=strchr(data,':');
1610 +       char *escr=strrchr(data,']');
1611 +       char *sepr=strrchr(data,':');
1612 +
1613 +       /* extract from "[address]:port" or "[address]"*/
1614 +       if (escl && escr)
1615 +       {
1616 +               memmove(data, data + 1, strlen(data) - strlen(escr));
1617 +               data[strlen(data) - strlen(escr) - 1] = 0;
1618 +               *escr++ = 0;
1619 +               if (*escr == ':')
1620 +                       escr++;
1621 +               return (*escr ? escr : NULL);
1622 +       }
1623 +       /* extract from "address:port" or "address" */
1624 +       if ((sepl == sepr) && sepr && sepl)
1625 +       {
1626 +               *sepr++ = 0;
1627 +               return sepr;
1628 +       }
1629 +
1630 +       /* return empty string */
1631 +       return NULL;
1632 +}
1633 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/get_port.h snapshot-20010525/src/util/get_port.h
1634 --- snapshot-20010525.noipv6/src/util/get_port.h        Thu Jan  1 01:00:00 1970
1635 +++ snapshot-20010525/src/util/get_port.h       Tue May 29 18:23:16 2001
1636 @@ -0,0 +1,28 @@
1637 +#ifndef _GET_PORT_H_INCLUDED_
1638 +#define _GET_PORT_H_INCLUDED_
1639 +
1640 +/*++
1641 +/* NAME
1642 +/*     get_port 3h
1643 +/* SUMMARY
1644 +/*     trivial host and port extracter
1645 +/* SYNOPSIS
1646 +/*     #include <get_port.h>
1647 +/* DESCRIPTION
1648 +/* .nf
1649 +
1650 + /* External interface. */
1651 +
1652 +extern char *get_port(char *);
1653 +
1654 +
1655 +/* LICENSE
1656 +/* .ad
1657 +/* .fi
1658 +/*     BSD Style (or BSD like) license.
1659 +/* AUTHOR(S)
1660 +/*     Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
1661 +/*     Wroclaw, POLAND
1662 +/*--*/
1663 +
1664 +#endif
1665 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/inet_addr_host.c snapshot-20010525/src/util/inet_addr_host.c
1666 --- snapshot-20010525.noipv6/src/util/inet_addr_host.c  Fri Dec 11 19:55:35 1998
1667 +++ snapshot-20010525/src/util/inet_addr_host.c Tue May 29 18:23:16 2001
1668 @@ -38,7 +38,10 @@
1669  #include <sys_defs.h>
1670  #include <netinet/in.h>
1671  #include <arpa/inet.h>
1672 +#include <sys/socket.h>
1673  #include <netdb.h>
1674 +#include <stdlib.h>
1675 +#include <string.h>
1676  
1677  #ifndef INADDR_NONE
1678  #define INADDR_NONE 0xffffffff
1679 @@ -48,15 +51,45 @@
1680  
1681  #include <inet_addr_list.h>
1682  #include <inet_addr_host.h>
1683 +#ifdef TEST
1684 +#include <msg.h>
1685 +#endif
1686  
1687  /* inet_addr_host - look up address list for host */
1688  
1689  int     inet_addr_host(INET_ADDR_LIST *addr_list, const char *hostname)
1690  {
1691 +#ifdef INET6
1692 +    int s;
1693 +    struct addrinfo hints, *res0, *res;
1694 +#ifdef TEST    
1695 +       char buforhosta[1024];
1696 +#endif 
1697 +    int error;
1698 +#else
1699      struct hostent *hp;
1700      struct in_addr addr;
1701 +#endif
1702      int     initial_count = addr_list->used;
1703  
1704 +#ifdef INET6
1705 +    memset(&hints, 0, sizeof(hints));
1706 +    hints.ai_family = PF_UNSPEC;
1707 +    hints.ai_socktype = SOCK_DGRAM;
1708 +    error = getaddrinfo(hostname, NULL, &hints, &res0);
1709 +    if (error == 0) {
1710 +       for (res = res0; res; res = res->ai_next) {
1711 +           /* filter out address families that are not supported */
1712 +           s = socket(res->ai_family, SOCK_DGRAM, 0);
1713 +           if (s < 0)
1714 +               continue;
1715 +           close(s);
1716 +
1717 +           inet_addr_list_append(addr_list, res->ai_addr);
1718 +       }
1719 +       freeaddrinfo(res0);
1720 +    }
1721 +#else
1722      if ((addr.s_addr = inet_addr(hostname)) != INADDR_NONE) {
1723         inet_addr_list_append(addr_list, &addr);
1724      } else {
1725 @@ -65,9 +98,12 @@
1726                 inet_addr_list_append(addr_list,
1727                                     (struct in_addr *) * hp->h_addr_list++);
1728      }
1729 +#endif
1730 +
1731      return (addr_list->used - initial_count);
1732  }
1733  
1734 +
1735  #ifdef TEST
1736  
1737  #include <msg.h>
1738 @@ -78,6 +114,8 @@
1739  {
1740      INET_ADDR_LIST addr_list;
1741      int     i;
1742 +    struct sockaddr *sa;
1743 +    char hbuf[NI_MAXHOST];
1744  
1745      msg_vstream_init(argv[0], VSTREAM_ERR);
1746  
1747 @@ -89,8 +127,12 @@
1748         if (inet_addr_host(&addr_list, *argv) == 0)
1749             msg_fatal("not found: %s", *argv);
1750  
1751 -       for (i = 0; i < addr_list.used; i++)
1752 -           vstream_printf("%s\n", inet_ntoa(addr_list.addrs[i]));
1753 +       for (i = 0; i < addr_list.used; i++) {
1754 +           sa = (struct sockaddr *)&addr_list.addrs[i];
1755 +           getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf), NULL, 0,
1756 +                   NI_NUMERICHOST);
1757 +           vstream_printf("%s\n", hbuf);
1758 +       }
1759         vstream_fflush(VSTREAM_OUT);
1760      }
1761      inet_addr_list_free(&addr_list);
1762 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/inet_addr_list.c snapshot-20010525/src/util/inet_addr_list.c
1763 --- snapshot-20010525.noipv6/src/util/inet_addr_list.c  Mon Nov 20 19:06:30 2000
1764 +++ snapshot-20010525/src/util/inet_addr_list.c Tue May 29 18:23:16 2001
1765 @@ -44,6 +44,13 @@
1766  #include <netinet/in.h>
1767  #include <arpa/inet.h>
1768  
1769 +#include <netdb.h>
1770 +
1771 +#ifdef INET6
1772 +#include <string.h>
1773 +#include <sys/socket.h>
1774 +#endif
1775 +
1776  /* Utility library. */
1777  
1778  #include <msg.h>
1779 @@ -56,12 +63,39 @@
1780  {
1781      list->used = 0;
1782      list->size = 2;
1783 +#ifdef INET6
1784 +    list->addrs = (struct sockaddr_storage *)
1785 +#else
1786      list->addrs = (struct in_addr *)
1787 +#endif
1788         mymalloc(sizeof(*list->addrs) * list->size);
1789  }
1790  
1791  /* inet_addr_list_append - append address to internet address list */
1792  
1793 +#ifdef INET6
1794 +void    inet_addr_list_append(INET_ADDR_LIST *list, 
1795 +                              struct sockaddr * addr)
1796 +{
1797 +    char   *myname = "inet_addr_list_append";
1798 +    char hbuf[NI_MAXHOST];
1799 +
1800 +    if (msg_verbose > 1) {
1801 +       if (getnameinfo(addr, SA_LEN(addr), hbuf, sizeof(hbuf), NULL, 0,
1802 +           NI_NUMERICHOST)) {
1803 +           strncpy(hbuf, "??????", sizeof(hbuf));
1804 +       }
1805 +       msg_info("%s: %s", myname, hbuf);
1806 +    }
1807 +
1808 +    if (list->used >= list->size)
1809 +       list->size *= 2;
1810 +    list->addrs = (struct sockaddr_storage *)
1811 +       myrealloc((char *) list->addrs,
1812 +                 sizeof(*list->addrs) * list->size);
1813 +    memcpy(&list->addrs[list->used++], addr, SA_LEN(addr));
1814 +}
1815 +#else
1816  void    inet_addr_list_append(INET_ADDR_LIST *list, struct in_addr * addr)
1817  {
1818      char   *myname = "inet_addr_list_append";
1819 @@ -76,6 +110,7 @@
1820                   sizeof(*list->addrs) * list->size);
1821      list->addrs[list->used++] = *addr;
1822  }
1823 +#endif
1824  
1825  /* inet_addr_list_free - destroy internet address list */
1826  
1827 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/inet_addr_list.h snapshot-20010525/src/util/inet_addr_list.h
1828 --- snapshot-20010525.noipv6/src/util/inet_addr_list.h  Fri Dec 11 19:55:35 1998
1829 +++ snapshot-20010525/src/util/inet_addr_list.h Tue May 29 18:23:16 2001
1830 @@ -16,18 +16,37 @@
1831    */
1832  #include <netinet/in.h>
1833  
1834 +#ifndef SA_LEN
1835 +#ifndef HAS_SA_LEN
1836 +#define SA_LEN(x)       (((x)->sa_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
1837 +#define SS_LEN(x)       (((x).ss_family == AF_INET6) ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
1838 +#else
1839 +#define SA_LEN(x)       ((x)->sa_len)
1840 +#define SS_LEN(x)       ((x).ss_len)
1841 +#endif
1842 +#endif
1843 +
1844   /*
1845    * External interface.
1846    */
1847  typedef struct INET_ADDR_LIST {
1848      int     used;                      /* nr of elements in use */
1849      int     size;                      /* actual list size */
1850 +#ifdef INET6
1851 +    struct sockaddr_storage *addrs;    /* payload */
1852 +#else
1853      struct in_addr *addrs;             /* payload */
1854 +#endif
1855  } INET_ADDR_LIST;
1856  
1857  extern void inet_addr_list_init(INET_ADDR_LIST *);
1858  extern void inet_addr_list_free(INET_ADDR_LIST *);
1859 +#ifdef INET6
1860 +struct sockaddr;
1861 +extern void inet_addr_list_append(INET_ADDR_LIST *, struct sockaddr *);
1862 +#else
1863  extern void inet_addr_list_append(INET_ADDR_LIST *, struct in_addr *);
1864 +#endif
1865  
1866  /* LICENSE
1867  /* .ad
1868 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/inet_addr_local.c snapshot-20010525/src/util/inet_addr_local.c
1869 --- snapshot-20010525.noipv6/src/util/inet_addr_local.c Sun Feb 25 19:20:19 2001
1870 +++ snapshot-20010525/src/util/inet_addr_local.c        Tue May 29 18:47:06 2001
1871 @@ -47,6 +47,13 @@
1872  #endif
1873  #include <errno.h>
1874  #include <string.h>
1875 +#if defined(INET6) && (defined (LINUX) || defined (LINUX2))
1876 +#include <netdb.h>
1877 +#include <stdio.h>
1878 +#endif
1879 +#ifdef HAVE_GETIFADDRS
1880 +#include <ifaddrs.h>
1881 +#endif
1882  
1883  /* Utility library. */
1884  
1885 @@ -78,18 +85,98 @@
1886  
1887  int     inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list)
1888  {
1889 +#ifdef HAVE_GETIFADDRS
1890 +    char *myname = "inet_addr_local";
1891 +    struct ifaddrs *ifap, *ifa;
1892 +    int initial_count = addr_list->used;
1893 +    struct sockaddr *sa;
1894 +#ifdef INET6
1895 +#ifdef __KAME__
1896 +    struct sockaddr_in6 addr6;
1897 +#endif
1898 +#else
1899 +    void *addr;
1900 +#endif
1901 +
1902 +    if (getifaddrs(&ifap) < 0)
1903 +       msg_fatal("%s: getifaddrs: %m", myname);
1904 +
1905 +    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
1906 +               if (! (ifa->ifa_flags & IFF_RUNNING)) 
1907 +                       continue;
1908 +       sa = ifa->ifa_addr;
1909 +       switch (ifa->ifa_addr->sa_family) {
1910 +       case AF_INET:
1911 +#ifndef INET6
1912 +           addr = (void *)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
1913 +#endif
1914 +           break;
1915 +#ifdef INET6
1916 +       case AF_INET6:
1917 +#ifdef __KAME__
1918 +           memcpy(&addr6, ifa->ifa_addr, ifa->ifa_addr->sa_len);
1919 +           /* decode scoped address notation */
1920 +           if ((IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) ||
1921 +                IN6_IS_ADDR_SITELOCAL(&addr6.sin6_addr)) &&
1922 +               addr6.sin6_scope_id == 0) {
1923 +               addr6.sin6_scope_id = ntohs(addr6.sin6_addr.s6_addr[3] |
1924 +                   (unsigned int)addr6.sin6_addr.s6_addr[2] << 8);
1925 +               addr6.sin6_addr.s6_addr[2] = addr6.sin6_addr.s6_addr[3] = 0;
1926 +               sa = (struct sockaddr *)&addr6;
1927 +           }
1928 +#endif
1929 +           break;
1930 +#endif
1931 +       default:
1932 +           continue;
1933 +       }
1934 +
1935 +#ifdef INET6
1936 +       inet_addr_list_append(addr_list, sa);
1937 +#else
1938 +       inet_addr_list_append(addr_list, (struct in_addr *)addr);
1939 +#endif
1940 +    }
1941 +
1942 +    freeifaddrs(ifap);
1943 +    return (addr_list->used - initial_count);
1944 +#else
1945      char   *myname = "inet_addr_local";
1946      struct ifconf ifc;
1947      struct ifreq *ifr;
1948      struct ifreq *the_end;
1949      int     sock;
1950 -    VSTRING *buf = vstring_alloc(1024);
1951 +    VSTRING *buf;
1952      int     initial_count = addr_list->used;
1953      struct in_addr addr;
1954      struct ifreq *ifr_mask;
1955 +    int af = AF_INET;
1956 +#ifdef INET6
1957 +#if defined (LINUX) || defined (LINUX2)
1958 +#define _PATH_PROCNET_IFINET6   "/proc/net/if_inet6"
1959 +    FILE *f;
1960 +    char addr6p[8][5], addr6res[40], devname[20];
1961 +    int plen, scope, dad_status, if_idx, gaierror;
1962 +    struct addrinfo hints, *res, *res0;
1963 +#endif
1964 +    struct sockaddr_in6 addr6;
1965  
1966 -    if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
1967 +other_socket_type:
1968 +#endif
1969 +    buf = vstring_alloc(1024);
1970 +
1971 +    if ((sock = socket(af, SOCK_DGRAM, 0)) < 0) {
1972 +#ifdef INET6
1973 +       if (af == AF_INET6)
1974 +       {
1975 +           if (msg_verbose)
1976 +                   msg_warn("%s: socket: %m", myname);
1977 +           goto end;
1978 +       }
1979 +       else
1980 +#endif
1981         msg_fatal("%s: socket: %m", myname);
1982 +    }
1983  
1984      /*
1985       * Get the network interface list. XXX The socket API appears to have no
1986 @@ -126,10 +213,15 @@
1987       */
1988      the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
1989      for (ifr = ifc.ifc_req; ifr < the_end;) {
1990 -       if (ifr->ifr_addr.sa_family == AF_INET) {       /* IP interface */
1991 +       if ((ifr->ifr_addr.sa_family == AF_INET) &&
1992 +                       (ifr->ifr_addr.sa_family == af)) { /* IP interface */
1993             addr = ((struct sockaddr_in *) & ifr->ifr_addr)->sin_addr;
1994             if (addr.s_addr != INADDR_ANY) {    /* has IP address */
1995 +#ifdef INET6
1996 +               inet_addr_list_append(addr_list, &ifr->ifr_addr);
1997 +#else
1998                 inet_addr_list_append(addr_list, &addr);
1999 +#endif
2000                 if (mask_list) {
2001                     ifr_mask = (struct ifreq *) mymalloc(IFREQ_SIZE(ifr));
2002                     memcpy((char *) ifr_mask, (char *) ifr, IFREQ_SIZE(ifr));
2003 @@ -141,11 +233,61 @@
2004                 }
2005             }
2006         }
2007 +#ifdef INET6
2008 +       else if ((ifr->ifr_addr.sa_family == AF_INET6) &&
2009 +                       (ifr->ifr_addr.sa_family == af)) {  /* IPv6 interface */
2010 +           addr6 = *((struct sockaddr_in6 *) & ifr->ifr_addr);
2011 +#ifdef __KAME__
2012 +           /* decode scoped address notation */
2013 +           if ((IN6_IS_ADDR_LINKLOCAL(&addr6.sin6_addr) ||
2014 +                IN6_IS_ADDR_SITELOCAL(&addr6.sin6_addr)) &&
2015 +               addr6.sin6_scope_id == 0) {
2016 +               addr6.sin6_scope_id = ntohs(addr6.sin6_addr.s6_addr[3] |
2017 +                   (unsigned int)addr6.sin6_addr.s6_addr[2] << 8);
2018 +               addr6.sin6_addr.s6_addr[2] = addr6.sin6_addr.s6_addr[3] = 0;
2019 +           }
2020 +#endif
2021 +           if (!(IN6_IS_ADDR_UNSPECIFIED(&addr6.sin6_addr)))
2022 +               inet_addr_list_append(addr_list, (struct sockaddr *)&addr6);
2023 +       }
2024 +#endif
2025         ifr = NEXT_INTERFACE(ifr);
2026      }
2027      vstring_free(buf);
2028      (void) close(sock);
2029 +#ifdef INET6
2030 +end:
2031 +    if (af != AF_INET6) {
2032 +           af = AF_INET6;
2033 +           goto other_socket_type;
2034 +    }
2035 +#if defined (LINUX) || defined (LINUX2)
2036 +    if ((f = fopen(_PATH_PROCNET_IFINET6, "r")) != NULL) {
2037 +         while (fscanf(f, "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %20s\n",
2038 +              addr6p[0], addr6p[1], addr6p[2], addr6p[3], addr6p[4],
2039 +              addr6p[5], addr6p[6], addr6p[7],
2040 +              &if_idx, &plen, &scope, &dad_status, devname) != EOF) {
2041 +                sprintf(addr6res, "%s:%s:%s:%s:%s:%s:%s:%s",
2042 +                                addr6p[0], addr6p[1], addr6p[2], addr6p[3],
2043 +                                addr6p[4], addr6p[5], addr6p[6], addr6p[7]);
2044 +                addr6res[sizeof(addr6res) - 1] = 0;
2045 +                memset(&hints, 0, sizeof(hints));
2046 +                hints.ai_flags = AI_NUMERICHOST;
2047 +                hints.ai_family = AF_UNSPEC;
2048 +                hints.ai_socktype = SOCK_DGRAM;
2049 +                gaierror = getaddrinfo(addr6res, NULL, &hints, &res0);
2050 +                if (!gaierror) {
2051 +                        for (res = res0; res; res = res->ai_next) {
2052 +                              inet_addr_list_append(addr_list, res->ai_addr);
2053 +                        }
2054 +                        freeaddrinfo(res0);
2055 +                }
2056 +        }
2057 +    }
2058 +#endif /* linux */
2059 +#endif
2060      return (addr_list->used - initial_count);
2061 +#endif
2062  }
2063  
2064  #ifdef TEST
2065 @@ -158,6 +300,8 @@
2066      INET_ADDR_LIST addr_list;
2067      INET_ADDR_LIST mask_list;
2068      int     i;
2069 +    char abuf[NI_MAXHOST], mbuf[NI_MAXHOST];
2070 +    struct sockaddr *sa;
2071  
2072      msg_vstream_init(argv[0], VSTREAM_ERR);
2073  
2074 @@ -172,8 +316,17 @@
2075         msg_warn("found only one active network interface");
2076  
2077      for (i = 0; i < addr_list.used; i++) {
2078 -       vstream_printf("%s/", inet_ntoa(addr_list.addrs[i]));
2079 -       vstream_printf("%s\n", inet_ntoa(mask_list.addrs[i]));
2080 +       sa = (struct sockaddr *)&addr_list.addrs[i];
2081 +       if (getnameinfo(sa, SA_LEN(sa), abuf, sizeof(abuf), NULL, 0,
2082 +               NI_NUMERICHOST)) {
2083 +           strncpy(abuf, "???", sizeof(abuf));
2084 +       }
2085 +       sa = (struct sockaddr *)&mask_list.addrs[i];
2086 +       if (getnameinfo(sa, SA_LEN(sa), mbuf, sizeof(mbuf), NULL, 0,
2087 +               NI_NUMERICHOST)) {
2088 +           strncpy(mbuf, "???", sizeof(mbuf));
2089 +       }
2090 +       vstream_printf("%s/%s\n", abuf, mbuf);
2091      }
2092      vstream_fflush(VSTREAM_OUT);
2093      inet_addr_list_free(&addr_list);
2094 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/inet_connect.c snapshot-20010525/src/util/inet_connect.c
2095 --- snapshot-20010525.noipv6/src/util/inet_connect.c    Mon Nov 20 19:06:31 2000
2096 +++ snapshot-20010525/src/util/inet_connect.c   Tue May 29 18:23:16 2001
2097 @@ -55,6 +55,9 @@
2098  #include <string.h>
2099  #include <unistd.h>
2100  #include <errno.h>
2101 +#ifdef INET6
2102 +#include <netdb.h>
2103 +#endif
2104  
2105  /* Utility library. */
2106  
2107 @@ -73,7 +76,12 @@
2108      char   *buf;
2109      char   *host;
2110      char   *port;
2111 +#ifdef INET6
2112 +    struct addrinfo hints, *res, *res0;
2113 +    int    error;
2114 +#else
2115      struct sockaddr_in sin;
2116 +#endif
2117      int     sock;
2118  
2119      /*
2120 @@ -81,14 +89,58 @@
2121       * the local host.
2122       */
2123      buf = inet_parse(addr, &host, &port);
2124 +#ifdef INET6
2125 +    if (*host == 0)
2126 +       host = NULL;
2127 +    memset(&hints, 0, sizeof(hints));
2128 +    hints.ai_family = PF_UNSPEC;
2129 +    hints.ai_socktype = SOCK_STREAM;
2130 +    hints.ai_flags = AI_NUMERICHOST;   /* find_inet_addr is numeric only */
2131 +    if (getaddrinfo(host, port, &hints, &res0))
2132 +       msg_fatal("host not found: %s", host);
2133 +#else
2134      if (*host == 0)
2135         host = "localhost";
2136      memset((char *) &sin, 0, sizeof(sin));
2137      sin.sin_family = AF_INET;
2138      sin.sin_addr.s_addr = find_inet_addr(host);
2139      sin.sin_port = find_inet_port(port, "tcp");
2140 +#endif
2141      myfree(buf);
2142  
2143 +#ifdef INET6
2144 +    sock = -1;
2145 +    for (res = res0; res; res = res->ai_next) {
2146 +       if ((res->ai_family != AF_INET) && (res->ai_family != AF_INET6))
2147 +           continue;
2148 +
2149 +       sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
2150 +       if (sock < 0)
2151 +           continue;
2152 +       if (timeout > 0) {
2153 +           non_blocking(sock, NON_BLOCKING);
2154 +           if (timed_connect(sock, res->ai_addr, res->ai_addrlen, timeout) < 0) {
2155 +               close(sock);
2156 +               sock = -1;
2157 +               continue;
2158 +           }
2159 +           if (block_mode != NON_BLOCKING)
2160 +               non_blocking(sock, block_mode);
2161 +           break;
2162 +       } else {
2163 +           non_blocking(sock, block_mode);
2164 +           if (connect(sock, res->ai_addr, res->ai_addrlen) < 0
2165 +               && errno != EINPROGRESS) {
2166 +               close(sock);
2167 +               sock = -1;
2168 +               continue;
2169 +           }
2170 +           break;
2171 +       }
2172 +    }
2173 +    freeaddrinfo(res0);
2174 +    return sock;
2175 +#else
2176      /*
2177       * Create a client socket.
2178       */
2179 @@ -121,4 +173,5 @@
2180         }
2181         return (sock);
2182      }
2183 +#endif
2184  }
2185 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/inet_listen.c snapshot-20010525/src/util/inet_listen.c
2186 --- snapshot-20010525.noipv6/src/util/inet_listen.c     Mon Nov 20 19:06:32 2000
2187 +++ snapshot-20010525/src/util/inet_listen.c    Tue May 29 18:23:16 2001
2188 @@ -51,6 +51,11 @@
2189  #include <sys_defs.h>
2190  #include <sys/socket.h>
2191  #include <netinet/in.h>
2192 +#ifdef INET6
2193 +#if (! __GLIBC__ >= 2 && __GLIBC_MINOR__ >=1 )
2194 +#include <netinet6/in6.h>
2195 +#endif
2196 +#endif
2197  #include <arpa/inet.h>
2198  #include <netdb.h>
2199  #ifndef MAXHOSTNAMELEN
2200 @@ -79,33 +84,109 @@
2201  
2202  int     inet_listen(const char *addr, int backlog, int block_mode)
2203  {
2204 +#ifdef INET6
2205 +    struct addrinfo *res, *res0, hints;
2206 +    int error;
2207 +#else
2208 +    struct ai {
2209 +       int ai_family;
2210 +       int ai_socktype;
2211 +       int ai_protocol;
2212 +       struct sockaddr *ai_addr;
2213 +       SOCKADDR_SIZE ai_addrlen;
2214 +       struct ai *ai_next;
2215 +    } *res, *res0, resbody;
2216      struct sockaddr_in sin;
2217 +#endif
2218      int     sock;
2219      int     t = 1;
2220      char   *buf;
2221      char   *host;
2222      char   *port;
2223 +#ifdef INET6
2224 +    char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
2225 +#else
2226 +    char hbuf[sizeof("255.255.255.255") + 1];
2227 +    char pbuf[sizeof("255.255.255.255") + 1];
2228 +#endif
2229 +    char *cause = "unknown";
2230  
2231      /*
2232       * Translate address information to internal form.
2233       */
2234      buf = inet_parse(addr, &host, &port);
2235 -    memset((char *) &sin, 0, sizeof(sin));
2236 +#ifdef INET6
2237 +    memset(&hints, 0, sizeof(hints));
2238 +    hints.ai_flags = AI_PASSIVE;
2239 +    hints.ai_family = AF_UNSPEC;
2240 +    hints.ai_socktype = SOCK_STREAM;
2241 +    error = getaddrinfo(*host ? host : NULL, *port ? port : "0", &hints, &res0);
2242 +    if (error) {
2243 +       msg_fatal("getaddrinfo: %s", gai_strerror(error));
2244 +    }
2245 +    myfree(buf);
2246 +#else
2247 +    memset(&sin, 0, sizeof(sin));
2248      sin.sin_family = AF_INET;
2249 +#ifdef HAS_SA_LEN
2250 +    sin.sin_len = sizeof(sin);
2251 +#endif
2252      sin.sin_port = find_inet_port(port, "tcp");
2253      sin.sin_addr.s_addr = (*host ? find_inet_addr(host) : INADDR_ANY);
2254 -    myfree(buf);
2255  
2256 -    /*
2257 -     * Create a listener socket.
2258 -     */
2259 -    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
2260 -       msg_fatal("socket: %m");
2261 -    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) < 0)
2262 -       msg_fatal("setsockopt: %m");
2263 -    if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
2264 -       msg_fatal("bind %s port %d: %m", sin.sin_addr.s_addr == INADDR_ANY ?
2265 -              "INADDR_ANY" : inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
2266 +    memset(&resbody, 0, sizeof(resbody)); 
2267 +    resbody.ai_socktype = SOCK_STREAM;
2268 +    resbody.ai_family = AF_INET;
2269 +    resbody.ai_addr = (struct sockaddr *)&sin;
2270 +    resbody.ai_addrlen = sizeof(sin);
2271 +
2272 +    res0 = &resbody;
2273 +#endif
2274 +
2275 +    sock = -1;
2276 +    for (res = res0; res; res = res->ai_next) {
2277 +       if ((res->ai_family != AF_INET) && (res->ai_family != AF_INET6))
2278 +           continue;
2279 +
2280 +       /*
2281 +        * Create a listener socket.
2282 +        */
2283 +       if ((sock = socket(res->ai_family, res->ai_socktype, 0)) < 0) {
2284 +           cause = "socket";
2285 +           continue;
2286 +       }
2287 +#ifdef IPV6_V6ONLY
2288 +       if (res->ai_family == AF_INET6 &&
2289 +           setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &t, sizeof(t)) < 0) {
2290 +               /* if kernel/libc don't support this simple ignore it
2291 +           cause = "setsockopt(IPV6_V6ONLY)";
2292 +           close(sock);
2293 +           sock = -1;
2294 +           continue;
2295 +               */
2296 +               ;
2297 +       }
2298 +#endif
2299 +       if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) < 0) {
2300 +           cause = "setsockopt(SO_REUSEADDR)";
2301 +           close(sock);
2302 +           sock = -1;
2303 +           continue;
2304 +       }
2305 +
2306 +       if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
2307 +           cause = "bind";
2308 +           close(sock);
2309 +           sock = -1;
2310 +           continue;
2311 +       }
2312 +       break;
2313 +    }
2314 +    if (sock < 0)
2315 +       msg_fatal("%s: %m", cause);
2316 +#ifdef INET6
2317 +    freeaddrinfo(res0);
2318 +#endif
2319      non_blocking(sock, block_mode);
2320      if (listen(sock, backlog) < 0)
2321         msg_fatal("listen: %m");
2322 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/match_list.c snapshot-20010525/src/util/match_list.c
2323 --- snapshot-20010525.noipv6/src/util/match_list.c      Mon Nov 20 19:06:32 2000
2324 +++ snapshot-20010525/src/util/match_list.c     Tue May 29 18:23:16 2001
2325 @@ -107,7 +107,7 @@
2326                     list = match_list_parse(list, vstring_str(buf));
2327             if (vstream_fclose(fp))
2328                 msg_fatal("%s: read file %s: %m", myname, pattern);
2329 -       } else if (strchr(pattern, ':') != 0) { /* type:table */
2330 +       } else if ((strchr(pattern, ']') == 0) && (strchr(pattern, ':') != 0)) {        /* type:table */
2331             for (cp = pattern; *cp == '!'; cp++)
2332                  /* void */ ;
2333             if (dict_handle(pattern) == 0)
2334 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/match_ops.c snapshot-20010525/src/util/match_ops.c
2335 --- snapshot-20010525.noipv6/src/util/match_ops.c       Mon Sep  6 03:02:14 1999
2336 +++ snapshot-20010525/src/util/match_ops.c      Tue May 29 18:23:16 2001
2337 @@ -70,6 +70,307 @@
2338  #include <match_ops.h>
2339  #include <stringops.h>
2340  
2341 +#ifdef INET6
2342 +/*
2343 + *             $Id$
2344 + *
2345 + *             This program is free software; you can redistribute it and/or
2346 + *             modify it under the terms of the GNU General Public License
2347 + *             as published by the Free Software Foundation; either version
2348 + *             2 of the License, or (at your option) any later version.
2349 + *
2350 + * Authors:    Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
2351 + * 
2352 + * Modifications:
2353 + *             Artur Frysiak <wiget@pld.org.pl>
2354 + *             Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
2355 + */
2356 +
2357 +#include <stdio.h>
2358 +#include <stdlib.h>
2359 +#include <unistd.h>
2360 +#include <syslog.h>
2361 +#include <fcntl.h>
2362 +#include <sys/socket.h>
2363 +#include <netinet/in.h>
2364 +#include <string.h>
2365 +#include <netdb.h>
2366 +#include <arpa/inet.h>
2367 +#include <resolv.h>
2368 +
2369 +#ifndef        AF_DECnet
2370 +#define        AF_DECnet       12
2371 +#endif
2372 +
2373 +#ifndef        PF_PACKET
2374 +#define        PF_PACKET       17
2375 +#endif
2376 +
2377 +typedef struct
2378 +{
2379 +       unsigned char family;
2380 +       unsigned char bytelen;
2381 +       signed short  bitlen;
2382 +       unsigned int data[4];
2383 +} inet_prefix;
2384 +
2385 +/* prototypes */
2386 +int masked_match(char *, char *, char *);
2387 +int get_integer(int *, char *, int);
2388 +int get_addr_1(inet_prefix *, char *, int);
2389 +int get_prefix_1(inet_prefix *, char *, int);
2390 +int get_addr(inet_prefix *, char *, int);
2391 +int get_prefix(inet_prefix *, char *, int);
2392 +unsigned int get_addr32(char *);
2393 +int matches(char *, char *);
2394 +int inet_addr_match(inet_prefix *, inet_prefix *, int);
2395 +int mask_match(char *, char *, char *);
2396 +       
2397 +int get_integer(int *val, char *arg, int base)
2398 +{
2399 +       long res;
2400 +       char *ptr;
2401 +
2402 +       if (!arg || !*arg)
2403 +               return -1;
2404 +       res = strtol(arg, &ptr, base);
2405 +       if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
2406 +               return -1;
2407 +       *val = res;
2408 +       return 0;
2409 +}
2410 +
2411 +int get_addr_1(inet_prefix *addr, char *name, int family)
2412 +{
2413 +       char *cp;
2414 +       unsigned char *ap = (unsigned char*)addr->data;
2415 +       int i;
2416 +
2417 +       memset(addr, 0, sizeof(*addr));
2418 +
2419 +       if (strcmp(name, "default") == 0 || strcmp(name, "any") == 0) {
2420 +               if (family == AF_DECnet)
2421 +                       return -1;
2422 +               addr->family = family;
2423 +               addr->bytelen = (family == AF_INET6 ? 16 : 4);
2424 +               addr->bitlen = -1;
2425 +               return 0;
2426 +       }
2427 +
2428 +       if (strchr(name, ':')) {
2429 +               addr->family = AF_INET6;
2430 +               if (family != AF_UNSPEC && family != AF_INET6)
2431 +                       return -1;
2432 +               if (inet_pton(AF_INET6, name, addr->data) <= 0)
2433 +                       return -1;
2434 +               addr->bytelen = 16;
2435 +               addr->bitlen = -1;
2436 +               return 0;
2437 +       }
2438 +       addr->family = AF_INET;
2439 +       if (family != AF_UNSPEC && family != AF_INET)
2440 +               return -1;
2441 +       addr->bytelen = 4;
2442 +       addr->bitlen = -1;
2443 +       for (cp = name, i = 0; *cp; cp++) {
2444 +               if (*cp <= '9' && *cp >= '0') {
2445 +                       ap[i] = 10*ap[i] + (*cp-'0');
2446 +                       continue;
2447 +               }
2448 +               if (*cp == '.' && ++i <= 3)
2449 +                       continue;
2450 +               return -1;
2451 +       }
2452 +       return 0;
2453 +}
2454 +
2455 +int get_prefix_1(inet_prefix *dst, char *arg, int family)
2456 +{
2457 +       int err;
2458 +       unsigned plen;
2459 +       char *slash;
2460 +
2461 +       memset(dst, 0, sizeof(*dst));
2462 +
2463 +       if (strcmp(arg, "default") == 0 || strcmp(arg, "any") == 0) {
2464 +               if (family == AF_DECnet)
2465 +                       return -1;
2466 +               dst->family = family;
2467 +               dst->bytelen = 0;
2468 +               dst->bitlen = 0;
2469 +               return 0;
2470 +       }
2471 +
2472 +       slash = strchr(arg, '/');
2473 +       if (slash)
2474 +               *slash = 0;
2475 +       err = get_addr_1(dst, arg, family);
2476 +       if (err == 0) {
2477 +               switch(dst->family) {
2478 +                       case AF_INET6:
2479 +                               dst->bitlen = 128;
2480 +                               break;
2481 +                       case AF_DECnet:
2482 +                               dst->bitlen = 16;
2483 +                               break;
2484 +                       default:
2485 +                       case AF_INET:
2486 +                               dst->bitlen = 32;
2487 +               }
2488 +               if (slash) {
2489 +                       if (get_integer(&plen, slash+1, 0) || plen > dst->bitlen) {
2490 +                               err = -1;
2491 +                               goto done;
2492 +                       }
2493 +                       dst->bitlen = plen;
2494 +               }
2495 +       }
2496 +done:
2497 +       if (slash)
2498 +               *slash = '/';
2499 +       return err;
2500 +}
2501 +
2502 +int get_addr(inet_prefix *dst, char *arg, int family)
2503 +{
2504 +#ifdef AF_PACKET
2505 +       if (family == AF_PACKET)
2506 +               return -1;
2507 +#endif
2508 +       if (get_addr_1(dst, arg, family))
2509 +               return -1;
2510 +       return 0;
2511 +}
2512 +
2513 +int get_prefix(inet_prefix *dst, char *arg, int family)
2514 +{
2515 +#ifdef AF_PACKET
2516 +       if (family == AF_PACKET)
2517 +               return -1;
2518 +#endif
2519 +       if (get_prefix_1(dst, arg, family))
2520 +               return -1;
2521 +       return 0;
2522 +}
2523 +
2524 +unsigned int get_addr32(char *name)
2525 +{
2526 +       inet_prefix addr;
2527 +       if (get_addr_1(&addr, name, AF_INET))
2528 +               return -1;
2529 +       return addr.data[0];
2530 +}
2531 +
2532 +int matches(char *cmd, char *pattern)
2533 +{
2534 +       int len = strlen(cmd);
2535 +       if (len > strlen(pattern))
2536 +               return -1;
2537 +       return memcmp(pattern, cmd, len);
2538 +}
2539 +
2540 +int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits)
2541 +{
2542 +       unsigned int *a1 = a->data;
2543 +       unsigned int *a2 = b->data;
2544 +       int words = bits >> 0x05;
2545 +
2546 +       bits &= 0x1f;
2547 +
2548 +       if (words)
2549 +               if (memcmp(a1, a2, words << 2))
2550 +                       return -1;
2551 +
2552 +       if (bits) {
2553 +               unsigned int w1, w2;
2554 +               unsigned int mask;
2555 +
2556 +               w1 = a1[words];
2557 +               w2 = a2[words];
2558 +
2559 +               mask = htonl((0xffffffff) << (0x20 - bits));
2560 +
2561 +               if ((w1 ^ w2) & mask)
2562 +                       return 1;
2563 +       }
2564 +
2565 +       return 0;
2566 +}
2567 +
2568 +/* zero if matches */
2569 +int mask_match(char *network, char *cprefix, char *address)
2570 +{
2571 +       inet_prefix *inetwork;
2572 +       inet_prefix *iaddress;
2573 +       int ret, prefix;
2574 +
2575 +       if (!(network && address && cprefix))
2576 +               return -1;
2577 +       prefix = strtol(cprefix, (char **)NULL, 10);
2578 +       if ((prefix < 0) || (prefix > 128))
2579 +               return -1;
2580 +       if ((strlen(network) == 0) || (strlen(address) == 0))
2581 +               return -1;
2582 +
2583 +       inetwork = malloc(sizeof(inet_prefix));
2584 +       iaddress = malloc(sizeof(inet_prefix));
2585 +
2586 +       if ((get_addr(iaddress, address, AF_UNSPEC) >= 0)
2587 +                       && (get_addr(inetwork, network, AF_UNSPEC) >= 0))
2588 +               ret = inet_addr_match(inetwork, iaddress, prefix);
2589 +       else
2590 +               ret = -1;
2591 +       free(inetwork);
2592 +       free(iaddress);
2593 +
2594 +       /* 1 if matches */
2595 +       /* return (!ret); */
2596 +       /* 0 if matches */
2597 +       return ret;
2598 +}
2599 +
2600 +/*
2601 + * masked_match() - universal for IPv4 and IPv6
2602 + */
2603 +int masked_match(net_tok, mask_tok, string)
2604 +char   *net_tok;
2605 +char   *mask_tok;
2606 +char   *string;
2607 +{
2608 +#ifdef INET6
2609 +       struct in6_addr in6[2];
2610 +       char v4addr[2][INET_ADDRSTRLEN];
2611 +       char newmask[6];
2612 +       int plen;
2613 +#endif
2614 +
2615 +       /* Check for NULL */
2616 +       if (!(net_tok && mask_tok && string))
2617 +               return 1;
2618 +
2619 +       /* If IPv6 mapped convert to native-IPv4 */
2620 +#ifdef INET6
2621 +       if (inet_pton(AF_INET6, net_tok, &in6[0]) == 1 &&
2622 +           inet_pton(AF_INET6, string, &in6[1]) == 1 &&
2623 +           IN6_IS_ADDR_V4MAPPED(&in6[0]) && IN6_IS_ADDR_V4MAPPED(&in6[1])) {
2624 +               plen = atoi(mask_tok);
2625 +               if (32 < plen && plen < 129) {
2626 +                       sprintf(newmask, "%d", plen - 96);
2627 +                       mask_tok = newmask;
2628 +               }
2629 +
2630 +               (void)inet_ntop(AF_INET, &in6[0].s6_addr[12], v4addr[0],
2631 +                   sizeof(v4addr[0]));
2632 +               net_tok = v4addr[0];
2633 +               (void)inet_ntop(AF_INET, &in6[1].s6_addr[12], v4addr[1],
2634 +                   sizeof(v4addr[1]));
2635 +               string = v4addr[1];
2636 +       }
2637 +#endif
2638 +       return (!mask_match(net_tok, mask_tok, string));
2639 +}
2640 +#endif
2641 +
2642  /* match_string - match a string literal */
2643  
2644  int     match_string(const char *string, const char *pattern)
2645 @@ -158,6 +459,7 @@
2646      return (0);
2647  }
2648  
2649 +#ifndef INET6
2650  /* match_parse_mask - parse net/mask pattern */
2651  
2652  static int match_parse_mask(const char *pattern, unsigned long *net_bits,
2653 @@ -178,28 +480,55 @@
2654      myfree(saved_pattern);
2655      return (mask != 0);
2656  }
2657 +#endif
2658  
2659  /* match_hostaddr - match host by address */
2660  
2661  int     match_hostaddr(const char *addr, const char *pattern)
2662  {
2663      char   *myname = "match_hostaddr";
2664 +#ifdef INET6
2665 +    char *network, *mask, *escl, *escr, *patternx;
2666 +    struct in6_addr in6;
2667 +    char v4addr[INET_ADDRSTRLEN];
2668 +#else
2669      int     mask_shift;
2670      unsigned long mask_bits;
2671      unsigned long net_bits;
2672      unsigned long addr_bits;
2673 +#endif
2674  
2675      if (msg_verbose)
2676         msg_info("%s: %s ~? %s", myname, addr, pattern);
2677  
2678 +#ifdef INET6
2679 +    if (addr[strspn(addr, "01234567890./:abcdef")] != 0)
2680 +#else
2681      if (addr[strspn(addr, "01234567890./:")] != 0)
2682 +#endif
2683         return (0);
2684  
2685 +#ifdef INET6
2686 +    patternx = mystrdup(pattern);
2687 +    escl = strchr(patternx,'[');
2688 +    escr = strrchr(patternx,']');
2689 +    if (escl && escr) {
2690 +       *escr = 0;
2691 +       sprintf(patternx, "%s%s", escl + 1, escr + 1);
2692 +       pattern = patternx;
2693 +    }
2694 +#endif
2695 +    
2696      /*
2697       * Try dictionary lookup. This can be case insensitive. XXX Probably
2698       * should also try again after stripping least significant octets.
2699       */
2700 -    if (strchr(pattern, ':') != 0) {
2701 +#ifdef INET6
2702 +    if (!(escl && escr) && strchr(pattern, ':') != 0)
2703 +#else
2704 +    if (strchr(pattern, ':') != 0)
2705 +#endif
2706 +    {
2707         if (dict_lookup(pattern, addr) != 0)
2708             return (1);
2709         if (dict_errno != 0)
2710 @@ -210,6 +539,12 @@
2711      /*
2712       * Try an exact match with the host address.
2713       */
2714 +#ifdef INET6
2715 +    if (inet_pton(AF_INET6, addr, &in6) == 1 && IN6_IS_ADDR_V4MAPPED(&in6)) {
2716 +       (void)inet_ntop(AF_INET, &in6.s6_addr[12], v4addr, sizeof(v4addr));
2717 +       addr = v4addr;
2718 +    }
2719 +#endif
2720      if (strcasecmp(addr, pattern) == 0) {
2721         return (1);
2722      }
2723 @@ -218,6 +553,20 @@
2724       * In a net/mask pattern, the mask is specified as the number of bits of
2725       * the network part.
2726       */
2727 +#ifdef INET6
2728 +    network = mystrdup(patternx);
2729 +    mask = split_at(network, '/');
2730 +
2731 +    if (masked_match(network, mask, (char *)addr)) {
2732 +       myfree(network);
2733 +       myfree(patternx);
2734 +       return (1);
2735 +    } else {
2736 +       myfree(network);
2737 +       myfree(patternx);
2738 +    }
2739 +#else
2740 +           
2741      if (match_parse_mask(pattern, &net_bits, &mask_shift)) {
2742         addr_bits = inet_addr(addr);
2743         if (addr_bits == INADDR_NONE)
2744 @@ -225,5 +574,6 @@
2745         mask_bits = htonl((0xffffffff) << (BITS_PER_ADDR - mask_shift));
2746         return ((addr_bits & mask_bits) == (net_bits & mask_bits));
2747      }
2748 +#endif
2749      return (0);
2750  }
2751 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/sys_defs.h snapshot-20010525/src/util/sys_defs.h
2752 --- snapshot-20010525.noipv6/src/util/sys_defs.h        Tue May 29 16:03:38 2001
2753 +++ snapshot-20010525/src/util/sys_defs.h       Tue May 29 18:23:16 2001
2754 @@ -67,6 +67,10 @@
2755  #define DEF_MAILBOX_LOCK "flock, dotlock"
2756  #endif
2757  
2758 +#if ((defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105000000) || defined(USAGI_LIBINET6))
2759 +#define HAVE_GETIFADDRS
2760 +#endif
2761 +
2762   /*
2763    * UNIX on MAC.
2764    */
2765 diff -ruN --exclude *.wiget --exclude *.rej snapshot-20010525.noipv6/src/util/valid_hostname.c snapshot-20010525/src/util/valid_hostname.c
2766 --- snapshot-20010525.noipv6/src/util/valid_hostname.c  Sun Jan 28 15:10:18 2001
2767 +++ snapshot-20010525/src/util/valid_hostname.c Tue May 29 18:23:16 2001
2768 @@ -47,6 +47,13 @@
2769  #include <string.h>
2770  #include <ctype.h>
2771  
2772 +#ifdef INET6
2773 +#include <netinet/in.h>
2774 +#include <sys/socket.h>
2775 +#include <arpa/inet.h>
2776 +#include <netdb.h>
2777 +#endif
2778 +
2779  /* Utility library. */
2780  
2781  #include "msg.h"
2782 @@ -103,7 +110,23 @@
2783                     msg_warn("%s: misplaced hyphen: %.100s", myname, name);
2784                 return (0);
2785             }
2786 -       } else {
2787 +       }
2788 +#ifdef INET6
2789 +       else if (ch == ':') {
2790 +           struct addrinfo hints, *res;
2791 +
2792 +           memset(&hints, 0, sizeof(hints));
2793 +           hints.ai_family = AF_INET6;
2794 +           hints.ai_socktype = SOCK_STREAM;    /*dummy*/
2795 +           hints.ai_flags = AI_NUMERICHOST;
2796 +           if (getaddrinfo(name, "0", &hints, &res) == 0) {
2797 +               freeaddrinfo(res);
2798 +               return 1;
2799 +           } else
2800 +               return 0;
2801 +       }
2802 +#endif
2803 +       else {
2804             if (gripe)
2805                 msg_warn("%s: invalid character %d(decimal): %.100s",
2806                          myname, ch, name);
2807 @@ -135,6 +158,9 @@
2808      int     byte_count = 0;
2809      int     byte_val = 0;
2810      int     ch;
2811 +#ifdef INET6
2812 +    struct addrinfo hints, *res;
2813 +#endif
2814  
2815  #define BYTES_NEEDED   4
2816  
2817 @@ -146,6 +172,17 @@
2818             msg_warn("%s: empty address", myname);
2819         return (0);
2820      }
2821 +
2822 +#ifdef INET6
2823 +    memset(&hints, 0, sizeof(hints));
2824 +    hints.ai_family = AF_INET6;
2825 +    hints.ai_socktype = SOCK_STREAM;   /*dummy*/
2826 +    hints.ai_flags = AI_NUMERICHOST;
2827 +    if (getaddrinfo(addr, "0", &hints, &res) == 0) {
2828 +       freeaddrinfo(res);
2829 +       return 1;
2830 +    }
2831 +#endif
2832  
2833      /*
2834       * Scary code to avoid sscanf() overflow nasties.
This page took 0.283105 seconds and 4 git commands to generate.