Home | History | Annotate | Line # | Download | only in back-monitor
search.c revision 1.1.1.2
      1 /*	$NetBSD: search.c,v 1.1.1.2 2010/03/08 02:14:20 lukem Exp $	*/
      2 
      3 /* search.c - monitor backend search function */
      4 /* OpenLDAP: pkg/ldap/servers/slapd/back-monitor/search.c,v 1.39.2.6 2009/01/22 00:01:08 kurt Exp */
      5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
      6  *
      7  * Copyright 2001-2009 The OpenLDAP Foundation.
      8  * Portions Copyright 2001-2003 Pierangelo Masarati.
      9  * All rights reserved.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted only as authorized by the OpenLDAP
     13  * Public License.
     14  *
     15  * A copy of this license is available in file LICENSE in the
     16  * top-level directory of the distribution or, alternatively, at
     17  * <http://www.OpenLDAP.org/license.html>.
     18  */
     19 /* ACKNOWLEDGEMENTS:
     20  * This work was initially developed by Pierangelo Masarati for inclusion
     21  * in OpenLDAP Software.
     22  */
     23 
     24 #include "portable.h"
     25 
     26 #include <stdio.h>
     27 
     28 #include <ac/string.h>
     29 #include <ac/socket.h>
     30 
     31 #include "slap.h"
     32 #include "back-monitor.h"
     33 #include "proto-back-monitor.h"
     34 
     35 static int
     36 monitor_send_children(
     37 	Operation	*op,
     38 	SlapReply	*rs,
     39 	Entry		*e_parent,
     40 	int		sub )
     41 {
     42 	monitor_info_t	*mi = ( monitor_info_t * )op->o_bd->be_private;
     43 	Entry 			*e,
     44 				*e_tmp,
     45 				*e_ch = NULL,
     46 				*e_nonvolatile = NULL;
     47 	monitor_entry_t *mp;
     48 	int			rc,
     49 				nonvolatile = 0;
     50 
     51 	mp = ( monitor_entry_t * )e_parent->e_private;
     52 	e_nonvolatile = e = mp->mp_children;
     53 
     54 	if ( MONITOR_HAS_VOLATILE_CH( mp ) ) {
     55 		monitor_entry_create( op, rs, NULL, e_parent, &e_ch );
     56 	}
     57 	monitor_cache_release( mi, e_parent );
     58 
     59 	/* no volatile entries? */
     60 	if ( e_ch == NULL ) {
     61 		/* no persistent entries? return */
     62 		if ( e == NULL ) {
     63 			return LDAP_SUCCESS;
     64 		}
     65 
     66 	/* volatile entries */
     67 	} else {
     68 		/* if no persistent, return only volatile */
     69 		if ( e == NULL ) {
     70 			e = e_ch;
     71 
     72 		/* else append persistent to volatile */
     73 		} else {
     74 			e_tmp = e_ch;
     75 			do {
     76 				mp = ( monitor_entry_t * )e_tmp->e_private;
     77 				e_tmp = mp->mp_next;
     78 
     79 				if ( e_tmp == NULL ) {
     80 					mp->mp_next = e;
     81 					break;
     82 				}
     83 			} while ( e_tmp );
     84 			e = e_ch;
     85 		}
     86 	}
     87 
     88 	/* return entries */
     89 	for ( monitor_cache_lock( e ); e != NULL; ) {
     90 		monitor_entry_update( op, rs, e );
     91 
     92 		if ( op->o_abandon ) {
     93 			/* FIXME: may leak generated children */
     94 			if ( nonvolatile == 0 ) {
     95 				for ( e_tmp = e; e_tmp != NULL; ) {
     96 					mp = ( monitor_entry_t * )e_tmp->e_private;
     97 					e = e_tmp;
     98 					e_tmp = mp->mp_next;
     99 					monitor_cache_release( mi, e );
    100 
    101 					if ( e_tmp == e_nonvolatile ) {
    102 						break;
    103 					}
    104 				}
    105 
    106 			} else {
    107 				monitor_cache_release( mi, e );
    108 			}
    109 
    110 			return SLAPD_ABANDON;
    111 		}
    112 
    113 		rc = test_filter( op, e, op->oq_search.rs_filter );
    114 		if ( rc == LDAP_COMPARE_TRUE ) {
    115 			rs->sr_entry = e;
    116 			rs->sr_flags = 0;
    117 			rc = send_search_entry( op, rs );
    118 			rs->sr_entry = NULL;
    119 		}
    120 
    121 		mp = ( monitor_entry_t * )e->e_private;
    122 		e_tmp = mp->mp_next;
    123 
    124 		if ( sub ) {
    125 			rc = monitor_send_children( op, rs, e, sub );
    126 			if ( rc ) {
    127 				/* FIXME: may leak generated children */
    128 				if ( nonvolatile == 0 ) {
    129 					for ( ; e_tmp != NULL; ) {
    130 						mp = ( monitor_entry_t * )e_tmp->e_private;
    131 						e = e_tmp;
    132 						e_tmp = mp->mp_next;
    133 						monitor_cache_release( mi, e );
    134 
    135 						if ( e_tmp == e_nonvolatile ) {
    136 							break;
    137 						}
    138 					}
    139 				}
    140 
    141 				return( rc );
    142 			}
    143 		}
    144 
    145 		if ( e_tmp != NULL ) {
    146 			monitor_cache_lock( e_tmp );
    147 		}
    148 
    149 		if ( !sub ) {
    150 			/* otherwise the recursive call already released */
    151 			monitor_cache_release( mi, e );
    152 		}
    153 
    154 		e = e_tmp;
    155 		if ( e == e_nonvolatile ) {
    156 			nonvolatile = 1;
    157 		}
    158 	}
    159 
    160 	return LDAP_SUCCESS;
    161 }
    162 
    163 int
    164 monitor_back_search( Operation *op, SlapReply *rs )
    165 {
    166 	monitor_info_t	*mi = ( monitor_info_t * )op->o_bd->be_private;
    167 	int		rc = LDAP_SUCCESS;
    168 	Entry		*e = NULL, *matched = NULL;
    169 	slap_mask_t	mask;
    170 
    171 	Debug( LDAP_DEBUG_TRACE, "=> monitor_back_search\n", 0, 0, 0 );
    172 
    173 
    174 	/* get entry with reader lock */
    175 	monitor_cache_dn2entry( op, rs, &op->o_req_ndn, &e, &matched );
    176 	if ( e == NULL ) {
    177 		rs->sr_err = LDAP_NO_SUCH_OBJECT;
    178 		if ( matched ) {
    179 			if ( !access_allowed_mask( op, matched,
    180 					slap_schema.si_ad_entry,
    181 					NULL, ACL_DISCLOSE, NULL, NULL ) )
    182 			{
    183 				/* do nothing */ ;
    184 			} else {
    185 				rs->sr_matched = matched->e_dn;
    186 			}
    187 		}
    188 
    189 		send_ldap_result( op, rs );
    190 		if ( matched ) {
    191 			monitor_cache_release( mi, matched );
    192 			rs->sr_matched = NULL;
    193 		}
    194 
    195 		return rs->sr_err;
    196 	}
    197 
    198 	/* NOTE: __NEW__ "search" access is required
    199 	 * on searchBase object */
    200 	if ( !access_allowed_mask( op, e, slap_schema.si_ad_entry,
    201 				NULL, ACL_SEARCH, NULL, &mask ) )
    202 	{
    203 		monitor_cache_release( mi, e );
    204 
    205 		if ( !ACL_GRANT( mask, ACL_DISCLOSE ) ) {
    206 			rs->sr_err = LDAP_NO_SUCH_OBJECT;
    207 		} else {
    208 			rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
    209 		}
    210 
    211 		send_ldap_result( op, rs );
    212 
    213 		return rs->sr_err;
    214 	}
    215 
    216 	rs->sr_attrs = op->oq_search.rs_attrs;
    217 	switch ( op->oq_search.rs_scope ) {
    218 	case LDAP_SCOPE_BASE:
    219 		monitor_entry_update( op, rs, e );
    220 		rc = test_filter( op, e, op->oq_search.rs_filter );
    221  		if ( rc == LDAP_COMPARE_TRUE ) {
    222 			rs->sr_entry = e;
    223 			rs->sr_flags = 0;
    224 			send_search_entry( op, rs );
    225 			rs->sr_entry = NULL;
    226 		}
    227 		rc = LDAP_SUCCESS;
    228 		monitor_cache_release( mi, e );
    229 		break;
    230 
    231 	case LDAP_SCOPE_ONELEVEL:
    232 	case LDAP_SCOPE_SUBORDINATE:
    233 		rc = monitor_send_children( op, rs, e,
    234 			op->oq_search.rs_scope == LDAP_SCOPE_SUBORDINATE );
    235 		break;
    236 
    237 	case LDAP_SCOPE_SUBTREE:
    238 		monitor_entry_update( op, rs, e );
    239 		rc = test_filter( op, e, op->oq_search.rs_filter );
    240 		if ( rc == LDAP_COMPARE_TRUE ) {
    241 			rs->sr_entry = e;
    242 			rs->sr_flags = 0;
    243 			send_search_entry( op, rs );
    244 			rs->sr_entry = NULL;
    245 		}
    246 
    247 		rc = monitor_send_children( op, rs, e, 1 );
    248 		break;
    249 
    250 	default:
    251 		rc = LDAP_UNWILLING_TO_PERFORM;
    252 		monitor_cache_release( mi, e );
    253 	}
    254 
    255 	rs->sr_attrs = NULL;
    256 	rs->sr_err = rc;
    257 	if ( rs->sr_err != SLAPD_ABANDON ) {
    258 		send_ldap_result( op, rs );
    259 	}
    260 
    261 	return rs->sr_err;
    262 }
    263 
    264