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