/*
* Copyright (c) 2002-2005 Sendmail, Inc. and its suppliers.
* All rights reserved.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*
* $Id: mta.h,v 1.90 2007/06/02 04:11:39 ca Exp $
*/
#ifndef SM_MTA_H
#define SM_MTA_H 1
#include "sm/generic.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/limits.h"
#include "sm/smreplycodes.h"
#include "sm/smmts.h"
/*
** Session/transaction id: 64bit "id" counter, 8bit process"id"
** Do NOT change this: some functions extract the process "id" out of it.
** C/S (1) + 64bit (16) + 8bit (2) + '\0' (1)
*/
#define SMTP_STID_SIZE ((size_t) 20)
#define SMTPS_STID_FORMAT "S%016qX%02X"
#define SMTPS_STID_PID_OFF 17 /* offset of process "id" in id */
#define SMTPS_STID_IDC_OFF 1 /* offset of id counter in id */
#define SMTPS_MAX_SMTPS_ID 255 /* max process"id" */
#define sm_idcmp(se_id1, se_id2) \
strncmp((se_id1) + SMTPS_STID_IDC_OFF, (se_id2) + SMTPS_STID_IDC_OFF, \
SMTPS_STID_PID_OFF - SMTPS_STID_IDC_OFF)
/*
** 'C' SMTPC idx (8bit), running counter (32bit), thread idx (32bit)
** Do NOT change this: some functions extract the thread idx out of it.
*/
#define SMTPC_STID_FORMAT "C%02X%08X%08X"
#define SMTPC_STID_CID_OFF 1 /* offset of SMTPC idx in id */
#define SMTPC_STID_THR_OFF 11 /* offset of thread idx in id */
/* extract thread index from DA transaction id, ok iff return value is 1 */
#define SMTPC_GETTHRIDX(da_ta_id, thr_id) \
sm_io_sscanf((da_ta_id) + SMTPC_STID_THR_OFF, "%x", &thr_id)
/* extract SMTPC id from DA transaction id, ok iff return value is 1 */
#define SMTPC_GETCID(da_ta_id, sc_id) \
sm_io_sscanf((da_ta_id) + SMTPC_STID_CID_OFF, "%2x", &sc_id)
typedef char sessta_id_T[SMTP_STID_SIZE], *sessta_id_P;
typedef uint64_t id_count_T;
#define SESSTA_COPY(dst_id, src_id) sm_memcpy((dst_id), (src_id), SMTP_STID_SIZE)
#define SESSTA_EQ(id1, id2) sm_memeq((id1), (id2), SMTP_STID_SIZE)
#define SESSTA_CLR(id) sm_memzero((id), SMTP_STID_SIZE)
sm_ret_T sm_id2idc(sessta_id_P _se_id, id_count_T *_pidc);
sm_ret_T sm_getsmtpsid(sessta_id_P _se_id);
/*
** Recipient id: transaction id + recipient index (32bit)
** 27 = "S" + 8bit + 64bit + 32bit (base 64) + '\0'
** Question: is the hyphen necessary? Note: if it is removed then the code
** to extract the recipient index must be changed.
*/
#define SMTP_RCPTID_LEN 27
#define SMTP_RCPTID_SIZE ((size_t) SMTP_RCPTID_LEN)
#define SMTP_RCPTID_FORMAT "%19s-%06Y"
#define SMTP_RCPTIDX_MAX UINT32_MAX /* maximum recipient index */
typedef char rcpt_id_T[SMTP_RCPTID_SIZE], *rcpt_id_P;
#define RCPT_IDX_FORMAT "%Y"
#define RCPT_ID_COPY(dst_id, src_id) sm_memcpy((dst_id), (src_id), SMTP_RCPTID_SIZE)
#define RCPT_ID_EQ(id1, id2) sm_memeq((id1), (id2), SMTP_RCPTID_SIZE)
/* extract transaction id from recipient id */
#define RCPTID2SESSTAID(rcpt_id, ta_id) do { \
SESSTA_COPY((ta_id), (rcpt_id)); \
(ta_id)[SMTP_STID_SIZE - 1] = '\0'; \
} while (0)
/* extract recipient index from recipient id, ok iff return value is 1 */
#define RCPTID2IDX(rcpt_id, rcpt_idx) \
sm_io_sscanf((rcpt_id) + SMTP_STID_SIZE, RCPT_IDX_FORMAT, &(rcpt_idx))
typedef int smtp_status_T; /* (extended) smtp status code, includes errors */
/* Largest size of transaction/session/recipient id */
#define SMTP_ID_SIZE SMTP_RCPTID_SIZE
typedef char smtp_id_T[SMTP_ID_SIZE], *smtp_id_P;
/* should this be 200 instead to match the SMTP reply codes? */
#define SMTP_OK SM_SUCCESS
#define smtp_reply_type(r) ((int) ((r) / 100))
/* SMTP reply types */
#define SMTP_RTYPE_OK 2
#define SMTP_RTYPE_CONT 3
#define SMTP_RTYPE_TEMP 4
#define SMTP_RTYPE_PERM 5
#define IS_SMTP_REPLY(r) ((r) >= 200 && (r) <= 599)
#define smtp_is_reply_ok(r) (smtp_reply_type(r) == SMTP_RTYPE_OK)
#define smtp_is_reply_temp(r) (smtp_reply_type(r) == SMTP_RTYPE_TEMP)
#define smtp_is_reply_fail(r) (smtp_reply_type(r) == SMTP_RTYPE_PERM)
#define SMTP_IS_REPLY_ERROR(r) (smtp_is_reply_temp(r) || smtp_is_reply_fail(r))
/*
** Check whether str has an SMTP reply code at offset.
** Doesn't check whether str ends with ' ', '\0', or '-'.
*/
#define IS_SMTP_REPLY_STR(str, off) \
(sm_str_getlen(str) >= ((off) + 3) \
&& ISDIGIT(sm_str_rd_elem((str), (off))) \
&& ISDIGIT(sm_str_rd_elem((str), (off) + 1)) \
&& ISDIGIT(sm_str_rd_elem((str), (off) + 2)) \
&& (sm_str_rd_elem((str), (off)) == '2' \
|| sm_str_rd_elem((str), (off)) == '3' \
|| sm_str_rd_elem((str), (off)) == '4' \
|| sm_str_rd_elem((str), (off)) == '5') \
)
/* Use a real function to check for correct range? */
#define char2digit(c) ((c) - '0')
/* convert SMTP reply code to integer value; must be checked before! */
#define SMTP_REPLY_STR2VAL(str, off) \
((sm_str_rd_elem((str), (off)) == '2') ? SMTP_OK \
: (char2digit(sm_str_rd_elem((str), (off))) * 100 \
+ char2digit(sm_str_rd_elem((str), (off) + 1)) * 10 \
+ char2digit(sm_str_rd_elem((str), (off) + 2))))
/*
** Check whether a string contains a "matching" reply for a return code,
** i.e., it must be a SMTP reply string and the reply types must match,
** and they either must be identical or both must not be 421.
*/
#define SMTP_REPLY_MATCHES_RCODE(str, rcode, off, temp) \
(IS_SMTP_REPLY_STR((str), (off)) && \
smtp_reply_type((temp) = SMTP_REPLY_STR2VAL((str), (off))) == \
smtp_reply_type(rcode) && \
((temp) == (rcode) || ((temp) != SMTP_R_SSD && (rcode) != SMTP_R_SSD))\
)
/* some additional pseudo SMTP reply codes */
#define SMTPC_TEMP_ST 460 /* generic temporary error in DA */
#define SMTPC_IO_ST 461 /* generic I/O error in DA */
#define SMTPC_DA_ST 462 /* DA went away */
#define SMTPC_PROT 463 /* protocol error */
#define SMTPC_SE_OPEN_ST 465 /* session open failed */
#define SMTPC_SE_OP_TMO 466 /* session open timeout */
#define SMTPC_SE_OP_REFUSED 467 /* session open connection refused */
#define SMTPC_SE_OP_UNREACH 468 /* session open host/net unreachable */
#define SMTP_AR_TMO 480 /* TIMEOUT in AR */
#define SMTP_AR_TEMP 481 /* TEMP in AR */
#define SMTP_AR_ALIAS 482 /* alias expansion in AR failed */
#define SMTP_MAP_TEMP 483 /* temp map lookup failure */
#define SMTP_CDB_TEMP 485 /* tempfail in CDB */
#define SMTP_TMO_SCHED 490 /* timeout in sched */
#define SMTP_TMO_DA 491 /* timeout waiting for DA */
#define SMTP_TMO_DDSN 492 /* delayed DSN stored in DEFEDB first time */
#define SMTP_QUARANTINE 498 /* quarantine (not yet implemented) */
/*
** SMTPC: no reply yet from server (useful for pipelining, but also as
** initial status).
** SMTPS: do not send reply in main loop
*/
#define SMTP_NO_REPLY 499
#define SMTP_AR_NOTF 580 /* NOTFOUND in AR */
#define SMTP_AR_PERM 581 /* PERM in AR */
#define SMTP_AR_LOOP 582 /* CNAME loop in AR */
#define SMTP_AR_AL_REC 583 /* alias nesting too deep in AR */
#define SMTP_AR_MXEMPTY 584 /* MX list empty in AR ("loops back") */
#define SMTPC_SE_TTMYSELF 585 /* talking to myself */
/*
** Permanent error in CDB: entry not found,
** HACK: treat it as OK, this is "required" by the way updating recipients
** and transactions are handled: 2xy indicates "entry has been taken care of".
** Note: this will cause problem if success DSNs are implemented, because
** this wasn't a successful delivery.
*/
#define SMTP_CDB_PERM 285
/* TA/RCPT is "done" (has been taken care of) */
#define SMTP_DONE(status) ((status) == SM_SUCCESS || smtp_is_reply_ok(status))
/*
** XXX intermediate solution: host identification
** This should be a generic description of the connecting host,
** similar to SOCKADDR in V8.
*/
#if 0
struct sm_host_S
{
struct in_addr sss_client;
};
#endif
/* XXX HACK */
typedef struct in_addr sm_host_T, *sm_host_P;
/* maximum length of domain part of an address, RFC ? */
/* rename these to have an SM_ prefix?? */
#define MAXDOMAINLEN 256
#define MAXADDRLEN (256+64)
#define SM_MAXHDRLEN 1000
/* XXX HACK use LMTP if these are encountered */
/* used in various places, e.g., smar/t-mt-0.sh */
#if 0
#define LMTP_IPV4_ADDR (htonl(0x7FFFFFFF))
#else
#define LMTP_IPV4_ADDR (htonl(0x7F0000FF))
#endif
#define LMTP_IPV4_S2 "[127.0.0.255]"
#define LMTP_MT "lmtp:"
/* default log level */
#define SM_LOG_LEVEL 99999
/* some configuration defaults */
#define SM_MAX_RCPTS 65535
#define SM_MAX_TAS 65535
/* maximum length of section + id */
#define MAXSECTIONNAME 256
#define SM_TA_FL_VERP 0x0001
#define SM_GOT_CRLF 2 /* got CRLF, i.e., at begin of a line */
#define SM_EOT "\r\n.\r\n"
#define SM_DECL_EOT const char eot[] = SM_EOT
#define SM_EOT_LEN (sizeof(SM_EOT) - 1)
#define SM_EOH "\r\n\r\n"
#define SM_DECL_EOH const char eoh[] = SM_EOH
#define SM_EOH_LEN (sizeof(SM_EOH) - 1)
#define SM_EOL "\r\n"
#define SM_DECL_EOL const char eol[] = SM_EOL
#define SM_EOL_LEN (sizeof(SM_EOL) - 1)
#endif /* SM_MTA_H */
syntax highlighted by Code2HTML, v. 0.9.1