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.
-
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "includes.h"
/* nmbd.c sets this to True. */
BOOL global_in_nmbd = False;
-
/****************************
* SERVER AFFINITY ROUTINES *
****************************/
DEBUG(2,("saf_store: Refusing to store empty domain or servername!\n"));
return False;
}
+
+ if ( (strlen(domain) == 0) || (strlen(servername) == 0) ) {
+ DEBUG(0,("saf_store: refusing to store 0 length domain or servername!\n"));
+ return False;
+ }
if ( !gencache_init() )
return False;
return ret;
}
+BOOL saf_delete( const char *domain )
+{
+ char *key;
+ BOOL ret = False;
+
+ if ( !domain ) {
+ DEBUG(2,("saf_delete: Refusing to delete empty domain\n"));
+ return False;
+ }
+
+ if ( !gencache_init() )
+ return False;
+
+ key = saf_key(domain);
+ ret = gencache_del(key);
+
+ if (ret) {
+ DEBUG(10,("saf_delete: domain = [%s]\n", domain ));
+ }
+
+ SAFE_FREE( key );
+
+ return ret;
+}
+
/****************************************************************************
****************************************************************************/
BOOL ret = False;
char *key = NULL;
- if ( !domain ) {
+ if ( !domain || strlen(domain) == 0) {
DEBUG(2,("saf_fetch: Empty domain name!\n"));
return NULL;
}
return server;
}
-
/****************************************************************************
Generate a random trn_id.
****************************************************************************/
compare 2 ldap IPs by nearness to our interfaces - used in qsort
*******************************************************************/
-static int ip_service_compare(struct ip_service *ip1, struct ip_service *ip2)
+int ip_service_compare(struct ip_service *ip1, struct ip_service *ip2)
{
int result;
*********************************************************/
static BOOL resolve_ads(const char *name, int name_type,
+ const char *sitename,
struct ip_service **return_iplist, int *return_count)
{
int i, j;
int numdcs = 0;
int numaddrs = 0;
- if ( name_type != 0x1c )
+ if ((name_type != 0x1c) && (name_type != KDC_NAME_TYPE))
return False;
- DEBUG(5,("resolve_hosts: Attempting to resolve DC's for %s using DNS\n",
+ DEBUG(5,("resolve_ads: Attempting to resolve DC's for %s using DNS\n",
name));
if ( (ctx = talloc_init("resolve_ads")) == NULL ) {
DEBUG(0,("resolve_ads: talloc_init() failed!\n"));
return False;
}
-
- status = ads_dns_query_dcs( ctx, name, &dcs, &numdcs );
+
+ if (name_type == KDC_NAME_TYPE) {
+ status = ads_dns_query_kdcs(ctx, name, sitename, &dcs, &numdcs);
+ } else {
+ status = ads_dns_query_dcs(ctx, name, sitename, &dcs, &numdcs);
+ }
if ( !NT_STATUS_IS_OK( status ) ) {
+ talloc_destroy(ctx);
return False;
}
if ( (*return_iplist = SMB_MALLOC_ARRAY(struct ip_service, numaddrs)) == NULL ) {
DEBUG(0,("resolve_ads: malloc failed for %d entries\n", numaddrs ));
+ talloc_destroy(ctx);
return False;
}
(*return_count)++;
}
- TALLOC_FREE( dcs );
-
+ talloc_destroy(ctx);
return True;
}
**********************************************************************/
BOOL internal_resolve_name(const char *name, int name_type,
+ const char *sitename,
struct ip_service **return_iplist,
int *return_count, const char *resolve_order)
{
*return_iplist = NULL;
*return_count = 0;
- DEBUG(10, ("internal_resolve_name: looking up %s#%x\n", name, name_type));
+ DEBUG(10, ("internal_resolve_name: looking up %s#%x (sitename %s)\n",
+ name, name_type, sitename ? sitename : NULL));
if (allzeros || allones || is_address) {
result = True;
goto done;
}
+ } else if(strequal( tok, "kdc")) {
+ /* deal with KDC_NAME_TYPE names here. This will result in a
+ SRV record lookup */
+ if (resolve_ads(name, KDC_NAME_TYPE, sitename, return_iplist, return_count)) {
+ result = True;
+ /* Ensure we don't namecache this with the KDC port. */
+ name_type = KDC_NAME_TYPE;
+ goto done;
+ }
} else if(strequal( tok, "ads")) {
/* deal with 0x1c names here. This will result in a
SRV record lookup */
- if (resolve_ads(name, name_type, return_iplist, return_count)) {
+ if (resolve_ads(name, name_type, sitename, return_iplist, return_count)) {
result = True;
goto done;
}
BOOL resolve_name(const char *name, struct in_addr *return_ip, int name_type)
{
struct ip_service *ip_list = NULL;
+ char *sitename = sitename_fetch();
int count = 0;
if (is_ipaddress(name)) {
*return_ip = *interpret_addr2(name);
+ SAFE_FREE(sitename);
return True;
}
- if (internal_resolve_name(name, name_type, &ip_list, &count, lp_name_resolve_order())) {
+ if (internal_resolve_name(name, name_type, sitename, &ip_list, &count, lp_name_resolve_order())) {
int i;
/* only return valid addresses for TCP connections */
{
*return_ip = ip_list[i].ip;
SAFE_FREE(ip_list);
+ SAFE_FREE(sitename);
return True;
}
}
}
SAFE_FREE(ip_list);
+ SAFE_FREE(sitename);
return False;
}
return False;
}
- if (internal_resolve_name(group, 0x1D, &ip_list, &count, lp_name_resolve_order())) {
+ if (internal_resolve_name(group, 0x1D, NULL, &ip_list, &count, lp_name_resolve_order())) {
*master_ip = ip_list[0].ip;
SAFE_FREE(ip_list);
return True;
}
- if(internal_resolve_name(group, 0x1B, &ip_list, &count, lp_name_resolve_order())) {
+ if(internal_resolve_name(group, 0x1B, NULL, &ip_list, &count, lp_name_resolve_order())) {
*master_ip = ip_list[0].ip;
SAFE_FREE(ip_list);
return True;
BOOL get_pdc_ip(const char *domain, struct in_addr *ip)
{
- struct ip_service *ip_list;
- int count;
+ char *sitename = sitename_fetch();
+ struct ip_service *ip_list = NULL;
+ int count = 0;
/* Look up #1B name */
- if (!internal_resolve_name(domain, 0x1b, &ip_list, &count, lp_name_resolve_order())) {
+ if (!internal_resolve_name(domain, 0x1b, sitename, &ip_list, &count, lp_name_resolve_order())) {
+ SAFE_FREE(sitename);
return False;
}
+ SAFE_FREE(sitename);
+
/* if we get more than 1 IP back we have to assume it is a
multi-homed PDC and not a mess up */
return True;
}
+/* Private enum type for lookups. */
+
+enum dc_lookup_type { DC_NORMAL_LOOKUP, DC_ADS_ONLY, DC_KDC_ONLY };
+
/********************************************************
Get the IP address list of the domain controllers for
a domain.
*********************************************************/
-static NTSTATUS get_dc_list(const char *domain, struct ip_service **ip_list,
- int *count, BOOL ads_only, int *ordered)
+static NTSTATUS get_dc_list(const char *domain, const char *sitename, struct ip_service **ip_list,
+ int *count, enum dc_lookup_type lookup_type, int *ordered)
{
fstring resolve_order;
char *saf_servername;
fstrcpy( resolve_order, lp_name_resolve_order() );
strlower_m( resolve_order );
- if ( ads_only ) {
+ if ( lookup_type == DC_ADS_ONLY) {
if ( strstr( resolve_order, "host" ) ) {
fstrcpy( resolve_order, "ads" );
} else {
fstrcpy( resolve_order, "NULL" );
}
+ } else if (lookup_type == DC_KDC_ONLY) {
+ /* DNS SRV lookups used by the ads/kdc resolver
+ are already sorted by priority and weight */
+ *ordered = True;
+ fstrcpy( resolve_order, "kdc" );
}
/* fetch the server we have affinity for. Add the
'password server' list to a search for our domain controllers */
- saf_servername = saf_fetch( domain );
+ saf_servername = saf_fetch( domain);
if ( strequal(domain, lp_workgroup()) || strequal(domain, lp_realm()) ) {
pstr_sprintf( pserver, "%s, %s",
DEBUG(10,("get_dc_list: no preferred domain controllers.\n"));
/* TODO: change return type of internal_resolve_name to
* NTSTATUS */
- if (internal_resolve_name(domain, 0x1C, ip_list, count,
+ if (internal_resolve_name(domain, 0x1C, sitename, ip_list, count,
resolve_order)) {
return NT_STATUS_OK;
} else {
p = pserver;
while (next_token(&p,name,LIST_SEP,sizeof(name))) {
if (strequal(name, "*")) {
- if (internal_resolve_name(domain, 0x1C, &auto_ip_list,
+ if (internal_resolve_name(domain, 0x1C, sitename, &auto_ip_list,
&auto_count, resolve_order))
num_addresses += auto_count;
done_auto_lookup = True;
just return the list of DC's. Or maybe we just failed. */
if ( (num_addresses == 0) ) {
- if ( !done_auto_lookup ) {
- if (internal_resolve_name(domain, 0x1C, ip_list, count, resolve_order)) {
- return NT_STATUS_OK;
- } else {
- return NT_STATUS_NO_LOGON_SERVERS;
- }
- } else {
+ if ( done_auto_lookup ) {
DEBUG(4,("get_dc_list: no servers found\n"));
+ SAFE_FREE(auto_ip_list);
+ return NT_STATUS_NO_LOGON_SERVERS;
+ }
+ if (internal_resolve_name(domain, 0x1C, sitename, ip_list, count,
+ resolve_order)) {
+ return NT_STATUS_OK;
+ } else {
return NT_STATUS_NO_LOGON_SERVERS;
}
}
if ( (return_iplist = SMB_MALLOC_ARRAY(struct ip_service, num_addresses)) == NULL ) {
DEBUG(3,("get_dc_list: malloc fail !\n"));
+ SAFE_FREE(auto_ip_list);
return NT_STATUS_NO_MEMORY;
}
Small wrapper function to get the DC list and sort it if neccessary.
*********************************************************************/
-NTSTATUS get_sorted_dc_list( const char *domain, struct ip_service **ip_list, int *count, BOOL ads_only )
+NTSTATUS get_sorted_dc_list( const char *domain, const char *sitename, struct ip_service **ip_list, int *count, BOOL ads_only )
{
BOOL ordered;
NTSTATUS status;
-
- DEBUG(8,("get_sorted_dc_list: attempting lookup using [%s]\n",
+ enum dc_lookup_type lookup_type = DC_NORMAL_LOOKUP;
+
+ DEBUG(8,("get_sorted_dc_list: attempting lookup for name %s (sitename %s) "
+ "using [%s]\n",
+ domain,
+ sitename ? sitename : "NULL",
(ads_only ? "ads" : lp_name_resolve_order())));
- status = get_dc_list(domain, ip_list, count, ads_only, &ordered);
+ if (ads_only) {
+ lookup_type = DC_ADS_ONLY;
+ }
+
+ status = get_dc_list(domain, sitename, ip_list, count, lookup_type, &ordered);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
return NT_STATUS_OK;
}
+
+/*********************************************************************
+ Get the KDC list - re-use all the logic in get_dc_list.
+*********************************************************************/
+
+NTSTATUS get_kdc_list( const char *realm, const char *sitename, struct ip_service **ip_list, int *count)
+{
+ BOOL ordered;
+ NTSTATUS status;
+
+ *count = 0;
+ *ip_list = NULL;
+
+ status = get_dc_list(realm, sitename, ip_list, count, DC_KDC_ONLY, &ordered);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* only sort if we don't already have an ordered list */
+ if ( !ordered ) {
+ sort_ip_list2( *ip_list, *count );
+ }
+
+ return NT_STATUS_OK;
+}