/* * 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 */