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 2 of the License, or
+ 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,
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, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
/*********************************************************************
*********************************************************************/
-static BOOL ads_dns_parse_query( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
+static bool ads_dns_parse_query( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
uint8 **ptr, struct dns_query *q )
{
uint8 *p = *ptr;
/*********************************************************************
*********************************************************************/
-static BOOL ads_dns_parse_rr( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
+static bool ads_dns_parse_rr( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
uint8 **ptr, struct dns_rr *rr )
{
uint8 *p = *ptr;
/*********************************************************************
*********************************************************************/
-static BOOL ads_dns_parse_rr_srv( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
+static bool ads_dns_parse_rr_srv( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
uint8 **ptr, struct dns_rr_srv *srv )
{
struct dns_rr rr;
/*********************************************************************
*********************************************************************/
-static BOOL ads_dns_parse_rr_ns( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
+static bool ads_dns_parse_rr_ns( TALLOC_CTX *ctx, uint8 *start, uint8 *end,
uint8 **ptr, struct dns_rr_ns *nsrec )
{
struct dns_rr rr;
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 **buf, int *resp_length )
{
uint8 *buffer = NULL;
size_t buf_len;
int resp_len = NS_PACKETSZ;
-
+ static time_t last_dns_check = 0;
+ static NTSTATUS last_dns_status = NT_STATUS_OK;
+ time_t now = time(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);
- if (buf_len) {
+ if (buf_len) {
if ( (buffer = TALLOC_ARRAY(ctx, uint8, buf_len)) == NULL ) {
DEBUG(0,("ads_dns_lookup_srv: talloc() failed!\n"));
- return NT_STATUS_NO_MEMORY;
+ last_dns_status = NT_STATUS_NO_MEMORY;
+ last_dns_check = time(NULL);
+ return last_dns_status;
}
- } else {
- buffer = NULL;
}
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) {
- return NT_STATUS_IO_TIMEOUT;
+ last_dns_status = NT_STATUS_IO_TIMEOUT;
}
if (errno == ECONNREFUSED) {
- return NT_STATUS_CONNECTION_REFUSED;
+ last_dns_status = NT_STATUS_CONNECTION_REFUSED;
}
- return NT_STATUS_UNSUCCESSFUL;
+ last_dns_check = time(NULL);
+ return last_dns_status;
}
} while ( buf_len < resp_len && resp_len < MAX_DNS_PACKET_SIZE );
*buf = buffer;
*resp_length = resp_len;
- return NT_STATUS_OK;
+ last_dns_check = time(NULL);
+ last_dns_status = NT_STATUS_OK;
+ return last_dns_status;
}
/*********************************************************************
/****************************************************************************
Store the AD client sitename.
We store indefinately as every new CLDAP query will re-write this.
- If the sitename is "Default-First-Site-Name" we don't store it
- as this isn't a valid DNS name.
****************************************************************************/
-BOOL sitename_store(const char *realm, const char *sitename)
+bool sitename_store(const char *realm, const char *sitename)
{
time_t expire;
- BOOL ret = False;
+ bool ret = False;
char *key;
if (!gencache_init()) {
}
if (!realm || (strlen(realm) == 0)) {
- DEBUG(0,("no realm\n"));
+ DEBUG(0,("sitename_store: no realm\n"));
return False;
}
{
char *sitename = NULL;
time_t timeout;
- BOOL ret = False;
+ bool ret = False;
const char *query_realm;
char *key;
Did the sitename change ?
****************************************************************************/
-BOOL stored_sitename_changed(const char *realm, const char *sitename)
+bool stored_sitename_changed(const char *realm, const char *sitename)
{
- BOOL ret = False;
+ bool ret = False;
char *new_sitename;
if (!realm || (strlen(realm) == 0)) {
- DEBUG(0,("no realm\n"));
+ DEBUG(0,("stored_sitename_changed: no realm\n"));
return False;
}
Query with optional sitename.
********************************************************************/
-NTSTATUS ads_dns_query_internal(TALLOC_CTX *ctx,
- const char *servicename,
- const char *realm,
- const char *sitename,
- struct dns_rr_srv **dclist,
- int *numdcs )
+static NTSTATUS ads_dns_query_internal(TALLOC_CTX *ctx,
+ const char *servicename,
+ const char *dc_pdc_gc_domains,
+ const char *realm,
+ const char *sitename,
+ struct dns_rr_srv **dclist,
+ int *numdcs )
{
char *name;
if (sitename) {
- name = talloc_asprintf(ctx, "%s._tcp.%s._sites.dc._msdcs.%s",
- servicename, sitename, realm );
- } else {
- name = talloc_asprintf(ctx, "%s._tcp.dc._msdcs.%s",
- servicename, realm );
- }
+ name = talloc_asprintf(ctx, "%s._tcp.%s._sites.%s._msdcs.%s",
+ servicename, sitename,
+ dc_pdc_gc_domains, realm);
+ } else {
+ name = talloc_asprintf(ctx, "%s._tcp.%s._msdcs.%s",
+ servicename, dc_pdc_gc_domains, realm);
+ }
if (!name) {
return NT_STATUS_NO_MEMORY;
}
********************************************************************/
NTSTATUS ads_dns_query_dcs(TALLOC_CTX *ctx,
- const char *realm,
- const char *sitename,
- struct dns_rr_srv **dclist,
- int *numdcs )
+ const char *realm,
+ const char *sitename,
+ struct dns_rr_srv **dclist,
+ int *numdcs )
{
NTSTATUS status;
- status = ads_dns_query_internal(ctx, "_ldap", realm, sitename,
+ status = ads_dns_query_internal(ctx, "_ldap", "dc", realm, sitename,
dclist, numdcs);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
return status;
}
- if (sitename && !NT_STATUS_IS_OK(status)) {
+ if (sitename &&
+ ((!NT_STATUS_IS_OK(status)) ||
+ (NT_STATUS_IS_OK(status) && (numdcs == 0)))) {
/* Sitename DNS query may have failed. Try without. */
- status = ads_dns_query_internal(ctx, "_ldap", realm, NULL,
- dclist, numdcs);
+ status = ads_dns_query_internal(ctx, "_ldap", "dc", realm,
+ NULL, dclist, numdcs);
+ }
+ return status;
+}
+
+/********************************************************************
+ Query for AD GC's.
+********************************************************************/
+
+NTSTATUS ads_dns_query_gcs(TALLOC_CTX *ctx,
+ const char *realm,
+ const char *sitename,
+ struct dns_rr_srv **dclist,
+ int *numdcs )
+{
+ NTSTATUS status;
+
+ status = ads_dns_query_internal(ctx, "_ldap", "gc", realm, sitename,
+ dclist, numdcs);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
+ NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) {
+ return status;
+ }
+
+ if (sitename &&
+ ((!NT_STATUS_IS_OK(status)) ||
+ (NT_STATUS_IS_OK(status) && (numdcs == 0)))) {
+ /* Sitename DNS query may have failed. Try without. */
+ status = ads_dns_query_internal(ctx, "_ldap", "gc", realm,
+ NULL, dclist, numdcs);
}
return status;
}
********************************************************************/
NTSTATUS ads_dns_query_kdcs(TALLOC_CTX *ctx,
- const char *realm,
- const char *sitename,
- struct dns_rr_srv **dclist,
- int *numdcs )
+ const char *dns_forest_name,
+ const char *sitename,
+ struct dns_rr_srv **dclist,
+ int *numdcs )
{
NTSTATUS status;
- status = ads_dns_query_internal(ctx, "_kerberos", realm, sitename,
- dclist, numdcs);
+ status = ads_dns_query_internal(ctx, "_kerberos", "dc",
+ dns_forest_name, sitename, dclist,
+ numdcs);
if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT) ||
NT_STATUS_EQUAL(status, NT_STATUS_CONNECTION_REFUSED)) {
return status;
}
- if (sitename && !NT_STATUS_IS_OK(status)) {
+ if (sitename &&
+ ((!NT_STATUS_IS_OK(status)) ||
+ (NT_STATUS_IS_OK(status) && (numdcs == 0)))) {
/* Sitename DNS query may have failed. Try without. */
- status = ads_dns_query_internal(ctx, "_kerberos", realm, NULL,
+ status = ads_dns_query_internal(ctx, "_kerberos", "dc",
+ dns_forest_name, NULL,
dclist, numdcs);
}
return status;
}
+
+/********************************************************************
+ Query for AD PDC. Sitename is obsolete here.
+********************************************************************/
+
+NTSTATUS ads_dns_query_pdc(TALLOC_CTX *ctx,
+ const char *dns_domain_name,
+ struct dns_rr_srv **dclist,
+ int *numdcs )
+{
+ return ads_dns_query_internal(ctx, "_ldap", "pdc", dns_domain_name,
+ NULL, dclist, numdcs);
+}
+
+/********************************************************************
+ Query for AD DC by guid. Sitename is obsolete here.
+********************************************************************/
+
+NTSTATUS ads_dns_query_dcs_guid(TALLOC_CTX *ctx,
+ const char *dns_forest_name,
+ const struct GUID *domain_guid,
+ struct dns_rr_srv **dclist,
+ int *numdcs )
+{
+ /*_ldap._tcp.DomainGuid.domains._msdcs.DnsForestName */
+
+ const char *domains;
+ const char *guid_string;
+
+ guid_string = GUID_string(ctx, domain_guid);
+ if (!guid_string) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* little hack */
+ domains = talloc_asprintf(ctx, "%s.domains", guid_string);
+ if (!domains) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ return ads_dns_query_internal(ctx, "_ldap", domains, dns_forest_name,
+ NULL, dclist, numdcs);
+}