Back to index

openldap  2.4.31
search.c
Go to the documentation of this file.
00001 /* search.c - monitor backend search function */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
00004  *
00005  * Copyright 2001-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 2001-2003 Pierangelo Masarati.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 /* ACKNOWLEDGEMENTS:
00018  * This work was initially developed by Pierangelo Masarati for inclusion
00019  * in OpenLDAP Software.
00020  */
00021 
00022 #include "portable.h"
00023 
00024 #include <stdio.h>
00025 
00026 #include <ac/string.h>
00027 #include <ac/socket.h>
00028 
00029 #include "slap.h"
00030 #include "back-monitor.h"
00031 #include "proto-back-monitor.h"
00032 
00033 static void
00034 monitor_find_children(
00035        Operation *op,
00036        SlapReply *rs,
00037        Entry *e_parent,
00038        Entry **nonv,
00039        Entry **vol
00040 )
00041 {
00042        monitor_entry_t *mp;
00043 
00044        mp = ( monitor_entry_t * )e_parent->e_private;
00045        *nonv = mp->mp_children;
00046 
00047        if ( MONITOR_HAS_VOLATILE_CH( mp ) ) {
00048               monitor_entry_create( op, rs, NULL, e_parent, vol );
00049        }
00050 }
00051 
00052 static int
00053 monitor_send_children(
00054        Operation     *op,
00055        SlapReply     *rs,
00056        Entry         *e_nonvolatile,
00057        Entry         *e_ch,
00058        int           sub )
00059 {
00060        monitor_info_t       *mi = ( monitor_info_t * )op->o_bd->be_private;
00061        Entry                *e,
00062                             *e_tmp;
00063        monitor_entry_t *mp;
00064        int                  rc,
00065                             nonvolatile = 0;
00066 
00067        e = e_nonvolatile;
00068 
00069        /* no volatile entries? */
00070        if ( e_ch == NULL ) {
00071               /* no persistent entries? return */
00072               if ( e == NULL ) {
00073                      return LDAP_SUCCESS;
00074               }
00075 
00076        /* volatile entries */
00077        } else {
00078               /* if no persistent, return only volatile */
00079               if ( e == NULL ) {
00080                      e = e_ch;
00081 
00082               /* else append persistent to volatile */
00083               } else {
00084                      e_tmp = e_ch;
00085                      do {
00086                             mp = ( monitor_entry_t * )e_tmp->e_private;
00087                             e_tmp = mp->mp_next;
00088        
00089                             if ( e_tmp == NULL ) {
00090                                    mp->mp_next = e;
00091                                    break;
00092                             }
00093                      } while ( e_tmp );
00094                      e = e_ch;
00095               }
00096        }
00097 
00098        /* return entries */
00099        for ( ; e != NULL; e = e_tmp ) {
00100               Entry *sub_nv = NULL, *sub_ch = NULL;
00101 
00102               monitor_cache_lock( e );
00103               monitor_entry_update( op, rs, e );
00104 
00105               if ( e == e_nonvolatile )
00106                      nonvolatile = 1;
00107 
00108               mp = ( monitor_entry_t * )e->e_private;
00109               e_tmp = mp->mp_next;
00110 
00111               if ( op->o_abandon ) {
00112                      monitor_cache_release( mi, e );
00113                      rc = SLAPD_ABANDON;
00114                      goto freeout;
00115               }
00116 
00117               if ( sub )
00118                      monitor_find_children( op, rs, e, &sub_nv, &sub_ch );
00119 
00120               rc = test_filter( op, e, op->oq_search.rs_filter );
00121               if ( rc == LDAP_COMPARE_TRUE ) {
00122                      rs->sr_entry = e;
00123                      rs->sr_flags = REP_ENTRY_MUSTRELEASE;
00124                      rc = send_search_entry( op, rs );
00125                      if ( rc ) {
00126                             for ( e = sub_ch; e != NULL; e = sub_nv ) {
00127                                    mp = ( monitor_entry_t * )e->e_private;
00128                                    sub_nv = mp->mp_next;
00129                                    monitor_cache_lock( e );
00130                                    monitor_cache_release( mi, e );
00131                             }
00132                             goto freeout;
00133                      }
00134               } else {
00135                      monitor_cache_release( mi, e );
00136               }
00137 
00138               if ( sub ) {
00139                      rc = monitor_send_children( op, rs, sub_nv, sub_ch, sub );
00140                      if ( rc ) {
00141 freeout:
00142                             if ( nonvolatile == 0 ) {
00143                                    for ( ; e_tmp != NULL; ) {
00144                                           mp = ( monitor_entry_t * )e_tmp->e_private;
00145                                           e = e_tmp;
00146                                           e_tmp = mp->mp_next;
00147                                           monitor_cache_lock( e );
00148                                           monitor_cache_release( mi, e );
00149        
00150                                           if ( e_tmp == e_nonvolatile ) {
00151                                                  break;
00152                                           }
00153                                    }
00154                             }
00155 
00156                             return( rc );
00157                      }
00158               }
00159        }
00160        
00161        return LDAP_SUCCESS;
00162 }
00163 
00164 int
00165 monitor_back_search( Operation *op, SlapReply *rs )
00166 {
00167        monitor_info_t       *mi = ( monitor_info_t * )op->o_bd->be_private;
00168        int           rc = LDAP_SUCCESS;
00169        Entry         *e = NULL, *matched = NULL;
00170        Entry         *e_nv = NULL, *e_ch = NULL;
00171        slap_mask_t   mask;
00172 
00173        Debug( LDAP_DEBUG_TRACE, "=> monitor_back_search\n", 0, 0, 0 );
00174 
00175 
00176        /* get entry with reader lock */
00177        monitor_cache_dn2entry( op, rs, &op->o_req_ndn, &e, &matched );
00178        if ( e == NULL ) {
00179               rs->sr_err = LDAP_NO_SUCH_OBJECT;
00180               if ( matched ) {
00181                      if ( !access_allowed_mask( op, matched,
00182                                    slap_schema.si_ad_entry,
00183                                    NULL, ACL_DISCLOSE, NULL, NULL ) )
00184                      {
00185                             /* do nothing */ ;
00186                      } else {
00187                             rs->sr_matched = matched->e_dn;
00188                      }
00189               }
00190 
00191               send_ldap_result( op, rs );
00192               if ( matched ) {
00193                      monitor_cache_release( mi, matched );
00194                      rs->sr_matched = NULL;
00195               }
00196 
00197               return rs->sr_err;
00198        }
00199 
00200        /* NOTE: __NEW__ "search" access is required
00201         * on searchBase object */
00202        if ( !access_allowed_mask( op, e, slap_schema.si_ad_entry,
00203                             NULL, ACL_SEARCH, NULL, &mask ) )
00204        {
00205               monitor_cache_release( mi, e );
00206 
00207               if ( !ACL_GRANT( mask, ACL_DISCLOSE ) ) {
00208                      rs->sr_err = LDAP_NO_SUCH_OBJECT;
00209               } else {
00210                      rs->sr_err = LDAP_INSUFFICIENT_ACCESS;
00211               }
00212 
00213               send_ldap_result( op, rs );
00214 
00215               return rs->sr_err;
00216        }
00217 
00218        rs->sr_attrs = op->oq_search.rs_attrs;
00219        switch ( op->oq_search.rs_scope ) {
00220        case LDAP_SCOPE_BASE:
00221               monitor_entry_update( op, rs, e );
00222               rc = test_filter( op, e, op->oq_search.rs_filter );
00223               if ( rc == LDAP_COMPARE_TRUE ) {
00224                      rs->sr_entry = e;
00225                      rs->sr_flags = REP_ENTRY_MUSTRELEASE;
00226                      send_search_entry( op, rs );
00227                      rs->sr_entry = NULL;
00228               } else {
00229                      monitor_cache_release( mi, e );
00230               }
00231               rc = LDAP_SUCCESS;
00232               break;
00233 
00234        case LDAP_SCOPE_ONELEVEL:
00235        case LDAP_SCOPE_SUBORDINATE:
00236               monitor_find_children( op, rs, e, &e_nv, &e_ch );
00237               monitor_cache_release( mi, e );
00238               rc = monitor_send_children( op, rs, e_nv, e_ch,
00239                      op->oq_search.rs_scope == LDAP_SCOPE_SUBORDINATE );
00240               break;
00241 
00242        case LDAP_SCOPE_SUBTREE:
00243               monitor_entry_update( op, rs, e );
00244               monitor_find_children( op, rs, e, &e_nv, &e_ch );
00245               rc = test_filter( op, e, op->oq_search.rs_filter );
00246               if ( rc == LDAP_COMPARE_TRUE ) {
00247                      rs->sr_entry = e;
00248                      rs->sr_flags = REP_ENTRY_MUSTRELEASE;
00249                      send_search_entry( op, rs );
00250                      rs->sr_entry = NULL;
00251               } else {
00252                      monitor_cache_release( mi, e );
00253               }
00254 
00255               rc = monitor_send_children( op, rs, e_nv, e_ch, 1 );
00256               break;
00257 
00258        default:
00259               rc = LDAP_UNWILLING_TO_PERFORM;
00260               monitor_cache_release( mi, e );
00261        }
00262 
00263        rs->sr_attrs = NULL;
00264        rs->sr_err = rc;
00265        if ( rs->sr_err != SLAPD_ABANDON ) {
00266               send_ldap_result( op, rs );
00267        }
00268 
00269        return rs->sr_err;
00270 }
00271