4 * Copyright (C) 2006 Hans Leidekker
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.
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/port.h"
23 #include "wine/debug.h"
27 #include <sys/types.h>
29 #ifdef HAVE_NETINET_IN_H
30 # include <netinet/in.h>
32 #ifdef HAVE_ARPA_NAMESER_H
33 # include <arpa/nameser.h>
47 WINE_DEFAULT_DEBUG_CHANNEL(dnsapi
);
49 const char *dns_type_to_str( unsigned short type
)
53 #define X(x) case (x): return #x;
111 default: { static char tmp
[7]; sprintf( tmp
, "0x%04x", type
); return tmp
; }
115 static int dns_strcmpX( LPCVOID str1
, LPCVOID str2
, BOOL wide
)
118 return lstrcmpiW( (LPCWSTR
)str1
, (LPCWSTR
)str2
);
120 return lstrcmpiA( (LPCSTR
)str1
, (LPCSTR
)str2
);
123 /******************************************************************************
124 * DnsRecordCompare [DNSAPI.@]
127 BOOL WINAPI
DnsRecordCompare( PDNS_RECORD r1
, PDNS_RECORD r2
)
132 TRACE( "(%p,%p)\n", r1
, r2
);
134 if (r1
->wType
!= r2
->wType
||
135 r1
->wDataLength
!= r2
->wDataLength
||
136 r1
->Flags
.DW
!= r2
->Flags
.DW
||
137 r1
->dwTtl
!= r2
->dwTtl
||
138 r1
->dwReserved
!= r2
->dwReserved
) return FALSE
;
140 wide
= (r1
->Flags
.S
.CharSet
== DnsCharSetUnicode
) ? TRUE
: FALSE
;
141 if (dns_strcmpX( r1
->pName
, r2
->pName
, wide
)) return FALSE
;
147 if (r1
->Data
.A
.IpAddress
!= r2
->Data
.A
.IpAddress
) return FALSE
;
152 if (r1
->Data
.SOA
.dwSerialNo
!= r2
->Data
.SOA
.dwSerialNo
||
153 r1
->Data
.SOA
.dwRefresh
!= r2
->Data
.SOA
.dwRefresh
||
154 r1
->Data
.SOA
.dwRetry
!= r2
->Data
.SOA
.dwRetry
||
155 r1
->Data
.SOA
.dwExpire
!= r2
->Data
.SOA
.dwExpire
||
156 r1
->Data
.SOA
.dwDefaultTtl
!= r2
->Data
.SOA
.dwDefaultTtl
)
158 if (dns_strcmpX( r1
->Data
.SOA
.pNamePrimaryServer
,
159 r2
->Data
.SOA
.pNamePrimaryServer
, wide
) ||
160 dns_strcmpX( r1
->Data
.SOA
.pNameAdministrator
,
161 r2
->Data
.SOA
.pNameAdministrator
, wide
))
174 if (dns_strcmpX( r1
->Data
.PTR
.pNameHost
,
175 r2
->Data
.PTR
.pNameHost
, wide
)) return FALSE
;
181 if (dns_strcmpX( r1
->Data
.MINFO
.pNameMailbox
,
182 r2
->Data
.MINFO
.pNameMailbox
, wide
) ||
183 dns_strcmpX( r1
->Data
.MINFO
.pNameErrorsMailbox
,
184 r2
->Data
.MINFO
.pNameErrorsMailbox
, wide
))
192 if (r1
->Data
.MX
.wPreference
!= r2
->Data
.MX
.wPreference
)
194 if (dns_strcmpX( r1
->Data
.MX
.pNameExchange
,
195 r2
->Data
.MX
.pNameExchange
, wide
))
204 if (r1
->Data
.TXT
.dwStringCount
!= r2
->Data
.TXT
.dwStringCount
)
206 for (i
= 0; i
< r1
->Data
.TXT
.dwStringCount
; i
++)
208 if (dns_strcmpX( r1
->Data
.TXT
.pStringArray
[i
],
209 r2
->Data
.TXT
.pStringArray
[i
], wide
))
216 if (r1
->Data
.Null
.dwByteCount
!= r2
->Data
.Null
.dwByteCount
)
218 if (memcmp( r1
->Data
.Null
.Data
,
219 r2
->Data
.Null
.Data
, r1
->Data
.Null
.dwByteCount
))
225 for (i
= 0; i
< sizeof(IP6_ADDRESS
)/sizeof(DWORD
); i
++)
227 if (r1
->Data
.AAAA
.Ip6Address
.IP6Dword
[i
] !=
228 r2
->Data
.AAAA
.Ip6Address
.IP6Dword
[i
]) return FALSE
;
234 if (r1
->Data
.KEY
.wFlags
!= r2
->Data
.KEY
.wFlags
||
235 r1
->Data
.KEY
.chProtocol
!= r2
->Data
.KEY
.chProtocol
||
236 r1
->Data
.KEY
.chAlgorithm
!= r2
->Data
.KEY
.chAlgorithm
)
238 if (memcmp( r1
->Data
.KEY
.Key
, r2
->Data
.KEY
.Key
,
239 r1
->wDataLength
- sizeof(DNS_KEY_DATA
) + 1 ))
245 if (dns_strcmpX( r1
->Data
.SIG
.pNameSigner
,
246 r2
->Data
.SIG
.pNameSigner
, wide
))
248 if (r1
->Data
.SIG
.wTypeCovered
!= r2
->Data
.SIG
.wTypeCovered
||
249 r1
->Data
.SIG
.chAlgorithm
!= r2
->Data
.SIG
.chAlgorithm
||
250 r1
->Data
.SIG
.chLabelCount
!= r2
->Data
.SIG
.chLabelCount
||
251 r1
->Data
.SIG
.dwOriginalTtl
!= r2
->Data
.SIG
.dwOriginalTtl
||
252 r1
->Data
.SIG
.dwExpiration
!= r2
->Data
.SIG
.dwExpiration
||
253 r1
->Data
.SIG
.dwTimeSigned
!= r2
->Data
.SIG
.dwTimeSigned
||
254 r1
->Data
.SIG
.wKeyTag
!= r2
->Data
.SIG
.wKeyTag
)
256 if (memcmp( r1
->Data
.SIG
.Signature
, r2
->Data
.SIG
.Signature
,
257 r1
->wDataLength
- sizeof(DNS_SIG_DATAA
) + 1 ))
263 if (r1
->Data
.ATMA
.AddressType
!= r2
->Data
.ATMA
.AddressType
)
265 for (i
= 0; i
< DNS_ATMA_MAX_ADDR_LENGTH
; i
++)
267 if (r1
->Data
.ATMA
.Address
[i
] != r2
->Data
.ATMA
.Address
[i
])
274 if (dns_strcmpX( r1
->Data
.NXT
.pNameNext
,
275 r2
->Data
.NXT
.pNameNext
, wide
)) return FALSE
;
276 if (r1
->Data
.NXT
.wNumTypes
!= r2
->Data
.NXT
.wNumTypes
) return FALSE
;
277 if (memcmp( r1
->Data
.NXT
.wTypes
, r2
->Data
.NXT
.wTypes
,
278 r1
->wDataLength
- sizeof(DNS_NXT_DATAA
) + sizeof(WORD
) ))
284 if (dns_strcmpX( r1
->Data
.SRV
.pNameTarget
,
285 r2
->Data
.SRV
.pNameTarget
, wide
)) return FALSE
;
286 if (r1
->Data
.SRV
.wPriority
!= r2
->Data
.SRV
.wPriority
||
287 r1
->Data
.SRV
.wWeight
!= r2
->Data
.SRV
.wWeight
||
288 r1
->Data
.SRV
.wPort
!= r2
->Data
.SRV
.wPort
)
294 if (dns_strcmpX( r1
->Data
.TKEY
.pNameAlgorithm
,
295 r2
->Data
.TKEY
.pNameAlgorithm
, wide
))
297 if (r1
->Data
.TKEY
.dwCreateTime
!= r2
->Data
.TKEY
.dwCreateTime
||
298 r1
->Data
.TKEY
.dwExpireTime
!= r2
->Data
.TKEY
.dwExpireTime
||
299 r1
->Data
.TKEY
.wMode
!= r2
->Data
.TKEY
.wMode
||
300 r1
->Data
.TKEY
.wError
!= r2
->Data
.TKEY
.wError
||
301 r1
->Data
.TKEY
.wKeyLength
!= r2
->Data
.TKEY
.wKeyLength
||
302 r1
->Data
.TKEY
.wOtherLength
!= r2
->Data
.TKEY
.wOtherLength
||
303 r1
->Data
.TKEY
.cAlgNameLength
!= r2
->Data
.TKEY
.cAlgNameLength
||
304 r1
->Data
.TKEY
.bPacketPointers
!= r2
->Data
.TKEY
.bPacketPointers
)
307 /* FIXME: ignoring pAlgorithmPacket field */
308 if (memcmp( r1
->Data
.TKEY
.pKey
, r2
->Data
.TKEY
.pKey
,
309 r1
->Data
.TKEY
.wKeyLength
) ||
310 memcmp( r1
->Data
.TKEY
.pOtherData
, r2
->Data
.TKEY
.pOtherData
,
311 r1
->Data
.TKEY
.wOtherLength
)) return FALSE
;
316 if (dns_strcmpX( r1
->Data
.TSIG
.pNameAlgorithm
,
317 r2
->Data
.TSIG
.pNameAlgorithm
, wide
))
319 if (r1
->Data
.TSIG
.i64CreateTime
!= r2
->Data
.TSIG
.i64CreateTime
||
320 r1
->Data
.TSIG
.wFudgeTime
!= r2
->Data
.TSIG
.wFudgeTime
||
321 r1
->Data
.TSIG
.wOriginalXid
!= r2
->Data
.TSIG
.wOriginalXid
||
322 r1
->Data
.TSIG
.wError
!= r2
->Data
.TSIG
.wError
||
323 r1
->Data
.TSIG
.wSigLength
!= r2
->Data
.TSIG
.wSigLength
||
324 r1
->Data
.TSIG
.wOtherLength
!= r2
->Data
.TSIG
.wOtherLength
||
325 r1
->Data
.TSIG
.cAlgNameLength
!= r2
->Data
.TSIG
.cAlgNameLength
||
326 r1
->Data
.TSIG
.bPacketPointers
!= r2
->Data
.TSIG
.bPacketPointers
)
329 /* FIXME: ignoring pAlgorithmPacket field */
330 if (memcmp( r1
->Data
.TSIG
.pSignature
, r2
->Data
.TSIG
.pSignature
,
331 r1
->Data
.TSIG
.wSigLength
) ||
332 memcmp( r1
->Data
.TSIG
.pOtherData
, r2
->Data
.TSIG
.pOtherData
,
333 r1
->Data
.TSIG
.wOtherLength
)) return FALSE
;
338 if (r1
->Data
.WINS
.dwMappingFlag
!= r2
->Data
.WINS
.dwMappingFlag
||
339 r1
->Data
.WINS
.dwLookupTimeout
!= r2
->Data
.WINS
.dwLookupTimeout
||
340 r1
->Data
.WINS
.dwCacheTimeout
!= r2
->Data
.WINS
.dwCacheTimeout
||
341 r1
->Data
.WINS
.cWinsServerCount
!= r2
->Data
.WINS
.cWinsServerCount
)
343 if (memcmp( r1
->Data
.WINS
.WinsServers
, r2
->Data
.WINS
.WinsServers
,
344 r1
->wDataLength
- sizeof(DNS_WINS_DATA
) + sizeof(IP4_ADDRESS
) ))
350 if (r1
->Data
.WINSR
.dwMappingFlag
!= r2
->Data
.WINSR
.dwMappingFlag
||
351 r1
->Data
.WINSR
.dwLookupTimeout
!= r2
->Data
.WINSR
.dwLookupTimeout
||
352 r1
->Data
.WINSR
.dwCacheTimeout
!= r2
->Data
.WINSR
.dwCacheTimeout
)
354 if (dns_strcmpX( r1
->Data
.WINSR
.pNameResultDomain
,
355 r2
->Data
.WINSR
.pNameResultDomain
, wide
))
360 FIXME( "unknown type: %s\n", dns_type_to_str( r1
->wType
) );
366 static LPVOID
dns_strcpyX( LPCVOID src
, DNS_CHARSET in
, DNS_CHARSET out
)
370 case DnsCharSetUnicode
:
374 case DnsCharSetUnicode
: return dns_strdup_w( src
);
375 case DnsCharSetUtf8
: return dns_strdup_wu( src
);
376 case DnsCharSetAnsi
: return dns_strdup_wa( src
);
378 WARN( "unhandled target charset: %d\n", out
);
385 case DnsCharSetUnicode
: return dns_strdup_uw( src
);
386 case DnsCharSetUtf8
: return dns_strdup_u( src
);
387 case DnsCharSetAnsi
: return dns_strdup_ua( src
);
389 WARN( "unhandled target charset: %d\n", out
);
395 case DnsCharSetUnicode
: return dns_strdup_aw( src
);
396 case DnsCharSetUtf8
: return dns_strdup_au( src
);
397 case DnsCharSetAnsi
: return dns_strdup_a( src
);
399 WARN( "unhandled target charset: %d\n", out
);
403 WARN( "unhandled source charset: %d\n", in
);
409 /******************************************************************************
410 * DnsRecordCopyEx [DNSAPI.@]
413 PDNS_RECORD WINAPI
DnsRecordCopyEx( PDNS_RECORD src
, DNS_CHARSET in
, DNS_CHARSET out
)
416 unsigned int i
, size
;
418 TRACE( "(%p,%d,%d)\n", src
, in
, out
);
420 size
= FIELD_OFFSET(DNS_RECORD
, Data
) + src
->wDataLength
;
421 dst
= dns_zero_alloc( size
);
422 if (!dst
) return NULL
;
424 memcpy( dst
, src
, size
);
426 if (src
->Flags
.S
.CharSet
== DnsCharSetUtf8
||
427 src
->Flags
.S
.CharSet
== DnsCharSetAnsi
||
428 src
->Flags
.S
.CharSet
== DnsCharSetUnicode
) in
= src
->Flags
.S
.CharSet
;
430 dst
->Flags
.S
.CharSet
= out
;
431 dst
->pName
= dns_strcpyX( src
->pName
, in
, out
);
432 if (!dst
->pName
) goto error
;
441 for (i
= 0; i
< src
->Data
.TXT
.dwStringCount
; i
++)
443 dst
->Data
.TXT
.pStringArray
[i
] =
444 dns_strcpyX( src
->Data
.TXT
.pStringArray
[i
], in
, out
);
446 if (!dst
->Data
.TXT
.pStringArray
[i
])
448 for (--i
; i
>= 0; i
--)
449 dns_free( dst
->Data
.TXT
.pStringArray
[i
] );
458 dst
->Data
.MINFO
.pNameMailbox
=
459 dns_strcpyX( src
->Data
.MINFO
.pNameMailbox
, in
, out
);
460 if (!dst
->Data
.MINFO
.pNameMailbox
) goto error
;
462 dst
->Data
.MINFO
.pNameErrorsMailbox
=
463 dns_strcpyX( src
->Data
.MINFO
.pNameErrorsMailbox
, in
, out
);
464 if (!dst
->Data
.MINFO
.pNameErrorsMailbox
)
466 dns_free( dst
->Data
.MINFO
.pNameMailbox
);
475 dst
->Data
.MX
.pNameExchange
=
476 dns_strcpyX( src
->Data
.MX
.pNameExchange
, in
, out
);
477 if (!dst
->Data
.MX
.pNameExchange
) goto error
;
482 dst
->Data
.NXT
.pNameNext
=
483 dns_strcpyX( src
->Data
.NXT
.pNameNext
, in
, out
);
484 if (!dst
->Data
.NXT
.pNameNext
) goto error
;
496 dst
->Data
.PTR
.pNameHost
=
497 dns_strcpyX( src
->Data
.PTR
.pNameHost
, in
, out
);
498 if (!dst
->Data
.PTR
.pNameHost
) goto error
;
503 dst
->Data
.SIG
.pNameSigner
=
504 dns_strcpyX( src
->Data
.SIG
.pNameSigner
, in
, out
);
505 if (!dst
->Data
.SIG
.pNameSigner
) goto error
;
510 dst
->Data
.SOA
.pNamePrimaryServer
=
511 dns_strcpyX( src
->Data
.SOA
.pNamePrimaryServer
, in
, out
);
512 if (!dst
->Data
.SOA
.pNamePrimaryServer
) goto error
;
514 dst
->Data
.SOA
.pNameAdministrator
=
515 dns_strcpyX( src
->Data
.SOA
.pNameAdministrator
, in
, out
);
516 if (!dst
->Data
.SOA
.pNameAdministrator
)
518 dns_free( dst
->Data
.SOA
.pNamePrimaryServer
);
525 dst
->Data
.SRV
.pNameTarget
=
526 dns_strcpyX( src
->Data
.SRV
.pNameTarget
, in
, out
);
527 if (!dst
->Data
.SRV
.pNameTarget
) goto error
;
536 dns_free( dst
->pName
);
541 /******************************************************************************
542 * DnsRecordListFree [DNSAPI.@]
545 void WINAPI
DnsRecordListFree( PDNS_RECORD list
, DNS_FREE_TYPE type
)
547 DNS_RECORD
*r
, *next
;
550 TRACE( "(%p,%d)\n", list
, type
);
556 case DnsFreeRecordList
:
558 for (r
= list
; (list
= r
); r
= next
)
560 dns_free( r
->pName
);
569 for (i
= 0; i
< r
->Data
.TXT
.dwStringCount
; i
++)
570 dns_free( r
->Data
.TXT
.pStringArray
[i
] );
577 dns_free( r
->Data
.MINFO
.pNameMailbox
);
578 dns_free( r
->Data
.MINFO
.pNameErrorsMailbox
);
585 dns_free( r
->Data
.MX
.pNameExchange
);
590 dns_free( r
->Data
.NXT
.pNameNext
);
602 dns_free( r
->Data
.PTR
.pNameHost
);
607 dns_free( r
->Data
.SIG
.pNameSigner
);
612 dns_free( r
->Data
.SOA
.pNamePrimaryServer
);
613 dns_free( r
->Data
.SOA
.pNameAdministrator
);
618 dns_free( r
->Data
.SRV
.pNameTarget
);
631 case DnsFreeParsedMessageFields
:
633 FIXME( "unhandled free type: %d\n", type
);
637 WARN( "unknown free type: %d\n", type
);
642 /******************************************************************************
643 * DnsRecordSetCopyEx [DNSAPI.@]
646 PDNS_RECORD WINAPI
DnsRecordSetCopyEx( PDNS_RECORD src_set
, DNS_CHARSET in
, DNS_CHARSET out
)
649 DNS_RECORD
*src
, *dst
;
651 TRACE( "(%p,%d,%d)\n", src_set
, in
, out
);
653 DNS_RRSET_INIT( dst_set
);
655 for (src
= src_set
; (src_set
= src
); src
= src_set
->pNext
)
657 dst
= DnsRecordCopyEx( src
, in
, out
);
660 DNS_RRSET_TERMINATE( dst_set
);
661 DnsRecordListFree( dst_set
.pFirstRR
, DnsFreeRecordList
);
664 DNS_RRSET_ADD( dst_set
, dst
);
667 DNS_RRSET_TERMINATE( dst_set
);
668 return dst_set
.pFirstRR
;