1 /*
2 * DNS support
3 *
4 * Copyright (C) 2006 Hans Leidekker
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21 #include "precomp.h"
22
23 #define NDEBUG
24 #include <debug.h>
25
dns_type_to_str(unsigned short type)26 const char *dns_type_to_str( unsigned short type )
27 {
28 switch (type)
29 {
30 #define X(x) case (x): return #x;
31 X(DNS_TYPE_ZERO)
32 X(DNS_TYPE_A)
33 X(DNS_TYPE_NS)
34 X(DNS_TYPE_MD)
35 X(DNS_TYPE_MF)
36 X(DNS_TYPE_CNAME)
37 X(DNS_TYPE_SOA)
38 X(DNS_TYPE_MB)
39 X(DNS_TYPE_MG)
40 X(DNS_TYPE_MR)
41 X(DNS_TYPE_NULL)
42 X(DNS_TYPE_WKS)
43 X(DNS_TYPE_PTR)
44 X(DNS_TYPE_HINFO)
45 X(DNS_TYPE_MINFO)
46 X(DNS_TYPE_MX)
47 X(DNS_TYPE_TEXT)
48 X(DNS_TYPE_RP)
49 X(DNS_TYPE_AFSDB)
50 X(DNS_TYPE_X25)
51 X(DNS_TYPE_ISDN)
52 X(DNS_TYPE_RT)
53 X(DNS_TYPE_NSAP)
54 X(DNS_TYPE_NSAPPTR)
55 X(DNS_TYPE_SIG)
56 X(DNS_TYPE_KEY)
57 X(DNS_TYPE_PX)
58 X(DNS_TYPE_GPOS)
59 X(DNS_TYPE_AAAA)
60 X(DNS_TYPE_LOC)
61 X(DNS_TYPE_NXT)
62 X(DNS_TYPE_EID)
63 X(DNS_TYPE_NIMLOC)
64 X(DNS_TYPE_SRV)
65 X(DNS_TYPE_ATMA)
66 X(DNS_TYPE_NAPTR)
67 X(DNS_TYPE_KX)
68 X(DNS_TYPE_CERT)
69 X(DNS_TYPE_A6)
70 X(DNS_TYPE_DNAME)
71 X(DNS_TYPE_SINK)
72 X(DNS_TYPE_OPT)
73 X(DNS_TYPE_UINFO)
74 X(DNS_TYPE_UID)
75 X(DNS_TYPE_GID)
76 X(DNS_TYPE_UNSPEC)
77 X(DNS_TYPE_ADDRS)
78 X(DNS_TYPE_TKEY)
79 X(DNS_TYPE_TSIG)
80 X(DNS_TYPE_IXFR)
81 X(DNS_TYPE_AXFR)
82 X(DNS_TYPE_MAILB)
83 X(DNS_TYPE_MAILA)
84 X(DNS_TYPE_ANY)
85 X(DNS_TYPE_WINS)
86 X(DNS_TYPE_WINSR)
87 #undef X
88 default: { static char tmp[7]; sprintf( tmp, "0x%04x", type ); return tmp; }
89 }
90 }
91
dns_strcmpX(LPCVOID str1,LPCVOID str2,BOOL wide)92 static int dns_strcmpX( LPCVOID str1, LPCVOID str2, BOOL wide )
93 {
94 if (wide)
95 return lstrcmpiW( str1, str2 );
96 else
97 return lstrcmpiA( str1, str2 );
98 }
99
100 /******************************************************************************
101 * DnsRecordCompare [DNSAPI.@]
102 *
103 */
DnsRecordCompare(PDNS_RECORD r1,PDNS_RECORD r2)104 BOOL WINAPI DnsRecordCompare( PDNS_RECORD r1, PDNS_RECORD r2 )
105 {
106 BOOL wide;
107 unsigned int i;
108
109 DPRINT( "(%p,%p)\n", r1, r2 );
110
111 if (r1->wType != r2->wType ||
112 r1->wDataLength != r2->wDataLength ||
113 r1->Flags.S.Section != r2->Flags.S.Section ||
114 r1->Flags.S.Delete != r2->Flags.S.Delete ||
115 r1->Flags.S.Unused != r2->Flags.S.Unused ||
116 r1->Flags.S.Reserved != r2->Flags.S.Reserved ||
117 r1->dwReserved != r2->dwReserved) return FALSE;
118
119 wide = (r1->Flags.S.CharSet == DnsCharSetUnicode || r1->Flags.S.CharSet == DnsCharSetUnknown);
120 if (dns_strcmpX( r1->pName, r2->pName, wide )) return FALSE;
121
122 switch (r1->wType)
123 {
124 case DNS_TYPE_A:
125 {
126 if (r1->Data.A.IpAddress != r2->Data.A.IpAddress) return FALSE;
127 break;
128 }
129 case DNS_TYPE_SOA:
130 {
131 if (r1->Data.SOA.dwSerialNo != r2->Data.SOA.dwSerialNo ||
132 r1->Data.SOA.dwRefresh != r2->Data.SOA.dwRefresh ||
133 r1->Data.SOA.dwRetry != r2->Data.SOA.dwRetry ||
134 r1->Data.SOA.dwExpire != r2->Data.SOA.dwExpire ||
135 r1->Data.SOA.dwDefaultTtl != r2->Data.SOA.dwDefaultTtl)
136 return FALSE;
137 if (dns_strcmpX( r1->Data.SOA.pNamePrimaryServer,
138 r2->Data.SOA.pNamePrimaryServer, wide ) ||
139 dns_strcmpX( r1->Data.SOA.pNameAdministrator,
140 r2->Data.SOA.pNameAdministrator, wide ))
141 return FALSE;
142 break;
143 }
144 case DNS_TYPE_PTR:
145 case DNS_TYPE_NS:
146 case DNS_TYPE_CNAME:
147 case DNS_TYPE_MB:
148 case DNS_TYPE_MD:
149 case DNS_TYPE_MF:
150 case DNS_TYPE_MG:
151 case DNS_TYPE_MR:
152 {
153 if (dns_strcmpX( r1->Data.PTR.pNameHost,
154 r2->Data.PTR.pNameHost, wide )) return FALSE;
155 break;
156 }
157 case DNS_TYPE_MINFO:
158 case DNS_TYPE_RP:
159 {
160 if (dns_strcmpX( r1->Data.MINFO.pNameMailbox,
161 r2->Data.MINFO.pNameMailbox, wide ) ||
162 dns_strcmpX( r1->Data.MINFO.pNameErrorsMailbox,
163 r2->Data.MINFO.pNameErrorsMailbox, wide ))
164 return FALSE;
165 break;
166 }
167 case DNS_TYPE_MX:
168 case DNS_TYPE_AFSDB:
169 case DNS_TYPE_RT:
170 {
171 if (r1->Data.MX.wPreference != r2->Data.MX.wPreference)
172 return FALSE;
173 if (dns_strcmpX( r1->Data.MX.pNameExchange,
174 r2->Data.MX.pNameExchange, wide ))
175 return FALSE;
176 break;
177 }
178 case DNS_TYPE_HINFO:
179 case DNS_TYPE_ISDN:
180 case DNS_TYPE_TEXT:
181 case DNS_TYPE_X25:
182 {
183 if (r1->Data.TXT.dwStringCount != r2->Data.TXT.dwStringCount)
184 return FALSE;
185 for (i = 0; i < r1->Data.TXT.dwStringCount; i++)
186 {
187 if (dns_strcmpX( r1->Data.TXT.pStringArray[i],
188 r2->Data.TXT.pStringArray[i], wide ))
189 return FALSE;
190 }
191 break;
192 }
193 case DNS_TYPE_NULL:
194 {
195 if (r1->Data.Null.dwByteCount != r2->Data.Null.dwByteCount)
196 return FALSE;
197 if (memcmp( r1->Data.Null.Data,
198 r2->Data.Null.Data, r1->Data.Null.dwByteCount ))
199 return FALSE;
200 break;
201 }
202 case DNS_TYPE_AAAA:
203 {
204 for (i = 0; i < sizeof(IP6_ADDRESS)/sizeof(DWORD); i++)
205 {
206 if (r1->Data.AAAA.Ip6Address.IP6Dword[i] !=
207 r2->Data.AAAA.Ip6Address.IP6Dword[i]) return FALSE;
208 }
209 break;
210 }
211 case DNS_TYPE_KEY:
212 {
213 if (r1->Data.KEY.wFlags != r2->Data.KEY.wFlags ||
214 r1->Data.KEY.chProtocol != r2->Data.KEY.chProtocol ||
215 r1->Data.KEY.chAlgorithm != r2->Data.KEY.chAlgorithm)
216 return FALSE;
217 if (memcmp( r1->Data.KEY.Key, r2->Data.KEY.Key,
218 r1->wDataLength - sizeof(DNS_KEY_DATA) + 1 ))
219 return FALSE;
220 break;
221 }
222 case DNS_TYPE_SIG:
223 {
224 if (dns_strcmpX( r1->Data.SIG.pNameSigner,
225 r2->Data.SIG.pNameSigner, wide ))
226 return FALSE;
227 if (r1->Data.SIG.wTypeCovered != r2->Data.SIG.wTypeCovered ||
228 r1->Data.SIG.chAlgorithm != r2->Data.SIG.chAlgorithm ||
229 r1->Data.SIG.chLabelCount != r2->Data.SIG.chLabelCount ||
230 r1->Data.SIG.dwOriginalTtl != r2->Data.SIG.dwOriginalTtl ||
231 r1->Data.SIG.dwExpiration != r2->Data.SIG.dwExpiration ||
232 r1->Data.SIG.dwTimeSigned != r2->Data.SIG.dwTimeSigned ||
233 r1->Data.SIG.wKeyTag != r2->Data.SIG.wKeyTag)
234 return FALSE;
235 if (memcmp( r1->Data.SIG.Signature, r2->Data.SIG.Signature,
236 r1->wDataLength - sizeof(DNS_SIG_DATAA) + 1 ))
237 return FALSE;
238 break;
239 }
240 case DNS_TYPE_ATMA:
241 {
242 if (r1->Data.ATMA.AddressType != r2->Data.ATMA.AddressType)
243 return FALSE;
244 for (i = 0; i < DNS_ATMA_MAX_ADDR_LENGTH; i++)
245 {
246 if (r1->Data.ATMA.Address[i] != r2->Data.ATMA.Address[i])
247 return FALSE;
248 }
249 break;
250 }
251 case DNS_TYPE_NXT:
252 {
253 if (dns_strcmpX( r1->Data.NXT.pNameNext,
254 r2->Data.NXT.pNameNext, wide )) return FALSE;
255 if (r1->Data.NXT.wNumTypes != r2->Data.NXT.wNumTypes) return FALSE;
256 if (memcmp( r1->Data.NXT.wTypes, r2->Data.NXT.wTypes,
257 r1->wDataLength - sizeof(DNS_NXT_DATAA) + sizeof(WORD) ))
258 return FALSE;
259 break;
260 }
261 case DNS_TYPE_SRV:
262 {
263 if (dns_strcmpX( r1->Data.SRV.pNameTarget,
264 r2->Data.SRV.pNameTarget, wide )) return FALSE;
265 if (r1->Data.SRV.wPriority != r2->Data.SRV.wPriority ||
266 r1->Data.SRV.wWeight != r2->Data.SRV.wWeight ||
267 r1->Data.SRV.wPort != r2->Data.SRV.wPort)
268 return FALSE;
269 break;
270 }
271 case DNS_TYPE_TKEY:
272 {
273 if (dns_strcmpX( r1->Data.TKEY.pNameAlgorithm,
274 r2->Data.TKEY.pNameAlgorithm, wide ))
275 return FALSE;
276 if (r1->Data.TKEY.dwCreateTime != r2->Data.TKEY.dwCreateTime ||
277 r1->Data.TKEY.dwExpireTime != r2->Data.TKEY.dwExpireTime ||
278 r1->Data.TKEY.wMode != r2->Data.TKEY.wMode ||
279 r1->Data.TKEY.wError != r2->Data.TKEY.wError ||
280 r1->Data.TKEY.wKeyLength != r2->Data.TKEY.wKeyLength ||
281 r1->Data.TKEY.wOtherLength != r2->Data.TKEY.wOtherLength ||
282 r1->Data.TKEY.cAlgNameLength != r2->Data.TKEY.cAlgNameLength ||
283 r1->Data.TKEY.bPacketPointers != r2->Data.TKEY.bPacketPointers)
284 return FALSE;
285
286 /* FIXME: ignoring pAlgorithmPacket field */
287 if (memcmp( r1->Data.TKEY.pKey, r2->Data.TKEY.pKey,
288 r1->Data.TKEY.wKeyLength ) ||
289 memcmp( r1->Data.TKEY.pOtherData, r2->Data.TKEY.pOtherData,
290 r1->Data.TKEY.wOtherLength )) return FALSE;
291 break;
292 }
293 case DNS_TYPE_TSIG:
294 {
295 if (dns_strcmpX( r1->Data.TSIG.pNameAlgorithm,
296 r2->Data.TSIG.pNameAlgorithm, wide ))
297 return FALSE;
298 if (r1->Data.TSIG.i64CreateTime != r2->Data.TSIG.i64CreateTime ||
299 r1->Data.TSIG.wFudgeTime != r2->Data.TSIG.wFudgeTime ||
300 r1->Data.TSIG.wOriginalXid != r2->Data.TSIG.wOriginalXid ||
301 r1->Data.TSIG.wError != r2->Data.TSIG.wError ||
302 r1->Data.TSIG.wSigLength != r2->Data.TSIG.wSigLength ||
303 r1->Data.TSIG.wOtherLength != r2->Data.TSIG.wOtherLength ||
304 r1->Data.TSIG.cAlgNameLength != r2->Data.TSIG.cAlgNameLength ||
305 r1->Data.TSIG.bPacketPointers != r2->Data.TSIG.bPacketPointers)
306 return FALSE;
307
308 /* FIXME: ignoring pAlgorithmPacket field */
309 if (memcmp( r1->Data.TSIG.pSignature, r2->Data.TSIG.pSignature,
310 r1->Data.TSIG.wSigLength ) ||
311 memcmp( r1->Data.TSIG.pOtherData, r2->Data.TSIG.pOtherData,
312 r1->Data.TSIG.wOtherLength )) return FALSE;
313 break;
314 }
315 case DNS_TYPE_WINS:
316 {
317 if (r1->Data.WINS.dwMappingFlag != r2->Data.WINS.dwMappingFlag ||
318 r1->Data.WINS.dwLookupTimeout != r2->Data.WINS.dwLookupTimeout ||
319 r1->Data.WINS.dwCacheTimeout != r2->Data.WINS.dwCacheTimeout ||
320 r1->Data.WINS.cWinsServerCount != r2->Data.WINS.cWinsServerCount)
321 return FALSE;
322 if (memcmp( r1->Data.WINS.WinsServers, r2->Data.WINS.WinsServers,
323 r1->wDataLength - sizeof(DNS_WINS_DATA) + sizeof(IP4_ADDRESS) ))
324 return FALSE;
325 break;
326 }
327 case DNS_TYPE_WINSR:
328 {
329 if (r1->Data.WINSR.dwMappingFlag != r2->Data.WINSR.dwMappingFlag ||
330 r1->Data.WINSR.dwLookupTimeout != r2->Data.WINSR.dwLookupTimeout ||
331 r1->Data.WINSR.dwCacheTimeout != r2->Data.WINSR.dwCacheTimeout)
332 return FALSE;
333 if (dns_strcmpX( r1->Data.WINSR.pNameResultDomain,
334 r2->Data.WINSR.pNameResultDomain, wide ))
335 return FALSE;
336 break;
337 }
338 default:
339 DPRINT1( "unknown type: %s\n", dns_type_to_str( r1->wType ) );
340 return FALSE;
341 }
342 return TRUE;
343 }
344
dns_strcpyX(LPCVOID src,DNS_CHARSET in,DNS_CHARSET out)345 static LPVOID dns_strcpyX( LPCVOID src, DNS_CHARSET in, DNS_CHARSET out )
346 {
347 switch (in)
348 {
349 case DnsCharSetUnicode:
350 {
351 switch (out)
352 {
353 case DnsCharSetUnicode: return dns_strdup_w( src );
354 case DnsCharSetUtf8: return dns_strdup_wu( src );
355 case DnsCharSetAnsi: return dns_strdup_wa( src );
356 default:
357 DPRINT1( "unhandled target charset: %d\n", out );
358 break;
359 }
360 break;
361 }
362 case DnsCharSetUtf8:
363 switch (out)
364 {
365 case DnsCharSetUnicode: return dns_strdup_uw( src );
366 case DnsCharSetUtf8: return dns_strdup_u( src );
367 case DnsCharSetAnsi: return dns_strdup_ua( src );
368 default:
369 DPRINT1( "unhandled target charset: %d\n", out );
370 break;
371 }
372 break;
373 case DnsCharSetAnsi:
374 switch (out)
375 {
376 case DnsCharSetUnicode: return dns_strdup_aw( src );
377 case DnsCharSetUtf8: return dns_strdup_au( src );
378 case DnsCharSetAnsi: return dns_strdup_a( src );
379 default:
380 DPRINT1( "unhandled target charset: %d\n", out );
381 break;
382 }
383 break;
384 default:
385 DPRINT1( "unhandled source charset: %d\n", in );
386 break;
387 }
388 return NULL;
389 }
390
391 /******************************************************************************
392 * DnsRecordCopyEx [DNSAPI.@]
393 *
394 */
DnsRecordCopyEx(PDNS_RECORD src,DNS_CHARSET in,DNS_CHARSET out)395 PDNS_RECORD WINAPI DnsRecordCopyEx( PDNS_RECORD src, DNS_CHARSET in, DNS_CHARSET out )
396 {
397 DNS_RECORD *dst;
398 unsigned int i, size;
399
400 DPRINT( "(%p,%d,%d)\n", src, in, out );
401
402 size = FIELD_OFFSET(DNS_RECORD, Data) + src->wDataLength;
403 dst = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
404 if (!dst) return NULL;
405
406 memcpy( dst, src, size );
407
408 if (src->Flags.S.CharSet == DnsCharSetUtf8 ||
409 src->Flags.S.CharSet == DnsCharSetAnsi ||
410 src->Flags.S.CharSet == DnsCharSetUnicode) in = src->Flags.S.CharSet;
411
412 dst->Flags.S.CharSet = out;
413 dst->pName = dns_strcpyX( src->pName, in, out );
414 if (!dst->pName) goto error;
415
416 switch (src->wType)
417 {
418 case DNS_TYPE_HINFO:
419 case DNS_TYPE_ISDN:
420 case DNS_TYPE_TEXT:
421 case DNS_TYPE_X25:
422 {
423 for (i = 0; i < src->Data.TXT.dwStringCount; i++)
424 {
425 dst->Data.TXT.pStringArray[i] =
426 dns_strcpyX( src->Data.TXT.pStringArray[i], in, out );
427
428 if (!dst->Data.TXT.pStringArray[i])
429 {
430 while (i > 0) HeapFree( GetProcessHeap(), 0, dst->Data.TXT.pStringArray[--i] );
431 goto error;
432 }
433 }
434 break;
435 }
436 case DNS_TYPE_MINFO:
437 case DNS_TYPE_RP:
438 {
439 dst->Data.MINFO.pNameMailbox =
440 dns_strcpyX( src->Data.MINFO.pNameMailbox, in, out );
441 if (!dst->Data.MINFO.pNameMailbox) goto error;
442
443 dst->Data.MINFO.pNameErrorsMailbox =
444 dns_strcpyX( src->Data.MINFO.pNameErrorsMailbox, in, out );
445 if (!dst->Data.MINFO.pNameErrorsMailbox)
446 {
447 HeapFree( GetProcessHeap(), 0, dst->Data.MINFO.pNameMailbox );
448 goto error;
449 }
450 break;
451 }
452 case DNS_TYPE_AFSDB:
453 case DNS_TYPE_RT:
454 case DNS_TYPE_MX:
455 {
456 dst->Data.MX.pNameExchange =
457 dns_strcpyX( src->Data.MX.pNameExchange, in, out );
458 if (!dst->Data.MX.pNameExchange) goto error;
459 break;
460 }
461 case DNS_TYPE_NXT:
462 {
463 dst->Data.NXT.pNameNext =
464 dns_strcpyX( src->Data.NXT.pNameNext, in, out );
465 if (!dst->Data.NXT.pNameNext) goto error;
466 break;
467 }
468 case DNS_TYPE_CNAME:
469 case DNS_TYPE_MB:
470 case DNS_TYPE_MD:
471 case DNS_TYPE_MF:
472 case DNS_TYPE_MG:
473 case DNS_TYPE_MR:
474 case DNS_TYPE_NS:
475 case DNS_TYPE_PTR:
476 {
477 dst->Data.PTR.pNameHost =
478 dns_strcpyX( src->Data.PTR.pNameHost, in, out );
479 if (!dst->Data.PTR.pNameHost) goto error;
480 break;
481 }
482 case DNS_TYPE_SIG:
483 {
484 dst->Data.SIG.pNameSigner =
485 dns_strcpyX( src->Data.SIG.pNameSigner, in, out );
486 if (!dst->Data.SIG.pNameSigner) goto error;
487 break;
488 }
489 case DNS_TYPE_SOA:
490 {
491 dst->Data.SOA.pNamePrimaryServer =
492 dns_strcpyX( src->Data.SOA.pNamePrimaryServer, in, out );
493 if (!dst->Data.SOA.pNamePrimaryServer) goto error;
494
495 dst->Data.SOA.pNameAdministrator =
496 dns_strcpyX( src->Data.SOA.pNameAdministrator, in, out );
497 if (!dst->Data.SOA.pNameAdministrator)
498 {
499 HeapFree( GetProcessHeap(), 0, dst->Data.SOA.pNamePrimaryServer );
500 goto error;
501 }
502 break;
503 }
504 case DNS_TYPE_SRV:
505 {
506 dst->Data.SRV.pNameTarget =
507 dns_strcpyX( src->Data.SRV.pNameTarget, in, out );
508 if (!dst->Data.SRV.pNameTarget) goto error;
509 break;
510 }
511 default:
512 break;
513 }
514 return dst;
515
516 error:
517 HeapFree( GetProcessHeap(), 0, dst->pName );
518 HeapFree( GetProcessHeap(), 0, dst );
519 return NULL;
520 }
521
522 /******************************************************************************
523 * DnsRecordListFree [DNSAPI.@]
524 *
525 */
DnsRecordListFree(PDNS_RECORD list,DNS_FREE_TYPE type)526 VOID WINAPI DnsRecordListFree( PDNS_RECORD list, DNS_FREE_TYPE type )
527 {
528 DNS_RECORD *r, *next;
529 unsigned int i;
530
531 DPRINT( "(%p,%d)\n", list, type );
532
533 if (!list) return;
534
535 switch (type)
536 {
537 case DnsFreeRecordList:
538 {
539 for (r = list; (list = r); r = next)
540 {
541 HeapFree( GetProcessHeap(), 0, r->pName );
542
543 switch (r->wType)
544 {
545 case DNS_TYPE_HINFO:
546 case DNS_TYPE_ISDN:
547 case DNS_TYPE_TEXT:
548 case DNS_TYPE_X25:
549 {
550 for (i = 0; i < r->Data.TXT.dwStringCount; i++)
551 HeapFree( GetProcessHeap(), 0, r->Data.TXT.pStringArray[i] );
552
553 break;
554 }
555 case DNS_TYPE_MINFO:
556 case DNS_TYPE_RP:
557 {
558 HeapFree( GetProcessHeap(), 0, r->Data.MINFO.pNameMailbox );
559 HeapFree( GetProcessHeap(), 0, r->Data.MINFO.pNameErrorsMailbox );
560 break;
561 }
562 case DNS_TYPE_AFSDB:
563 case DNS_TYPE_RT:
564 case DNS_TYPE_MX:
565 {
566 HeapFree( GetProcessHeap(), 0, r->Data.MX.pNameExchange );
567 break;
568 }
569 case DNS_TYPE_NXT:
570 {
571 HeapFree( GetProcessHeap(), 0, r->Data.NXT.pNameNext );
572 break;
573 }
574 case DNS_TYPE_CNAME:
575 case DNS_TYPE_MB:
576 case DNS_TYPE_MD:
577 case DNS_TYPE_MF:
578 case DNS_TYPE_MG:
579 case DNS_TYPE_MR:
580 case DNS_TYPE_NS:
581 case DNS_TYPE_PTR:
582 {
583 HeapFree( GetProcessHeap(), 0, r->Data.PTR.pNameHost );
584 break;
585 }
586 case DNS_TYPE_SIG:
587 {
588 HeapFree( GetProcessHeap(), 0, r->Data.SIG.pNameSigner );
589 break;
590 }
591 case DNS_TYPE_SOA:
592 {
593 HeapFree( GetProcessHeap(), 0, r->Data.SOA.pNamePrimaryServer );
594 HeapFree( GetProcessHeap(), 0, r->Data.SOA.pNameAdministrator );
595 break;
596 }
597 case DNS_TYPE_SRV:
598 {
599 HeapFree( GetProcessHeap(), 0, r->Data.SRV.pNameTarget );
600 break;
601 }
602 default:
603 break;
604 }
605
606 next = r->pNext;
607 HeapFree( GetProcessHeap(), 0, r );
608 }
609 break;
610 }
611 case DnsFreeFlat:
612 case DnsFreeParsedMessageFields:
613 {
614 DPRINT1( "unhandled free type: %d\n", type );
615 break;
616 }
617 default:
618 DPRINT1( "unknown free type: %d\n", type );
619 break;
620 }
621 }
622
623 /******************************************************************************
624 * DnsRecordSetCompare [DNSAPI.@]
625 *
626 */
DnsRecordSetCompare(PDNS_RECORD set1,PDNS_RECORD set2,PDNS_RECORD * diff1,PDNS_RECORD * diff2)627 BOOL WINAPI DnsRecordSetCompare( PDNS_RECORD set1, PDNS_RECORD set2,
628 PDNS_RECORD *diff1, PDNS_RECORD *diff2 )
629 {
630 BOOL ret = TRUE;
631 DNS_RECORD *r, *t, *u;
632 DNS_RRSET rr1, rr2;
633
634 DPRINT( "(%p,%p,%p,%p)\n", set1, set2, diff1, diff2 );
635
636 if (!set1 && !set2) return FALSE;
637
638 if (diff1) *diff1 = NULL;
639 if (diff2) *diff2 = NULL;
640
641 if (set1 && !set2)
642 {
643 if (diff1) *diff1 = DnsRecordSetCopyEx( set1, 0, set1->Flags.S.CharSet );
644 return FALSE;
645 }
646 if (!set1 && set2)
647 {
648 if (diff2) *diff2 = DnsRecordSetCopyEx( set2, 0, set2->Flags.S.CharSet );
649 return FALSE;
650 }
651
652 DNS_RRSET_INIT( rr1 );
653 DNS_RRSET_INIT( rr2 );
654
655 for (r = set1; r; r = r->pNext)
656 {
657 for (t = set2; t; t = t->pNext)
658 {
659 u = DnsRecordCopyEx( r, r->Flags.S.CharSet, t->Flags.S.CharSet );
660 if (!u) goto error;
661
662 if (!DnsRecordCompare( t, u ))
663 {
664 DNS_RRSET_ADD( rr1, u );
665 ret = FALSE;
666 }
667 else DnsRecordListFree( u, DnsFreeRecordList );
668 }
669 }
670
671 for (t = set2; t; t = t->pNext)
672 {
673 for (r = set1; r; r = r->pNext)
674 {
675 u = DnsRecordCopyEx( t, t->Flags.S.CharSet, r->Flags.S.CharSet );
676 if (!u) goto error;
677
678 if (!DnsRecordCompare( r, u ))
679 {
680 DNS_RRSET_ADD( rr2, u );
681 ret = FALSE;
682 }
683 else DnsRecordListFree( u, DnsFreeRecordList );
684 }
685 }
686
687 DNS_RRSET_TERMINATE( rr1 );
688 DNS_RRSET_TERMINATE( rr2 );
689
690 if (diff1) *diff1 = rr1.pFirstRR;
691 else DnsRecordListFree( rr1.pFirstRR, DnsFreeRecordList );
692
693 if (diff2) *diff2 = rr2.pFirstRR;
694 else DnsRecordListFree( rr2.pFirstRR, DnsFreeRecordList );
695
696 return ret;
697
698 error:
699 DNS_RRSET_TERMINATE( rr1 );
700 DNS_RRSET_TERMINATE( rr2 );
701
702 DnsRecordListFree( rr1.pFirstRR, DnsFreeRecordList );
703 DnsRecordListFree( rr2.pFirstRR, DnsFreeRecordList );
704
705 return FALSE;
706 }
707
708 /******************************************************************************
709 * DnsRecordSetCopyEx [DNSAPI.@]
710 *
711 */
DnsRecordSetCopyEx(PDNS_RECORD src_set,DNS_CHARSET in,DNS_CHARSET out)712 PDNS_RECORD WINAPI DnsRecordSetCopyEx( PDNS_RECORD src_set, DNS_CHARSET in, DNS_CHARSET out )
713 {
714 DNS_RRSET dst_set;
715 DNS_RECORD *src, *dst;
716
717 DPRINT( "(%p,%d,%d)\n", src_set, in, out );
718
719 DNS_RRSET_INIT( dst_set );
720
721 for (src = src_set; (src_set = src); src = src_set->pNext)
722 {
723 dst = DnsRecordCopyEx( src, in, out );
724 if (!dst)
725 {
726 DNS_RRSET_TERMINATE( dst_set );
727 DnsRecordListFree( dst_set.pFirstRR, DnsFreeRecordList );
728 return NULL;
729 }
730 DNS_RRSET_ADD( dst_set, dst );
731 }
732
733 DNS_RRSET_TERMINATE( dst_set );
734 return dst_set.pFirstRR;
735 }
736
737 /******************************************************************************
738 * DnsRecordSetDetach [DNSAPI.@]
739 *
740 */
DnsRecordSetDetach(PDNS_RECORD set)741 PDNS_RECORD WINAPI DnsRecordSetDetach( PDNS_RECORD set )
742 {
743 DNS_RECORD *r, *s;
744
745 DPRINT( "(%p)\n", set );
746
747 for (r = set; (set = r); r = set->pNext)
748 {
749 if (r->pNext && !r->pNext->pNext)
750 {
751 s = r->pNext;
752 r->pNext = NULL;
753 return s;
754 }
755 }
756 return NULL;
757 }
758