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