So that callers can extract the location of the referred-to LDAP server, change nsdb_parse_result() to parse an array of referral URIs, if one is returned.
Signed-off-by: Chuck Lever <[email protected]> --- src/libnsdb/administrator.c | 4 +-- src/libnsdb/fileserver.c | 10 ++++--- src/libnsdb/ldap.c | 60 +++++++++++++++++++++++++++++++++++++++++-- src/libnsdb/nsdb-internal.h | 2 + 4 files changed, 65 insertions(+), 11 deletions(-) diff --git a/src/libnsdb/administrator.c b/src/libnsdb/administrator.c index a664fa9..aa4aad3 100644 --- a/src/libnsdb/administrator.c +++ b/src/libnsdb/administrator.c @@ -474,7 +474,7 @@ again: retval = nsdb_parse_reference(ld, message, ldap_err); break; case LDAP_RES_SEARCH_RESULT: - retval = nsdb_parse_result(ld, message, ldap_err); + retval = nsdb_parse_result(ld, message, NULL, ldap_err); break; default: xlog(L_ERROR, "%s: Unrecognized LDAP message type", @@ -1658,7 +1658,7 @@ again: retval = nsdb_parse_reference(ld, message, ldap_err); break; case LDAP_RES_SEARCH_RESULT: - retval = nsdb_parse_result(ld, message, ldap_err); + retval = nsdb_parse_result(ld, message, NULL, ldap_err); break; default: xlog(L_ERROR, "%s: Unrecognized LDAP message type", diff --git a/src/libnsdb/fileserver.c b/src/libnsdb/fileserver.c index cb25f3b..d4519d6 100644 --- a/src/libnsdb/fileserver.c +++ b/src/libnsdb/fileserver.c @@ -443,7 +443,7 @@ nsdb_get_ncedn_s(nsdb_t host, const char *naming_context, char **dn, retval = nsdb_parse_reference(ld, message, ldap_err); break; case LDAP_RES_SEARCH_RESULT: - retval = nsdb_parse_result(ld, message, ldap_err); + retval = nsdb_parse_result(ld, message, NULL, ldap_err); break; default: xlog(L_ERROR, "%s: Unrecognized LDAP message type", @@ -632,7 +632,7 @@ nsdb_get_naming_contexts_s(nsdb_t host, char ***contexts, message, ldap_err); break; case LDAP_RES_SEARCH_RESULT: - retval = nsdb_parse_result(ld, message, ldap_err); + retval = nsdb_parse_result(ld, message, NULL, ldap_err); break; default: xlog(L_ERROR, "%s: Unrecognized LDAP message type", @@ -1091,7 +1091,7 @@ nsdb_resolve_fsn_find_entry_s(LDAP *ld, const char *nce, const char *fsn_uuid, retval = nsdb_parse_reference(ld, message, ldap_err); break; case LDAP_RES_SEARCH_RESULT: - retval = nsdb_parse_result(ld, message, ldap_err); + retval = nsdb_parse_result(ld, message, NULL, ldap_err); break; default: xlog(L_ERROR, "%s: Unrecognized LDAP message type", @@ -1404,7 +1404,7 @@ nsdb_get_fsn_find_entry_s(LDAP *ld, const char *nce, const char *fsn_uuid, retval = nsdb_parse_reference(ld, message, ldap_err); break; case LDAP_RES_SEARCH_RESULT: - retval = nsdb_parse_result(ld, message, ldap_err); + retval = nsdb_parse_result(ld, message, NULL, ldap_err); break; default: xlog(L_ERROR, "%s: Unrecognized LDAP message type", @@ -1663,7 +1663,7 @@ nsdb_list_find_entries_s(LDAP *ld, const char *nce, char ***fsns, retval = nsdb_parse_reference(ld, message, ldap_err); break; case LDAP_RES_SEARCH_RESULT: - retval = nsdb_parse_result(ld, message, ldap_err); + retval = nsdb_parse_result(ld, message, NULL, ldap_err); break; default: xlog(L_ERROR, "%s: Unrecognized LDAP message type", diff --git a/src/libnsdb/ldap.c b/src/libnsdb/ldap.c index f6b430e..0abbdd2 100644 --- a/src/libnsdb/ldap.c +++ b/src/libnsdb/ldap.c @@ -810,18 +810,66 @@ nsdb_parse_reference(LDAP *ld, LDAPMessage *reference, } /** + * Duplicate an array of referral URIs + * + * @param refs an array of NUL-terminated C strings containing LDAP URIs + * @param referrals OUT: pointer to an array of NUL-terminated C strings + * @return a FedFsStatus code + * + * Caller must free "referrals" with nsdb_free_string_array(). + */ +static FedFsStatus +nsdb_copy_referrals_array(char **refs, char ***referrals) +{ + int i, count; + char **tmp; + + for (i = 0; refs[i] != NULL; i++) + xlog(D_GENERAL, "%s: Referral: %s", __func__, refs[i]); + if (referrals == NULL) + return FEDFS_OK; + count = i; + + tmp = calloc(count, sizeof(char *)); + if (tmp == NULL) { + xlog(D_GENERAL, "%s: no memory for array", __func__); + return FEDFS_ERR_SVRFAULT; + } + + for (i = 0; i < count; i++) { + tmp[i] = strdup(refs[i]); + if (tmp[i] == NULL) { + xlog(D_GENERAL, "%s: no memory for string", __func__); + nsdb_free_string_array(tmp); + return FEDFS_ERR_SVRFAULT; + } + } + tmp[i] = NULL; + + *referrals = tmp; + return FEDFS_OK; +} + +/** * Handle an LDAP search result message * * @param ld an initialized LDAP server descriptor * @param result an LDAP_RES_SEARCH_RESULT message + * @param referrals OUT: pointer to an array of NUL-terminated C strings * @param ldap_err OUT: possibly an LDAP error code * @return a FedFsStatus code + * + * If "ldap_err" contains LDAP_REFERRAL, caller must free "referrals" + * with nsdb_free_string_array(). */ FedFsStatus -nsdb_parse_result(LDAP *ld, LDAPMessage *result, unsigned int *ldap_err) +nsdb_parse_result(LDAP *ld, LDAPMessage *result, char ***referrals, + unsigned int *ldap_err) { char *matched_dn = NULL, *error_msg = NULL; int rc, result_code; + char **refs = NULL; + FedFsStatus retval; if (ld == NULL || result == NULL || ldap_err == NULL) { xlog(L_ERROR, "%s: Invalid parameter", __func__); @@ -829,7 +877,7 @@ nsdb_parse_result(LDAP *ld, LDAPMessage *result, unsigned int *ldap_err) } rc = ldap_parse_result(ld, result, &result_code, - &matched_dn, &error_msg, NULL, NULL, 0); + &matched_dn, &error_msg, &refs, NULL, 0); if (rc != LDAP_SUCCESS) { xlog(D_GENERAL, "%s: Failed to parse result: %s", __func__, ldap_err2string(rc)); @@ -857,11 +905,17 @@ nsdb_parse_result(LDAP *ld, LDAPMessage *result, unsigned int *ldap_err) ber_memfree(error_msg); } + retval = FEDFS_OK; + if (refs != NULL) { + retval = nsdb_copy_referrals_array(refs, referrals); + ber_memvfree((void **)refs); + } + if (result_code != LDAP_SUCCESS) { *ldap_err = result_code; return FEDFS_ERR_NSDB_LDAP_VAL; } - return FEDFS_OK; + return retval; } /** diff --git a/src/libnsdb/nsdb-internal.h b/src/libnsdb/nsdb-internal.h index d293dd7..c2283ed 100644 --- a/src/libnsdb/nsdb-internal.h +++ b/src/libnsdb/nsdb-internal.h @@ -102,7 +102,7 @@ FedFsStatus nsdb_delete_attribute_all_s(LDAP *ld, const char *dn, FedFsStatus nsdb_parse_reference(LDAP *ld, LDAPMessage *reference, unsigned int *ldap_err); FedFsStatus nsdb_parse_result(LDAP *ld, LDAPMessage *result, - unsigned int *ldap_err); + char ***referrals, unsigned int *ldap_err); _Bool nsdb_compare_dns(LDAPDN dn1, LDAPDN dn2); _Bool nsdb_compare_dn_string(LDAPDN dn1, const char *dn2_in, unsigned int *ldap_err); _______________________________________________ fedfs-utils-devel mailing list [email protected] https://oss.oracle.com/mailman/listinfo/fedfs-utils-devel
