1/* referral.c - BDB backend referral handler */ 2/* $OpenLDAP$ */ 3/* This work is part of OpenLDAP Software <http://www.openldap.org/>. 4 * 5 * Copyright 2000-2011 The OpenLDAP Foundation. 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted only as authorized by the OpenLDAP 10 * Public License. 11 * 12 * A copy of this license is available in the file LICENSE in the 13 * top-level directory of the distribution or, alternatively, at 14 * <http://www.OpenLDAP.org/license.html>. 15 */ 16 17#include "portable.h" 18#include <stdio.h> 19#include <ac/string.h> 20 21#include "back-bdb.h" 22 23int 24bdb_referrals( Operation *op, SlapReply *rs ) 25{ 26 struct bdb_info *bdb = (struct bdb_info *) op->o_bd->be_private; 27 Entry *e = NULL; 28 EntryInfo *ei; 29 int rc = LDAP_SUCCESS; 30 31 DB_TXN *rtxn; 32 DB_LOCK lock; 33 34 if( op->o_tag == LDAP_REQ_SEARCH ) { 35 /* let search take care of itself */ 36 return rc; 37 } 38 39 if( get_manageDSAit( op ) ) { 40 /* let op take care of DSA management */ 41 return rc; 42 } 43 44 rc = bdb_reader_get(op, bdb->bi_dbenv, &rtxn); 45 switch(rc) { 46 case 0: 47 break; 48 default: 49 return LDAP_OTHER; 50 } 51 52dn2entry_retry: 53 /* get entry */ 54 rc = bdb_dn2entry( op, rtxn, &op->o_req_ndn, &ei, 1, &lock ); 55 56 /* bdb_dn2entry() may legally leave ei == NULL 57 * if rc != 0 and rc != DB_NOTFOUND 58 */ 59 if ( ei ) { 60 e = ei->bei_e; 61 } 62 63 switch(rc) { 64 case DB_NOTFOUND: 65 case 0: 66 break; 67 case LDAP_BUSY: 68 rs->sr_text = "ldap server busy"; 69 return LDAP_BUSY; 70 case DB_LOCK_DEADLOCK: 71 case DB_LOCK_NOTGRANTED: 72 goto dn2entry_retry; 73 default: 74 Debug( LDAP_DEBUG_TRACE, 75 LDAP_XSTRING(bdb_referrals) 76 ": dn2entry failed: %s (%d)\n", 77 db_strerror(rc), rc, 0 ); 78 rs->sr_text = "internal error"; 79 return LDAP_OTHER; 80 } 81 82 if ( rc == DB_NOTFOUND ) { 83 rc = LDAP_SUCCESS; 84 rs->sr_matched = NULL; 85 if ( e != NULL ) { 86 Debug( LDAP_DEBUG_TRACE, 87 LDAP_XSTRING(bdb_referrals) 88 ": tag=%lu target=\"%s\" matched=\"%s\"\n", 89 (unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val ); 90 91 if( is_entry_referral( e ) ) { 92 BerVarray ref = get_entry_referrals( op, e ); 93 rc = LDAP_OTHER; 94 rs->sr_ref = referral_rewrite( ref, &e->e_name, 95 &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 96 ber_bvarray_free( ref ); 97 if ( rs->sr_ref ) { 98 rs->sr_matched = ber_strdup_x( 99 e->e_name.bv_val, op->o_tmpmemctx ); 100 } 101 } 102 103 bdb_cache_return_entry_r (bdb, e, &lock); 104 e = NULL; 105 } 106 107 if( rs->sr_ref != NULL ) { 108 /* send referrals */ 109 rc = rs->sr_err = LDAP_REFERRAL; 110 send_ldap_result( op, rs ); 111 ber_bvarray_free( rs->sr_ref ); 112 rs->sr_ref = NULL; 113 } else if ( rc != LDAP_SUCCESS ) { 114 rs->sr_text = rs->sr_matched ? "bad referral object" : NULL; 115 } 116 117 if (rs->sr_matched) { 118 op->o_tmpfree( (char *)rs->sr_matched, op->o_tmpmemctx ); 119 rs->sr_matched = NULL; 120 } 121 return rc; 122 } 123 124 if ( is_entry_referral( e ) ) { 125 /* entry is a referral */ 126 BerVarray refs = get_entry_referrals( op, e ); 127 rs->sr_ref = referral_rewrite( 128 refs, &e->e_name, &op->o_req_dn, LDAP_SCOPE_DEFAULT ); 129 130 Debug( LDAP_DEBUG_TRACE, 131 LDAP_XSTRING(bdb_referrals) 132 ": tag=%lu target=\"%s\" matched=\"%s\"\n", 133 (unsigned long)op->o_tag, op->o_req_dn.bv_val, e->e_name.bv_val ); 134 135 rs->sr_matched = e->e_name.bv_val; 136 if( rs->sr_ref != NULL ) { 137 rc = rs->sr_err = LDAP_REFERRAL; 138 send_ldap_result( op, rs ); 139 ber_bvarray_free( rs->sr_ref ); 140 rs->sr_ref = NULL; 141 } else { 142 rc = LDAP_OTHER; 143 rs->sr_text = "bad referral object"; 144 } 145 146 rs->sr_matched = NULL; 147 ber_bvarray_free( refs ); 148 } 149 150 bdb_cache_return_entry_r(bdb, e, &lock); 151 return rc; 152} 153