summaryrefslogtreecommitdiff
path: root/usr/src/lib/libadutils/common/addisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libadutils/common/addisc.c')
-rw-r--r--usr/src/lib/libadutils/common/addisc.c108
1 files changed, 70 insertions, 38 deletions
diff --git a/usr/src/lib/libadutils/common/addisc.c b/usr/src/lib/libadutils/common/addisc.c
index b32f9d7694..187981b5a2 100644
--- a/usr/src/lib/libadutils/common/addisc.c
+++ b/usr/src/lib/libadutils/common/addisc.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -103,6 +102,16 @@
#include "adutils_impl.h"
#include "addisc.h"
+/*
+ * These set some sanity policies for discovery. After a discovery
+ * cycle, we will consider the results (successful or unsuccessful)
+ * to be valid for at least MINIMUM_TTL seconds, and for at most
+ * MAXIMUM_TTL seconds. Note that the caller is free to request
+ * discovery cycles sooner than MINIMUM_TTL if it has reason to believe
+ * that the situation has changed.
+ */
+#define MINIMUM_TTL (5 * 60)
+#define MAXIMUM_TTL (20 * 60)
enum ad_item_state {
AD_STATE_INVALID = 0, /* The value is not valid */
@@ -127,7 +136,7 @@ typedef struct ad_item {
enum ad_item_state state;
enum ad_data_type type;
void *value;
- time_t ttl;
+ time_t expires;
unsigned int version; /* Version is only changed */
/* if the value changes */
#define PARAM1 0
@@ -144,6 +153,8 @@ typedef struct ad_disc {
ad_subnet_t *subnets;
boolean_t subnets_changed;
time_t subnets_last_check;
+ time_t expires_not_before;
+ time_t expires_not_after;
ad_item_t domain_name; /* DNS hostname string */
ad_item_t domain_controller; /* Directory hostname and */
/* port array */
@@ -216,7 +227,7 @@ is_valid(ad_item_t *item)
if (item->state == AD_STATE_FIXED)
return (B_TRUE);
if (item->state == AD_STATE_AUTO &&
- (item->ttl == 0 || item->ttl > time(NULL)))
+ (item->expires == 0 || item->expires > time(NULL)))
return (B_TRUE);
}
return (B_FALSE);
@@ -247,9 +258,9 @@ update_item(ad_item_t *item, void *value, enum ad_item_state state,
item->state = state;
if (ttl == 0)
- item->ttl = 0;
+ item->expires = 0;
else
- item->ttl = time(NULL) + ttl;
+ item->expires = time(NULL) + ttl;
}
@@ -593,26 +604,6 @@ DN_to_DNS(const char *dn_name)
}
-/* Format the DN of an AD LDAP subnet object for some subnet */
-static char *
-subnet_to_DN(const char *subnet, const char *baseDN)
-{
- char *result;
- int len;
-
- len = snprintf(NULL, 0,
- "CN=%s,CN=Subnets,CN=Sites,%s",
- subnet, baseDN) + 1;
-
- result = malloc(len);
- if (result != NULL)
- (void) snprintf(result, len,
- "CN=%s,CN=Subnets,CN=Sites,%s",
- subnet, baseDN);
- return (result);
-}
-
-
/* Make a list of subnet object DNs from a list of subnets */
static char **
subnets_to_DNs(ad_subnet_t *subnets, const char *base_dn)
@@ -628,8 +619,9 @@ subnets_to_DNs(ad_subnet_t *subnets, const char *base_dn)
return (NULL);
for (i = 0; subnets[i].subnet[0] != '\0'; i++) {
- if ((results[i] = subnet_to_DN(subnets[i].subnet, base_dn))
- == NULL) {
+ (void) asprintf(&results[i], "CN=%s,CN=Subnets,CN=Sites,%s",
+ subnets[i].subnet, base_dn);
+ if (results[i] == NULL) {
for (j = 0; j < i; j++)
free(results[j]);
free(results);
@@ -828,7 +820,8 @@ err:
* A utility function to bind to a Directory server
*/
-static LDAP*
+static
+LDAP *
ldap_lookup_init(idmap_ad_disc_ds_t *ds)
{
int i;
@@ -988,15 +981,17 @@ ldap_lookup_trusted_domains(LDAP **ld, idmap_ad_disc_ds_t *globalCatalog,
if (partner != NULL && direction != NULL) {
num++;
- trusted_domains = realloc(trusted_domains,
+ void *tmp = realloc(trusted_domains,
(num + 1) *
sizeof (ad_disc_trusteddomains_t));
- if (trusted_domains == NULL) {
+ if (tmp == NULL) {
+ free(trusted_domains);
ldap_value_free(partner);
ldap_value_free(direction);
ldap_msgfree(results);
return (NULL);
}
+ trusted_domains = tmp;
/* Last element should be zero */
memset(&trusted_domains[num], 0,
sizeof (ad_disc_trusteddomains_t));
@@ -1221,6 +1216,22 @@ ad_disc_refresh(ad_disc_t ctx)
}
+/*
+ * Called when the discovery cycle is done. Sets a master TTL
+ * that will avoid doing new time-based discoveries too soon after
+ * the last discovery cycle. Most interesting when the discovery
+ * cycle failed, because then the TTLs on the individual items will
+ * not be updated and may go stale.
+ */
+void
+ad_disc_done(ad_disc_t ctx)
+{
+ time_t now = time(NULL);
+
+ ctx->expires_not_before = now + MINIMUM_TTL;
+ ctx->expires_not_after = now + MAXIMUM_TTL;
+}
+
/* Discover joined Active Directory domainName */
static ad_item_t *
@@ -1425,12 +1436,13 @@ validate_SiteName(ad_disc_t ctx)
return (NULL);
if (!is_valid(&ctx->site_name) ||
- is_changed(&ctx->site_name, PARAM1, &ctx->domain_controller) ||
+ is_changed(&ctx->site_name, PARAM1, domain_controller_item) ||
ctx->subnets == NULL || ctx->subnets_changed) {
subnets = find_subnets();
ctx->subnets_last_check = time(NULL);
update_required = B_TRUE;
} else if (ctx->subnets_last_check + 60 < time(NULL)) {
+ /* NEEDSWORK magic constant 60 above */
subnets = find_subnets();
ctx->subnets_last_check = time(NULL);
if (cmpsubnets(ctx->subnets, subnets) != 0)
@@ -1471,6 +1483,8 @@ validate_SiteName(ad_disc_t ctx)
forest_name = DN_to_DNS(config_naming_context + len);
update_item(&ctx->forest_name, forest_name,
AD_STATE_AUTO, 0);
+ update_version(&ctx->forest_name, PARAM1,
+ domain_controller_item);
}
}
@@ -1495,6 +1509,8 @@ validate_SiteName(ad_disc_t ctx)
site_name[len] = '\0';
update_item(&ctx->site_name, site_name,
AD_STATE_AUTO, 0);
+ update_version(&ctx->site_name, PARAM1,
+ domain_controller_item);
}
}
@@ -1997,17 +2013,33 @@ ad_disc_unset(ad_disc_t ctx)
int
ad_disc_get_TTL(ad_disc_t ctx)
{
+ time_t expires;
int ttl;
- ttl = MIN_GT_ZERO(ctx->domain_controller.ttl, ctx->global_catalog.ttl);
- ttl = MIN_GT_ZERO(ttl, ctx->site_domain_controller.ttl);
- ttl = MIN_GT_ZERO(ttl, ctx->site_global_catalog.ttl);
+ expires = MIN_GT_ZERO(ctx->domain_controller.expires,
+ ctx->global_catalog.expires);
+ expires = MIN_GT_ZERO(expires, ctx->site_domain_controller.expires);
+ expires = MIN_GT_ZERO(expires, ctx->site_global_catalog.expires);
- if (ttl == -1)
+ if (expires == -1) {
return (-1);
- ttl -= time(NULL);
- if (ttl < 0)
+ }
+
+ if (ctx->expires_not_before != 0 &&
+ expires < ctx->expires_not_before) {
+ expires = ctx->expires_not_before;
+ }
+
+ if (ctx->expires_not_after != 0 &&
+ expires > ctx->expires_not_after) {
+ expires = ctx->expires_not_after;
+ }
+
+ ttl = expires - time(NULL);
+
+ if (ttl < 0) {
return (0);
+ }
return (ttl);
}