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