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