if ( rs->sr_err == LDAP_COMPARE_TRUE ) {
                        /* check size limit */
-                       if ( --op->ors_slimit == -1 ) {
-#ifdef SLAP_ZONE_ALLOC
-                               slap_zn_runlock(bdb->bi_cache.c_zctx, e);
-#endif
-                               bdb_cache_return_entry_r( bdb->bi_dbenv,
-                                               &bdb->bi_cache, e, &lock );
-                               e = NULL;
-                               rs->sr_entry = NULL;
-                               rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
-                               rs->sr_ref = rs->sr_v2ref;
-                               send_ldap_result( op, rs );
-                               rs->sr_err = LDAP_SUCCESS;
-                               goto done;
-                       }
-
                        if ( get_pagedresults(op) > SLAP_CONTROL_IGNORED ) {
                                if ( rs->sr_nentries >= ((PagedResultsState *)op->o_pagedresults_state)->ps_size ) {
 #ifdef SLAP_ZONE_ALLOC
                                rs->sr_err = LDAP_SUCCESS;
                                result = send_search_entry( op, rs );
 
-                               switch (result) {
+                               switch ( result ) {
                                case 0:         /* entry sent ok */
                                        break;
                                case 1:         /* entry not sent */
                                        break;
-                               case -1:        /* connection closed */
+                               default:
 #ifdef SLAP_ZONE_ALLOC
                                        slap_zn_runlock(bdb->bi_cache.c_zctx, e);
 #endif
                                                &bdb->bi_cache, e, &lock);
                                        e = NULL;
                                        rs->sr_entry = NULL;
-                                       rs->sr_err = LDAP_OTHER;
+                                       switch ( result ) {
+                                       case SLAPD_SEND_SIZELIMIT:
+                                               rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
+                                               rs->sr_ref = rs->sr_v2ref;
+                                               send_ldap_result( op, rs );
+                                               rs->sr_err = LDAP_SUCCESS;
+                                               break;
+                                       case -1:        /* connection closed */
+                                               rs->sr_err = LDAP_OTHER;
+                                               break;
+                                       }
                                        goto done;
                                }
                        }
 
                        }
                        ldap_msgfree( res );
                        if ( abort ) {
+                               if ( abort == SLAPD_SEND_SIZELIMIT ) {
+                                       rc = rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
+                               }
                                ldap_abandon_ext( lc->lc_ld, msgid, NULL, NULL );
                                goto finish;
                        }
 
                        }
 
                        if ( scopeok ) {
-                               /* check size limit */
-                               if ( --op->ors_slimit == -1 ) {
-                                       cache_return_entry_r( &li->li_cache, e );
-                                       rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
-                                       rs->sr_entry = NULL;
-                                       send_ldap_result( op, rs );
-                                       rc = LDAP_SUCCESS;
-                                       goto done;
-                               }
-
                                if (e) {
                                        rs->sr_flags = 0;
                                        result = send_search_entry( op, rs );
 
-                                       switch (result) {
+                                       switch ( result ) {
                                        case 0:         /* entry sent ok */
                                                break;
                                        case 1:         /* entry not sent */
                                                cache_return_entry_r( &li->li_cache, e );
                                                rc = LDAP_SUCCESS;
                                                goto done;
+                                       case SLAPD_SEND_SIZELIMIT:
+                                               cache_return_entry_r( &li->li_cache, e );
+                                               rc = rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
+                                               rs->sr_entry = NULL;
+                                               send_ldap_result( op, rs );
+                                               rc = LDAP_SUCCESS;
+                                               goto done;
                                        }
                                }
 
 
                                        candidates[ i ].sr_type = REP_RESULT;
                                }
 
-                               if ( --op->ors_slimit == -1 ) {
-                                       ldap_msgfree( res );
-                                       res = NULL;
+                               is_ok++;
+
+                               e = ldap_first_entry( msc->msc_ld, res );
+                               savepriv = op->o_private;
+                               op->o_private = (void *)i;
+                               rc = meta_send_entry( op, rs, mc, i, e );
+                               ldap_msgfree( res );
+                               res = NULL;
 
+                               switch ( rc ) {
+                               case SLAPD_SEND_SIZELIMIT:
                                        rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
                                        savepriv = op->o_private;
                                        op->o_private = (void *)i;
                                        send_ldap_result( op, rs );
                                        op->o_private = savepriv;
                                        goto finish;
-                               }
 
-                               is_ok++;
-
-                               e = ldap_first_entry( msc->msc_ld, res );
-                               savepriv = op->o_private;
-                               op->o_private = (void *)i;
-                               meta_send_entry( op, rs, mc, i, e );
+                               case -1:
+                                       rs->sr_err = LDAP_OTHER;
+                                       goto finish;
+                               }
                                op->o_private = savepriv;
 
-                               ldap_msgfree( res );
-                               res = NULL;
-
                                gotit = 1;
 
 #if 0
        rs->sr_entry = &ent;
        rs->sr_attrs = op->ors_attrs;
        rs->sr_flags = 0;
-       send_search_entry( op, rs );
+       switch ( send_search_entry( op, rs ) ) {
+       case 0:
+       case 1:
+               rc = LDAP_SUCCESS;
+               break;
+       case -1:
+               rc = LDAP_OTHER;
+               break;
+       case SLAPD_SEND_SIZELIMIT:
+               rc = LDAP_SIZELIMIT_EXCEEDED;
+               break;
+       default:
+               /* trap other values when added... */
+               assert( 0 );
+       }
        rs->sr_entry = NULL;
        rs->sr_attrs = NULL;
        
        }
        entry_clean( &ent );
 
-       return LDAP_SUCCESS;
+       return rc;
 }
 
 
                if ( rc == LDAP_COMPARE_TRUE ) {
                        rs->sr_entry = e;
                        rs->sr_flags = 0;
-                       send_search_entry( op, rs );
+                       rc = send_search_entry( op, rs );
                        rs->sr_entry = NULL;
                }
 
 
                                                send_entry = 1;
 
                                        if (send_entry) {
+                                               int     rc;
+
                                                rs->sr_entry = e;
                                                rs->sr_attrs = op->ors_attrs;
                                                rs->sr_flags = REP_ENTRY_MODIFIABLE;
-                                               send_search_entry( op, rs );
+                                               rc = send_search_entry( op, rs );
+                                               switch ( rc ) {
+                                               case SLAPD_SEND_SIZELIMIT:
+                                                       rs->sr_entry = NULL;
+                                                       rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
+                                                       goto done2;
+                                               }
                                        }
 
                                        entry_free( e );
 
                rs->sr_err = POPi;
 
-
-
+done:;
                PUTBACK; FREETMPS; LEAVE;
        }
 
 
 
                if ( test_filter( op, e, op->ors_filter ) == LDAP_COMPARE_TRUE )
                {
-                       if ( --op->ors_slimit == -1 ) {
-                               rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
-                               goto send_results;
-                       }
-
                        rs->sr_attrs = op->ors_attrs;
                        rs->sr_operational_attrs = NULL;
                        rs->sr_entry = e;
                        rs->sr_attrs = NULL;
                        rs->sr_operational_attrs = NULL;
 
-                       if ( sres == -1 ) {
+                       switch ( sres ) {
+                       case -1:
                                /*
                                 * FIXME: send_search_entry failed;
                                 * better stop
                                Debug( LDAP_DEBUG_TRACE, "backsql_search(): "
                                        "connection lost\n", 0, 0, 0 );
                                goto end_of_search;
+
+                       case SLAPD_SEND_SIZELIMIT:
+                               rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
+                               goto send_results;
                        }
                }
 
 
                                rs->sr_entry = NULL;
                                rs->sr_err = LDAP_OTHER;
                                goto done;
+                       case SLAPD_SEND_SIZELIMIT:
+                               rs->sr_entry = NULL;
+                               rs->sr_err = LDAP_SIZELIMIT_EXCEEDED;
+                               goto done;
                        }
                }
                rs->sr_err = LDAP_SUCCESS;
 
        }
 }
 
+/*
+ * returns:
+ *
+ *  0                  entry sent
+ *  1                  entry not sent (other)
+ * -1                  entry not sent (connection closed)
+ * SLAPD_SEND_SIZELIMIT        entry not sent (caller must send sizelimitExceeded)
+ */
+
 int
 slap_send_search_entry( Operation *op, SlapReply *rs )
 {
        }
 
        if ( op->o_res_ber == NULL ) {
+               if ( --op->ors_slimit == -1 ) {
+                       rc = SLAPD_SEND_SIZELIMIT;
+                       ber_free_buf( ber );
+                       /* putback, so dumb backends that don't 
+                        * check sizelimit won't at least return
+                        * more than expected... */
+                       op->ors_slimit++;
+                       goto error_return;
+               }
                bytes = send_ldap_ber( op->o_conn, ber );
                ber_free_buf( ber );
 
 
 /* unknown config file directive */
 #define SLAP_CONF_UNKNOWN (-1026)
 
+/* pseudo error code indicating caller should send sizelimitExceeded */
+#define SLAPD_SEND_SIZELIMIT (-1027)
+
 /* We assume "C" locale, that is US-ASCII */
 #define ASCII_SPACE(c) ( (c) == ' ' )
 #define ASCII_LOWER(c) ( (c) >= 'a' && (c) <= 'z' )
 } slap_overinfo;
 
 /* Should successive callbacks in a chain be processed? */
-#define        SLAP_CB_FREEME          0x4000
-#define        SLAP_CB_CONTINUE        0x8000
+#define        SLAP_CB_FREEME          0x04000
+#define        SLAP_CB_CONTINUE        0x08000
 
 /*
  * Paged Results state