/*++ Copyright (c) 1996 Microsoft Corporation Module Name : dnsrec.h Abstract: This file contains type definitions for async DNS Author: Rohan Phillips (Rohanp) June-19-1998 Revision History: --*/ # ifndef _ADNS_STRUCT_HXX_ # define _ADNS_STRUCT_HXX_ #define TCP_REG_LIST_SIGNATURE 'TgeR' #define DNS_FLAGS_NONE 0x0 #define DNS_FLAGS_TCP_ONLY 0x1 #define DNS_FLAGS_UDP_ONLY 0x2 #define SMTP_MAX_DNS_ENTRIES 100 typedef void (WINAPI * USERDELETEFUNC) (PVOID); //----------------------------------------------------------------------------- // // Description: // Encapsulates a list of IP addresses (for DNS servers) and maintains // state information on them... whether the servers are up or down, and // provides retry logic for down servers. // // Some member functions to control the state-tracking logic and error- // logging are listed as pure virtual functions (see the bottom of this // class declaration). To use this class, derive from it and implement // those functions. //----------------------------------------------------------------------------- class CDnsServerList { protected: typedef enum _SERVER_STATE { DNS_STATE_DOWN = 0, DNS_STATE_UP, DNS_STATE_PROBATION } SERVER_STATE; DWORD m_dwSig; int m_cUpServers; PIP_ARRAY m_IpListPtr; DWORD *m_prgdwFailureTick; SERVER_STATE *m_prgServerState; DWORD *m_prgdwFailureCount; DWORD *m_prgdwConnections; CShareLockNH m_sl; public: CDnsServerList(); ~CDnsServerList(); BOOL Update(PIP_ARRAY IpPtr); BOOL UpdateIfChanged(PIP_ARRAY IpPtr); DWORD GetWorkingServerIp(DWORD *dwIp, BOOL fThrottle); void MarkDown(DWORD dwIp, DWORD dwErr, BOOL fUdp); void ResetTimeoutServersIfNeeded(); void ResetServerOnConnect(DWORD dwIp); BOOL CopyList(PIP_ARRAY *ppipArray); DWORD GetCount() { DWORD dwCount; m_sl.ShareLock(); dwCount = m_IpListPtr ? m_IpListPtr->cAddrCount : 0; m_sl.ShareUnlock(); return dwCount; } DWORD GetUpServerCount() { DWORD dwCount; m_sl.ShareLock(); dwCount = m_cUpServers; m_sl.ShareUnlock(); return dwCount; } DWORD GetAnyServerIp(PDWORD pdwIp) { m_sl.ShareLock(); if(!m_IpListPtr || 0 == m_IpListPtr->cAddrCount) { m_sl.ShareUnlock(); return DNS_ERROR_NO_DNS_SERVERS; } *pdwIp = m_IpListPtr->aipAddrs[0]; m_sl.ShareUnlock(); return ERROR_SUCCESS; } BOOL AllowConnection(DWORD iServer) { // Note: Sharelock must have been acquired by caller if(m_prgServerState[iServer] == DNS_STATE_UP) return TRUE; if(m_prgServerState[iServer] == DNS_STATE_PROBATION && m_prgdwConnections[iServer] < ConnectsAllowedInProbation()) { m_prgdwConnections[iServer]++; return TRUE; } return FALSE; } // // Pure virtual methods to be overridden by a class to implement processing // specific to the application/component. // virtual DWORD ConnectsAllowedInProbation() = 0; virtual DWORD ErrorsBeforeFailover() = 0; virtual void LogServerDown( DWORD dwServerIp, BOOL fUdp, DWORD dwErr, DWORD cUpServers) = 0; }; //----------------------------------------------------------------------------- // Description: // This class adds SMTP DNS specific error-controls and error-logging to // the generic DNS server state tracking class. //----------------------------------------------------------------------------- class CTcpRegIpList : public CDnsServerList { public: DWORD ConnectsAllowedInProbation(); DWORD ErrorsBeforeFailover(); void LogServerDown( DWORD dwServerIp, BOOL fUdp, DWORD dwErr, DWORD cUpServers); }; typedef struct _MXIPLISTENTRY_ { DWORD IpAddress; LIST_ENTRY ListEntry; }MXIPLIST_ENTRY, *PMXIPLIST_ENTRY; typedef struct _MX_NAMES_ { char DnsName[MAX_INTERNET_NAME]; DWORD NumEntries; LIST_ENTRY IpListHead; }MX_NAMES, *PMX_NAMES; typedef struct _SMTPDNS_REC_ { DWORD NumRecords; //number of record in DnsArray DWORD StartRecord; //the starting index PVOID pMailMsgObj; //pointer to a mailmsg obj PVOID pAdvQContext; PVOID pRcptIdxList; DWORD dwNumRcpts; MX_NAMES *DnsArray[SMTP_MAX_DNS_ENTRIES]; } SMTPDNS_RECS, *PSMTPDNS_RECS; class CDnsLogger { public: virtual void DnsPrintfMsg(char *szFormat, ...) = 0; virtual void DnsPrintfErr(char *szFormat, ...) = 0; virtual void DnsPrintfDbg(char *szFormat, ...) = 0; virtual void DnsLogAsyncQuery( char *pszQuestionName, WORD wQuestionType, DWORD dwSmtpFlags, BOOL fUdp, CDnsServerList *pDnsServerList) = 0; virtual void DnsLogApiQuery( char *pszQuestionName, WORD wQuestionType, DWORD dwDnsApiFlags, BOOL fGlobal, PIP_ARRAY pipServers) = 0; virtual void DnsLogResponse( DWORD dwStatus, PDNS_RECORD pDnsRecordList, PBYTE pbMsg, DWORD dwMessageLength) = 0; virtual void DnsPrintRecord(PDNS_RECORD pDnsRecord) = 0; }; extern CDnsLogger *g_pDnsLogger; // The following are defined as macros since they wrap functions that // take a variable number of arguments #define DNS_PRINTF_MSG \ if(g_pDnsLogger) \ g_pDnsLogger->DnsPrintfMsg #define DNS_PRINTF_ERR \ if(g_pDnsLogger) \ g_pDnsLogger->DnsPrintfErr #define DNS_PRINTF_DBG \ if(g_pDnsLogger) \ g_pDnsLogger->DnsPrintfDbg inline void DNS_LOG_ASYNC_QUERY( IN DNS_NAME pszQuestionName, IN WORD wQuestionType, IN DWORD dwSmtpFlags, IN BOOL fUdp, IN CDnsServerList *pDnsServerList) { if(g_pDnsLogger) { g_pDnsLogger->DnsLogAsyncQuery(pszQuestionName, wQuestionType, dwSmtpFlags, fUdp, pDnsServerList); } } inline void DNS_LOG_API_QUERY( IN DNS_NAME pszQuestionName, IN WORD wQuestionType, IN DWORD dwDnsApiFlags, IN BOOL fGlobal, IN PIP_ARRAY pipServers) { if(g_pDnsLogger) { g_pDnsLogger->DnsLogApiQuery(pszQuestionName, wQuestionType, dwDnsApiFlags, fGlobal, pipServers); } } inline void DNS_LOG_RESPONSE( IN DWORD dwStatus, IN PDNS_RECORD pDnsRecordList, PBYTE pbMsg, DWORD dwMessageLength) { if(g_pDnsLogger) { g_pDnsLogger->DnsLogResponse(dwStatus, pDnsRecordList, pbMsg, dwMessageLength); } } inline void DNS_PRINT_RECORD( IN PDNS_RECORD pDnsRecord) { if(g_pDnsLogger) g_pDnsLogger->DnsPrintRecord(pDnsRecord); } #endif