smtp_mx_session_limit = 2). Files: smtp/smtp_connect.c,
smtp/smtp_proto.c.
+20050623
+
+ Cleanup: generalized the delegated attribute scan/print
+ interfaces, and updated the deliver_pass module with delegated
+ attribute scan/print support. Files: util/attr_scan0.c,
+ util/attr_print0.c, global/dsb_scan.c, global/dsn_print.c,
+ global/rcpt_buf,c global/rcpt_print.c, global/deliver_pass.c.
+
Open problems:
Laptop friendliness: make the qmgr remember when the next
If you upgrade from Postfix 2.1 or earlier, read RELEASE_NOTES-2.2
before proceeding.
+Incompatibility with snapshot 20050622
+======================================
+
+The Postfix SMTP client by default limits the number of MX server
+addresses to smtp_mx_address_limit=5. Previously this limit was
+disabled by default. The new limit prevents Postfix from spending
+lots of time trying to connect to lots of bogus MX servers.
+
+The Postfix SMTP error handling of [45]XX server greetings was
+cleaned up. The server reply is now properly reported. As a side
+effect, the failed session now counts towards the limit on the total
+number of sessions per domain name (default: smtp_mx_session_limit=2).
+
Incompatibility with snapshot 20050615
======================================
bounce_append_service.o: ../../include/vstring.h
bounce_append_service.o: bounce_append_service.c
bounce_append_service.o: bounce_service.h
+bounce_cleanup.o: ../../include/attr.h
bounce_cleanup.o: ../../include/bounce_log.h
bounce_cleanup.o: ../../include/dsn.h
bounce_cleanup.o: ../../include/dsn_buf.h
bounce_cleanup.o: ../../include/vstring.h
bounce_cleanup.o: bounce_cleanup.c
bounce_cleanup.o: bounce_service.h
+bounce_notify_service.o: ../../include/attr.h
bounce_notify_service.o: ../../include/bounce.h
bounce_notify_service.o: ../../include/bounce_log.h
bounce_notify_service.o: ../../include/cleanup_user.h
bounce_notify_util.o: ../../include/vstring.h
bounce_notify_util.o: bounce_notify_util.c
bounce_notify_util.o: bounce_service.h
+bounce_notify_verp.o: ../../include/attr.h
bounce_notify_verp.o: ../../include/bounce.h
bounce_notify_verp.o: ../../include/bounce_log.h
bounce_notify_verp.o: ../../include/cleanup_user.h
bounce_notify_verp.o: ../../include/vstring.h
bounce_notify_verp.o: bounce_notify_verp.c
bounce_notify_verp.o: bounce_service.h
+bounce_one_service.o: ../../include/attr.h
bounce_one_service.o: ../../include/bounce.h
bounce_one_service.o: ../../include/bounce_log.h
bounce_one_service.o: ../../include/cleanup_user.h
bounce_one_service.o: ../../include/vstring.h
bounce_one_service.o: bounce_one_service.c
bounce_one_service.o: bounce_service.h
+bounce_trace_service.o: ../../include/attr.h
bounce_trace_service.o: ../../include/bounce_log.h
bounce_trace_service.o: ../../include/cleanup_user.h
bounce_trace_service.o: ../../include/deliver_request.h
bounce_trace_service.o: ../../include/vstring.h
bounce_trace_service.o: bounce_service.h
bounce_trace_service.o: bounce_trace_service.c
+bounce_warn_service.o: ../../include/attr.h
bounce_warn_service.o: ../../include/bounce_log.h
bounce_warn_service.o: ../../include/cleanup_user.h
bounce_warn_service.o: ../../include/dsn.h
deliver_pass.o: deliver_pass.c
deliver_pass.o: deliver_pass.h
deliver_pass.o: deliver_request.h
+deliver_pass.o: dsb_scan.h
deliver_pass.o: dsn.h
deliver_pass.o: dsn_buf.h
deliver_pass.o: mail_params.h
#include <mail_params.h>
#include <deliver_pass.h>
+#include <dsb_scan.h>
/* deliver_pass_initial_reply - retrieve initial delivery process response */
/* deliver_pass_final_reply - retrieve final delivery status response */
-static int deliver_pass_final_reply(VSTREAM *stream, VSTRING *dsn_status,
- VSTRING *reason,
- VSTRING *dsn_dtype,
- VSTRING *dsn_dtext,
- VSTRING *dsn_mtype,
- VSTRING *dsn_mname)
+static int deliver_pass_final_reply(VSTREAM *stream, DSN_BUF *dsb)
{
int stat;
if (attr_scan(stream, ATTR_FLAG_STRICT,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_STATUS, dsn_status,
- ATTR_TYPE_STR, MAIL_ATTR_WHY, reason,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_DTYPE, dsn_dtype,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_DTEXT, dsn_dtext,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_MTYPE, dsn_mtype,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_MNAME, dsn_mname,
+ ATTR_TYPE_FUNC, dsb_scan, (void *) dsb,
ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &stat,
- ATTR_TYPE_END) != 7) {
+ ATTR_TYPE_END) != 2) {
msg_warn("%s: malformed response", VSTREAM_PATH(stream));
stat = -1;
}
RECIPIENT *rcpt)
{
VSTREAM *stream;
- VSTRING *junk;
+ DSN_BUF *dsb;
int status;
char *saved_service;
char *transport;
* Initialize.
*/
stream = mail_connect_wait(class, transport);
- junk = vstring_alloc(1);
+ dsb = dsb_create();
/*
* Get the delivery process initial response. Send the queue file info
if ((status = deliver_pass_initial_reply(stream)) == 0
&& (status = deliver_pass_send_request(stream, request, nexthop,
rcpt)) == 0)
- status = deliver_pass_final_reply(stream, junk, junk, junk,
- junk, junk, junk);
+ status = deliver_pass_final_reply(stream, dsb);
/*
* Clean up.
*/
vstream_fclose(stream);
- vstring_free(junk);
+ dsb_free(dsb);
myfree(saved_service);
return (status);
/* SYNOPSIS
/* #include <dsb_scan.h>
/*
-/* int dsb_scan(stream, flags, ptr)
+/* int dsb_scan(scan_fn, stream, flags, ptr)
+/* ATTR_SCAN_MASTER_FN scan_fn;
/* VSTREAM *stream;
/* int flags;
/* void *ptr;
/* DESCRIPTION
/* dsb_scan() reads a DSN_BUF from the named stream using the
-/* default attribute scan routines. This function is meant
+/* specified attribute scan routine. dsb_scan() is meant
/* to be passed as a call-back to attr_scan(), thusly:
/*
/* ... ATTR_SCAN_FUNC, dsb_scan, (void *) &dsbuf, ...
/* dsb_scan - read DSN_BUF from stream */
-int dsb_scan(VSTREAM *fp, int flags, void *ptr)
+int dsb_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
+ int flags, void *ptr)
{
DSN_BUF *dsb = (DSN_BUF *) ptr;
int ret;
* The attribute order is determined by backwards compatibility. It can
* be sanitized after all the ad-hoc DSN read/write code is replaced.
*/
- ret = attr_scan(fp, flags | ATTR_FLAG_MORE,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_STATUS, dsb->status,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_DTYPE, dsb->dtype,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_DTEXT, dsb->dtext,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_MTYPE, dsb->mtype,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_MNAME, dsb->mname,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_ACTION, dsb->action,
- ATTR_TYPE_STR, MAIL_ATTR_WHY, dsb->reason,
- ATTR_TYPE_END);
+ ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_STATUS, dsb->status,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_DTYPE, dsb->dtype,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_DTEXT, dsb->dtext,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_MTYPE, dsb->mtype,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_MNAME, dsb->mname,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_ACTION, dsb->action,
+ ATTR_TYPE_STR, MAIL_ATTR_WHY, dsb->reason,
+ ATTR_TYPE_END);
return (ret == 7 ? 1 : -1);
}
* Utility library.
*/
#include <vstream.h>
+#include <attr.h>
/*
* Global library.
/*
* External interface.
*/
-extern int dsb_scan(VSTREAM *, int, void *);
+extern int dsb_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
/* LICENSE
/* .ad
/* SYNOPSIS
/* #include <dsn_print.h>
/*
-/* int dsn_print(stream, flags, ptr)
+/* int dsn_print(print_fn, stream, flags, ptr)
+/* ATTR_PRINT_MASTER_FN print_fn;
/* VSTREAM *stream;
/* int flags;
/* void *ptr;
/* DESCRIPTION
/* dsn_print() writes a DSN structure to the named stream using
-/* the default attribute print routines. This function is meant
+/* the specified attribute print routine. dsn_print() is meant
/* to be passed as a call-back to attr_print(), thusly:
/*
/* ... ATTR_PRINT_FUNC, dsn_print, (void *) dsn, ...
/* dsn_print - write DSN to stream */
-int dsn_print(VSTREAM *fp, int flags, void *ptr)
+int dsn_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
+ int flags, void *ptr)
{
DSN *dsn = (DSN *) ptr;
int ret;
* The attribute order is determined by backwards compatibility. It can
* be sanitized after all the ad-hoc DSN read/write code is replaced.
*/
- ret = attr_print(fp, flags | ATTR_FLAG_MORE,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_STATUS, dsn->status,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_DTYPE, S(dsn->dtype),
- ATTR_TYPE_STR, MAIL_ATTR_DSN_DTEXT, S(dsn->dtext),
- ATTR_TYPE_STR, MAIL_ATTR_DSN_MTYPE, S(dsn->mtype),
- ATTR_TYPE_STR, MAIL_ATTR_DSN_MNAME, S(dsn->mname),
- ATTR_TYPE_STR, MAIL_ATTR_DSN_ACTION, S(dsn->action),
- ATTR_TYPE_STR, MAIL_ATTR_WHY, dsn->reason,
- ATTR_TYPE_END);
+ ret = print_fn(fp, flags | ATTR_FLAG_MORE,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_STATUS, dsn->status,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_DTYPE, S(dsn->dtype),
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_DTEXT, S(dsn->dtext),
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_MTYPE, S(dsn->mtype),
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_MNAME, S(dsn->mname),
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_ACTION, S(dsn->action),
+ ATTR_TYPE_STR, MAIL_ATTR_WHY, dsn->reason,
+ ATTR_TYPE_END);
return (ret);
}
* Utility library.
*/
#include <vstream.h>
+#include <attr.h>
/*
* Global library.
/*
* External interface.
*/
-extern int dsn_print(VSTREAM *, int, void *);
+extern int dsn_print(ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *);
/* LICENSE
/* .ad
* Patches change both the patchlevel and the release date. Snapshots have no
* patchlevel; they change the release date only.
*/
-#define MAIL_RELEASE_DATE "20050622"
+#define MAIL_RELEASE_DATE "20050623"
#define MAIL_VERSION_NUMBER "2.3"
#define VAR_MAIL_VERSION "mail_version"
/* void rcpb_free(rcpt)
/* RCPT_BUF *rcpt;
/*
-/* int rcpb_scan(stream, flags, ptr)
+/* int rcpb_scan(scan_fn, stream, flags, ptr)
+/* ATTR_SCAN_MASTER_FN scan_fn;
/* VSTREAM *stream;
/* int flags;
/* void *ptr;
/* DESCRIPTION
/* rcpb_scan() reads a recipient buffer from the named stream
-/* using the default attribute scan routines. This function
+/* using the specified attribute scan routine. rcpb_scan()
/* is meant to be passed as a call-back to attr_scan(), thusly:
/*
/* ... ATTR_SCAN_FUNC, rcpb_scan, (void *) rcpt_buf, ...
/* rcpb_scan - receive recipient buffer */
-int rcpb_scan(VSTREAM *fp, int flags, void *ptr)
+int rcpb_scan(ATTR_SCAN_MASTER_FN scan_fn, VSTREAM *fp,
+ int flags, void *ptr)
{
RCPT_BUF *rcpt = (RCPT_BUF *) ptr;
int ret;
/*
- * As with DSN, the order of attributes is determined by historical
- * compatibility and can be fixed after all the ad-hoc read/write code is
- * replaced.
+ * The order of attributes is determined by historical compatibility and
+ * can be fixed after all the ad-hoc read/write code is replaced.
*/
- ret = attr_scan(fp, flags | ATTR_FLAG_MORE,
- ATTR_TYPE_STR, MAIL_ATTR_ORCPT, rcpt->orig_addr,
- ATTR_TYPE_STR, MAIL_ATTR_RECIP, rcpt->address,
- ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &rcpt->offset,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, rcpt->dsn_orcpt,
- ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, &rcpt->dsn_notify,
- ATTR_TYPE_END);
+ ret = scan_fn(fp, flags | ATTR_FLAG_MORE,
+ ATTR_TYPE_STR, MAIL_ATTR_ORCPT, rcpt->orig_addr,
+ ATTR_TYPE_STR, MAIL_ATTR_RECIP, rcpt->address,
+ ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, &rcpt->offset,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, rcpt->dsn_orcpt,
+ ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, &rcpt->dsn_notify,
+ ATTR_TYPE_END);
return (ret == 5 ? 1 : -1);
}
*/
#include <vstream.h>
#include <vstring.h>
+#include <attr.h>
/*
* External interface.
extern RCPT_BUF *rcpb_create(void);
extern void rcpb_free(RCPT_BUF *);
-extern int rcpb_scan(VSTREAM *, int, void *);
+extern int rcpb_scan(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
#define RECIPIENT_FROM_RCPT_BUF(rcpt, buf) \
((rcpt)->address = vstring_str((buf)->address), \
/* SYNOPSIS
/* #include <rcpt_print.h>
/*
-/* int rcpt_print(stream, flags, ptr)
+/* int rcpt_print(print_fn, stream, flags, ptr)
+/* ATTR_PRINT_MASTER_FN print_fn;
/* VSTREAM *stream;
/* int flags;
/* void *ptr;
/* DESCRIPTION
/* rcpt_print() writes the contents of a RECIPIENT structure
-/* to the named stream using the default attribute print
-/* routines. This function is meant to be passed as a call-back
-/* to attr_print(),
-/* thusly:
+/* to the named stream using the specified attribute print
+/* routine. rcpt_print() is meant to be passed as a call-back
+/* to attr_print(), thusly:
/*
/* ... ATTR_PRINT_FUNC, rcpt_print, (void *) recipient, ...
/* DIAGNOSTICS
/* rcpt_print - write recipient to stream */
-int rcpt_print(VSTREAM *fp, int flags, void *ptr)
+int rcpt_print(ATTR_PRINT_MASTER_FN print_fn, VSTREAM *fp,
+ int flags, void *ptr)
{
RECIPIENT *rcpt = (RECIPIENT *) ptr;
int ret;
#define S(s) ((s) ? (s) : "")
/*
- * The attribute order is determined by backwards compatibility. It can
- * be sanitized after all the ad-hoc recipient read/write code is replaced.
+ * The attribute order is determined by backwards compatibility. It can
+ * be sanitized after all the ad-hoc recipient read/write code is
+ * replaced.
*/
ret =
- attr_print(fp, flags | ATTR_FLAG_MORE,
- ATTR_TYPE_STR, MAIL_ATTR_ORCPT, S(rcpt->orig_addr),
- ATTR_TYPE_STR, MAIL_ATTR_RECIP, rcpt->address,
- ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, rcpt->offset,
- ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, S(rcpt->dsn_orcpt),
- ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, rcpt->dsn_notify,
- ATTR_TYPE_END);
+ print_fn(fp, flags | ATTR_FLAG_MORE,
+ ATTR_TYPE_STR, MAIL_ATTR_ORCPT, S(rcpt->orig_addr),
+ ATTR_TYPE_STR, MAIL_ATTR_RECIP, rcpt->address,
+ ATTR_TYPE_LONG, MAIL_ATTR_OFFSET, rcpt->offset,
+ ATTR_TYPE_STR, MAIL_ATTR_DSN_ORCPT, S(rcpt->dsn_orcpt),
+ ATTR_TYPE_NUM, MAIL_ATTR_DSN_NOTIFY, rcpt->dsn_notify,
+ ATTR_TYPE_END);
return (ret);
}
* Utility library.
*/
#include <vstream.h>
+#include <attr.h>
/*
* Global library.
/*
* External interface.
*/
-extern int rcpt_print(VSTREAM *, int, void *);
+extern int rcpt_print(ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
/* LICENSE
/* .ad
SSL_SESSION *tls_session_activate(const char *session_data, int session_data_len)
{
+#if (OPENSSL_VERSION_NUMBER < 0x0090707fL)
+#define BOGUS_CONST
+#else
+#define BOGUS_CONST const
+#endif
SSL_SESSION *session;
- const unsigned char *ptr;
+ BOGUS_CONST unsigned char *ptr;
/*
* Activate the SSL_SESSION object.
*/
- ptr = (const unsigned char *) session_data;
+ ptr = (BOGUS_CONST unsigned char *) session_data;
session = d2i_SSL_SESSION((SSL_SESSION **) 0, &ptr, session_data_len);
if (!session)
tls_print_errors();
#define ATTR_FLAG_ALL (07)
/*
-Delegation for better data abstraction. */
-typedef int (*ATTR_SCAN_FN)(VSTREAM *, int, void *);
-typedef int (*ATTR_PRINT_FN)(VSTREAM *, int, void *);
+ * Delegation for better data abstraction.
+ */
+typedef int (*ATTR_SCAN_MASTER_FN) (VSTREAM *, int, ...);
+typedef int (*ATTR_SCAN_SLAVE_FN) (ATTR_SCAN_MASTER_FN, VSTREAM *, int, void *);
+typedef int (*ATTR_PRINT_MASTER_FN) (VSTREAM *, int,...);
+typedef int (*ATTR_PRINT_SLAVE_FN) (ATTR_PRINT_MASTER_FN, VSTREAM *, int, void *);
/*
* Default to null-terminated, as opposed to base64-encoded.
/* .IP "ATTR_TYPE_DATA (char *, int, char *)"
/* This argument is followed by an attribute name, an attribute value
/* length, and an attribute value pointer.
-/* .IP "ATTR_TYPE_FUNC (ATTR_PRINT_FN, void *)"
+/* .IP "ATTR_TYPE_FUNC (ATTR_PRINT_SLAVE_FN, void *)"
/* This argument is followed by a function pointer and generic data
/* pointer.
/* .IP "ATTR_TYPE_HASH (HTABLE *)"
HTABLE_INFO **ht;
int len_val;
static VSTRING *base64_buf;
- ATTR_PRINT_FN print_fn;
+ ATTR_PRINT_SLAVE_FN print_fn;
void *print_arg;
/*
msg_info("send attr %s = [data %d bytes]", attr_name, len_val);
break;
case ATTR_TYPE_FUNC:
- print_fn = va_arg(ap, ATTR_PRINT_FN);
+ print_fn = va_arg(ap, ATTR_PRINT_SLAVE_FN);
print_arg = va_arg(ap, void *);
- print_fn(fp, flags | ATTR_FLAG_MORE, print_arg);
+ print_fn(attr_print0, fp, flags | ATTR_FLAG_MORE, print_arg);
break;
case ATTR_TYPE_HASH:
ht_info_list = htable_list(va_arg(ap, HTABLE *));
/* This argument is followed by an attribute name and a VSTRING pointer.
/* .IP "ATTR_TYPE_DATA (char *, VSTRING *)"
/* This argument is followed by an attribute name and a VSTRING pointer.
-/* .IP "ATTR_TYPE_FUNC (ATTR_SCAN_FN, void *)"
+/* .IP "ATTR_TYPE_FUNC (ATTR_SCAN_SLAVE_FN, void *)"
/* This argument is followed by a function pointer and a generic data
/* pointer.
/* .IP "ATTR_TYPE_HASH (HTABLE *)"
HTABLE *hash_table;
int ch;
int conversions;
- ATTR_SCAN_FN scan_fn;
+ ATTR_SCAN_SLAVE_FN scan_fn;
void *scan_arg;
/*
return (-1);
break;
case ATTR_TYPE_FUNC:
- scan_fn = va_arg(ap, ATTR_SCAN_FN);
+ scan_fn = va_arg(ap, ATTR_SCAN_SLAVE_FN);
scan_arg = va_arg(ap, void *);
- if (scan_fn(fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
+ if (scan_fn(attr_scan0, fp, flags | ATTR_FLAG_MORE, scan_arg) < 0)
return (-1);
break;
case ATTR_TYPE_HASH: