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 #ifndef __MINGW32__
00049 # include <ntverp.h>
00050 #endif
00051
00052
00053 #ifndef __MINGW32__
00054 enum { DnsSectionAdditional = DnsSectionAddtional };
00055 #endif
00056
00057 #else
00058
00059 # define P_HAS_RESOLVER 1 // set if using Unix-style DNS routines
00060 # include <arpa/nameser.h>
00061 # include <resolv.h>
00062 # if defined(P_MACOSX) && (P_MACOSX >= 700)
00063 # include <arpa/nameser_compat.h>
00064 # endif
00065
00066 #endif // _WIN32
00067
00068 #if defined(_WIN32) && VER_PRODUCTBUILD < 6000
00069 typedef struct
00070 {
00071 WORD wOrder;
00072 WORD wPreference;
00073 PSTR pFlags;
00074 PSTR pService;
00075 PSTR pRegularExpression;
00076 PSTR pReplacement;
00077 }
00078 DNS_NAPTR_DATA;
00079 #endif
00080
00081
00082 #ifdef P_HAS_RESOLVER
00083
00085
00086
00087
00088
00089
00090 #ifndef T_SRV
00091 #define T_SRV 33
00092 #endif
00093
00094 #ifndef T_NAPTR
00095 #define T_NAPTR 35
00096 #endif
00097
00098
00099 #define DNS_STATUS int
00100 #define DNS_TYPE_SRV T_SRV
00101 #define DNS_TYPE_MX T_MX
00102 #define DNS_TYPE_A T_A
00103 #define DNS_TYPE_NAPTR T_NAPTR
00104 #define DnsFreeRecordList 0
00105 #define DNS_QUERY_STANDARD 0
00106 #define DNS_QUERY_BYPASS_CACHE 0
00107
00108 typedef struct _DnsAData {
00109 DWORD IpAddress;
00110 } DNS_A_DATA;
00111
00112 typedef struct {
00113 char pNameExchange[MAXDNAME];
00114 WORD wPreference;
00115 } DNS_MX_DATA;
00116
00117 typedef struct {
00118 char pNameHost[MAXDNAME];
00119 } DNS_PTR_DATA;
00120
00121 typedef struct _DnsSRVData {
00122 char pNameTarget[MAXDNAME];
00123 WORD wPriority;
00124 WORD wWeight;
00125 WORD wPort;
00126 } DNS_SRV_DATA;
00127
00128 typedef struct _DnsNULLData {
00129 DWORD dwByteCount;
00130 char data[1];
00131 } DNS_NULL_DATA;
00132
00133 typedef struct _DnsRecordFlags
00134 {
00135 unsigned Section : 2;
00136 unsigned Delete : 1;
00137 unsigned CharSet : 2;
00138 unsigned Unused : 3;
00139 unsigned Reserved : 24;
00140 } DNS_RECORD_FLAGS;
00141
00142 typedef enum _DnsSection
00143 {
00144 DnsSectionQuestion,
00145 DnsSectionAnswer,
00146 DnsSectionAuthority,
00147 DnsSectionAdditional,
00148 } DNS_SECTION;
00149
00150
00151 class DnsRecord {
00152 public:
00153 DnsRecord * pNext;
00154 char pName[MAXDNAME];
00155 WORD wType;
00156 WORD wDataLength;
00157
00158 union {
00159 DWORD DW;
00160 DNS_RECORD_FLAGS S;
00161 } Flags;
00162
00163 union {
00164 DNS_A_DATA A;
00165 DNS_MX_DATA MX;
00166 DNS_PTR_DATA NS;
00167 DNS_SRV_DATA SRV;
00168 DNS_NULL_DATA Null;
00169 } Data;
00170 };
00171
00172 typedef DnsRecord * PDNS_RECORD;
00173
00174
00175 typedef DWORD IP4_ADDRESS, *PIP4_ADDRESS;
00176
00177 typedef struct _IP4_ARRAY
00178 {
00179 DWORD AddrCount;
00180 IP4_ADDRESS AddrArray[1];
00181 }
00182 IP4_ARRAY, *PIP4_ARRAY;
00183
00184
00185 extern void DnsRecordListFree(PDNS_RECORD rec, int FreeType);
00186
00187 extern DNS_STATUS DnsQuery_A(const char * service,
00188 WORD requestType,
00189 DWORD options,
00190 PIP4_ARRAY,
00191 PDNS_RECORD * results,
00192 void *);
00193
00194
00195 #endif // P_HAS_RESOLVER
00196
00197 namespace PDNS {
00198
00200
00201
00202
00203
00204
00205 template <unsigned type, class RecordListType, class RecordType>
00206 PBoolean Lookup(const PString & name, RecordListType & recordList)
00207 {
00208 if (name.IsEmpty())
00209 return false;
00210
00211 recordList.RemoveAll();
00212
00213 PDNS_RECORD results = NULL;
00214 DNS_STATUS status = DnsQuery_A((const char *)name,
00215 type,
00216 DNS_QUERY_STANDARD,
00217 (PIP4_ARRAY)NULL,
00218 &results,
00219 NULL);
00220 if (status != 0)
00221 return false;
00222
00223
00224 PDNS_RECORD dnsRecord = results;
00225 while (dnsRecord != NULL) {
00226 RecordType * record = recordList.HandleDNSRecord(dnsRecord, results);
00227 if (record != NULL)
00228 recordList.Append(record);
00229 dnsRecord = dnsRecord->pNext;
00230 }
00231
00232 if (results != NULL)
00233 DnsRecordListFree(results, DnsFreeRecordList);
00234
00235 return recordList.GetSize() != 0;
00236 }
00237
00239
00240 class SRVRecord : public PObject
00241 {
00242 PCLASSINFO(SRVRecord, PObject);
00243 public:
00244 SRVRecord()
00245 { used = false; }
00246
00247 Comparison Compare(const PObject & obj) const;
00248 void PrintOn(ostream & strm) const;
00249
00250 PString hostName;
00251 PIPSocket::Address hostAddress;
00252 PBoolean used;
00253 WORD port;
00254 WORD priority;
00255 WORD weight;
00256 };
00257
00258 PDECLARE_SORTED_LIST(SRVRecordList, PDNS::SRVRecord)
00259 public:
00260 void PrintOn(ostream & strm) const;
00261
00262 SRVRecord * GetFirst();
00263 SRVRecord * GetNext();
00264
00265 PDNS::SRVRecord * HandleDNSRecord(PDNS_RECORD dnsRecord, PDNS_RECORD results);
00266
00267 protected:
00268 PINDEX priPos;
00269 PWORDArray priList;
00270 };
00271
00276 inline PBoolean GetRecords(const PString & service, SRVRecordList & serviceList)
00277 { return Lookup<DNS_TYPE_SRV, SRVRecordList, SRVRecord>(service, serviceList); }
00278
00282 inline PBoolean GetSRVRecords(
00283 const PString & service,
00284 SRVRecordList & serviceList
00285 )
00286 { return GetRecords(service, serviceList); }
00287
00292 PBoolean GetSRVRecords(
00293 const PString & service,
00294 const PString & type,
00295 const PString & domain,
00296 SRVRecordList & serviceList
00297 );
00298
00304 PBoolean LookupSRV(
00305 const PString & srvQuery,
00306 WORD defaultPort,
00307 PIPSocketAddressAndPortVector & addrList
00308 );
00309
00310 PBoolean LookupSRV(
00311 const PString & domain,
00312 const PString & service,
00313 WORD defaultPort,
00314 PIPSocketAddressAndPortVector & addrList
00315 );
00316
00317 PBoolean LookupSRV(
00318 const PURL & url,
00319 const PString & service,
00320 PStringList & returnStr
00321 );
00322
00324
00325 class MXRecord : public PObject
00326 {
00327 PCLASSINFO(MXRecord, PObject);
00328 public:
00329 MXRecord()
00330 { used = false; }
00331 Comparison Compare(const PObject & obj) const;
00332 void PrintOn(ostream & strm) const;
00333
00334 PString hostName;
00335 PIPSocket::Address hostAddress;
00336 PBoolean used;
00337 WORD preference;
00338 };
00339
00340 PDECLARE_SORTED_LIST(MXRecordList, PDNS::MXRecord)
00341 public:
00342 void PrintOn(ostream & strm) const;
00343
00344 MXRecord * GetFirst();
00345 MXRecord * GetNext();
00346
00347 PDNS::MXRecord * HandleDNSRecord(PDNS_RECORD dnsRecord, PDNS_RECORD results);
00348
00349 protected:
00350 PINDEX lastIndex;
00351 };
00352
00356 inline PBoolean GetRecords(
00357 const PString & domain,
00358 MXRecordList & serviceList
00359 )
00360 { return Lookup<DNS_TYPE_MX, MXRecordList, MXRecord>(domain, serviceList); }
00361
00365 inline PBoolean GetMXRecords(
00366 const PString & domain,
00367 MXRecordList & serviceList
00368 )
00369 {
00370 return GetRecords(domain, serviceList);
00371 }
00372
00374
00375 };
00376
00377 #endif // P_DNS
00378
00379 #endif // PTLIB_PDNS_H
00380
00381
00382