183 #ifdef STRCASECMP_IN_STRINGS_H
217 #define SMTPD_PROXY_XFORWARD_NAME (1<<0)
218 #define SMTPD_PROXY_XFORWARD_ADDR (1<<1)
219 #define SMTPD_PROXY_XFORWARD_PROTO (1<<2)
220 #define SMTPD_PROXY_XFORWARD_HELO (1<<3)
221 #define SMTPD_PROXY_XFORWARD_IDENT (1<<4)
222 #define SMTPD_PROXY_XFORWARD_DOMAIN (1<<5)
223 #define SMTPD_PROXY_XFORWARD_PORT (1<<6)
228 static VSTREAM *smtpd_proxy_replay_stream;
233 static void smtpd_proxy_fake_server_reply(
SMTPD_STATE *,
int);
234 static int smtpd_proxy_rdwr_error(
SMTPD_STATE *,
int);
236 static
int smtpd_proxy_rec_put(
VSTREAM *,
int, const
char *, ssize_t);
241 #define STR(x) vstring_str(x)
242 #define LEN(x) VSTRING_LEN(x)
243 #define STREQ(x, y) (strcmp((x), (y)) == 0)
247 static int smtpd_proxy_xforward_flush(SMTPD_STATE *state,
VSTRING *buf)
262 static int smtpd_proxy_xforward_send(SMTPD_STATE *state,
VSTRING *buf,
270 #define CONSTR_LEN(s) (sizeof(s) - 1)
271 #define PAYLOAD_LIMIT (512 - CONSTR_LEN("250 " XFORWARD_CMD "\r\n"))
273 if (!value_available)
288 msg_warn(
"%s command payload %s=%.10s... exceeds SMTP protocol limit",
295 if ((ret = smtpd_proxy_xforward_flush(state, buf)) < 0)
304 static int smtpd_proxy_connect(SMTPD_STATE *state)
313 static const NAME_CODE known_xforward_features[] = {
323 int server_xforward_features;
324 int (*connect_fn) (
const char *,
int,
int);
325 const char *endpoint;
346 return (smtpd_proxy_rdwr_error(state, 0));
389 server_xforward_features = 0;
391 while ((words =
mystrtok(&lines,
"\n")) != 0) {
394 while ((word =
mystrtok(&words,
" \t")) != 0)
395 server_xforward_features |=
408 if (server_xforward_features) {
439 || smtpd_proxy_xforward_flush(state, buf));
464 static void smtpd_proxy_fake_server_reply(SMTPD_STATE *state,
int status)
481 static int smtpd_proxy_replay_rdwr_error(SMTPD_STATE *state)
487 msg_warn(
"proxy speed-adjust log I/O error: %m");
501 static int smtpd_proxy_rdwr_error(SMTPD_STATE *state,
int err)
503 const char *myname =
"smtpd_proxy_rdwr_error";
510 msg_panic(
"%s: proxy error %d without proxy handle", myname, err);
526 msg_panic(
"%s: unknown proxy %s error %d",
542 static int smtpd_proxy_replay_send(SMTPD_STATE *state)
544 const char *myname =
"smtpd_proxy_replay_send";
545 static VSTRING *replay_buf = 0;
553 if (smtpd_proxy_replay_stream == 0)
554 msg_panic(
"%s: no before-queue filter speed-adjust log", myname);
564 return (smtpd_proxy_replay_rdwr_error(state));
569 if (smtpd_proxy_connect(state) < 0)
594 if (
vstream_fseek(smtpd_proxy_replay_stream, (off_t) 0, SEEK_SET) < 0)
595 return (smtpd_proxy_replay_rdwr_error(state));
598 switch (rec_type =
rec_get(smtpd_proxy_replay_stream, replay_buf,
607 STR(replay_buf),
LEN(replay_buf)) < 0)
617 msg_panic(
"%s: malformed server reply type: %s",
618 myname,
STR(replay_buf));
628 msg_panic(
"%s: missing server reply type", myname);
629 if (smtpd_proxy_cmd(state, expect,
"%s",
STR(replay_buf)) < 0)
644 return (smtpd_proxy_replay_rdwr_error(state));
646 msg_panic(
"%s: unexpected record type; %d", myname, rec_type);
653 static int PRINTFLIKE(3, 4) smtpd_proxy_save_cmd(SMTPD_STATE *state,
int expect, const
char *
fmt,...)
662 return (smtpd_proxy_replay_rdwr_error(state));
687 return (strcmp(fmt,
".") ? 0 : smtpd_proxy_replay_send(state));
692 static int smtpd_proxy_cmd(SMTPD_STATE *state,
int expect,
const char *
fmt,...)
707 return (smtpd_proxy_rdwr_error(state, err));
760 if (last_char !=
'\n')
761 msg_warn(
"%s: response longer than %d: %.30s...",
783 for (cp =
STR(buffer); *cp &&
ISDIGIT(*cp); cp++)
785 if (cp -
STR(buffer) == 3) {
788 if (*cp ==
' ' || *cp == 0)
791 msg_warn(
"received garbage from proxy %s: %.100s",
804 msg_warn(
"proxy %s rejected \"%s\": \"%s\"",
810 smtpd_proxy_rdwr_error(state, 0);
820 static int smtpd_proxy_save_rec_put(VSTREAM *stream,
int rec_type,
821 const char *data, ssize_t len)
823 const char *myname =
"smtpd_proxy_save_rec_put";
826 #define VSTREAM_TO_SMTPD_STATE(s) ((SMTPD_STATE *) vstream_context(s))
832 msg_panic(
"%s: attempt to use closed stream", myname);
838 ret =
rec_put(stream, rec_type, data, len);
840 msg_panic(
"%s: need REC_TYPE_NORM or REC_TYPE_CONT", myname);
845 if (ret != rec_type) {
854 static int smtpd_proxy_rec_put(VSTREAM *stream,
int rec_type,
855 const char *data, ssize_t len)
857 const char *myname =
"smtpd_proxy_rec_put";
877 msg_panic(
"%s: need REC_TYPE_NORM or REC_TYPE_CONT", myname);
883 static int smtpd_proxy_save_rec_fprintf(VSTREAM *stream,
int rec_type,
886 const char *myname =
"smtpd_proxy_save_rec_fprintf";
894 msg_panic(
"%s: attempt to use closed stream", myname);
904 msg_panic(
"%s: need REC_TYPE_NORM", myname);
910 if (ret != rec_type) {
919 static int smtpd_proxy_rec_fprintf(VSTREAM *stream,
int rec_type,
922 const char *myname =
"smtpd_proxy_rec_fprintf";
943 msg_panic(
"%s: need REC_TYPE_NORM", myname);
952 static int smtpd_proxy_replay_setup(SMTPD_STATE *state)
954 const char *myname =
"smtpd_proxy_replay_setup";
966 if (smtpd_proxy_replay_stream != 0) {
968 if ((file_offs =
vstream_ftell(smtpd_proxy_replay_stream)) != 0)
969 msg_panic(
"%s: bad before-queue filter speed-adjust log offset %lu",
970 myname, (
unsigned long) file_offs);
973 msg_info(
"%s: reuse speed-adjust stream fd=%d", myname,
981 if (smtpd_proxy_replay_stream == 0) {
983 (
struct timeval *) 0);
984 if (smtpd_proxy_replay_stream == 0)
985 return (smtpd_proxy_replay_rdwr_error(state));
986 if (unlink(
VSTREAM_PATH(smtpd_proxy_replay_stream)) < 0)
987 msg_warn(
"remove before-queue filter speed-adjust log %s: %m",
990 msg_info(
"%s: new speed-adjust stream fd=%d", myname,
1008 int timeout,
const char *ehlo_name,
1009 const char *mail_from)
1017 #define SMTPD_PROXY_ALLOC(p, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12) \
1018 ((p) = (SMTPD_PROXY *) mymalloc(sizeof(*(p))), (p)->a1, (p)->a2, \
1019 (p)->a3, (p)->a4, (p)->a5, (p)->a6, (p)->a7, (p)->a8, (p)->a9, \
1020 (p)->a10, (p)->a11, (p)->a12, (p))
1025 if (state->
proxy != 0)
1026 msg_panic(
"smtpd_proxy_create: handle still exists");
1035 cmd = smtpd_proxy_cmd,
1037 rec_put = smtpd_proxy_rec_put,
1038 flags = flags, service_stream = 0,
1039 service_name = service, timeout = timeout,
1040 ehlo_name = ehlo_name, mail_from = mail_from);
1041 if (smtpd_proxy_connect(state) < 0) {
1057 msg_panic(
"smtpd_proxy_create: speed-adjust support is not available");
1059 if (smtpd_proxy_replay_setup(state) < 0)
1065 cmd = smtpd_proxy_save_cmd,
1067 rec_put = smtpd_proxy_save_rec_put,
1068 flags = flags, service_stream = 0,
1069 service_name = service, timeout = timeout,
1070 ehlo_name = ehlo_name, mail_from = mail_from);
1111 if (proxy->
reply != 0)
1123 if (smtpd_proxy_replay_stream == 0)
1128 smtpd_proxy_replay_stream = 0;
1132 if (
vstream_fseek(smtpd_proxy_replay_stream, (off_t) 0, SEEK_SET) < 0) {
1133 msg_warn(
"seek before-queue filter speed-adjust log: %m");
1135 smtpd_proxy_replay_stream = 0;
1138 if (ftruncate(
vstream_fileno(smtpd_proxy_replay_stream), (off_t) 0) < 0) {
1139 msg_warn(
"truncate before-queue filter speed-adjust log: %m");
1141 smtpd_proxy_replay_stream = 0;
1150 static const NAME_MASK proxy_opts_table[] = {
1162 flags =
name_mask(param_name, proxy_opts_table, param_val);
1165 msg_warn(
"smtpd_proxy %s support is not available",
1167 flags &= ~SMTPD_PROXY_FLAG_SPEED_ADJUST;
#define SMTPD_PROX_WANT_ANY
const CLEANUP_STAT_DETAIL * cleanup_stat_detail(unsigned status)
int rec_vfprintf(VSTREAM *stream, int type, const char *format, va_list ap)
#define MAIL_ERROR_RESOURCE
#define SMTPD_PROXY_XFORWARD_PORT
#define IS_AVAIL_CLIENT_PORT(v)
#define IS_AVAIL_CLIENT_HELO(v)
NORETURN msg_panic(const char *fmt,...)
#define IS_AVAIL_CLIENT_ADDR(v)
#define VSTREAM_TO_SMTPD_STATE(s)
off_t vstream_ftell(VSTREAM *stream)
#define XFORWARD_DOM_LOCAL
void smtpd_proxy_close(SMTPD_STATE *state)
int smtpd_proxy_create(SMTPD_STATE *state, int flags, const char *service, int timeout, const char *ehlo_name, const char *mail_from)
int smtpd_proxy_parse_opts(const char *param_name, const char *param_val)
#define vstream_clearerr(vp)
#define IS_AVAIL_CLIENT_IDENT(v)
#define SMTPD_PROX_WANT_MORE
#define CA_VSTREAM_CTL_CONTEXT(v)
#define MAIL_ATTR_RWR_LOCAL
int smtp_get(VSTRING *vp, VSTREAM *stream, ssize_t bound, int flags)
int alldig(const char *string)
#define vstream_setjmp(stream)
#define SMTPD_PROX_WANT_BAD
char * mystrtok(char **src, const char *sep)
#define SMTPD_PROXY_FLAG_SPEED_ADJUST
int strncasecmp(const char *s1, const char *s2, size_t n)
#define SMTPD_PROXY_NAME_SPEED_ADJUST
#define IS_AVAIL_CLIENT_PROTO(v)
#define SMTPD_PROXY_XFORWARD_IDENT
void smtp_vprintf(VSTREAM *stream, const char *fmt, va_list ap)
VSTRING * vstring_sprintf_append(VSTRING *vp, const char *format,...)
VSTRING * vstring_vsprintf(VSTRING *vp, const char *format, va_list ap)
#define CLEANUP_STAT_PROXY
int inet_connect(const char *, int, int)
int vstream_fclose(VSTREAM *stream)
const char * service_name
int unix_connect(const char *, int, int)
#define SMTPD_PROXY_XFORWARD_NAME
#define VSTRING_RESET(vp)
#define SMTPD_PROX_WANT_OK
#define MAIL_QUEUE_INCOMING
VSTREAM * mail_queue_enter(const char *queue_name, mode_t mode, struct timeval *tp)
void msg_warn(const char *fmt,...)
#define MAIL_ERROR_SOFTWARE
VSTRING * vstring_alloc(ssize_t len)
void smtp_fputs(const char *cp, ssize_t todo, VSTREAM *stream)
void smtpd_proxy_free(SMTPD_STATE *state)
#define smtp_timeout_setup(stream, timeout)
#define NAME_CODE_FLAG_NONE
#define name_mask(tag, table, str)
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
void smtp_fwrite(const char *cp, ssize_t todo, VSTREAM *stream)
#define SMTPD_PROXY_ALLOC(p, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12)
#define FORWARD_DOMAIN(s)
int rec_put(VSTREAM *stream, int type, const char *data, ssize_t len)
int name_code(const NAME_CODE *table, int flags, const char *name)
#define XFORWARD_DOM_REMOTE
off_t vstream_fseek(VSTREAM *stream, off_t offset, int whence)
int vstream_fflush(VSTREAM *stream)
#define SMTPD_PROX_WANT_NONE
struct SMTPD_PROXY * proxy
int vstream_tweak_tcp(VSTREAM *)
int strcasecmp(const char *s1, const char *s2)
#define SMTPD_PROXY_XFORWARD_ADDR
VSTRING * vstring_free(VSTRING *vp)
#define vstream_fileno(vp)
VSTRING * xtext_quote(VSTRING *quoted, const char *unquoted, const char *special)
#define CA_VSTREAM_CTL_END
#define SMTP_GET_FLAG_SKIP
char * printable(char *string, int replacement)
void vstream_control(VSTREAM *stream, int name,...)
#define SMTPD_PROXY_XFORWARD_PROTO
#define IS_AVAIL_CLIENT_NAME(v)
#define rec_get(fp, buf, limit)
#define vstream_ferror(vp)
int rec_fprintf(VSTREAM *stream, int type, const char *format,...)
VSTRING * vstring_strcat(VSTRING *vp, const char *src)
VSTREAM * vstream_fdopen(int fd, int flags)
#define SMTPD_PROXY_XFORWARD_HELO
#define SMTPD_PROXY_XFORWARD_DOMAIN
#define XFORWARD_UNAVAILABLE
void msg_info(const char *fmt,...)