From 34a65739d32d7e895e71b2b81298fab82dfd11fe Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 4 May 2012 16:47:27 -0400 Subject: Move source3/libads/dns.c to lib/addns --- lib/addns/dnsquery.c | 910 +++++++++++++++++++++++++++++++++++++++++++ lib/addns/dnsquery.h | 61 +++ lib/addns/wscript_build | 5 + libcli/dns/wscript_build | 4 + libcli/nbt/wscript_build | 4 +- source3/Makefile.in | 2 +- source3/libads/dns.c | 908 ------------------------------------------ source3/libads/dns.h | 61 --- source3/libads/ldap.c | 2 +- source3/libsmb/dsgetdcname.c | 2 +- source3/libsmb/namequery.c | 2 +- source3/utils/net_ads.c | 2 +- source3/utils/net_lookup.c | 2 +- source3/wscript_build | 5 +- 14 files changed, 991 insertions(+), 979 deletions(-) create mode 100644 lib/addns/dnsquery.c create mode 100644 lib/addns/dnsquery.h mode change 100644 => 100755 lib/addns/wscript_build mode change 100644 => 100755 libcli/dns/wscript_build mode change 100644 => 100755 libcli/nbt/wscript_build delete mode 100644 source3/libads/dns.c delete mode 100644 source3/libads/dns.h diff --git a/lib/addns/dnsquery.c b/lib/addns/dnsquery.c new file mode 100644 index 0000000000..f680d63258 --- /dev/null +++ b/lib/addns/dnsquery.c @@ -0,0 +1,910 @@ +/* + Unix SMB/CIFS implementation. + DNS utility library + Copyright (C) Gerald (Jerry) Carter 2006. + Copyright (C) Jeremy Allison 2007. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "includes.h" +#include "lib/util/util_net.h" +#include "lib/util/tsort.h" +#include "dnsquery.h" + +/* AIX resolv.h uses 'class' in struct ns_rr */ + +#if defined(AIX) +# if defined(class) +# undef class +# endif +#endif /* AIX */ + +/* resolver headers */ + +#include +#include +#include +#include +#include + +#define MAX_DNS_PACKET_SIZE 0xffff + +#ifdef NS_HFIXEDSZ /* Bind 8/9 interface */ +#if !defined(C_IN) /* AIX 5.3 already defines C_IN */ +# define C_IN ns_c_in +#endif +#if !defined(T_A) /* AIX 5.3 already defines T_A */ +# define T_A ns_t_a +#endif + +#if defined(HAVE_IPV6) +#if !defined(T_AAAA) +# define T_AAAA ns_t_aaaa +#endif +#endif + +# define T_SRV ns_t_srv +#if !defined(T_NS) /* AIX 5.3 already defines T_NS */ +# define T_NS ns_t_ns +#endif +#else +# ifdef HFIXEDSZ +# define NS_HFIXEDSZ HFIXEDSZ +# else +# define NS_HFIXEDSZ sizeof(HEADER) +# endif /* HFIXEDSZ */ +# ifdef PACKETSZ +# define NS_PACKETSZ PACKETSZ +# else /* 512 is usually the default */ +# define NS_PACKETSZ 512 +# endif /* PACKETSZ */ +# define T_SRV 33 +#endif + +/********************************************************************* +*********************************************************************/ + +static bool ads_dns_parse_query( TALLOC_CTX *ctx, uint8_t *start, uint8_t *end, + uint8_t **ptr, struct dns_query *q ) +{ + uint8_t *p = *ptr; + char hostname[MAX_DNS_NAME_LENGTH]; + int namelen; + + ZERO_STRUCTP( q ); + + if ( !start || !end || !q || !*ptr) + return false; + + /* See RFC 1035 for details. If this fails, then return. */ + + namelen = dn_expand( start, end, p, hostname, sizeof(hostname) ); + if ( namelen < 0 ) { + return false; + } + p += namelen; + q->hostname = talloc_strdup( ctx, hostname ); + + /* check that we have space remaining */ + + if ( PTR_DIFF(p+4, end) > 0 ) + return false; + + q->type = RSVAL( p, 0 ); + q->in_class = RSVAL( p, 2 ); + p += 4; + + *ptr = p; + + return true; +} + +/********************************************************************* +*********************************************************************/ + +static bool ads_dns_parse_rr( TALLOC_CTX *ctx, uint8_t *start, uint8_t *end, + uint8_t **ptr, struct dns_rr *rr ) +{ + uint8_t *p = *ptr; + char hostname[MAX_DNS_NAME_LENGTH]; + int namelen; + + if ( !start || !end || !rr || !*ptr) + return -1; + + ZERO_STRUCTP( rr ); + /* pull the name from the answer */ + + namelen = dn_expand( start, end, p, hostname, sizeof(hostname) ); + if ( namelen < 0 ) { + return -1; + } + p += namelen; + rr->hostname = talloc_strdup( ctx, hostname ); + + /* check that we have space remaining */ + + if ( PTR_DIFF(p+10, end) > 0 ) + return false; + + /* pull some values and then skip onto the string */ + + rr->type = RSVAL(p, 0); + rr->in_class = RSVAL(p, 2); + rr->ttl = RIVAL(p, 4); + rr->rdatalen = RSVAL(p, 8); + + p += 10; + + /* sanity check the available space */ + + if ( PTR_DIFF(p+rr->rdatalen, end ) > 0 ) { + return false; + + } + + /* save a point to the rdata for this section */ + + rr->rdata = p; + p += rr->rdatalen; + + *ptr = p; + + return true; +} + +/********************************************************************* +*********************************************************************/ + +static bool ads_dns_parse_rr_srv( TALLOC_CTX *ctx, uint8_t *start, uint8_t *end, + uint8_t **ptr, struct dns_rr_srv *srv ) +{ + struct dns_rr rr; + uint8_t *p; + char dcname[MAX_DNS_NAME_LENGTH]; + int namelen; + + if ( !start || !end || !srv || !*ptr) + return -1; + + /* Parse the RR entry. Coming out of the this, ptr is at the beginning + of the next record */ + + if ( !ads_dns_parse_rr( ctx, start, end, ptr, &rr ) ) { + DEBUG(1,("ads_dns_parse_rr_srv: Failed to parse RR record\n")); + return false; + } + + if ( rr.type != T_SRV ) { + DEBUG(1,("ads_dns_parse_rr_srv: Bad answer type (%d)\n", + rr.type)); + return false; + } + + p = rr.rdata; + + srv->priority = RSVAL(p, 0); + srv->weight = RSVAL(p, 2); + srv->port = RSVAL(p, 4); + + p += 6; + + namelen = dn_expand( start, end, p, dcname, sizeof(dcname) ); + if ( namelen < 0 ) { + DEBUG(1,("ads_dns_parse_rr_srv: Failed to uncompress name!\n")); + return false; + } + + srv->hostname = talloc_strdup( ctx, dcname ); + + DEBUG(10,("ads_dns_parse_rr_srv: Parsed %s [%u, %u, %u]\n", + srv->hostname, + srv->priority, + srv->weight, + srv->port)); + + return true; +} + +/********************************************************************* +*********************************************************************/ + +static bool ads_dns_parse_rr_ns( TALLOC_CTX *ctx, uint8_t *start, uint8_t *end, + uint8_t **ptr, struct dns_rr_ns *nsrec ) +{ + struct dns_rr rr; + uint8_t *p; + char nsname[MAX_DNS_NAME_LENGTH]; + int namelen; + + if ( !start || !end || !nsrec || !*ptr) + return -1; + + /* Parse the RR entry. Coming out of the this, ptr is at the beginning + of the next record */ + + if ( !ads_dns_parse_rr( ctx, start, end, ptr, &rr ) ) { + DEBUG(1,("ads_dns_parse_rr_ns: Failed to parse RR record\n")); + return false; + } + + if ( rr.type != T_NS ) { + DEBUG(1,("ads_dns_parse_rr_ns: Bad answer type (%d)\n", + rr.type)); + return false; + } + + p = rr.rdata; + + /* ame server hostname */ + + namelen = dn_expand( start, end, p, nsname, sizeof(nsname) ); + if ( namelen < 0 ) { + DEBUG(1,("ads_dns_parse_rr_ns: Failed to uncompress name!\n")); + return false; + } + nsrec->hostname = talloc_strdup( ctx, nsname ); + + return true; +} + +/********************************************************************* + Sort SRV record list based on weight and priority. See RFC 2782. +*********************************************************************/ + +static int dnssrvcmp( struct dns_rr_srv *a, struct dns_rr_srv *b ) +{ + if ( a->priority == b->priority ) { + + /* randomize entries with an equal weight and priority */ + if ( a->weight == b->weight ) + return 0; + + /* higher weights should be sorted lower */ + if ( a->weight > b->weight ) + return -1; + else + return 1; + } + + if ( a->priority < b->priority ) + return -1; + + return 1; +} + +/********************************************************************* + Simple wrapper for a DNS query +*********************************************************************/ + +#define DNS_FAILED_WAITTIME 30 + +static NTSTATUS dns_send_req( TALLOC_CTX *ctx, const char *name, int q_type, + uint8_t **buf, int *resp_length ) +{ + uint8_t *buffer = NULL; + size_t buf_len = 0; + int resp_len = NS_PACKETSZ; + static time_t last_dns_check = 0; + static NTSTATUS last_dns_status = NT_STATUS_OK; + time_t now = time_mono(NULL); + + /* Try to prevent bursts of DNS lookups if the server is down */ + + /* Protect against large clock changes */ + + if ( last_dns_check > now ) + last_dns_check = 0; + + /* IF we had a DNS timeout or a bad server and we are still + in the 30 second cache window, just return the previous + status and save the network timeout. */ + + if ( (NT_STATUS_EQUAL(last_dns_status,NT_STATUS_IO_TIMEOUT) || + NT_STATUS_EQUAL(last_dns_status,NT_STATUS_CONNECTION_REFUSED)) && + (last_dns_check+DNS_FAILED_WAITTIME) > now ) + { + DEBUG(10,("last_dns_check: Returning cached status (%s)\n", + nt_errstr(last_dns_status) )); + return last_dns_status; + } + + /* Send the Query */ + do { + if ( buffer ) + TALLOC_FREE( buffer ); + + buf_len = resp_len * sizeof(uint8_t); + + if (buf_len) { + if ((buffer = talloc_array(ctx, uint8_t, buf_len)) + == NULL ) { + DEBUG(0,("ads_dns_lookup_srv: " + "talloc() failed!\n")); + last_dns_status = NT_STATUS_NO_MEMORY; + last_dns_check = time_mono(NULL); + return last_dns_status; + } + } + + if ((resp_len = res_query(name, C_IN, q_type, buffer, buf_len)) + < 0 ) { + DEBUG(3,("ads_dns_lookup_srv: " + "Failed to resolve %s (%s)\n", + name, strerror(errno))); + TALLOC_FREE( buffer ); + last_dns_status = NT_STATUS_UNSUCCESSFUL; + + if (errno == ETIMEDOUT) { + last_dns_status = NT_STATUS_IO_TIMEOUT; + } + if (errno == ECONNREFUSED) { + last_dns_status = NT_STATUS_CONNECTION_REFUSED; + } + last_dns_check = time_mono(NULL); + return last_dns_status; + } + + /* On AIX, Solaris, and possibly some older glibc systems (e.g. SLES8) + truncated replies never give back a resp_len > buflen + which ends up causing DNS resolve failures on large tcp DNS replies */ + + if (buf_len == resp_len) { + if (resp_len == MAX_DNS_PACKET_SIZE) { + DEBUG(1,("dns_send_req: DNS reply too large when resolving %s\n", + name)); + TALLOC_FREE( buffer ); + last_dns_status = NT_STATUS_BUFFER_TOO_SMALL; + last_dns_check = time_mono(NULL); + return last_dns_status; + } + + resp_len = MIN(resp_len*2, MAX_DNS_PACKET_SIZE); + } + + + } while ( buf_len < resp_len && resp_len <= MAX_DNS_PACKET_SIZE ); + + *buf = buffer; + *resp_length = resp_len; + + last_dns_check = time_mono(NULL); + last_dns_status = NT_STATUS_OK; + return last_dns_status; +} + +/********************************************************************* + Simple wrapper for a DNS SRV query +*********************************************************************/ + +static NTSTATUS ads_dns_lookup_srv( TALLOC_CTX *ctx, + const char *dns_hosts_file, + const char *name, + struct dns_rr_srv **dclist, + int *numdcs) +{ + uint8_t *buffer = NULL; + int resp_len = 0; + struct dns_rr_srv *dcs = NULL; + int query_count, answer_count, auth_count, additional_count; + uint8_t *p = buffer; + int rrnum; + int idx = 0; + NTSTATUS status; + + if ( !ctx || !name || !dclist ) { + return NT_STATUS_INVALID_PARAMETER; + } + + if (dns_hosts_file) { + return resolve_dns_hosts_file_as_dns_rr(dns_hosts_file, + name, true, ctx, + dclist, numdcs); + } + + /* Send the request. May have to loop several times in case + of large replies */ + + status = dns_send_req( ctx, name, T_SRV, &buffer, &resp_len ); + if ( !NT_STATUS_IS_OK(status) ) { + DEBUG(3,("ads_dns_lookup_srv: Failed to send DNS query (%s)\n", + nt_errstr(status))); + return status; + } + p = buffer; + + /* For some insane reason, the ns_initparse() et. al. routines are only + available in libresolv.a, and not the shared lib. Who knows why.... + So we have to parse the DNS reply ourselves */ + + /* Pull the answer RR's count from the header. + * Use the NMB ordering macros */ + + query_count = RSVAL( p, 4 ); + answer_count = RSVAL( p, 6 ); + auth_count = RSVAL( p, 8 ); + additional_count = RSVAL( p, 10 ); + + DEBUG(4,("ads_dns_lookup_srv: " + "%d records returned in the answer section.\n", + answer_count)); + + if (answer_count) { + if ((dcs = talloc_zero_array(ctx, struct dns_rr_srv, + answer_count)) == NULL ) { + DEBUG(0,("ads_dns_lookup_srv: " + "talloc() failure for %d char*'s\n", + answer_count)); + return NT_STATUS_NO_MEMORY; + } + } else { + dcs = NULL; + } + + /* now skip the header */ + + p += NS_HFIXEDSZ; + + /* parse the query section */ + + for ( rrnum=0; rrnum. + */ + +#ifndef _ADS_DNS_H +#define _ADS_DNS_H + +#include "libcli/dns/dns.h" + +/* The following definitions come from libads/dns.c */ + +NTSTATUS ads_dns_lookup_ns(TALLOC_CTX *ctx, + const char *dns_hosts_file, + const char *dnsdomain, + struct dns_rr_ns **nslist, + int *numns); +NTSTATUS ads_dns_query_dcs(TALLOC_CTX *ctx, + const char *dns_hosts_file, + const char *realm, + const char *sitename, + struct dns_rr_srv **dclist, + int *numdcs ); +NTSTATUS ads_dns_query_gcs(TALLOC_CTX *ctx, + const char *dns_hosts_file, + const char *realm, + const char *sitename, + struct dns_rr_srv **dclist, + int *numdcs ); +NTSTATUS ads_dns_query_kdcs(TALLOC_CTX *ctx, + const char *dns_hosts_file, + const char *dns_forest_name, + const char *sitename, + struct dns_rr_srv **dclist, + int *numdcs ); +NTSTATUS ads_dns_query_pdc(TALLOC_CTX *ctx, + const char *dns_hosts_file, + const char *dns_domain_name, + struct dns_rr_srv **dclist, + int *numdcs ); +NTSTATUS ads_dns_query_dcs_guid(TALLOC_CTX *ctx, + const char *dns_hosts_file, + const char *dns_forest_name, + const char *domain_guid, + struct dns_rr_srv **dclist, + int *numdcs ); +#endif /* _ADS_DNS_H */ diff --git a/lib/addns/wscript_build b/lib/addns/wscript_build old mode 100644 new mode 100755 index 69a4716245..a7010531a0 --- a/lib/addns/wscript_build +++ b/lib/addns/wscript_build @@ -5,3 +5,8 @@ bld.SAMBA_LIBRARY('addns', public_deps='talloc krb5 k5crypto com_err gssapi gssapi_krb5 uuid', private_library=True, vars=locals()) + +bld.SAMBA_SUBSYSTEM('DNSQUERY', + source='dnsquery.c', + deps='samba-util lmhosts resolv' + ) diff --git a/libcli/dns/wscript_build b/libcli/dns/wscript_build old mode 100644 new mode 100755 index 2e445da141..fab872712f --- a/libcli/dns/wscript_build +++ b/libcli/dns/wscript_build @@ -3,3 +3,7 @@ bld.SAMBA_SUBSYSTEM('LIBCLI_DNS', source='dns.c', deps='LIBTSOCKET tevent-util') + +bld.SAMBA_SUBSYSTEM('DNS_HOSTS_FILE', + source='dns_hosts_file.c', + deps='samba-util errors') diff --git a/libcli/nbt/wscript_build b/libcli/nbt/wscript_build old mode 100644 new mode 100755 index a70db083e6..55867bae91 --- a/libcli/nbt/wscript_build +++ b/libcli/nbt/wscript_build @@ -7,8 +7,8 @@ bld.SAMBA_SUBSYSTEM('NDR_NBT_BUF', ) bld.SAMBA_SUBSYSTEM('lmhosts', - source='lmhosts.c ../dns/dns_hosts_file.c', - deps='replace talloc' + source='lmhosts.c', + deps='DNS_HOSTS_FILE replace talloc' ) bld.SAMBA_LIBRARY('cli-nbt', diff --git a/source3/Makefile.in b/source3/Makefile.in index 1eb8cd8bf3..31382db542 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -544,7 +544,7 @@ LIBNBT_OBJ = ../libcli/nbt/nbtname.o \ LIBNMB_OBJ = libsmb/unexpected.o libsmb/namecache.o libsmb/nmblib.o \ libsmb/namequery.o ../libcli/nbt/lmhosts.o ../libcli/dns/dns_hosts_file.o libsmb/conncache.o \ - libads/dns.o libads/sitename_cache.o + ../lib/addds/dnsquery.o libads/sitename_cache.o NTERR_OBJ = ../libcli/util/nterr.o libsmb/smberr.o DOSERR_OBJ = ../libcli/util/doserr.o diff --git a/source3/libads/dns.c b/source3/libads/dns.c deleted file mode 100644 index 6f846fa780..0000000000 --- a/source3/libads/dns.c +++ /dev/null @@ -1,908 +0,0 @@ -/* - Unix SMB/CIFS implementation. - DNS utility library - Copyright (C) Gerald (Jerry) Carter 2006. - Copyright (C) Jeremy Allison 2007. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ - -#include "includes.h" -#include "libads/dns.h" - -/* AIX resolv.h uses 'class' in struct ns_rr */ - -#if defined(AIX) -# if defined(class) -# undef class -# endif -#endif /* AIX */ - -/* resolver headers */ - -#include -#include -#include -#include -#include - -#define MAX_DNS_PACKET_SIZE 0xffff - -#ifdef NS_HFIXEDSZ /* Bind 8/9 interface */ -#if !defined(C_IN) /* AIX 5.3 already defines C_IN */ -# define C_IN ns_c_in -#endif -#if !defined(T_A) /* AIX 5.3 already defines T_A */ -# define T_A ns_t_a -#endif - -#if defined(HAVE_IPV6) -#if !defined(T_AAAA) -# define T_AAAA ns_t_aaaa -#endif -#endif - -# define T_SRV ns_t_srv -#if !defined(T_NS) /* AIX 5.3 already defines T_NS */ -# define T_NS ns_t_ns -#endif -#else -# ifdef HFIXEDSZ -# define NS_HFIXEDSZ HFIXEDSZ -# else -# define NS_HFIXEDSZ sizeof(HEADER) -# endif /* HFIXEDSZ */ -# ifdef PACKETSZ -# define NS_PACKETSZ PACKETSZ -# else /* 512 is usually the default */ -# define NS_PACKETSZ 512 -# endif /* PACKETSZ */ -# define T_SRV 33 -#endif - -/********************************************************************* -*********************************************************************/ - -static bool ads_dns_parse_query( TALLOC_CTX *ctx, uint8_t *start, uint8_t *end, - uint8_t **ptr, struct dns_query *q ) -{ - uint8_t *p = *ptr; - char hostname[MAX_DNS_NAME_LENGTH]; - int namelen; - - ZERO_STRUCTP( q ); - - if ( !start || !end || !q || !*ptr) - return false; - - /* See RFC 1035 for details. If this fails, then return. */ - - namelen = dn_expand( start, end, p, hostname, sizeof(hostname) ); - if ( namelen < 0 ) { - return false; - } - p += namelen; - q->hostname = talloc_strdup( ctx, hostname ); - - /* check that we have space remaining */ - - if ( PTR_DIFF(p+4, end) > 0 ) - return false; - - q->type = RSVAL( p, 0 ); - q->in_class = RSVAL( p, 2 ); - p += 4; - - *ptr = p; - - return true; -} - -/********************************************************************* -*********************************************************************/ - -static bool ads_dns_parse_rr( TALLOC_CTX *ctx, uint8_t *start, uint8_t *end, - uint8_t **ptr, struct dns_rr *rr ) -{ - uint8_t *p = *ptr; - char hostname[MAX_DNS_NAME_LENGTH]; - int namelen; - - if ( !start || !end || !rr || !*ptr) - return -1; - - ZERO_STRUCTP( rr ); - /* pull the name from the answer */ - - namelen = dn_expand( start, end, p, hostname, sizeof(hostname) ); - if ( namelen < 0 ) { - return -1; - } - p += namelen; - rr->hostname = talloc_strdup( ctx, hostname ); - - /* check that we have space remaining */ - - if ( PTR_DIFF(p+10, end) > 0 ) - return false; - - /* pull some values and then skip onto the string */ - - rr->type = RSVAL(p, 0); - rr->in_class = RSVAL(p, 2); - rr->ttl = RIVAL(p, 4); - rr->rdatalen = RSVAL(p, 8); - - p += 10; - - /* sanity check the available space */ - - if ( PTR_DIFF(p+rr->rdatalen, end ) > 0 ) { - return false; - - } - - /* save a point to the rdata for this section */ - - rr->rdata = p; - p += rr->rdatalen; - - *ptr = p; - - return true; -} - -/********************************************************************* -*********************************************************************/ - -static bool ads_dns_parse_rr_srv( TALLOC_CTX *ctx, uint8_t *start, uint8_t *end, - uint8_t **ptr, struct dns_rr_srv *srv ) -{ - struct dns_rr rr; - uint8_t *p; - char dcname[MAX_DNS_NAME_LENGTH]; - int namelen; - - if ( !start || !end || !srv || !*ptr) - return -1; - - /* Parse the RR entry. Coming out of the this, ptr is at the beginning - of the next record */ - - if ( !ads_dns_parse_rr( ctx, start, end, ptr, &rr ) ) { - DEBUG(1,("ads_dns_parse_rr_srv: Failed to parse RR record\n")); - return false; - } - - if ( rr.type != T_SRV ) { - DEBUG(1,("ads_dns_parse_rr_srv: Bad answer type (%d)\n", - rr.type)); - return false; - } - - p = rr.rdata; - - srv->priority = RSVAL(p, 0); - srv->weight = RSVAL(p, 2); - srv->port = RSVAL(p, 4); - - p += 6; - - namelen = dn_expand( start, end, p, dcname, sizeof(dcname) ); - if ( namelen < 0 ) { - DEBUG(1,("ads_dns_parse_rr_srv: Failed to uncompress name!\n")); - return false; - } - - srv->hostname = talloc_strdup( ctx, dcname ); - - DEBUG(10,("ads_dns_parse_rr_srv: Parsed %s [%u, %u, %u]\n", - srv->hostname, - srv->priority, - srv->weight, - srv->port)); - - return true; -} - -/********************************************************************* -*********************************************************************/ - -static bool ads_dns_parse_rr_ns( TALLOC_CTX *ctx, uint8_t *start, uint8_t *end, - uint8_t **ptr, struct dns_rr_ns *nsrec ) -{ - struct dns_rr rr; - uint8_t *p; - char nsname[MAX_DNS_NAME_LENGTH]; - int namelen; - - if ( !start || !end || !nsrec || !*ptr) - return -1; - - /* Parse the RR entry. Coming out of the this, ptr is at the beginning - of the next record */ - - if ( !ads_dns_parse_rr( ctx, start, end, ptr, &rr ) ) { - DEBUG(1,("ads_dns_parse_rr_ns: Failed to parse RR record\n")); - return false; - } - - if ( rr.type != T_NS ) { - DEBUG(1,("ads_dns_parse_rr_ns: Bad answer type (%d)\n", - rr.type)); - return false; - } - - p = rr.rdata; - - /* ame server hostname */ - - namelen = dn_expand( start, end, p, nsname, sizeof(nsname) ); - if ( namelen < 0 ) { - DEBUG(1,("ads_dns_parse_rr_ns: Failed to uncompress name!\n")); - return false; - } - nsrec->hostname = talloc_strdup( ctx, nsname ); - - return true; -} - -/********************************************************************* - Sort SRV record list based on weight and priority. See RFC 2782. -*********************************************************************/ - -static int dnssrvcmp( struct dns_rr_srv *a, struct dns_rr_srv *b ) -{ - if ( a->priority == b->priority ) { - - /* randomize entries with an equal weight and priority */ - if ( a->weight == b->weight ) - return 0; - - /* higher weights should be sorted lower */ - if ( a->weight > b->weight ) - return -1; - else - return 1; - } - - if ( a->priority < b->priority ) - return -1; - - return 1; -} - -/********************************************************************* - Simple wrapper for a DNS query -*********************************************************************/ - -#define DNS_FAILED_WAITTIME 30 - -static NTSTATUS dns_send_req( TALLOC_CTX *ctx, const char *name, int q_type, - uint8_t **buf, int *resp_length ) -{ - uint8_t *buffer = NULL; - size_t buf_len = 0; - int resp_len = NS_PACKETSZ; - static time_t last_dns_check = 0; - static NTSTATUS last_dns_status = NT_STATUS_OK; - time_t now = time_mono(NULL); - - /* Try to prevent bursts of DNS lookups if the server is down */ - - /* Protect against large clock changes */ - - if ( last_dns_check > now ) - last_dns_check = 0; - - /* IF we had a DNS timeout or a bad server and we are still - in the 30 second cache window, just return the previous - status and save the network timeout. */ - - if ( (NT_STATUS_EQUAL(last_dns_status,NT_STATUS_IO_TIMEOUT) || - NT_STATUS_EQUAL(last_dns_status,NT_STATUS_CONNECTION_REFUSED)) && - (last_dns_check+DNS_FAILED_WAITTIME) > now ) - { - DEBUG(10,("last_dns_check: Returning cached status (%s)\n", - nt_errstr(last_dns_status) )); - return last_dns_status; - } - - /* Send the Query */ - do { - if ( buffer ) - TALLOC_FREE( buffer ); - - buf_len = resp_len * sizeof(uint8_t); - - if (buf_len) { - if ((buffer = talloc_array(ctx, uint8_t, buf_len)) - == NULL ) { - DEBUG(0,("ads_dns_lookup_srv: " - "talloc() failed!\n")); - last_dns_status = NT_STATUS_NO_MEMORY; - last_dns_check = time_mono(NULL); - return last_dns_status; - } - } - - if ((resp_len = res_query(name, C_IN, q_type, buffer, buf_len)) - < 0 ) { - DEBUG(3,("ads_dns_lookup_srv: " - "Failed to resolve %s (%s)\n", - name, strerror(errno))); - TALLOC_FREE( buffer ); - last_dns_status = NT_STATUS_UNSUCCESSFUL; - - if (errno == ETIMEDOUT) { - last_dns_status = NT_STATUS_IO_TIMEOUT; - } - if (errno == ECONNREFUSED) { - last_dns_status = NT_STATUS_CONNECTION_REFUSED; - } - last_dns_check = time_mono(NULL); - return last_dns_status; - } - - /* On AIX, Solaris, and possibly some older glibc systems (e.g. SLES8) - truncated replies never give back a resp_len > buflen - which ends up causing DNS resolve failures on large tcp DNS replies */ - - if (buf_len == resp_len) { - if (resp_len == MAX_DNS_PACKET_SIZE) { - DEBUG(1,("dns_send_req: DNS reply too large when resolving %s\n", - name)); - TALLOC_FREE( buffer ); - last_dns_status = NT_STATUS_BUFFER_TOO_SMALL; - last_dns_check = time_mono(NULL); - return last_dns_status; - } - - resp_len = MIN(resp_len*2, MAX_DNS_PACKET_SIZE); - } - - - } while ( buf_len < resp_len && resp_len <= MAX_DNS_PACKET_SIZE ); - - *buf = buffer; - *resp_length = resp_len; - - last_dns_check = time_mono(NULL); - last_dns_status = NT_STATUS_OK; - return last_dns_status; -} - -/********************************************************************* - Simple wrapper for a DNS SRV query -*********************************************************************/ - -static NTSTATUS ads_dns_lookup_srv( TALLOC_CTX *ctx, - const char *dns_hosts_file, - const char *name, - struct dns_rr_srv **dclist, - int *numdcs) -{ - uint8_t *buffer = NULL; - int resp_len = 0; - struct dns_rr_srv *dcs = NULL; - int query_count, answer_count, auth_count, additional_count; - uint8_t *p = buffer; - int rrnum; - int idx = 0; - NTSTATUS status; - - if ( !ctx || !name || !dclist ) { - return NT_STATUS_INVALID_PARAMETER; - } - - if (dns_hosts_file) { - return resolve_dns_hosts_file_as_dns_rr(dns_hosts_file, - name, true, ctx, - dclist, numdcs); - } - - /* Send the request. May have to loop several times in case - of large replies */ - - status = dns_send_req( ctx, name, T_SRV, &buffer, &resp_len ); - if ( !NT_STATUS_IS_OK(status) ) { - DEBUG(3,("ads_dns_lookup_srv: Failed to send DNS query (%s)\n", - nt_errstr(status))); - return status; - } - p = buffer; - - /* For some insane reason, the ns_initparse() et. al. routines are only - available in libresolv.a, and not the shared lib. Who knows why.... - So we have to parse the DNS reply ourselves */ - - /* Pull the answer RR's count from the header. - * Use the NMB ordering macros */ - - query_count = RSVAL( p, 4 ); - answer_count = RSVAL( p, 6 ); - auth_count = RSVAL( p, 8 ); - additional_count = RSVAL( p, 10 ); - - DEBUG(4,("ads_dns_lookup_srv: " - "%d records returned in the answer section.\n", - answer_count)); - - if (answer_count) { - if ((dcs = talloc_zero_array(ctx, struct dns_rr_srv, - answer_count)) == NULL ) { - DEBUG(0,("ads_dns_lookup_srv: " - "talloc() failure for %d char*'s\n", - answer_count)); - return NT_STATUS_NO_MEMORY; - } - } else { - dcs = NULL; - } - - /* now skip the header */ - - p += NS_HFIXEDSZ; - - /* parse the query section */ - - for ( rrnum=0; rrnum. - */ - -#ifndef _ADS_DNS_H -#define _ADS_DNS_H - -#include "libcli/dns/dns.h" - -/* The following definitions come from libads/dns.c */ - -NTSTATUS ads_dns_lookup_ns(TALLOC_CTX *ctx, - const char *dns_hosts_file, - const char *dnsdomain, - struct dns_rr_ns **nslist, - int *numns); -NTSTATUS ads_dns_query_dcs(TALLOC_CTX *ctx, - const char *dns_hosts_file, - const char *realm, - const char *sitename, - struct dns_rr_srv **dclist, - int *numdcs ); -NTSTATUS ads_dns_query_gcs(TALLOC_CTX *ctx, - const char *dns_hosts_file, - const char *realm, - const char *sitename, - struct dns_rr_srv **dclist, - int *numdcs ); -NTSTATUS ads_dns_query_kdcs(TALLOC_CTX *ctx, - const char *dns_hosts_file, - const char *dns_forest_name, - const char *sitename, - struct dns_rr_srv **dclist, - int *numdcs ); -NTSTATUS ads_dns_query_pdc(TALLOC_CTX *ctx, - const char *dns_hosts_file, - const char *dns_domain_name, - struct dns_rr_srv **dclist, - int *numdcs ); -NTSTATUS ads_dns_query_dcs_guid(TALLOC_CTX *ctx, - const char *dns_hosts_file, - const char *dns_forest_name, - const char *domain_guid, - struct dns_rr_srv **dclist, - int *numdcs ); -#endif /* _ADS_DNS_H */ diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 23b655f401..f3987c99c1 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -25,7 +25,7 @@ #include "ads.h" #include "libads/sitename_cache.h" #include "libads/cldap.h" -#include "libads/dns.h" +#include "../lib/addns/dnsquery.h" #include "../libds/common/flags.h" #include "smbldap.h" #include "../libcli/security/security.h" diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c index 7b4b68195a..02f4bc928d 100644 --- a/source3/libsmb/dsgetdcname.c +++ b/source3/libsmb/dsgetdcname.c @@ -24,7 +24,7 @@ #include "libads/sitename_cache.h" #include "../librpc/gen_ndr/ndr_netlogon.h" #include "libads/cldap.h" -#include "libads/dns.h" +#include "../lib/addns/dnsquery.h" #include "libsmb/clidgram.h" /* 15 minutes */ diff --git a/source3/libsmb/namequery.c b/source3/libsmb/namequery.c index 417464c17e..3eae347068 100644 --- a/source3/libsmb/namequery.c +++ b/source3/libsmb/namequery.c @@ -21,7 +21,7 @@ #include "includes.h" #include "../lib/util/tevent_ntstatus.h" #include "libads/sitename_cache.h" -#include "libads/dns.h" +#include "../lib/addns/dnsquery.h" #include "../libcli/netlogon/netlogon.h" #include "lib/async_req/async_sock.h" #include "libsmb/nmblib.h" diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 22f235f059..de00a1e3bb 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -28,7 +28,7 @@ #include "nsswitch/libwbclient/wbclient.h" #include "ads.h" #include "libads/cldap.h" -#include "libads/dns.h" +#include "../lib/addns/dnsquery.h" #include "../libds/common/flags.h" #include "librpc/gen_ndr/libnet_join.h" #include "libnet/libnet_join.h" diff --git a/source3/utils/net_lookup.c b/source3/utils/net_lookup.c index 7f204745b1..b0d6fe51f0 100644 --- a/source3/utils/net_lookup.c +++ b/source3/utils/net_lookup.c @@ -19,7 +19,7 @@ #include "includes.h" #include "utils/net.h" #include "libads/sitename_cache.h" -#include "libads/dns.h" +#include "../lib/addns/dnsquery.h" #include "../librpc/gen_ndr/ndr_netlogon.h" #include "smb_krb5.h" #include "../libcli/security/security.h" diff --git a/source3/wscript_build b/source3/wscript_build index 4deb556d23..2f474a871a 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -113,7 +113,8 @@ SECRETS_SRC = '''passdb/secrets.c passdb/machine_account_secrets.c LIBNMB_SRC = '''libsmb/unexpected.c libsmb/namecache.c libsmb/nmblib.c libsmb/namequery.c libsmb/conncache.c - libads/dns.c libads/sitename_cache.c''' + + libads/sitename_cache.c''' LIBNTLMSSP_SRC = ''' libsmb/ntlmssp.c @@ -1006,7 +1007,7 @@ bld.SAMBA3_SUBSYSTEM('LIBEVENTLOG', bld.SAMBA3_SUBSYSTEM('LIBNMB', source=LIBNMB_SRC, - deps='lmhosts resolv', + deps='DNSQUERY lmhosts resolv', vars=locals()) bld.SAMBA3_SUBSYSTEM('SERVICES', -- cgit