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