2 IPv6 support depends on v6-capable getifaddrs() function
3 (i.e. from USAGI libinet6, not glibc)
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.
10 If you write (correctly working) missing code, please send
11 it to me and I'll add it to patch.
13 Jakub Bogusz <qboosh@pld.org.pl>
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
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
27 + if [ -f /usr/local/v6/lib/libinet6.a ]; then
34 +if [ -z "$INET6" -a -f /usr/include/netinet/ip6.h -a -f /usr/include/linux/icmpv6.h ]; then
39 dcosx*) SYSTEM=$VERSION;;
42 : ${CC='gcc $(WARN)'} ${OPT='-O'} ${DEBUG='-g'} ${AWK=awk}
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"
52 + CCARGS="$CCARGS -DINET6 -D__ss_family=ss_family -D__ss_len=ss_len"
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"
64 export SYSTYPE AR ARFL RANLIB SYSLIBS CC OPT DEBUG AWK OPTS
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
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 \
78 OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \
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 \
87 HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \
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 \
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
102 #include <inet_addr_list.h>
103 #include <name_mask.h>
105 +#include <sys/socket.h>
106 +#include <netinet/in.h>
110 /* Global library. */
113 const char *mynetworks(void)
115 static VSTRING *result;
117 + char hbuf[NI_MAXHOST];
121 char *myname = "mynetworks";
127 + struct sockaddr *sa;
128 + struct sockaddr_in6 *addr6;
129 + struct sockaddr_in6 *mask6;
130 + struct in6_addr net6;
134 mask_style = name_mask("mynetworks mask style", mask_styles,
135 var_mynetworks_style);
137 my_mask_list = own_inet_mask_list();
139 for (i = 0; i < my_addr_list->used; i++) {
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];
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)))
156 + case MASK_STYLE_HOST:
157 + memcpy (&net6, &(addr6->sin6_addr), sizeof(net6));
161 + msg_panic("unknown mynetworks mask style: %s",
162 + var_mynetworks_style);
164 + inet_ntop(AF_INET6, &net6, hbuf, sizeof(hbuf));
166 + msg_warn("%s: skipped network with zero mask: [%s/0]", myname, hbuf);
168 + vstring_sprintf_append(result, "[%s/%d] ", hbuf, shift);
170 + } else if (sa->sa_family != AF_INET) {
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);
176 addr = ntohl(my_addr_list->addrs[i].s_addr);
177 mask = ntohl(my_mask_list->addrs[i].s_addr);
180 switch (mask_style) {
183 mask = IN_CLASSD_NET;
184 shift = IN_CLASSD_NSHIFT;
187 + if (getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf), NULL, 0,
189 + strncpy(hbuf, "???", sizeof(hbuf));
190 + msg_fatal("%s: bad address class: %s", myname, hbuf);
192 msg_fatal("%s: bad address class: %s",
193 myname, inet_ntoa(my_addr_list->addrs[i]));
199 var_mynetworks_style);
201 net.s_addr = htonl(addr & mask);
202 + if (shift == BITS_PER_ADDR) {
204 + if (getnameinfo(sa, SA_LEN(sa), hbuf, sizeof(hbuf), NULL, 0,
206 + strncpy(hbuf, "???", sizeof(hbuf));
207 + msg_warn("%s: skipped network with zero mask: %s/0", myname, hbuf);
209 + msg_warn("%s: skipped network with zero mask: %s/0",
210 + myname, inet_ntoa(my_addr_list->addrs[i]));
214 vstring_sprintf_append(result, "%s/%d ",
215 inet_ntoa(net), BITS_PER_ADDR - shift);
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
221 #include <netinet/in.h>
222 #include <arpa/inet.h>
225 +#include <sys/socket.h>
229 #ifdef STRCASECMP_IN_STRINGS_H
231 @@ -113,10 +117,11 @@
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);
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) {
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);
259 msg_fatal("parameter %s: no local interface found for %s",
261 inet_ntoa(addr_list->addrs[nvirtual]));
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]);
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]);
284 inet_addr_list_free(&local_addrs);
287 /* own_inet_addr - is this my own internet address */
290 +int own_inet_addr(struct sockaddr * addr)
295 + struct sockaddr *sa;
297 + if (addr_list.used == 0)
298 + own_inet_addr_init(&addr_list, &mask_list);
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)
304 + switch (addr->sa_family) {
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);
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);
319 + if (memcmp(p, q, l) == 0)
325 int own_inet_addr(struct in_addr * addr)
329 for (i = 0; i < addr_list.used; i++)
330 if (addr->s_addr == addr_list.addrs[i].s_addr)
336 /* own_inet_addr_list - return list of addresses */
340 /* proxy_inet_addr - is this my proxy internet address */
343 +int proxy_inet_addr(struct sockaddr * addr)
348 + struct sockaddr *sa;
350 + if (*var_proxy_interfaces == 0)
353 + if (proxy_list.used == 0)
354 + proxy_inet_addr_init(&proxy_list);
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)
360 + switch (addr->sa_family) {
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);
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);
375 + if (memcmp(p, q, l) == 0)
381 int proxy_inet_addr(struct in_addr * addr)
390 /* proxy_inet_addr_list - return list of addresses */
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
398 #include <netinet/in.h>
400 +#include <sys/socket.h>
404 * External interface.
407 +extern int own_inet_addr(struct sockaddr *);
409 extern int own_inet_addr(struct in_addr *);
411 extern struct INET_ADDR_LIST *own_inet_addr_list(void);
412 extern struct INET_ADDR_LIST *own_inet_mask_list(void);
414 +extern int proxy_inet_addr(struct sockaddr *);
416 extern int proxy_inet_addr(struct in_addr *);
418 extern struct INET_ADDR_LIST *proxy_inet_addr_list(void);
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
425 PEER_NAME *peer_name(int sock)
427 static PEER_NAME peer;
428 - struct sockaddr_in sin;
429 - SOCKADDR_SIZE len = sizeof(sin);
436 + struct sockaddr peer_un;
437 + struct sockaddr_in peer_un4;
439 + struct sockaddr_in6 peer_un6;
442 +#define sun p_un.peer_un
443 +#define sin p_un.peer_un4
445 +#define sin6 p_un.peer_un6
446 + static char hbuf[NI_MAXHOST];
447 + static char abuf[NI_MAXHOST];
451 + SOCKADDR_SIZE len = sizeof(p_un);
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) {
459 peer.type = PEER_TYPE_INET;
460 hp = gethostbyaddr((char *) &(sin.sin_addr),
462 hp->h_name : "unknown");
463 peer.addr = inet_ntoa(sin.sin_addr);
467 + peer.type = PEER_TYPE_INET;
468 + if (getnameinfo(&sun, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) != 0)
469 + peer.name = "unknown";
475 + peer.type = PEER_TYPE_INET6;
476 + if (getnameinfo(&sun, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD) != 0)
477 + peer.name = "unknown";
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
490 #define PEER_TYPE_UNKNOWN 0
491 #define PEER_TYPE_INET 1
492 #define PEER_TYPE_LOCAL 2
494 +#define PEER_TYPE_INET6 3
497 extern PEER_NAME *peer_name(int);
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
503 #include <netinet/in.h>
504 #include <arpa/inet.h>
509 #define INADDR_NONE 0xffffffff
512 char *saved_addr = mystrdup(addr);
515 + struct addrinfo hints, *res, *res0;
518 struct in_addr ipaddr;
522 #define RETURN(x) { myfree(saved_addr); return(x); }
524 if (*dest == '[' && dest[len - 1] == ']') {
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);
533 + for (res = res0; res; res = res->ai_next) {
534 + if (own_inet_addr(res->ai_addr)) {
535 + freeaddrinfo(res0);
539 + freeaddrinfo(res0);
542 if ((ipaddr.s_addr = inet_addr(dest)) != INADDR_NONE
543 && (own_inet_addr(&ipaddr) || proxy_inet_addr(&ipaddr)))
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
553 +/* System library. */
555 +#include <sys_defs.h>
556 +#include <netinet/in.h>
557 +#include <arpa/inet.h>
560 +#include <sys/socket.h>
564 +#ifdef STRCASECMP_IN_STRINGS_H
565 +#include <strings.h>
568 +/* Utility library. */
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>
577 +/* Global library. */
579 +#include <mail_params.h>
580 +#include <wildcard_inet_addr.h>
582 +/* Application-specific. */
583 +static INET_ADDR_LIST addr_list;
585 +/* wildcard_inet_addr_init - initialize my own address list */
587 +static void wildcard_inet_addr_init(INET_ADDR_LIST *addr_list)
590 + struct addrinfo hints, *res, *res0;
591 + char hbuf[NI_MAXHOST];
593 +#ifdef NI_WITHSCOPEID
594 + const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
596 + const int niflags = NI_NUMERICHOST;
599 + inet_addr_list_init(addr_list);
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);
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)
611 + if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
612 + NULL, 0, niflags) != 0)
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); */
618 + freeaddrinfo(res0);
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");
626 +/* wildcard_inet_addr_list - return list of addresses */
628 +INET_ADDR_LIST *wildcard_inet_addr_list(void)
630 + if (addr_list.used == 0)
631 + wildcard_inet_addr_init(&addr_list);
633 + return (&addr_list);
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
639 +#ifndef _WILDCARD_INET_ADDR_H_INCLUDED_
640 +#define _WILDCARD_INET_ADDR_H_INCLUDED_
644 +/* wildcard_inet_addr_list 3h
646 +/* grab the list of wildcard IP addresses.
648 +/* #include <own_inet_addr.h>
656 +#include <netinet/in.h>
658 +#include <sys/socket.h>
662 + * External interface.
664 +extern struct INET_ADDR_LIST *wildcard_inet_addr_list(void);
671 +/* Jun-ichiro itojun Hagino
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
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) {
683 + MASTER_INET_ADDRLIST(serv) = wildcard_inet_addr_list();
684 + serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
686 MASTER_INET_ADDRLIST(serv) = 0; /* wild-card */
687 serv->listen_fd_count = 1;
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
704 /* master_listen_init - enable connection requests */
706 void master_listen_init(MASTER_SERV *serv)
708 char *myname = "master_listen_init";
713 + char hbuf[NI_MAXHOST];
714 + SOCKADDR_SIZE salen;
718 * Find out what transport we should use, then create one or more
719 @@ -111,18 +120,31 @@
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++) {
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));
735 + end_point = concatenate(hbuf, ":", MASTER_INET_PORT(serv), (char *) 0);
737 end_point = concatenate(inet_ntoa(MASTER_INET_ADDRLIST(serv)->addrs[n]),
738 ":", MASTER_INET_PORT(serv), (char *) 0);
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);
747 + serv->listen_fd[m] = tmpfd;
748 + close_on_exec(serv->listen_fd[m++], CLOSE_ON_EXEC);
752 + serv->listen_fd_count=m;
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
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)
774 - struct in_addr in_addr;
776 + struct sockaddr_storage ss;
778 + struct sockaddr ss;
780 + struct sockaddr_in *sin;
782 + struct sockaddr_in6 *sin6;
783 + char hbuf[NI_MAXHOST];
785 + char hbuf[sizeof("255.255.255.255") + 1];
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);
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);
801 + switch (addr->type) {
803 + if (addr->data_len != sizeof(sin->sin_addr)) {
804 + msg_warn("skipping invalid address (AAAA, len=%u)",
808 + sin = (struct sockaddr_in *)&ss;
809 + memset(sin, 0, sizeof(*sin));
810 + sin->sin_family = AF_INET;
812 + sin->sin_len = sizeof(*sin);
814 + memcpy(&sin->sin_addr, addr->data, sizeof(sin->sin_addr));
818 + if (addr->data_len != sizeof(sin6->sin6_addr)) {
819 + msg_warn("skipping invalid address (AAAA, len=%u)",
823 + sin6 = (struct sockaddr_in6 *)&ss;
824 + memset(sin6, 0, sizeof(*sin6));
825 + sin6->sin6_family = AF_INET6;
827 + sin6->sin6_len = sizeof(*sin6);
829 + memcpy(&sin6->sin6_addr, addr->data, sizeof(sin6->sin6_addr));
833 + msg_warn("skipping unsupported address (type=%u)", addr->type);
838 + (void)getnameinfo((struct sockaddr *)&ss, SS_LEN(ss),
839 + hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
841 + (void)inet_ntop(AF_INET, &sin->sin_addr, hbuf, sizeof(hbuf));
843 + msg_info("pref %4d host %s/%s", addr->pref, addr->name, hbuf);
845 msg_info("end %s address list", what);
847 @@ -155,15 +205,23 @@
848 static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRING *why)
850 char *myname = "smtp_addr_one";
852 struct in_addr inaddr;
858 + struct addrinfo hints, *res0, *res;
866 msg_info("%s: host %s", myname, host);
870 * Interpret a numerical name as an address.
873 smtp_errno = SMTP_FAIL;
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);
884 + smtp_errno = SMTP_RETRY;
887 + vstring_sprintf(why, "[%s]: %s",host,gai_strerror(error));
888 + smtp_errno = SMTP_FAIL;
891 + return (addr_list);
893 + for (res = res0; res; res = res->ai_next) {
894 + memset((char *) &fixed, 0, sizeof(fixed));
895 + switch(res->ai_family) {
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);
904 + addr = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr;
905 + addrlen = sizeof(struct in_addr);
908 + msg_warn("%s: unknown address family %d for %s",
909 + myname, res->ai_family, host);
912 + addr_list = dns_rr_append(addr_list,
913 + dns_rr_create(host, &fixed, pref, addr, addrlen));
916 + freeaddrinfo(res0);
922 INET_ADDR_LIST *self;
926 + struct sockaddr *sa;
930 * Find the first address that lists any address that this mail system is
931 @@ -260,12 +363,36 @@
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++) {
938 + sa = (struct sockaddr *)&self->addrs[i];
939 + switch(addr->type) {
942 + if (sa->sa_family != AF_INET6)
944 + if (memcmp(&((struct sockaddr_in6 *)sa)->sin6_addr,
945 + addr->data, sizeof(struct in6_addr)) == 0) {
950 + if (sa->sa_family != AF_INET)
952 + if (memcmp(&((struct sockaddr_in *)sa)->sin_addr,
953 + addr->data, sizeof(struct in_addr)) == 0) {
959 if (INADDRP(addr->data)->s_addr == self->addrs[i].s_addr) {
961 msg_info("%s: found at pref %d", myname, addr->pref);
969 @@ -273,12 +400,36 @@
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++) {
976 + sa = (struct sockaddr *)&self->addrs[i];
977 + switch(addr->type) {
980 + if (sa->sa_family != AF_INET6)
982 + if (memcmp(&((struct sockaddr_in6 *)sa)->sin6_addr,
983 + addr->data, sizeof(struct in6_addr)) == 0) {
988 + if (sa->sa_family != AF_INET)
990 + if (memcmp(&((struct sockaddr_in *)sa)->sin_addr,
991 + addr->data, sizeof(struct in_addr)) == 0) {
997 if (INADDRP(addr->data)->s_addr == self->addrs[i].s_addr) {
999 msg_info("%s: found at pref %d", myname, addr->pref);
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
1011 /* System library. */
1013 #include <sys_defs.h>
1014 +#include <stdlib.h>
1015 #include <sys/socket.h>
1016 #include <netinet/in.h>
1017 #include <arpa/inet.h>
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>
1026 @@ -134,19 +136,45 @@
1029 char *myname = "smtp_connect_addr";
1030 - struct sockaddr_in sin;
1033 + struct sockaddr_storage ss;
1035 + struct sockaddr ss;
1037 + struct sockaddr *sa;
1038 + struct sockaddr_in *sin;
1040 + struct sockaddr_in6 *sin6;
1042 + SOCKADDR_SIZE salen;
1044 + char hbuf[NI_MAXHOST];
1046 + char hbuf[sizeof("255.255.255.255") + 1];
1049 INET_ADDR_LIST *addr_list;
1054 - unsigned long inaddr;
1056 + sa = (struct sockaddr *)&ss;
1057 + sin = (struct sockaddr_in *)&ss;
1059 + sin6 = (struct sockaddr_in6 *)&ss;
1065 - if (addr->data_len > sizeof(sin.sin_addr)) {
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))))
1070 + if (addr->data_len > sizeof(sin->sin_addr))
1073 msg_warn("%s: skip address with length %d", myname, addr->data_len);
1074 smtp_errno = SMTP_RETRY;
1076 @@ -155,17 +183,39 @@
1080 - memset((char *) &sin, 0, sizeof(sin));
1081 - sin.sin_family = AF_INET;
1083 - if ((sock = socket(sin.sin_family, SOCK_STREAM, 0)) < 0)
1084 - msg_fatal("%s: socket: %m", myname);
1086 + switch (addr->type) {
1089 + memset(sin6, 0, sizeof(*sin6));
1090 + sin6->sin6_family = AF_INET6;
1091 + salen = sizeof(*sin6);
1094 + default: /* T_A: */
1095 + memset(sin, 0, sizeof(*sin));
1096 + sin->sin_family = AF_INET;
1097 + salen = sizeof(*sin);
1101 + sa->sa_len = salen;
1103 + if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
1104 + msg_warn("%s: socket: %m", myname);
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.
1110 if (*var_smtp_bind_addr) {
1112 + struct sockaddr_in sin;
1114 + memset(&sin, 0, sizeof(sin));
1115 + sin.sin_family = AF_INET;
1117 + sin.sin_len = sizeof(sin);
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));
1125 msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
1127 + char hbufl[NI_MAXHOST];
1128 + struct addrinfo hints, *res;
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);
1142 + msg_info("%s: bind %s", myname, hbufl);
1148 @@ -181,8 +250,17 @@
1149 * the mail appears to come from the "right" machine address.
1151 else if ((addr_list = own_inet_addr_list())->used == 1) {
1153 + struct sockaddr_in sin;
1154 + unsigned long inaddr; /*XXX BAD!*/
1156 + memset(&sin, 0, sizeof(sin));
1157 + sin.sin_family = AF_INET;
1159 + sin.sin_len = sizeof(sin);
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 @@
1169 msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
1172 + char hbufl[NI_MAXHOST];
1173 + struct addrinfo hints, *res = NULL, *loopback = NULL;
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)
1182 + * getnameinfo -> getaddrinfo loop is here so that we can
1183 + * get rid of port.
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);
1198 + msg_info("%s: bind %s", myname, hbufl);
1201 + freeaddrinfo(res);
1203 + freeaddrinfo(loopback);
1208 * Connect to the SMTP server.
1210 - sin.sin_port = port;
1211 - memcpy((char *) &sin.sin_addr, addr->data, sizeof(sin.sin_addr));
1212 + switch (addr->type) {
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));
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));
1234 + sa->sa_len = salen;
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;
1250 - conn_stat = connect(sock, (struct sockaddr *) & sin, sizeof(sin));
1251 + conn_stat = connect(sock, sa, salen);
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;
1261 * Skip this host if it takes no action within some time limit.
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;
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);
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);
1289 @@ -259,12 +392,12 @@
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);
1299 - return (smtp_session_alloc(dest, stream, addr->name, inet_ntoa(sin.sin_addr)));
1300 + return (smtp_session_alloc(dest, stream, addr->name, hbuf));
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
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,
1317 vstring_strcpy(fqdn, name);
1318 htable_enter(cache, name, result = vstring_export(fqdn));
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)
1328 + char *myname = "has_my_addr";
1329 + struct addrinfo hints, *res, *res0;
1331 + char hbuf[NI_MAXHOST];
1334 + msg_info("%s: host %s", myname, host);
1337 + * If we can't lookup the host, play safe and assume it is OK.
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);
1348 + msg_info("%s: host %s: %s", myname, host, gai_strerror(error));
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));
1357 + msg_info("%s: addr %s", myname, hbuf);
1359 + if (own_inet_addr(res->ai_addr)) {
1360 + freeaddrinfo(res0);
1364 + freeaddrinfo(res0);
1366 + msg_info("%s: host %s: no match", myname, host);
1370 char *myname = "has_my_addr";
1371 struct in_addr addr;
1373 @@ -1400,6 +1443,7 @@
1374 msg_info("%s: host %s: no match", myname, host);
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); }
1384 addr = STR(vstring_strcpy(error_text, address));
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);
1393 if ((dict = dict_handle(table)) == 0)
1394 msg_panic("%s: dictionary not found: %s", myname, table);
1396 if (flags == 0 || (flags & dict->flags) != 0) {
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,
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 @@
1414 SMTPD_RBL_STATE *rbl;
1418 + struct in6_addr a;
1422 msg_info("%s: %s %s", myname, reply_class, addr);
1425 - * IPv4 only for now
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, ".");
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, ".");
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, ".");
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
1455 +/* Utility library. */
1458 +#include <mymalloc.h>
1459 +#include <valid_hostname.h>
1460 +#include <stringops.h>
1462 +/* Global library. */
1465 * Older systems don't have h_errno. Even modern systems don't have
1471 -/* Utility library. */
1474 -#include <mymalloc.h>
1475 -#include <valid_hostname.h>
1476 -#include <stringops.h>
1478 -/* Global library. */
1482 +#define GAI_STRERROR(error) \
1483 + ((error = EAI_SYSTEM) ? gai_strerror(error) : strerror(errno))
1486 /* Application-specific. */
1489 @@ -102,21 +106,28 @@
1491 void smtpd_peer_init(SMTPD_STATE *state)
1493 - struct sockaddr_in sin;
1494 - SOCKADDR_SIZE len = sizeof(sin);
1496 + struct sockaddr_storage ss;
1498 + struct sockaddr ss;
1499 + struct in_addr *in;
1503 + struct sockaddr *sa;
1504 + SOCKADDR_SIZE len;
1506 + sa = (struct sockaddr *)&ss;
1510 * Avoid suprious complaints from Purify on Solaris.
1512 - memset((char *) &sin, 0, len);
1513 + memset((char *) sa, 0, len);
1516 * Look up the peer address information.
1518 - if (getpeername(vstream_fileno(state->client),
1519 - (struct sockaddr *) & sin, &len) >= 0) {
1520 + if (getpeername(vstream_fileno(state->client), sa, &len) >= 0) {
1524 @@ -132,23 +143,56 @@
1526 * Look up and "verify" the client hostname.
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);
1533 + else if (errno == 0 && (sa->sa_family == AF_INET
1535 + || sa->sa_family == AF_INET6
1539 + char hbuf[NI_MAXHOST];
1540 + char abuf[NI_MAXHOST];
1541 + struct addrinfo hints, *rnull = NULL;
1543 + char abuf[sizeof("255.255.255.255") + 1];
1549 + (void)getnameinfo(sa, len, abuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
1551 + in = &((struct sockaddr_in *)sa)->sin_addr;
1552 + inet_ntop(AF_INET, in, abuf, sizeof(hbuf));
1554 + state->addr = mystrdup(abuf);
1556 + error = getnameinfo(sa, len, hbuf, sizeof(hbuf), NULL, 0, NI_NAMEREQD);
1559 + hp = gethostbyaddr((char *)in, sizeof(*in), AF_INET);
1562 + hbuf = mystrdup(hp->h_name);
1567 state->name = mystrdup("unknown");
1569 + state->peer_code = (error == EAI_AGAIN ? 4 : 5);
1571 state->peer_code = (h_errno == TRY_AGAIN ? 4 : 5);
1572 - } else if (valid_hostaddr(hp->h_name, DONT_GRIPE)) {
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;
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;
1590 @@ -160,16 +204,31 @@
1591 state->peer_code = code; \
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);
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));
1604 + /* memcmp() isn't needed if we use getaddrinfo */
1606 + freeaddrinfo(rnull);
1608 hp = gethostbyname(state->name); /* clobbers hp->name!! */
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);
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);
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 */
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
1643 if (strncmp(argv[optind], "inet:", 5) == 0)
1645 - sock = inet_listen(argv[optind], backlog, BLOCKING);
1646 + sock = inet_listen(argv[optind], backlog, BLOCKING, 1);
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
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 \
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 \
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 \
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
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
1704 +/* trivial host and port extracter
1706 +/* #include <get_port.h>
1708 +/* char *get_port(data)
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.
1717 +/* If port not found return null pointer.
1721 +/* BSD Style (or BSD like) license.
1723 +/* Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
1727 +/* System libraries */
1729 +#include <sys_defs.h>
1730 +#include <string.h>
1732 +/* Utility library. */
1734 +#include "get_port.h"
1736 +/* get_port - extract port number from string */
1738 +char *get_port(char *data)
1740 + const char *escl=strchr(data,'[');
1741 + const char *sepl=strchr(data,':');
1742 + char *escr=strrchr(data,']');
1743 + char *sepr=strrchr(data,':');
1745 + /* extract from "[address]:port" or "[address]"*/
1748 + memmove(data, data + 1, strlen(data) - strlen(escr));
1749 + data[strlen(data) - strlen(escr) - 1] = 0;
1753 + return (*escr ? escr : NULL);
1755 + /* extract from "address:port" or "address" */
1756 + if ((sepl == sepr) && sepr && sepl)
1762 + /* return empty string */
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
1769 +#ifndef _GET_PORT_H_INCLUDED_
1770 +#define _GET_PORT_H_INCLUDED_
1776 +/* trivial host and port extracter
1778 +/* #include <get_port.h>
1782 + /* External interface. */
1784 +extern char *get_port(char *);
1790 +/* BSD Style (or BSD like) license.
1792 +/* Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
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
1801 #include <sys_defs.h>
1802 #include <netinet/in.h>
1803 #include <arpa/inet.h>
1804 +#include <sys/socket.h>
1806 +#include <stdlib.h>
1807 +#include <string.h>
1810 #define INADDR_NONE 0xffffffff
1813 #include <inet_addr_list.h>
1814 #include <inet_addr_host.h>
1819 /* inet_addr_host - look up address list for host */
1821 int inet_addr_host(INET_ADDR_LIST *addr_list, const char *hostname)
1825 + struct addrinfo hints, *res0, *res;
1827 + char buforhosta[1024];
1832 struct in_addr addr;
1834 int initial_count = addr_list->used;
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);
1842 + for (res = res0; res; res = res->ai_next) {
1843 + if(res->ai_family != AF_INET && res->ai_family != AF_INET6)
1845 + /* filter out address families that are not supported */
1846 + s = socket(res->ai_family, SOCK_DGRAM, 0);
1851 + inet_addr_list_append(addr_list, res->ai_addr);
1853 + freeaddrinfo(res0);
1856 if ((addr.s_addr = inet_addr(hostname)) != INADDR_NONE) {
1857 inet_addr_list_append(addr_list, &addr);
1860 inet_addr_list_append(addr_list,
1861 (struct in_addr *) * hp->h_addr_list++);
1865 return (addr_list->used - initial_count);
1874 INET_ADDR_LIST addr_list;
1876 + struct sockaddr *sa;
1877 + char hbuf[NI_MAXHOST];
1879 msg_vstream_init(argv[0], VSTREAM_ERR);
1882 if (inet_addr_host(&addr_list, *argv) == 0)
1883 msg_fatal("not found: %s", *argv);
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,
1891 + vstream_printf("%s\n", hbuf);
1893 vstream_fflush(VSTREAM_OUT);
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
1900 #include <arpa/inet.h>
1906 +#include <string.h>
1907 +#include <sys/socket.h>
1910 /* Utility library. */
1918 + list->addrs = (struct sockaddr_storage *)
1920 list->addrs = (struct in_addr *)
1922 mymalloc(sizeof(*list->addrs) * list->size);
1925 /* inet_addr_list_append - append address to internet address list */
1928 +void inet_addr_list_append(INET_ADDR_LIST *list,
1929 + struct sockaddr * addr)
1931 + char *myname = "inet_addr_list_append";
1932 + char hbuf[NI_MAXHOST];
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));
1939 + msg_info("%s: %s", myname, hbuf);
1942 + if (list->used >= list->size)
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));
1950 void inet_addr_list_append(INET_ADDR_LIST *list, struct in_addr * addr)
1952 char *myname = "inet_addr_list_append";
1953 @@ -83,15 +117,22 @@
1954 sizeof(*list->addrs) * list->size);
1955 list->addrs[list->used++] = *addr;
1959 /* inet_addr_list_comp - compare addresses */
1961 static int inet_addr_list_comp(const void *a, const void *b)
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));
1968 const struct in_addr *a_addr = (const struct in_addr *) a;
1969 const struct in_addr *b_addr = (const struct in_addr *) b;
1971 return (a_addr->s_addr - b_addr->s_addr);
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
1981 #include <netinet/in.h>
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))
1988 +#define SA_LEN(x) ((x)->sa_len)
1989 +#define SS_LEN(x) ((x).ss_len)
1994 * External interface.
1996 typedef struct INET_ADDR_LIST {
1997 int used; /* nr of elements in use */
1998 int size; /* actual list size */
2000 + struct sockaddr_storage *addrs; /* payload */
2002 struct in_addr *addrs; /* payload */
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 *);
2011 +extern void inet_addr_list_append(INET_ADDR_LIST *, struct sockaddr *);
2013 extern void inet_addr_list_append(INET_ADDR_LIST *, struct in_addr *);
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
2025 +#if defined(INET6) && (defined (LINUX) || defined (LINUX2))
2029 +#ifdef HAVE_GETIFADDRS
2030 +#include <ifaddrs.h>
2033 /* Utility library. */
2035 @@ -78,18 +85,104 @@
2037 int inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list)
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;
2046 + struct sockaddr_in6 addr6;
2049 + void *addr,*addrm;
2052 + if (getifaddrs(&ifap) < 0)
2053 + msg_fatal("%s: getifaddrs: %m", myname);
2055 + for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
2056 + if ((!(ifa->ifa_flags & IFF_RUNNING)) || (ifa->ifa_addr == NULL) || (ifa->ifa_netmask == NULL))
2058 + sa = ifa->ifa_addr;
2059 + sam = ifa->ifa_netmask;
2060 + switch (ifa->ifa_addr->sa_family) {
2063 + addr = (void *)&((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
2064 + addrm = (void *)&((struct sockaddr_in *)ifa->ifa_netmask)->sin_addr;
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;
2088 + inet_addr_list_append(addr_list, sa);
2089 + if (mask_list != NULL)
2090 + inet_addr_list_append(mask_list, sam);
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);
2098 + freeifaddrs(ifap);
2099 + return (addr_list->used - initial_count);
2101 char *myname = "inet_addr_local";
2104 struct ifreq *the_end;
2106 - VSTRING *buf = vstring_alloc(1024);
2108 int initial_count = addr_list->used;
2109 struct in_addr addr;
2110 struct ifreq *ifr_mask;
2113 +#if defined (LINUX) || defined (LINUX2)
2114 +#define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
2116 + char addr6p[8][5], addr6res[40], devname[20];
2117 + int plen, scope, dad_status, if_idx, gaierror;
2118 + struct addrinfo hints, *res, *res0;
2120 + struct sockaddr_in6 addr6;
2124 + buf = vstring_alloc(1024);
2126 - if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
2127 + if ((sock = socket(af, SOCK_DGRAM, 0)) < 0) {
2129 + if (af == AF_INET6)
2132 + msg_warn("%s: socket: %m", myname);
2137 msg_fatal("%s: socket: %m", myname);
2141 * Get the network interface list. XXX The socket API appears to have no
2142 @@ -126,10 +219,15 @@
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 */
2152 + inet_addr_list_append(addr_list, &ifr->ifr_addr);
2154 inet_addr_list_append(addr_list, &addr);
2157 ifr_mask = (struct ifreq *) mymalloc(IFREQ_SIZE(ifr));
2158 memcpy((char *) ifr_mask, (char *) ifr, IFREQ_SIZE(ifr));
2159 @@ -141,11 +239,70 @@
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);
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;
2177 + if (!(IN6_IS_ADDR_UNSPECIFIED(&addr6.sin6_addr))) {
2178 + inet_addr_list_append(addr_list, (struct sockaddr *)&addr6);
2180 +#error "mask_list for IPv6 without libinet6 not done yet (error to avoid open-relay)"
2181 + /* TODO: how to get netmask here? */
2186 ifr = NEXT_INTERFACE(ifr);
2192 + if (af != AF_INET6) {
2194 + goto other_socket_type;
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);
2212 + for (res = res0; res; res = res->ai_next) {
2213 + inet_addr_list_append(addr_list, res->ai_addr);
2215 +#error "mask_list for IPv6 without libinet6 not done yet (error to avoid open-relay)"
2216 + /* TODO: calculate netmask basing on plen */
2219 + freeaddrinfo(res0);
2225 return (addr_list->used - initial_count);
2231 INET_ADDR_LIST addr_list;
2232 INET_ADDR_LIST mask_list;
2234 + char abuf[NI_MAXHOST], mbuf[NI_MAXHOST];
2235 + struct sockaddr *sa;
2237 msg_vstream_init(argv[0], VSTREAM_ERR);
2239 @@ -172,8 +331,17 @@
2240 msg_warn("found only one active network interface");
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));
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));
2255 + vstream_printf("%s/%s\n", abuf, mbuf);
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
2270 /* Utility library. */
2277 + struct addrinfo hints, *res, *res0;
2280 struct sockaddr_in sin;
2288 buf = inet_parse(addr, &host, &port);
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);
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");
2310 + for (res = res0; res; res = res->ai_next) {
2311 + if ((res->ai_family != AF_INET) && (res->ai_family != AF_INET6))
2314 + sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
2317 + if (timeout > 0) {
2318 + non_blocking(sock, NON_BLOCKING);
2319 + if (timed_connect(sock, res->ai_addr, res->ai_addrlen, timeout) < 0) {
2324 + if (block_mode != NON_BLOCKING)
2325 + non_blocking(sock, block_mode);
2328 + non_blocking(sock, block_mode);
2329 + if (connect(sock, res->ai_addr, res->ai_addrlen) < 0
2330 + && errno != EINPROGRESS) {
2338 + freeaddrinfo(res0);
2342 * Create a client socket.
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
2355 /* #include <listen.h>
2357 -/* int inet_listen(addr, backlog, block_mode)
2358 +/* int inet_listen(addr, backlog, block_mode, addinuse_fatal)
2359 /* const char *addr;
2363 #include <sys_defs.h>
2364 #include <sys/socket.h>
2365 #include <netinet/in.h>
2367 +#if (! __GLIBC__ >= 2 && __GLIBC_MINOR__ >=1 )
2368 +#include <netinet6/in6.h>
2371 #include <arpa/inet.h>
2373 #ifndef MAXHOSTNAMELEN
2374 #include <sys/param.h>
2380 @@ -77,35 +83,116 @@
2382 /* inet_listen - create inet-domain listener */
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)
2388 + struct addrinfo *res, *res0, hints;
2395 + struct sockaddr *ai_addr;
2396 + SOCKADDR_SIZE ai_addrlen;
2397 + struct ai *ai_next;
2398 + } *res, *res0, resbody;
2399 struct sockaddr_in sin;
2403 + int addrinuse = 0;
2408 + char hbuf[NI_MAXHOST], pbuf[NI_MAXSERV];
2410 + char hbuf[sizeof("255.255.255.255") + 1];
2411 + char pbuf[sizeof("255.255.255.255") + 1];
2413 + char *cause = "unknown";
2416 * Translate address information to internal form.
2418 buf = inet_parse(addr, &host, &port);
2419 - memset((char *) &sin, 0, sizeof(sin));
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);
2427 + msg_fatal("getaddrinfo: %s", gai_strerror(error));
2431 + memset(&sin, 0, sizeof(sin));
2432 sin.sin_family = AF_INET;
2434 + sin.sin_len = sizeof(sin);
2436 sin.sin_port = find_inet_port(port, "tcp");
2437 sin.sin_addr.s_addr = (*host ? find_inet_addr(host) : INADDR_ANY);
2441 - * Create a listener socket.
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);
2460 + for (res = res0; res; res = res->ai_next) {
2461 + if ((res->ai_family != AF_INET) && (res->ai_family != AF_INET6))
2465 + * Create a listener socket.
2467 + if ((sock = socket(res->ai_family, res->ai_socktype, 0)) < 0) {
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)";
2483 + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) < 0) {
2484 + cause = "setsockopt(SO_REUSEADDR)";
2490 + if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
2492 + if (errno == EADDRINUSE)
2500 + if (sock < 0 && (addrinuse_fatal || !addrinuse))
2501 + msg_fatal("%s: %m", cause);
2503 + freeaddrinfo(res0);
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
2514 * Listener external interface.
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);
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
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++)
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
2538 #include <match_ops.h>
2539 #include <stringops.h>
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.
2550 + * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
2553 + * Artur Frysiak <wiget@pld.org.pl>
2554 + * Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>
2558 +#include <stdlib.h>
2559 +#include <unistd.h>
2560 +#include <syslog.h>
2562 +#include <sys/socket.h>
2563 +#include <netinet/in.h>
2564 +#include <string.h>
2566 +#include <arpa/inet.h>
2567 +#include <resolv.h>
2570 +#define AF_DECnet 12
2574 +#define PF_PACKET 17
2579 + unsigned char family;
2580 + unsigned char bytelen;
2581 + signed short bitlen;
2582 + unsigned int data[4];
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 *);
2597 +int get_integer(int *val, char *arg, int base)
2602 + if (!arg || !*arg)
2604 + res = strtol(arg, &ptr, base);
2605 + if (!ptr || ptr == arg || *ptr || res > INT_MAX || res < INT_MIN)
2611 +int get_addr_1(inet_prefix *addr, char *name, int family)
2614 + unsigned char *ap = (unsigned char*)addr->data;
2617 + memset(addr, 0, sizeof(*addr));
2619 + if (strcmp(name, "default") == 0 || strcmp(name, "any") == 0) {
2620 + if (family == AF_DECnet)
2622 + addr->family = family;
2623 + addr->bytelen = (family == AF_INET6 ? 16 : 4);
2624 + addr->bitlen = -1;
2628 + if (strchr(name, ':')) {
2629 + addr->family = AF_INET6;
2630 + if (family != AF_UNSPEC && family != AF_INET6)
2632 + if (inet_pton(AF_INET6, name, addr->data) <= 0)
2634 + addr->bytelen = 16;
2635 + addr->bitlen = -1;
2638 + addr->family = AF_INET;
2639 + if (family != AF_UNSPEC && family != AF_INET)
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');
2648 + if (*cp == '.' && ++i <= 3)
2655 +int get_prefix_1(inet_prefix *dst, char *arg, int family)
2661 + memset(dst, 0, sizeof(*dst));
2663 + if (strcmp(arg, "default") == 0 || strcmp(arg, "any") == 0) {
2664 + if (family == AF_DECnet)
2666 + dst->family = family;
2672 + slash = strchr(arg, '/');
2675 + err = get_addr_1(dst, arg, family);
2677 + switch(dst->family) {
2679 + dst->bitlen = 128;
2689 + if (get_integer(&plen, slash+1, 0) || plen > dst->bitlen) {
2693 + dst->bitlen = plen;
2702 +int get_addr(inet_prefix *dst, char *arg, int family)
2705 + if (family == AF_PACKET)
2708 + if (get_addr_1(dst, arg, family))
2713 +int get_prefix(inet_prefix *dst, char *arg, int family)
2716 + if (family == AF_PACKET)
2719 + if (get_prefix_1(dst, arg, family))
2724 +unsigned int get_addr32(char *name)
2727 + if (get_addr_1(&addr, name, AF_INET))
2729 + return addr.data[0];
2732 +int matches(char *cmd, char *pattern)
2734 + int len = strlen(cmd);
2735 + if (len > strlen(pattern))
2737 + return memcmp(pattern, cmd, len);
2740 +int inet_addr_match(inet_prefix *a, inet_prefix *b, int bits)
2742 + unsigned int *a1 = a->data;
2743 + unsigned int *a2 = b->data;
2744 + int words = bits >> 0x05;
2749 + if (memcmp(a1, a2, words << 2))
2753 + unsigned int w1, w2;
2754 + unsigned int mask;
2759 + mask = htonl((0xffffffff) << (0x20 - bits));
2761 + if ((w1 ^ w2) & mask)
2768 +/* zero if matches */
2769 +int mask_match(char *network, char *cprefix, char *address)
2771 + inet_prefix *inetwork;
2772 + inet_prefix *iaddress;
2775 + if (!(network && address && cprefix))
2777 + prefix = strtol(cprefix, (char **)NULL, 10);
2778 + if ((prefix < 0) || (prefix > 128))
2780 + if ((strlen(network) == 0) || (strlen(address) == 0))
2783 + inetwork = malloc(sizeof(inet_prefix));
2784 + iaddress = malloc(sizeof(inet_prefix));
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);
2794 + /* 1 if matches */
2795 + /* return (!ret); */
2796 + /* 0 if matches */
2801 + * masked_match() - universal for IPv4 and IPv6 - 1 if matches
2803 +int masked_match(net_tok, mask_tok, string)
2809 + struct in6_addr in6[2];
2810 + char v4addr[2][INET_ADDRSTRLEN];
2815 + /* Check for NULL */
2816 + if (!(net_tok && mask_tok && string))
2817 + return 0; /* doesn't match!!! */
2819 + /* If IPv6 mapped convert to native-IPv4 */
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;
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];
2838 + return (!mask_match(net_tok, mask_tok, string));
2843 /* match_string - match a string literal */
2845 int match_string(int unused_flags, const char *string, const char *pattern)
2851 /* match_parse_mask - parse net/mask pattern */
2853 static int match_parse_mask(const char *pattern, unsigned long *net_bits,
2854 @@ -198,28 +501,55 @@
2859 /* match_hostaddr - match host by address */
2861 int match_hostaddr(int unused_flags, const char *addr, const char *pattern)
2863 char *myname = "match_hostaddr";
2865 + char *network, *mask, *escl, *escr, *patternx;
2866 + struct in6_addr in6;
2867 + char v4addr[INET_ADDRSTRLEN];
2870 unsigned long mask_bits;
2871 unsigned long net_bits;
2872 unsigned long addr_bits;
2873 struct in_addr net_addr;
2877 msg_info("%s: %s ~? %s", myname, addr, pattern);
2880 + if (addr[strspn(addr, "01234567890./:abcdef")] != 0)
2882 if (addr[strspn(addr, "01234567890./:")] != 0)
2887 + patternx = mystrdup(pattern);
2888 + escl = strchr(patternx,'[');
2889 + escr = strrchr(patternx,']');
2890 + if (escl && escr) {
2892 + sprintf(patternx, "%s%s", escl + 1, escr + 1);
2893 + pattern = patternx;
2898 * Try dictionary lookup. This can be case insensitive. XXX Probably
2899 * should also try again after stripping least significant octets.
2901 - if (strchr(pattern, ':') != 0) {
2903 + if (!(escl && escr) && strchr(pattern, ':') != 0)
2905 + if (strchr(pattern, ':') != 0)
2908 if (dict_lookup(pattern, addr) != 0)
2910 if (dict_errno != 0)
2911 @@ -230,6 +560,12 @@
2913 * Try an exact match with the host address.
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));
2921 if (strcasecmp(addr, pattern) == 0) {
2924 @@ -238,6 +574,20 @@
2925 * In a net/mask pattern, the mask is specified as the number of bits of
2929 + network = mystrdup(patternx);
2930 + mask = split_at(network, '/');
2932 + if (masked_match(network, mask, (char *)addr)) {
2942 if (match_parse_mask(pattern, &net_bits, &mask_shift)) {
2943 addr_bits = inet_addr(addr);
2944 if (addr_bits == INADDR_NONE)
2946 pattern, inet_ntoa(net_addr), mask_shift);
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
2956 #define DEF_MAILBOX_LOCK "flock, dotlock"
2959 +#if ((defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105000000) || defined(USAGI_LIBINET6))
2960 +#define HAVE_GETIFADDRS
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
2974 +#include <netinet/in.h>
2975 +#include <sys/socket.h>
2976 +#include <arpa/inet.h>
2980 /* Utility library. */
2983 @@ -109,7 +116,23 @@
2984 msg_warn("%s: misplaced hyphen: %.100s", myname, name);
2990 + else if (ch == ':') {
2991 + struct addrinfo hints, *res;
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);
3006 msg_warn("%s: invalid character %d(decimal): %.100s",
3013 + struct addrinfo hints, *res;
3016 #define BYTES_NEEDED 4
3018 @@ -166,6 +192,17 @@
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);
3034 * Scary code to avoid sscanf() overflow nasties.