Fixed crash opportunity under some conditions
[pwlib.git] / include / ptclib / pdns.h
blob01437c94ad0c632f380ebed84afb803994d55848
1 /*
2 * pdns.h
4 * PWLib library for DNS lookup services
6 * Portable Windows Library
8 * Copyright (c) 2003 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Contributor(s): ______________________________________.
26 * $Log$
27 * Revision 1.8 2004/06/24 07:36:24 csoutheren
28 * Added definitions of T_SRV and T_NAPTR for hosts that do not have these
30 * Revision 1.7 2004/05/31 12:49:47 csoutheren
31 * Added handling of unknown DNS types
33 * Revision 1.6 2004/05/28 06:50:42 csoutheren
34 * Reorganised DNS functions to use templates, and exposed more internals to allow new DNS lookup types to be added
36 * Revision 1.5 2003/07/22 23:52:20 dereksmithies
37 * Fix from Fabrizio Ammollo to cope with when P_DNS is disabled. Thanks!
39 * Revision 1.4 2003/04/16 07:02:55 robertj
40 * Cleaned up source.
42 * Revision 1.3 2003/04/15 08:14:06 craigs
43 * Added single string form of GetSRVRecords
45 * Revision 1.2 2003/04/15 08:06:24 craigs
46 * Added Unix implementation
48 * Revision 1.1 2003/04/15 04:06:56 craigs
49 * Initial version
53 #if P_DNS
54 #ifndef _PDNS_H
55 #define _PDNS_H
57 #ifdef P_USE_PRAGMA
58 #pragma interface
59 #endif
61 #include <ptlib/sockets.h>
63 #include <ptclib/random.h>
65 #if defined(_WIN32)
67 # include <windns.h>
68 # pragma comment(lib, P_DNS_LIBRARY)
70 #else
72 # define P_HAS_RESOLVER 1 // set if using Unix-style DNS routines
73 # include <arpa/nameser.h>
74 # include <resolv.h>
75 # if defined(P_MACOSX) && (P_MACOSX >= 700)
76 # include <arpa/nameser_compat.h>
77 # endif
79 #endif // _WIN32
81 #ifdef P_HAS_RESOLVER
83 //////////////////////////////////////////////////////////////////////////
85 // these classes provide an emulation of the Microsoft DNS API
86 // on non-Window systems
89 #ifndef T_SRV
90 #define T_SRV 33
91 #endif
93 #ifndef T_NAPTR
94 #define T_NAPTR 35
95 #endif
98 #define DNS_STATUS int
99 #define DNS_TYPE_SRV T_SRV
100 #define DNS_TYPE_MX T_MX
101 #define DNS_TYPE_A T_A
102 #define DNS_TYPE_NAPTR T_NAPTR
103 #define DnsFreeRecordList 0
104 #define DNS_QUERY_STANDARD 0
105 #define DNS_QUERY_BYPASS_CACHE 0
107 typedef struct _DnsAData {
108 DWORD IpAddress;
109 } DNS_A_DATA;
111 typedef struct {
112 char pNameExchange[MAXDNAME];
113 WORD wPreference;
114 } DNS_MX_DATA;
116 typedef struct {
117 char pNameHost[MAXDNAME];
118 } DNS_PTR_DATA;
120 typedef struct _DnsSRVData {
121 char pNameTarget[MAXDNAME];
122 WORD wPriority;
123 WORD wWeight;
124 WORD wPort;
125 } DNS_SRV_DATA;
127 typedef struct _DnsNULLData {
128 DWORD dwByteCount;
129 char data[1];
130 } DNS_NULL_DATA;
132 typedef struct _DnsRecordFlags
134 unsigned Section : 2;
135 unsigned Delete : 1;
136 unsigned CharSet : 2;
137 unsigned Unused : 3;
138 unsigned Reserved : 24;
139 } DNS_RECORD_FLAGS;
141 typedef enum _DnsSection
143 DnsSectionQuestion,
144 DnsSectionAnswer,
145 DnsSectionAuthority,
146 DnsSectionAddtional,
147 } DNS_SECTION;
150 class DnsRecord {
151 public:
152 DnsRecord * pNext;
153 char pName[MAXDNAME];
154 WORD wType;
155 WORD wDataLength;
157 union {
158 DWORD DW; // flags as DWORD
159 DNS_RECORD_FLAGS S; // flags as structure
160 } Flags;
162 union {
163 DNS_A_DATA A;
164 DNS_MX_DATA MX;
165 DNS_PTR_DATA NS;
166 DNS_SRV_DATA SRV;
167 DNS_NULL_DATA Null;
168 } Data;
171 typedef DnsRecord * PDNS_RECORD;
173 extern void DnsRecordListFree(PDNS_RECORD rec, int FreeType);
175 extern DNS_STATUS DnsQuery_A(const char * service,
176 WORD requestType,
177 DWORD options,
178 void *,
179 PDNS_RECORD * results,
180 void *);
183 #endif // P_HAS_RESOLVER
185 namespace PDNS {
187 //////////////////////////////////////////////////////////////////////////
189 // this template automates the creation of a list of records for
190 // a specific type of DNS lookup
193 template <unsigned type, class RecordListType, class RecordType>
194 BOOL Lookup(const PString & name, RecordListType & recordList)
196 if (name.IsEmpty())
197 return FALSE;
199 recordList.RemoveAll();
201 PDNS_RECORD results = NULL;
202 DNS_STATUS status = DnsQuery_A((const char *)name,
203 type,
204 DNS_QUERY_STANDARD,
205 NULL,
206 &results,
207 NULL);
208 if (status != 0)
209 return FALSE;
211 // find records matching the correct type
212 PDNS_RECORD dnsRecord = results;
213 while (dnsRecord != NULL) {
214 RecordType * record = recordList.HandleDNSRecord(dnsRecord, results);
215 if (record != NULL)
216 recordList.Append(record);
217 dnsRecord = dnsRecord->pNext;
220 if (results != NULL)
221 DnsRecordListFree(results, DnsFreeRecordList);
223 return recordList.GetSize() != 0;
226 /////////////////////////////////////////////////////////////
228 class SRVRecord : public PObject
230 PCLASSINFO(SRVRecord, PObject);
231 public:
232 SRVRecord()
233 { used = FALSE; }
235 Comparison Compare(const PObject & obj) const;
236 void PrintOn(ostream & strm) const;
238 PString hostName;
239 PIPSocket::Address hostAddress;
240 BOOL used;
241 WORD port;
242 WORD priority;
243 WORD weight;
246 PDECLARE_SORTED_LIST(SRVRecordList, PDNS::SRVRecord)
247 public:
248 void PrintOn(ostream & strm) const;
250 SRVRecord * GetFirst();
251 SRVRecord * GetNext();
253 PDNS::SRVRecord * HandleDNSRecord(PDNS_RECORD dnsRecord, PDNS_RECORD results);
255 protected:
256 PINDEX priPos;
257 PWORDArray priList;
261 * return a list of DNS SRV record with the specified service type
264 inline BOOL GetRecords(const PString & service, SRVRecordList & serviceList)
265 { return Lookup<DNS_TYPE_SRV, SRVRecordList, SRVRecord>(service, serviceList); }
268 * provided for backwards compatibility
270 inline BOOL GetSRVRecords(
271 const PString & service,
272 SRVRecordList & serviceList
274 { return GetRecords(service, serviceList); }
277 * return a list of DNS SRV record with the specified service, type and domain
280 BOOL GetSRVRecords(
281 const PString & service,
282 const PString & type,
283 const PString & domain,
284 SRVRecordList & serviceList
287 ////////////////////////////////////////////////////////////////
289 class MXRecord : public PObject
291 PCLASSINFO(MXRecord, PObject);
292 public:
293 MXRecord()
294 { used = FALSE; }
295 Comparison Compare(const PObject & obj) const;
296 void PrintOn(ostream & strm) const;
298 PString hostName;
299 PIPSocket::Address hostAddress;
300 BOOL used;
301 WORD preference;
304 PDECLARE_SORTED_LIST(MXRecordList, PDNS::MXRecord)
305 public:
306 void PrintOn(ostream & strm) const;
308 MXRecord * GetFirst();
309 MXRecord * GetNext();
311 PDNS::MXRecord * HandleDNSRecord(PDNS_RECORD dnsRecord, PDNS_RECORD results);
313 protected:
314 PINDEX lastIndex;
318 * return a list of MX records for the specified domain
320 inline BOOL GetRecords(
321 const PString & domain,
322 MXRecordList & serviceList
324 { return Lookup<DNS_TYPE_MX, MXRecordList, MXRecord>(domain, serviceList); }
327 * provided for backwards compatibility
329 inline BOOL GetMXRecords(
330 const PString & domain,
331 MXRecordList & serviceList
334 return GetRecords(domain, serviceList);
337 ///////////////////////////////////////////////////////////////////////////
339 }; // namespace PDNS
341 #endif // _PDNS_H
342 #endif // P_DNS
344 // End Of File ///////////////////////////////////////////////////////////////