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