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