summaryrefslogtreecommitdiffstats
path: root/ldap/servers/slapd/referral.c
diff options
context:
space:
mode:
Diffstat (limited to 'ldap/servers/slapd/referral.c')
-rw-r--r--ldap/servers/slapd/referral.c685
1 files changed, 0 insertions, 685 deletions
diff --git a/ldap/servers/slapd/referral.c b/ldap/servers/slapd/referral.c
index cede05d6..429f6ef4 100644
--- a/ldap/servers/slapd/referral.c
+++ b/ldap/servers/slapd/referral.c
@@ -12,36 +12,12 @@
#include "slap.h"
/* Forward Decls */
-static int ref_array_del(Ref **target, int write, int read);
-static int ref_array_add(const char *dn, struct berval *referral, int write, int read);
-static Ref **ref_array_find(const char *dn);
-static int ref_array_mod(Ref **target, struct berval *referral, int write, int read);
-static void strcat_escaped( char *s1, char *s2 );
static void adjust_referral_basedn( char **urlp, const Slapi_DN *refcontainerdn, char *opdn_norm, int isreference );
static int dn_is_below( const char *dn_norm, const char *ancestor_norm );
static Ref_Array *g_get_global_referrals(void);
static void ref_free (Ref **goner);
static Ref_Array global_referrals;
-struct refCb {
- int type;
- char *cbName;
- void (*cb)(Slapi_PBlock *, void *);
- void *cbData;
- struct refCb *next;
-};
-
-struct refCb *refCbList=NULL;
-
-int
-ref_register_callback(int type, char *description,
- void (*cb)(Slapi_PBlock *, void *), void *cbData);
-int
-ref_remove_callback(char *description);
-static
-int ref_call_cbs(int type, Slapi_PBlock *pb);
-
-
#define SLAPD_DEFAULT_REFARRAY_SIZE 10
/*
@@ -76,438 +52,6 @@ g_get_global_referrals(void)
return( &global_referrals );
}
-/*
- * Function: ref_array_del
- *
- * Returns: 0 good, -1 bad.
- *
- * Description: finds "dn" in the list and unsets the read or write
- * flag(s). If both are then zero, then it frees up that entry.
- * target should point to the referral that is to be deleted.
- * Note: This does NOT lock global_referrals.ra_rwlock.
- *
- * Author: RJP
- */
-static int
-ref_array_del(Ref **target, int write, int read)
-{
- Ref **lastref = NULL;
- Ref_Array *grefs = NULL;
-
- grefs = g_get_global_referrals();
-
- if (target == NULL) {
- return(-1);
- }
-
- /*Unset either or both flags*/
- if (write) {
- (*target)->ref_writes = 0;
- }
- if (read) {
- (*target)->ref_reads = 0;
- grefs->ra_readcount--;
- }
-
- /*If there is a flag set, then don't delete the referral*/
- if (((*target)->ref_writes == 1) || (*target)->ref_reads == 1){
- return(0);
- }
-
- /* Free up target */
- ref_free(target);
-
-
- /*
- * Okay, we want to maintain our array's compactedness,
- * so we take the referral that's in the last position, and
- * put that in target's place. If they are one and the
- * same, then no problem. This shouldn't ever seg fault.
- * (famous last words).
- */
- lastref = &grefs->ra_refs[grefs->ra_nextindex - 1];
-
- *target = *lastref;
-
- grefs->ra_refs[grefs->ra_nextindex - 1] = NULL;
-
- /*reset the next_index*/
- grefs->ra_nextindex--;
-
- return(0);
-
-}
-
-
-/*
- * Function: ref_array_replace
- *
- * Returns: 0 good, -1 bad.
- *
- * Description: Locks the mutex associated with global_referrals,
- * adds that referral and "dn" to the global_referrals if it
- * doesn't exist already. If it does exist, and the new
- * referral is different, then the old one gets clobbered.
- * If referral is NULL, then it deletes the referral
- * associated with dn.
- * Note: This locks global_referrals.ra_rwlock.
- *
- * Author: RJP
- */
-int
-ref_array_replace(const char *dn, struct berval *referral, int write, int read)
-{
- Ref **target = NULL;
- int err;
- Ref_Array *grefs = NULL;
-
- grefs = g_get_global_referrals();
-
- if (dn == NULL) {
- return(0);
- }
-
- GR_LOCK_WRITE();
-
- /* Find the referral, if any. */
- target = ref_array_find(dn);
-
- /* If datasource is NULL, then delete target. */
- if ( referral == NULL ){
-
- /* If target is null, then there is nothing to do. */
- if (target == NULL) {
- GR_UNLOCK_WRITE();
- return(0);
- }
- err = ref_array_del(target, write, read);
-
- GR_UNLOCK_WRITE();
-
- return(err);
- }
-
- /* If target is NULL, then add target to the end. */
- if ( target == NULL) {
- err = ref_array_add(dn, referral, write, read);
- GR_UNLOCK_WRITE();
- return(err);
- }
-
- /* Else, the referral already exists and we should modify it. */
- err = ref_array_mod(target, referral, write, read);
- GR_UNLOCK_WRITE();
- return(err);
-}
-
-
-/*
- * Function: ref_array_mod
- *
- * Returns: 0 good, -1 bad.
- *
- * Description: modifies the existing referral.
- * First it checks the host:port in datasource
- * against the host:port in the existing referral.
- * If they don't match, then it replaces the referral
- *
- * Note: This does NOT lock global_referrals.ra_rwlock.
- *
- * Author: RJP
- */
-static int
-ref_array_mod(Ref **target, struct berval *referral, int write, int read)
-{
- Ref_Array *grefs = NULL;
-
- grefs = g_get_global_referrals();
-
- if (referral == NULL || target == NULL) {
- return(0);
- }
-
- /* Actually, instead of comparing them, we might as well just swap */
- ber_bvfree( (*target)->ref_referral );
-
- (*target)->ref_referral = referral ;
-
- /*
- * We have to update the read/write flags which
- * refer reads and writes, respectively
- */
- if (write) {
- (*target)->ref_writes = 1;
- }
- if (read) {
- /*Don't update the readcount unnecessarily*/
- if ((*target)->ref_reads == 0) {
- grefs->ra_readcount++;
- }
-
- (*target)->ref_reads = 1;
- }
-
- return(0);
-
-}
-
-
-
-/*
- * Function: ref_array_add
- *
- * Returns: 0 good, -1 bad.
- *
- * Description: adds that referral and "dn" to the global_referrals
- * Note: This does NOT lock global_referrals.ra_rwlock.
- *
- * Author: RJP
- */
-static int
-ref_array_add(const char *dn, struct berval *referral, int write, int read)
-{
- Ref **target = NULL;
- Ref_Array *grefs = NULL;
-
- grefs = g_get_global_referrals();
-
- if (dn == NULL || referral == NULL) {
- return(0);
- }
-
-
- /* We may have to realloc if we are about to index an out-of-range slot */
- if (grefs->ra_nextindex >= grefs->ra_size){
- /* reset the size */
- grefs->ra_size += 10;
-
- /* reallocate */
- grefs->ra_refs = (Ref **) slapi_ch_realloc((char *) grefs->ra_refs,
- grefs->ra_size * (sizeof(Ref *)));
- }
-
- /* Tack the new referral to the end. */
- target = &(grefs->ra_refs[grefs->ra_nextindex]);
-
- /* Malloc and fill the fields of the new referral */
- (*target) = (Ref *) slapi_ch_malloc( sizeof(Ref));
- (*target)->ref_dn = slapi_dn_normalize_case(slapi_ch_strdup(dn));
- (*target)->ref_referral = referral;
-
- /* Update the next available index */
- grefs->ra_nextindex++;
-
- (*target)->ref_writes = 0;
- (*target)->ref_reads = 0;
-
- /*
- * We have to update the read/write flags which
- * refer reads and writes, respectively
- */
- if (write) {
- (*target)->ref_writes = 1;
- }
- if (read) {
- (*target)->ref_reads = 1;
- grefs->ra_readcount++;
- }
-
- return(0);
-}
-
-/*
- * Function: ref_array_find
- *
- * Returns: a pointer to a pointer to a Ref, or NULL
- *
- * Description: Traverses the array of referrals, until
- * it either finds a match or gets to the end.
- * Note: This DOES NOT lock global_referrals.ra_rwlock.
- *
- * Author: RJP
- *
- */
-static Ref **
-ref_array_find(const char *dn)
-{
- int walker;
- Ref_Array *grefs = NULL;
-
- grefs = g_get_global_referrals();
-
- if (dn == NULL) {
- return(NULL);
- }
-
- /* Walk down the array, testing for a match */
- for (walker = 0; walker < grefs->ra_nextindex; walker++){
-
- if (strcasecmp (grefs->ra_refs[walker]->ref_dn, dn) == 0) {
- return(&grefs->ra_refs[walker]);
- }
- }
- return(NULL);
-}
-
-/*
- * Function: send_read_referrals
- *
- * Returns: A copy of global_referrals
- *
- * Description: Given a dn, this function sends all the copyingfrom
- * referrals beneath "dn" that are within "scope."
- * returns a copy of the global_referrals array
- * that it makes for use later. This is to avoid
- * any race conditions of ORC ending in the middle
- * of the search and scewing things up. NULL is returned
- * if there are no copyingfrom referrals in there.
- *
- * If "dn" does not exactly match a referral's dn, we append
- * "/referralDN" to the referral itself, i.e, we send a
- * referral like this:
- * ldap://host:port/dn
- * instead of one like this:
- * ldap://host:port
- * We do not append the referral DN to the referrals present
- * in the copy of the global_referrals array that we return.
- *
- * Author: RJP
- *
- */
-Ref_Array *
-send_read_referrals(Slapi_PBlock *pb, int scope, char *dn,
- struct berval ***urls)
-{
- int walker, urllen, dnlen;
- struct berval *refs[2], refcopy;
- char *urlcopy;
- Ref_Array *grefs = NULL;
- Ref_Array *the_copy = NULL;
- int found_one = 0;
-
- /* Get a pointer to global_referrals */
- grefs = g_get_global_referrals();
-
- GR_LOCK_READ();
-
- /*If no copyingfroms, just return*/
- if (grefs->ra_readcount <= 0) {
- GR_UNLOCK_READ();
- return(NULL);
- }
-
- refs[1] = NULL;
-
- /*
- * Walk through the refs in the_copy and send any referrals
- * that are below "dn". Take "scope" into account as well.
- */
- for (walker = 0; walker < grefs->ra_nextindex; walker++) {
- if ( grefs->ra_refs[walker]->ref_reads &&
- (( scope == LDAP_SCOPE_BASE &&
- strcasecmp(grefs->ra_refs[walker]->ref_dn, dn) == 0 ) ||
- ( scope == LDAP_SCOPE_ONELEVEL &&
- slapi_dn_isparent(dn, grefs->ra_refs[walker]->ref_dn)) ||
- ( scope == LDAP_SCOPE_SUBTREE &&
- slapi_dn_issuffix(grefs->ra_refs[walker]->ref_dn, dn)))) {
- found_one = 1;
-
- /*
- * Make an array of 1 referral. If the referral DN is below "dn",
- * i.e, it is not the same as "dn", we make a copy and append a
- * URL-escaped version of the referral DN to the original referral.
- */
- if ( scope == LDAP_SCOPE_BASE ||
- strcasecmp( grefs->ra_refs[walker]->ref_dn, dn ) == 0 ) {
- refs[0] = grefs->ra_refs[walker]->ref_referral;
- urlcopy = NULL;
- } else {
- urllen = strlen( grefs->ra_refs[walker]->ref_referral->bv_val );
- dnlen = strlen( grefs->ra_refs[walker]->ref_dn );
- /* space for worst-case expansion due to escape plus room for '/' */
- urlcopy = slapi_ch_malloc( urllen + 3 * dnlen + 2 );
-
- strcpy( urlcopy, grefs->ra_refs[walker]->ref_referral->bv_val );
- urlcopy[urllen] = '/';
- ++urllen;
- urlcopy[urllen] = '\0';
- strcat_escaped( urlcopy + urllen, grefs->ra_refs[walker]->ref_dn );
-
- refcopy.bv_val = urlcopy;
- refcopy.bv_len = strlen( urlcopy );
- refs[0] = &refcopy;
- }
-
- send_ldap_referral( pb, NULL, refs, urls );
- slapi_pblock_set( pb, SLAPI_SEARCH_REFERRALS, *urls );
-
- if ( urlcopy != NULL ) {
- slapi_ch_free( (void **)&urlcopy );
- }
- }
- }
-
- /* Make a copy of global_referrals to avoid any race conditions */
- if (found_one) {
- the_copy = ref_array_dup();
- }
-
- GR_UNLOCK_READ();
-
- /*
- * After we sent all the referrals, return the copy of
- * global_referrals for use later. If there were none found, return
- * NULL
- */
- return(the_copy);
-}
-
-/*
- * Function: ref_array_dup
- *
- * Returns: a copy of global_referrals
- *
- * Description: Makes a copy of global_referrals and returns that puppy
- * Note: Does not lock global_referrals.
- *
- * Author: RJP
- *
- */
-Ref_Array *
-ref_array_dup(void)
-{
- Ref_Array *grefs = NULL;
- Ref_Array *the_copy = NULL;
- int walker;
-
- /*Allocate the first structure*/
- the_copy = (Ref_Array *) slapi_ch_calloc(1, sizeof(Ref_Array));
-
- /* Don't bother with the lock, it's only a local copy. */
- the_copy->ra_rwlock = NULL;
-
- /*Grab a reference to the global_referrals*/
- grefs = g_get_global_referrals();
-
- /* Initialize all the fields of the copy. */
- the_copy->ra_size = grefs->ra_size;
- the_copy->ra_nextindex = grefs->ra_nextindex;
- the_copy->ra_readcount = grefs->ra_readcount;
- the_copy->ra_refs = (Ref **) slapi_ch_calloc(the_copy->ra_size, sizeof( Ref * ));
-
- /*Walk down grefs, copying each Ref struct */
- for (walker = 0; walker < grefs->ra_nextindex; walker++) {
- the_copy->ra_refs[walker] = (Ref *)slapi_ch_calloc(1, sizeof(Ref));
- the_copy->ra_refs[walker]->ref_dn = slapi_ch_strdup(grefs->ra_refs[walker]->ref_dn);
- the_copy->ra_refs[walker]->ref_referral = slapi_ch_bvdup(grefs->ra_refs[walker]->ref_referral);
- the_copy->ra_refs[walker]->ref_reads = grefs->ra_refs[walker]->ref_reads;
- the_copy->ra_refs[walker]->ref_writes = grefs->ra_refs[walker]->ref_writes;
- }
-
- return(the_copy);
-
-}
-
/*
* Function: ref_free
@@ -527,39 +71,6 @@ ref_free (Ref **goner)
slapi_ch_free((void**) goner);
}
-/*
- * Function: ref_array_dup_free
- *
- * Returns: nothingness
- *
- * Description: takes a Ref_Array dup and frees that puppy
- *
- * Author: RJP
- *
- */
-void
-ref_array_dup_free(Ref_Array *the_copy)
-{
- int walker;
-
- if (the_copy == NULL) {
- return;
- }
-
- /* Walk down the array, deleting each referral */
- for (walker = 0; walker < the_copy->ra_nextindex; walker++)
- {
- ref_free (&the_copy->ra_refs[walker]);
- }
-
- /* free the array of pointers */
- slapi_ch_free((void **) &the_copy->ra_refs);
- slapi_ch_free((void **) &the_copy);
-
- return;
-}
-
-
/*
* Function: referrals_free
@@ -595,125 +106,6 @@ referrals_free (void)
}
/*
- * Function: ref_array_moddn
- *
- * Returns: 0 good, -1 bad.
- *
- * Description: modifies the existing referral's dn.
- * First it locks global_referrals.ra_rwlock.
- * Then it clobbers the existing dn.
- * Then it replaces it with a new dn constructed
- * from newrdn.
- * Note: This locks global_referrals.ra_rwlock.
- *
- * Author: RJP
- */
-void
-ref_array_moddn(const char *dn, char *newrdn, Slapi_PBlock *pb)
-{
- char *pdn = NULL;
- char *newdn = NULL;
- Ref **target = NULL;
- Ref_Array *grefs = NULL;
-
- grefs = g_get_global_referrals();
-
- if (dn == NULL) {
- return;
- }
-
- GR_LOCK_WRITE();
-
- /* Find the referral. */
- target = ref_array_find(dn);
-
- /*
- * If we can't find it, then we're done. This is okay, because this
- * is the only check that is made to see if the entry has a
- * copiedfrom in it.
- */
- if (target == NULL) {
- GR_UNLOCK_WRITE();
- return;
- }
- /* construct the new dn */
- if ( (pdn = slapi_dn_beparent( pb, dn )) != NULL ) {
- /* parent + rdn + separator(s) + null */
- newdn = (char *) slapi_ch_malloc( strlen( pdn ) + strlen( newrdn ) + 3 );
- strcpy( newdn, newrdn );
- strcat( newdn, ", " );
- strcat( newdn, pdn );
- } else {
- newdn = (char *) slapi_ch_strdup( newrdn );
- }
- slapi_ch_free((void **) &pdn );
- (void) slapi_dn_normalize_case( newdn );
-
-
- /* We have found the referral. blow away the dn*/
- slapi_ch_free((void**) &((*target)->ref_dn));
-
- /* stick in the new one. */
- (*target)->ref_dn = newdn;
-
- GR_UNLOCK_WRITE();
-
- return;
-}
-
-
-/*
- * HREF_CHAR_ACCEPTABLE was copied from libldap/tmplout.c
- */
-/* Note: an identical function is in ../plugins/replication/replutil.c */
-#define HREF_CHAR_ACCEPTABLE( c ) (( c >= '-' && c <= '9' ) || \
- ( c >= '@' && c <= 'Z' ) || \
- ( c == '_' ) || \
- ( c >= 'a' && c <= 'z' ))
-
-/*
- * Function: strcat_escaped
- *
- * Returns: nothing
- *
- * Description: Appends string s2 to s1, URL-escaping (%HH) unsafe
- * characters in s2 as appropriate. This function was
- * copied from libldap/tmplout.c.
- *
- * Author: MCS
- */
-/*
- * append s2 to s1, URL-escaping (%HH) unsafe characters
- */
-/* Note: an identical function is in ../plugins/replication/replutil.c */
-static void
-strcat_escaped( char *s1, char *s2 )
-{
- char *p, *q;
- char *hexdig = "0123456789ABCDEF";
-
- p = s1 + strlen( s1 );
- for ( q = s2; *q != '\0'; ++q ) {
- if ( HREF_CHAR_ACCEPTABLE( *q )) {
- *p++ = *q;
- } else {
- *p++ = '%';
- *p++ = hexdig[ 0x0F & ((*(unsigned char*)q) >> 4) ];
- *p++ = hexdig[ 0x0F & *q ];
- }
- }
-
- *p = '\0';
-}
-
-void
-update_global_referrals(Slapi_PBlock *pb)
-{
- ref_call_cbs(0,pb);
- return;
-}
-
-/*
* ref_adjust() -- adjust referrals based on operation-specific data.
* The general idea is for us (the server) to be smart so LDAP clients
* can be as dumb as possible.
@@ -1124,80 +516,3 @@ get_data_source(Slapi_PBlock *pb, const Slapi_DN *sdn, int orc, void *cfrp)
return(bvp);
}
-
-
-int
-ref_register_callback(int type, char *description,
- void (*cb)(Slapi_PBlock *, void *), void *cbData)
-{
- struct refCb *cbPtr;
- struct refCb *newCb;
-
- if(NULL == (newCb =
- (struct refCb *)slapi_ch_calloc(1,sizeof(struct refCb)))) {
- /* out of memory? */
- return(-1);
- }
- newCb->type = type;
- newCb->next = NULL;
- newCb->cb = cb;
- newCb->cbData = cbData;
- newCb->cbName = slapi_ch_strdup(description);
-
- if(NULL == refCbList) {
- refCbList = newCb;
- return(0);
- }
- cbPtr = refCbList;
- while(NULL != cbPtr->next) cbPtr = cbPtr->next;
- cbPtr->next=newCb;
-
- return(0);
-}
-
-int
-ref_remove_callback(char *description)
-{
- struct refCb *cbPtr = refCbList;
- struct refCb *cbPrev = refCbList;
-
- if((NULL == description) || (NULL == cbPtr))
- return(-1);
-
- while(cbPtr) {
- if(!strcmp(description,cbPtr->cbName)) {
- if(cbPrev == refCbList) {
- refCbList = cbPtr->next;
- } else {
- cbPrev->next = cbPtr->next;
- }
- slapi_ch_free((void **)&cbPtr->cbName);
- /* we don't know how the cbData was allocated...we won't attempt
- to free it */
- slapi_ch_free((void **)&cbPtr);
- break;
- }
- cbPrev = cbPtr;
- cbPtr = cbPtr->next;
- }
-
- return(0);
-}
-
-static
-int ref_call_cbs(int type, Slapi_PBlock *pb)
-{
- struct refCb *cbPtr = refCbList;
-
- if(NULL == cbPtr) {
- return(0);
- }
-
- while(cbPtr) {
- (*cbPtr->cb)(pb, cbPtr->cbData);
- cbPtr = cbPtr->next;
- }
-
- return(0);
-}
-