@@ -142,6 +142,52 @@ nsdb_list_resolve_and_display_fsn(nsdb_t host, const char *nce, const char *fsn_
}
/**
+ * Attempt to follow an LDAP referral to another NSDB
+ *
+ * @param host OUT: pointer to an initialized nsdb_t that may be replaced
+ * @return a FedFsStatus code
+ */
+static FedFsStatus
+nsdb_list_follow_ldap_referral(nsdb_t *host)
+{
+ static unsigned int nest = 0;
+ FedFsStatus retval;
+ nsdb_t old, refer;
+
+ old = *host;
+ if (!nsdb_follow_referrals(old)) {
+ fprintf(stderr, "LDAP referrals for NSDB %s:%u disallowed\n",
+ nsdb_hostname(old), nsdb_port(old));
+ return FEDFS_ERR_NSDB_LDAP_REFERRAL_NOTFOLLOWED;
+ }
+
+ if (nest++ > 10) {
+ fprintf(stderr, "Possible referral loop for NSDB %s:%u\n",
+ nsdb_hostname(old), nsdb_port(old));
+ return FEDFS_ERR_NSDB_LDAP_REFERRAL_NOTFOLLOWED;
+ }
+
+ retval = nsdb_lookup_nsdb_by_uri(nsdb_referred_to(old), &refer);
+ switch (retval) {
+ case FEDFS_OK:
+ break;
+ case FEDFS_ERR_NSDB_PARAMS:
+ fprintf(stderr, "Encountered referral to unrecognized NSDB %s\n",
+ nsdb_referred_to(old));
+ return FEDFS_ERR_NSDB_LDAP_REFERRAL_NOTFOLLOWED;
+ default:
+ fprintf(stderr, "Problem following referral: %s",
+ nsdb_display_fedfsstatus(retval));
+ return retval;
+ }
+
+ nsdb_close_nsdb(old);
+ nsdb_free_nsdb(old);
+ *host = refer;
+ return FEDFS_OK;
+}
+
+/**
* Program entry point
*
* @param argc count of command line arguments
@@ -232,6 +278,7 @@ main(int argc, char **argv)
goto out;
}
+again:
retval = nsdb_open_nsdb(host, NULL, NULL, &ldap_err);
switch (retval) {
case FEDFS_OK:
@@ -280,6 +327,12 @@ main(int argc, char **argv)
fprintf(stderr, "NCE %s does not exist\n", nce);
break;
case FEDFS_ERR_NSDB_LDAP_VAL:
+ if (ldap_err == LDAP_REFERRAL) {
+ retval = nsdb_list_follow_ldap_referral(&host);
+ if (retval != FEDFS_OK)
+ break;
+ goto again;
+ }
fprintf(stderr, "Failed to list FSNs: %s\n",
ldap_err2string(ldap_err));
break;
@@ -190,6 +190,52 @@ nsdb_resolve_fsn_display_fsls(struct fedfs_fsl *fsls)
}
/**
+ * Attempt to follow an LDAP referral to another NSDB
+ *
+ * @param host OUT: pointer to an initialized nsdb_t that may be replaced
+ * @return a FedFsStatus code
+ */
+static FedFsStatus
+nsdb_resolve_fsn_follow_ldap_referral(nsdb_t *host)
+{
+ static unsigned int nest = 0;
+ FedFsStatus retval;
+ nsdb_t old, refer;
+
+ old = *host;
+ if (!nsdb_follow_referrals(old)) {
+ fprintf(stderr, "LDAP referrals for NSDB %s:%u disallowed\n",
+ nsdb_hostname(old), nsdb_port(old));
+ return FEDFS_ERR_NSDB_LDAP_REFERRAL_NOTFOLLOWED;
+ }
+
+ if (nest++ > 10) {
+ fprintf(stderr, "Possible referral loop for NSDB %s:%u\n",
+ nsdb_hostname(old), nsdb_port(old));
+ return FEDFS_ERR_NSDB_LDAP_REFERRAL_NOTFOLLOWED;
+ }
+
+ retval = nsdb_lookup_nsdb_by_uri(nsdb_referred_to(old), &refer);
+ switch (retval) {
+ case FEDFS_OK:
+ break;
+ case FEDFS_ERR_NSDB_PARAMS:
+ fprintf(stderr, "Encountered referral to unrecognized NSDB %s\n",
+ nsdb_referred_to(old));
+ return FEDFS_ERR_NSDB_LDAP_REFERRAL_NOTFOLLOWED;
+ default:
+ fprintf(stderr, "Problem following referral: %s\n",
+ nsdb_display_fedfsstatus(retval));
+ return retval;
+ }
+
+ nsdb_close_nsdb(old);
+ nsdb_free_nsdb(old);
+ *host = refer;
+ return FEDFS_OK;
+}
+
+/**
* Program entry point
*
* @param argc count of command line arguments
@@ -292,6 +338,7 @@ main(int argc, char **argv)
goto out;
}
+again:
retval = nsdb_open_nsdb(host, NULL, NULL, &ldap_err);
switch (retval) {
case FEDFS_OK:
@@ -332,6 +379,12 @@ main(int argc, char **argv)
fprintf(stderr, "Failed to find FSN %s\n", fsn_uuid);
goto out_close;
case FEDFS_ERR_NSDB_LDAP_VAL:
+ if (ldap_err == LDAP_REFERRAL) {
+ retval = nsdb_resolve_fsn_follow_ldap_referral(&host);
+ if (retval != FEDFS_OK)
+ goto out_close;
+ goto again;
+ }
fprintf(stderr, "NSDB LDAP error: %s\n",
ldap_err2string(ldap_err));
goto out_close;
@@ -366,6 +419,12 @@ main(int argc, char **argv)
fprintf(stderr, "Failed to find FSN %s\n", fsn_uuid);
break;
case FEDFS_ERR_NSDB_LDAP_VAL:
+ if (ldap_err == LDAP_REFERRAL) {
+ retval = nsdb_resolve_fsn_follow_ldap_referral(&host);
+ if (retval != FEDFS_OK)
+ break;
+ goto again;
+ }
fprintf(stderr, "NSDB LDAP error: %s\n",
ldap_err2string(ldap_err));
break;
NSDB tools that perform fileserver queries are allowed to follow LDAP referrals if the NSDB's "follow referrals" flag is on. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> --- src/nsdbc/nsdb-list.c | 53 ++++++++++++++++++++++++++++++++++++++ src/nsdbc/nsdb-resolve-fsn.c | 59 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 0 deletions(-)