Home | History | Annotate | Line # | Download | only in overlays
retcode.c revision 1.1.1.3.24.1
      1  1.1.1.3.24.1    tls /*	$NetBSD: retcode.c,v 1.1.1.3.24.1 2014/08/10 07:09:51 tls Exp $	*/
      2       1.1.1.2  lukem 
      3           1.1  lukem /* retcode.c - customizable response for client testing purposes */
      4  1.1.1.3.24.1    tls /* $OpenLDAP$ */
      5           1.1  lukem /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6           1.1  lukem  *
      7  1.1.1.3.24.1    tls  * Copyright 2005-2014 The OpenLDAP Foundation.
      8           1.1  lukem  * Portions Copyright 2005 Pierangelo Masarati <ando (at) sys-net.it>
      9           1.1  lukem  * All rights reserved.
     10           1.1  lukem  *
     11           1.1  lukem  * Redistribution and use in source and binary forms, with or without
     12           1.1  lukem  * modification, are permitted only as authorized by the OpenLDAP
     13           1.1  lukem  * Public License.
     14           1.1  lukem  *
     15           1.1  lukem  * A copy of this license is available in the file LICENSE in the
     16           1.1  lukem  * top-level directory of the distribution or, alternatively, at
     17           1.1  lukem  * <http://www.OpenLDAP.org/license.html>.
     18           1.1  lukem  */
     19           1.1  lukem /* ACKNOWLEDGEMENTS:
     20           1.1  lukem  * This work was initially developed by Pierangelo Masarati for inclusion
     21           1.1  lukem  * in OpenLDAP Software.
     22           1.1  lukem  */
     23           1.1  lukem 
     24           1.1  lukem #include "portable.h"
     25           1.1  lukem 
     26           1.1  lukem #ifdef SLAPD_OVER_RETCODE
     27           1.1  lukem 
     28           1.1  lukem #include <stdio.h>
     29           1.1  lukem 
     30           1.1  lukem #include <ac/unistd.h>
     31           1.1  lukem #include <ac/string.h>
     32           1.1  lukem #include <ac/ctype.h>
     33           1.1  lukem #include <ac/socket.h>
     34           1.1  lukem 
     35           1.1  lukem #include "slap.h"
     36           1.1  lukem #include "config.h"
     37           1.1  lukem #include "lutil.h"
     38           1.1  lukem #include "ldif.h"
     39           1.1  lukem 
     40           1.1  lukem static slap_overinst		retcode;
     41           1.1  lukem 
     42           1.1  lukem static AttributeDescription	*ad_errCode;
     43           1.1  lukem static AttributeDescription	*ad_errText;
     44           1.1  lukem static AttributeDescription	*ad_errOp;
     45           1.1  lukem static AttributeDescription	*ad_errSleepTime;
     46           1.1  lukem static AttributeDescription	*ad_errMatchedDN;
     47           1.1  lukem static AttributeDescription	*ad_errUnsolicitedOID;
     48           1.1  lukem static AttributeDescription	*ad_errUnsolicitedData;
     49           1.1  lukem static AttributeDescription	*ad_errDisconnect;
     50           1.1  lukem 
     51           1.1  lukem static ObjectClass		*oc_errAbsObject;
     52           1.1  lukem static ObjectClass		*oc_errObject;
     53           1.1  lukem static ObjectClass		*oc_errAuxObject;
     54           1.1  lukem 
     55           1.1  lukem typedef enum retcode_op_e {
     56           1.1  lukem 	SN_DG_OP_NONE		= 0x0000,
     57           1.1  lukem 	SN_DG_OP_ADD		= 0x0001,
     58           1.1  lukem 	SN_DG_OP_BIND		= 0x0002,
     59           1.1  lukem 	SN_DG_OP_COMPARE	= 0x0004,
     60           1.1  lukem 	SN_DG_OP_DELETE		= 0x0008,
     61           1.1  lukem 	SN_DG_OP_MODIFY		= 0x0010,
     62           1.1  lukem 	SN_DG_OP_RENAME		= 0x0020,
     63           1.1  lukem 	SN_DG_OP_SEARCH		= 0x0040,
     64           1.1  lukem 	SN_DG_EXTENDED		= 0x0080,
     65           1.1  lukem 	SN_DG_OP_AUTH		= SN_DG_OP_BIND,
     66           1.1  lukem 	SN_DG_OP_READ		= (SN_DG_OP_COMPARE|SN_DG_OP_SEARCH),
     67           1.1  lukem 	SN_DG_OP_WRITE		= (SN_DG_OP_ADD|SN_DG_OP_DELETE|SN_DG_OP_MODIFY|SN_DG_OP_RENAME),
     68           1.1  lukem 	SN_DG_OP_ALL		= (SN_DG_OP_AUTH|SN_DG_OP_READ|SN_DG_OP_WRITE|SN_DG_EXTENDED)
     69           1.1  lukem } retcode_op_e;
     70           1.1  lukem 
     71           1.1  lukem typedef struct retcode_item_t {
     72       1.1.1.2  lukem 	struct berval		rdi_line;
     73           1.1  lukem 	struct berval		rdi_dn;
     74           1.1  lukem 	struct berval		rdi_ndn;
     75           1.1  lukem 	struct berval		rdi_text;
     76           1.1  lukem 	struct berval		rdi_matched;
     77           1.1  lukem 	int			rdi_err;
     78           1.1  lukem 	BerVarray		rdi_ref;
     79           1.1  lukem 	int			rdi_sleeptime;
     80           1.1  lukem 	Entry			rdi_e;
     81           1.1  lukem 	slap_mask_t		rdi_mask;
     82           1.1  lukem 	struct berval		rdi_unsolicited_oid;
     83           1.1  lukem 	struct berval		rdi_unsolicited_data;
     84           1.1  lukem 
     85           1.1  lukem 	unsigned		rdi_flags;
     86           1.1  lukem #define	RDI_PRE_DISCONNECT	(0x1U)
     87           1.1  lukem #define	RDI_POST_DISCONNECT	(0x2U)
     88           1.1  lukem 
     89           1.1  lukem 	struct retcode_item_t	*rdi_next;
     90           1.1  lukem } retcode_item_t;
     91           1.1  lukem 
     92           1.1  lukem typedef struct retcode_t {
     93           1.1  lukem 	struct berval		rd_pdn;
     94           1.1  lukem 	struct berval		rd_npdn;
     95           1.1  lukem 
     96           1.1  lukem 	int			rd_sleep;
     97           1.1  lukem 
     98           1.1  lukem 	retcode_item_t		*rd_item;
     99           1.1  lukem 
    100       1.1.1.2  lukem 	int			rd_indir;
    101           1.1  lukem #define	RETCODE_FINDIR		0x01
    102       1.1.1.2  lukem #define	RETCODE_INDIR( rd )	( (rd)->rd_indir )
    103           1.1  lukem } retcode_t;
    104           1.1  lukem 
    105           1.1  lukem static int
    106           1.1  lukem retcode_entry_response( Operation *op, SlapReply *rs, BackendInfo *bi, Entry *e );
    107           1.1  lukem 
    108           1.1  lukem static unsigned int
    109           1.1  lukem retcode_sleep( int s )
    110           1.1  lukem {
    111           1.1  lukem 	unsigned int r = 0;
    112           1.1  lukem 
    113           1.1  lukem 	/* sleep as required */
    114           1.1  lukem 	if ( s < 0 ) {
    115           1.1  lukem #if 0	/* use high-order bits for better randomness (Numerical Recipes in "C") */
    116           1.1  lukem 		r = rand() % (-s);
    117           1.1  lukem #endif
    118           1.1  lukem 		r = ((double)(-s))*rand()/(RAND_MAX + 1.0);
    119           1.1  lukem 	} else if ( s > 0 ) {
    120           1.1  lukem 		r = (unsigned int)s;
    121           1.1  lukem 	}
    122           1.1  lukem 	if ( r ) {
    123           1.1  lukem 		sleep( r );
    124           1.1  lukem 	}
    125           1.1  lukem 
    126           1.1  lukem 	return r;
    127           1.1  lukem }
    128           1.1  lukem 
    129           1.1  lukem static int
    130           1.1  lukem retcode_cleanup_cb( Operation *op, SlapReply *rs )
    131           1.1  lukem {
    132           1.1  lukem 	rs->sr_matched = NULL;
    133           1.1  lukem 	rs->sr_text = NULL;
    134           1.1  lukem 
    135           1.1  lukem 	if ( rs->sr_ref != NULL ) {
    136           1.1  lukem 		ber_bvarray_free( rs->sr_ref );
    137           1.1  lukem 		rs->sr_ref = NULL;
    138           1.1  lukem 	}
    139           1.1  lukem 
    140           1.1  lukem 	ch_free( op->o_callback );
    141           1.1  lukem 	op->o_callback = NULL;
    142           1.1  lukem 
    143           1.1  lukem 	return SLAP_CB_CONTINUE;
    144           1.1  lukem }
    145           1.1  lukem 
    146           1.1  lukem static int
    147           1.1  lukem retcode_send_onelevel( Operation *op, SlapReply *rs )
    148           1.1  lukem {
    149           1.1  lukem 	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
    150           1.1  lukem 	retcode_t	*rd = (retcode_t *)on->on_bi.bi_private;
    151           1.1  lukem 
    152           1.1  lukem 	retcode_item_t	*rdi;
    153           1.1  lukem 
    154           1.1  lukem 	for ( rdi = rd->rd_item; rdi != NULL; rdi = rdi->rdi_next ) {
    155           1.1  lukem 		if ( op->o_abandon ) {
    156           1.1  lukem 			return rs->sr_err = SLAPD_ABANDON;
    157           1.1  lukem 		}
    158           1.1  lukem 
    159           1.1  lukem 		rs->sr_err = test_filter( op, &rdi->rdi_e, op->ors_filter );
    160           1.1  lukem 		if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
    161           1.1  lukem 			/* safe default */
    162           1.1  lukem 			rs->sr_attrs = op->ors_attrs;
    163           1.1  lukem 			rs->sr_operational_attrs = NULL;
    164           1.1  lukem 			rs->sr_ctrls = NULL;
    165           1.1  lukem 			rs->sr_flags = 0;
    166           1.1  lukem 			rs->sr_err = LDAP_SUCCESS;
    167           1.1  lukem 			rs->sr_entry = &rdi->rdi_e;
    168           1.1  lukem 
    169           1.1  lukem 			rs->sr_err = send_search_entry( op, rs );
    170  1.1.1.3.24.1    tls 			rs->sr_flags = 0;
    171           1.1  lukem 			rs->sr_entry = NULL;
    172  1.1.1.3.24.1    tls 			rs->sr_attrs = NULL;
    173           1.1  lukem 
    174           1.1  lukem 			switch ( rs->sr_err ) {
    175           1.1  lukem 			case LDAP_UNAVAILABLE:	/* connection closed */
    176           1.1  lukem 				rs->sr_err = LDAP_OTHER;
    177           1.1  lukem 				/* fallthru */
    178           1.1  lukem 			case LDAP_SIZELIMIT_EXCEEDED:
    179           1.1  lukem 				goto done;
    180           1.1  lukem 			}
    181           1.1  lukem 		}
    182           1.1  lukem 		rs->sr_err = LDAP_SUCCESS;
    183           1.1  lukem 	}
    184           1.1  lukem 
    185           1.1  lukem done:;
    186           1.1  lukem 
    187           1.1  lukem 	send_ldap_result( op, rs );
    188           1.1  lukem 
    189           1.1  lukem 	return rs->sr_err;
    190           1.1  lukem }
    191           1.1  lukem 
    192           1.1  lukem static int
    193           1.1  lukem retcode_op_add( Operation *op, SlapReply *rs )
    194           1.1  lukem {
    195           1.1  lukem 	return retcode_entry_response( op, rs, NULL, op->ora_e );
    196           1.1  lukem }
    197           1.1  lukem 
    198           1.1  lukem typedef struct retcode_cb_t {
    199           1.1  lukem 	BackendInfo	*rdc_info;
    200           1.1  lukem 	unsigned	rdc_flags;
    201           1.1  lukem 	ber_tag_t	rdc_tag;
    202           1.1  lukem 	AttributeName	*rdc_attrs;
    203           1.1  lukem } retcode_cb_t;
    204           1.1  lukem 
    205           1.1  lukem static int
    206           1.1  lukem retcode_cb_response( Operation *op, SlapReply *rs )
    207           1.1  lukem {
    208           1.1  lukem 	retcode_cb_t	*rdc = (retcode_cb_t *)op->o_callback->sc_private;
    209           1.1  lukem 
    210           1.1  lukem 	op->o_tag = rdc->rdc_tag;
    211           1.1  lukem 	if ( rs->sr_type == REP_SEARCH ) {
    212           1.1  lukem 		ber_tag_t	o_tag = op->o_tag;
    213           1.1  lukem 		int		rc;
    214           1.1  lukem 
    215           1.1  lukem 		if ( op->o_tag == LDAP_REQ_SEARCH ) {
    216           1.1  lukem 			rs->sr_attrs = rdc->rdc_attrs;
    217           1.1  lukem 		}
    218           1.1  lukem 		rc = retcode_entry_response( op, rs, rdc->rdc_info, rs->sr_entry );
    219           1.1  lukem 		op->o_tag = o_tag;
    220           1.1  lukem 
    221           1.1  lukem 		return rc;
    222           1.1  lukem 	}
    223           1.1  lukem 
    224           1.1  lukem 	switch ( rs->sr_err ) {
    225           1.1  lukem 	case LDAP_SUCCESS:
    226           1.1  lukem 	case LDAP_NO_SUCH_OBJECT:
    227           1.1  lukem 		/* in case of noSuchObject, stop the internal search
    228           1.1  lukem 		 * for in-directory error stuff */
    229           1.1  lukem 		if ( !op->o_abandon ) {
    230           1.1  lukem 			rdc->rdc_flags = SLAP_CB_CONTINUE;
    231           1.1  lukem 		}
    232           1.1  lukem 		return 0;
    233           1.1  lukem 	}
    234           1.1  lukem 
    235           1.1  lukem 	return SLAP_CB_CONTINUE;
    236           1.1  lukem }
    237           1.1  lukem 
    238           1.1  lukem static int
    239           1.1  lukem retcode_op_internal( Operation *op, SlapReply *rs )
    240           1.1  lukem {
    241           1.1  lukem 	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
    242           1.1  lukem 
    243           1.1  lukem 	Operation	op2 = *op;
    244           1.1  lukem 	BackendDB	db = *op->o_bd;
    245           1.1  lukem 	slap_callback	sc = { 0 };
    246           1.1  lukem 	retcode_cb_t	rdc;
    247           1.1  lukem 
    248           1.1  lukem 	int		rc;
    249           1.1  lukem 
    250           1.1  lukem 	op2.o_tag = LDAP_REQ_SEARCH;
    251           1.1  lukem 	op2.ors_scope = LDAP_SCOPE_BASE;
    252           1.1  lukem 	op2.ors_deref = LDAP_DEREF_NEVER;
    253           1.1  lukem 	op2.ors_tlimit = SLAP_NO_LIMIT;
    254           1.1  lukem 	op2.ors_slimit = SLAP_NO_LIMIT;
    255           1.1  lukem 	op2.ors_limit = NULL;
    256           1.1  lukem 	op2.ors_attrsonly = 0;
    257           1.1  lukem 	op2.ors_attrs = slap_anlist_all_attributes;
    258           1.1  lukem 
    259           1.1  lukem 	ber_str2bv_x( "(objectClass=errAbsObject)",
    260           1.1  lukem 		STRLENOF( "(objectClass=errAbsObject)" ),
    261           1.1  lukem 		1, &op2.ors_filterstr, op2.o_tmpmemctx );
    262           1.1  lukem 	op2.ors_filter = str2filter_x( &op2, op2.ors_filterstr.bv_val );
    263           1.1  lukem 
    264       1.1.1.2  lukem 	/* errAbsObject is defined by this overlay! */
    265       1.1.1.2  lukem 	assert( op2.ors_filter != NULL );
    266       1.1.1.2  lukem 
    267           1.1  lukem 	db.bd_info = on->on_info->oi_orig;
    268           1.1  lukem 	op2.o_bd = &db;
    269           1.1  lukem 
    270           1.1  lukem 	rdc.rdc_info = on->on_info->oi_orig;
    271           1.1  lukem 	rdc.rdc_flags = RETCODE_FINDIR;
    272           1.1  lukem 	if ( op->o_tag == LDAP_REQ_SEARCH ) {
    273           1.1  lukem 		rdc.rdc_attrs = op->ors_attrs;
    274           1.1  lukem 	}
    275           1.1  lukem 	rdc.rdc_tag = op->o_tag;
    276           1.1  lukem 	sc.sc_response = retcode_cb_response;
    277           1.1  lukem 	sc.sc_private = &rdc;
    278           1.1  lukem 	op2.o_callback = &sc;
    279           1.1  lukem 
    280           1.1  lukem 	rc = op2.o_bd->be_search( &op2, rs );
    281           1.1  lukem 	op->o_abandon = op2.o_abandon;
    282           1.1  lukem 
    283       1.1.1.2  lukem 	filter_free_x( &op2, op2.ors_filter, 1 );
    284           1.1  lukem 	ber_memfree_x( op2.ors_filterstr.bv_val, op2.o_tmpmemctx );
    285           1.1  lukem 
    286           1.1  lukem 	if ( rdc.rdc_flags == SLAP_CB_CONTINUE ) {
    287           1.1  lukem 		return SLAP_CB_CONTINUE;
    288           1.1  lukem 	}
    289           1.1  lukem 
    290           1.1  lukem 	return rc;
    291           1.1  lukem }
    292           1.1  lukem 
    293           1.1  lukem static int
    294           1.1  lukem retcode_op_func( Operation *op, SlapReply *rs )
    295           1.1  lukem {
    296           1.1  lukem 	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
    297           1.1  lukem 	retcode_t	*rd = (retcode_t *)on->on_bi.bi_private;
    298           1.1  lukem 
    299           1.1  lukem 	retcode_item_t	*rdi;
    300           1.1  lukem 	struct berval		nrdn, npdn;
    301           1.1  lukem 
    302           1.1  lukem 	slap_callback		*cb = NULL;
    303           1.1  lukem 
    304           1.1  lukem 	/* sleep as required */
    305           1.1  lukem 	retcode_sleep( rd->rd_sleep );
    306           1.1  lukem 
    307           1.1  lukem 	if ( !dnIsSuffix( &op->o_req_ndn, &rd->rd_npdn ) ) {
    308           1.1  lukem 		if ( RETCODE_INDIR( rd ) ) {
    309           1.1  lukem 			switch ( op->o_tag ) {
    310           1.1  lukem 			case LDAP_REQ_ADD:
    311           1.1  lukem 				return retcode_op_add( op, rs );
    312           1.1  lukem 
    313           1.1  lukem 			case LDAP_REQ_BIND:
    314           1.1  lukem 				/* skip if rootdn */
    315           1.1  lukem 				/* FIXME: better give the db a chance? */
    316           1.1  lukem 				if ( be_isroot_pw( op ) ) {
    317           1.1  lukem 					return LDAP_SUCCESS;
    318           1.1  lukem 				}
    319           1.1  lukem 				return retcode_op_internal( op, rs );
    320           1.1  lukem 
    321           1.1  lukem 			case LDAP_REQ_SEARCH:
    322           1.1  lukem 				if ( op->ors_scope == LDAP_SCOPE_BASE ) {
    323           1.1  lukem 					rs->sr_err = retcode_op_internal( op, rs );
    324           1.1  lukem 					switch ( rs->sr_err ) {
    325           1.1  lukem 					case SLAP_CB_CONTINUE:
    326           1.1  lukem 						if ( rs->sr_nentries == 0 ) {
    327           1.1  lukem 							break;
    328           1.1  lukem 						}
    329           1.1  lukem 						rs->sr_err = LDAP_SUCCESS;
    330           1.1  lukem 						/* fallthru */
    331           1.1  lukem 
    332           1.1  lukem 					default:
    333           1.1  lukem 						send_ldap_result( op, rs );
    334           1.1  lukem 						break;
    335           1.1  lukem 					}
    336           1.1  lukem 					return rs->sr_err;
    337           1.1  lukem 				}
    338           1.1  lukem 				break;
    339           1.1  lukem 
    340           1.1  lukem 			case LDAP_REQ_MODIFY:
    341           1.1  lukem 			case LDAP_REQ_DELETE:
    342           1.1  lukem 			case LDAP_REQ_MODRDN:
    343           1.1  lukem 			case LDAP_REQ_COMPARE:
    344           1.1  lukem 				return retcode_op_internal( op, rs );
    345           1.1  lukem 			}
    346           1.1  lukem 		}
    347           1.1  lukem 
    348           1.1  lukem 		return SLAP_CB_CONTINUE;
    349           1.1  lukem 	}
    350           1.1  lukem 
    351           1.1  lukem 	if ( op->o_tag == LDAP_REQ_SEARCH
    352           1.1  lukem 			&& op->ors_scope != LDAP_SCOPE_BASE
    353           1.1  lukem 			&& op->o_req_ndn.bv_len == rd->rd_npdn.bv_len )
    354           1.1  lukem 	{
    355           1.1  lukem 		return retcode_send_onelevel( op, rs );
    356           1.1  lukem 	}
    357           1.1  lukem 
    358           1.1  lukem 	dnParent( &op->o_req_ndn, &npdn );
    359           1.1  lukem 	if ( npdn.bv_len != rd->rd_npdn.bv_len ) {
    360           1.1  lukem 		rs->sr_err = LDAP_NO_SUCH_OBJECT;
    361           1.1  lukem 		rs->sr_matched = rd->rd_pdn.bv_val;
    362           1.1  lukem 		send_ldap_result( op, rs );
    363           1.1  lukem 		rs->sr_matched = NULL;
    364           1.1  lukem 		return rs->sr_err;
    365           1.1  lukem 	}
    366           1.1  lukem 
    367           1.1  lukem 	dnRdn( &op->o_req_ndn, &nrdn );
    368           1.1  lukem 
    369           1.1  lukem 	for ( rdi = rd->rd_item; rdi != NULL; rdi = rdi->rdi_next ) {
    370           1.1  lukem 		struct berval	rdi_nrdn;
    371           1.1  lukem 
    372           1.1  lukem 		dnRdn( &rdi->rdi_ndn, &rdi_nrdn );
    373           1.1  lukem 		if ( dn_match( &nrdn, &rdi_nrdn ) ) {
    374           1.1  lukem 			break;
    375           1.1  lukem 		}
    376           1.1  lukem 	}
    377           1.1  lukem 
    378           1.1  lukem 	if ( rdi != NULL && rdi->rdi_mask != SN_DG_OP_ALL ) {
    379           1.1  lukem 		retcode_op_e	o_tag = SN_DG_OP_NONE;
    380           1.1  lukem 
    381           1.1  lukem 		switch ( op->o_tag ) {
    382           1.1  lukem 		case LDAP_REQ_ADD:
    383           1.1  lukem 			o_tag = SN_DG_OP_ADD;
    384           1.1  lukem 			break;
    385           1.1  lukem 
    386           1.1  lukem 		case LDAP_REQ_BIND:
    387           1.1  lukem 			o_tag = SN_DG_OP_BIND;
    388           1.1  lukem 			break;
    389           1.1  lukem 
    390           1.1  lukem 		case LDAP_REQ_COMPARE:
    391           1.1  lukem 			o_tag = SN_DG_OP_COMPARE;
    392           1.1  lukem 			break;
    393           1.1  lukem 
    394           1.1  lukem 		case LDAP_REQ_DELETE:
    395           1.1  lukem 			o_tag = SN_DG_OP_DELETE;
    396           1.1  lukem 			break;
    397           1.1  lukem 
    398           1.1  lukem 		case LDAP_REQ_MODIFY:
    399           1.1  lukem 			o_tag = SN_DG_OP_MODIFY;
    400           1.1  lukem 			break;
    401           1.1  lukem 
    402           1.1  lukem 		case LDAP_REQ_MODRDN:
    403           1.1  lukem 			o_tag = SN_DG_OP_RENAME;
    404           1.1  lukem 			break;
    405           1.1  lukem 
    406           1.1  lukem 		case LDAP_REQ_SEARCH:
    407           1.1  lukem 			o_tag = SN_DG_OP_SEARCH;
    408           1.1  lukem 			break;
    409           1.1  lukem 
    410           1.1  lukem 		case LDAP_REQ_EXTENDED:
    411           1.1  lukem 			o_tag = SN_DG_EXTENDED;
    412           1.1  lukem 			break;
    413           1.1  lukem 
    414           1.1  lukem 		default:
    415           1.1  lukem 			/* Should not happen */
    416           1.1  lukem 			break;
    417           1.1  lukem 		}
    418           1.1  lukem 
    419           1.1  lukem 		if ( !( o_tag & rdi->rdi_mask ) ) {
    420           1.1  lukem 			return SLAP_CB_CONTINUE;
    421           1.1  lukem 		}
    422           1.1  lukem 	}
    423           1.1  lukem 
    424           1.1  lukem 	if ( rdi == NULL ) {
    425           1.1  lukem 		rs->sr_matched = rd->rd_pdn.bv_val;
    426           1.1  lukem 		rs->sr_err = LDAP_NO_SUCH_OBJECT;
    427           1.1  lukem 		rs->sr_text = "retcode not found";
    428           1.1  lukem 
    429           1.1  lukem 	} else {
    430           1.1  lukem 		if ( rdi->rdi_flags & RDI_PRE_DISCONNECT ) {
    431           1.1  lukem 			return rs->sr_err = SLAPD_DISCONNECT;
    432           1.1  lukem 		}
    433           1.1  lukem 
    434           1.1  lukem 		rs->sr_err = rdi->rdi_err;
    435           1.1  lukem 		rs->sr_text = rdi->rdi_text.bv_val;
    436           1.1  lukem 		rs->sr_matched = rdi->rdi_matched.bv_val;
    437           1.1  lukem 
    438           1.1  lukem 		/* FIXME: we only honor the rdi_ref field in case rdi_err
    439           1.1  lukem 		 * is LDAP_REFERRAL otherwise send_ldap_result() bails out */
    440           1.1  lukem 		if ( rs->sr_err == LDAP_REFERRAL ) {
    441           1.1  lukem 			BerVarray	ref;
    442           1.1  lukem 
    443           1.1  lukem 			if ( rdi->rdi_ref != NULL ) {
    444           1.1  lukem 				ref = rdi->rdi_ref;
    445           1.1  lukem 			} else {
    446           1.1  lukem 				ref = default_referral;
    447           1.1  lukem 			}
    448           1.1  lukem 
    449           1.1  lukem 			if ( ref != NULL ) {
    450           1.1  lukem 				rs->sr_ref = referral_rewrite( ref,
    451           1.1  lukem 					NULL, &op->o_req_dn, LDAP_SCOPE_DEFAULT );
    452           1.1  lukem 
    453           1.1  lukem 			} else {
    454           1.1  lukem 				rs->sr_err = LDAP_OTHER;
    455           1.1  lukem 				rs->sr_text = "bad referral object";
    456           1.1  lukem 			}
    457           1.1  lukem 		}
    458           1.1  lukem 
    459           1.1  lukem 		retcode_sleep( rdi->rdi_sleeptime );
    460           1.1  lukem 	}
    461           1.1  lukem 
    462           1.1  lukem 	switch ( op->o_tag ) {
    463           1.1  lukem 	case LDAP_REQ_EXTENDED:
    464           1.1  lukem 		if ( rdi == NULL ) {
    465           1.1  lukem 			break;
    466           1.1  lukem 		}
    467           1.1  lukem 		cb = ( slap_callback * )ch_malloc( sizeof( slap_callback ) );
    468           1.1  lukem 		memset( cb, 0, sizeof( slap_callback ) );
    469           1.1  lukem 		cb->sc_cleanup = retcode_cleanup_cb;
    470           1.1  lukem 		op->o_callback = cb;
    471           1.1  lukem 		break;
    472           1.1  lukem 
    473           1.1  lukem 	default:
    474           1.1  lukem 		if ( rdi && !BER_BVISNULL( &rdi->rdi_unsolicited_oid ) ) {
    475           1.1  lukem 			ber_int_t	msgid = op->o_msgid;
    476           1.1  lukem 
    477           1.1  lukem 			/* RFC 4511 unsolicited response */
    478           1.1  lukem 
    479           1.1  lukem 			op->o_msgid = 0;
    480           1.1  lukem 			if ( strcmp( rdi->rdi_unsolicited_oid.bv_val, "0" ) == 0 ) {
    481           1.1  lukem 				send_ldap_result( op, rs );
    482           1.1  lukem 
    483           1.1  lukem 			} else {
    484           1.1  lukem 				ber_tag_t	tag = op->o_tag;
    485           1.1  lukem 
    486           1.1  lukem 				op->o_tag = LDAP_REQ_EXTENDED;
    487           1.1  lukem 				rs->sr_rspoid = rdi->rdi_unsolicited_oid.bv_val;
    488           1.1  lukem 				if ( !BER_BVISNULL( &rdi->rdi_unsolicited_data ) ) {
    489           1.1  lukem 					rs->sr_rspdata = &rdi->rdi_unsolicited_data;
    490           1.1  lukem 				}
    491           1.1  lukem 				send_ldap_extended( op, rs );
    492           1.1  lukem 				rs->sr_rspoid = NULL;
    493           1.1  lukem 				rs->sr_rspdata = NULL;
    494           1.1  lukem 				op->o_tag = tag;
    495           1.1  lukem 
    496           1.1  lukem 			}
    497           1.1  lukem 			op->o_msgid = msgid;
    498           1.1  lukem 
    499           1.1  lukem 		} else {
    500           1.1  lukem 			send_ldap_result( op, rs );
    501           1.1  lukem 		}
    502           1.1  lukem 
    503           1.1  lukem 		if ( rs->sr_ref != NULL ) {
    504           1.1  lukem 			ber_bvarray_free( rs->sr_ref );
    505           1.1  lukem 			rs->sr_ref = NULL;
    506           1.1  lukem 		}
    507           1.1  lukem 		rs->sr_matched = NULL;
    508           1.1  lukem 		rs->sr_text = NULL;
    509           1.1  lukem 
    510           1.1  lukem 		if ( rdi && rdi->rdi_flags & RDI_POST_DISCONNECT ) {
    511           1.1  lukem 			return rs->sr_err = SLAPD_DISCONNECT;
    512           1.1  lukem 		}
    513           1.1  lukem 		break;
    514           1.1  lukem 	}
    515           1.1  lukem 
    516           1.1  lukem 	return rs->sr_err;
    517           1.1  lukem }
    518           1.1  lukem 
    519           1.1  lukem static int
    520           1.1  lukem retcode_op2str( ber_tag_t op, struct berval *bv )
    521           1.1  lukem {
    522           1.1  lukem 	switch ( op ) {
    523           1.1  lukem 	case LDAP_REQ_BIND:
    524           1.1  lukem 		BER_BVSTR( bv, "bind" );
    525           1.1  lukem 		return 0;
    526           1.1  lukem 	case LDAP_REQ_ADD:
    527           1.1  lukem 		BER_BVSTR( bv, "add" );
    528           1.1  lukem 		return 0;
    529           1.1  lukem 	case LDAP_REQ_DELETE:
    530           1.1  lukem 		BER_BVSTR( bv, "delete" );
    531           1.1  lukem 		return 0;
    532           1.1  lukem 	case LDAP_REQ_MODRDN:
    533           1.1  lukem 		BER_BVSTR( bv, "modrdn" );
    534           1.1  lukem 		return 0;
    535           1.1  lukem 	case LDAP_REQ_MODIFY:
    536           1.1  lukem 		BER_BVSTR( bv, "modify" );
    537           1.1  lukem 		return 0;
    538           1.1  lukem 	case LDAP_REQ_COMPARE:
    539           1.1  lukem 		BER_BVSTR( bv, "compare" );
    540           1.1  lukem 		return 0;
    541           1.1  lukem 	case LDAP_REQ_SEARCH:
    542           1.1  lukem 		BER_BVSTR( bv, "search" );
    543           1.1  lukem 		return 0;
    544           1.1  lukem 	case LDAP_REQ_EXTENDED:
    545           1.1  lukem 		BER_BVSTR( bv, "extended" );
    546           1.1  lukem 		return 0;
    547           1.1  lukem 	}
    548           1.1  lukem 	return -1;
    549           1.1  lukem }
    550           1.1  lukem 
    551           1.1  lukem static int
    552           1.1  lukem retcode_entry_response( Operation *op, SlapReply *rs, BackendInfo *bi, Entry *e )
    553           1.1  lukem {
    554           1.1  lukem 	Attribute	*a;
    555           1.1  lukem 	int		err;
    556           1.1  lukem 	char		*next;
    557           1.1  lukem 	int		disconnect = 0;
    558           1.1  lukem 
    559           1.1  lukem 	if ( get_manageDSAit( op ) ) {
    560           1.1  lukem 		return SLAP_CB_CONTINUE;
    561           1.1  lukem 	}
    562           1.1  lukem 
    563           1.1  lukem 	if ( !is_entry_objectclass_or_sub( e, oc_errAbsObject ) ) {
    564           1.1  lukem 		return SLAP_CB_CONTINUE;
    565           1.1  lukem 	}
    566           1.1  lukem 
    567           1.1  lukem 	/* operation */
    568           1.1  lukem 	a = attr_find( e->e_attrs, ad_errOp );
    569           1.1  lukem 	if ( a != NULL ) {
    570           1.1  lukem 		int		i,
    571           1.1  lukem 				gotit = 0;
    572           1.1  lukem 		struct berval	bv = BER_BVNULL;
    573           1.1  lukem 
    574           1.1  lukem 		(void)retcode_op2str( op->o_tag, &bv );
    575           1.1  lukem 
    576           1.1  lukem 		if ( BER_BVISNULL( &bv ) ) {
    577           1.1  lukem 			return SLAP_CB_CONTINUE;
    578           1.1  lukem 		}
    579           1.1  lukem 
    580           1.1  lukem 		for ( i = 0; !BER_BVISNULL( &a->a_nvals[ i ] ); i++ ) {
    581           1.1  lukem 			if ( bvmatch( &a->a_nvals[ i ], &bv ) ) {
    582           1.1  lukem 				gotit = 1;
    583           1.1  lukem 				break;
    584           1.1  lukem 			}
    585           1.1  lukem 		}
    586           1.1  lukem 
    587           1.1  lukem 		if ( !gotit ) {
    588           1.1  lukem 			return SLAP_CB_CONTINUE;
    589           1.1  lukem 		}
    590           1.1  lukem 	}
    591           1.1  lukem 
    592           1.1  lukem 	/* disconnect */
    593           1.1  lukem 	a = attr_find( e->e_attrs, ad_errDisconnect );
    594           1.1  lukem 	if ( a != NULL ) {
    595           1.1  lukem 		if ( bvmatch( &a->a_nvals[ 0 ], &slap_true_bv ) ) {
    596           1.1  lukem 			return rs->sr_err = SLAPD_DISCONNECT;
    597           1.1  lukem 		}
    598           1.1  lukem 		disconnect = 1;
    599           1.1  lukem 	}
    600           1.1  lukem 
    601           1.1  lukem 	/* error code */
    602           1.1  lukem 	a = attr_find( e->e_attrs, ad_errCode );
    603           1.1  lukem 	if ( a == NULL ) {
    604           1.1  lukem 		return SLAP_CB_CONTINUE;
    605           1.1  lukem 	}
    606           1.1  lukem 	err = strtol( a->a_nvals[ 0 ].bv_val, &next, 0 );
    607           1.1  lukem 	if ( next == a->a_nvals[ 0 ].bv_val || next[ 0 ] != '\0' ) {
    608           1.1  lukem 		return SLAP_CB_CONTINUE;
    609           1.1  lukem 	}
    610           1.1  lukem 	rs->sr_err = err;
    611           1.1  lukem 
    612           1.1  lukem 	/* sleep time */
    613           1.1  lukem 	a = attr_find( e->e_attrs, ad_errSleepTime );
    614           1.1  lukem 	if ( a != NULL && a->a_nvals[ 0 ].bv_val[ 0 ] != '-' ) {
    615           1.1  lukem 		int	sleepTime;
    616           1.1  lukem 
    617           1.1  lukem 		if ( lutil_atoi( &sleepTime, a->a_nvals[ 0 ].bv_val ) == 0 ) {
    618           1.1  lukem 			retcode_sleep( sleepTime );
    619           1.1  lukem 		}
    620           1.1  lukem 	}
    621           1.1  lukem 
    622           1.1  lukem 	if ( rs->sr_err != LDAP_SUCCESS && !LDAP_API_ERROR( rs->sr_err )) {
    623           1.1  lukem 		BackendDB	db = *op->o_bd,
    624           1.1  lukem 				*o_bd = op->o_bd;
    625           1.1  lukem 		void		*o_callback = op->o_callback;
    626           1.1  lukem 
    627           1.1  lukem 		/* message text */
    628           1.1  lukem 		a = attr_find( e->e_attrs, ad_errText );
    629           1.1  lukem 		if ( a != NULL ) {
    630           1.1  lukem 			rs->sr_text = a->a_vals[ 0 ].bv_val;
    631           1.1  lukem 		}
    632           1.1  lukem 
    633           1.1  lukem 		/* matched DN */
    634           1.1  lukem 		a = attr_find( e->e_attrs, ad_errMatchedDN );
    635           1.1  lukem 		if ( a != NULL ) {
    636           1.1  lukem 			rs->sr_matched = a->a_vals[ 0 ].bv_val;
    637           1.1  lukem 		}
    638           1.1  lukem 
    639           1.1  lukem 		if ( bi == NULL ) {
    640           1.1  lukem 			slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
    641           1.1  lukem 
    642           1.1  lukem 			bi = on->on_info->oi_orig;
    643           1.1  lukem 		}
    644           1.1  lukem 
    645           1.1  lukem 		db.bd_info = bi;
    646           1.1  lukem 		op->o_bd = &db;
    647           1.1  lukem 		op->o_callback = NULL;
    648           1.1  lukem 
    649           1.1  lukem 		/* referral */
    650           1.1  lukem 		if ( rs->sr_err == LDAP_REFERRAL ) {
    651           1.1  lukem 			BerVarray	refs = default_referral;
    652           1.1  lukem 
    653           1.1  lukem 			a = attr_find( e->e_attrs, slap_schema.si_ad_ref );
    654           1.1  lukem 			if ( a != NULL ) {
    655           1.1  lukem 				refs = a->a_vals;
    656           1.1  lukem 			}
    657           1.1  lukem 			rs->sr_ref = referral_rewrite( refs,
    658           1.1  lukem 				NULL, &op->o_req_dn, op->oq_search.rs_scope );
    659           1.1  lukem 
    660           1.1  lukem 			send_search_reference( op, rs );
    661           1.1  lukem 			ber_bvarray_free( rs->sr_ref );
    662           1.1  lukem 			rs->sr_ref = NULL;
    663           1.1  lukem 
    664           1.1  lukem 		} else {
    665           1.1  lukem 			a = attr_find( e->e_attrs, ad_errUnsolicitedOID );
    666           1.1  lukem 			if ( a != NULL ) {
    667           1.1  lukem 				struct berval	oid = BER_BVNULL,
    668           1.1  lukem 						data = BER_BVNULL;
    669           1.1  lukem 				ber_int_t	msgid = op->o_msgid;
    670           1.1  lukem 
    671           1.1  lukem 				/* RFC 4511 unsolicited response */
    672           1.1  lukem 
    673           1.1  lukem 				op->o_msgid = 0;
    674           1.1  lukem 
    675           1.1  lukem 				oid = a->a_nvals[ 0 ];
    676           1.1  lukem 
    677           1.1  lukem 				a = attr_find( e->e_attrs, ad_errUnsolicitedData );
    678           1.1  lukem 				if ( a != NULL ) {
    679           1.1  lukem 					data = a->a_nvals[ 0 ];
    680           1.1  lukem 				}
    681           1.1  lukem 
    682           1.1  lukem 				if ( strcmp( oid.bv_val, "0" ) == 0 ) {
    683           1.1  lukem 					send_ldap_result( op, rs );
    684           1.1  lukem 
    685           1.1  lukem 				} else {
    686           1.1  lukem 					ber_tag_t	tag = op->o_tag;
    687           1.1  lukem 
    688           1.1  lukem 					op->o_tag = LDAP_REQ_EXTENDED;
    689           1.1  lukem 					rs->sr_rspoid = oid.bv_val;
    690           1.1  lukem 					if ( !BER_BVISNULL( &data ) ) {
    691           1.1  lukem 						rs->sr_rspdata = &data;
    692           1.1  lukem 					}
    693           1.1  lukem 					send_ldap_extended( op, rs );
    694           1.1  lukem 					rs->sr_rspoid = NULL;
    695           1.1  lukem 					rs->sr_rspdata = NULL;
    696           1.1  lukem 					op->o_tag = tag;
    697           1.1  lukem 				}
    698           1.1  lukem 				op->o_msgid = msgid;
    699           1.1  lukem 
    700           1.1  lukem 			} else {
    701           1.1  lukem 				send_ldap_result( op, rs );
    702           1.1  lukem 			}
    703           1.1  lukem 		}
    704           1.1  lukem 
    705           1.1  lukem 		rs->sr_text = NULL;
    706           1.1  lukem 		rs->sr_matched = NULL;
    707           1.1  lukem 		op->o_bd = o_bd;
    708           1.1  lukem 		op->o_callback = o_callback;
    709           1.1  lukem 	}
    710           1.1  lukem 
    711           1.1  lukem 	if ( rs->sr_err != LDAP_SUCCESS ) {
    712           1.1  lukem 		if ( disconnect ) {
    713           1.1  lukem 			return rs->sr_err = SLAPD_DISCONNECT;
    714           1.1  lukem 		}
    715           1.1  lukem 
    716           1.1  lukem 		op->o_abandon = 1;
    717           1.1  lukem 		return rs->sr_err;
    718           1.1  lukem 	}
    719           1.1  lukem 
    720           1.1  lukem 	return SLAP_CB_CONTINUE;
    721           1.1  lukem }
    722           1.1  lukem 
    723           1.1  lukem static int
    724           1.1  lukem retcode_response( Operation *op, SlapReply *rs )
    725           1.1  lukem {
    726           1.1  lukem 	slap_overinst	*on = (slap_overinst *)op->o_bd->bd_info;
    727           1.1  lukem 	retcode_t	*rd = (retcode_t *)on->on_bi.bi_private;
    728           1.1  lukem 
    729           1.1  lukem 	if ( rs->sr_type != REP_SEARCH || !RETCODE_INDIR( rd ) ) {
    730           1.1  lukem 		return SLAP_CB_CONTINUE;
    731           1.1  lukem 	}
    732           1.1  lukem 
    733           1.1  lukem 	return retcode_entry_response( op, rs, NULL, rs->sr_entry );
    734           1.1  lukem }
    735           1.1  lukem 
    736           1.1  lukem static int
    737           1.1  lukem retcode_db_init( BackendDB *be, ConfigReply *cr )
    738           1.1  lukem {
    739           1.1  lukem 	slap_overinst	*on = (slap_overinst *)be->bd_info;
    740           1.1  lukem 	retcode_t	*rd;
    741           1.1  lukem 
    742           1.1  lukem 	srand( getpid() );
    743           1.1  lukem 
    744           1.1  lukem 	rd = (retcode_t *)ch_malloc( sizeof( retcode_t ) );
    745           1.1  lukem 	memset( rd, 0, sizeof( retcode_t ) );
    746           1.1  lukem 
    747           1.1  lukem 	on->on_bi.bi_private = (void *)rd;
    748           1.1  lukem 
    749           1.1  lukem 	return 0;
    750           1.1  lukem }
    751           1.1  lukem 
    752       1.1.1.2  lukem static void
    753       1.1.1.2  lukem retcode_item_destroy( retcode_item_t *rdi )
    754           1.1  lukem {
    755       1.1.1.2  lukem 	ber_memfree( rdi->rdi_line.bv_val );
    756           1.1  lukem 
    757       1.1.1.2  lukem 	ber_memfree( rdi->rdi_dn.bv_val );
    758       1.1.1.2  lukem 	ber_memfree( rdi->rdi_ndn.bv_val );
    759           1.1  lukem 
    760       1.1.1.2  lukem 	if ( !BER_BVISNULL( &rdi->rdi_text ) ) {
    761       1.1.1.2  lukem 		ber_memfree( rdi->rdi_text.bv_val );
    762           1.1  lukem 	}
    763           1.1  lukem 
    764       1.1.1.2  lukem 	if ( !BER_BVISNULL( &rdi->rdi_matched ) ) {
    765       1.1.1.2  lukem 		ber_memfree( rdi->rdi_matched.bv_val );
    766       1.1.1.2  lukem 	}
    767           1.1  lukem 
    768       1.1.1.2  lukem 	if ( rdi->rdi_ref ) {
    769       1.1.1.2  lukem 		ber_bvarray_free( rdi->rdi_ref );
    770       1.1.1.2  lukem 	}
    771           1.1  lukem 
    772       1.1.1.2  lukem 	BER_BVZERO( &rdi->rdi_e.e_name );
    773       1.1.1.2  lukem 	BER_BVZERO( &rdi->rdi_e.e_nname );
    774       1.1.1.2  lukem 
    775       1.1.1.2  lukem 	entry_clean( &rdi->rdi_e );
    776       1.1.1.2  lukem 
    777  1.1.1.3.24.1    tls 	if ( !BER_BVISNULL( &rdi->rdi_unsolicited_oid ) ) {
    778  1.1.1.3.24.1    tls 		ber_memfree( rdi->rdi_unsolicited_oid.bv_val );
    779  1.1.1.3.24.1    tls 		if ( !BER_BVISNULL( &rdi->rdi_unsolicited_data ) )
    780  1.1.1.3.24.1    tls 			ber_memfree( rdi->rdi_unsolicited_data.bv_val );
    781  1.1.1.3.24.1    tls 	}
    782  1.1.1.3.24.1    tls 
    783       1.1.1.2  lukem 	ch_free( rdi );
    784       1.1.1.2  lukem }
    785       1.1.1.2  lukem 
    786       1.1.1.2  lukem enum {
    787       1.1.1.2  lukem 	RC_PARENT = 1,
    788       1.1.1.2  lukem 	RC_ITEM
    789       1.1.1.2  lukem };
    790       1.1.1.2  lukem 
    791       1.1.1.2  lukem static ConfigDriver rc_cf_gen;
    792       1.1.1.2  lukem 
    793       1.1.1.2  lukem static ConfigTable rccfg[] = {
    794       1.1.1.2  lukem 	{ "retcode-parent", "dn",
    795       1.1.1.2  lukem 		2, 2, 0, ARG_MAGIC|ARG_DN|RC_PARENT, rc_cf_gen,
    796       1.1.1.2  lukem 		"( OLcfgOvAt:20.1 NAME 'olcRetcodeParent' "
    797       1.1.1.2  lukem 			"DESC '' "
    798       1.1.1.2  lukem 			"SYNTAX OMsDN SINGLE-VALUE )", NULL, NULL },
    799       1.1.1.2  lukem 	{ "retcode-item", "rdn> <retcode> <...",
    800       1.1.1.2  lukem 		3, 0, 0, ARG_MAGIC|RC_ITEM, rc_cf_gen,
    801       1.1.1.2  lukem 		"( OLcfgOvAt:20.2 NAME 'olcRetcodeItem' "
    802       1.1.1.2  lukem 			"DESC '' "
    803       1.1.1.2  lukem 	  		"EQUALITY caseIgnoreMatch "
    804       1.1.1.2  lukem 			"SYNTAX OMsDirectoryString "
    805       1.1.1.2  lukem 			"X-ORDERED 'VALUES' )", NULL, NULL },
    806       1.1.1.2  lukem 	{ "retcode-indir", "on|off",
    807       1.1.1.2  lukem 		1, 2, 0, ARG_OFFSET|ARG_ON_OFF,
    808       1.1.1.2  lukem 			(void *)offsetof(retcode_t, rd_indir),
    809       1.1.1.2  lukem 		"( OLcfgOvAt:20.3 NAME 'olcRetcodeInDir' "
    810       1.1.1.2  lukem 			"DESC '' "
    811       1.1.1.2  lukem 			"SYNTAX OMsBoolean SINGLE-VALUE )", NULL, NULL },
    812       1.1.1.2  lukem 
    813       1.1.1.2  lukem 	{ "retcode-sleep", "sleeptime",
    814       1.1.1.2  lukem 		2, 2, 0, ARG_OFFSET|ARG_INT,
    815       1.1.1.2  lukem 			(void *)offsetof(retcode_t, rd_sleep),
    816       1.1.1.2  lukem 		"( OLcfgOvAt:20.4 NAME 'olcRetcodeSleep' "
    817       1.1.1.2  lukem 			"DESC '' "
    818       1.1.1.2  lukem 			"SYNTAX OMsInteger SINGLE-VALUE )", NULL, NULL },
    819       1.1.1.2  lukem 
    820       1.1.1.2  lukem 	{ NULL, NULL, 0, 0, 0, ARG_IGNORED }
    821       1.1.1.2  lukem };
    822       1.1.1.2  lukem 
    823       1.1.1.2  lukem static ConfigOCs rcocs[] = {
    824       1.1.1.2  lukem 	{ "( OLcfgOvOc:20.1 "
    825       1.1.1.2  lukem 		"NAME 'olcRetcodeConfig' "
    826       1.1.1.2  lukem 		"DESC 'Retcode configuration' "
    827       1.1.1.2  lukem 		"SUP olcOverlayConfig "
    828       1.1.1.2  lukem 		"MAY ( olcRetcodeParent "
    829       1.1.1.2  lukem 			"$ olcRetcodeItem "
    830       1.1.1.2  lukem 			"$ olcRetcodeInDir "
    831       1.1.1.2  lukem 			"$ olcRetcodeSleep "
    832       1.1.1.2  lukem 		") )",
    833       1.1.1.2  lukem 		Cft_Overlay, rccfg, NULL, NULL },
    834       1.1.1.2  lukem 	{ NULL, 0, NULL }
    835       1.1.1.2  lukem };
    836       1.1.1.2  lukem 
    837       1.1.1.2  lukem static int
    838       1.1.1.2  lukem rc_cf_gen( ConfigArgs *c )
    839       1.1.1.2  lukem {
    840       1.1.1.2  lukem 	slap_overinst	*on = (slap_overinst *)c->bi;
    841       1.1.1.2  lukem 	retcode_t	*rd = (retcode_t *)on->on_bi.bi_private;
    842       1.1.1.2  lukem 	int		rc = ARG_BAD_CONF;
    843       1.1.1.2  lukem 
    844       1.1.1.2  lukem 	if ( c->op == SLAP_CONFIG_EMIT ) {
    845       1.1.1.2  lukem 		switch( c->type ) {
    846       1.1.1.2  lukem 		case RC_PARENT:
    847       1.1.1.2  lukem 			if ( !BER_BVISEMPTY( &rd->rd_pdn )) {
    848       1.1.1.2  lukem 				rc = value_add_one( &c->rvalue_vals,
    849       1.1.1.2  lukem 						    &rd->rd_pdn );
    850       1.1.1.2  lukem 				if ( rc == 0 ) {
    851       1.1.1.2  lukem 					rc = value_add_one( &c->rvalue_nvals,
    852       1.1.1.2  lukem 							    &rd->rd_npdn );
    853       1.1.1.2  lukem 				}
    854       1.1.1.2  lukem 				return rc;
    855       1.1.1.2  lukem 			}
    856       1.1.1.2  lukem 			rc = 0;
    857       1.1.1.2  lukem 			break;
    858       1.1.1.2  lukem 
    859       1.1.1.2  lukem 		case RC_ITEM: {
    860       1.1.1.2  lukem 			retcode_item_t *rdi;
    861       1.1.1.2  lukem 			int i;
    862       1.1.1.2  lukem 
    863       1.1.1.2  lukem 			for ( rdi = rd->rd_item, i = 0; rdi; rdi = rdi->rdi_next, i++ ) {
    864       1.1.1.2  lukem 				char buf[4096];
    865       1.1.1.2  lukem 				struct berval bv;
    866       1.1.1.2  lukem 				char *ptr;
    867       1.1.1.2  lukem 
    868       1.1.1.2  lukem 				bv.bv_len = snprintf( buf, sizeof( buf ), SLAP_X_ORDERED_FMT, i );
    869       1.1.1.2  lukem 				bv.bv_len += rdi->rdi_line.bv_len;
    870       1.1.1.2  lukem 				ptr = bv.bv_val = ch_malloc( bv.bv_len + 1 );
    871       1.1.1.2  lukem 				ptr = lutil_strcopy( ptr, buf );
    872       1.1.1.2  lukem 				ptr = lutil_strncopy( ptr, rdi->rdi_line.bv_val, rdi->rdi_line.bv_len );
    873       1.1.1.2  lukem 				ber_bvarray_add( &c->rvalue_vals, &bv );
    874       1.1.1.2  lukem 			}
    875       1.1.1.2  lukem 			rc = 0;
    876       1.1.1.2  lukem 			} break;
    877       1.1.1.2  lukem 
    878       1.1.1.2  lukem 		default:
    879       1.1.1.2  lukem 			assert( 0 );
    880       1.1.1.2  lukem 			break;
    881           1.1  lukem 		}
    882           1.1  lukem 
    883       1.1.1.2  lukem 		return rc;
    884           1.1  lukem 
    885       1.1.1.2  lukem 	} else if ( c->op == LDAP_MOD_DELETE ) {
    886       1.1.1.2  lukem 		switch( c->type ) {
    887       1.1.1.2  lukem 		case RC_PARENT:
    888       1.1.1.2  lukem 			if ( rd->rd_pdn.bv_val ) {
    889       1.1.1.2  lukem 				ber_memfree ( rd->rd_pdn.bv_val );
    890       1.1.1.2  lukem 				rc = 0;
    891       1.1.1.2  lukem 			}
    892       1.1.1.2  lukem 			if ( rd->rd_npdn.bv_val ) {
    893       1.1.1.2  lukem 				ber_memfree ( rd->rd_npdn.bv_val );
    894       1.1.1.2  lukem 			}
    895       1.1.1.2  lukem 			break;
    896       1.1.1.2  lukem 
    897       1.1.1.2  lukem 		case RC_ITEM:
    898       1.1.1.2  lukem 			if ( c->valx == -1 ) {
    899       1.1.1.2  lukem 				retcode_item_t *rdi, *next;
    900       1.1.1.2  lukem 
    901       1.1.1.2  lukem 				for ( rdi = rd->rd_item; rdi != NULL; rdi = next ) {
    902       1.1.1.2  lukem 					next = rdi->rdi_next;
    903       1.1.1.2  lukem 					retcode_item_destroy( rdi );
    904       1.1.1.2  lukem 				}
    905       1.1.1.2  lukem 
    906       1.1.1.2  lukem 			} else {
    907       1.1.1.2  lukem 				retcode_item_t **rdip, *rdi;
    908       1.1.1.2  lukem 				int i;
    909       1.1.1.2  lukem 
    910       1.1.1.2  lukem 				for ( rdip = &rd->rd_item, i = 0; i <= c->valx && *rdip; i++, rdip = &(*rdip)->rdi_next )
    911       1.1.1.2  lukem 					;
    912       1.1.1.2  lukem 				if ( *rdip == NULL ) {
    913       1.1.1.2  lukem 					return 1;
    914       1.1.1.2  lukem 				}
    915       1.1.1.2  lukem 				rdi = *rdip;
    916       1.1.1.2  lukem 				*rdip = rdi->rdi_next;
    917       1.1.1.2  lukem 
    918       1.1.1.2  lukem 				retcode_item_destroy( rdi );
    919       1.1.1.2  lukem 			}
    920       1.1.1.2  lukem 			rc = 0;
    921       1.1.1.2  lukem 			break;
    922       1.1.1.2  lukem 
    923       1.1.1.2  lukem 		default:
    924       1.1.1.2  lukem 			assert( 0 );
    925       1.1.1.2  lukem 			break;
    926           1.1  lukem 		}
    927       1.1.1.2  lukem 		return rc;	/* FIXME */
    928       1.1.1.2  lukem 	}
    929       1.1.1.2  lukem 
    930       1.1.1.2  lukem 	switch( c->type ) {
    931       1.1.1.2  lukem 	case RC_PARENT:
    932       1.1.1.2  lukem 		if ( rd->rd_pdn.bv_val ) {
    933       1.1.1.2  lukem 			ber_memfree ( rd->rd_pdn.bv_val );
    934       1.1.1.2  lukem 		}
    935       1.1.1.2  lukem 		if ( rd->rd_npdn.bv_val ) {
    936       1.1.1.2  lukem 			ber_memfree ( rd->rd_npdn.bv_val );
    937       1.1.1.2  lukem 		}
    938       1.1.1.2  lukem 		rd->rd_pdn = c->value_dn;
    939       1.1.1.2  lukem 		rd->rd_npdn = c->value_ndn;
    940       1.1.1.2  lukem 		rc = 0;
    941       1.1.1.2  lukem 		break;
    942           1.1  lukem 
    943       1.1.1.2  lukem 	case RC_ITEM: {
    944           1.1  lukem 		retcode_item_t	rdi = { BER_BVNULL }, **rdip;
    945           1.1  lukem 		struct berval		bv, rdn, nrdn;
    946           1.1  lukem 		char			*next = NULL;
    947       1.1.1.2  lukem 		int			i;
    948           1.1  lukem 
    949       1.1.1.2  lukem 		if ( c->argc < 3 ) {
    950       1.1.1.2  lukem 			snprintf( c->cr_msg, sizeof(c->cr_msg),
    951           1.1  lukem 				"\"retcode-item <RDN> <retcode> [<text>]\": "
    952       1.1.1.2  lukem 				"missing args" );
    953       1.1.1.2  lukem 			Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
    954       1.1.1.2  lukem 				c->log, c->cr_msg, 0 );
    955       1.1.1.2  lukem 			return ARG_BAD_CONF;
    956           1.1  lukem 		}
    957           1.1  lukem 
    958       1.1.1.2  lukem 		ber_str2bv( c->argv[ 1 ], 0, 0, &bv );
    959           1.1  lukem 
    960           1.1  lukem 		rc = dnPrettyNormal( NULL, &bv, &rdn, &nrdn, NULL );
    961           1.1  lukem 		if ( rc != LDAP_SUCCESS ) {
    962       1.1.1.2  lukem 			snprintf( c->cr_msg, sizeof(c->cr_msg),
    963       1.1.1.2  lukem 				"unable to normalize RDN \"%s\": %d",
    964       1.1.1.2  lukem 				c->argv[ 1 ], rc );
    965       1.1.1.2  lukem 			Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
    966       1.1.1.2  lukem 				c->log, c->cr_msg, 0 );
    967       1.1.1.2  lukem 			return ARG_BAD_CONF;
    968           1.1  lukem 		}
    969           1.1  lukem 
    970           1.1  lukem 		if ( !dnIsOneLevelRDN( &nrdn ) ) {
    971       1.1.1.2  lukem 			snprintf( c->cr_msg, sizeof(c->cr_msg),
    972       1.1.1.2  lukem 				"value \"%s\" is not a RDN",
    973       1.1.1.2  lukem 				c->argv[ 1 ] );
    974       1.1.1.2  lukem 			Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
    975       1.1.1.2  lukem 				c->log, c->cr_msg, 0 );
    976       1.1.1.2  lukem 			return ARG_BAD_CONF;
    977           1.1  lukem 		}
    978           1.1  lukem 
    979           1.1  lukem 		if ( BER_BVISNULL( &rd->rd_npdn ) ) {
    980           1.1  lukem 			/* FIXME: we use the database suffix */
    981       1.1.1.2  lukem 			if ( c->be->be_nsuffix == NULL ) {
    982       1.1.1.2  lukem 				snprintf( c->cr_msg, sizeof(c->cr_msg),
    983           1.1  lukem 					"either \"retcode-parent\" "
    984       1.1.1.2  lukem 					"or \"suffix\" must be defined" );
    985       1.1.1.2  lukem 				Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
    986       1.1.1.2  lukem 					c->log, c->cr_msg, 0 );
    987       1.1.1.2  lukem 				return ARG_BAD_CONF;
    988           1.1  lukem 			}
    989           1.1  lukem 
    990       1.1.1.2  lukem 			ber_dupbv( &rd->rd_pdn, &c->be->be_suffix[ 0 ] );
    991       1.1.1.2  lukem 			ber_dupbv( &rd->rd_npdn, &c->be->be_nsuffix[ 0 ] );
    992           1.1  lukem 		}
    993           1.1  lukem 
    994           1.1  lukem 		build_new_dn( &rdi.rdi_dn, &rd->rd_pdn, &rdn, NULL );
    995           1.1  lukem 		build_new_dn( &rdi.rdi_ndn, &rd->rd_npdn, &nrdn, NULL );
    996           1.1  lukem 
    997           1.1  lukem 		ch_free( rdn.bv_val );
    998           1.1  lukem 		ch_free( nrdn.bv_val );
    999           1.1  lukem 
   1000       1.1.1.2  lukem 		rdi.rdi_err = strtol( c->argv[ 2 ], &next, 0 );
   1001       1.1.1.2  lukem 		if ( next == c->argv[ 2 ] || next[ 0 ] != '\0' ) {
   1002       1.1.1.2  lukem 			snprintf( c->cr_msg, sizeof(c->cr_msg),
   1003       1.1.1.2  lukem 				"unable to parse return code \"%s\"",
   1004       1.1.1.2  lukem 				c->argv[ 2 ] );
   1005       1.1.1.2  lukem 			Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1006       1.1.1.2  lukem 				c->log, c->cr_msg, 0 );
   1007       1.1.1.2  lukem 			return ARG_BAD_CONF;
   1008           1.1  lukem 		}
   1009           1.1  lukem 
   1010           1.1  lukem 		rdi.rdi_mask = SN_DG_OP_ALL;
   1011           1.1  lukem 
   1012       1.1.1.2  lukem 		if ( c->argc > 3 ) {
   1013       1.1.1.2  lukem 			for ( i = 3; i < c->argc; i++ ) {
   1014       1.1.1.2  lukem 				if ( strncasecmp( c->argv[ i ], "op=", STRLENOF( "op=" ) ) == 0 )
   1015           1.1  lukem 				{
   1016           1.1  lukem 					char		**ops;
   1017           1.1  lukem 					int		j;
   1018           1.1  lukem 
   1019       1.1.1.2  lukem 					ops = ldap_str2charray( &c->argv[ i ][ STRLENOF( "op=" ) ], "," );
   1020           1.1  lukem 					assert( ops != NULL );
   1021           1.1  lukem 
   1022           1.1  lukem 					rdi.rdi_mask = SN_DG_OP_NONE;
   1023           1.1  lukem 
   1024           1.1  lukem 					for ( j = 0; ops[ j ] != NULL; j++ ) {
   1025           1.1  lukem 						if ( strcasecmp( ops[ j ], "add" ) == 0 ) {
   1026           1.1  lukem 							rdi.rdi_mask |= SN_DG_OP_ADD;
   1027           1.1  lukem 
   1028           1.1  lukem 						} else if ( strcasecmp( ops[ j ], "bind" ) == 0 ) {
   1029           1.1  lukem 							rdi.rdi_mask |= SN_DG_OP_BIND;
   1030           1.1  lukem 
   1031           1.1  lukem 						} else if ( strcasecmp( ops[ j ], "compare" ) == 0 ) {
   1032           1.1  lukem 							rdi.rdi_mask |= SN_DG_OP_COMPARE;
   1033           1.1  lukem 
   1034           1.1  lukem 						} else if ( strcasecmp( ops[ j ], "delete" ) == 0 ) {
   1035           1.1  lukem 							rdi.rdi_mask |= SN_DG_OP_DELETE;
   1036           1.1  lukem 
   1037           1.1  lukem 						} else if ( strcasecmp( ops[ j ], "modify" ) == 0 ) {
   1038           1.1  lukem 							rdi.rdi_mask |= SN_DG_OP_MODIFY;
   1039           1.1  lukem 
   1040           1.1  lukem 						} else if ( strcasecmp( ops[ j ], "rename" ) == 0
   1041           1.1  lukem 							|| strcasecmp( ops[ j ], "modrdn" ) == 0 )
   1042           1.1  lukem 						{
   1043           1.1  lukem 							rdi.rdi_mask |= SN_DG_OP_RENAME;
   1044           1.1  lukem 
   1045           1.1  lukem 						} else if ( strcasecmp( ops[ j ], "search" ) == 0 ) {
   1046           1.1  lukem 							rdi.rdi_mask |= SN_DG_OP_SEARCH;
   1047           1.1  lukem 
   1048           1.1  lukem 						} else if ( strcasecmp( ops[ j ], "extended" ) == 0 ) {
   1049           1.1  lukem 							rdi.rdi_mask |= SN_DG_EXTENDED;
   1050           1.1  lukem 
   1051           1.1  lukem 						} else if ( strcasecmp( ops[ j ], "auth" ) == 0 ) {
   1052           1.1  lukem 							rdi.rdi_mask |= SN_DG_OP_AUTH;
   1053           1.1  lukem 
   1054           1.1  lukem 						} else if ( strcasecmp( ops[ j ], "read" ) == 0 ) {
   1055           1.1  lukem 							rdi.rdi_mask |= SN_DG_OP_READ;
   1056           1.1  lukem 
   1057           1.1  lukem 						} else if ( strcasecmp( ops[ j ], "write" ) == 0 ) {
   1058           1.1  lukem 							rdi.rdi_mask |= SN_DG_OP_WRITE;
   1059           1.1  lukem 
   1060           1.1  lukem 						} else if ( strcasecmp( ops[ j ], "all" ) == 0 ) {
   1061           1.1  lukem 							rdi.rdi_mask |= SN_DG_OP_ALL;
   1062           1.1  lukem 
   1063           1.1  lukem 						} else {
   1064       1.1.1.2  lukem 							snprintf( c->cr_msg, sizeof(c->cr_msg),
   1065       1.1.1.2  lukem 								"unknown op \"%s\"",
   1066           1.1  lukem 								ops[ j ] );
   1067           1.1  lukem 							ldap_charray_free( ops );
   1068       1.1.1.2  lukem 							Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1069       1.1.1.2  lukem 								c->log, c->cr_msg, 0 );
   1070       1.1.1.2  lukem 							return ARG_BAD_CONF;
   1071           1.1  lukem 						}
   1072           1.1  lukem 					}
   1073           1.1  lukem 
   1074           1.1  lukem 					ldap_charray_free( ops );
   1075           1.1  lukem 
   1076       1.1.1.2  lukem 				} else if ( strncasecmp( c->argv[ i ], "text=", STRLENOF( "text=" ) ) == 0 )
   1077           1.1  lukem 				{
   1078           1.1  lukem 					if ( !BER_BVISNULL( &rdi.rdi_text ) ) {
   1079       1.1.1.2  lukem 						snprintf( c->cr_msg, sizeof(c->cr_msg),
   1080       1.1.1.2  lukem 							"\"text\" already provided" );
   1081       1.1.1.2  lukem 						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1082       1.1.1.2  lukem 							c->log, c->cr_msg, 0 );
   1083       1.1.1.2  lukem 						return ARG_BAD_CONF;
   1084           1.1  lukem 					}
   1085       1.1.1.2  lukem 					ber_str2bv( &c->argv[ i ][ STRLENOF( "text=" ) ], 0, 1, &rdi.rdi_text );
   1086           1.1  lukem 
   1087       1.1.1.2  lukem 				} else if ( strncasecmp( c->argv[ i ], "matched=", STRLENOF( "matched=" ) ) == 0 )
   1088           1.1  lukem 				{
   1089           1.1  lukem 					struct berval	dn;
   1090           1.1  lukem 
   1091           1.1  lukem 					if ( !BER_BVISNULL( &rdi.rdi_matched ) ) {
   1092       1.1.1.2  lukem 						snprintf( c->cr_msg, sizeof(c->cr_msg),
   1093       1.1.1.2  lukem 							"\"matched\" already provided" );
   1094       1.1.1.2  lukem 						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1095       1.1.1.2  lukem 							c->log, c->cr_msg, 0 );
   1096       1.1.1.2  lukem 						return ARG_BAD_CONF;
   1097           1.1  lukem 					}
   1098       1.1.1.2  lukem 					ber_str2bv( &c->argv[ i ][ STRLENOF( "matched=" ) ], 0, 0, &dn );
   1099           1.1  lukem 					if ( dnPretty( NULL, &dn, &rdi.rdi_matched, NULL ) != LDAP_SUCCESS ) {
   1100       1.1.1.2  lukem 						snprintf( c->cr_msg, sizeof(c->cr_msg),
   1101       1.1.1.2  lukem 							"unable to prettify matched DN \"%s\"",
   1102       1.1.1.2  lukem 							&c->argv[ i ][ STRLENOF( "matched=" ) ] );
   1103       1.1.1.2  lukem 						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1104       1.1.1.2  lukem 							c->log, c->cr_msg, 0 );
   1105       1.1.1.2  lukem 						return ARG_BAD_CONF;
   1106           1.1  lukem 					}
   1107           1.1  lukem 
   1108       1.1.1.2  lukem 				} else if ( strncasecmp( c->argv[ i ], "ref=", STRLENOF( "ref=" ) ) == 0 )
   1109           1.1  lukem 				{
   1110           1.1  lukem 					char		**refs;
   1111           1.1  lukem 					int		j;
   1112           1.1  lukem 
   1113           1.1  lukem 					if ( rdi.rdi_ref != NULL ) {
   1114       1.1.1.2  lukem 						snprintf( c->cr_msg, sizeof(c->cr_msg),
   1115       1.1.1.2  lukem 							"\"ref\" already provided" );
   1116       1.1.1.2  lukem 						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1117       1.1.1.2  lukem 							c->log, c->cr_msg, 0 );
   1118       1.1.1.2  lukem 						return ARG_BAD_CONF;
   1119           1.1  lukem 					}
   1120           1.1  lukem 
   1121           1.1  lukem 					if ( rdi.rdi_err != LDAP_REFERRAL ) {
   1122       1.1.1.2  lukem 						snprintf( c->cr_msg, sizeof(c->cr_msg),
   1123       1.1.1.2  lukem 							"providing \"ref\" "
   1124       1.1.1.2  lukem 							"along with a non-referral "
   1125       1.1.1.2  lukem 							"resultCode may cause slapd failures "
   1126       1.1.1.2  lukem 							"related to internal checks" );
   1127       1.1.1.2  lukem 						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1128       1.1.1.2  lukem 							c->log, c->cr_msg, 0 );
   1129           1.1  lukem 					}
   1130           1.1  lukem 
   1131       1.1.1.2  lukem 					refs = ldap_str2charray( &c->argv[ i ][ STRLENOF( "ref=" ) ], " " );
   1132           1.1  lukem 					assert( refs != NULL );
   1133           1.1  lukem 
   1134           1.1  lukem 					for ( j = 0; refs[ j ] != NULL; j++ ) {
   1135           1.1  lukem 						struct berval	bv;
   1136           1.1  lukem 
   1137           1.1  lukem 						ber_str2bv( refs[ j ], 0, 1, &bv );
   1138           1.1  lukem 						ber_bvarray_add( &rdi.rdi_ref, &bv );
   1139           1.1  lukem 					}
   1140           1.1  lukem 
   1141           1.1  lukem 					ldap_charray_free( refs );
   1142           1.1  lukem 
   1143       1.1.1.2  lukem 				} else if ( strncasecmp( c->argv[ i ], "sleeptime=", STRLENOF( "sleeptime=" ) ) == 0 )
   1144           1.1  lukem 				{
   1145           1.1  lukem 					if ( rdi.rdi_sleeptime != 0 ) {
   1146       1.1.1.2  lukem 						snprintf( c->cr_msg, sizeof(c->cr_msg),
   1147       1.1.1.2  lukem 							"\"sleeptime\" already provided" );
   1148       1.1.1.2  lukem 						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1149       1.1.1.2  lukem 							c->log, c->cr_msg, 0 );
   1150       1.1.1.2  lukem 						return ARG_BAD_CONF;
   1151           1.1  lukem 					}
   1152           1.1  lukem 
   1153       1.1.1.2  lukem 					if ( lutil_atoi( &rdi.rdi_sleeptime, &c->argv[ i ][ STRLENOF( "sleeptime=" ) ] ) ) {
   1154       1.1.1.2  lukem 						snprintf( c->cr_msg, sizeof(c->cr_msg),
   1155       1.1.1.2  lukem 							"unable to parse \"sleeptime=%s\"",
   1156       1.1.1.2  lukem 							&c->argv[ i ][ STRLENOF( "sleeptime=" ) ] );
   1157       1.1.1.2  lukem 						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1158       1.1.1.2  lukem 							c->log, c->cr_msg, 0 );
   1159       1.1.1.2  lukem 						return ARG_BAD_CONF;
   1160           1.1  lukem 					}
   1161           1.1  lukem 
   1162       1.1.1.2  lukem 				} else if ( strncasecmp( c->argv[ i ], "unsolicited=", STRLENOF( "unsolicited=" ) ) == 0 )
   1163           1.1  lukem 				{
   1164           1.1  lukem 					char		*data;
   1165           1.1  lukem 
   1166           1.1  lukem 					if ( !BER_BVISNULL( &rdi.rdi_unsolicited_oid ) ) {
   1167       1.1.1.2  lukem 						snprintf( c->cr_msg, sizeof(c->cr_msg),
   1168       1.1.1.2  lukem 							"\"unsolicited\" already provided" );
   1169       1.1.1.2  lukem 						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1170       1.1.1.2  lukem 							c->log, c->cr_msg, 0 );
   1171       1.1.1.2  lukem 						return ARG_BAD_CONF;
   1172           1.1  lukem 					}
   1173           1.1  lukem 
   1174       1.1.1.2  lukem 					data = strchr( &c->argv[ i ][ STRLENOF( "unsolicited=" ) ], ':' );
   1175           1.1  lukem 					if ( data != NULL ) {
   1176           1.1  lukem 						struct berval	oid;
   1177           1.1  lukem 
   1178       1.1.1.2  lukem 						if ( ldif_parse_line2( &c->argv[ i ][ STRLENOF( "unsolicited=" ) ],
   1179           1.1  lukem 							&oid, &rdi.rdi_unsolicited_data, NULL ) )
   1180           1.1  lukem 						{
   1181       1.1.1.2  lukem 							snprintf( c->cr_msg, sizeof(c->cr_msg),
   1182       1.1.1.2  lukem 								"unable to parse \"unsolicited\"" );
   1183       1.1.1.2  lukem 							Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1184       1.1.1.2  lukem 								c->log, c->cr_msg, 0 );
   1185       1.1.1.2  lukem 							return ARG_BAD_CONF;
   1186           1.1  lukem 						}
   1187           1.1  lukem 
   1188           1.1  lukem 						ber_dupbv( &rdi.rdi_unsolicited_oid, &oid );
   1189           1.1  lukem 
   1190           1.1  lukem 					} else {
   1191       1.1.1.2  lukem 						ber_str2bv( &c->argv[ i ][ STRLENOF( "unsolicited=" ) ], 0, 1,
   1192           1.1  lukem 							&rdi.rdi_unsolicited_oid );
   1193           1.1  lukem 					}
   1194           1.1  lukem 
   1195       1.1.1.2  lukem 				} else if ( strncasecmp( c->argv[ i ], "flags=", STRLENOF( "flags=" ) ) == 0 )
   1196           1.1  lukem 				{
   1197       1.1.1.2  lukem 					char *arg = &c->argv[ i ][ STRLENOF( "flags=" ) ];
   1198           1.1  lukem 					if ( strcasecmp( arg, "disconnect" ) == 0 ) {
   1199           1.1  lukem 						rdi.rdi_flags |= RDI_PRE_DISCONNECT;
   1200           1.1  lukem 
   1201           1.1  lukem 					} else if ( strcasecmp( arg, "pre-disconnect" ) == 0 ) {
   1202           1.1  lukem 						rdi.rdi_flags |= RDI_PRE_DISCONNECT;
   1203           1.1  lukem 
   1204           1.1  lukem 					} else if ( strcasecmp( arg, "post-disconnect" ) == 0 ) {
   1205           1.1  lukem 						rdi.rdi_flags |= RDI_POST_DISCONNECT;
   1206           1.1  lukem 
   1207           1.1  lukem 					} else {
   1208       1.1.1.2  lukem 						snprintf( c->cr_msg, sizeof(c->cr_msg),
   1209       1.1.1.2  lukem 							"unknown flag \"%s\"", arg );
   1210       1.1.1.2  lukem 						Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1211       1.1.1.2  lukem 							c->log, c->cr_msg, 0 );
   1212       1.1.1.2  lukem 						return ARG_BAD_CONF;
   1213           1.1  lukem 					}
   1214           1.1  lukem 
   1215           1.1  lukem 				} else {
   1216       1.1.1.2  lukem 					snprintf( c->cr_msg, sizeof(c->cr_msg),
   1217       1.1.1.2  lukem 						"unknown option \"%s\"",
   1218       1.1.1.2  lukem 						c->argv[ i ] );
   1219       1.1.1.2  lukem 					Debug( LDAP_DEBUG_CONFIG, "%s: retcode: %s\n",
   1220       1.1.1.2  lukem 						c->log, c->cr_msg, 0 );
   1221       1.1.1.2  lukem 					return ARG_BAD_CONF;
   1222           1.1  lukem 				}
   1223           1.1  lukem 			}
   1224           1.1  lukem 		}
   1225           1.1  lukem 
   1226       1.1.1.2  lukem 		rdi.rdi_line.bv_len = 2*(c->argc - 1) + c->argc - 2;
   1227       1.1.1.2  lukem 		for ( i = 1; i < c->argc; i++ ) {
   1228       1.1.1.2  lukem 			rdi.rdi_line.bv_len += strlen( c->argv[ i ] );
   1229       1.1.1.2  lukem 		}
   1230       1.1.1.2  lukem 		next = rdi.rdi_line.bv_val = ch_malloc( rdi.rdi_line.bv_len + 1 );
   1231       1.1.1.2  lukem 
   1232       1.1.1.2  lukem 		for ( i = 1; i < c->argc; i++ ) {
   1233       1.1.1.2  lukem 			*next++ = '"';
   1234       1.1.1.2  lukem 			next = lutil_strcopy( next, c->argv[ i ] );
   1235       1.1.1.2  lukem 			*next++ = '"';
   1236       1.1.1.2  lukem 			*next++ = ' ';
   1237       1.1.1.2  lukem 		}
   1238       1.1.1.2  lukem 		*--next = '\0';
   1239       1.1.1.2  lukem 
   1240           1.1  lukem 		for ( rdip = &rd->rd_item; *rdip; rdip = &(*rdip)->rdi_next )
   1241           1.1  lukem 			/* go to last */ ;
   1242           1.1  lukem 
   1243           1.1  lukem 
   1244           1.1  lukem 		*rdip = ( retcode_item_t * )ch_malloc( sizeof( retcode_item_t ) );
   1245           1.1  lukem 		*(*rdip) = rdi;
   1246           1.1  lukem 
   1247       1.1.1.2  lukem 		rc = 0;
   1248       1.1.1.2  lukem 		} break;
   1249           1.1  lukem 
   1250       1.1.1.2  lukem 	default:
   1251       1.1.1.2  lukem 		rc = SLAP_CONF_UNKNOWN;
   1252       1.1.1.2  lukem 		break;
   1253           1.1  lukem 	}
   1254           1.1  lukem 
   1255       1.1.1.2  lukem 	return rc;
   1256           1.1  lukem }
   1257           1.1  lukem 
   1258           1.1  lukem static int
   1259           1.1  lukem retcode_db_open( BackendDB *be, ConfigReply *cr)
   1260           1.1  lukem {
   1261           1.1  lukem 	slap_overinst	*on = (slap_overinst *)be->bd_info;
   1262           1.1  lukem 	retcode_t	*rd = (retcode_t *)on->on_bi.bi_private;
   1263           1.1  lukem 
   1264           1.1  lukem 	retcode_item_t	*rdi;
   1265           1.1  lukem 
   1266           1.1  lukem 	for ( rdi = rd->rd_item; rdi; rdi = rdi->rdi_next ) {
   1267           1.1  lukem 		LDAPRDN			rdn = NULL;
   1268           1.1  lukem 		int			rc, j;
   1269           1.1  lukem 		char*			p;
   1270           1.1  lukem 		struct berval		val[ 3 ];
   1271           1.1  lukem 		char			buf[ SLAP_TEXT_BUFLEN ];
   1272           1.1  lukem 
   1273           1.1  lukem 		/* DN */
   1274           1.1  lukem 		rdi->rdi_e.e_name = rdi->rdi_dn;
   1275           1.1  lukem 		rdi->rdi_e.e_nname = rdi->rdi_ndn;
   1276           1.1  lukem 
   1277           1.1  lukem 		/* objectClass */
   1278           1.1  lukem 		val[ 0 ] = oc_errObject->soc_cname;
   1279           1.1  lukem 		val[ 1 ] = slap_schema.si_oc_extensibleObject->soc_cname;
   1280           1.1  lukem 		BER_BVZERO( &val[ 2 ] );
   1281           1.1  lukem 
   1282           1.1  lukem 		attr_merge( &rdi->rdi_e, slap_schema.si_ad_objectClass, val, NULL );
   1283           1.1  lukem 
   1284           1.1  lukem 		/* RDN avas */
   1285           1.1  lukem 		rc = ldap_bv2rdn( &rdi->rdi_dn, &rdn, (char **) &p,
   1286           1.1  lukem 				LDAP_DN_FORMAT_LDAP );
   1287           1.1  lukem 
   1288           1.1  lukem 		assert( rc == LDAP_SUCCESS );
   1289           1.1  lukem 
   1290           1.1  lukem 		for ( j = 0; rdn[ j ]; j++ ) {
   1291           1.1  lukem 			LDAPAVA			*ava = rdn[ j ];
   1292           1.1  lukem 			AttributeDescription	*ad = NULL;
   1293           1.1  lukem 			const char		*text;
   1294           1.1  lukem 
   1295           1.1  lukem 			rc = slap_bv2ad( &ava->la_attr, &ad, &text );
   1296           1.1  lukem 			assert( rc == LDAP_SUCCESS );
   1297           1.1  lukem 
   1298           1.1  lukem 			attr_merge_normalize_one( &rdi->rdi_e, ad,
   1299           1.1  lukem 					&ava->la_value, NULL );
   1300           1.1  lukem 		}
   1301           1.1  lukem 
   1302           1.1  lukem 		ldap_rdnfree( rdn );
   1303           1.1  lukem 
   1304           1.1  lukem 		/* error code */
   1305           1.1  lukem 		snprintf( buf, sizeof( buf ), "%d", rdi->rdi_err );
   1306           1.1  lukem 		ber_str2bv( buf, 0, 0, &val[ 0 ] );
   1307           1.1  lukem 
   1308           1.1  lukem 		attr_merge_one( &rdi->rdi_e, ad_errCode, &val[ 0 ], NULL );
   1309           1.1  lukem 
   1310           1.1  lukem 		if ( rdi->rdi_ref != NULL ) {
   1311           1.1  lukem 			attr_merge_normalize( &rdi->rdi_e, slap_schema.si_ad_ref,
   1312           1.1  lukem 				rdi->rdi_ref, NULL );
   1313           1.1  lukem 		}
   1314           1.1  lukem 
   1315           1.1  lukem 		/* text */
   1316           1.1  lukem 		if ( !BER_BVISNULL( &rdi->rdi_text ) ) {
   1317           1.1  lukem 			val[ 0 ] = rdi->rdi_text;
   1318           1.1  lukem 
   1319           1.1  lukem 			attr_merge_normalize_one( &rdi->rdi_e, ad_errText, &val[ 0 ], NULL );
   1320           1.1  lukem 		}
   1321           1.1  lukem 
   1322           1.1  lukem 		/* matched */
   1323           1.1  lukem 		if ( !BER_BVISNULL( &rdi->rdi_matched ) ) {
   1324           1.1  lukem 			val[ 0 ] = rdi->rdi_matched;
   1325           1.1  lukem 
   1326           1.1  lukem 			attr_merge_normalize_one( &rdi->rdi_e, ad_errMatchedDN, &val[ 0 ], NULL );
   1327           1.1  lukem 		}
   1328           1.1  lukem 
   1329           1.1  lukem 		/* sleep time */
   1330           1.1  lukem 		if ( rdi->rdi_sleeptime ) {
   1331           1.1  lukem 			snprintf( buf, sizeof( buf ), "%d", rdi->rdi_sleeptime );
   1332           1.1  lukem 			ber_str2bv( buf, 0, 0, &val[ 0 ] );
   1333           1.1  lukem 
   1334           1.1  lukem 			attr_merge_one( &rdi->rdi_e, ad_errSleepTime, &val[ 0 ], NULL );
   1335           1.1  lukem 		}
   1336           1.1  lukem 
   1337           1.1  lukem 		/* operations */
   1338           1.1  lukem 		if ( rdi->rdi_mask & SN_DG_OP_ADD ) {
   1339           1.1  lukem 			BER_BVSTR( &val[ 0 ], "add" );
   1340           1.1  lukem 			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
   1341           1.1  lukem 		}
   1342           1.1  lukem 
   1343           1.1  lukem 		if ( rdi->rdi_mask & SN_DG_OP_BIND ) {
   1344           1.1  lukem 			BER_BVSTR( &val[ 0 ], "bind" );
   1345           1.1  lukem 			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
   1346           1.1  lukem 		}
   1347           1.1  lukem 
   1348           1.1  lukem 		if ( rdi->rdi_mask & SN_DG_OP_COMPARE ) {
   1349           1.1  lukem 			BER_BVSTR( &val[ 0 ], "compare" );
   1350           1.1  lukem 			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
   1351           1.1  lukem 		}
   1352           1.1  lukem 
   1353           1.1  lukem 		if ( rdi->rdi_mask & SN_DG_OP_DELETE ) {
   1354           1.1  lukem 			BER_BVSTR( &val[ 0 ], "delete" );
   1355           1.1  lukem 			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
   1356           1.1  lukem 		}
   1357           1.1  lukem 
   1358           1.1  lukem 		if ( rdi->rdi_mask & SN_DG_EXTENDED ) {
   1359           1.1  lukem 			BER_BVSTR( &val[ 0 ], "extended" );
   1360           1.1  lukem 			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
   1361           1.1  lukem 		}
   1362           1.1  lukem 
   1363           1.1  lukem 		if ( rdi->rdi_mask & SN_DG_OP_MODIFY ) {
   1364           1.1  lukem 			BER_BVSTR( &val[ 0 ], "modify" );
   1365           1.1  lukem 			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
   1366           1.1  lukem 		}
   1367           1.1  lukem 
   1368           1.1  lukem 		if ( rdi->rdi_mask & SN_DG_OP_RENAME ) {
   1369           1.1  lukem 			BER_BVSTR( &val[ 0 ], "rename" );
   1370           1.1  lukem 			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
   1371           1.1  lukem 		}
   1372           1.1  lukem 
   1373           1.1  lukem 		if ( rdi->rdi_mask & SN_DG_OP_SEARCH ) {
   1374           1.1  lukem 			BER_BVSTR( &val[ 0 ], "search" );
   1375           1.1  lukem 			attr_merge_normalize_one( &rdi->rdi_e, ad_errOp, &val[ 0 ], NULL );
   1376           1.1  lukem 		}
   1377           1.1  lukem 	}
   1378           1.1  lukem 
   1379           1.1  lukem 	return 0;
   1380           1.1  lukem }
   1381           1.1  lukem 
   1382           1.1  lukem static int
   1383           1.1  lukem retcode_db_destroy( BackendDB *be, ConfigReply *cr )
   1384           1.1  lukem {
   1385           1.1  lukem 	slap_overinst	*on = (slap_overinst *)be->bd_info;
   1386           1.1  lukem 	retcode_t	*rd = (retcode_t *)on->on_bi.bi_private;
   1387           1.1  lukem 
   1388           1.1  lukem 	if ( rd ) {
   1389           1.1  lukem 		retcode_item_t	*rdi, *next;
   1390           1.1  lukem 
   1391           1.1  lukem 		for ( rdi = rd->rd_item; rdi != NULL; rdi = next ) {
   1392           1.1  lukem 			next = rdi->rdi_next;
   1393       1.1.1.2  lukem 			retcode_item_destroy( rdi );
   1394           1.1  lukem 		}
   1395           1.1  lukem 
   1396           1.1  lukem 		if ( !BER_BVISNULL( &rd->rd_pdn ) ) {
   1397           1.1  lukem 			ber_memfree( rd->rd_pdn.bv_val );
   1398           1.1  lukem 		}
   1399           1.1  lukem 
   1400           1.1  lukem 		if ( !BER_BVISNULL( &rd->rd_npdn ) ) {
   1401           1.1  lukem 			ber_memfree( rd->rd_npdn.bv_val );
   1402           1.1  lukem 		}
   1403           1.1  lukem 
   1404           1.1  lukem 		ber_memfree( rd );
   1405           1.1  lukem 	}
   1406           1.1  lukem 
   1407           1.1  lukem 	return 0;
   1408           1.1  lukem }
   1409           1.1  lukem 
   1410           1.1  lukem #if SLAPD_OVER_RETCODE == SLAPD_MOD_DYNAMIC
   1411           1.1  lukem static
   1412           1.1  lukem #endif /* SLAPD_OVER_RETCODE == SLAPD_MOD_DYNAMIC */
   1413           1.1  lukem int
   1414           1.1  lukem retcode_initialize( void )
   1415           1.1  lukem {
   1416           1.1  lukem 	int		i, code;
   1417           1.1  lukem 
   1418           1.1  lukem 	static struct {
   1419           1.1  lukem 		char			*desc;
   1420           1.1  lukem 		AttributeDescription	**ad;
   1421           1.1  lukem 	} retcode_at[] = {
   1422           1.1  lukem 	        { "( 1.3.6.1.4.1.4203.666.11.4.1.1 "
   1423           1.1  lukem 		        "NAME ( 'errCode' ) "
   1424           1.1  lukem 		        "DESC 'LDAP error code' "
   1425           1.1  lukem 		        "EQUALITY integerMatch "
   1426           1.1  lukem 		        "ORDERING integerOrderingMatch "
   1427           1.1  lukem 		        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 "
   1428           1.1  lukem 			"SINGLE-VALUE )",
   1429           1.1  lukem 			&ad_errCode },
   1430           1.1  lukem 		{ "( 1.3.6.1.4.1.4203.666.11.4.1.2 "
   1431           1.1  lukem 			"NAME ( 'errOp' ) "
   1432           1.1  lukem 			"DESC 'Operations the errObject applies to' "
   1433           1.1  lukem 			"EQUALITY caseIgnoreMatch "
   1434           1.1  lukem 			"SUBSTR caseIgnoreSubstringsMatch "
   1435           1.1  lukem 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )",
   1436           1.1  lukem 			&ad_errOp},
   1437           1.1  lukem 		{ "( 1.3.6.1.4.1.4203.666.11.4.1.3 "
   1438           1.1  lukem 			"NAME ( 'errText' ) "
   1439           1.1  lukem 			"DESC 'LDAP error textual description' "
   1440           1.1  lukem 			"EQUALITY caseIgnoreMatch "
   1441           1.1  lukem 			"SUBSTR caseIgnoreSubstringsMatch "
   1442           1.1  lukem 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 "
   1443           1.1  lukem 			"SINGLE-VALUE )",
   1444           1.1  lukem 			&ad_errText },
   1445           1.1  lukem 		{ "( 1.3.6.1.4.1.4203.666.11.4.1.4 "
   1446           1.1  lukem 			"NAME ( 'errSleepTime' ) "
   1447           1.1  lukem 			"DESC 'Time to wait before returning the error' "
   1448           1.1  lukem 			"EQUALITY integerMatch "
   1449           1.1  lukem 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 "
   1450           1.1  lukem 			"SINGLE-VALUE )",
   1451           1.1  lukem 			&ad_errSleepTime },
   1452           1.1  lukem 		{ "( 1.3.6.1.4.1.4203.666.11.4.1.5 "
   1453           1.1  lukem 			"NAME ( 'errMatchedDN' ) "
   1454           1.1  lukem 			"DESC 'Value to be returned as matched DN' "
   1455           1.1  lukem 			"EQUALITY distinguishedNameMatch "
   1456           1.1  lukem 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 "
   1457           1.1  lukem 			"SINGLE-VALUE )",
   1458           1.1  lukem 			&ad_errMatchedDN },
   1459           1.1  lukem 		{ "( 1.3.6.1.4.1.4203.666.11.4.1.6 "
   1460           1.1  lukem 			"NAME ( 'errUnsolicitedOID' ) "
   1461           1.1  lukem 			"DESC 'OID to be returned within unsolicited response' "
   1462           1.1  lukem 			"EQUALITY objectIdentifierMatch "
   1463           1.1  lukem 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 "
   1464           1.1  lukem 			"SINGLE-VALUE )",
   1465           1.1  lukem 			&ad_errUnsolicitedOID },
   1466           1.1  lukem 		{ "( 1.3.6.1.4.1.4203.666.11.4.1.7 "
   1467           1.1  lukem 			"NAME ( 'errUnsolicitedData' ) "
   1468           1.1  lukem 			"DESC 'Data to be returned within unsolicited response' "
   1469           1.1  lukem 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 "
   1470           1.1  lukem 			"SINGLE-VALUE )",
   1471           1.1  lukem 			&ad_errUnsolicitedData },
   1472           1.1  lukem 		{ "( 1.3.6.1.4.1.4203.666.11.4.1.8 "
   1473           1.1  lukem 			"NAME ( 'errDisconnect' ) "
   1474           1.1  lukem 			"DESC 'Disconnect without notice' "
   1475           1.1  lukem 			"SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 "
   1476           1.1  lukem 			"SINGLE-VALUE )",
   1477           1.1  lukem 			&ad_errDisconnect },
   1478           1.1  lukem 		{ NULL }
   1479           1.1  lukem 	};
   1480           1.1  lukem 
   1481           1.1  lukem 	static struct {
   1482           1.1  lukem 		char		*desc;
   1483           1.1  lukem 		ObjectClass	**oc;
   1484           1.1  lukem 	} retcode_oc[] = {
   1485           1.1  lukem 		{ "( 1.3.6.1.4.1.4203.666.11.4.3.0 "
   1486           1.1  lukem 			"NAME ( 'errAbsObject' ) "
   1487           1.1  lukem 			"SUP top ABSTRACT "
   1488           1.1  lukem 			"MUST ( errCode ) "
   1489           1.1  lukem 			"MAY ( "
   1490           1.1  lukem 				"cn "
   1491           1.1  lukem 				"$ description "
   1492           1.1  lukem 				"$ errOp "
   1493           1.1  lukem 				"$ errText "
   1494           1.1  lukem 				"$ errSleepTime "
   1495           1.1  lukem 				"$ errMatchedDN "
   1496           1.1  lukem 				"$ errUnsolicitedOID "
   1497           1.1  lukem 				"$ errUnsolicitedData "
   1498           1.1  lukem 				"$ errDisconnect "
   1499           1.1  lukem 			") )",
   1500           1.1  lukem 			&oc_errAbsObject },
   1501           1.1  lukem 		{ "( 1.3.6.1.4.1.4203.666.11.4.3.1 "
   1502           1.1  lukem 			"NAME ( 'errObject' ) "
   1503           1.1  lukem 			"SUP errAbsObject STRUCTURAL "
   1504           1.1  lukem 			")",
   1505           1.1  lukem 			&oc_errObject },
   1506           1.1  lukem 		{ "( 1.3.6.1.4.1.4203.666.11.4.3.2 "
   1507           1.1  lukem 			"NAME ( 'errAuxObject' ) "
   1508           1.1  lukem 			"SUP errAbsObject AUXILIARY "
   1509           1.1  lukem 			")",
   1510           1.1  lukem 			&oc_errAuxObject },
   1511           1.1  lukem 		{ NULL }
   1512           1.1  lukem 	};
   1513           1.1  lukem 
   1514           1.1  lukem 
   1515           1.1  lukem 	for ( i = 0; retcode_at[ i ].desc != NULL; i++ ) {
   1516           1.1  lukem 		code = register_at( retcode_at[ i ].desc, retcode_at[ i ].ad, 0 );
   1517           1.1  lukem 		if ( code ) {
   1518           1.1  lukem 			Debug( LDAP_DEBUG_ANY,
   1519           1.1  lukem 				"retcode: register_at failed\n", 0, 0, 0 );
   1520           1.1  lukem 			return code;
   1521           1.1  lukem 		}
   1522           1.1  lukem 
   1523           1.1  lukem 		(*retcode_at[ i ].ad)->ad_type->sat_flags |= SLAP_AT_HIDE;
   1524           1.1  lukem 	}
   1525           1.1  lukem 
   1526           1.1  lukem 	for ( i = 0; retcode_oc[ i ].desc != NULL; i++ ) {
   1527           1.1  lukem 		code = register_oc( retcode_oc[ i ].desc, retcode_oc[ i ].oc, 0 );
   1528           1.1  lukem 		if ( code ) {
   1529           1.1  lukem 			Debug( LDAP_DEBUG_ANY,
   1530           1.1  lukem 				"retcode: register_oc failed\n", 0, 0, 0 );
   1531           1.1  lukem 			return code;
   1532           1.1  lukem 		}
   1533           1.1  lukem 
   1534           1.1  lukem 		(*retcode_oc[ i ].oc)->soc_flags |= SLAP_OC_HIDE;
   1535           1.1  lukem 	}
   1536           1.1  lukem 
   1537           1.1  lukem 	retcode.on_bi.bi_type = "retcode";
   1538           1.1  lukem 
   1539           1.1  lukem 	retcode.on_bi.bi_db_init = retcode_db_init;
   1540           1.1  lukem 	retcode.on_bi.bi_db_open = retcode_db_open;
   1541           1.1  lukem 	retcode.on_bi.bi_db_destroy = retcode_db_destroy;
   1542           1.1  lukem 
   1543           1.1  lukem 	retcode.on_bi.bi_op_add = retcode_op_func;
   1544           1.1  lukem 	retcode.on_bi.bi_op_bind = retcode_op_func;
   1545           1.1  lukem 	retcode.on_bi.bi_op_compare = retcode_op_func;
   1546           1.1  lukem 	retcode.on_bi.bi_op_delete = retcode_op_func;
   1547           1.1  lukem 	retcode.on_bi.bi_op_modify = retcode_op_func;
   1548           1.1  lukem 	retcode.on_bi.bi_op_modrdn = retcode_op_func;
   1549           1.1  lukem 	retcode.on_bi.bi_op_search = retcode_op_func;
   1550           1.1  lukem 
   1551           1.1  lukem 	retcode.on_bi.bi_extended = retcode_op_func;
   1552           1.1  lukem 
   1553           1.1  lukem 	retcode.on_response = retcode_response;
   1554           1.1  lukem 
   1555       1.1.1.2  lukem 	retcode.on_bi.bi_cf_ocs = rcocs;
   1556       1.1.1.2  lukem 
   1557       1.1.1.2  lukem 	code = config_register_schema( rccfg, rcocs );
   1558       1.1.1.2  lukem 	if ( code ) {
   1559       1.1.1.2  lukem 		return code;
   1560       1.1.1.2  lukem 	}
   1561       1.1.1.2  lukem 
   1562           1.1  lukem 	return overlay_register( &retcode );
   1563           1.1  lukem }
   1564           1.1  lukem 
   1565           1.1  lukem #if SLAPD_OVER_RETCODE == SLAPD_MOD_DYNAMIC
   1566           1.1  lukem int
   1567           1.1  lukem init_module( int argc, char *argv[] )
   1568           1.1  lukem {
   1569           1.1  lukem 	return retcode_initialize();
   1570           1.1  lukem }
   1571           1.1  lukem #endif /* SLAPD_OVER_RETCODE == SLAPD_MOD_DYNAMIC */
   1572           1.1  lukem 
   1573           1.1  lukem #endif /* SLAPD_OVER_RETCODE */
   1574