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