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 #if P_DNS
00065 #ifndef _PDNS_H
00066 #define _PDNS_H
00067
00068 #ifdef P_USE_PRAGMA
00069 #pragma interface
00070 #endif
00071
00072 #include <ptlib/sockets.h>
00073
00074 #include <ptclib/random.h>
00075 #include <ptclib/url.h>
00076
00077 #if defined(_WIN32)
00078
00079 # include <windns.h>
00080 # pragma comment(lib, P_DNS_LIBRARY)
00081
00082 #else
00083
00084 # define P_HAS_RESOLVER 1 // set if using Unix-style DNS routines
00085 # include <arpa/nameser.h>
00086 # include <resolv.h>
00087 # if defined(P_MACOSX) && (P_MACOSX >= 700)
00088 # include <arpa/nameser_compat.h>
00089 # endif
00090
00091 #endif // _WIN32
00092
00093 #ifdef P_HAS_RESOLVER
00094
00096
00097
00098
00099
00100
00101 #ifndef T_SRV
00102 #define T_SRV 33
00103 #endif
00104
00105 #ifndef T_NAPTR
00106 #define T_NAPTR 35
00107 #endif
00108
00109
00110 #define DNS_STATUS int
00111 #define DNS_TYPE_SRV T_SRV
00112 #define DNS_TYPE_MX T_MX
00113 #define DNS_TYPE_A T_A
00114 #define DNS_TYPE_NAPTR T_NAPTR
00115 #define DnsFreeRecordList 0
00116 #define DNS_QUERY_STANDARD 0
00117 #define DNS_QUERY_BYPASS_CACHE 0
00118
00119 typedef struct _DnsAData {
00120 DWORD IpAddress;
00121 } DNS_A_DATA;
00122
00123 typedef struct {
00124 char pNameExchange[MAXDNAME];
00125 WORD wPreference;
00126 } DNS_MX_DATA;
00127
00128 typedef struct {
00129 char pNameHost[MAXDNAME];
00130 } DNS_PTR_DATA;
00131
00132 typedef struct _DnsSRVData {
00133 char pNameTarget[MAXDNAME];
00134 WORD wPriority;
00135 WORD wWeight;
00136 WORD wPort;
00137 } DNS_SRV_DATA;
00138
00139 typedef struct _DnsNULLData {
00140 DWORD dwByteCount;
00141 char data[1];
00142 } DNS_NULL_DATA;
00143
00144 typedef struct _DnsRecordFlags
00145 {
00146 unsigned Section : 2;
00147 unsigned Delete : 1;
00148 unsigned CharSet : 2;
00149 unsigned Unused : 3;
00150 unsigned Reserved : 24;
00151 } DNS_RECORD_FLAGS;
00152
00153 typedef enum _DnsSection
00154 {
00155 DnsSectionQuestion,
00156 DnsSectionAnswer,
00157 DnsSectionAuthority,
00158 DnsSectionAddtional,
00159 } DNS_SECTION;
00160
00161
00162 class DnsRecord {
00163 public:
00164 DnsRecord * pNext;
00165 char pName[MAXDNAME];
00166 WORD wType;
00167 WORD wDataLength;
00168
00169 union {
00170 DWORD DW;
00171 DNS_RECORD_FLAGS S;
00172 } Flags;
00173
00174 union {
00175 DNS_A_DATA A;
00176 DNS_MX_DATA MX;
00177 DNS_PTR_DATA NS;
00178 DNS_SRV_DATA SRV;
00179 DNS_NULL_DATA Null;
00180 } Data;
00181 };
00182
00183 typedef DnsRecord * PDNS_RECORD;
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 void *,
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 BOOL 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 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 BOOL 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 BOOL GetRecords(const PString & service, SRVRecordList & serviceList)
00277 { return Lookup<DNS_TYPE_SRV, SRVRecordList, SRVRecord>(service, serviceList); }
00278
00282 inline BOOL GetSRVRecords(
00283 const PString & service,
00284 SRVRecordList & serviceList
00285 )
00286 { return GetRecords(service, serviceList); }
00287
00292 BOOL GetSRVRecords(
00293 const PString & service,
00294 const PString & type,
00295 const PString & domain,
00296 SRVRecordList & serviceList
00297 );
00298
00304 BOOL LookupSRV(
00305 const PString & domain,
00306 const PString & service,
00307 WORD defaultPort,
00308 PIPSocketAddressAndPortVector & addrList
00309 );
00310
00311 BOOL LookupSRV(
00312 const PURL & url,
00313 const PString & service,
00314 PStringList & returnStr
00315 );
00316
00318
00319 class MXRecord : public PObject
00320 {
00321 PCLASSINFO(MXRecord, PObject);
00322 public:
00323 MXRecord()
00324 { used = FALSE; }
00325 Comparison Compare(const PObject & obj) const;
00326 void PrintOn(ostream & strm) const;
00327
00328 PString hostName;
00329 PIPSocket::Address hostAddress;
00330 BOOL used;
00331 WORD preference;
00332 };
00333
00334 PDECLARE_SORTED_LIST(MXRecordList, PDNS::MXRecord)
00335 public:
00336 void PrintOn(ostream & strm) const;
00337
00338 MXRecord * GetFirst();
00339 MXRecord * GetNext();
00340
00341 PDNS::MXRecord * HandleDNSRecord(PDNS_RECORD dnsRecord, PDNS_RECORD results);
00342
00343 protected:
00344 PINDEX lastIndex;
00345 };
00346
00350 inline BOOL GetRecords(
00351 const PString & domain,
00352 MXRecordList & serviceList
00353 )
00354 { return Lookup<DNS_TYPE_MX, MXRecordList, MXRecord>(domain, serviceList); }
00355
00359 inline BOOL GetMXRecords(
00360 const PString & domain,
00361 MXRecordList & serviceList
00362 )
00363 {
00364 return GetRecords(domain, serviceList);
00365 }
00366
00368
00369 };
00370
00371 #endif // _PDNS_H
00372 #endif // P_DNS
00373
00374