00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #ifndef PTLIB_PDNS_H
00032 #define PTLIB_PDNS_H
00033
00034 #if P_DNS
00035
00036 #ifdef P_USE_PRAGMA
00037 #pragma interface
00038 #endif
00039
00040 #include <ptlib/sockets.h>
00041
00042 #include <ptclib/random.h>
00043 #include <ptclib/url.h>
00044
00045 #if defined(_WIN32)
00046
00047 #include <windns.h>
00048 #include <ntverp.h>
00049
00050
00051 enum { DnsSectionAdditional = DnsSectionAddtional };
00052
00053 #if VER_PRODUCTBUILD < 6000
00054 typedef struct
00055 {
00056 WORD wOrder;
00057 WORD wPreference;
00058 PSTR pFlags;
00059 PSTR pService;
00060 PSTR pRegularExpression;
00061 PSTR pReplacement;
00062 }
00063 DNS_NAPTR_DATA;
00064 #endif
00065
00066 #else
00067
00068 #define P_HAS_RESOLVER 1 // set if using Unix-style DNS routines
00069 #include <arpa/nameser.h>
00070 #include <resolv.h>
00071 #if defined(P_MACOSX) && (P_MACOSX >= 700)
00072 #include <arpa/nameser_compat.h>
00073 #endif
00074
00075 #endif // _WIN32
00076
00077
00078 #ifdef P_HAS_RESOLVER
00079
00081
00082
00083
00084
00085
00086 #ifndef T_SRV
00087 #define T_SRV 33
00088 #endif
00089
00090 #ifndef T_NAPTR
00091 #define T_NAPTR 35
00092 #endif
00093
00094
00095 #define DNS_STATUS int
00096 #define DNS_TYPE_SRV T_SRV
00097 #define DNS_TYPE_MX T_MX
00098 #define DNS_TYPE_A T_A
00099 #define DNS_TYPE_AAAA T_AAAA
00100 #define DNS_TYPE_NAPTR T_NAPTR
00101 #define DnsFreeRecordList 1
00102 #define DNS_QUERY_STANDARD 0
00103 #define DNS_QUERY_BYPASS_CACHE 0
00104
00105 typedef struct _DnsAData {
00106 DWORD IpAddress;
00107 } DNS_A_DATA;
00108
00109 typedef struct _DnsAAAAData {
00110 DWORD Ip6Address[4];
00111 } DNS_AAAA_DATA;
00112
00113 typedef struct {
00114 char pNameExchange[MAXDNAME];
00115 WORD wPreference;
00116 } DNS_MX_DATA;
00117
00118 typedef struct {
00119 char pNameHost[MAXDNAME];
00120 } DNS_PTR_DATA;
00121
00122 typedef struct _DnsSRVData {
00123 char pNameTarget[MAXDNAME];
00124 WORD wPriority;
00125 WORD wWeight;
00126 WORD wPort;
00127 } DNS_SRV_DATA;
00128
00129 typedef struct _DnsNULLData {
00130 DWORD dwByteCount;
00131 char data[1];
00132 } DNS_NULL_DATA;
00133
00134 typedef struct _DnsRecordFlags
00135 {
00136 unsigned Section : 2;
00137 unsigned Delete : 1;
00138 unsigned CharSet : 2;
00139 unsigned Unused : 3;
00140 unsigned Reserved : 24;
00141 } DNS_RECORD_FLAGS;
00142
00143 typedef enum _DnsSection
00144 {
00145 DnsSectionQuestion,
00146 DnsSectionAnswer,
00147 DnsSectionAuthority,
00148 DnsSectionAdditional,
00149 } DNS_SECTION;
00150
00151
00152 class DnsRecord {
00153 public:
00154 DnsRecord * pNext;
00155 char pName[MAXDNAME];
00156 WORD wType;
00157 WORD wDataLength;
00158
00159 union {
00160 DWORD DW;
00161 DNS_RECORD_FLAGS S;
00162 } Flags;
00163
00164 union {
00165 DNS_A_DATA A;
00166 DNS_AAAA_DATA AAAA;
00167 DNS_MX_DATA MX;
00168 DNS_PTR_DATA NS;
00169 DNS_SRV_DATA SRV;
00170 DNS_NULL_DATA Null;
00171 } Data;
00172 };
00173
00174 typedef DnsRecord DNS_RECORD;
00175 typedef DnsRecord * PDNS_RECORD;
00176
00177
00178 extern void DnsRecordListFree(PDNS_RECORD rec, int FreeType);
00179 extern PDNS_RECORD DnsRecordSetCopy(PDNS_RECORD src);
00180
00181 extern DNS_STATUS DnsQuery_A(const char * service,
00182 WORD requestType,
00183 DWORD options,
00184 void *,
00185 PDNS_RECORD * results,
00186 void *);
00187
00188
00189 #endif // P_HAS_RESOLVER
00190
00191 namespace PDNS {
00192
00194
00195 DNS_STATUS Cached_DnsQuery(
00196 const char * name,
00197 WORD type,
00198 DWORD options,
00199 void * extra,
00200 PDNS_RECORD * queryResults,
00201 void * reserved
00202 );
00203
00204
00205
00207
00208
00209
00210
00211
00212 template <unsigned type, class RecordListType, class RecordType>
00213 PBoolean Lookup(const PString & name, RecordListType & recordList)
00214 {
00215 if (name.IsEmpty())
00216 return false;
00217
00218 recordList.RemoveAll();
00219
00220 PDNS_RECORD results = NULL;
00221 DNS_STATUS status = Cached_DnsQuery((const char *)name,
00222 type,
00223 DNS_QUERY_STANDARD,
00224 NULL,
00225 &results,
00226 NULL);
00227 if (status != 0)
00228 return false;
00229
00230
00231 PDNS_RECORD dnsRecord = results;
00232 while (dnsRecord != NULL) {
00233 RecordType * record = recordList.HandleDNSRecord(dnsRecord, results);
00234 if (record != NULL)
00235 recordList.Append(record);
00236 dnsRecord = dnsRecord->pNext;
00237 }
00238
00239 if (results != NULL)
00240 DnsRecordListFree(results, DnsFreeRecordList);
00241
00242 return recordList.GetSize() != 0;
00243 }
00244
00246
00247 class SRVRecord : public PObject
00248 {
00249 PCLASSINFO(SRVRecord, PObject);
00250 public:
00251 SRVRecord()
00252 { used = false; }
00253
00254 Comparison Compare(const PObject & obj) const;
00255 void PrintOn(ostream & strm) const;
00256
00257 PString hostName;
00258 PIPSocket::Address hostAddress;
00259 PBoolean used;
00260 WORD port;
00261 WORD priority;
00262 WORD weight;
00263 };
00264
00265 PDECLARE_SORTED_LIST(SRVRecordList, PDNS::SRVRecord)
00266 public:
00267 void PrintOn(ostream & strm) const;
00268
00269 SRVRecord * GetFirst();
00270 SRVRecord * GetNext();
00271
00272 PDNS::SRVRecord * HandleDNSRecord(PDNS_RECORD dnsRecord, PDNS_RECORD results);
00273
00274 protected:
00275 PINDEX priPos;
00276 PWORDArray priList;
00277 };
00278
00283 inline PBoolean GetRecords(const PString & service, SRVRecordList & serviceList)
00284 { return Lookup<DNS_TYPE_SRV, SRVRecordList, SRVRecord>(service, serviceList); }
00285
00289 inline PBoolean GetSRVRecords(
00290 const PString & service,
00291 SRVRecordList & serviceList
00292 )
00293 { return GetRecords(service, serviceList); }
00294
00299 PBoolean GetSRVRecords(
00300 const PString & service,
00301 const PString & type,
00302 const PString & domain,
00303 SRVRecordList & serviceList
00304 );
00305
00311 PBoolean LookupSRV(
00312 const PString & srvQuery,
00313 WORD defaultPort,
00314 PIPSocketAddressAndPortVector & addrList
00315 );
00316
00317 PBoolean LookupSRV(
00318 const PString & domain,
00319 const PString & service,
00320 WORD defaultPort,
00321 PIPSocketAddressAndPortVector & addrList
00322 );
00323
00324 PBoolean LookupSRV(
00325 const PURL & url,
00326 const PString & service,
00327 PStringList & returnStr
00328 );
00329
00331
00332 class MXRecord : public PObject
00333 {
00334 PCLASSINFO(MXRecord, PObject);
00335 public:
00336 MXRecord()
00337 { used = false; }
00338 Comparison Compare(const PObject & obj) const;
00339 void PrintOn(ostream & strm) const;
00340
00341 PString hostName;
00342 PIPSocket::Address hostAddress;
00343 PBoolean used;
00344 WORD preference;
00345 };
00346
00347 PDECLARE_SORTED_LIST(MXRecordList, PDNS::MXRecord)
00348 public:
00349 void PrintOn(ostream & strm) const;
00350
00351 MXRecord * GetFirst();
00352 MXRecord * GetNext();
00353
00354 PDNS::MXRecord * HandleDNSRecord(PDNS_RECORD dnsRecord, PDNS_RECORD results);
00355
00356 protected:
00357 PINDEX lastIndex;
00358 };
00359
00363 inline PBoolean GetRecords(
00364 const PString & domain,
00365 MXRecordList & serviceList
00366 )
00367 { return Lookup<DNS_TYPE_MX, MXRecordList, MXRecord>(domain, serviceList); }
00368
00372 inline PBoolean GetMXRecords(
00373 const PString & domain,
00374 MXRecordList & serviceList
00375 )
00376 {
00377 return GetRecords(domain, serviceList);
00378 }
00379
00380
00381 };
00382
00383 #endif // P_DNS
00384
00385 #endif // PTLIB_PDNS_H
00386
00387
00388